Merge "Add visibility rule for migration." am: 447d6af218 am: 72fd984a43 am: 900a7ffa73
Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1535542
MUST ONLY BE SUBMITTED BY AUTOMERGER
Change-Id: Ifbe6c9432ff239e50b11add743b05768b576cd86
diff --git a/OsuLogin/AndroidManifest.xml b/OsuLogin/AndroidManifest.xml
index a428cb3..730cd87 100644
--- a/OsuLogin/AndroidManifest.xml
+++ b/OsuLogin/AndroidManifest.xml
@@ -31,7 +31,8 @@
<activity android:name="com.android.hotspot2.osulogin.OsuLoginActivity"
android:label="@string/action_bar_label"
android:theme="@style/AppTheme"
- android:configChanges="keyboardHidden|orientation|screenSize">
+ android:configChanges="keyboardHidden|orientation|screenSize"
+ android:exported="true">
<intent-filter>
<action android:name="android.net.wifi.action.PASSPOINT_LAUNCH_OSU_VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
diff --git a/OsuLogin/res/values-af/strings.xml b/OsuLogin/res/values-af/strings.xml
new file mode 100644
index 0000000..bfeee10
--- /dev/null
+++ b/OsuLogin/res/values-af/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"Sluit aanlyn aan"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"Kon nie aanmeld nie"</string>
+</resources>
diff --git a/OsuLogin/res/values-am/strings.xml b/OsuLogin/res/values-am/strings.xml
new file mode 100644
index 0000000..e27c578
--- /dev/null
+++ b/OsuLogin/res/values-am/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"የመስመር ላይ ምዝገባ"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"ምዝገባ አልተሳካም"</string>
+</resources>
diff --git a/OsuLogin/res/values-ar/strings.xml b/OsuLogin/res/values-ar/strings.xml
new file mode 100644
index 0000000..b72d7c1
--- /dev/null
+++ b/OsuLogin/res/values-ar/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"الاشتراك على الإنترنت"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"تعذّر الاشتراك."</string>
+</resources>
diff --git a/OsuLogin/res/values-as/strings.xml b/OsuLogin/res/values-as/strings.xml
new file mode 100644
index 0000000..422de32
--- /dev/null
+++ b/OsuLogin/res/values-as/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"অনলাইনত ছাই আপ কৰক"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"ছাইন আপ কৰিব পৰা নগ’ল"</string>
+</resources>
diff --git a/OsuLogin/res/values-az/strings.xml b/OsuLogin/res/values-az/strings.xml
new file mode 100644
index 0000000..977f939
--- /dev/null
+++ b/OsuLogin/res/values-az/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"Onlayn Qeydiyyat"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"Qeydiyyat alınmadı"</string>
+</resources>
diff --git a/OsuLogin/res/values-b+sr+Latn/strings.xml b/OsuLogin/res/values-b+sr+Latn/strings.xml
new file mode 100644
index 0000000..6eb2cc1
--- /dev/null
+++ b/OsuLogin/res/values-b+sr+Latn/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"Onlajn registracija"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"Registracija nije uspela"</string>
+</resources>
diff --git a/OsuLogin/res/values-be/strings.xml b/OsuLogin/res/values-be/strings.xml
new file mode 100644
index 0000000..158c3f2
--- /dev/null
+++ b/OsuLogin/res/values-be/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"Зарэгістравацца ў інтэрнэце"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"Не ўдалося зарэгістравацца"</string>
+</resources>
diff --git a/OsuLogin/res/values-bg/strings.xml b/OsuLogin/res/values-bg/strings.xml
new file mode 100644
index 0000000..ea3145d
--- /dev/null
+++ b/OsuLogin/res/values-bg/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"Онлайн регистрация"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"Регистрацията не бе успешна"</string>
+</resources>
diff --git a/OsuLogin/res/values-bn/strings.xml b/OsuLogin/res/values-bn/strings.xml
new file mode 100644
index 0000000..c9f615e
--- /dev/null
+++ b/OsuLogin/res/values-bn/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"অনলাইনে সাইন-আপ করুন"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"সাইন-আপ করা যায়নি"</string>
+</resources>
diff --git a/OsuLogin/res/values-bs/strings.xml b/OsuLogin/res/values-bs/strings.xml
new file mode 100644
index 0000000..e9b9751
--- /dev/null
+++ b/OsuLogin/res/values-bs/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"Online registracija"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"Registracija nije uspjela"</string>
+</resources>
diff --git a/OsuLogin/res/values-ca/strings.xml b/OsuLogin/res/values-ca/strings.xml
new file mode 100644
index 0000000..7d93096
--- /dev/null
+++ b/OsuLogin/res/values-ca/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"Registre en línia"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"Ha fallat el registre"</string>
+</resources>
diff --git a/OsuLogin/res/values-cs/strings.xml b/OsuLogin/res/values-cs/strings.xml
new file mode 100644
index 0000000..b9cb794
--- /dev/null
+++ b/OsuLogin/res/values-cs/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"Online registrace"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"Registrace selhala"</string>
+</resources>
diff --git a/OsuLogin/res/values-da/strings.xml b/OsuLogin/res/values-da/strings.xml
new file mode 100644
index 0000000..68c93b7
--- /dev/null
+++ b/OsuLogin/res/values-da/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"Online registrering"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"Registrering mislykkedes"</string>
+</resources>
diff --git a/OsuLogin/res/values-de/strings.xml b/OsuLogin/res/values-de/strings.xml
new file mode 100644
index 0000000..7e5a310
--- /dev/null
+++ b/OsuLogin/res/values-de/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"Online-Registrierung"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"Registrierung fehlgeschlagen"</string>
+</resources>
diff --git a/OsuLogin/res/values-el/strings.xml b/OsuLogin/res/values-el/strings.xml
new file mode 100644
index 0000000..a58e481
--- /dev/null
+++ b/OsuLogin/res/values-el/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"Εγγραφή στο διαδίκτυο"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"Αποτυχία εγγραφής"</string>
+</resources>
diff --git a/OsuLogin/res/values-en-rAU/strings.xml b/OsuLogin/res/values-en-rAU/strings.xml
new file mode 100644
index 0000000..fbbcab1
--- /dev/null
+++ b/OsuLogin/res/values-en-rAU/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"Online sign-up"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"Sign-up failed"</string>
+</resources>
diff --git a/OsuLogin/res/values-en-rCA/strings.xml b/OsuLogin/res/values-en-rCA/strings.xml
new file mode 100644
index 0000000..fbbcab1
--- /dev/null
+++ b/OsuLogin/res/values-en-rCA/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"Online sign-up"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"Sign-up failed"</string>
+</resources>
diff --git a/OsuLogin/res/values-en-rGB/strings.xml b/OsuLogin/res/values-en-rGB/strings.xml
new file mode 100644
index 0000000..fbbcab1
--- /dev/null
+++ b/OsuLogin/res/values-en-rGB/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"Online sign-up"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"Sign-up failed"</string>
+</resources>
diff --git a/OsuLogin/res/values-en-rIN/strings.xml b/OsuLogin/res/values-en-rIN/strings.xml
new file mode 100644
index 0000000..fbbcab1
--- /dev/null
+++ b/OsuLogin/res/values-en-rIN/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"Online sign-up"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"Sign-up failed"</string>
+</resources>
diff --git a/OsuLogin/res/values-en-rXC/strings.xml b/OsuLogin/res/values-en-rXC/strings.xml
new file mode 100644
index 0000000..af7ff67
--- /dev/null
+++ b/OsuLogin/res/values-en-rXC/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"Online Sign Up"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"Sign-up failed"</string>
+</resources>
diff --git a/OsuLogin/res/values-es-rUS/strings.xml b/OsuLogin/res/values-es-rUS/strings.xml
new file mode 100644
index 0000000..144804c
--- /dev/null
+++ b/OsuLogin/res/values-es-rUS/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"Registrarse en línea"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"Se produjo un error de registro"</string>
+</resources>
diff --git a/OsuLogin/res/values-es/strings.xml b/OsuLogin/res/values-es/strings.xml
new file mode 100644
index 0000000..3ad95cd8
--- /dev/null
+++ b/OsuLogin/res/values-es/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"Registro online"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"Error al completar el registro"</string>
+</resources>
diff --git a/OsuLogin/res/values-et/strings.xml b/OsuLogin/res/values-et/strings.xml
new file mode 100644
index 0000000..94c5cea
--- /dev/null
+++ b/OsuLogin/res/values-et/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"Veebis registreerimine"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"Registreerimine ebaõnnestus"</string>
+</resources>
diff --git a/OsuLogin/res/values-eu/strings.xml b/OsuLogin/res/values-eu/strings.xml
new file mode 100644
index 0000000..30caa87
--- /dev/null
+++ b/OsuLogin/res/values-eu/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"Sarean izen-ematea"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"Ezin izan da eman izena"</string>
+</resources>
diff --git a/OsuLogin/res/values-fa/strings.xml b/OsuLogin/res/values-fa/strings.xml
new file mode 100644
index 0000000..3005203
--- /dev/null
+++ b/OsuLogin/res/values-fa/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"ثبتنام آنلاین"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"ثبتنام انجام نشد"</string>
+</resources>
diff --git a/OsuLogin/res/values-fi/strings.xml b/OsuLogin/res/values-fi/strings.xml
new file mode 100644
index 0000000..24eac8a
--- /dev/null
+++ b/OsuLogin/res/values-fi/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"Rekisteröidy verkossa"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"Rekisteröityminen ei onnistunut"</string>
+</resources>
diff --git a/OsuLogin/res/values-fr-rCA/strings.xml b/OsuLogin/res/values-fr-rCA/strings.xml
new file mode 100644
index 0000000..bcaa662
--- /dev/null
+++ b/OsuLogin/res/values-fr-rCA/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"Inscription en ligne"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"Échec de l\'inscription"</string>
+</resources>
diff --git a/OsuLogin/res/values-fr/strings.xml b/OsuLogin/res/values-fr/strings.xml
new file mode 100644
index 0000000..bcaa662
--- /dev/null
+++ b/OsuLogin/res/values-fr/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"Inscription en ligne"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"Échec de l\'inscription"</string>
+</resources>
diff --git a/OsuLogin/res/values-gl/strings.xml b/OsuLogin/res/values-gl/strings.xml
new file mode 100644
index 0000000..5fc4444
--- /dev/null
+++ b/OsuLogin/res/values-gl/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"Rexistro en liña"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"Produciuse un erro co rexistro"</string>
+</resources>
diff --git a/OsuLogin/res/values-gu/strings.xml b/OsuLogin/res/values-gu/strings.xml
new file mode 100644
index 0000000..8449963
--- /dev/null
+++ b/OsuLogin/res/values-gu/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"ઑનલાઇન સાઇન અપ કરો"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"સાઇન અપ નિષ્ફળ"</string>
+</resources>
diff --git a/OsuLogin/res/values-hi/strings.xml b/OsuLogin/res/values-hi/strings.xml
new file mode 100644
index 0000000..9e07438
--- /dev/null
+++ b/OsuLogin/res/values-hi/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"ऑनलाइन साइन अप करें"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"साइन अप नहीं किया जा सका"</string>
+</resources>
diff --git a/OsuLogin/res/values-hr/strings.xml b/OsuLogin/res/values-hr/strings.xml
new file mode 100644
index 0000000..e9b9751
--- /dev/null
+++ b/OsuLogin/res/values-hr/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"Online registracija"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"Registracija nije uspjela"</string>
+</resources>
diff --git a/OsuLogin/res/values-hu/strings.xml b/OsuLogin/res/values-hu/strings.xml
new file mode 100644
index 0000000..cb0e036
--- /dev/null
+++ b/OsuLogin/res/values-hu/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"Online regisztráció"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"A regisztráció nem sikerült"</string>
+</resources>
diff --git a/OsuLogin/res/values-hy/strings.xml b/OsuLogin/res/values-hy/strings.xml
new file mode 100644
index 0000000..ae1c36a
--- /dev/null
+++ b/OsuLogin/res/values-hy/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"Առցանց գրանցում"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"Չհաջողվեց գրանցվել"</string>
+</resources>
diff --git a/OsuLogin/res/values-in/strings.xml b/OsuLogin/res/values-in/strings.xml
new file mode 100644
index 0000000..6aaf694
--- /dev/null
+++ b/OsuLogin/res/values-in/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"Pendaftaran Online"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"Pendaftaran gagal"</string>
+</resources>
diff --git a/OsuLogin/res/values-is/strings.xml b/OsuLogin/res/values-is/strings.xml
new file mode 100644
index 0000000..f1ae520
--- /dev/null
+++ b/OsuLogin/res/values-is/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"Skráning á netinu"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"Skráning mistókst"</string>
+</resources>
diff --git a/OsuLogin/res/values-it/strings.xml b/OsuLogin/res/values-it/strings.xml
new file mode 100644
index 0000000..fbff7b0
--- /dev/null
+++ b/OsuLogin/res/values-it/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"Registrazione online"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"Registrazione non riuscita"</string>
+</resources>
diff --git a/OsuLogin/res/values-iw/strings.xml b/OsuLogin/res/values-iw/strings.xml
new file mode 100644
index 0000000..866ef88
--- /dev/null
+++ b/OsuLogin/res/values-iw/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"הרשמה אונליין"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"ההרשמה נכשלה"</string>
+</resources>
diff --git a/OsuLogin/res/values-ja/strings.xml b/OsuLogin/res/values-ja/strings.xml
new file mode 100644
index 0000000..8a220d6
--- /dev/null
+++ b/OsuLogin/res/values-ja/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"オンライン登録"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"登録できませんでした"</string>
+</resources>
diff --git a/OsuLogin/res/values-ka/strings.xml b/OsuLogin/res/values-ka/strings.xml
new file mode 100644
index 0000000..bf08006
--- /dev/null
+++ b/OsuLogin/res/values-ka/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"ონლაინ რეგისტრაცია"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"რეგისტრაცია ვერ მოხერხდა"</string>
+</resources>
diff --git a/OsuLogin/res/values-kk/strings.xml b/OsuLogin/res/values-kk/strings.xml
new file mode 100644
index 0000000..8b87356
--- /dev/null
+++ b/OsuLogin/res/values-kk/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"Онлайн тіркелу"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"Тіркелмеді."</string>
+</resources>
diff --git a/OsuLogin/res/values-km/strings.xml b/OsuLogin/res/values-km/strings.xml
new file mode 100644
index 0000000..f58ccc3
--- /dev/null
+++ b/OsuLogin/res/values-km/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"ការចុះឈ្មោះលើអ៊ីនធឺណិត"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"ការចុះឈ្មោះមិនបានសម្រេច"</string>
+</resources>
diff --git a/OsuLogin/res/values-kn/strings.xml b/OsuLogin/res/values-kn/strings.xml
new file mode 100644
index 0000000..49a6562
--- /dev/null
+++ b/OsuLogin/res/values-kn/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"ಆನ್ಲೈನ್ ಸೈನ್ ಅಪ್"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"ಸೈನ್ ಅಪ್ ವಿಫಲವಾಗಿದೆ"</string>
+</resources>
diff --git a/OsuLogin/res/values-ko/strings.xml b/OsuLogin/res/values-ko/strings.xml
new file mode 100644
index 0000000..e647ca0
--- /dev/null
+++ b/OsuLogin/res/values-ko/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"온라인 가입"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"가입에 실패했습니다."</string>
+</resources>
diff --git a/OsuLogin/res/values-ky/strings.xml b/OsuLogin/res/values-ky/strings.xml
new file mode 100644
index 0000000..42da248
--- /dev/null
+++ b/OsuLogin/res/values-ky/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"Интернет аркылуу катталуу"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"Катталган жоксуз"</string>
+</resources>
diff --git a/OsuLogin/res/values-lo/strings.xml b/OsuLogin/res/values-lo/strings.xml
new file mode 100644
index 0000000..9ff2241
--- /dev/null
+++ b/OsuLogin/res/values-lo/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"ສະໝັກອອນລາຍ"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"ສະໝັກບໍ່ສຳເລັດ"</string>
+</resources>
diff --git a/OsuLogin/res/values-lt/strings.xml b/OsuLogin/res/values-lt/strings.xml
new file mode 100644
index 0000000..1a4c06e
--- /dev/null
+++ b/OsuLogin/res/values-lt/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"Internetinis prisiregistravimas"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"Nepavyko prisiregistruoti"</string>
+</resources>
diff --git a/OsuLogin/res/values-lv/strings.xml b/OsuLogin/res/values-lv/strings.xml
new file mode 100644
index 0000000..11cdb97
--- /dev/null
+++ b/OsuLogin/res/values-lv/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"Reģistrācija tiešsaistē"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"Reģistrācija neizdevās."</string>
+</resources>
diff --git a/OsuLogin/res/values-mk/strings.xml b/OsuLogin/res/values-mk/strings.xml
new file mode 100644
index 0000000..de608e1
--- /dev/null
+++ b/OsuLogin/res/values-mk/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"Онлајн регистрација"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"Регистрацијата не успеа"</string>
+</resources>
diff --git a/OsuLogin/res/values-ml/strings.xml b/OsuLogin/res/values-ml/strings.xml
new file mode 100644
index 0000000..8e797c8
--- /dev/null
+++ b/OsuLogin/res/values-ml/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"ഓൺലെെൻ സെെൻ അപ്പ്"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"സൈൻ അപ്പ് ചെയ്യാനായില്ല"</string>
+</resources>
diff --git a/OsuLogin/res/values-mn/strings.xml b/OsuLogin/res/values-mn/strings.xml
new file mode 100644
index 0000000..59d79d0
--- /dev/null
+++ b/OsuLogin/res/values-mn/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"Онлайнаар бүртгүүлэх"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"Бүртгүүлж чадсангүй"</string>
+</resources>
diff --git a/OsuLogin/res/values-mr/strings.xml b/OsuLogin/res/values-mr/strings.xml
new file mode 100644
index 0000000..15479a6
--- /dev/null
+++ b/OsuLogin/res/values-mr/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"ऑनलाइन साइन अप करा"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"साइन-अप करता आले नाही"</string>
+</resources>
diff --git a/OsuLogin/res/values-ms/strings.xml b/OsuLogin/res/values-ms/strings.xml
new file mode 100644
index 0000000..7e1cf95
--- /dev/null
+++ b/OsuLogin/res/values-ms/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"Pendaftaran Dalam Talian"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"Pendaftaran gagal"</string>
+</resources>
diff --git a/OsuLogin/res/values-my/strings.xml b/OsuLogin/res/values-my/strings.xml
new file mode 100644
index 0000000..1bd992e
--- /dev/null
+++ b/OsuLogin/res/values-my/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"အွန်လိုင်း အကောင့်ဖွင့်ရန်"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"အကောင့်ဖွင့်၍ မရပါ"</string>
+</resources>
diff --git a/OsuLogin/res/values-nb/strings.xml b/OsuLogin/res/values-nb/strings.xml
new file mode 100644
index 0000000..2e0c47a
--- /dev/null
+++ b/OsuLogin/res/values-nb/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"Registrering på nettet"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"Registreringen mislyktes"</string>
+</resources>
diff --git a/OsuLogin/res/values-ne/strings.xml b/OsuLogin/res/values-ne/strings.xml
new file mode 100644
index 0000000..16bd92f
--- /dev/null
+++ b/OsuLogin/res/values-ne/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"अनलाइन साइन अप"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"साइन अप गर्न सकिएन"</string>
+</resources>
diff --git a/OsuLogin/res/values-nl/strings.xml b/OsuLogin/res/values-nl/strings.xml
new file mode 100644
index 0000000..7cf8bd2
--- /dev/null
+++ b/OsuLogin/res/values-nl/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"Online aanmelding"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"Aanmelding mislukt"</string>
+</resources>
diff --git a/OsuLogin/res/values-or/strings.xml b/OsuLogin/res/values-or/strings.xml
new file mode 100644
index 0000000..e0584d7
--- /dev/null
+++ b/OsuLogin/res/values-or/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"ଅନଲାଇନ୍ ସାଇନ୍ ଅପ୍ କରନ୍ତୁ"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"ସାଇନ୍ ଅପ୍ ବିଫଳ ହୋଇଛି"</string>
+</resources>
diff --git a/OsuLogin/res/values-pa/strings.xml b/OsuLogin/res/values-pa/strings.xml
new file mode 100644
index 0000000..7e47d0e
--- /dev/null
+++ b/OsuLogin/res/values-pa/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"ਆਨਲਾਈਨ ਸਾਈਨ-ਅੱਪ ਕਰੋ"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"ਸਾਈਨ-ਅੱਪ ਕਰਨਾ ਅਸਫਲ ਰਿਹਾ"</string>
+</resources>
diff --git a/OsuLogin/res/values-pl/strings.xml b/OsuLogin/res/values-pl/strings.xml
new file mode 100644
index 0000000..c0722ab
--- /dev/null
+++ b/OsuLogin/res/values-pl/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"Rejestracja online"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"Nie udało się zarejestrować"</string>
+</resources>
diff --git a/OsuLogin/res/values-pt-rBR/strings.xml b/OsuLogin/res/values-pt-rBR/strings.xml
new file mode 100644
index 0000000..c9fe377
--- /dev/null
+++ b/OsuLogin/res/values-pt-rBR/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"Inscrição on-line"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"Falha na inscrição"</string>
+</resources>
diff --git a/OsuLogin/res/values-pt-rPT/strings.xml b/OsuLogin/res/values-pt-rPT/strings.xml
new file mode 100644
index 0000000..0059281
--- /dev/null
+++ b/OsuLogin/res/values-pt-rPT/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"Inscrição online"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"Falha na inscrição."</string>
+</resources>
diff --git a/OsuLogin/res/values-pt/strings.xml b/OsuLogin/res/values-pt/strings.xml
new file mode 100644
index 0000000..c9fe377
--- /dev/null
+++ b/OsuLogin/res/values-pt/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"Inscrição on-line"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"Falha na inscrição"</string>
+</resources>
diff --git a/OsuLogin/res/values-ro/strings.xml b/OsuLogin/res/values-ro/strings.xml
new file mode 100644
index 0000000..eead127
--- /dev/null
+++ b/OsuLogin/res/values-ro/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"Înscriere online"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"Nu s-a înscris"</string>
+</resources>
diff --git a/OsuLogin/res/values-ru/strings.xml b/OsuLogin/res/values-ru/strings.xml
new file mode 100644
index 0000000..a271ef7
--- /dev/null
+++ b/OsuLogin/res/values-ru/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"Регистрация в Интернете"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"Не удалось зарегистрироваться."</string>
+</resources>
diff --git a/OsuLogin/res/values-si/strings.xml b/OsuLogin/res/values-si/strings.xml
new file mode 100644
index 0000000..52e5979
--- /dev/null
+++ b/OsuLogin/res/values-si/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"සබැඳි ලියාපදිංචිය"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"ලියාපදිංචිය අසාර්ථක විය"</string>
+</resources>
diff --git a/OsuLogin/res/values-sk/strings.xml b/OsuLogin/res/values-sk/strings.xml
new file mode 100644
index 0000000..f6b9f70
--- /dev/null
+++ b/OsuLogin/res/values-sk/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"Online registrácia"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"Registrácia zlyhala"</string>
+</resources>
diff --git a/OsuLogin/res/values-sl/strings.xml b/OsuLogin/res/values-sl/strings.xml
new file mode 100644
index 0000000..6e6b95c
--- /dev/null
+++ b/OsuLogin/res/values-sl/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"Spletna registracija"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"Registracija ni uspela"</string>
+</resources>
diff --git a/OsuLogin/res/values-sq/strings.xml b/OsuLogin/res/values-sq/strings.xml
new file mode 100644
index 0000000..f67a238
--- /dev/null
+++ b/OsuLogin/res/values-sq/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"Regjistrimi në linjë"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"Regjistrimi dështoi"</string>
+</resources>
diff --git a/OsuLogin/res/values-sr/strings.xml b/OsuLogin/res/values-sr/strings.xml
new file mode 100644
index 0000000..14e0828
--- /dev/null
+++ b/OsuLogin/res/values-sr/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"Онлајн регистрација"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"Регистрација није успела"</string>
+</resources>
diff --git a/OsuLogin/res/values-sv/strings.xml b/OsuLogin/res/values-sv/strings.xml
new file mode 100644
index 0000000..ea5fdfd
--- /dev/null
+++ b/OsuLogin/res/values-sv/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"Registrering online"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"Registreringen misslyckades"</string>
+</resources>
diff --git a/OsuLogin/res/values-sw/strings.xml b/OsuLogin/res/values-sw/strings.xml
new file mode 100644
index 0000000..c20a402
--- /dev/null
+++ b/OsuLogin/res/values-sw/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"Kujisajili Mtandaoni"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"Imeshindwa kukusajili"</string>
+</resources>
diff --git a/OsuLogin/res/values-ta/strings.xml b/OsuLogin/res/values-ta/strings.xml
new file mode 100644
index 0000000..e2eb567
--- /dev/null
+++ b/OsuLogin/res/values-ta/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"ஆன்லைனில் பதிவு செய்"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"பதிவு செய்ய முடியவில்லை"</string>
+</resources>
diff --git a/OsuLogin/res/values-te/strings.xml b/OsuLogin/res/values-te/strings.xml
new file mode 100644
index 0000000..56b0b44
--- /dev/null
+++ b/OsuLogin/res/values-te/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"ఆన్లైన్ సైన్ అప్"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"సైన్-అప్ విఫలమయ్యింది"</string>
+</resources>
diff --git a/OsuLogin/res/values-th/strings.xml b/OsuLogin/res/values-th/strings.xml
new file mode 100644
index 0000000..552dca2
--- /dev/null
+++ b/OsuLogin/res/values-th/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"การลงชื่อสมัครใช้ออนไลน์"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"ลงชื่อสมัครใช้ไม่สำเร็จ"</string>
+</resources>
diff --git a/OsuLogin/res/values-tl/strings.xml b/OsuLogin/res/values-tl/strings.xml
new file mode 100644
index 0000000..ba89e96
--- /dev/null
+++ b/OsuLogin/res/values-tl/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"Pag-sign Up Online"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"Hindi nakapag-sign up"</string>
+</resources>
diff --git a/OsuLogin/res/values-tr/strings.xml b/OsuLogin/res/values-tr/strings.xml
new file mode 100644
index 0000000..1d927fe
--- /dev/null
+++ b/OsuLogin/res/values-tr/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"Online Kaydolma"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"Kaydolma işlemi başarısız oldu"</string>
+</resources>
diff --git a/OsuLogin/res/values-uk/strings.xml b/OsuLogin/res/values-uk/strings.xml
new file mode 100644
index 0000000..6e60ff0
--- /dev/null
+++ b/OsuLogin/res/values-uk/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"Онлайн-реєстрація"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"Не вдалося зареєструватись"</string>
+</resources>
diff --git a/OsuLogin/res/values-ur/strings.xml b/OsuLogin/res/values-ur/strings.xml
new file mode 100644
index 0000000..eed7686
--- /dev/null
+++ b/OsuLogin/res/values-ur/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"آن لائن سائن اپ کریں"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"سائن اپ ناکام ہو گیا"</string>
+</resources>
diff --git a/OsuLogin/res/values-uz/strings.xml b/OsuLogin/res/values-uz/strings.xml
new file mode 100644
index 0000000..152d129
--- /dev/null
+++ b/OsuLogin/res/values-uz/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"Onlayn registratsiya"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"Registratsiya qilinmadi"</string>
+</resources>
diff --git a/OsuLogin/res/values-vi/strings.xml b/OsuLogin/res/values-vi/strings.xml
new file mode 100644
index 0000000..8455807
--- /dev/null
+++ b/OsuLogin/res/values-vi/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"Đăng ký trực tuyến"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"Không đăng ký được"</string>
+</resources>
diff --git a/OsuLogin/res/values-zh-rCN/strings.xml b/OsuLogin/res/values-zh-rCN/strings.xml
new file mode 100644
index 0000000..7f13647
--- /dev/null
+++ b/OsuLogin/res/values-zh-rCN/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"在线注册"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"注册失败"</string>
+</resources>
diff --git a/OsuLogin/res/values-zh-rHK/strings.xml b/OsuLogin/res/values-zh-rHK/strings.xml
new file mode 100644
index 0000000..8731791
--- /dev/null
+++ b/OsuLogin/res/values-zh-rHK/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"網上申請"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"無法申請"</string>
+</resources>
diff --git a/OsuLogin/res/values-zh-rTW/strings.xml b/OsuLogin/res/values-zh-rTW/strings.xml
new file mode 100644
index 0000000..79208c8
--- /dev/null
+++ b/OsuLogin/res/values-zh-rTW/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"線上註冊"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"註冊失敗"</string>
+</resources>
diff --git a/OsuLogin/res/values-zu/strings.xml b/OsuLogin/res/values-zu/strings.xml
new file mode 100644
index 0000000..27ac6bb
--- /dev/null
+++ b/OsuLogin/res/values-zu/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="8288271429327488421">"I-OsuLogin"</string>
+ <string name="action_bar_label" msgid="550995560341508693">"Ukubhalisa Okuku-inthanethi"</string>
+ <string name="sign_up_failed" msgid="837216244603867568">"Ukubhalisa kuhlulekile"</string>
+</resources>
diff --git a/framework/Android.bp b/framework/Android.bp
index 49138ab..6976c5c 100644
--- a/framework/Android.bp
+++ b/framework/Android.bp
@@ -40,6 +40,7 @@
srcs: [
":framework-wifi-updatable-java-sources",
":framework-wifi-updatable-exported-aidl-sources",
+ ":module-utils-os-aidls",
],
}
@@ -60,7 +61,6 @@
"//external/robolectric-shadows:__subpackages__",
"//frameworks/base/packages/SettingsLib/tests/integ",
"//external/sl4a:__subpackages__",
- "//packages/apps/Settings/tests/robotests", // TODO(b/161767237): remove
]
// defaults shared between `framework-wifi` & `framework-wifi-pre-jarjar`
@@ -73,13 +73,14 @@
"framework-wifi-util-lib",
"android.hardware.wifi-V1.0-java-constants",
"modules-utils-build",
+ "modules-utils-os",
],
libs: [
"unsupportedappusage", // for android.compat.annotation.UnsupportedAppUsage
],
srcs: [
":framework-wifi-updatable-sources",
- ":framework-wifi-util-lib-aidls",
+ ":module-utils-os-aidls",
],
}
@@ -135,7 +136,7 @@
// defaults for tests that need to build against framework-wifi's @hide APIs
java_defaults {
name: "framework-wifi-test-defaults",
- sdk_version: "core_platform", // tests can use @CorePlatformApi's
+ sdk_version: "core_current",
libs: [
// order matters: classes in framework-wifi are resolved before framework, meaning
// @hide APIs in framework-wifi are resolved before @SystemApi stubs in framework
diff --git a/framework/TEST_MAPPING b/framework/TEST_MAPPING
new file mode 100644
index 0000000..7ddc308
--- /dev/null
+++ b/framework/TEST_MAPPING
@@ -0,0 +1,22 @@
+{
+ "presubmit-large": [
+ {
+ "name": "CtsWifiTestCases",
+ "options": [
+ {
+ "exclude-annotation": "android.net.wifi.cts.VirtualDeviceNotSupported"
+ }
+ ]
+ }
+ ],
+ "mainline-presubmit": [
+ {
+ "name": "CtsWifiTestCases[com.google.android.wifi.apex]",
+ "options": [
+ {
+ "exclude-annotation": "android.net.wifi.cts.VirtualDeviceNotSupported"
+ }
+ ]
+ }
+ ]
+}
diff --git a/framework/java/android/net/wifi/ITxPacketCountListener.aidl b/framework/aidl-export/android/net/wifi/CoexUnsafeChannel.aidl
similarity index 60%
copy from framework/java/android/net/wifi/ITxPacketCountListener.aidl
copy to framework/aidl-export/android/net/wifi/CoexUnsafeChannel.aidl
index 9105bd0..cb359e9 100644
--- a/framework/java/android/net/wifi/ITxPacketCountListener.aidl
+++ b/framework/aidl-export/android/net/wifi/CoexUnsafeChannel.aidl
@@ -1,11 +1,11 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
+/**
+ * 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
+ * http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -16,13 +16,4 @@
package android.net.wifi;
-/**
- * Interface for tx packet counter callback.
- * @deprecated no longer used, remove once removed from BaseWifiService
- * @hide
- */
-oneway interface ITxPacketCountListener
-{
- void onSuccess(int count);
- void onFailure(int reason);
-}
+parcelable CoexUnsafeChannel;
diff --git a/framework/java/android/net/wifi/ITxPacketCountListener.aidl b/framework/aidl-export/android/net/wifi/aware/AwareResources.aidl
similarity index 63%
copy from framework/java/android/net/wifi/ITxPacketCountListener.aidl
copy to framework/aidl-export/android/net/wifi/aware/AwareResources.aidl
index 9105bd0..d0bd2dd 100644
--- a/framework/java/android/net/wifi/ITxPacketCountListener.aidl
+++ b/framework/aidl-export/android/net/wifi/aware/AwareResources.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * 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.
@@ -14,15 +14,6 @@
* limitations under the License.
*/
-package android.net.wifi;
+package android.net.wifi.aware;
-/**
- * Interface for tx packet counter callback.
- * @deprecated no longer used, remove once removed from BaseWifiService
- * @hide
- */
-oneway interface ITxPacketCountListener
-{
- void onSuccess(int count);
- void onFailure(int reason);
-}
+parcelable AwareResources;
\ No newline at end of file
diff --git a/framework/api/current.txt b/framework/api/current.txt
index 53c3b33..1ece79a 100644
--- a/framework/api/current.txt
+++ b/framework/api/current.txt
@@ -14,6 +14,7 @@
field public static final int EASY_CONNECT_EVENT_FAILURE_NOT_COMPATIBLE = -3; // 0xfffffffd
field public static final int EASY_CONNECT_EVENT_FAILURE_NOT_SUPPORTED = -8; // 0xfffffff8
field public static final int EASY_CONNECT_EVENT_FAILURE_TIMEOUT = -6; // 0xfffffffa
+ field public static final int EASY_CONNECT_EVENT_FAILURE_URI_GENERATION = -13; // 0xfffffff3
}
public final class ScanResult implements android.os.Parcelable {
@@ -34,6 +35,7 @@
field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.ScanResult> CREATOR;
field public String SSID;
field public static final int WIFI_STANDARD_11AC = 5; // 0x5
+ field public static final int WIFI_STANDARD_11AD = 7; // 0x7
field public static final int WIFI_STANDARD_11AX = 6; // 0x6
field public static final int WIFI_STANDARD_11N = 4; // 0x4
field public static final int WIFI_STANDARD_LEGACY = 1; // 0x1
@@ -105,6 +107,8 @@
field @Deprecated public String FQDN;
field @Deprecated public static final int SECURITY_TYPE_EAP = 3; // 0x3
field @Deprecated public static final int SECURITY_TYPE_EAP_SUITE_B = 5; // 0x5
+ field @Deprecated public static final int SECURITY_TYPE_EAP_WPA3_ENTERPRISE = 9; // 0x9
+ field @Deprecated public static final int SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT = 5; // 0x5
field @Deprecated public static final int SECURITY_TYPE_OPEN = 0; // 0x0
field @Deprecated public static final int SECURITY_TYPE_OWE = 6; // 0x6
field @Deprecated public static final int SECURITY_TYPE_PSK = 2; // 0x2
@@ -144,6 +148,7 @@
@Deprecated public static class WifiConfiguration.GroupCipher {
field @Deprecated public static final int CCMP = 3; // 0x3
+ field @Deprecated public static final int GCMP_128 = 7; // 0x7
field @Deprecated public static final int GCMP_256 = 5; // 0x5
field @Deprecated public static final int SMS4 = 6; // 0x6
field @Deprecated public static final int TKIP = 2; // 0x2
@@ -173,6 +178,7 @@
@Deprecated public static class WifiConfiguration.PairwiseCipher {
field @Deprecated public static final int CCMP = 2; // 0x2
+ field @Deprecated public static final int GCMP_128 = 5; // 0x5
field @Deprecated public static final int GCMP_256 = 3; // 0x3
field @Deprecated public static final int NONE = 0; // 0x0
field @Deprecated public static final int SMS4 = 4; // 0x4
@@ -304,6 +310,7 @@
method @RequiresPermission(android.Manifest.permission.CHANGE_WIFI_STATE) public int addNetworkSuggestions(@NonNull java.util.List<android.net.wifi.WifiNetworkSuggestion>);
method public void addOrUpdatePasspointConfiguration(android.net.wifi.hotspot2.PasspointConfiguration);
method @RequiresPermission(allOf={android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.ACCESS_WIFI_STATE}) public void addSuggestionConnectionStatusListener(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.WifiManager.SuggestionConnectionStatusListener);
+ method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public boolean addSuggestionUserApprovalStatusListener(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.WifiManager.SuggestionUserApprovalStatusListener);
method @Deprecated public static int calculateSignalLevel(int, int);
method @IntRange(from=0) public int calculateSignalLevel(int);
method @Deprecated public void cancelWps(android.net.wifi.WifiManager.WpsCallback);
@@ -319,6 +326,7 @@
method public android.net.DhcpInfo getDhcpInfo();
method public int getMaxNumberOfNetworkSuggestionsPerApp();
method @IntRange(from=0) public int getMaxSignalLevel();
+ method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public int getNetworkSuggestionUserApprovalStatus();
method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public java.util.List<android.net.wifi.WifiNetworkSuggestion> getNetworkSuggestions();
method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public java.util.List<android.net.wifi.hotspot2.PasspointConfiguration> getPasspointConfigurations();
method public java.util.List<android.net.wifi.ScanResult> getScanResults();
@@ -326,19 +334,23 @@
method public boolean is5GHzBandSupported();
method public boolean is6GHzBandSupported();
method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public boolean isAutoWakeupEnabled();
+ method public boolean isBridgedApConcurrencySupported();
method @Deprecated public boolean isDeviceToApRttSupported();
method public boolean isEasyConnectSupported();
method public boolean isEnhancedOpenSupported();
method public boolean isEnhancedPowerReportingSupported();
+ method public boolean isMultiStaConcurrencySupported();
method public boolean isP2pSupported();
method public boolean isPreferredNetworkOffloadSupported();
method @Deprecated public boolean isScanAlwaysAvailable();
method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public boolean isScanThrottleEnabled();
method public boolean isStaApConcurrencySupported();
+ method public boolean isStaBridgedApConcurrencySupported();
method public boolean isTdlsSupported();
method public boolean isWapiSupported();
method public boolean isWifiEnabled();
method public boolean isWifiStandardSupported(int);
+ method public boolean isWpa3ApValidationSupported();
method public boolean isWpa3SaeSupported();
method public boolean isWpa3SuiteBSupported();
method @Deprecated public boolean pingSupplicant();
@@ -349,6 +361,7 @@
method @RequiresPermission(android.Manifest.permission.CHANGE_WIFI_STATE) public int removeNetworkSuggestions(@NonNull java.util.List<android.net.wifi.WifiNetworkSuggestion>);
method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_CARRIER_PROVISIONING}) public void removePasspointConfiguration(String);
method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public void removeSuggestionConnectionStatusListener(@NonNull android.net.wifi.WifiManager.SuggestionConnectionStatusListener);
+ method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public void removeSuggestionUserApprovalStatusListener(@NonNull android.net.wifi.WifiManager.SuggestionUserApprovalStatusListener);
method @Deprecated public boolean saveConfiguration();
method public void setTdlsEnabled(java.net.InetAddress, boolean);
method public void setTdlsEnabledWithMacAddress(String, boolean);
@@ -387,6 +400,11 @@
field public static final int STATUS_NETWORK_SUGGESTIONS_ERROR_INTERNAL = 1; // 0x1
field public static final int STATUS_NETWORK_SUGGESTIONS_ERROR_REMOVE_INVALID = 5; // 0x5
field public static final int STATUS_NETWORK_SUGGESTIONS_SUCCESS = 0; // 0x0
+ field public static final int STATUS_SUGGESTION_APPROVAL_APPROVED_BY_CARRIER_PRIVILEGE = 4; // 0x4
+ field public static final int STATUS_SUGGESTION_APPROVAL_APPROVED_BY_USER = 2; // 0x2
+ field public static final int STATUS_SUGGESTION_APPROVAL_PENDING = 1; // 0x1
+ field public static final int STATUS_SUGGESTION_APPROVAL_REJECTED_BY_USER = 3; // 0x3
+ field public static final int STATUS_SUGGESTION_APPROVAL_UNKNOWN = 0; // 0x0
field public static final int STATUS_SUGGESTION_CONNECTION_FAILURE_ASSOCIATION = 1; // 0x1
field public static final int STATUS_SUGGESTION_CONNECTION_FAILURE_AUTHENTICATION = 2; // 0x2
field public static final int STATUS_SUGGESTION_CONNECTION_FAILURE_IP_PROVISIONING = 3; // 0x3
@@ -444,6 +462,10 @@
method public void onConnectionStatus(@NonNull android.net.wifi.WifiNetworkSuggestion, int);
}
+ public static interface WifiManager.SuggestionUserApprovalStatusListener {
+ method public void onUserApprovalStatusChange();
+ }
+
public class WifiManager.WifiLock {
method public void acquire();
method public boolean isHeld();
@@ -476,7 +498,9 @@
method @NonNull public android.net.wifi.WifiNetworkSpecifier.Builder setSsidPattern(@NonNull android.os.PatternMatcher);
method @NonNull public android.net.wifi.WifiNetworkSpecifier.Builder setWpa2EnterpriseConfig(@NonNull android.net.wifi.WifiEnterpriseConfig);
method @NonNull public android.net.wifi.WifiNetworkSpecifier.Builder setWpa2Passphrase(@NonNull String);
- method @NonNull public android.net.wifi.WifiNetworkSpecifier.Builder setWpa3EnterpriseConfig(@NonNull android.net.wifi.WifiEnterpriseConfig);
+ method @NonNull public android.net.wifi.WifiNetworkSpecifier.Builder setWpa3Enterprise192BitModeConfig(@NonNull android.net.wifi.WifiEnterpriseConfig);
+ method @Deprecated @NonNull public android.net.wifi.WifiNetworkSpecifier.Builder setWpa3EnterpriseConfig(@NonNull android.net.wifi.WifiEnterpriseConfig);
+ method @NonNull public android.net.wifi.WifiNetworkSpecifier.Builder setWpa3EnterpriseStandardModeConfig(@NonNull android.net.wifi.WifiEnterpriseConfig);
method @NonNull public android.net.wifi.WifiNetworkSpecifier.Builder setWpa3Passphrase(@NonNull String);
}
@@ -487,8 +511,11 @@
method @Nullable public String getPassphrase();
method @Nullable public android.net.wifi.hotspot2.PasspointConfiguration getPasspointConfig();
method @IntRange(from=0) public int getPriority();
+ method public int getPriorityGroup();
method @Nullable public String getSsid();
+ method public int getSubscriptionId();
method public boolean isAppInteractionRequired();
+ method public boolean isCarrierMerged();
method public boolean isCredentialSharedWithUser();
method public boolean isEnhancedOpen();
method public boolean isHiddenSsid();
@@ -504,8 +531,10 @@
ctor public WifiNetworkSuggestion.Builder();
method @NonNull public android.net.wifi.WifiNetworkSuggestion build();
method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setBssid(@NonNull android.net.MacAddress);
+ method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setCarrierMerged(boolean);
method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setCredentialSharedWithUser(boolean);
method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setIsAppInteractionRequired(boolean);
+ method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setIsEnhancedMacRandomizationEnabled(boolean);
method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setIsEnhancedOpen(boolean);
method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setIsHiddenSsid(boolean);
method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setIsInitialAutojoinEnabled(boolean);
@@ -513,13 +542,17 @@
method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setIsUserInteractionRequired(boolean);
method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setPasspointConfig(@NonNull android.net.wifi.hotspot2.PasspointConfiguration);
method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setPriority(@IntRange(from=0) int);
+ method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setPriorityGroup(int);
method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setSsid(@NonNull String);
+ method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setSubscriptionId(int);
method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setUntrusted(boolean);
method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setWapiEnterpriseConfig(@NonNull android.net.wifi.WifiEnterpriseConfig);
method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setWapiPassphrase(@NonNull String);
method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setWpa2EnterpriseConfig(@NonNull android.net.wifi.WifiEnterpriseConfig);
method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setWpa2Passphrase(@NonNull String);
- method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setWpa3EnterpriseConfig(@NonNull android.net.wifi.WifiEnterpriseConfig);
+ method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setWpa3Enterprise192BitModeConfig(@NonNull android.net.wifi.WifiEnterpriseConfig);
+ method @Deprecated @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setWpa3EnterpriseConfig(@NonNull android.net.wifi.WifiEnterpriseConfig);
+ method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setWpa3EnterpriseStandardModeConfig(@NonNull android.net.wifi.WifiEnterpriseConfig);
method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setWpa3Passphrase(@NonNull String);
}
@@ -549,12 +582,22 @@
method public void onAttached(android.net.wifi.aware.WifiAwareSession);
}
+ public final class AwareResources implements android.os.Parcelable {
+ method public int describeContents();
+ method public int getNumOfAvailableDataPaths();
+ method public int getNumOfAvailablePublishSessions();
+ method public int getNumOfAvailableSubscribeSessions();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.aware.AwareResources> CREATOR;
+ }
+
public final class Characteristics implements android.os.Parcelable {
method public int describeContents();
method public int getMaxMatchFilterLength();
method public int getMaxServiceNameLength();
method public int getMaxServiceSpecificInfoLength();
method public int getSupportedCipherSuites();
+ method public boolean isInstantCommunicationModeSupported();
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.aware.Characteristics> CREATOR;
field public static final int WIFI_AWARE_CIPHER_SUITE_NCS_SK_128 = 1; // 0x1
@@ -576,6 +619,7 @@
method public void onPublishStarted(@NonNull android.net.wifi.aware.PublishDiscoverySession);
method public void onServiceDiscovered(android.net.wifi.aware.PeerHandle, byte[], java.util.List<byte[]>);
method public void onServiceDiscoveredWithinRange(android.net.wifi.aware.PeerHandle, byte[], java.util.List<byte[]>, int);
+ method public void onServiceLost(@NonNull android.net.wifi.aware.PeerHandle, int);
method public void onSessionConfigFailed();
method public void onSessionConfigUpdated();
method public void onSessionTerminated();
@@ -649,11 +693,16 @@
public class WifiAwareManager {
method public void attach(@NonNull android.net.wifi.aware.AttachCallback, @Nullable android.os.Handler);
method public void attach(@NonNull android.net.wifi.aware.AttachCallback, @NonNull android.net.wifi.aware.IdentityChangedListener, @Nullable android.os.Handler);
- method public android.net.wifi.aware.Characteristics getCharacteristics();
+ method @Nullable public android.net.wifi.aware.AwareResources getAvailableAwareResources();
+ method @Nullable public android.net.wifi.aware.Characteristics getCharacteristics();
method public boolean isAvailable();
+ method public boolean isDeviceAttached();
+ method public boolean isInstantCommunicationModeEnabled();
field public static final String ACTION_WIFI_AWARE_STATE_CHANGED = "android.net.wifi.aware.action.WIFI_AWARE_STATE_CHANGED";
field public static final int WIFI_AWARE_DATA_PATH_ROLE_INITIATOR = 0; // 0x0
field public static final int WIFI_AWARE_DATA_PATH_ROLE_RESPONDER = 1; // 0x1
+ field public static final int WIFI_AWARE_DISCOVERY_LOST_REASON_PEER_NOT_VISIBLE = 1; // 0x1
+ field public static final int WIFI_AWARE_DISCOVERY_LOST_REASON_UNKNOWN = 0; // 0x0
}
public final class WifiAwareNetworkInfo implements android.os.Parcelable android.net.TransportInfo {
@@ -791,9 +840,15 @@
method public int describeContents();
method public String getFqdn();
method public String getFriendlyName();
+ method @Nullable public long[] getMatchAllOis();
+ method @Nullable public long[] getMatchAnyOis();
+ method @NonNull public java.util.Collection<java.lang.String> getOtherHomePartnersList();
method public long[] getRoamingConsortiumOis();
method public void setFqdn(String);
method public void setFriendlyName(String);
+ method public void setMatchAllOis(@Nullable long[]);
+ method public void setMatchAnyOis(@Nullable long[]);
+ method public void setOtherHomePartnersList(@NonNull java.util.Collection<java.lang.String>);
method public void setRoamingConsortiumOis(long[]);
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.HomeSp> CREATOR;
@@ -1108,7 +1163,11 @@
public final class RangingRequest implements android.os.Parcelable {
method public int describeContents();
+ method public static int getDefaultRttBurstSize();
method public static int getMaxPeers();
+ method public static int getMaxRttBurstSize();
+ method public static int getMinRttBurstSize();
+ method public int getRttBurstSize();
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.rtt.RangingRequest> CREATOR;
}
@@ -1120,6 +1179,7 @@
method public android.net.wifi.rtt.RangingRequest.Builder addWifiAwarePeer(@NonNull android.net.MacAddress);
method public android.net.wifi.rtt.RangingRequest.Builder addWifiAwarePeer(@NonNull android.net.wifi.aware.PeerHandle);
method public android.net.wifi.rtt.RangingRequest build();
+ method @NonNull public android.net.wifi.rtt.RangingRequest.Builder setRttBurstSize(int);
}
public final class RangingResult implements android.os.Parcelable {
diff --git a/framework/api/system-current.txt b/framework/api/system-current.txt
index 07793c1..23e3962 100644
--- a/framework/api/system-current.txt
+++ b/framework/api/system-current.txt
@@ -1,8 +1,20 @@
// Signature format: 2.0
package android.net.wifi {
+ public final class CoexUnsafeChannel implements android.os.Parcelable {
+ ctor public CoexUnsafeChannel(int, int);
+ ctor public CoexUnsafeChannel(int, int, int);
+ method public int getBand();
+ method public int getChannel();
+ method public int getPowerCapDbm();
+ method public boolean isPowerCapAvailable();
+ method public void setPowerCapDbm(int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.CoexUnsafeChannel> CREATOR;
+ }
+
public abstract class EasyConnectStatusCallback {
ctor public EasyConnectStatusCallback();
+ method public void onBootstrapUriGenerated(@NonNull String);
method public abstract void onConfiguratorSuccess(int);
method public abstract void onEnrolleeSuccess(int);
method public void onFailure(int);
@@ -241,18 +253,23 @@
method public boolean areFeaturesSupported(long);
method public int describeContents();
method public int getMaxSupportedClients();
+ method @NonNull public int[] getSupportedChannelList(int);
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.SoftApCapability> CREATOR;
field public static final long SOFTAP_FEATURE_ACS_OFFLOAD = 1L; // 0x1L
field public static final long SOFTAP_FEATURE_CLIENT_FORCE_DISCONNECT = 2L; // 0x2L
+ field public static final long SOFTAP_FEATURE_MAC_ADDRESS_CUSTOMIZATION = 8L; // 0x8L
field public static final long SOFTAP_FEATURE_WPA3_SAE = 4L; // 0x4L
}
public final class SoftApConfiguration implements android.os.Parcelable {
method @NonNull public java.util.List<android.net.MacAddress> getAllowedClientList();
method public int getBand();
+ method @NonNull public int[] getBands();
method @NonNull public java.util.List<android.net.MacAddress> getBlockedClientList();
method public int getChannel();
+ method @NonNull public android.util.SparseIntArray getChannels();
+ method public int getMacRandomizationSetting();
method public int getMaxNumberOfClients();
method public long getShutdownTimeoutMillis();
method public boolean isAutoShutdownEnabled();
@@ -260,8 +277,11 @@
method @Nullable public android.net.wifi.WifiConfiguration toWifiConfiguration();
field public static final int BAND_2GHZ = 1; // 0x1
field public static final int BAND_5GHZ = 2; // 0x2
+ field public static final int BAND_60GHZ = 8; // 0x8
field public static final int BAND_6GHZ = 4; // 0x4
- field public static final int BAND_ANY = 7; // 0x7
+ field @Deprecated public static final int BAND_ANY = 7; // 0x7
+ field public static final int RANDOMIZATION_NONE = 0; // 0x0
+ field public static final int RANDOMIZATION_PERSISTENT = 1; // 0x1
}
public static final class SoftApConfiguration.Builder {
@@ -271,11 +291,14 @@
method @NonNull public android.net.wifi.SoftApConfiguration.Builder setAllowedClientList(@NonNull java.util.List<android.net.MacAddress>);
method @NonNull public android.net.wifi.SoftApConfiguration.Builder setAutoShutdownEnabled(boolean);
method @NonNull public android.net.wifi.SoftApConfiguration.Builder setBand(int);
+ method @NonNull public android.net.wifi.SoftApConfiguration.Builder setBands(@NonNull int[]);
method @NonNull public android.net.wifi.SoftApConfiguration.Builder setBlockedClientList(@NonNull java.util.List<android.net.MacAddress>);
method @NonNull public android.net.wifi.SoftApConfiguration.Builder setBssid(@Nullable android.net.MacAddress);
method @NonNull public android.net.wifi.SoftApConfiguration.Builder setChannel(int, int);
+ method @NonNull public android.net.wifi.SoftApConfiguration.Builder setChannels(@NonNull android.util.SparseIntArray);
method @NonNull public android.net.wifi.SoftApConfiguration.Builder setClientControlByUserEnabled(boolean);
method @NonNull public android.net.wifi.SoftApConfiguration.Builder setHiddenSsid(boolean);
+ method @NonNull public android.net.wifi.SoftApConfiguration.Builder setMacRandomizationSetting(int);
method @NonNull public android.net.wifi.SoftApConfiguration.Builder setMaxNumberOfClients(@IntRange(from=0) int);
method @NonNull public android.net.wifi.SoftApConfiguration.Builder setPassphrase(@Nullable String, int);
method @NonNull public android.net.wifi.SoftApConfiguration.Builder setShutdownTimeoutMillis(@IntRange(from=0) long);
@@ -285,14 +308,20 @@
public final class SoftApInfo implements android.os.Parcelable {
method public int describeContents();
method public int getBandwidth();
+ method @Nullable public android.net.MacAddress getBssid();
method public int getFrequency();
+ method public int getWifiStandard();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field public static final int CHANNEL_WIDTH_160MHZ = 6; // 0x6
field public static final int CHANNEL_WIDTH_20MHZ = 2; // 0x2
field public static final int CHANNEL_WIDTH_20MHZ_NOHT = 1; // 0x1
+ field public static final int CHANNEL_WIDTH_2160MHZ = 7; // 0x7
field public static final int CHANNEL_WIDTH_40MHZ = 3; // 0x3
+ field public static final int CHANNEL_WIDTH_4320MHZ = 8; // 0x8
+ field public static final int CHANNEL_WIDTH_6480MHZ = 9; // 0x9
field public static final int CHANNEL_WIDTH_80MHZ = 4; // 0x4
field public static final int CHANNEL_WIDTH_80MHZ_PLUS_MHZ = 5; // 0x5
+ field public static final int CHANNEL_WIDTH_8640MHZ = 10; // 0xa
field public static final int CHANNEL_WIDTH_INVALID = 0; // 0x0
field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.SoftApInfo> CREATOR;
}
@@ -309,6 +338,7 @@
method @Deprecated @NonNull public android.net.IpConfiguration getIpConfiguration();
method @Deprecated @NonNull public android.net.wifi.WifiConfiguration.NetworkSelectionStatus getNetworkSelectionStatus();
method @Deprecated @NonNull public String getPrintableSsid();
+ method @Deprecated @NonNull public String getProfileKey();
method @Deprecated public int getRecentFailureReason();
method @Deprecated public boolean hasNoInternetAccess();
method @Deprecated public boolean isEphemeral();
@@ -320,12 +350,19 @@
field @Deprecated public static final int METERED_OVERRIDE_METERED = 1; // 0x1
field @Deprecated public static final int METERED_OVERRIDE_NONE = 0; // 0x0
field @Deprecated public static final int METERED_OVERRIDE_NOT_METERED = 2; // 0x2
+ field @Deprecated public static final int RANDOMIZATION_AUTO = 3; // 0x3
+ field @Deprecated public static final int RANDOMIZATION_ENHANCED = 2; // 0x2
field @Deprecated public static final int RANDOMIZATION_NONE = 0; // 0x0
field @Deprecated public static final int RANDOMIZATION_PERSISTENT = 1; // 0x1
field @Deprecated public static final int RECENT_FAILURE_AP_UNABLE_TO_HANDLE_NEW_STA = 17; // 0x11
+ field @Deprecated public static final int RECENT_FAILURE_DISCONNECTION_AP_BUSY = 1004; // 0x3ec
+ field @Deprecated public static final int RECENT_FAILURE_MBO_OCE_DISCONNECT = 1001; // 0x3e9
field @Deprecated public static final int RECENT_FAILURE_NONE = 0; // 0x0
+ field @Deprecated public static final int RECENT_FAILURE_POOR_CHANNEL_CONDITIONS = 1003; // 0x3eb
+ field @Deprecated public static final int RECENT_FAILURE_REFUSED_TEMPORARILY = 1002; // 0x3ea
field @Deprecated public boolean allowAutojoin;
field @Deprecated public int carrierId;
+ field @Deprecated public boolean carrierMerged;
field @Deprecated public String creatorName;
field @Deprecated public int creatorUid;
field @Deprecated public boolean fromWifiNetworkSpecifier;
@@ -340,6 +377,7 @@
field @Deprecated public int numScorerOverrideAndSwitchedNetwork;
field @Deprecated public boolean requirePmf;
field @Deprecated public boolean shared;
+ field @Deprecated public int subscriptionId;
field @Deprecated public boolean useExternalScores;
}
@@ -360,6 +398,8 @@
method @Deprecated public boolean hasEverConnected();
field @Deprecated public static final int DISABLED_ASSOCIATION_REJECTION = 1; // 0x1
field @Deprecated public static final int DISABLED_AUTHENTICATION_FAILURE = 2; // 0x2
+ field @Deprecated public static final int DISABLED_AUTHENTICATION_FAILURE_CARRIER_SPECIFIC = 10; // 0xa
+ field @Deprecated public static final int DISABLED_AUTHENTICATION_FAILURE_GENERIC = 2; // 0x2
field @Deprecated public static final int DISABLED_AUTHENTICATION_NO_CREDENTIALS = 5; // 0x5
field @Deprecated public static final int DISABLED_AUTHENTICATION_NO_SUBSCRIPTION = 9; // 0x9
field @Deprecated public static final int DISABLED_BY_WIFI_MANAGER = 7; // 0x7
@@ -406,11 +446,16 @@
method @Nullable public String getRequestingPackageName();
method public double getRetriedTxPacketsPerSecond();
method public int getScore();
+ method public int getSubscriptionId();
method public double getSuccessfulRxPacketsPerSecond();
method public double getSuccessfulTxPacketsPerSecond();
+ method public boolean isCarrierMerged();
method public boolean isEphemeral();
+ method public boolean isOemPaid();
+ method public boolean isOemPrivate();
method public boolean isOsuAp();
method public boolean isPasspointAp();
+ method public boolean isTrusted();
method @Nullable public static String sanitizeSsid(@Nullable String);
field public static final String DEFAULT_MAC_ADDRESS = "02:00:00:00:00:00";
field public static final int INVALID_RSSI = -127; // 0xffffff81
@@ -429,6 +474,8 @@
method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void factoryReset();
method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD, android.Manifest.permission.NETWORK_STACK}) public void forget(int, @Nullable android.net.wifi.WifiManager.ActionListener);
method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public java.util.List<android.util.Pair<android.net.wifi.WifiConfiguration,java.util.Map<java.lang.Integer,java.util.List<android.net.wifi.ScanResult>>>> getAllMatchingWifiConfigs(@NonNull java.util.List<android.net.wifi.ScanResult>);
+ method @RequiresPermission(android.Manifest.permission.WIFI_ACCESS_COEX_UNSAFE_CHANNELS) public int getCoexRestrictions();
+ method @NonNull @RequiresPermission(android.Manifest.permission.WIFI_ACCESS_COEX_UNSAFE_CHANNELS) public java.util.Set<android.net.wifi.CoexUnsafeChannel> getCoexUnsafeChannels();
method @Nullable @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public String getCountryCode();
method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public android.net.Network getCurrentNetwork();
method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public String[] getFactoryMacAddresses();
@@ -436,22 +483,26 @@
method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public java.util.Map<android.net.wifi.hotspot2.OsuProvider,android.net.wifi.hotspot2.PasspointConfiguration> getMatchingPasspointConfigsForOsuProviders(@NonNull java.util.Set<android.net.wifi.hotspot2.OsuProvider>);
method @NonNull @RequiresPermission(allOf={android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.ACCESS_WIFI_STATE}) public java.util.Map<android.net.wifi.WifiNetworkSuggestion,java.util.List<android.net.wifi.ScanResult>> getMatchingScanResults(@NonNull java.util.List<android.net.wifi.WifiNetworkSuggestion>, @Nullable java.util.List<android.net.wifi.ScanResult>);
method @RequiresPermission(allOf={android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.ACCESS_WIFI_STATE, android.Manifest.permission.READ_WIFI_CREDENTIAL}) public java.util.List<android.net.wifi.WifiConfiguration> getPrivilegedConfiguredNetworks();
- method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public android.net.wifi.SoftApConfiguration getSoftApConfiguration();
+ method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.OVERRIDE_WIFI_CONFIG}) public android.net.wifi.SoftApConfiguration getSoftApConfiguration();
method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public void getWifiActivityEnergyInfoAsync(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.WifiManager.OnWifiActivityEnergyInfoListener);
method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public android.net.wifi.WifiConfiguration getWifiApConfiguration();
method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public int getWifiApState();
method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public java.util.List<android.net.wifi.WifiConfiguration> getWifiConfigForMatchedNetworkSuggestionsSharedWithUser(@NonNull java.util.List<android.net.wifi.ScanResult>);
+ method public boolean is60GHzBandSupported();
method public boolean isApMacRandomizationSupported();
+ method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public boolean isCarrierNetworkOffloadEnabled(int, boolean);
method public boolean isConnectedMacRandomizationSupported();
method @Deprecated public boolean isDeviceToDeviceRttSupported();
method public boolean isPortableHotspotSupported();
method public boolean isVerboseLoggingEnabled();
method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public boolean isWifiApEnabled();
method public boolean isWifiScannerSupported();
+ method @RequiresPermission(android.Manifest.permission.WIFI_ACCESS_COEX_UNSAFE_CHANNELS) public void registerCoexCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.WifiManager.CoexCallback);
method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void registerNetworkRequestMatchCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.WifiManager.NetworkRequestMatchCallback);
method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void registerSoftApCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.WifiManager.SoftApCallback);
method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void registerTrafficStateCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.WifiManager.TrafficStateCallback);
method @RequiresPermission(android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE) public void removeOnWifiUsabilityStatsListener(@NonNull android.net.wifi.WifiManager.OnWifiUsabilityStatsListener);
+ method @RequiresPermission(android.Manifest.permission.NETWORK_AIRPLANE_MODE) public void restartWifiSubsystem(@Nullable String);
method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void restoreBackupData(@NonNull byte[]);
method @Nullable @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public android.net.wifi.SoftApConfiguration restoreSoftApBackupData(@NonNull byte[]);
method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void restoreSupplicantBackupData(@NonNull byte[], @NonNull byte[]);
@@ -459,23 +510,29 @@
method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public byte[] retrieveSoftApBackupData();
method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD, android.Manifest.permission.NETWORK_STACK}) public void save(@NonNull android.net.wifi.WifiConfiguration, @Nullable android.net.wifi.WifiManager.ActionListener);
method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void setAutoWakeupEnabled(boolean);
+ method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void setCarrierNetworkOffloadEnabled(int, boolean, boolean);
+ method @RequiresPermission(android.Manifest.permission.WIFI_UPDATE_COEX_UNSAFE_CHANNELS) public void setCoexUnsafeChannels(@NonNull java.util.Set<android.net.wifi.CoexUnsafeChannel>, int);
method @RequiresPermission(android.Manifest.permission.WIFI_SET_DEVICE_MOBILITY_STATE) public void setDeviceMobilityState(int);
method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void setMacRandomizationSettingPasspointEnabled(@NonNull String, boolean);
method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void setPasspointMeteredOverride(@NonNull String, int);
method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void setScanAlwaysAvailable(boolean);
method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void setScanThrottleEnabled(boolean);
- method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public boolean setSoftApConfiguration(@NonNull android.net.wifi.SoftApConfiguration);
+ method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.OVERRIDE_WIFI_CONFIG}) public boolean setSoftApConfiguration(@NonNull android.net.wifi.SoftApConfiguration);
method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void setVerboseLoggingEnabled(boolean);
method @Deprecated @RequiresPermission(android.Manifest.permission.CHANGE_WIFI_STATE) public boolean setWifiApConfiguration(android.net.wifi.WifiConfiguration);
method @RequiresPermission(android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE) public boolean setWifiConnectedNetworkScorer(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.WifiManager.WifiConnectedNetworkScorer);
method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void startEasyConnectAsConfiguratorInitiator(@NonNull String, int, int, @NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.EasyConnectStatusCallback);
method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void startEasyConnectAsEnrolleeInitiator(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.EasyConnectStatusCallback);
+ method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void startEasyConnectAsEnrolleeResponder(@Nullable String, int, @NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.EasyConnectStatusCallback);
method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void startLocalOnlyHotspot(@NonNull android.net.wifi.SoftApConfiguration, @Nullable java.util.concurrent.Executor, @Nullable android.net.wifi.WifiManager.LocalOnlyHotspotCallback);
method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public boolean startScan(android.os.WorkSource);
method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void startSubscriptionProvisioning(@NonNull android.net.wifi.hotspot2.OsuProvider, @NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.hotspot2.ProvisioningCallback);
+ method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void startTemporarilyDisablingAllNonCarrierMergedWifi(int);
method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public boolean startTetheredHotspot(@Nullable android.net.wifi.SoftApConfiguration);
method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void stopEasyConnectSession();
method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public boolean stopSoftAp();
+ method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void stopTemporarilyDisablingAllNonCarrierMergedWifi();
+ method @RequiresPermission(android.Manifest.permission.WIFI_ACCESS_COEX_UNSAFE_CHANNELS) public void unregisterCoexCallback(@NonNull android.net.wifi.WifiManager.CoexCallback);
method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void unregisterNetworkRequestMatchCallback(@NonNull android.net.wifi.WifiManager.NetworkRequestMatchCallback);
method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void unregisterSoftApCallback(@NonNull android.net.wifi.WifiManager.SoftApCallback);
method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void unregisterTrafficStateCallback(@NonNull android.net.wifi.WifiManager.TrafficStateCallback);
@@ -489,16 +546,27 @@
field public static final int CHANGE_REASON_ADDED = 0; // 0x0
field public static final int CHANGE_REASON_CONFIG_CHANGE = 2; // 0x2
field public static final int CHANGE_REASON_REMOVED = 1; // 0x1
+ field public static final int COEX_RESTRICTION_SOFTAP = 2; // 0x2
+ field public static final int COEX_RESTRICTION_WIFI_AWARE = 4; // 0x4
+ field public static final int COEX_RESTRICTION_WIFI_DIRECT = 1; // 0x1
field public static final String CONFIGURED_NETWORKS_CHANGED_ACTION = "android.net.wifi.CONFIGURED_NETWORKS_CHANGE";
field public static final int DEVICE_MOBILITY_STATE_HIGH_MVMT = 1; // 0x1
field public static final int DEVICE_MOBILITY_STATE_LOW_MVMT = 2; // 0x2
field public static final int DEVICE_MOBILITY_STATE_STATIONARY = 3; // 0x3
field public static final int DEVICE_MOBILITY_STATE_UNKNOWN = 0; // 0x0
+ field public static final int EASY_CONNECT_CRYPTOGRAPHY_CURVE_BRAINPOOLP256R1 = 3; // 0x3
+ field public static final int EASY_CONNECT_CRYPTOGRAPHY_CURVE_BRAINPOOLP384R1 = 4; // 0x4
+ field public static final int EASY_CONNECT_CRYPTOGRAPHY_CURVE_BRAINPOOLP512R1 = 5; // 0x5
+ field public static final int EASY_CONNECT_CRYPTOGRAPHY_CURVE_DEFAULT = 0; // 0x0
+ field public static final int EASY_CONNECT_CRYPTOGRAPHY_CURVE_PRIME256V1 = 0; // 0x0
+ field public static final int EASY_CONNECT_CRYPTOGRAPHY_CURVE_SECP384R1 = 1; // 0x1
+ field public static final int EASY_CONNECT_CRYPTOGRAPHY_CURVE_SECP521R1 = 2; // 0x2
+ field public static final int EASY_CONNECT_DEVICE_INFO_MAXIMUM_LENGTH = 40; // 0x28
field public static final int EASY_CONNECT_NETWORK_ROLE_AP = 1; // 0x1
field public static final int EASY_CONNECT_NETWORK_ROLE_STA = 0; // 0x0
field public static final String EXTRA_CHANGE_REASON = "changeReason";
- field public static final String EXTRA_LINK_PROPERTIES = "android.net.wifi.extra.LINK_PROPERTIES";
- field public static final String EXTRA_MULTIPLE_NETWORKS_CHANGED = "multipleChanges";
+ field @Deprecated public static final String EXTRA_LINK_PROPERTIES = "android.net.wifi.extra.LINK_PROPERTIES";
+ field @Deprecated public static final String EXTRA_MULTIPLE_NETWORKS_CHANGED = "multipleChanges";
field public static final String EXTRA_OSU_NETWORK = "android.net.wifi.extra.OSU_NETWORK";
field public static final String EXTRA_PREVIOUS_WIFI_AP_STATE = "previous_wifi_state";
field public static final String EXTRA_URL = "android.net.wifi.extra.URL";
@@ -506,7 +574,7 @@
field public static final String EXTRA_WIFI_AP_INTERFACE_NAME = "android.net.wifi.extra.WIFI_AP_INTERFACE_NAME";
field public static final String EXTRA_WIFI_AP_MODE = "android.net.wifi.extra.WIFI_AP_MODE";
field public static final String EXTRA_WIFI_AP_STATE = "wifi_state";
- field public static final String EXTRA_WIFI_CONFIGURATION = "wifiConfiguration";
+ field @Deprecated public static final String EXTRA_WIFI_CONFIGURATION = "wifiConfiguration";
field public static final String EXTRA_WIFI_CREDENTIAL_EVENT_TYPE = "et";
field public static final String EXTRA_WIFI_CREDENTIAL_SSID = "ssid";
field public static final int IFACE_IP_MODE_CONFIGURATION_ERROR = 0; // 0x0
@@ -536,6 +604,11 @@
method public void onSuccess();
}
+ public abstract static class WifiManager.CoexCallback {
+ ctor public WifiManager.CoexCallback();
+ method public abstract void onCoexUnsafeChannelsChanged();
+ }
+
public static interface WifiManager.NetworkRequestMatchCallback {
method public default void onAbort();
method public default void onMatch(@NonNull java.util.List<android.net.wifi.ScanResult>);
@@ -566,7 +639,9 @@
method public default void onBlockedClientConnecting(@NonNull android.net.wifi.WifiClient, int);
method public default void onCapabilityChanged(@NonNull android.net.wifi.SoftApCapability);
method public default void onConnectedClientsChanged(@NonNull java.util.List<android.net.wifi.WifiClient>);
+ method public default void onConnectedClientsChanged(@NonNull android.net.wifi.SoftApInfo, @NonNull java.util.List<android.net.wifi.WifiClient>);
method public default void onInfoChanged(@NonNull android.net.wifi.SoftApInfo);
+ method public default void onInfoChanged(@NonNull java.util.List<android.net.wifi.SoftApInfo>);
method public default void onStateChanged(int, int);
}
@@ -597,10 +672,14 @@
public final class WifiNetworkSuggestion implements android.os.Parcelable {
method @NonNull public android.net.wifi.WifiConfiguration getWifiConfiguration();
+ method public boolean isOemPaid();
+ method public boolean isOemPrivate();
}
public static final class WifiNetworkSuggestion.Builder {
method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_CARRIER_PROVISIONING) public android.net.wifi.WifiNetworkSuggestion.Builder setCarrierId(int);
+ method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setOemPaid(boolean);
+ method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setOemPrivate(boolean);
}
public class WifiScanner {
@@ -643,6 +722,7 @@
field public static final int WIFI_BAND_5_GHZ = 2; // 0x2
field public static final int WIFI_BAND_5_GHZ_DFS_ONLY = 4; // 0x4
field public static final int WIFI_BAND_5_GHZ_WITH_DFS = 6; // 0x6
+ field public static final int WIFI_BAND_60_GHZ = 16; // 0x10
field public static final int WIFI_BAND_6_GHZ = 8; // 0x8
field public static final int WIFI_BAND_BOTH = 3; // 0x3
field public static final int WIFI_BAND_BOTH_WITH_DFS = 7; // 0x7
@@ -785,6 +865,10 @@
method @Deprecated public android.net.NetworkSpecifier createNetworkSpecifierPmk(@NonNull android.net.wifi.aware.PeerHandle, @NonNull byte[]);
}
+ public class WifiAwareManager {
+ method public void enableInstantCommunicationMode(boolean);
+ }
+
public class WifiAwareSession implements java.lang.AutoCloseable {
method public android.net.NetworkSpecifier createNetworkSpecifierPmk(int, @NonNull byte[], @NonNull byte[]);
}
@@ -883,6 +967,10 @@
package android.net.wifi.rtt {
+ public final class RangingRequest implements android.os.Parcelable {
+ method @NonNull public java.util.List<android.net.wifi.rtt.ResponderConfig> getRttPeers();
+ }
+
public static final class RangingRequest.Builder {
method public android.net.wifi.rtt.RangingRequest.Builder addResponder(@NonNull android.net.wifi.rtt.ResponderConfig);
}
diff --git a/framework/api/system-lint-baseline.txt b/framework/api/system-lint-baseline.txt
index 6547ee8..9a3b66a 100644
--- a/framework/api/system-lint-baseline.txt
+++ b/framework/api/system-lint-baseline.txt
@@ -1,6 +1,13 @@
// Baseline format: 1.0
MissingGetterMatchingBuilder: android.net.wifi.rtt.RangingRequest.Builder#addResponder(android.net.wifi.rtt.ResponderConfig):
- android.net.wifi.rtt.RangingRequest does not declare a `getResponders()` method matching method android.net.wifi.rtt.RangingRequest.Builder.addResponder(android.net.wifi.rtt.ResponderConfig)
+
+
MissingNullability: android.net.wifi.rtt.RangingRequest.Builder#addResponder(android.net.wifi.rtt.ResponderConfig):
+
+
+MutableBareField: android.net.wifi.WifiConfiguration#carrierMerged:
+
+MutableBareField: android.net.wifi.WifiConfiguration#subscriptionId:
+ Bare field subscriptionId must be marked final, or moved behind accessors if mutable
diff --git a/framework/jarjar-rules.txt b/framework/jarjar-rules.txt
index 7b84d57..2331c2f 100644
--- a/framework/jarjar-rules.txt
+++ b/framework/jarjar-rules.txt
@@ -110,8 +110,6 @@
rule fi.iki.elonen.** com.android.wifi.x.@0
## used by both framework-wifi and service-wifi ##
-rule android.content.pm.BaseParceledListSlice* com.android.wifi.x.@0
-rule android.content.pm.ParceledListSlice* com.android.wifi.x.@0
rule android.os.HandlerExecutor* com.android.wifi.x.@0
rule android.telephony.Annotation* com.android.wifi.x.@0
rule com.android.internal.util.AsyncChannel* com.android.wifi.x.@0
diff --git a/framework/java/android/net/wifi/CoexUnsafeChannel.java b/framework/java/android/net/wifi/CoexUnsafeChannel.java
new file mode 100644
index 0000000..3f9efa0
--- /dev/null
+++ b/framework/java/android/net/wifi/CoexUnsafeChannel.java
@@ -0,0 +1,176 @@
+/*
+ * 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;
+
+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_6_GHZ;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/**
+ * Data structure class representing a Wi-Fi channel that would cause interference to/receive
+ * interference from the active cellular channels and should be avoided.
+ *
+ * If {@link #isPowerCapAvailable()} is {@code true}, then a valid power cap value is available
+ * through {@link #getPowerCapDbm()} to be used if this channel cannot be avoided. If {@code false},
+ * then {@link #getPowerCapDbm()} throws an IllegalStateException and the channel will not need to
+ * cap its power.
+ *
+ * @hide
+ */
+@SystemApi
+public final class CoexUnsafeChannel implements Parcelable {
+ private @WifiAnnotations.WifiBandBasic int mBand;
+ private int mChannel;
+ private boolean mIsPowerCapAvailable = false;
+ private int mPowerCapDbm;
+
+ /**
+ * Constructor for a CoexUnsafeChannel with no power cap specified.
+ * @param band One of {@link WifiAnnotations.WifiBandBasic}
+ * @param channel Channel number
+ */
+ public CoexUnsafeChannel(@WifiAnnotations.WifiBandBasic int band, int channel) {
+ mBand = band;
+ mChannel = channel;
+ }
+
+ /**
+ * Constructor for a CoexUnsafeChannel with power cap specified.
+ * @param band One of {@link WifiAnnotations.WifiBandBasic}
+ * @param channel Channel number
+ * @param powerCapDbm Power cap in dBm
+ */
+ public CoexUnsafeChannel(@WifiAnnotations.WifiBandBasic int band, int channel,
+ int powerCapDbm) {
+ mBand = band;
+ mChannel = channel;
+ setPowerCapDbm(powerCapDbm);
+ }
+
+ /** Returns the Wi-Fi band of this channel as one of {@link WifiAnnotations.WifiBandBasic} */
+ public @WifiAnnotations.WifiBandBasic int getBand() {
+ return mBand;
+ }
+
+ /** Returns the channel number of this channel. */
+ public int getChannel() {
+ return mChannel;
+ }
+
+ /** Returns {@code true} if {@link #getPowerCapDbm()} is a valid value, else {@code false} */
+ public boolean isPowerCapAvailable() {
+ return mIsPowerCapAvailable;
+ }
+
+ /**
+ * Returns the power cap of this channel in dBm. Throws IllegalStateException if
+ * {@link #isPowerCapAvailable()} is {@code false}.
+ */
+ public int getPowerCapDbm() {
+ if (!mIsPowerCapAvailable) {
+ throw new IllegalStateException("getPowerCapDbm called but power cap is unavailable");
+ }
+ return mPowerCapDbm;
+ }
+
+ /** Set the power cap of this channel. */
+ public void setPowerCapDbm(int powerCapDbm) {
+ mIsPowerCapAvailable = true;
+ mPowerCapDbm = powerCapDbm;
+ }
+
+ @Override
+ public boolean equals(@Nullable Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ CoexUnsafeChannel that = (CoexUnsafeChannel) o;
+ return mBand == that.mBand
+ && mChannel == that.mChannel
+ && mIsPowerCapAvailable == that.mIsPowerCapAvailable
+ && mPowerCapDbm == that.mPowerCapDbm;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mBand, mChannel, mIsPowerCapAvailable, mPowerCapDbm);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sj = new StringBuilder("CoexUnsafeChannel{");
+ sj.append(mChannel);
+ sj.append(", ");
+ if (mBand == WIFI_BAND_24_GHZ) {
+ sj.append("2.4GHz");
+ } else if (mBand == WIFI_BAND_5_GHZ) {
+ sj.append("5GHz");
+ } else if (mBand == WIFI_BAND_6_GHZ) {
+ sj.append("6GHz");
+ } else {
+ sj.append("UNKNOWN BAND");
+ }
+ if (mIsPowerCapAvailable) {
+ sj.append(", ").append(mPowerCapDbm).append("dBm");
+ }
+ sj.append('}');
+ return sj.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(mBand);
+ dest.writeInt(mChannel);
+ dest.writeBoolean(mIsPowerCapAvailable);
+ if (mIsPowerCapAvailable) {
+ dest.writeInt(mPowerCapDbm);
+ }
+ }
+
+ /** Implement the Parcelable interface */
+ public static final @NonNull Creator<CoexUnsafeChannel> CREATOR =
+ new Creator<CoexUnsafeChannel>() {
+ public CoexUnsafeChannel createFromParcel(Parcel in) {
+ final int band = in.readInt();
+ final int channel = in.readInt();
+ final boolean isPowerCapAvailable = in.readBoolean();
+ if (isPowerCapAvailable) {
+ final int powerCapDbm = in.readInt();
+ return new CoexUnsafeChannel(band, channel, powerCapDbm);
+ }
+ return new CoexUnsafeChannel(band, channel);
+ }
+
+ public CoexUnsafeChannel[] newArray(int size) {
+ return new CoexUnsafeChannel[size];
+ }
+ };
+}
diff --git a/framework/java/android/net/wifi/EasyConnectStatusCallback.java b/framework/java/android/net/wifi/EasyConnectStatusCallback.java
index 6c2e6dd..ee70255 100644
--- a/framework/java/android/net/wifi/EasyConnectStatusCallback.java
+++ b/framework/java/android/net/wifi/EasyConnectStatusCallback.java
@@ -161,6 +161,11 @@
*/
public static final int EASY_CONNECT_EVENT_FAILURE_ENROLLEE_REJECTED_CONFIGURATION = -12;
+ /**
+ * Easy Connect Failure event: System failed to generate DPP URI.
+ */
+ public static final int EASY_CONNECT_EVENT_FAILURE_URI_GENERATION = -13;
+
/** @hide */
@IntDef(prefix = {"EASY_CONNECT_EVENT_FAILURE_"}, value = {
EASY_CONNECT_EVENT_FAILURE_INVALID_URI,
@@ -175,6 +180,7 @@
EASY_CONNECT_EVENT_FAILURE_CANNOT_FIND_NETWORK,
EASY_CONNECT_EVENT_FAILURE_ENROLLEE_AUTHENTICATION,
EASY_CONNECT_EVENT_FAILURE_ENROLLEE_REJECTED_CONFIGURATION,
+ EASY_CONNECT_EVENT_FAILURE_URI_GENERATION,
})
@Retention(RetentionPolicy.SOURCE)
public @interface EasyConnectFailureStatusCode {
@@ -264,4 +270,17 @@
*/
@SystemApi
public abstract void onProgress(@EasyConnectProgressStatusCode int code);
+
+ /**
+ * Called when local Easy Connect Responder successfully generates a DPP URI from
+ * the supplicant. This callback is the first successful outcome
+ * of a Easy Connect Responder flow starting with
+ * {@link WifiManager#startEasyConnectAsEnrolleeResponder(String, int, Executor,
+ * EasyConnectStatusCallback)} .
+ *
+ * @param uri DPP URI from the supplicant.
+ * @hide
+ */
+ @SystemApi
+ public void onBootstrapUriGenerated(@NonNull String uri) {};
}
diff --git a/framework/java/android/net/wifi/ITxPacketCountListener.aidl b/framework/java/android/net/wifi/ICoexCallback.aidl
similarity index 69%
copy from framework/java/android/net/wifi/ITxPacketCountListener.aidl
copy to framework/java/android/net/wifi/ICoexCallback.aidl
index 9105bd0..89e4c4b 100644
--- a/framework/java/android/net/wifi/ITxPacketCountListener.aidl
+++ b/framework/java/android/net/wifi/ICoexCallback.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * 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.
@@ -17,12 +17,10 @@
package android.net.wifi;
/**
- * Interface for tx packet counter callback.
- * @deprecated no longer used, remove once removed from BaseWifiService
+ * Interface for Wi-Fi/cellular coex callback.
* @hide
*/
-oneway interface ITxPacketCountListener
+oneway interface ICoexCallback
{
- void onSuccess(int count);
- void onFailure(int reason);
+ void onCoexUnsafeChannelsChanged();
}
diff --git a/framework/java/android/net/wifi/IDppCallback.aidl b/framework/java/android/net/wifi/IDppCallback.aidl
index d7a958a..dcbe846 100644
--- a/framework/java/android/net/wifi/IDppCallback.aidl
+++ b/framework/java/android/net/wifi/IDppCallback.aidl
@@ -45,4 +45,10 @@
* to show progress.
*/
void onProgress(int status);
+
+ /**
+ * Called when local DPP Responder successfully generates a URI.
+ */
+ void onBootstrapUriGenerated(String uri);
+
}
diff --git a/framework/java/android/net/wifi/ISoftApCallback.aidl b/framework/java/android/net/wifi/ISoftApCallback.aidl
index f81bcb9..3db0a5d 100644
--- a/framework/java/android/net/wifi/ISoftApCallback.aidl
+++ b/framework/java/android/net/wifi/ISoftApCallback.aidl
@@ -40,19 +40,16 @@
void onStateChanged(int state, int failureReason);
/**
- * Service to manager callback providing connected client's information.
+ * Service to manager callback providing informations of softap.
*
- * @param clients the currently connected clients
+ * @param infos The currently {@link SoftApInfo} in each AP instance.
+ * @param clients The currently connected clients in each AP instance.
+ * @param isBridged whether or not the current AP enabled on bridged mode.
+ * @param isRegistration whether or not the callbackk was triggered when register.
*/
- void onConnectedClientsChanged(in List<WifiClient> clients);
-
- /**
- * Service to manager callback providing information of softap.
- *
- * @param softApInfo is the softap information. {@link SoftApInfo}
- */
- void onInfoChanged(in SoftApInfo softApInfo);
-
+ void onConnectedClientsOrInfoChanged(in Map<String, SoftApInfo> infos,
+ in Map<String, List<WifiClient>> clients, boolean isBridged,
+ boolean isRegistration);
/**
* Service to manager callback providing capability of softap.
diff --git a/framework/java/android/net/wifi/ITxPacketCountListener.aidl b/framework/java/android/net/wifi/ISuggestionUserApprovalStatusListener.aidl
similarity index 69%
rename from framework/java/android/net/wifi/ITxPacketCountListener.aidl
rename to framework/java/android/net/wifi/ISuggestionUserApprovalStatusListener.aidl
index 9105bd0..5aa3a90 100644
--- a/framework/java/android/net/wifi/ITxPacketCountListener.aidl
+++ b/framework/java/android/net/wifi/ISuggestionUserApprovalStatusListener.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * 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.
@@ -17,12 +17,11 @@
package android.net.wifi;
/**
- * Interface for tx packet counter callback.
- * @deprecated no longer used, remove once removed from BaseWifiService
+ * Interface for suggestion user approval status listener.
+ *
* @hide
*/
-oneway interface ITxPacketCountListener
+oneway interface ISuggestionUserApprovalStatusListener
{
- void onSuccess(int count);
- void onFailure(int reason);
+ void onUserApprovalStatusChange();
}
diff --git a/framework/java/android/net/wifi/IWifiManager.aidl b/framework/java/android/net/wifi/IWifiManager.aidl
index 3f79364..23f47ef 100644
--- a/framework/java/android/net/wifi/IWifiManager.aidl
+++ b/framework/java/android/net/wifi/IWifiManager.aidl
@@ -16,15 +16,15 @@
package android.net.wifi;
-import android.content.pm.ParceledListSlice;
-
import android.net.wifi.hotspot2.OsuProvider;
import android.net.wifi.hotspot2.PasspointConfiguration;
import android.net.wifi.hotspot2.IProvisioningCallback;
import android.net.DhcpInfo;
import android.net.Network;
+import android.net.wifi.CoexUnsafeChannel;
import android.net.wifi.IActionListener;
+import android.net.wifi.ICoexCallback;
import android.net.wifi.IDppCallback;
import android.net.wifi.ILocalOnlyHotspotCallback;
import android.net.wifi.INetworkRequestMatchCallback;
@@ -33,6 +33,7 @@
import android.net.wifi.IScanResultsCallback;
import android.net.wifi.ISoftApCallback;
import android.net.wifi.ISuggestionConnectionStatusListener;
+import android.net.wifi.ISuggestionUserApprovalStatusListener;
import android.net.wifi.ITrafficStateCallback;
import android.net.wifi.IWifiConnectedNetworkScorer;
import android.net.wifi.ScanResult;
@@ -45,6 +46,8 @@
import android.os.ResultReceiver;
import android.os.WorkSource;
+import com.android.modules.utils.ParceledListSlice;
+
/**
* Interface that allows controlling and querying Wi-Fi connectivity.
*
@@ -80,8 +83,6 @@
int matchProviderWithCurrentNetwork(String fqdn);
- void deauthenticateNetwork(long holdoff, boolean ess);
-
boolean removeNetwork(int netId, String packageName);
boolean enableNetwork(int netId, boolean disableOthers, String packageName);
@@ -120,11 +121,13 @@
boolean is6GHzBandSupported();
+ boolean is60GHzBandSupported();
+
boolean isWifiStandardSupported(int standard);
DhcpInfo getDhcpInfo();
- void setScanAlwaysAvailable(boolean isAvailable);
+ void setScanAlwaysAvailable(boolean isAvailable, String packageName);
boolean isScanAlwaysAvailable();
@@ -144,9 +147,21 @@
void updateInterfaceIpState(String ifaceName, int mode);
- boolean startSoftAp(in WifiConfiguration wifiConfig);
+ boolean isDefaultCoexAlgorithmEnabled();
- boolean startTetheredHotspot(in SoftApConfiguration softApConfig);
+ void setCoexUnsafeChannels(in List<CoexUnsafeChannel> unsafeChannels, int mandatoryRestrictions);
+
+ List<CoexUnsafeChannel> getCoexUnsafeChannels();
+
+ int getCoexRestrictions();
+
+ void registerCoexCallback(in ICoexCallback callback);
+
+ void unregisterCoexCallback(in ICoexCallback callback);
+
+ boolean startSoftAp(in WifiConfiguration wifiConfig, String packageName);
+
+ boolean startTetheredHotspot(in SoftApConfiguration softApConfig, String packageName);
boolean stopSoftAp();
@@ -235,15 +250,18 @@
void startDppAsEnrolleeInitiator(in IBinder binder, in String configuratorUri,
in IDppCallback callback);
+ void startDppAsEnrolleeResponder(in IBinder binder, in String deviceInfo, int curve,
+ in IDppCallback callback);
+
void stopDppSession();
void updateWifiUsabilityScore(int seqNum, int score, int predictionHorizonSec);
- oneway void connect(in WifiConfiguration config, int netId, in IBinder binder, in IActionListener listener, int callbackIdentifier);
+ oneway void connect(in WifiConfiguration config, int netId, in IActionListener listener);
- oneway void save(in WifiConfiguration config, in IBinder binder, in IActionListener listener, int callbackIdentifier);
+ oneway void save(in WifiConfiguration config, in IActionListener listener);
- oneway void forget(int netId, in IBinder binder, in IActionListener listener, int callbackIdentifier);
+ oneway void forget(int netId, in IActionListener listener);
void registerScanResultsCallback(in IScanResultsCallback callback);
@@ -275,4 +293,20 @@
void setAutoWakeupEnabled(boolean enable);
boolean isAutoWakeupEnabled();
+
+ int getNetworkSuggestionUserApprovalStatus(String packageName);
+
+ void startTemporarilyDisablingAllNonCarrierMergedWifi(int subId);
+
+ void stopTemporarilyDisablingAllNonCarrierMergedWifi();
+
+ void setCarrierNetworkOffloadEnabled(int subscriptionId, boolean merged, boolean enabled);
+
+ boolean isCarrierNetworkOffloadEnabled(int subscriptionId, boolean merged);
+
+ void restartWifiSubsystem(String reason);
+
+ boolean addSuggestionUserApprovalStatusListener(in IBinder binder, in ISuggestionUserApprovalStatusListener listener, int listenerIdentifier, String packageName, String featureId);
+
+ void removeSuggestionUserApprovalStatusListener(int listenerIdentifier, String packageName);
}
diff --git a/framework/java/android/net/wifi/ScanResult.java b/framework/java/android/net/wifi/ScanResult.java
index 5589bd1..9f8ecf1 100644
--- a/framework/java/android/net/wifi/ScanResult.java
+++ b/framework/java/android/net/wifi/ScanResult.java
@@ -82,6 +82,12 @@
public String capabilities;
/**
+ * The interface name on which the scan result was received.
+ * @hide
+ */
+ public String ifaceName;
+
+ /**
* @hide
* No security protocol.
*/
@@ -314,6 +320,11 @@
public static final int WIFI_STANDARD_11AX = 6;
/**
+ * Wi-Fi 802.11ad/ay
+ */
+ public static final int WIFI_STANDARD_11AD = 7;
+
+ /**
* AP wifi standard.
*/
private @WifiStandard int mWifiStandard;
@@ -346,6 +357,8 @@
return "11ac";
case WIFI_STANDARD_11AX:
return "11ax";
+ case WIFI_STANDARD_11AD:
+ return "11ad";
case WIFI_STANDARD_UNKNOWN:
return "unknown";
}
@@ -596,6 +609,27 @@
public static final int BAND_6_GHZ_OP_CLASS_136_CH_2_FREQ_MHZ = 5935;
/**
+ * 60 GHz band first channel number
+ * @hide
+ */
+ public static final int BAND_60_GHZ_FIRST_CH_NUM = 1;
+ /**
+ * 60 GHz band last channel number
+ * @hide
+ */
+ public static final int BAND_60_GHZ_LAST_CH_NUM = 6;
+ /**
+ * 60 GHz band frequency of first channel in MHz
+ * @hide
+ */
+ public static final int BAND_60_GHZ_START_FREQ_MHZ = 58320;
+ /**
+ * 60 GHz band frequency of last channel in MHz
+ * @hide
+ */
+ public static final int BAND_60_GHZ_END_FREQ_MHZ = 70200;
+
+ /**
* Utility function to check if a frequency within 2.4 GHz band
* @param freqMhz frequency in MHz
* @return true if within 2.4GHz, false otherwise
@@ -632,6 +666,17 @@
}
/**
+ * Utility function to check if a frequency within 60 GHz band
+ * @param freqMhz
+ * @return true if within 60GHz, false otherwise
+ *
+ * @hide
+ */
+ public static boolean is60GHz(int freqMhz) {
+ return freqMhz >= BAND_60_GHZ_START_FREQ_MHZ && freqMhz <= BAND_60_GHZ_END_FREQ_MHZ;
+ }
+
+ /**
* Utility function to convert channel number/band to frequency in MHz
* @param channel number to convert
* @param band of channel to convert
@@ -667,6 +712,13 @@
return UNSPECIFIED;
}
}
+ if (band == WifiScanner.WIFI_BAND_60_GHZ) {
+ if (channel >= BAND_60_GHZ_FIRST_CH_NUM && channel <= BAND_60_GHZ_LAST_CH_NUM) {
+ return ((channel - BAND_60_GHZ_FIRST_CH_NUM) * 2160) + BAND_60_GHZ_START_FREQ_MHZ;
+ } else {
+ return UNSPECIFIED;
+ }
+ }
return UNSPECIFIED;
}
@@ -717,6 +769,13 @@
}
/**
+ * @hide
+ */
+ public boolean is60GHz() {
+ return ScanResult.is60GHz(frequency);
+ }
+
+ /**
* @hide
* anqp lines from supplicant BSS response
*/
@@ -955,6 +1014,7 @@
flags = source.flags;
radioChainInfos = source.radioChainInfos;
this.mWifiStandard = source.mWifiStandard;
+ this.ifaceName = source.ifaceName;
}
}
@@ -993,6 +1053,7 @@
sb.append(", 80211mcResponder: ");
sb.append(((flags & FLAG_80211mc_RESPONDER) != 0) ? "is supported" : "is not supported");
sb.append(", Radio Chain Infos: ").append(Arrays.toString(radioChainInfos));
+ sb.append(", interface name: ").append(ifaceName);
return sb.toString();
}
@@ -1072,6 +1133,7 @@
} else {
dest.writeInt(0);
}
+ dest.writeString((ifaceName != null) ? ifaceName.toString() : "");
}
/** Implement the Parcelable interface */
@@ -1150,6 +1212,7 @@
sr.radioChainInfos[i].level = in.readInt();
}
}
+ sr.ifaceName = in.readString();
return sr;
}
diff --git a/framework/java/android/net/wifi/SecurityParams.java b/framework/java/android/net/wifi/SecurityParams.java
new file mode 100644
index 0000000..8ee2ea0
--- /dev/null
+++ b/framework/java/android/net/wifi/SecurityParams.java
@@ -0,0 +1,888 @@
+/*
+ * 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;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.net.wifi.WifiConfiguration.AuthAlgorithm;
+import android.net.wifi.WifiConfiguration.GroupCipher;
+import android.net.wifi.WifiConfiguration.GroupMgmtCipher;
+import android.net.wifi.WifiConfiguration.KeyMgmt;
+import android.net.wifi.WifiConfiguration.PairwiseCipher;
+import android.net.wifi.WifiConfiguration.Protocol;
+import android.net.wifi.WifiConfiguration.SecurityType;
+import android.net.wifi.WifiConfiguration.SuiteBCipher;
+import android.os.Parcel;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.BitSet;
+import java.util.Objects;
+
+/**
+ * A class representing a security configuration.
+ * @hide
+ */
+public class SecurityParams {
+ private static final String TAG = "SecurityParams";
+
+ /** Passpoint Release 1 */
+ public static final int PASSPOINT_R1 = 1;
+
+ /** Passpoint Release 2 */
+ public static final int PASSPOINT_R2 = 2;
+
+ /** Passpoint Release 3 */
+ public static final int PASSPOINT_R3 = 3;
+
+ @IntDef(prefix = { "PASSPOINT_" }, value = {
+ PASSPOINT_R1,
+ PASSPOINT_R2,
+ PASSPOINT_R3,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface PasspointRelease {}
+
+ private @SecurityType int mSecurityType = WifiConfiguration.SECURITY_TYPE_PSK;
+
+ /**
+ * This indicates that this security type is enabled or disabled.
+ * Ex. While receiving Transition Disable Indication, older
+ * security should be disabled.
+ */
+ private boolean mEnabled = true;
+
+ /**
+ * The set of key management protocols supported by this configuration.
+ * See {@link KeyMgmt} for descriptions of the values.
+ * This is set automatically based on the security type.
+ */
+ private BitSet mAllowedKeyManagement = new BitSet();
+
+ /**
+ * The set of security protocols supported by this configuration.
+ * See {@link Protocol} for descriptions of the values.
+ * This is set automatically based on the security type.
+ */
+ private BitSet mAllowedProtocols = new BitSet();
+
+ /**
+ * The set of authentication protocols supported by this configuration.
+ * See {@link AuthAlgorithm} for descriptions of the values.
+ * This is set automatically based on the security type.
+ */
+ private BitSet mAllowedAuthAlgorithms = new BitSet();
+
+ /**
+ * The set of pairwise ciphers for WPA supported by this configuration.
+ * See {@link PairwiseCipher} for descriptions of the values.
+ * This is set automatically based on the security type.
+ */
+ private BitSet mAllowedPairwiseCiphers = new BitSet();
+
+ /**
+ * The set of group ciphers supported by this configuration.
+ * See {@link GroupCipher} for descriptions of the values.
+ * This is set automatically based on the security type.
+ */
+ private BitSet mAllowedGroupCiphers = new BitSet();
+
+ /**
+ * The set of group management ciphers supported by this configuration.
+ * See {@link GroupMgmtCipher} for descriptions of the values.
+ */
+ private BitSet mAllowedGroupManagementCiphers = new BitSet();
+
+ /**
+ * The set of SuiteB ciphers supported by this configuration.
+ * To be used for WPA3-Enterprise mode. Set automatically by the framework based on the
+ * certificate type that is used in this configuration.
+ */
+ private BitSet mAllowedSuiteBCiphers = new BitSet();
+
+ /**
+ * True if the network requires Protected Management Frames (PMF), false otherwise.
+ */
+ private boolean mRequirePmf = false;
+
+ private @PasspointRelease int mPasspointRelease = PASSPOINT_R2;
+
+ /** Indicate that this SAE security type only accepts H2E (Hash-to-Element) mode. */
+ private boolean mIsSaeH2eOnlyMode = false;
+
+ /** Indicate that this SAE security type only accepts PK (Public Key) mode. */
+ private boolean mIsSaePkOnlyMode = false;
+
+ /** Indicate whether this is added by auto-upgrade or not. */
+ private boolean mIsAddedByAutoUpgrade = false;
+
+ /** Constructor */
+ private SecurityParams() {
+ }
+
+ /** Copy constructor */
+ public SecurityParams(@NonNull SecurityParams source) {
+ this.mSecurityType = source.mSecurityType;
+ this.mEnabled = source.mEnabled;
+ this.mAllowedKeyManagement = (BitSet) source.mAllowedKeyManagement.clone();
+ this.mAllowedProtocols = (BitSet) source.mAllowedProtocols.clone();
+ this.mAllowedAuthAlgorithms = (BitSet) source.mAllowedAuthAlgorithms.clone();
+ this.mAllowedPairwiseCiphers = (BitSet) source.mAllowedPairwiseCiphers.clone();
+ this.mAllowedGroupCiphers = (BitSet) source.mAllowedGroupCiphers.clone();
+ this.mAllowedGroupManagementCiphers =
+ (BitSet) source.mAllowedGroupManagementCiphers.clone();
+ this.mAllowedSuiteBCiphers =
+ (BitSet) source.mAllowedSuiteBCiphers.clone();
+ this.mRequirePmf = source.mRequirePmf;
+ this.mIsSaeH2eOnlyMode = source.mIsSaeH2eOnlyMode;
+ this.mIsSaePkOnlyMode = source.mIsSaePkOnlyMode;
+ this.mIsAddedByAutoUpgrade = source.mIsAddedByAutoUpgrade;
+ }
+
+ @Override
+ public boolean equals(Object thatObject) {
+ if (this == thatObject) {
+ return true;
+ }
+ if (!(thatObject instanceof SecurityParams)) {
+ return false;
+ }
+ SecurityParams that = (SecurityParams) thatObject;
+
+ if (this.mSecurityType != that.mSecurityType) return false;
+ if (this.mEnabled != that.mEnabled) return false;
+ if (!this.mAllowedKeyManagement.equals(that.mAllowedKeyManagement)) return false;
+ if (!this.mAllowedProtocols.equals(that.mAllowedProtocols)) return false;
+ if (!this.mAllowedAuthAlgorithms.equals(that.mAllowedAuthAlgorithms)) return false;
+ if (!this.mAllowedPairwiseCiphers.equals(that.mAllowedPairwiseCiphers)) return false;
+ if (!this.mAllowedGroupCiphers.equals(that.mAllowedGroupCiphers)) return false;
+ if (!this.mAllowedGroupManagementCiphers.equals(that.mAllowedGroupManagementCiphers)) {
+ return false;
+ }
+ if (!this.mAllowedSuiteBCiphers.equals(that.mAllowedSuiteBCiphers)) return false;
+ if (this.mRequirePmf != that.mRequirePmf) return false;
+ if (this.mIsSaeH2eOnlyMode != that.mIsSaeH2eOnlyMode) return false;
+ if (this.mIsSaePkOnlyMode != that.mIsSaePkOnlyMode) return false;
+ if (this.mIsAddedByAutoUpgrade != that.mIsAddedByAutoUpgrade) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mSecurityType, mEnabled,
+ mAllowedKeyManagement, mAllowedProtocols, mAllowedAuthAlgorithms,
+ mAllowedPairwiseCiphers, mAllowedGroupCiphers, mAllowedGroupManagementCiphers,
+ mAllowedSuiteBCiphers, mRequirePmf,
+ mIsSaeH2eOnlyMode, mIsSaePkOnlyMode, mIsAddedByAutoUpgrade);
+ }
+
+ /**
+ * Get the security type of this params.
+ *
+ * @return The security type defined in {@link WifiConfiguration}.
+ */
+ public @SecurityType int getSecurityType() {
+ return mSecurityType;
+ }
+
+ /**
+ * Check the security type of this params.
+ *
+ * @param type the testing security type.
+ * @return true if this is for the corresponiding type.
+ */
+ public boolean isSecurityType(@SecurityType int type) {
+ return type == mSecurityType;
+ }
+
+ /**
+ * Check whether the security of given params is the same as this one.
+ *
+ * @param params the testing security params.
+ * @return true if their security types are the same.
+ */
+ public boolean isSameSecurityType(SecurityParams params) {
+ return params.mSecurityType == mSecurityType;
+ }
+
+ /**
+ * Update security params to legacy WifiConfiguration object.
+ *
+ * @param config the target configuration.
+ */
+ public void updateLegacyWifiConfiguration(WifiConfiguration config) {
+ config.allowedKeyManagement = (BitSet) mAllowedKeyManagement.clone();
+ config.allowedProtocols = (BitSet) mAllowedProtocols.clone();
+ config.allowedAuthAlgorithms = (BitSet) mAllowedAuthAlgorithms.clone();
+ config.allowedPairwiseCiphers = (BitSet) mAllowedPairwiseCiphers.clone();
+ config.allowedGroupCiphers = (BitSet) mAllowedGroupCiphers.clone();
+ config.allowedGroupManagementCiphers = (BitSet) mAllowedGroupManagementCiphers.clone();
+ config.allowedSuiteBCiphers = (BitSet) mAllowedSuiteBCiphers.clone();
+ config.requirePmf = mRequirePmf;
+ }
+
+ /**
+ * Set this params enabled.
+ *
+ * @param enable enable a specific security type.
+ */
+ public void setEnabled(boolean enable) {
+ mEnabled = enable;
+ }
+
+ /**
+ * Indicate this params is enabled or not.
+ */
+ public boolean isEnabled() {
+ return mEnabled;
+ }
+
+ /**
+ * Set the supporting Fast Initial Link Set-up (FILS) key management.
+ *
+ * FILS can be applied to all security types.
+ * @param enableFilsSha256 Enable FILS SHA256.
+ * @param enableFilsSha384 Enable FILS SHA256.
+ */
+ public void enableFils(boolean enableFilsSha256, boolean enableFilsSha384) {
+ if (enableFilsSha256) {
+ mAllowedKeyManagement.set(KeyMgmt.FILS_SHA256);
+ }
+
+ if (enableFilsSha384) {
+ mAllowedKeyManagement.set(KeyMgmt.FILS_SHA384);
+ }
+ }
+
+ /**
+ * Get the copy of allowed key management.
+ */
+ public BitSet getAllowedKeyManagement() {
+ return (BitSet) mAllowedKeyManagement.clone();
+ }
+
+ /**
+ * Get the copy of allowed protocols.
+ */
+ public BitSet getAllowedProtocols() {
+ return (BitSet) mAllowedProtocols.clone();
+ }
+
+ /**
+ * Get the copy of allowed auth algorithms.
+ */
+ public BitSet getAllowedAuthAlgorithms() {
+ return (BitSet) mAllowedAuthAlgorithms.clone();
+ }
+
+ /**
+ * Get the copy of allowed pairwise ciphers.
+ */
+ public BitSet getAllowedPairwiseCiphers() {
+ return (BitSet) mAllowedPairwiseCiphers.clone();
+ }
+
+ /**
+ * Get the copy of allowed group ciphers.
+ */
+ public BitSet getAllowedGroupCiphers() {
+ return (BitSet) mAllowedGroupCiphers.clone();
+ }
+
+ /**
+ * Get the copy of allowed group management ciphers.
+ */
+ public BitSet getAllowedGroupManagementCiphers() {
+ return (BitSet) mAllowedGroupManagementCiphers.clone();
+ }
+
+ /**
+ * Enable Suite-B ciphers.
+ *
+ * @param enableEcdheEcdsa enable Diffie-Hellman with Elliptic Curve ECDSA cipher support.
+ * @param enableEcdheRsa enable Diffie-Hellman with RSA cipher support.
+ */
+ public void enableSuiteBCiphers(boolean enableEcdheEcdsa, boolean enableEcdheRsa) {
+ if (enableEcdheEcdsa) {
+ mAllowedSuiteBCiphers.set(SuiteBCipher.ECDHE_ECDSA);
+ } else {
+ mAllowedSuiteBCiphers.clear(SuiteBCipher.ECDHE_ECDSA);
+ }
+
+ if (enableEcdheRsa) {
+ mAllowedSuiteBCiphers.set(SuiteBCipher.ECDHE_RSA);
+ } else {
+ mAllowedSuiteBCiphers.clear(SuiteBCipher.ECDHE_RSA);
+ }
+ }
+
+ /**
+ * Get the copy of allowed suite-b ciphers.
+ */
+ public BitSet getAllowedSuiteBCiphers() {
+ return (BitSet) mAllowedSuiteBCiphers.clone();
+ }
+
+ /**
+ * Indicate PMF is required or not.
+ */
+ public boolean isRequirePmf() {
+ return mRequirePmf;
+ }
+
+ /**
+ * Indicate that this is open security type.
+ */
+ public boolean isOpenSecurityType() {
+ return isSecurityType(WifiConfiguration.SECURITY_TYPE_OPEN)
+ || isSecurityType(WifiConfiguration.SECURITY_TYPE_OWE);
+ }
+
+ /**
+ * Indicate that this is enterprise security type.
+ */
+ public boolean isEnterpriseSecurityType() {
+ return mAllowedKeyManagement.get(KeyMgmt.WPA_EAP)
+ || mAllowedKeyManagement.get(KeyMgmt.IEEE8021X)
+ || mAllowedKeyManagement.get(KeyMgmt.SUITE_B_192)
+ || mAllowedKeyManagement.get(KeyMgmt.WAPI_CERT);
+ }
+
+ /**
+ * Enable Hash-to-Element only mode.
+ *
+ * @param enable set H2E only mode enabled or not.
+ */
+ public void enableSaeH2eOnlyMode(boolean enable) {
+ mIsSaeH2eOnlyMode = enable;
+ }
+
+ /**
+ * Indicate whether this params is H2E only mode.
+ *
+ * @return true if this is H2E only mode params.
+ */
+ public boolean isSaeH2eOnlyMode() {
+ return mIsSaeH2eOnlyMode;
+ }
+ /**
+ * Enable Pubilc-Key only mode.
+ *
+ * @param enable set PK only mode enabled or not.
+ */
+ public void enableSaePkOnlyMode(boolean enable) {
+ mIsSaePkOnlyMode = enable;
+ }
+
+ /**
+ * Indicate whether this params is PK only mode.
+ *
+ * @return true if this is PK only mode params.
+ */
+ public boolean isSaePkOnlyMode() {
+ return mIsSaePkOnlyMode;
+ }
+
+ /**
+ * Set whether this is added by auto-upgrade.
+ *
+ * @param addedByAutoUpgrade true if added by auto-upgrade.
+ */
+ public void setIsAddedByAutoUpgrade(boolean addedByAutoUpgrade) {
+ mIsAddedByAutoUpgrade = addedByAutoUpgrade;
+ }
+
+ /**
+ * Indicate whether this is added by auto-upgrade or not.
+ *
+ * @return true if added by auto-upgrade; otherwise, false.
+ */
+ public boolean isAddedByAutoUpgrade() {
+ return mIsAddedByAutoUpgrade;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sbuf = new StringBuilder();
+ sbuf.append("Security Parameters:\n");
+ sbuf.append(" Type: ").append(mSecurityType).append("\n");
+ sbuf.append(" Enabled: ").append(mEnabled).append("\n");
+ sbuf.append(" KeyMgmt:");
+ for (int k = 0; k < mAllowedKeyManagement.size(); k++) {
+ if (mAllowedKeyManagement.get(k)) {
+ sbuf.append(" ");
+ if (k < KeyMgmt.strings.length) {
+ sbuf.append(KeyMgmt.strings[k]);
+ } else {
+ sbuf.append("??");
+ }
+ }
+ }
+ sbuf.append('\n');
+ sbuf.append(" Protocols:");
+ for (int p = 0; p < mAllowedProtocols.size(); p++) {
+ if (mAllowedProtocols.get(p)) {
+ sbuf.append(" ");
+ if (p < Protocol.strings.length) {
+ sbuf.append(Protocol.strings[p]);
+ } else {
+ sbuf.append("??");
+ }
+ }
+ }
+ sbuf.append('\n');
+ sbuf.append(" AuthAlgorithms:");
+ for (int a = 0; a < mAllowedAuthAlgorithms.size(); a++) {
+ if (mAllowedAuthAlgorithms.get(a)) {
+ sbuf.append(" ");
+ if (a < AuthAlgorithm.strings.length) {
+ sbuf.append(AuthAlgorithm.strings[a]);
+ } else {
+ sbuf.append("??");
+ }
+ }
+ }
+ sbuf.append('\n');
+ sbuf.append(" PairwiseCiphers:");
+ for (int pc = 0; pc < mAllowedPairwiseCiphers.size(); pc++) {
+ if (mAllowedPairwiseCiphers.get(pc)) {
+ sbuf.append(" ");
+ if (pc < PairwiseCipher.strings.length) {
+ sbuf.append(PairwiseCipher.strings[pc]);
+ } else {
+ sbuf.append("??");
+ }
+ }
+ }
+ sbuf.append('\n');
+ sbuf.append(" GroupCiphers:");
+ for (int gc = 0; gc < mAllowedGroupCiphers.size(); gc++) {
+ if (mAllowedGroupCiphers.get(gc)) {
+ sbuf.append(" ");
+ if (gc < GroupCipher.strings.length) {
+ sbuf.append(GroupCipher.strings[gc]);
+ } else {
+ sbuf.append("??");
+ }
+ }
+ }
+ sbuf.append('\n');
+ sbuf.append(" GroupMgmtCiphers:");
+ for (int gmc = 0; gmc < mAllowedGroupManagementCiphers.size(); gmc++) {
+ if (mAllowedGroupManagementCiphers.get(gmc)) {
+ sbuf.append(" ");
+ if (gmc < GroupMgmtCipher.strings.length) {
+ sbuf.append(GroupMgmtCipher.strings[gmc]);
+ } else {
+ sbuf.append("??");
+ }
+ }
+ }
+ sbuf.append('\n');
+ sbuf.append(" SuiteBCiphers:");
+ for (int sbc = 0; sbc < mAllowedSuiteBCiphers.size(); sbc++) {
+ if (mAllowedSuiteBCiphers.get(sbc)) {
+ sbuf.append(" ");
+ if (sbc < SuiteBCipher.strings.length) {
+ sbuf.append(SuiteBCipher.strings[sbc]);
+ } else {
+ sbuf.append("??");
+ }
+ }
+ }
+ sbuf.append('\n');
+ sbuf.append(" RequirePmf: ").append(mRequirePmf).append('\n');
+ sbuf.append(" IsAddedByAutoUpgrade: ").append(mIsAddedByAutoUpgrade).append("\n");
+ sbuf.append(" IsSaeH2eOnlyMode: ").append(mIsSaeH2eOnlyMode).append("\n");
+ sbuf.append(" IsSaePkOnlyMode: ").append(mIsSaePkOnlyMode).append("\n");
+ return sbuf.toString();
+ }
+
+ private static BitSet readBitSet(Parcel src) {
+ int cardinality = src.readInt();
+
+ BitSet set = new BitSet();
+ for (int i = 0; i < cardinality; i++) {
+ set.set(src.readInt());
+ }
+
+ return set;
+ }
+
+ private static void writeBitSet(Parcel dest, BitSet set) {
+ int nextSetBit = -1;
+
+ dest.writeInt(set.cardinality());
+
+ while ((nextSetBit = set.nextSetBit(nextSetBit + 1)) != -1) {
+ dest.writeInt(nextSetBit);
+ }
+ }
+
+ /** Write this object to the parcel. */
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(mSecurityType);
+ dest.writeBoolean(mEnabled);
+ writeBitSet(dest, mAllowedKeyManagement);
+ writeBitSet(dest, mAllowedProtocols);
+ writeBitSet(dest, mAllowedAuthAlgorithms);
+ writeBitSet(dest, mAllowedPairwiseCiphers);
+ writeBitSet(dest, mAllowedGroupCiphers);
+ writeBitSet(dest, mAllowedGroupManagementCiphers);
+ writeBitSet(dest, mAllowedSuiteBCiphers);
+ dest.writeBoolean(mRequirePmf);
+ dest.writeBoolean(mIsAddedByAutoUpgrade);
+ dest.writeBoolean(mIsSaeH2eOnlyMode);
+ dest.writeBoolean(mIsSaePkOnlyMode);
+
+ }
+
+ /** Create a SecurityParams object from the parcel. */
+ public static final @NonNull SecurityParams createFromParcel(Parcel in) {
+ SecurityParams params = new SecurityParams();
+ params.mSecurityType = in.readInt();
+ params.mEnabled = in.readBoolean();
+ params.mAllowedKeyManagement = readBitSet(in);
+ params.mAllowedProtocols = readBitSet(in);
+ params.mAllowedAuthAlgorithms = readBitSet(in);
+ params.mAllowedPairwiseCiphers = readBitSet(in);
+ params.mAllowedGroupCiphers = readBitSet(in);
+ params.mAllowedGroupManagementCiphers = readBitSet(in);
+ params.mAllowedSuiteBCiphers = readBitSet(in);
+ params.mRequirePmf = in.readBoolean();
+ params.mIsAddedByAutoUpgrade = in.readBoolean();
+ params.mIsSaeH2eOnlyMode = in.readBoolean();
+ params.mIsSaePkOnlyMode = in.readBoolean();
+ return params;
+ }
+
+ /**
+ * Create a params according to the security type.
+ *
+ * @param securityType One of the following security types:
+ * {@link WifiConfiguration#SECURITY_TYPE_OPEN},
+ * {@link WifiConfiguration#SECURITY_TYPE_WEP},
+ * {@link WifiConfiguration#SECURITY_TYPE_PSK},
+ * {@link WifiConfiguration#SECURITY_TYPE_EAP},
+ * {@link WifiConfiguration#SECURITY_TYPE_SAE},
+ * {@link WifiConfiguration#SECURITY_TYPE_OWE},
+ * {@link WifiConfiguration#SECURITY_TYPE_WAPI_PSK},
+ * {@link WifiConfiguration#SECURITY_TYPE_WAPI_CERT},
+ * {@link WifiConfiguration#SECURITY_TYPE_EAP_WPA3_ENTERPRISE},
+ * {@link WifiConfiguration#SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT},
+ *
+ * @return the corresponding security params if the security type is valid;
+ * otherwise, throw IllegalArgumentException.
+ */
+ public static @NonNull SecurityParams createSecurityParamsBySecurityType(
+ @WifiConfiguration.SecurityType int securityType) {
+ switch (securityType) {
+ case WifiConfiguration.SECURITY_TYPE_OPEN:
+ return createOpenParams();
+ case WifiConfiguration.SECURITY_TYPE_WEP:
+ return createWepParams();
+ case WifiConfiguration.SECURITY_TYPE_PSK:
+ return createWpaWpa2PersonalParams();
+ case WifiConfiguration.SECURITY_TYPE_EAP:
+ return createWpaWpa2EnterpriseParams();
+ case WifiConfiguration.SECURITY_TYPE_SAE:
+ return createWpa3PersonalParams();
+ // The value of {@link WifiConfiguration.SECURITY_TYPE_EAP_SUITE_B} is the same as
+ // {@link #WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT}, remove it
+ // to avoid duplicate case label errors.
+ case WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT:
+ return createWpa3Enterprise192BitParams();
+ case WifiConfiguration.SECURITY_TYPE_OWE:
+ return createEnhancedOpenParams();
+ case WifiConfiguration.SECURITY_TYPE_WAPI_PSK:
+ return createWapiPskParams();
+ case WifiConfiguration.SECURITY_TYPE_WAPI_CERT:
+ return createWapiCertParams();
+ case WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE:
+ return createWpa3EnterpriseParams();
+ case WifiConfiguration.SECURITY_TYPE_OSEN:
+ return createOsenParams();
+ case WifiConfiguration.SECURITY_TYPE_PASSPOINT_R1_R2:
+ return SecurityParams.createPasspointParams(PASSPOINT_R2);
+ case WifiConfiguration.SECURITY_TYPE_PASSPOINT_R3:
+ return SecurityParams.createPasspointParams(PASSPOINT_R3);
+ default:
+ throw new IllegalArgumentException("unknown security type " + securityType);
+ }
+ }
+
+ /**
+ * Create EAP security params.
+ */
+ private static @NonNull SecurityParams createWpaWpa2EnterpriseParams() {
+ SecurityParams params = new SecurityParams();
+ params.mSecurityType = WifiConfiguration.SECURITY_TYPE_EAP;
+
+ params.mAllowedKeyManagement.set(KeyMgmt.WPA_EAP);
+ params.mAllowedKeyManagement.set(KeyMgmt.IEEE8021X);
+
+ params.mAllowedProtocols.set(Protocol.RSN);
+ params.mAllowedProtocols.set(Protocol.WPA);
+
+ params.mAllowedPairwiseCiphers.set(PairwiseCipher.CCMP);
+ params.mAllowedPairwiseCiphers.set(PairwiseCipher.TKIP);
+
+ params.mAllowedGroupCiphers.set(GroupCipher.CCMP);
+ params.mAllowedGroupCiphers.set(GroupCipher.TKIP);
+ return params;
+ }
+
+ /**
+ * Create Passpoint security params.
+ */
+ private static @NonNull SecurityParams createPasspointParams(@PasspointRelease int release) {
+ SecurityParams params = new SecurityParams();
+ switch (release) {
+ case PASSPOINT_R1:
+ case PASSPOINT_R2:
+ params.mSecurityType = WifiConfiguration.SECURITY_TYPE_PASSPOINT_R1_R2;
+ break;
+ case PASSPOINT_R3:
+ params.mSecurityType = WifiConfiguration.SECURITY_TYPE_PASSPOINT_R3;
+ params.mRequirePmf = true;
+ break;
+ default:
+ throw new IllegalArgumentException("invalid passpoint release " + release);
+ }
+
+ params.mAllowedKeyManagement.set(KeyMgmt.WPA_EAP);
+ params.mAllowedKeyManagement.set(KeyMgmt.IEEE8021X);
+
+ params.mAllowedProtocols.set(Protocol.RSN);
+
+ params.mAllowedPairwiseCiphers.set(PairwiseCipher.CCMP);
+
+ params.mAllowedGroupCiphers.set(GroupCipher.CCMP);
+
+ return params;
+ }
+
+ /**
+ * Create Enhanced Open params.
+ */
+ private static @NonNull SecurityParams createEnhancedOpenParams() {
+ SecurityParams params = new SecurityParams();
+ params.mSecurityType = WifiConfiguration.SECURITY_TYPE_OWE;
+
+ params.mAllowedKeyManagement.set(KeyMgmt.OWE);
+
+ params.mAllowedProtocols.set(Protocol.RSN);
+
+ params.mAllowedPairwiseCiphers.set(PairwiseCipher.CCMP);
+ params.mAllowedPairwiseCiphers.set(PairwiseCipher.GCMP_128);
+ params.mAllowedPairwiseCiphers.set(PairwiseCipher.GCMP_256);
+
+ params.mAllowedGroupCiphers.set(GroupCipher.CCMP);
+ params.mAllowedGroupCiphers.set(GroupCipher.GCMP_128);
+ params.mAllowedGroupCiphers.set(GroupCipher.GCMP_256);
+
+ params.mRequirePmf = true;
+ return params;
+ }
+
+ /**
+ * Create Open params.
+ */
+ private static @NonNull SecurityParams createOpenParams() {
+ SecurityParams params = new SecurityParams();
+ params.mSecurityType = WifiConfiguration.SECURITY_TYPE_OPEN;
+
+ params.mAllowedKeyManagement.set(KeyMgmt.NONE);
+
+ params.mAllowedProtocols.set(Protocol.RSN);
+ params.mAllowedProtocols.set(Protocol.WPA);
+ return params;
+ }
+
+ /**
+ * Create OSEN params.
+ */
+ private static @NonNull SecurityParams createOsenParams() {
+ SecurityParams params = new SecurityParams();
+ params.mSecurityType = WifiConfiguration.SECURITY_TYPE_OSEN;
+
+ params.mAllowedKeyManagement.set(KeyMgmt.OSEN);
+
+ params.mAllowedProtocols.set(Protocol.OSEN);
+
+ params.mAllowedPairwiseCiphers.set(PairwiseCipher.CCMP);
+ params.mAllowedPairwiseCiphers.set(PairwiseCipher.TKIP);
+
+ params.mAllowedGroupCiphers.set(GroupCipher.CCMP);
+ params.mAllowedGroupCiphers.set(GroupCipher.TKIP);
+ return params;
+ }
+
+ /**
+ * Create WAPI-CERT params.
+ */
+ private static @NonNull SecurityParams createWapiCertParams() {
+ SecurityParams params = new SecurityParams();
+ params.mSecurityType = WifiConfiguration.SECURITY_TYPE_WAPI_CERT;
+
+ params.mAllowedKeyManagement.set(KeyMgmt.WAPI_CERT);
+
+ params.mAllowedProtocols.set(Protocol.WAPI);
+
+ params.mAllowedPairwiseCiphers.set(PairwiseCipher.SMS4);
+
+ params.mAllowedGroupCiphers.set(GroupCipher.SMS4);
+ return params;
+ }
+
+ /**
+ * Create WAPI-PSK params.
+ */
+ private static @NonNull SecurityParams createWapiPskParams() {
+ SecurityParams params = new SecurityParams();
+ params.mSecurityType = WifiConfiguration.SECURITY_TYPE_WAPI_PSK;
+
+ params.mAllowedKeyManagement.set(KeyMgmt.WAPI_PSK);
+
+ params.mAllowedProtocols.set(Protocol.WAPI);
+
+ params.mAllowedPairwiseCiphers.set(PairwiseCipher.SMS4);
+
+ params.mAllowedGroupCiphers.set(GroupCipher.SMS4);
+ return params;
+ }
+
+ /**
+ * Create WEP params.
+ */
+ private static @NonNull SecurityParams createWepParams() {
+ SecurityParams params = new SecurityParams();
+ params.mSecurityType = WifiConfiguration.SECURITY_TYPE_WEP;
+
+ params.mAllowedKeyManagement.set(KeyMgmt.NONE);
+
+ params.mAllowedProtocols.set(Protocol.RSN);
+
+ params.mAllowedAuthAlgorithms.set(AuthAlgorithm.OPEN);
+ params.mAllowedAuthAlgorithms.set(AuthAlgorithm.SHARED);
+
+ params.mAllowedPairwiseCiphers.set(PairwiseCipher.CCMP);
+ params.mAllowedPairwiseCiphers.set(PairwiseCipher.TKIP);
+
+ params.mAllowedGroupCiphers.set(GroupCipher.CCMP);
+ params.mAllowedGroupCiphers.set(GroupCipher.TKIP);
+ params.mAllowedGroupCiphers.set(GroupCipher.WEP40);
+ params.mAllowedGroupCiphers.set(GroupCipher.WEP104);
+ return params;
+ }
+
+ /**
+ * Create WPA3 Enterprise 192-bit params.
+ */
+ private static @NonNull SecurityParams createWpa3Enterprise192BitParams() {
+ SecurityParams params = new SecurityParams();
+ params.mSecurityType = WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT;
+
+ params.mAllowedKeyManagement.set(KeyMgmt.WPA_EAP);
+ params.mAllowedKeyManagement.set(KeyMgmt.IEEE8021X);
+ params.mAllowedKeyManagement.set(KeyMgmt.SUITE_B_192);
+
+ params.mAllowedProtocols.set(Protocol.RSN);
+
+ params.mAllowedPairwiseCiphers.set(PairwiseCipher.GCMP_128);
+ params.mAllowedPairwiseCiphers.set(PairwiseCipher.GCMP_256);
+
+ params.mAllowedGroupCiphers.set(GroupCipher.GCMP_128);
+ params.mAllowedGroupCiphers.set(GroupCipher.GCMP_256);
+
+ params.mAllowedGroupManagementCiphers.set(GroupMgmtCipher.BIP_GMAC_256);
+
+ // Note: allowedSuiteBCiphers bitset will be set by the service once the
+ // certificates are attached to this profile
+
+ params.mRequirePmf = true;
+ return params;
+ }
+
+ /**
+ * Create WPA3 Enterprise params.
+ */
+ private static @NonNull SecurityParams createWpa3EnterpriseParams() {
+ SecurityParams params = new SecurityParams();
+ params.mSecurityType = WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE;
+
+ params.mAllowedKeyManagement.set(KeyMgmt.WPA_EAP);
+ params.mAllowedKeyManagement.set(KeyMgmt.IEEE8021X);
+
+ params.mAllowedProtocols.set(Protocol.RSN);
+
+ params.mAllowedPairwiseCiphers.set(PairwiseCipher.CCMP);
+ params.mAllowedPairwiseCiphers.set(PairwiseCipher.GCMP_256);
+
+ params.mAllowedGroupCiphers.set(GroupCipher.CCMP);
+ params.mAllowedGroupCiphers.set(GroupCipher.GCMP_256);
+
+ params.mRequirePmf = true;
+ return params;
+ }
+
+ /**
+ * Create WPA3 Personal params.
+ */
+ private static @NonNull SecurityParams createWpa3PersonalParams() {
+ SecurityParams params = new SecurityParams();
+ params.mSecurityType = WifiConfiguration.SECURITY_TYPE_SAE;
+
+ params.mAllowedKeyManagement.set(KeyMgmt.SAE);
+
+ params.mAllowedProtocols.set(Protocol.RSN);
+
+ params.mAllowedPairwiseCiphers.set(PairwiseCipher.CCMP);
+ params.mAllowedPairwiseCiphers.set(PairwiseCipher.GCMP_128);
+ params.mAllowedPairwiseCiphers.set(PairwiseCipher.GCMP_256);
+
+ params.mAllowedGroupCiphers.set(GroupCipher.CCMP);
+ params.mAllowedGroupCiphers.set(GroupCipher.GCMP_128);
+ params.mAllowedGroupCiphers.set(GroupCipher.GCMP_256);
+
+ params.mRequirePmf = true;
+ return params;
+ }
+
+ /**
+ * Create WPA/WPA2 Personal params.
+ */
+ private static @NonNull SecurityParams createWpaWpa2PersonalParams() {
+ SecurityParams params = new SecurityParams();
+ params.mSecurityType = WifiConfiguration.SECURITY_TYPE_PSK;
+
+ params.mAllowedKeyManagement.set(KeyMgmt.WPA_PSK);
+
+ params.mAllowedProtocols.set(Protocol.RSN);
+ params.mAllowedProtocols.set(Protocol.WPA);
+
+ params.mAllowedPairwiseCiphers.set(PairwiseCipher.CCMP);
+ params.mAllowedPairwiseCiphers.set(PairwiseCipher.TKIP);
+
+ params.mAllowedGroupCiphers.set(GroupCipher.CCMP);
+ params.mAllowedGroupCiphers.set(GroupCipher.TKIP);
+ params.mAllowedGroupCiphers.set(GroupCipher.WEP40);
+ params.mAllowedGroupCiphers.set(GroupCipher.WEP104);
+ return params;
+ }
+}
diff --git a/framework/java/android/net/wifi/SoftApCapability.java b/framework/java/android/net/wifi/SoftApCapability.java
index dcb57ec..6f72f0b 100644
--- a/framework/java/android/net/wifi/SoftApCapability.java
+++ b/framework/java/android/net/wifi/SoftApCapability.java
@@ -20,11 +20,15 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
+import android.net.wifi.SoftApConfiguration.BandType;
import android.os.Parcel;
import android.os.Parcelable;
+import com.android.modules.utils.build.SdkLevel;
+
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.Arrays;
import java.util.Objects;
/**
@@ -36,11 +40,13 @@
@SystemApi
public final class SoftApCapability implements Parcelable {
+ private static final String TAG = "SoftApCapability";
+ private static final int[] EMPTY_INT_ARRAY = new int[0];
/**
* Support for automatic channel selection in driver (ACS).
* Driver will auto select best channel based on interference to optimize performance.
*
- * flag when {@link R.bool.config_wifi_softap_acs_supported)} is true.
+ * flag when {@link R.bool.config_wifi_softap_acs_supported} is true.
*
* <p>
* Use {@link WifiManager.SoftApCallback#onInfoChanged(SoftApInfo)} and
@@ -51,7 +57,7 @@
/**
* Support for client force disconnect.
- * flag when {@link R.bool.config_wifi_sofap_client_force_disconnect_supported)} is true
+ * flag when {@link R.bool.config_wifiSofapClientForceDisconnectSupported} is true
*
* <p>
* Several Soft AP client control features, e.g. specifying the maximum number of
@@ -61,20 +67,32 @@
*/
public static final long SOFTAP_FEATURE_CLIENT_FORCE_DISCONNECT = 1 << 1;
-
/**
* Support for WPA3 Simultaneous Authentication of Equals (WPA3-SAE).
*
- * flag when {@link config_wifi_softap_sae_supported)} is true.
+ * flag when {@link config_wifi_softap_sae_supported} is true.
*/
public static final long SOFTAP_FEATURE_WPA3_SAE = 1 << 2;
+ /**
+ * Support for MAC address customization.
+ * flag when {@link R.bool.config_wifiSoftapMacAddressCustomizationSupported} is true
+ *
+ * <p>
+ * Check feature support before invoking
+ * {@link SoftApConfiguration.Builder#setBssid(MadAddress)} or
+ * {@link SoftApConfiguration.Builder#setMacRandomizationSetting(int)} with
+ * {@link SoftApConfiguration.RANDOMIZATION_PERSISTENT}
+ */
+ public static final long SOFTAP_FEATURE_MAC_ADDRESS_CUSTOMIZATION = 1 << 3;
+
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@LongDef(flag = true, prefix = { "SOFTAP_FEATURE_" }, value = {
SOFTAP_FEATURE_ACS_OFFLOAD,
SOFTAP_FEATURE_CLIENT_FORCE_DISCONNECT,
SOFTAP_FEATURE_WPA3_SAE,
+ SOFTAP_FEATURE_MAC_ADDRESS_CUSTOMIZATION,
})
public @interface HotspotFeatures {}
@@ -83,6 +101,26 @@
private int mMaximumSupportedClientNumber;
/**
+ * A list storing supported 2.4G channels.
+ */
+ private int[] mSupportedChannelListIn24g = EMPTY_INT_ARRAY;
+
+ /**
+ * A list storing supported 5G channels.
+ */
+ private int[] mSupportedChannelListIn5g = EMPTY_INT_ARRAY;
+
+ /**
+ * A list storing supported 6G channels.
+ */
+ private int[] mSupportedChannelListIn6g = EMPTY_INT_ARRAY;
+
+ /**
+ * A list storing supported 60G channels.
+ */
+ private int[] mSupportedChannelListIn60g = EMPTY_INT_ARRAY;
+
+ /**
* Get the maximum supported client numbers which AP resides on.
*/
public int getMaxSupportedClients() {
@@ -111,12 +149,82 @@
}
/**
+ * Set supported channel list in target band type.
+ *
+ * @param band One of the following band types:
+ * {@link SoftApConfiguation#BAND_2GHZ}, {@link SoftApConfiguation#BAND_5GHZ},
+ * {@link SoftApConfiguation#BAND_6GHZ}, or {@link SoftApConfiguation#BAND_60GHZ}.
+ * @param supportedChannelList supported channel list in target band
+ * @return true if band and supportedChannelList are valid, otherwise false.
+ *
+ * @throws IllegalArgumentException when band type is invalid.
+ * @hide
+ */
+ public boolean setSupportedChannelList(@BandType int band,
+ @Nullable int[] supportedChannelList) {
+ if (supportedChannelList == null) return false;
+ switch (band) {
+ case SoftApConfiguration.BAND_2GHZ:
+ mSupportedChannelListIn24g = supportedChannelList;
+ break;
+ case SoftApConfiguration.BAND_5GHZ:
+ mSupportedChannelListIn5g = supportedChannelList;
+ break;
+ case SoftApConfiguration.BAND_6GHZ:
+ mSupportedChannelListIn6g = supportedChannelList;
+ break;
+ case SoftApConfiguration.BAND_60GHZ:
+ mSupportedChannelListIn60g = supportedChannelList;
+ break;
+ default:
+ throw new IllegalArgumentException("Invalid band: " + band);
+ }
+ return true;
+ }
+
+ /**
+ * Returns a list of the supported channels in the given band.
+ * The result depends on the on the country code that has been set.
+ * Can be used to set the channel of the AP with the
+ * {@link SoftapConfiguration.Builder#setChannel(int, int)} API.
+ *
+ * @param band One of the following band types:
+ * {@link SoftApConfiguation#BAND_2GHZ}, {@link SoftApConfiguation#BAND_5GHZ},
+ * {@link SoftApConfiguation#BAND_6GHZ}, {@link SoftApConfiguation#BAND_60GHZ}.
+ * @return List of supported channels for the band.
+ *
+ * @throws IllegalArgumentException when band type is invalid.
+ */
+ @NonNull
+ public int[] getSupportedChannelList(@BandType int band) {
+ if (!SdkLevel.isAtLeastS()) {
+ throw new UnsupportedOperationException();
+ }
+ switch (band) {
+ case SoftApConfiguration.BAND_2GHZ:
+ return mSupportedChannelListIn24g;
+ case SoftApConfiguration.BAND_5GHZ:
+ return mSupportedChannelListIn5g;
+ case SoftApConfiguration.BAND_6GHZ:
+ return mSupportedChannelListIn6g;
+ case SoftApConfiguration.BAND_60GHZ:
+ return mSupportedChannelListIn60g;
+ default:
+ throw new IllegalArgumentException("Invalid band: " + band);
+ }
+ }
+
+ /**
* @hide
*/
public SoftApCapability(@Nullable SoftApCapability source) {
if (source != null) {
mSupportedFeatures = source.mSupportedFeatures;
mMaximumSupportedClientNumber = source.mMaximumSupportedClientNumber;
+ mSupportedChannelListIn24g = source.mSupportedChannelListIn24g;
+ mSupportedChannelListIn5g = source.mSupportedChannelListIn5g;
+ mSupportedChannelListIn6g = source.mSupportedChannelListIn6g;
+ mSupportedChannelListIn60g = source.mSupportedChannelListIn60g;
}
}
@@ -144,15 +252,22 @@
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeLong(mSupportedFeatures);
dest.writeInt(mMaximumSupportedClientNumber);
+ dest.writeIntArray(mSupportedChannelListIn24g);
+ dest.writeIntArray(mSupportedChannelListIn5g);
+ dest.writeIntArray(mSupportedChannelListIn6g);
+ dest.writeIntArray(mSupportedChannelListIn60g);
}
@NonNull
/** Implement the Parcelable interface */
public static final Creator<SoftApCapability> CREATOR = new Creator<SoftApCapability>() {
public SoftApCapability createFromParcel(Parcel in) {
- long supportedFeatures = in.readLong();
- SoftApCapability capability = new SoftApCapability(supportedFeatures);
+ SoftApCapability capability = new SoftApCapability(in.readLong());
capability.mMaximumSupportedClientNumber = in.readInt();
+ capability.setSupportedChannelList(SoftApConfiguration.BAND_2GHZ, in.createIntArray());
+ capability.setSupportedChannelList(SoftApConfiguration.BAND_5GHZ, in.createIntArray());
+ capability.setSupportedChannelList(SoftApConfiguration.BAND_6GHZ, in.createIntArray());
+ capability.setSupportedChannelList(SoftApConfiguration.BAND_60GHZ, in.createIntArray());
return capability;
}
@@ -167,6 +282,12 @@
StringBuilder sbuf = new StringBuilder();
sbuf.append("SupportedFeatures=").append(mSupportedFeatures);
sbuf.append("MaximumSupportedClientNumber=").append(mMaximumSupportedClientNumber);
+ sbuf.append("SupportedChannelListIn24g")
+ .append(Arrays.toString(mSupportedChannelListIn24g));
+ sbuf.append("SupportedChannelListIn5g").append(Arrays.toString(mSupportedChannelListIn5g));
+ sbuf.append("SupportedChannelListIn6g").append(Arrays.toString(mSupportedChannelListIn6g));
+ sbuf.append("SupportedChannelListIn60g")
+ .append(Arrays.toString(mSupportedChannelListIn60g));
return sbuf.toString();
}
@@ -176,11 +297,19 @@
if (!(o instanceof SoftApCapability)) return false;
SoftApCapability capability = (SoftApCapability) o;
return mSupportedFeatures == capability.mSupportedFeatures
- && mMaximumSupportedClientNumber == capability.mMaximumSupportedClientNumber;
+ && mMaximumSupportedClientNumber == capability.mMaximumSupportedClientNumber
+ && Arrays.equals(mSupportedChannelListIn24g, capability.mSupportedChannelListIn24g)
+ && Arrays.equals(mSupportedChannelListIn5g, capability.mSupportedChannelListIn5g)
+ && Arrays.equals(mSupportedChannelListIn6g, capability.mSupportedChannelListIn6g)
+ && Arrays.equals(mSupportedChannelListIn60g, capability.mSupportedChannelListIn60g);
}
@Override
public int hashCode() {
- return Objects.hash(mSupportedFeatures, mMaximumSupportedClientNumber);
+ return Objects.hash(mSupportedFeatures, mMaximumSupportedClientNumber,
+ Arrays.hashCode(mSupportedChannelListIn24g),
+ Arrays.hashCode(mSupportedChannelListIn5g),
+ Arrays.hashCode(mSupportedChannelListIn6g),
+ Arrays.hashCode(mSupportedChannelListIn60g));
}
}
diff --git a/framework/java/android/net/wifi/SoftApConfiguration.java b/framework/java/android/net/wifi/SoftApConfiguration.java
index d2ff658..d36acb7 100644
--- a/framework/java/android/net/wifi/SoftApConfiguration.java
+++ b/framework/java/android/net/wifi/SoftApConfiguration.java
@@ -26,13 +26,14 @@
import android.os.Parcelable;
import android.text.TextUtils;
import android.util.Log;
+import android.util.SparseIntArray;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.Preconditions;
+import com.android.modules.utils.build.SdkLevel;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
-import java.nio.charset.CharsetEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
@@ -87,9 +88,19 @@
public static final int BAND_6GHZ = 1 << 2;
/**
+ * 60GHz band.
+ * @hide
+ */
+ @SystemApi
+ public static final int BAND_60GHZ = 1 << 3;
+
+ /**
* Device is allowed to choose the optimal band (2Ghz, 5Ghz, 6Ghz) based on device capability,
* operating country code and current radio conditions.
* @hide
+ *
+ * @deprecated The bands are a bit mask - use any combination of {@code BAND_},
+ * for instance {@code BAND_2GHZ | BAND_5GHZ | BAND_6GHZ}.
*/
@SystemApi
public static final int BAND_ANY = BAND_2GHZ | BAND_5GHZ | BAND_6GHZ;
@@ -100,11 +111,13 @@
BAND_2GHZ,
BAND_5GHZ,
BAND_6GHZ,
+ BAND_60GHZ,
})
public @interface BandType {}
private static boolean isBandValid(@BandType int band) {
- return ((band != 0) && ((band & ~BAND_ANY) == 0));
+ int bandAny = BAND_2GHZ | BAND_5GHZ | BAND_6GHZ | BAND_60GHZ;
+ return ((band != 0) && ((band & ~bandAny) == 0));
}
private static final int MIN_CH_2G_BAND = 1;
@@ -113,6 +126,8 @@
private static final int MAX_CH_5G_BAND = 196;
private static final int MIN_CH_6G_BAND = 1;
private static final int MAX_CH_6G_BAND = 253;
+ private static final int MIN_CH_60G_BAND = 1;
+ private static final int MAX_CH_60G_BAND = 6;
@@ -135,6 +150,13 @@
return false;
}
break;
+
+ case BAND_60GHZ:
+ if (channel < MIN_CH_60G_BAND || channel > MAX_CH_60G_BAND) {
+ return false;
+ }
+ break;
+
default:
return false;
}
@@ -164,16 +186,12 @@
private final boolean mHiddenSsid;
/**
- * The operating band of the AP.
- * One or combination of the following band type:
- * {@link #BAND_2GHZ}, {@link #BAND_5GHZ}, {@link #BAND_6GHZ}.
+ * The operating channels of the dual APs.
+ *
+ * The SparseIntArray that consists the band and the channel of matching the band.
*/
- private final @BandType int mBand;
-
- /**
- * The operating channel of the AP.
- */
- private final int mChannel;
+ @NonNull
+ private final SparseIntArray mChannels;
/**
* The maximim allowed number of clients that can associate to the AP.
@@ -217,6 +235,34 @@
*/
private final long mShutdownTimeoutMillis;
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = {"RANDOMIZATION_"}, value = {
+ RANDOMIZATION_NONE,
+ RANDOMIZATION_PERSISTENT})
+ public @interface MacRandomizationSetting {}
+
+ /**
+ * Use factory MAC as BSSID for the AP
+ * @hide
+ */
+ @SystemApi
+ public static final int RANDOMIZATION_NONE = 0;
+ /**
+ * Generate a randomized MAC as BSSID for the AP
+ * @hide
+ */
+ @SystemApi
+ public static final int RANDOMIZATION_PERSISTENT = 1;
+
+ /**
+ * Level of MAC randomization for the AP BSSID.
+ * @hide
+ */
+ @MacRandomizationSetting
+ private int mMacRandomizationSetting;
+
+
/**
* THe definition of security type OPEN.
*/
@@ -249,16 +295,21 @@
/** Private constructor for Builder and Parcelable implementation. */
private SoftApConfiguration(@Nullable String ssid, @Nullable MacAddress bssid,
- @Nullable String passphrase, boolean hiddenSsid, @BandType int band, int channel,
+ @Nullable String passphrase, boolean hiddenSsid, @NonNull SparseIntArray channels,
@SecurityType int securityType, int maxNumberOfClients, boolean shutdownTimeoutEnabled,
long shutdownTimeoutMillis, boolean clientControlByUser,
- @NonNull List<MacAddress> blockedList, @NonNull List<MacAddress> allowedList) {
+ @NonNull List<MacAddress> blockedList, @NonNull List<MacAddress> allowedList,
+ int macRandomizationSetting) {
mSsid = ssid;
mBssid = bssid;
mPassphrase = passphrase;
mHiddenSsid = hiddenSsid;
- mBand = band;
- mChannel = channel;
+ if (channels.size() != 0) {
+ mChannels = channels.clone();
+ } else {
+ mChannels = new SparseIntArray(1);
+ mChannels.put(BAND_2GHZ, 0);
+ }
mSecurityType = securityType;
mMaxNumberOfClients = maxNumberOfClients;
mAutoShutdownEnabled = shutdownTimeoutEnabled;
@@ -266,6 +317,7 @@
mClientControlByUser = clientControlByUser;
mBlockedClientList = new ArrayList<>(blockedList);
mAllowedClientList = new ArrayList<>(allowedList);
+ mMacRandomizationSetting = macRandomizationSetting;
}
@Override
@@ -281,42 +333,42 @@
&& Objects.equals(mBssid, other.mBssid)
&& Objects.equals(mPassphrase, other.mPassphrase)
&& mHiddenSsid == other.mHiddenSsid
- && mBand == other.mBand
- && mChannel == other.mChannel
+ && mChannels.toString().equals(other.mChannels.toString())
&& mSecurityType == other.mSecurityType
&& mMaxNumberOfClients == other.mMaxNumberOfClients
&& mAutoShutdownEnabled == other.mAutoShutdownEnabled
&& mShutdownTimeoutMillis == other.mShutdownTimeoutMillis
&& mClientControlByUser == other.mClientControlByUser
&& Objects.equals(mBlockedClientList, other.mBlockedClientList)
- && Objects.equals(mAllowedClientList, other.mAllowedClientList);
+ && Objects.equals(mAllowedClientList, other.mAllowedClientList)
+ && mMacRandomizationSetting == other.mMacRandomizationSetting;
}
@Override
public int hashCode() {
return Objects.hash(mSsid, mBssid, mPassphrase, mHiddenSsid,
- mBand, mChannel, mSecurityType, mMaxNumberOfClients, mAutoShutdownEnabled,
+ mChannels.toString(), mSecurityType, mMaxNumberOfClients, mAutoShutdownEnabled,
mShutdownTimeoutMillis, mClientControlByUser, mBlockedClientList,
- mAllowedClientList);
+ mAllowedClientList, mMacRandomizationSetting);
}
@Override
public String toString() {
StringBuilder sbuf = new StringBuilder();
- sbuf.append("ssid=").append(mSsid);
- if (mBssid != null) sbuf.append(" \n bssid=").append(mBssid.toString());
- sbuf.append(" \n Passphrase =").append(
+ sbuf.append("ssid = ").append(mSsid);
+ if (mBssid != null) sbuf.append(" \n bssid = ").append(mBssid.toString());
+ sbuf.append(" \n Passphrase = ").append(
TextUtils.isEmpty(mPassphrase) ? "<empty>" : "<non-empty>");
- sbuf.append(" \n HiddenSsid =").append(mHiddenSsid);
- sbuf.append(" \n Band =").append(mBand);
- sbuf.append(" \n Channel =").append(mChannel);
- sbuf.append(" \n SecurityType=").append(getSecurityType());
- sbuf.append(" \n MaxClient=").append(mMaxNumberOfClients);
- sbuf.append(" \n AutoShutdownEnabled=").append(mAutoShutdownEnabled);
- sbuf.append(" \n ShutdownTimeoutMillis=").append(mShutdownTimeoutMillis);
- sbuf.append(" \n ClientControlByUser=").append(mClientControlByUser);
- sbuf.append(" \n BlockedClientList=").append(mBlockedClientList);
- sbuf.append(" \n AllowedClientList=").append(mAllowedClientList);
+ sbuf.append(" \n HiddenSsid = ").append(mHiddenSsid);
+ sbuf.append(" \n Channels = ").append(mChannels);
+ sbuf.append(" \n SecurityType = ").append(getSecurityType());
+ sbuf.append(" \n MaxClient = ").append(mMaxNumberOfClients);
+ sbuf.append(" \n AutoShutdownEnabled = ").append(mAutoShutdownEnabled);
+ sbuf.append(" \n ShutdownTimeoutMillis = ").append(mShutdownTimeoutMillis);
+ sbuf.append(" \n ClientControlByUser = ").append(mClientControlByUser);
+ sbuf.append(" \n BlockedClientList = ").append(mBlockedClientList);
+ sbuf.append(" \n AllowedClientList= ").append(mAllowedClientList);
+ sbuf.append(" \n MacRandomizationSetting = ").append(mMacRandomizationSetting);
return sbuf.toString();
}
@@ -326,8 +378,7 @@
dest.writeParcelable(mBssid, flags);
dest.writeString(mPassphrase);
dest.writeBoolean(mHiddenSsid);
- dest.writeInt(mBand);
- dest.writeInt(mChannel);
+ writeSparseIntArray(dest, mChannels);
dest.writeInt(mSecurityType);
dest.writeInt(mMaxNumberOfClients);
dest.writeBoolean(mAutoShutdownEnabled);
@@ -335,8 +386,45 @@
dest.writeBoolean(mClientControlByUser);
dest.writeTypedList(mBlockedClientList);
dest.writeTypedList(mAllowedClientList);
+ dest.writeInt(mMacRandomizationSetting);
}
+ /* Reference from frameworks/base/core/java/android/os/Parcel.java */
+ private static void writeSparseIntArray(@NonNull Parcel dest,
+ @Nullable SparseIntArray val) {
+ if (val == null) {
+ dest.writeInt(-1);
+ return;
+ }
+ int n = val.size();
+ dest.writeInt(n);
+ int i = 0;
+ while (i < n) {
+ dest.writeInt(val.keyAt(i));
+ dest.writeInt(val.valueAt(i));
+ i++;
+ }
+ }
+
+
+ /* Reference from frameworks/base/core/java/android/os/Parcel.java */
+ @NonNull
+ private static SparseIntArray readSparseIntArray(@NonNull Parcel in) {
+ int n = in.readInt();
+ if (n < 0) {
+ return new SparseIntArray();
+ }
+ SparseIntArray sa = new SparseIntArray(n);
+ while (n > 0) {
+ int key = in.readInt();
+ int value = in.readInt();
+ sa.append(key, value);
+ n--;
+ }
+ return sa;
+ }
+
+
@Override
public int describeContents() {
return 0;
@@ -349,10 +437,10 @@
return new SoftApConfiguration(
in.readString(),
in.readParcelable(MacAddress.class.getClassLoader()),
- in.readString(), in.readBoolean(), in.readInt(), in.readInt(), in.readInt(),
+ in.readString(), in.readBoolean(), readSparseIntArray(in), in.readInt(),
in.readInt(), in.readBoolean(), in.readLong(), in.readBoolean(),
in.createTypedArrayList(MacAddress.CREATOR),
- in.createTypedArrayList(MacAddress.CREATOR));
+ in.createTypedArrayList(MacAddress.CREATOR), in.readInt());
}
@Override
@@ -363,7 +451,7 @@
/**
* Return String set to be the SSID for the AP.
- * {@link Builder#setSsid(String)}.
+ * See also {@link Builder#setSsid(String)}.
*/
@Nullable
public String getSsid() {
@@ -372,7 +460,7 @@
/**
* Returns MAC address set to be BSSID for the AP.
- * {@link Builder#setBssid(MacAddress)}.
+ * See also {@link Builder#setBssid(MacAddress)}.
*/
@Nullable
public MacAddress getBssid() {
@@ -381,7 +469,7 @@
/**
* Returns String set to be passphrase for current AP.
- * {@link Builder#setPassphrase(String, int)}.
+ * See also {@link Builder#setPassphrase(String, int)}.
*/
@Nullable
public String getPassphrase() {
@@ -391,7 +479,7 @@
/**
* Returns Boolean set to be indicate hidden (true: doesn't broadcast its SSID) or
* not (false: broadcasts its SSID) for the AP.
- * {@link Builder#setHiddenSsid(boolean)}.
+ * See also {@link Builder#setHiddenSsid(boolean)}.
*/
public boolean isHiddenSsid() {
return mHiddenSsid;
@@ -400,27 +488,75 @@
/**
* Returns band type set to be the band for the AP.
*
- * One or combination of the following band type:
- * {@link #BAND_2GHZ}, {@link #BAND_5GHZ}, {@link #BAND_6GHZ}.
+ * One or combination of {@code BAND_}, for instance
+ * {@link #BAND_2GHZ}, {@link #BAND_5GHZ}, or {@code BAND_2GHZ | BAND_5GHZ}.
*
- * {@link Builder#setBand(int)}.
+ * Note: Returns the lowest band when more than one band is set.
+ * Use {@link #getBands()} to get dual bands setting.
+ *
+ * See also {@link Builder#setBand(int)}.
*
* @hide
*/
@SystemApi
public @BandType int getBand() {
- return mBand;
+ return mChannels.keyAt(0);
+ }
+
+ /**
+ * Returns a sorted array in ascending order that consists of the configured band types
+ * for the APs.
+ *
+ * The band type is one or combination of {@code BAND_}, for instance
+ * {@link #BAND_2GHZ}, {@link #BAND_5GHZ}, or {@code BAND_2GHZ | BAND_5GHZ}.
+ *
+ * Note: return array may only include one band when current setting is single AP mode.
+ * See also {@link Builder#setBands(int[])}.
+ *
+ * @hide
+ */
+ @SystemApi
+ public @NonNull int[] getBands() {
+ if (!SdkLevel.isAtLeastS()) {
+ throw new UnsupportedOperationException();
+ }
+ int[] bands = new int[mChannels.size()];
+ for (int i = 0; i < bands.length; i++) {
+ bands[i] = mChannels.keyAt(i);
+ }
+ return bands;
}
/**
* Returns Integer set to be the channel for the AP.
- * {@link Builder#setChannel(int)}.
+ *
+ * Note: Returns the channel which associated to the lowest band if more than one channel
+ * is set. Use {@link Builder#getChannels()} to get dual channel setting.
+ * See also {@link Builder#setChannel(int, int)}.
*
* @hide
*/
@SystemApi
public int getChannel() {
- return mChannel;
+ return mChannels.valueAt(0);
+ }
+
+
+ /**
+ * Returns SparseIntArray (key: {@code BandType} , value: channel) that consists of
+ * the configured bands and channels for the AP(s).
+ *
+ * Note: return array may only include one channel when current setting is single AP mode.
+ * See also {@link Builder#setChannels(SparseIntArray)}.
+ *
+ * @hide
+ */
+ @SystemApi
+ public @NonNull SparseIntArray getChannels() {
+ if (!SdkLevel.isAtLeastS()) {
+ throw new UnsupportedOperationException();
+ }
+ return mChannels.clone();
}
/**
@@ -438,7 +574,7 @@
/**
* Returns the maximum number of clients that can associate to the AP.
- * {@link Builder#setMaxNumberOfClients(int)}.
+ * See also {@link Builder#setMaxNumberOfClients(int)}.
*
* @hide
*/
@@ -450,7 +586,7 @@
/**
* Returns whether auto shutdown is enabled or not.
* The Soft AP will shutdown when there are no devices associated to it for
- * the timeout duration. See {@link Builder#setAutoShutdownEnabled(boolean)}.
+ * the timeout duration. See also {@link Builder#setAutoShutdownEnabled(boolean)}.
*
* @hide
*/
@@ -462,7 +598,7 @@
/**
* Returns the shutdown timeout in milliseconds.
* The Soft AP will shutdown when there are no devices associated to it for
- * the timeout duration. See {@link Builder#setShutdownTimeoutMillis(long)}.
+ * the timeout duration. See also {@link Builder#setShutdownTimeoutMillis(long)}.
*
* @hide
*/
@@ -474,7 +610,7 @@
/**
* Returns a flag indicating whether clients need to be pre-approved by the user.
* (true: authorization required) or not (false: not required).
- * {@link Builder#setClientControlByUserEnabled(Boolean)}.
+ * See also {@link Builder#setClientControlByUserEnabled(Boolean)}.
*
* @hide
*/
@@ -509,6 +645,21 @@
}
/**
+ * Returns the level of MAC randomization for the AP BSSID.
+ * See also {@link Builder#setMacRandomizationSetting(int)}.
+ *
+ * @hide
+ */
+ @SystemApi
+ @MacRandomizationSetting
+ public int getMacRandomizationSetting() {
+ if (!SdkLevel.isAtLeastS()) {
+ throw new UnsupportedOperationException();
+ }
+ return mMacRandomizationSetting;
+ }
+
+ /**
* Returns a {@link WifiConfiguration} representation of this {@link SoftApConfiguration}.
* Note that SoftApConfiguration may contain configuration which is cannot be represented
* by the legacy WifiConfiguration, in such cases a null will be returned.
@@ -527,7 +678,7 @@
wifiConfig.SSID = mSsid;
wifiConfig.preSharedKey = mPassphrase;
wifiConfig.hiddenSSID = mHiddenSsid;
- wifiConfig.apChannel = mChannel;
+ wifiConfig.apChannel = getChannel();
switch (mSecurityType) {
case SECURITY_TYPE_OPEN:
wifiConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
@@ -541,7 +692,7 @@
return null;
}
- switch (mBand) {
+ switch (getBand()) {
case BAND_2GHZ:
wifiConfig.apBand = WifiConfiguration.AP_BAND_2GHZ;
break;
@@ -555,7 +706,7 @@
wifiConfig.apBand = WifiConfiguration.AP_BAND_ANY;
break;
default:
- Log.e(TAG, "Convert fail, unsupported band setting :" + mBand);
+ Log.e(TAG, "Convert fail, unsupported band setting :" + getBand());
return null;
}
return wifiConfig;
@@ -576,8 +727,7 @@
private MacAddress mBssid;
private String mPassphrase;
private boolean mHiddenSsid;
- private int mBand;
- private int mChannel;
+ private SparseIntArray mChannels;
private int mMaxNumberOfClients;
private int mSecurityType;
private boolean mAutoShutdownEnabled;
@@ -585,6 +735,7 @@
private boolean mClientControlByUser;
private List<MacAddress> mBlockedClientList;
private List<MacAddress> mAllowedClientList;
+ private int mMacRandomizationSetting;
/**
* Constructs a Builder with default values (see {@link Builder}).
@@ -594,8 +745,8 @@
mBssid = null;
mPassphrase = null;
mHiddenSsid = false;
- mBand = BAND_2GHZ;
- mChannel = 0;
+ mChannels = new SparseIntArray(1);
+ mChannels.put(BAND_2GHZ, 0);
mMaxNumberOfClients = 0;
mSecurityType = SECURITY_TYPE_OPEN;
mAutoShutdownEnabled = true; // enabled by default.
@@ -603,6 +754,7 @@
mClientControlByUser = false;
mBlockedClientList = new ArrayList<>();
mAllowedClientList = new ArrayList<>();
+ mMacRandomizationSetting = RANDOMIZATION_PERSISTENT;
}
/**
@@ -615,8 +767,7 @@
mBssid = other.mBssid;
mPassphrase = other.mPassphrase;
mHiddenSsid = other.mHiddenSsid;
- mBand = other.mBand;
- mChannel = other.mChannel;
+ mChannels = other.mChannels.clone();
mMaxNumberOfClients = other.mMaxNumberOfClients;
mSecurityType = other.mSecurityType;
mAutoShutdownEnabled = other.mAutoShutdownEnabled;
@@ -624,6 +775,7 @@
mClientControlByUser = other.mClientControlByUser;
mBlockedClientList = new ArrayList<>(other.mBlockedClientList);
mAllowedClientList = new ArrayList<>(other.mAllowedClientList);
+ mMacRandomizationSetting = other.mMacRandomizationSetting;
}
/**
@@ -639,9 +791,9 @@
}
}
return new SoftApConfiguration(mSsid, mBssid, mPassphrase,
- mHiddenSsid, mBand, mChannel, mSecurityType, mMaxNumberOfClients,
+ mHiddenSsid, mChannels, mSecurityType, mMaxNumberOfClients,
mAutoShutdownEnabled, mShutdownTimeoutMillis, mClientControlByUser,
- mBlockedClientList, mAllowedClientList);
+ mBlockedClientList, mAllowedClientList, mMacRandomizationSetting);
}
/**
@@ -670,17 +822,41 @@
* Specifies a BSSID for the AP.
* <p>
* <li>If not set, defaults to null.</li>
+ *
+ * If multiple bands are requested via {@link #setBands(int[])} or
+ * {@link #setChannels(SparseIntArray)}, HAL will derive 2 MAC addresses since framework
+ * only sends down 1 MAC address.
+ *
+ * An example (but different implementation may perform a different mapping):
+ * <li>MAC address 1: copy value of MAC address,
+ * and set byte 1 = (0xFF - BSSID[1])</li>
+ * <li>MAC address 2: copy value of MAC address,
+ * and set byte 2 = (0xFF - BSSID[2])</li>
+ *
+ * Example BSSID argument: e2:38:60:c4:0e:b7
+ * Derived MAC address 1: e2:c7:60:c4:0e:b7
+ * Derived MAC address 2: e2:38:9f:c4:0e:b7
+ *
+ * <p>
+ * Use {@link WifiManager.SoftApCallback#onCapabilityChanged(SoftApCapability)} and
+ * {@link SoftApCapability#areFeaturesSupported(long)}
+ * with {@link SoftApCapability.SOFTAP_FEATURE_MAC_ADDRESS_CUSTOMIZATION} to determine
+ * whether or not this feature is supported.
+ *
* @param bssid BSSID, or null to have the BSSID chosen by the framework. The caller is
* responsible for avoiding collisions.
* @return Builder for chaining.
- * @throws IllegalArgumentException when the given BSSID is the all-zero or broadcast MAC
- * address.
+ * @throws IllegalArgumentException when the given BSSID is the all-zero
+ * , multicast or broadcast MAC address.
*/
@NonNull
public Builder setBssid(@Nullable MacAddress bssid) {
if (bssid != null) {
Preconditions.checkArgument(!bssid.equals(WifiManager.ALL_ZEROS_MAC_ADDRESS));
- Preconditions.checkArgument(!bssid.equals(MacAddress.BROADCAST_ADDRESS));
+ if (bssid.getAddressType() != MacAddress.TYPE_UNICAST) {
+ throw new IllegalArgumentException("bssid doesn't support "
+ + "multicast or broadcast mac address");
+ }
}
mBssid = bssid;
return this;
@@ -712,10 +888,6 @@
}
} else {
Preconditions.checkStringNotEmpty(passphrase);
- final CharsetEncoder asciiEncoder = StandardCharsets.US_ASCII.newEncoder();
- if (!asciiEncoder.canEncode(passphrase)) {
- throw new IllegalArgumentException("passphrase not ASCII encodable");
- }
if (securityType == SECURITY_TYPE_WPA2_PSK
|| securityType == SECURITY_TYPE_WPA3_SAE_TRANSITION) {
if (passphrase.length() < PSK_MIN_LEN || passphrase.length() > PSK_MAX_LEN) {
@@ -754,53 +926,155 @@
* @param band One or combination of the following band type:
* {@link #BAND_2GHZ}, {@link #BAND_5GHZ}, {@link #BAND_6GHZ}.
* @return Builder for chaining.
+ * @throws IllegalArgumentException when an invalid band type is provided.
*/
@NonNull
public Builder setBand(@BandType int band) {
if (!isBandValid(band)) {
- throw new IllegalArgumentException("Invalid band type");
+ throw new IllegalArgumentException("Invalid band type: " + band);
}
- mBand = band;
- // Since band preference is specified, no specific channel is selected.
- mChannel = 0;
+ mChannels = new SparseIntArray(1);
+ mChannels.put(band, 0);
return this;
}
/**
+ * Specifies the bands for the APs.
+ * If more than 1 band is set, this will bring up concurrent APs.
+ * on the requested bands (if possible).
+ * <p>
+ *
+ * Use {@link WifiManager#isBridgedApConcurrencySupported()} to determine
+ * whether or not concurrent APs are supported.
+ *
+ * @param bands Array of the {@link #BandType}.
+ * @return Builder for chaining.
+ * @throws IllegalArgumentException when more than 2 bands are set or an invalid band type
+ * is provided.
+ */
+ @NonNull
+ public Builder setBands(@NonNull int[] bands) {
+ if (!SdkLevel.isAtLeastS()) {
+ throw new UnsupportedOperationException();
+ }
+ if (bands.length == 0 || bands.length > 2) {
+ throw new IllegalArgumentException("Unsupported number of bands("
+ + bands.length + ") configured");
+ }
+ SparseIntArray channels = new SparseIntArray(bands.length);
+ for (int val : bands) {
+ if (!isBandValid(val)) {
+ throw new IllegalArgumentException("Invalid band type: " + val);
+ }
+ channels.put(val, 0);
+ }
+ mChannels = channels;
+ return this;
+ }
+
+
+ /**
* Specifies the channel and associated band for the AP.
*
* The channel which AP resides on. Valid channels are country dependent.
+ * The {@link SoftApCapability#getSupportedChannelList(int)} can be used to obtain
+ * valid channels.
+ *
* <p>
- * The default for the channel is a the special value 0 to have the framework
- * auto-select a valid channel from the band configured with
+ * If not set, the default for the channel is the special value 0 which has the
+ * framework auto-select a valid channel from the band configured with
* {@link #setBand(int)}.
*
- * The channel auto selection will offload to driver when
- * {@link SoftApCapability#areFeaturesSupported(
- * SoftApCapability.SOFTAP_FEATURE_ACS_OFFLOAD)}
- * return true. Driver will auto select best channel which based on environment
- * interference to get best performance. Check {@link SoftApCapability} to get more detail.
+ * The channel auto selection will be offloaded to driver when
+ * {@link SoftApCapability#areFeaturesSupported(long)}
+ * with {@link SoftApCapability.SOFTAP_FEATURE_ACS_OFFLOAD}
+ * return true. The driver will auto select the best channel (e.g. best performance)
+ * based on environment interference. Check {@link SoftApCapability} for more detail.
*
- * Note, since 6GHz band use the same channel numbering of 2.4GHz and 5GHZ bands,
- * the caller needs to pass the band containing the selected channel.
+ * The API contains (band, channel) input since the 6GHz band uses the same channel
+ * numbering scheme as is used in the 2.4GHz and 5GHz band. Therefore, both are needed to
+ * uniquely identify individual channels.
*
* <p>
- * <li>If not set, defaults to 0.</li>
* @param channel operating channel of the AP.
* @param band containing this channel.
* @return Builder for chaining.
+ * @throws IllegalArgumentException when the invalid channel or band type is configured.
*/
@NonNull
public Builder setChannel(int channel, @BandType int band) {
if (!isChannelBandPairValid(channel, band)) {
- throw new IllegalArgumentException("Invalid band type");
+ throw new IllegalArgumentException("Invalid channel(" + channel
+ + ") & band (" + band + ") configured");
}
- mBand = band;
- mChannel = channel;
+ mChannels = new SparseIntArray(1);
+ mChannels.put(band, channel);
return this;
}
/**
+ * Specifies the channels and associated bands for the APs.
+ *
+ * When more than 1 channel is set, this will bring up concurrent APs on the requested
+ * channels and bands (if possible).
+ *
+ * Valid channels are country dependent.
+ * The {@link SoftApCapability#getSupportedChannelList(int)} can be used to obtain
+ * valid channels in each band.
+ *
+ * Use {@link WifiManager#isBridgedApConcurrencySupported()} to determine
+ * whether or not concurrent APs are supported.
+ *
+ * <p>
+ * If not set, the default for the channel is the special value 0 which has the framework
+ * auto-select a valid channel from the band configured with {@link #setBands(int[])}.
+ *
+ * The channel auto selection will be offloaded to driver when
+ * {@link SoftApCapability#areFeaturesSupported(long)}
+ * with {@link SoftApCapability.SOFTAP_FEATURE_ACS_OFFLOAD}
+ * returns true. The driver will auto select the best channel (e.g. best performance)
+ * based on environment interference. Check {@link SoftApCapability} for more detail.
+ *
+ * The API contains (band, channel) input since the 6GHz band uses the same channel
+ * numbering scheme as is used in the 2.4GHz and 5GHz band. Therefore, both are needed to
+ * uniquely identify individual channels.
+ *
+ * <p>
+ * @param channels SparseIntArray (key: {@code #BandType} , value: channel) consists of
+ * {@code BAND_} and corresponding channel.
+ * @return Builder for chaining.
+ * @throws IllegalArgumentException when more than 2 channels are set or the invalid
+ * channel or band type is configured.
+ */
+ @NonNull
+ public Builder setChannels(@NonNull SparseIntArray channels) {
+ if (!SdkLevel.isAtLeastS()) {
+ throw new UnsupportedOperationException();
+ }
+ if (channels.size() == 0 || channels.size() > 2) {
+ throw new IllegalArgumentException("Unsupported number of channels("
+ + channels.size() + ") configured");
+ }
+ for (int i = 0; i < channels.size(); i++) {
+ int channel = channels.valueAt(i);
+ int band = channels.keyAt(i);
+ if (channel == 0) {
+ if (!isBandValid(band)) {
+ throw new IllegalArgumentException("Invalid band type: " + band);
+ }
+ } else {
+ if (!isChannelBandPairValid(channel, band)) {
+ throw new IllegalArgumentException("Invalid channel(" + channel
+ + ") & band (" + band + ") configured");
+ }
+ }
+ }
+ mChannels = channels.clone();
+ return this;
+ }
+
+
+ /**
* Specifies the maximum number of clients that can associate to the AP.
*
* The maximum number of clients (STAs) which can associate to the AP.
@@ -815,14 +1089,14 @@
* <p>
* <li>If not set, defaults to 0.</li>
*
- * This method requires hardware support. If the method is used to set a
+ * This method requires HAL support. If the method is used to set a
* non-zero {@code maxNumberOfClients} value then
* {@link WifiManager#startTetheredHotspot} will report error code
* {@link WifiManager#SAP_START_FAILURE_UNSUPPORTED_CONFIGURATION}.
*
* <p>
* Use {@link WifiManager.SoftApCallback#onCapabilityChanged(SoftApCapability)} and
- * {@link SoftApCapability#areFeaturesSupported(int)}
+ * {@link SoftApCapability#areFeaturesSupported(long)}
* with {@link SoftApCapability.SOFTAP_FEATURE_CLIENT_FORCE_DISCONNECT} to determine whether
* or not this feature is supported.
*
@@ -896,13 +1170,13 @@
* {@link #setBlockedClientList(List)} and {@link #setAllowedClientList(List)}.
*
* <p>
- * This method requires hardware support. Hardware support can be determined using
+ * This method requires HAL support. HAL support can be determined using
* {@link WifiManager.SoftApCallback#onCapabilityChanged(SoftApCapability)} and
- * {@link SoftApCapability#areFeaturesSupported(int)}
+ * {@link SoftApCapability#areFeaturesSupported(long)}
* with {@link SoftApCapability.SOFTAP_FEATURE_CLIENT_FORCE_DISCONNECT}
*
* <p>
- * If the method is called on a device without hardware support then starting the soft AP
+ * If the method is called on a device without HAL support then starting the soft AP
* using {@link WifiManager#startTetheredHotspot(SoftApConfiguration)} will fail with
* {@link WifiManager#SAP_START_FAILURE_UNSUPPORTED_CONFIGURATION}.
*
@@ -951,13 +1225,13 @@
* to the Soft AP.
*
* <p>
- * This method requires hardware support. Hardware support can be determined using
+ * This method requires HAL support. HAL support can be determined using
* {@link WifiManager.SoftApCallback#onCapabilityChanged(SoftApCapability)} and
- * {@link SoftApCapability#areFeaturesSupported(int)}
+ * {@link SoftApCapability#areFeaturesSupported(long)}
* with {@link SoftApCapability.SOFTAP_FEATURE_CLIENT_FORCE_DISCONNECT}
*
* <p>
- * If the method is called on a device without hardware support then starting the soft AP
+ * If the method is called on a device without HAL support then starting the soft AP
* using {@link WifiManager#startTetheredHotspot(SoftApConfiguration)} will fail with
* {@link WifiManager#SAP_START_FAILURE_UNSUPPORTED_CONFIGURATION}.
*
@@ -969,5 +1243,37 @@
mBlockedClientList = new ArrayList<>(blockedClientList);
return this;
}
+
+ /**
+ * Specifies the level of MAC randomization for the AP BSSID.
+ * The Soft AP BSSID will be randomized only if the BSSID isn't set
+ * {@link #setBssid(MacAddress)} and this method is either uncalled
+ * or called with {@link #RANDOMIZATION_PERSISTENT}.
+ *
+ * <p>
+ * <li>If not set, defaults to {@link #RANDOMIZATION_PERSISTENT}</li>
+ *
+ * <p>
+ * Requires HAL support when set to {@link #RANDOMIZATION_PERSISTENT}.
+ * Use {@link WifiManager.SoftApCallback#onCapabilityChanged(SoftApCapability)} and
+ * {@link SoftApCapability#areFeaturesSupported(long)}
+ * with {@link SoftApCapability.SOFTAP_FEATURE_MAC_ADDRESS_CUSTOMIZATION} to determine
+ * whether or not this feature is supported.
+ *
+ * @param macRandomizationSetting One of the following setting:
+ * {@link #RANDOMIZATION_NONE} or {@link #RANDOMIZATION_PERSISTENT}.
+ * @return Builder for chaining.
+ *
+ * @see #setBssid(MacAddress)
+ */
+ @NonNull
+ public Builder setMacRandomizationSetting(
+ @MacRandomizationSetting int macRandomizationSetting) {
+ if (!SdkLevel.isAtLeastS()) {
+ throw new UnsupportedOperationException();
+ }
+ mMacRandomizationSetting = macRandomizationSetting;
+ return this;
+ }
}
}
diff --git a/framework/java/android/net/wifi/SoftApInfo.java b/framework/java/android/net/wifi/SoftApInfo.java
index 24ed8ef..e42e786 100644
--- a/framework/java/android/net/wifi/SoftApInfo.java
+++ b/framework/java/android/net/wifi/SoftApInfo.java
@@ -19,9 +19,13 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
+import android.net.MacAddress;
import android.os.Parcel;
import android.os.Parcelable;
+import com.android.internal.util.Preconditions;
+import com.android.modules.utils.build.SdkLevel;
+
import java.util.Objects;
/**
@@ -82,7 +86,33 @@
*/
public static final int CHANNEL_WIDTH_160MHZ = 6;
+ /**
+ * AP Channel bandwidth is 2160 MHZ.
+ *
+ * @see #getBandwidth()
+ */
+ public static final int CHANNEL_WIDTH_2160MHZ = 7;
+ /**
+ * AP Channel bandwidth is 4320 MHZ.
+ *
+ * @see #getBandwidth()
+ */
+ public static final int CHANNEL_WIDTH_4320MHZ = 8;
+
+ /**
+ * AP Channel bandwidth is 6480 MHZ.
+ *
+ * @see #getBandwidth()
+ */
+ public static final int CHANNEL_WIDTH_6480MHZ = 9;
+
+ /**
+ * AP Channel bandwidth is 8640 MHZ.
+ *
+ * @see #getBandwidth()
+ */
+ public static final int CHANNEL_WIDTH_8640MHZ = 10;
/** The frequency which AP resides on. */
private int mFrequency = 0;
@@ -90,6 +120,19 @@
@WifiAnnotations.Bandwidth
private int mBandwidth = CHANNEL_WIDTH_INVALID;
+ /** The MAC Address which AP resides on. */
+ @Nullable
+ private MacAddress mBssid;
+
+ /** The identifier of the AP instance which AP resides on with current info. */
+ @Nullable
+ private String mApInstanceIdentifier;
+
+ /**
+ * The operational mode of the AP.
+ */
+ private @WifiAnnotations.WifiStandard int mWifiStandard = ScanResult.WIFI_STANDARD_UNKNOWN;
+
/**
* Get the frequency which AP resides on.
*/
@@ -110,7 +153,9 @@
*
* @return One of {@link #CHANNEL_WIDTH_20MHZ}, {@link #CHANNEL_WIDTH_40MHZ},
* {@link #CHANNEL_WIDTH_80MHZ}, {@link #CHANNEL_WIDTH_160MHZ},
- * {@link #CHANNEL_WIDTH_80MHZ_PLUS_MHZ} or {@link #CHANNEL_WIDTH_INVALID}.
+ * {@link #CHANNEL_WIDTH_80MHZ_PLUS_MHZ}, {@link #CHANNEL_WIDTH_2160MHZ},
+ * {@link #CHANNEL_WIDTH_4320MHZ}, {@link #CHANNEL_WIDTH_6480MHZ},
+ * {@link #CHANNEL_WIDTH_8640MHZ}, or {@link #CHANNEL_WIDTH_INVALID}.
*/
@WifiAnnotations.Bandwidth
public int getBandwidth() {
@@ -126,12 +171,87 @@
}
/**
+ * Get the MAC address (BSSID) of the AP. Null when AP disabled.
+ */
+ @Nullable
+ public MacAddress getBssid() {
+ if (!SdkLevel.isAtLeastS()) {
+ throw new UnsupportedOperationException();
+ }
+ return mBssid;
+ }
+
+ /**
+ * Set the MAC address which AP resides on.
+ * <p>
+ * <li>If not set, defaults to null.</li>
+ * @param bssid BSSID, The caller is responsible for avoiding collisions.
+ * @throws IllegalArgumentException when the given BSSID is the all-zero or broadcast MAC
+ * address.
+ *
+ * @hide
+ */
+ public void setBssid(@Nullable MacAddress bssid) {
+ if (bssid != null) {
+ Preconditions.checkArgument(!bssid.equals(WifiManager.ALL_ZEROS_MAC_ADDRESS));
+ Preconditions.checkArgument(!bssid.equals(MacAddress.BROADCAST_ADDRESS));
+ }
+ mBssid = bssid;
+ }
+
+ /**
+ * Set the operational mode of the AP.
+ *
+ * @param wifiStandard values from {@link ScanResult}'s {@code WIFI_STANDARD_}
+ * @hide
+ */
+ public void setWifiStandard(@WifiAnnotations.WifiStandard int wifiStandard) {
+ mWifiStandard = wifiStandard;
+ }
+
+ /**
+ * Get the operational mode of the AP.
+ * @return valid values from {@link ScanResult}'s {@code WIFI_STANDARD_}
+ */
+ public @WifiAnnotations.WifiStandard int getWifiStandard() {
+ if (!SdkLevel.isAtLeastS()) {
+ throw new UnsupportedOperationException();
+ }
+ return mWifiStandard;
+ }
+
+ /**
+ * Set the AP instance identifier.
+ * @hide
+ */
+ public void setApInstanceIdentifier(@NonNull String apInstanceIdentifier) {
+ mApInstanceIdentifier = apInstanceIdentifier;
+ }
+
+ /**
+ * Get the AP instance identifier.
+ *
+ * The AP instance identifier is a unique identity which can be used to
+ * associate the {@link SoftApInfo} to a specific {@link WifiClient}
+ * - see {@link WifiClient#getApInstanceIdentifier()}
+ *
+ * @hide
+ */
+ @Nullable
+ public String getApInstanceIdentifier() {
+ return mApInstanceIdentifier;
+ }
+
+ /**
* @hide
*/
public SoftApInfo(@Nullable SoftApInfo source) {
if (source != null) {
mFrequency = source.mFrequency;
mBandwidth = source.mBandwidth;
+ mBssid = source.mBssid;
+ mWifiStandard = source.mWifiStandard;
+ mApInstanceIdentifier = source.mApInstanceIdentifier;
}
}
@@ -152,6 +272,9 @@
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeInt(mFrequency);
dest.writeInt(mBandwidth);
+ dest.writeParcelable(mBssid, flags);
+ dest.writeInt(mWifiStandard);
+ dest.writeString(mApInstanceIdentifier);
}
@NonNull
@@ -161,6 +284,9 @@
SoftApInfo info = new SoftApInfo();
info.mFrequency = in.readInt();
info.mBandwidth = in.readInt();
+ info.mBssid = in.readParcelable(MacAddress.class.getClassLoader());
+ info.mWifiStandard = in.readInt();
+ info.mApInstanceIdentifier = in.readString();
return info;
}
@@ -172,10 +298,15 @@
@NonNull
@Override
public String toString() {
- return "SoftApInfo{"
- + "bandwidth= " + mBandwidth
- + ",frequency= " + mFrequency
- + '}';
+ StringBuilder sbuf = new StringBuilder();
+ sbuf.append("SoftApInfo{");
+ sbuf.append("bandwidth= ").append(mBandwidth);
+ sbuf.append(", frequency= ").append(mFrequency);
+ if (mBssid != null) sbuf.append(",bssid=").append(mBssid.toString());
+ sbuf.append(", wifiStandard= ").append(mWifiStandard);
+ sbuf.append(", mApInstanceIdentifier= ").append(mApInstanceIdentifier);
+ sbuf.append("}");
+ return sbuf.toString();
}
@Override
@@ -184,11 +315,14 @@
if (!(o instanceof SoftApInfo)) return false;
SoftApInfo softApInfo = (SoftApInfo) o;
return mFrequency == softApInfo.mFrequency
- && mBandwidth == softApInfo.mBandwidth;
+ && mBandwidth == softApInfo.mBandwidth
+ && Objects.equals(mBssid, softApInfo.mBssid)
+ && mWifiStandard == softApInfo.mWifiStandard
+ && Objects.equals(mApInstanceIdentifier, softApInfo.mApInstanceIdentifier);
}
@Override
public int hashCode() {
- return Objects.hash(mFrequency, mBandwidth);
+ return Objects.hash(mFrequency, mBandwidth, mBssid, mWifiStandard, mApInstanceIdentifier);
}
}
diff --git a/framework/java/android/net/wifi/WifiAnnotations.java b/framework/java/android/net/wifi/WifiAnnotations.java
index acda7e0..807b40b 100644
--- a/framework/java/android/net/wifi/WifiAnnotations.java
+++ b/framework/java/android/net/wifi/WifiAnnotations.java
@@ -57,6 +57,10 @@
SoftApInfo.CHANNEL_WIDTH_80MHZ,
SoftApInfo.CHANNEL_WIDTH_80MHZ_PLUS_MHZ,
SoftApInfo.CHANNEL_WIDTH_160MHZ,
+ SoftApInfo.CHANNEL_WIDTH_2160MHZ,
+ SoftApInfo.CHANNEL_WIDTH_4320MHZ,
+ SoftApInfo.CHANNEL_WIDTH_6480MHZ,
+ SoftApInfo.CHANNEL_WIDTH_8640MHZ,
})
@Retention(RetentionPolicy.SOURCE)
public @interface Bandwidth {}
@@ -77,6 +81,7 @@
ScanResult.WIFI_STANDARD_11N,
ScanResult.WIFI_STANDARD_11AC,
ScanResult.WIFI_STANDARD_11AX,
+ ScanResult.WIFI_STANDARD_11AD,
})
@Retention(RetentionPolicy.SOURCE)
public @interface WifiStandard{}
diff --git a/framework/java/android/net/wifi/WifiClient.java b/framework/java/android/net/wifi/WifiClient.java
index 3794566..85e2b33 100644
--- a/framework/java/android/net/wifi/WifiClient.java
+++ b/framework/java/android/net/wifi/WifiClient.java
@@ -30,6 +30,9 @@
private final MacAddress mMacAddress;
+ /** The identifier of the AP instance which the client connected. */
+ private final String mApInstanceIdentifier;
+
/**
* The mac address of this client.
*/
@@ -38,15 +41,30 @@
return mMacAddress;
}
+ /**
+ * Get AP instance identifier.
+ *
+ * The AP instance identifier is a unique identity which can be used to
+ * associate the {@link SoftApInfo} to a specific {@link WifiClient}
+ * - see {@link SoftApInfo#getApInstanceIdentifier()}
+ * @hide
+ */
+ @NonNull
+ public String getApInstanceIdentifier() {
+ return mApInstanceIdentifier;
+ }
+
private WifiClient(Parcel in) {
mMacAddress = in.readParcelable(null);
+ mApInstanceIdentifier = in.readString();
}
/** @hide */
- public WifiClient(@NonNull MacAddress macAddress) {
+ public WifiClient(@NonNull MacAddress macAddress, @NonNull String apInstanceIdentifier) {
Objects.requireNonNull(macAddress, "mMacAddress must not be null.");
this.mMacAddress = macAddress;
+ this.mApInstanceIdentifier = apInstanceIdentifier;
}
@Override
@@ -57,6 +75,7 @@
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeParcelable(mMacAddress, flags);
+ dest.writeString(mApInstanceIdentifier);
}
@NonNull
@@ -75,6 +94,7 @@
public String toString() {
return "WifiClient{"
+ "mMacAddress=" + mMacAddress
+ + "mApInstanceIdentifier=" + mApInstanceIdentifier
+ '}';
}
@@ -83,13 +103,12 @@
if (this == o) return true;
if (!(o instanceof WifiClient)) return false;
WifiClient client = (WifiClient) o;
- return mMacAddress.equals(client.mMacAddress);
+ return Objects.equals(mMacAddress, client.mMacAddress)
+ && mApInstanceIdentifier.equals(client.mApInstanceIdentifier);
}
@Override
public int hashCode() {
- return Objects.hash(mMacAddress);
+ return Objects.hash(mMacAddress, mApInstanceIdentifier);
}
}
-
-
diff --git a/framework/java/android/net/wifi/WifiConfiguration.java b/framework/java/android/net/wifi/WifiConfiguration.java
index 93c6358..6c0b2df 100644
--- a/framework/java/android/net/wifi/WifiConfiguration.java
+++ b/framework/java/android/net/wifi/WifiConfiguration.java
@@ -19,6 +19,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.PackageManager;
@@ -34,6 +35,8 @@
import android.os.Parcelable;
import android.os.SystemClock;
import android.os.UserHandle;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;
@@ -44,10 +47,13 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
import java.util.Calendar;
+import java.util.Collections;
import java.util.HashMap;
+import java.util.List;
/**
* A class representing a configured Wi-Fi network, including the
@@ -248,6 +254,11 @@
*/
public static final int WAPI = 3;
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(value = {WPA, RSN, OSEN, WAPI})
+ public @interface ProtocolScheme {};
+
public static final String varName = "proto";
public static final String[] strings = { "WPA", "RSN", "OSEN", "WAPI" };
@@ -272,6 +283,11 @@
/** SAE (Used only for WPA3-Personal) */
public static final int SAE = 3;
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(value = {OPEN, SHARED, LEAP, SAE})
+ public @interface AuthAlgorithmScheme {};
+
public static final String varName = "auth_alg";
public static final String[] strings = { "OPEN", "SHARED", "LEAP", "SAE" };
@@ -301,9 +317,20 @@
*/
public static final int SMS4 = 4;
+ /**
+ * AES in Galois/Counter Mode with a 128-bit integrity key
+ */
+ public static final int GCMP_128 = 5;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(value = {NONE, TKIP, CCMP, GCMP_256, SMS4, GCMP_128})
+ public @interface PairwiseCipherScheme {};
+
public static final String varName = "pairwise";
- public static final String[] strings = { "NONE", "TKIP", "CCMP", "GCMP_256", "SMS4" };
+ public static final String[] strings = { "NONE", "TKIP", "CCMP", "GCMP_256", "SMS4",
+ "GCMP_128" };
}
/**
@@ -345,13 +372,22 @@
* SMS4 cipher for WAPI
*/
public static final int SMS4 = 6;
+ /**
+ * AES in Galois/Counter Mode with a 128-bit integrity key
+ */
+ public static final int GCMP_128 = 7;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(value = {WEP40, WEP104, TKIP, CCMP, GTK_NOT_USED, GCMP_256, SMS4, GCMP_128})
+ public @interface GroupCipherScheme {};
public static final String varName = "group";
public static final String[] strings =
{ /* deprecated */ "WEP40", /* deprecated */ "WEP104",
"TKIP", "CCMP", "GTK_NOT_USED", "GCMP_256",
- "SMS4" };
+ "SMS4", "GCMP_128" };
}
/**
@@ -374,9 +410,16 @@
/** GMAC-256 = Galois Message Authentication Code */
public static final int BIP_GMAC_256 = 2;
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(value = {BIP_CMAC_256, BIP_GMAC_128, BIP_GMAC_256})
+ public @interface GroupMgmtCipherScheme {};
+
private static final String varName = "groupMgmt";
- private static final String[] strings = { "BIP_CMAC_256",
+ /** @hide */
+ @SuppressLint("AllUpper")
+ public static final @NonNull String[] strings = { "BIP_CMAC_256",
"BIP_GMAC_128", "BIP_GMAC_256"};
}
@@ -397,9 +440,16 @@
/** Diffie-Hellman with_RSA signature */
public static final int ECDHE_RSA = 1;
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(value = {ECDHE_ECDSA, ECDHE_RSA})
+ public @interface SuiteBCipherScheme {};
+
private static final String varName = "SuiteB";
- private static final String[] strings = { "ECDHE_ECDSA", "ECDHE_RSA" };
+ /** @hide */
+ @SuppressLint("AllUpper")
+ public static final String[] strings = { "ECDHE_ECDSA", "ECDHE_RSA" };
}
/** Possible status of a network configuration. */
@@ -426,14 +476,46 @@
public static final int SECURITY_TYPE_EAP = 3;
/** Security type for an SAE network. */
public static final int SECURITY_TYPE_SAE = 4;
- /** Security type for an EAP Suite B network. */
- public static final int SECURITY_TYPE_EAP_SUITE_B = 5;
+ /**
+ * Security type for a WPA3-Enterprise in 192-bit security network.
+ * This is the same as {@link #SECURITY_TYPE_EAP_SUITE_B} and uses the same value.
+ */
+ public static final int SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT = 5;
+ /**
+ * Security type for a WPA3-Enterprise in 192-bit security network.
+ * @deprecated Use the {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT} constant
+ * (which is the same value).
+ */
+ @Deprecated
+ public static final int SECURITY_TYPE_EAP_SUITE_B =
+ SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT;
/** Security type for an OWE network. */
public static final int SECURITY_TYPE_OWE = 6;
/** Security type for a WAPI PSK network. */
public static final int SECURITY_TYPE_WAPI_PSK = 7;
/** Security type for a WAPI Certificate network. */
public static final int SECURITY_TYPE_WAPI_CERT = 8;
+ /** Security type for a WPA3-Enterprise network. */
+ public static final int SECURITY_TYPE_EAP_WPA3_ENTERPRISE = 9;
+ /**
+ * Security type for an OSEN network.
+ * @hide
+ */
+ public static final int SECURITY_TYPE_OSEN = 10;
+ /**
+ * Security type for a Passpoint R1/R2 network.
+ * Passpoint R1/R2 uses Enterprise security, where TKIP and WEP are not allowed.
+ * @hide
+ */
+ public static final int SECURITY_TYPE_PASSPOINT_R1_R2 = 11;
+
+ /**
+ * Security type for a Passpoint R3 network.
+ * Passpoint R3 uses Enterprise security, where TKIP and WEP are not allowed,
+ * and PMF must be set to Required.
+ * @hide
+ */
+ public static final int SECURITY_TYPE_PASSPOINT_R3 = 12;
/**
* Security types we support.
@@ -449,13 +531,92 @@
SECURITY_TYPE_EAP_SUITE_B,
SECURITY_TYPE_OWE,
SECURITY_TYPE_WAPI_PSK,
- SECURITY_TYPE_WAPI_CERT
+ SECURITY_TYPE_WAPI_CERT,
+ SECURITY_TYPE_EAP_WPA3_ENTERPRISE,
+ SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT,
+ SECURITY_TYPE_PASSPOINT_R1_R2,
+ SECURITY_TYPE_PASSPOINT_R3,
})
public @interface SecurityType {}
+ private List<SecurityParams> mSecurityParamsList = new ArrayList<>();
+
+ private void updateLegacySecurityParams() {
+ if (mSecurityParamsList.isEmpty()) return;
+ mSecurityParamsList.get(0).updateLegacyWifiConfiguration(this);
+ }
+
/**
* Set the various security params to correspond to the provided security type.
* This is accomplished by setting the various BitSets exposed in WifiConfiguration.
+ * <br>
+ * This API would clear existing security types and add a default one.
+ *
+ * @param securityType One of the following security types:
+ * {@link #SECURITY_TYPE_OPEN},
+ * {@link #SECURITY_TYPE_WEP},
+ * {@link #SECURITY_TYPE_PSK},
+ * {@link #SECURITY_TYPE_EAP},
+ * {@link #SECURITY_TYPE_SAE},
+ * {@link #SECURITY_TYPE_OWE},
+ * {@link #SECURITY_TYPE_WAPI_PSK},
+ * {@link #SECURITY_TYPE_WAPI_CERT},
+ * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE},
+ * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT},
+ */
+ public void setSecurityParams(@SecurityType int securityType) {
+ // Clear existing data.
+ mSecurityParamsList.clear();
+ addSecurityParams(securityType);
+ }
+
+ /**
+ * Set security params by the given key management mask.
+ *
+ * @param givenAllowedKeyManagement the given allowed key management mask.
+ * @hide
+ */
+ public void setSecurityParams(@NonNull BitSet givenAllowedKeyManagement) {
+ if (givenAllowedKeyManagement == null) {
+ throw new IllegalArgumentException("Invalid allowed key management mask.");
+ }
+ // Clear existing data.
+ mSecurityParamsList.clear();
+
+ allowedKeyManagement = (BitSet) givenAllowedKeyManagement.clone();
+ convertLegacyFieldsToSecurityParamsIfNeeded();
+ }
+
+ /**
+ * Add the various security params.
+ * <br>
+ * This API would clear existing security types and add a default one.
+ * @hide
+ */
+ public void setSecurityParams(SecurityParams params) {
+ // Clear existing data.
+ mSecurityParamsList.clear();
+ addSecurityParams(params);
+ }
+
+ /**
+ * Set the security params by the given security params list.
+ *
+ * This will overwrite existing security params list directly.
+ *
+ * @param securityParamsList the desired security params list.
+ * @hide
+ */
+ public void setSecurityParams(@NonNull List<SecurityParams> securityParamsList) {
+ if (securityParamsList == null || securityParamsList.isEmpty()) {
+ throw new IllegalArgumentException("An empty security params list is invalid.");
+ }
+ mSecurityParamsList = new ArrayList<>(securityParamsList);
+ }
+
+ /**
+ * Add the various security params to correspond to the provided security type.
+ * This is accomplished by setting the various BitSets exposed in WifiConfiguration.
*
* @param securityType One of the following security types:
* {@link #SECURITY_TYPE_OPEN},
@@ -463,82 +624,276 @@
* {@link #SECURITY_TYPE_PSK},
* {@link #SECURITY_TYPE_EAP},
* {@link #SECURITY_TYPE_SAE},
- * {@link #SECURITY_TYPE_EAP_SUITE_B},
* {@link #SECURITY_TYPE_OWE},
- * {@link #SECURITY_TYPE_WAPI_PSK}, or
- * {@link #SECURITY_TYPE_WAPI_CERT}
+ * {@link #SECURITY_TYPE_WAPI_PSK},
+ * {@link #SECURITY_TYPE_WAPI_CERT},
+ * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE},
+ * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT},
+ *
+ * @hide
*/
- public void setSecurityParams(@SecurityType int securityType) {
- // Clear all the bitsets.
- allowedKeyManagement.clear();
- allowedProtocols.clear();
- allowedAuthAlgorithms.clear();
- allowedPairwiseCiphers.clear();
- allowedGroupCiphers.clear();
- allowedGroupManagementCiphers.clear();
- allowedSuiteBCiphers.clear();
-
- switch (securityType) {
- case SECURITY_TYPE_OPEN:
- allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
- break;
- case SECURITY_TYPE_WEP:
- allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
- allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
- allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED);
- break;
- case SECURITY_TYPE_PSK:
- allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
- break;
- case SECURITY_TYPE_EAP:
- allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP);
- allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X);
- break;
- case SECURITY_TYPE_SAE:
- allowedProtocols.set(WifiConfiguration.Protocol.RSN);
- allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SAE);
- allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
- allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.GCMP_256);
- allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
- allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_256);
- requirePmf = true;
- break;
- case SECURITY_TYPE_EAP_SUITE_B:
- allowedProtocols.set(WifiConfiguration.Protocol.RSN);
- allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP);
- allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X);
- allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SUITE_B_192);
- allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.GCMP_256);
- allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_256);
- allowedGroupManagementCiphers.set(WifiConfiguration.GroupMgmtCipher.BIP_GMAC_256);
- // Note: allowedSuiteBCiphers bitset will be set by the service once the
- // certificates are attached to this profile
- requirePmf = true;
- break;
- case SECURITY_TYPE_OWE:
- allowedProtocols.set(WifiConfiguration.Protocol.RSN);
- allowedKeyManagement.set(WifiConfiguration.KeyMgmt.OWE);
- allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
- allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.GCMP_256);
- allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
- allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_256);
- requirePmf = true;
- break;
- case SECURITY_TYPE_WAPI_PSK:
- allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WAPI_PSK);
- allowedProtocols.set(WifiConfiguration.Protocol.WAPI);
- allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.SMS4);
- allowedGroupCiphers.set(WifiConfiguration.GroupCipher.SMS4);
- break;
- case SECURITY_TYPE_WAPI_CERT:
- allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WAPI_CERT);
- allowedProtocols.set(WifiConfiguration.Protocol.WAPI);
- allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.SMS4);
- allowedGroupCiphers.set(WifiConfiguration.GroupCipher.SMS4);
- break;
- default:
- throw new IllegalArgumentException("unknown security type " + securityType);
+ public void addSecurityParams(@SecurityType int securityType) {
+ // This ensures that there won't be duplicate security types.
+ if (mSecurityParamsList.stream().anyMatch(params -> params.isSecurityType(securityType))) {
+ throw new IllegalArgumentException("duplicate security type " + securityType);
}
+ addSecurityParams(SecurityParams.createSecurityParamsBySecurityType(securityType));
+ }
+
+ /** @hide */
+ public void addSecurityParams(@NonNull SecurityParams newParams) {
+ if (mSecurityParamsList.stream().anyMatch(params -> params.isSameSecurityType(newParams))) {
+ throw new IllegalArgumentException("duplicate security params " + newParams);
+ }
+ if (!mSecurityParamsList.isEmpty()) {
+ if (newParams.isEnterpriseSecurityType() && !isEnterprise()) {
+ throw new IllegalArgumentException(
+ "An enterprise security type cannot be added to a personal configuation.");
+ }
+ if (!newParams.isEnterpriseSecurityType() && isEnterprise()) {
+ throw new IllegalArgumentException(
+ "A personal security type cannot be added to an enterprise configuation.");
+ }
+ if (newParams.isOpenSecurityType() && !isOpenNetwork()) {
+ throw new IllegalArgumentException(
+ "An open security type cannot be added to a non-open configuation.");
+ }
+ if (!newParams.isOpenSecurityType() && isOpenNetwork()) {
+ throw new IllegalArgumentException(
+ "A non-open security type cannot be added to an open configuation.");
+ }
+ if (newParams.isSecurityType(SECURITY_TYPE_OSEN)) {
+ throw new IllegalArgumentException(
+ "An OSEN security type must be the only one type.");
+ }
+ }
+ mSecurityParamsList.add(new SecurityParams(newParams));
+ updateLegacySecurityParams();
+ }
+
+ /**
+ * If there is no security params, generate one according to legacy fields.
+ * @hide
+ */
+ public void convertLegacyFieldsToSecurityParamsIfNeeded() {
+ if (!mSecurityParamsList.isEmpty()) return;
+
+ if (allowedKeyManagement.get(KeyMgmt.WAPI_CERT)) {
+ setSecurityParams(SECURITY_TYPE_WAPI_CERT);
+ } else if (allowedKeyManagement.get(KeyMgmt.WAPI_PSK)) {
+ setSecurityParams(SECURITY_TYPE_WAPI_PSK);
+ } else if (allowedKeyManagement.get(KeyMgmt.SUITE_B_192)) {
+ setSecurityParams(SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT);
+ } else if (allowedKeyManagement.get(KeyMgmt.OWE)) {
+ setSecurityParams(SECURITY_TYPE_OWE);
+ } else if (allowedKeyManagement.get(KeyMgmt.SAE)) {
+ setSecurityParams(SECURITY_TYPE_SAE);
+ } else if (allowedKeyManagement.get(KeyMgmt.OSEN)) {
+ setSecurityParams(SECURITY_TYPE_OSEN);
+ } else if (allowedKeyManagement.get(KeyMgmt.WPA2_PSK)) {
+ setSecurityParams(SECURITY_TYPE_PSK);
+ } else if (allowedKeyManagement.get(KeyMgmt.WPA_EAP)) {
+ if (requirePmf) {
+ setSecurityParams(SECURITY_TYPE_EAP_WPA3_ENTERPRISE);
+ } else {
+ setSecurityParams(SECURITY_TYPE_EAP);
+ }
+ } else if (allowedKeyManagement.get(KeyMgmt.WPA_PSK)) {
+ setSecurityParams(SECURITY_TYPE_PSK);
+ } else if (allowedKeyManagement.get(KeyMgmt.NONE)) {
+ if (hasWepKeys()) {
+ setSecurityParams(SECURITY_TYPE_WEP);
+ } else {
+ setSecurityParams(SECURITY_TYPE_OPEN);
+ }
+ } else {
+ setSecurityParams(SECURITY_TYPE_OPEN);
+ }
+ }
+
+ /**
+ * Disable the various security params to correspond to the provided security type.
+ * This is accomplished by setting the various BitSets exposed in WifiConfiguration.
+ *
+ * @param securityType One of the following security types:
+ * {@link #SECURITY_TYPE_OPEN},
+ * {@link #SECURITY_TYPE_WEP},
+ * {@link #SECURITY_TYPE_PSK},
+ * {@link #SECURITY_TYPE_EAP},
+ * {@link #SECURITY_TYPE_SAE},
+ * {@link #SECURITY_TYPE_OWE},
+ * {@link #SECURITY_TYPE_WAPI_PSK},
+ * {@link #SECURITY_TYPE_WAPI_CERT},
+ * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE},
+ * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT},
+ *
+ * @hide
+ */
+ public void setSecurityParamsEnabled(@SecurityType int securityType, boolean enable) {
+ mSecurityParamsList.stream()
+ .filter(params -> params.isSecurityType(securityType))
+ .findAny()
+ .ifPresent(params -> params.setEnabled(enable));
+ }
+
+ /**
+ * Get the specific security param.
+ *
+ * @param securityType One of the following security types:
+ * {@link #SECURITY_TYPE_OPEN},
+ * {@link #SECURITY_TYPE_WEP},
+ * {@link #SECURITY_TYPE_PSK},
+ * {@link #SECURITY_TYPE_EAP},
+ * {@link #SECURITY_TYPE_SAE},
+ * {@link #SECURITY_TYPE_OWE},
+ * {@link #SECURITY_TYPE_WAPI_PSK},
+ * {@link #SECURITY_TYPE_WAPI_CERT},
+ * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE},
+ * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT},
+ *
+ * @return the copy of specific security params if found; otherwise null.
+ * @hide
+ */
+ public @Nullable SecurityParams getSecurityParams(@SecurityType int securityType) {
+ SecurityParams p = mSecurityParamsList.stream()
+ .filter(params -> params.isSecurityType(securityType))
+ .findAny()
+ .orElse(null);
+ return (p != null) ? new SecurityParams(p) : null;
+ }
+
+ /**
+ * Indicate whether this configuration is the specific security type.
+ *
+ * @param securityType One of the following security types:
+ * {@link #SECURITY_TYPE_OPEN},
+ * {@link #SECURITY_TYPE_WEP},
+ * {@link #SECURITY_TYPE_PSK},
+ * {@link #SECURITY_TYPE_EAP},
+ * {@link #SECURITY_TYPE_SAE},
+ * {@link #SECURITY_TYPE_OWE},
+ * {@link #SECURITY_TYPE_WAPI_PSK},
+ * {@link #SECURITY_TYPE_WAPI_CERT},
+ * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE},
+ * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT},
+ *
+ * @return true if there is a security params matches the type.
+ * @hide
+ */
+ public boolean isSecurityType(@SecurityType int securityType) {
+ return mSecurityParamsList.stream()
+ .anyMatch(params -> params.isSecurityType(securityType));
+ }
+
+ /**
+ * Get the security params list of this configuration.
+ *
+ * The returning list is a priority list, the first is the lowest priority and default one.
+ *
+ * @return this list of security params.
+ * @hide
+ */
+ public List<SecurityParams> getSecurityParamsList() {
+ return Collections.unmodifiableList(mSecurityParamsList);
+ }
+
+ /**
+ * Enable the support of Fast Initial Link Set-up (FILS).
+ *
+ * FILS can be applied to all security types.
+ * @param enableFilsSha256 Enable FILS SHA256.
+ * @param enableFilsSha384 Enable FILS SHA256.
+ * @hide
+ */
+ public void enableFils(boolean enableFilsSha256, boolean enableFilsSha384) {
+ mSecurityParamsList.stream()
+ .forEach(params -> params.enableFils(enableFilsSha256, enableFilsSha384));
+ updateLegacySecurityParams();
+ }
+
+ /**
+ * Indicate FILS SHA256 is enabled.
+ *
+ * @return true if FILS SHA256 is enabled.
+ * @hide
+ */
+ public boolean isFilsSha256Enabled() {
+ return mSecurityParamsList.stream()
+ .anyMatch(params -> params.getAllowedKeyManagement().get(KeyMgmt.FILS_SHA256));
+ }
+
+ /**
+ * Indicate FILS SHA384 is enabled.
+ *
+ * @return true if FILS SHA384 is enabled.
+ * @hide
+ */
+ public boolean isFilsSha384Enabled() {
+ return mSecurityParamsList.stream()
+ .anyMatch(params -> params.getAllowedKeyManagement().get(KeyMgmt.FILS_SHA384));
+ }
+
+ /**
+ * Enable Suite-B ciphers.
+ *
+ * @param enableEcdheEcdsa enable Diffie-Hellman with Elliptic Curve ECDSA cipher support.
+ * @param enableEcdheRsa enable Diffie-Hellman with RSA cipher support.
+ * @hide
+ */
+ public void enableSuiteBCiphers(boolean enableEcdheEcdsa, boolean enableEcdheRsa) {
+ mSecurityParamsList.stream()
+ .filter(params -> params.isSecurityType(SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT))
+ .findAny()
+ .ifPresent(params -> params.enableSuiteBCiphers(enableEcdheEcdsa, enableEcdheRsa));
+ updateLegacySecurityParams();
+ }
+
+ /**
+ * Indicate ECDHE_ECDSA is enabled.
+ *
+ * @return true if enabled.
+ * @hide
+ */
+ public boolean isSuiteBCipherEcdheEcdsaEnabled() {
+ return mSecurityParamsList.stream()
+ .anyMatch(params -> params.getAllowedSuiteBCiphers().get(SuiteBCipher.ECDHE_ECDSA));
+ }
+
+ /**
+ * Indicate ECDHE_RSA is enabled.
+ *
+ * @return true if enabled.
+ * @hide
+ */
+ public boolean isSuiteBCipherEcdheRsaEnabled() {
+ return mSecurityParamsList.stream()
+ .anyMatch(params -> params.getAllowedSuiteBCiphers().get(SuiteBCipher.ECDHE_RSA));
+ }
+
+ /**
+ * Set SAE Hash-toElement only mode enabled.
+ *
+ * @param enable true if enabled; false otherwise.
+ * @hide
+ */
+ public void enableSaeH2eOnlyMode(boolean enable) {
+ mSecurityParamsList.stream()
+ .filter(params -> params.isSecurityType(SECURITY_TYPE_SAE))
+ .findAny()
+ .ifPresent(params -> params.enableSaeH2eOnlyMode(enable));
+ }
+
+ /**
+ * Set SAE Public-Key only mode enabled.
+ *
+ * @param enable true if enabled; false otherwise.
+ * @hide
+ */
+ public void enableSaePkOnlyMode(boolean enable) {
+ mSecurityParamsList.stream()
+ .filter(params -> params.isSecurityType(SECURITY_TYPE_SAE))
+ .findAny()
+ .ifPresent(params -> params.enableSaePkOnlyMode(enable));
}
/** @hide */
@@ -596,6 +951,12 @@
public static final int AP_BAND_5GHZ = 1;
/**
+ * 60GHz band
+ * @hide
+ */
+ public static final int AP_BAND_60GHZ = 2;
+
+ /**
* Device is allowed to choose the optimal band (2Ghz or 5Ghz) based on device capability,
* operating country code and current radio conditions.
* @hide
@@ -858,6 +1219,14 @@
public int carrierId = TelephonyManager.UNKNOWN_CARRIER_ID;
/**
+ * The subscription ID identifies the SIM card for which this network configuration is valid.
+ * See {@link SubscriptionInfo#getSubscriptionId()}
+ * @hide
+ */
+ @SystemApi
+ public int subscriptionId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+
+ /**
* @hide
* Auto-join is allowed by user for this network.
* Default true.
@@ -969,6 +1338,36 @@
public boolean trusted;
/**
+ * Indicate whether the network is oem paid or not. Networks are considered oem paid
+ * if the corresponding connection is only available to system apps.
+ *
+ * This bit can only be used by suggestion network, see
+ * {@link WifiNetworkSuggestion.Builder#setOemPaid(boolean)}
+ * @hide
+ */
+ public boolean oemPaid;
+
+
+ /**
+ * Indicate whether the network is oem private or not. Networks are considered oem private
+ * if the corresponding connection is only available to system apps.
+ *
+ * This bit can only be used by suggestion network, see
+ * {@link WifiNetworkSuggestion.Builder#setOemPrivate(boolean)}
+ * @hide
+ */
+ public boolean oemPrivate;
+
+ /**
+ * Indicate whether or not the network is a carrier merged network.
+ * This bit can only be used by suggestion network, see
+ * {@link WifiNetworkSuggestion.Builder#setCarrierMerged(boolean)}
+ * @hide
+ */
+ @SystemApi
+ public boolean carrierMerged;
+
+ /**
* True if this Wifi configuration is created from a {@link WifiNetworkSuggestion},
* false otherwise.
*
@@ -1068,27 +1467,25 @@
return metered;
}
- /**
- * @hide
- * Returns true if this WiFi config is for an open network.
- */
- public boolean isOpenNetwork() {
- final int cardinality = allowedKeyManagement.cardinality();
- final boolean hasNoKeyMgmt = cardinality == 0
- || (cardinality == 1 && (allowedKeyManagement.get(KeyMgmt.NONE)
- || allowedKeyManagement.get(KeyMgmt.OWE)));
-
- boolean hasNoWepKeys = true;
- if (wepKeys != null) {
- for (int i = 0; i < wepKeys.length; i++) {
- if (wepKeys[i] != null) {
- hasNoWepKeys = false;
- break;
- }
+ /** Check whether wep keys exist. */
+ private boolean hasWepKeys() {
+ if (wepKeys == null) return false;
+ for (int i = 0; i < wepKeys.length; i++) {
+ if (wepKeys[i] != null) {
+ return true;
}
}
+ return false;
+ }
- return hasNoKeyMgmt && hasNoWepKeys;
+ /**
+ * @hide
+ * Returns true if this WiFi config is for an Open or Enhanced Open network.
+ */
+ public boolean isOpenNetwork() {
+ boolean hasNonOpenSecurityType = mSecurityParamsList.stream()
+ .anyMatch(params -> !params.isOpenSecurityType());
+ return !hasNonOpenSecurityType && !hasWepKeys();
}
/**
@@ -1130,7 +1527,9 @@
@Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = {"RANDOMIZATION_"}, value = {
RANDOMIZATION_NONE,
- RANDOMIZATION_PERSISTENT})
+ RANDOMIZATION_PERSISTENT,
+ RANDOMIZATION_ENHANCED,
+ RANDOMIZATION_AUTO})
public @interface MacRandomizationSetting {}
/**
@@ -1147,14 +1546,30 @@
public static final int RANDOMIZATION_PERSISTENT = 1;
/**
+ * Use a randomly generated MAC address for connections to this network.
+ * This option does not persist the randomized MAC address.
+ * @hide
+ */
+ @SystemApi
+ public static final int RANDOMIZATION_ENHANCED = 2;
+
+ /**
+ * Let the wifi framework automatically decide the MAC randomization strategy.
+ * @hide
+ */
+ @SystemApi
+ public static final int RANDOMIZATION_AUTO = 3;
+
+ /**
* Level of MAC randomization for this network.
- * One of {@link #RANDOMIZATION_NONE} or {@link #RANDOMIZATION_PERSISTENT}.
- * By default this field is set to {@link #RANDOMIZATION_PERSISTENT}.
+ * One of {@link #RANDOMIZATION_NONE}, {@link #RANDOMIZATION_AUTO},
+ * {@link #RANDOMIZATION_PERSISTENT} or {@link #RANDOMIZATION_ENHANCED}.
+ * By default this field is set to {@link #RANDOMIZATION_AUTO}.
* @hide
*/
@SystemApi
@MacRandomizationSetting
- public int macRandomizationSetting = RANDOMIZATION_PERSISTENT;
+ public int macRandomizationSetting = RANDOMIZATION_AUTO;
/**
* @hide
@@ -1165,12 +1580,18 @@
/**
* @hide
- * The wall clock time of when |mRandomizedMacAddress| should be re-randomized in aggressive
- * randomization mode.
+ * The wall clock time of when |mRandomizedMacAddress| should be re-randomized in enhanced
+ * MAC randomization mode.
*/
public long randomizedMacExpirationTimeMs = 0;
/**
+ * The wall clock time of when |mRandomizedMacAddress| is last modified.
+ * @hide
+ */
+ public long randomizedMacLastModifiedTimeMs = 0;
+
+ /**
* @hide
* Checks if the given MAC address can be used for Connected Mac Randomization
* by verifying that it is non-null, unicast, locally assigned, and not default mac.
@@ -1271,7 +1692,9 @@
DISABLED_NO_INTERNET_PERMANENT,
DISABLED_BY_WIFI_MANAGER,
DISABLED_BY_WRONG_PASSWORD,
- DISABLED_AUTHENTICATION_NO_SUBSCRIPTION})
+ DISABLED_AUTHENTICATION_NO_SUBSCRIPTION,
+ DISABLED_AUTHENTICATION_FAILURE_GENERIC,
+ DISABLED_AUTHENTICATION_FAILURE_CARRIER_SPECIFIC})
public @interface NetworkSelectionDisableReason {}
// Quality Network disabled reasons
@@ -1282,42 +1705,42 @@
* @hide
*/
public static final int NETWORK_SELECTION_DISABLED_STARTING_INDEX = 1;
- /**
- * The starting index for network selection temporarily disabled reasons.
- * @hide
- */
- public static final int TEMPORARILY_DISABLED_STARTING_INDEX = 1;
- /** This network is disabled because of multiple association rejections. */
+ /** This network is temporarily disabled because of multiple association rejections. */
public static final int DISABLED_ASSOCIATION_REJECTION = 1;
- /** This network is disabled because of multiple authentication failure. */
- public static final int DISABLED_AUTHENTICATION_FAILURE = 2;
- /** This network is disabled because of multiple DHCP failure. */
+ /** This network is disabled due to generic authentication failure. */
+ public static final int DISABLED_AUTHENTICATION_FAILURE_GENERIC = 2;
+ /** Separate DISABLED_AUTHENTICATION_FAILURE into DISABLED_AUTHENTICATION_FAILURE_GENERIC
+ * and DISABLED_AUTHENTICATION_FAILURE_CARRIER_SPECIFIC
+ * @deprecated Use the {@link #DISABLED_AUTHENTICATION_FAILURE_GENERIC} constant
+ * (which is the same value).
+ */
+ @Deprecated
+ public static final int DISABLED_AUTHENTICATION_FAILURE =
+ DISABLED_AUTHENTICATION_FAILURE_GENERIC;
+ /** This network is temporarily disabled because of multiple DHCP failure. */
public static final int DISABLED_DHCP_FAILURE = 3;
/** This network is temporarily disabled because it has no Internet access. */
public static final int DISABLED_NO_INTERNET_TEMPORARY = 4;
- /**
- * The starting index for network selection permanently disabled reasons.
- * @hide
- */
- public static final int PERMANENTLY_DISABLED_STARTING_INDEX = 5;
- /** This network is disabled due to absence of user credentials */
+ /** This network is permanently disabled due to absence of user credentials */
public static final int DISABLED_AUTHENTICATION_NO_CREDENTIALS = 5;
/**
* This network is permanently disabled because it has no Internet access and the user does
* not want to stay connected.
*/
public static final int DISABLED_NO_INTERNET_PERMANENT = 6;
- /** This network is disabled due to WifiManager disabling it explicitly. */
+ /** This network is permanently disabled due to WifiManager disabling it explicitly. */
public static final int DISABLED_BY_WIFI_MANAGER = 7;
- /** This network is disabled due to wrong password. */
+ /** This network is permanently disabled due to wrong password. */
public static final int DISABLED_BY_WRONG_PASSWORD = 8;
- /** This network is disabled because service is not subscribed. */
+ /** This network is permanently disabled because service is not subscribed. */
public static final int DISABLED_AUTHENTICATION_NO_SUBSCRIPTION = 9;
+ /** This network is disabled due to carrier specific EAP failure. */
+ public static final int DISABLED_AUTHENTICATION_FAILURE_CARRIER_SPECIFIC = 10;
/**
* All other disable reasons should be strictly less than this value.
* @hide
*/
- public static final int NETWORK_SELECTION_DISABLED_MAX = 10;
+ public static final int NETWORK_SELECTION_DISABLED_MAX = 11;
/**
* Get an integer that is equal to the maximum integer value of all the
@@ -1361,6 +1784,8 @@
/**
* Network Selection disable timeout for the error. After the timeout milliseconds,
* enable the network again.
+ * If this is set to Integer.MAX_VALUE, the network will be permanently disabled until
+ * the next time the user manually connects to it.
*/
public final int mDisableTimeoutMillis;
@@ -1455,6 +1880,18 @@
1,
Integer.MAX_VALUE));
+ reasons.append(DISABLED_AUTHENTICATION_FAILURE_GENERIC,
+ new DisableReasonInfo(
+ "NETWORK_SELECTION_DISABLED_AUTHENTICATION_FAILURE_GENERIC",
+ 5,
+ 5 * 60 * 1000));
+
+ reasons.append(DISABLED_AUTHENTICATION_FAILURE_CARRIER_SPECIFIC,
+ new DisableReasonInfo(
+ "NETWORK_SELECTION_DISABLED_AUTHENTICATION_FAILURE_CARRIER_SPECIFIC",
+ 1,
+ Integer.MAX_VALUE));
+
return reasons;
}
@@ -1529,6 +1966,11 @@
private String mConnectChoice;
/**
+ * The RSSI when the user made the connectChoice.
+ */
+ private int mConnectChoiceRssi;
+
+ /**
* Used to cache the temporary candidate during the network selection procedure. It will be
* kept updating once a new scan result has a higher score than current one
*/
@@ -1559,6 +2001,14 @@
private boolean mHasEverConnected;
/**
+ * Boolean indicating if captive portal has never been detected on this network.
+ *
+ * This should be true by default, for newly created WifiConfigurations until a captive
+ * portal is detected.
+ */
+ private boolean mHasNeverDetectedCaptivePortal = true;
+
+ /**
* set whether this network is visible in latest Qualified Network Selection
* @param seen value set to candidate
* @hide
@@ -1631,6 +2081,23 @@
mConnectChoice = newConnectChoice;
}
+ /**
+ * Associate a RSSI with the user connect choice network.
+ * @param rssi signal strength
+ * @hide
+ */
+ public void setConnectChoiceRssi(int rssi) {
+ mConnectChoiceRssi = rssi;
+ }
+
+ /**
+ * @return returns the RSSI of the last time the user made the connect choice.
+ * @hide
+ */
+ public int getConnectChoiceRssi() {
+ return mConnectChoiceRssi;
+ }
+
/** Get the current Quality network selection status as a String (for debugging). */
@NonNull
public String getNetworkStatusString() {
@@ -1647,6 +2114,19 @@
return mHasEverConnected;
}
+ /**
+ * Set whether a captive portal has never been detected on this network.
+ * @hide
+ */
+ public void setHasNeverDetectedCaptivePortal(boolean value) {
+ mHasNeverDetectedCaptivePortal = value;
+ }
+
+ /** @hide */
+ public boolean hasNeverDetectedCaptivePortal() {
+ return mHasNeverDetectedCaptivePortal;
+ }
+
/** @hide */
public NetworkSelectionStatus() {
// previously stored configs will not have this parameter, so we default to false.
@@ -1921,7 +2401,9 @@
setCandidate(source.getCandidate());
setCandidateScore(source.getCandidateScore());
setConnectChoice(source.getConnectChoice());
+ setConnectChoiceRssi(source.getConnectChoiceRssi());
setHasEverConnected(source.hasEverConnected());
+ setHasNeverDetectedCaptivePortal(source.hasNeverDetectedCaptivePortal());
}
/** @hide */
@@ -1937,10 +2419,12 @@
if (getConnectChoice() != null) {
dest.writeInt(CONNECT_CHOICE_EXISTS);
dest.writeString(getConnectChoice());
+ dest.writeInt(getConnectChoiceRssi());
} else {
dest.writeInt(CONNECT_CHOICE_NOT_EXISTS);
}
dest.writeInt(hasEverConnected() ? 1 : 0);
+ dest.writeInt(hasNeverDetectedCaptivePortal() ? 1 : 0);
}
/** @hide */
@@ -1955,10 +2439,12 @@
setNetworkSelectionBSSID(in.readString());
if (in.readInt() == CONNECT_CHOICE_EXISTS) {
setConnectChoice(in.readString());
+ setConnectChoiceRssi(in.readInt());
} else {
setConnectChoice(null);
}
setHasEverConnected(in.readInt() != 0);
+ setHasNeverDetectedCaptivePortal(in.readInt() != 0);
}
}
@@ -1983,27 +2469,42 @@
*/
@RecentFailureReason
private int mAssociationStatus = RECENT_FAILURE_NONE;
+ private long mLastUpdateTimeSinceBootMillis;
/**
* @param status the association status code for the recent failure
*/
- public void setAssociationStatus(@RecentFailureReason int status) {
+ public void setAssociationStatus(@RecentFailureReason int status,
+ long updateTimeSinceBootMs) {
mAssociationStatus = status;
+ mLastUpdateTimeSinceBootMillis = updateTimeSinceBootMs;
}
/**
* Sets the RecentFailure to NONE
*/
public void clear() {
mAssociationStatus = RECENT_FAILURE_NONE;
+ mLastUpdateTimeSinceBootMillis = 0;
}
/**
- * Get the recent failure code. One of {@link #RECENT_FAILURE_NONE} or
- * {@link #RECENT_FAILURE_AP_UNABLE_TO_HANDLE_NEW_STA}.
+ * Get the recent failure code. One of {@link #RECENT_FAILURE_NONE},
+ * {@link #RECENT_FAILURE_AP_UNABLE_TO_HANDLE_NEW_STA},
+ * {@link #RECENT_FAILURE_MBO_OCE_DISCONNECT},
+ * {@link #RECENT_FAILURE_REFUSED_TEMPORARILY},
+ * {@link #RECENT_FAILURE_POOR_CHANNEL_CONDITIONS}.
+ * {@link #RECENT_FAILURE_DISCONNECTION_AP_BUSY}
*/
@RecentFailureReason
public int getAssociationStatus() {
return mAssociationStatus;
}
+
+ /**
+ * Get the timestamp the failure status is last updated, in milliseconds since boot.
+ */
+ public long getLastUpdateTimeSinceBootMillis() {
+ return mLastUpdateTimeSinceBootMillis;
+ }
}
/**
@@ -2019,7 +2520,12 @@
@Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = "RECENT_FAILURE_", value = {
RECENT_FAILURE_NONE,
- RECENT_FAILURE_AP_UNABLE_TO_HANDLE_NEW_STA})
+ RECENT_FAILURE_AP_UNABLE_TO_HANDLE_NEW_STA,
+ RECENT_FAILURE_MBO_OCE_DISCONNECT,
+ RECENT_FAILURE_REFUSED_TEMPORARILY,
+ RECENT_FAILURE_POOR_CHANNEL_CONDITIONS,
+ RECENT_FAILURE_DISCONNECTION_AP_BUSY
+ })
public @interface RecentFailureReason {}
/**
@@ -2037,12 +2543,46 @@
public static final int RECENT_FAILURE_AP_UNABLE_TO_HANDLE_NEW_STA = 17;
/**
+ * This network recently disconnected as a result of MBO/OCE.
+ * @hide
+ */
+ @SystemApi
+ public static final int RECENT_FAILURE_MBO_OCE_DISCONNECT = 1001;
+
+ /**
+ * Failed to connect because the association is rejected by the AP.
+ * IEEE 802.11 association status code 30.
+ * @hide
+ */
+ @SystemApi
+ public static final int RECENT_FAILURE_REFUSED_TEMPORARILY = 1002;
+
+ /**
+ * Failed to connect because of excess frame loss and/or poor channel conditions.
+ * IEEE 802.11 association status code 34.
+ * @hide
+ */
+ @SystemApi
+ public static final int RECENT_FAILURE_POOR_CHANNEL_CONDITIONS = 1003;
+
+ /**
+ * Disconnected by the AP because the AP can't handle all the associated stations.
+ * IEEE 802.11 disconnection reason code 5.
+ * @hide
+ */
+ @SystemApi
+ public static final int RECENT_FAILURE_DISCONNECTION_AP_BUSY = 1004;
+
+ /**
* Get the failure reason for the most recent connection attempt, or
* {@link #RECENT_FAILURE_NONE} if there was no failure.
*
* Failure reasons include:
* {@link #RECENT_FAILURE_AP_UNABLE_TO_HANDLE_NEW_STA}
- *
+ * {@link #RECENT_FAILURE_MBO_OCE_DISCONNECT}
+ * {@link #RECENT_FAILURE_REFUSED_TEMPORARILY}
+ * {@link #RECENT_FAILURE_POOR_CHANNEL_CONDITIONS}
+ * {@link #RECENT_FAILURE_DISCONNECTION_AP_BUSY}
* @hide
*/
@RecentFailureReason
@@ -2103,6 +2643,9 @@
ephemeral = false;
osu = false;
trusted = true; // Networks are considered trusted by default.
+ oemPaid = false;
+ oemPrivate = false;
+ carrierMerged = false;
fromWifiNetworkSuggestion = false;
fromWifiNetworkSpecifier = false;
meteredHint = false;
@@ -2150,12 +2693,11 @@
*/
@UnsupportedAppUsage
public boolean isEnterprise() {
- return (allowedKeyManagement.get(KeyMgmt.WPA_EAP)
- || allowedKeyManagement.get(KeyMgmt.IEEE8021X)
- || allowedKeyManagement.get(KeyMgmt.SUITE_B_192)
- || allowedKeyManagement.get(KeyMgmt.WAPI_CERT))
+ boolean hasEnterpriseSecurityType = mSecurityParamsList.stream()
+ .anyMatch(params -> params.isEnterpriseSecurityType());
+ return (hasEnterpriseSecurityType
&& enterpriseConfig != null
- && enterpriseConfig.getEapMethod() != WifiEnterpriseConfig.Eap.NONE;
+ && enterpriseConfig.getEapMethod() != WifiEnterpriseConfig.Eap.NONE);
}
private static String logTimeOfDay(long millis) {
@@ -2208,9 +2750,13 @@
}
if (mNetworkSelectionStatus.getConnectChoice() != null) {
sbuf.append(" connect choice: ").append(mNetworkSelectionStatus.getConnectChoice());
+ sbuf.append(" connect choice rssi: ")
+ .append(mNetworkSelectionStatus.getConnectChoiceRssi());
}
sbuf.append(" hasEverConnected: ")
.append(mNetworkSelectionStatus.hasEverConnected()).append("\n");
+ sbuf.append(" hasNeverDetectedCaptivePortal: ")
+ .append(mNetworkSelectionStatus.hasNeverDetectedCaptivePortal()).append("\n");
if (this.numAssociation > 0) {
sbuf.append(" numAssociation ").append(this.numAssociation).append("\n");
@@ -2223,13 +2769,16 @@
if (this.ephemeral) sbuf.append(" ephemeral");
if (this.osu) sbuf.append(" osu");
if (this.trusted) sbuf.append(" trusted");
+ if (this.oemPaid) sbuf.append(" oemPaid");
+ if (this.oemPrivate) sbuf.append(" oemPrivate");
+ if (this.carrierMerged) sbuf.append(" carrierMerged");
if (this.fromWifiNetworkSuggestion) sbuf.append(" fromWifiNetworkSuggestion");
if (this.fromWifiNetworkSpecifier) sbuf.append(" fromWifiNetworkSpecifier");
if (this.meteredHint) sbuf.append(" meteredHint");
if (this.useExternalScores) sbuf.append(" useExternalScores");
- if (this.validatedInternetAccess || this.ephemeral || this.trusted
- || this.fromWifiNetworkSuggestion || this.fromWifiNetworkSpecifier
- || this.meteredHint || this.useExternalScores) {
+ if (this.validatedInternetAccess || this.ephemeral || this.trusted || this.oemPaid
+ || this.oemPrivate || this.carrierMerged || this.fromWifiNetworkSuggestion
+ || this.fromWifiNetworkSpecifier || this.meteredHint || this.useExternalScores) {
sbuf.append("\n");
}
if (this.meteredOverride != METERED_OVERRIDE_NONE) {
@@ -2240,6 +2789,9 @@
sbuf.append(" randomizedMacExpirationTimeMs: ")
.append(randomizedMacExpirationTimeMs == 0 ? "<none>"
: logTimeOfDay(randomizedMacExpirationTimeMs)).append("\n");
+ sbuf.append(" randomizedMacLastModifiedTimeMs: ")
+ .append(randomizedMacLastModifiedTimeMs == 0 ? "<none>"
+ : logTimeOfDay(randomizedMacLastModifiedTimeMs)).append("\n");
sbuf.append(" KeyMgmt:");
for (int k = 0; k < this.allowedKeyManagement.size(); k++) {
if (this.allowedKeyManagement.get(k)) {
@@ -2327,6 +2879,10 @@
sbuf.append('*');
}
+ sbuf.append("\nSecurityParams List:\n");
+ mSecurityParamsList.stream()
+ .forEach(params -> sbuf.append(params.toString()));
+
sbuf.append("\nEnterprise config:\n");
sbuf.append(enterpriseConfig);
@@ -2373,7 +2929,8 @@
}
}
sbuf.append("recentFailure: ").append("Association Rejection code: ")
- .append(recentFailure.getAssociationStatus()).append("\n");
+ .append(recentFailure.getAssociationStatus()).append(", last update time: ")
+ .append(recentFailure.getLastUpdateTimeSinceBootMillis()).append("\n");
return sbuf.toString();
}
@@ -2491,7 +3048,18 @@
@KeyMgmt.KeyMgmtScheme
public int getAuthType() {
if (allowedKeyManagement.cardinality() > 1) {
- throw new IllegalStateException("More than one auth type set");
+ if (allowedKeyManagement.get(KeyMgmt.WPA_EAP)) {
+ if (allowedKeyManagement.cardinality() == 2
+ && allowedKeyManagement.get(KeyMgmt.IEEE8021X)) {
+ return KeyMgmt.WPA_EAP;
+ }
+ if (allowedKeyManagement.cardinality() == 3
+ && allowedKeyManagement.get(KeyMgmt.IEEE8021X)
+ && allowedKeyManagement.get(KeyMgmt.SUITE_B_192)) {
+ return KeyMgmt.SUITE_B_192;
+ }
+ }
+ throw new IllegalStateException("Invalid auth type set: " + allowedKeyManagement);
}
if (allowedKeyManagement.get(KeyMgmt.WPA_PSK)) {
return KeyMgmt.WPA_PSK;
@@ -2536,6 +3104,26 @@
return key;
}
+ /**
+ * Get a unique key which represent this Wi-Fi network. If two profiles are for
+ * the same Wi-Fi network, but from different provider, they would have the same key.
+ * @hide
+ */
+ public String getNetworkKey() {
+ // Passpoint ephemeral networks have their unique identifier set. Return it as is to be
+ // able to match internally.
+ if (mPasspointUniqueId != null) {
+ return mPasspointUniqueId;
+ }
+
+ String key = SSID + getDefaultSecurityType();
+ if (!shared) {
+ key += "-" + UserHandle.getUserHandleForUid(creatorUid).getIdentifier();
+ }
+
+ return key;
+ }
+
/** @hide
* return the SSID + security type in String format.
*/
@@ -2743,6 +3331,7 @@
allowedGroupCiphers = (BitSet) source.allowedGroupCiphers.clone();
allowedGroupManagementCiphers = (BitSet) source.allowedGroupManagementCiphers.clone();
allowedSuiteBCiphers = (BitSet) source.allowedSuiteBCiphers.clone();
+ mSecurityParamsList = new ArrayList(source.mSecurityParamsList);
enterpriseConfig = new WifiEnterpriseConfig(source.enterpriseConfig);
defaultGwMacAddress = source.defaultGwMacAddress;
@@ -2759,6 +3348,9 @@
ephemeral = source.ephemeral;
osu = source.osu;
trusted = source.trusted;
+ oemPaid = source.oemPaid;
+ oemPrivate = source.oemPrivate;
+ carrierMerged = source.carrierMerged;
fromWifiNetworkSuggestion = source.fromWifiNetworkSuggestion;
fromWifiNetworkSpecifier = source.fromWifiNetworkSpecifier;
meteredHint = source.meteredHint;
@@ -2781,13 +3373,16 @@
numNoInternetAccessReports = source.numNoInternetAccessReports;
noInternetAccessExpected = source.noInternetAccessExpected;
shared = source.shared;
- recentFailure.setAssociationStatus(source.recentFailure.getAssociationStatus());
+ recentFailure.setAssociationStatus(source.recentFailure.getAssociationStatus(),
+ source.recentFailure.getLastUpdateTimeSinceBootMillis());
mRandomizedMacAddress = source.mRandomizedMacAddress;
macRandomizationSetting = source.macRandomizationSetting;
randomizedMacExpirationTimeMs = source.randomizedMacExpirationTimeMs;
+ randomizedMacLastModifiedTimeMs = source.randomizedMacLastModifiedTimeMs;
requirePmf = source.requirePmf;
updateIdentifier = source.updateIdentifier;
carrierId = source.carrierId;
+ subscriptionId = source.subscriptionId;
mPasspointUniqueId = source.mPasspointUniqueId;
}
}
@@ -2827,6 +3422,10 @@
writeBitSet(dest, allowedGroupManagementCiphers);
writeBitSet(dest, allowedSuiteBCiphers);
+ dest.writeInt(mSecurityParamsList.size());
+ mSecurityParamsList.stream()
+ .forEach(params -> params.writeToParcel(dest, flags));
+
dest.writeParcelable(enterpriseConfig, flags);
dest.writeParcelable(mIpConfiguration, flags);
@@ -2836,6 +3435,9 @@
dest.writeInt(isLegacyPasspointConfig ? 1 : 0);
dest.writeInt(ephemeral ? 1 : 0);
dest.writeInt(trusted ? 1 : 0);
+ dest.writeInt(oemPaid ? 1 : 0);
+ dest.writeInt(oemPrivate ? 1 : 0);
+ dest.writeInt(carrierMerged ? 1 : 0);
dest.writeInt(fromWifiNetworkSuggestion ? 1 : 0);
dest.writeInt(fromWifiNetworkSpecifier ? 1 : 0);
dest.writeInt(meteredHint ? 1 : 0);
@@ -2855,12 +3457,15 @@
dest.writeInt(shared ? 1 : 0);
dest.writeString(mPasspointManagementObjectTree);
dest.writeInt(recentFailure.getAssociationStatus());
+ dest.writeLong(recentFailure.getLastUpdateTimeSinceBootMillis());
dest.writeParcelable(mRandomizedMacAddress, flags);
dest.writeInt(macRandomizationSetting);
dest.writeInt(osu ? 1 : 0);
dest.writeLong(randomizedMacExpirationTimeMs);
+ dest.writeLong(randomizedMacLastModifiedTimeMs);
dest.writeInt(carrierId);
dest.writeString(mPasspointUniqueId);
+ dest.writeInt(subscriptionId);
}
/** Implement the Parcelable interface {@hide} */
@@ -2902,6 +3507,11 @@
config.allowedGroupManagementCiphers = readBitSet(in);
config.allowedSuiteBCiphers = readBitSet(in);
+ int numSecurityParams = in.readInt();
+ for (int i = 0; i < numSecurityParams; i++) {
+ config.mSecurityParamsList.add(SecurityParams.createFromParcel(in));
+ }
+
config.enterpriseConfig = in.readParcelable(null);
config.setIpConfiguration(in.readParcelable(null));
config.dhcpServer = in.readString();
@@ -2910,6 +3520,9 @@
config.isLegacyPasspointConfig = in.readInt() != 0;
config.ephemeral = in.readInt() != 0;
config.trusted = in.readInt() != 0;
+ config.oemPaid = in.readInt() != 0;
+ config.oemPrivate = in.readInt() != 0;
+ config.carrierMerged = in.readInt() != 0;
config.fromWifiNetworkSuggestion = in.readInt() != 0;
config.fromWifiNetworkSpecifier = in.readInt() != 0;
config.meteredHint = in.readInt() != 0;
@@ -2928,13 +3541,15 @@
config.noInternetAccessExpected = in.readInt() != 0;
config.shared = in.readInt() != 0;
config.mPasspointManagementObjectTree = in.readString();
- config.recentFailure.setAssociationStatus(in.readInt());
+ config.recentFailure.setAssociationStatus(in.readInt(), in.readLong());
config.mRandomizedMacAddress = in.readParcelable(null);
config.macRandomizationSetting = in.readInt();
config.osu = in.readInt() != 0;
config.randomizedMacExpirationTimeMs = in.readLong();
+ config.randomizedMacLastModifiedTimeMs = in.readLong();
config.carrierId = in.readInt();
config.mPasspointUniqueId = in.readString();
+ config.subscriptionId = in.readInt();
return config;
}
@@ -2979,9 +3594,66 @@
* @hide
*/
public boolean needsPreSharedKey() {
- return allowedKeyManagement.get(KeyMgmt.WPA_PSK)
- || allowedKeyManagement.get(KeyMgmt.SAE)
- || allowedKeyManagement.get(KeyMgmt.WAPI_PSK);
+ return mSecurityParamsList.stream()
+ .anyMatch(params -> params.isSecurityType(SECURITY_TYPE_PSK)
+ || params.isSecurityType(SECURITY_TYPE_SAE)
+ || params.isSecurityType(SECURITY_TYPE_WAPI_PSK));
+ }
+
+ /**
+ * Get a unique key which represent this Wi-Fi configuration profile. If two profiles are for
+ * the same Wi-Fi network, but from different providers (apps, carriers, or data subscriptions),
+ * they would have different keys.
+ * @return a unique key which represent this profile.
+ * @hide
+ */
+ @SystemApi
+ @NonNull public String getProfileKey() {
+ if (mPasspointUniqueId != null) {
+ return mPasspointUniqueId;
+ }
+
+ String key = SSID + getDefaultSecurityType();
+ if (!shared) {
+ key += "-" + UserHandle.getUserHandleForUid(creatorUid).getIdentifier();
+ }
+ if (fromWifiNetworkSuggestion) {
+ key += "_" + creatorName + "-" + carrierId + "-" + subscriptionId;
+ }
+
+ return key;
+ }
+
+ /**
+ * Get the default security type string.
+ * @hide
+ */
+ public String getDefaultSecurityType() {
+ String key;
+ if (allowedKeyManagement.get(KeyMgmt.WPA_PSK)) {
+ key = KeyMgmt.strings[KeyMgmt.WPA_PSK];
+ } else if (allowedKeyManagement.get(KeyMgmt.WPA_EAP)
+ || allowedKeyManagement.get(KeyMgmt.IEEE8021X)) {
+ key = KeyMgmt.strings[KeyMgmt.WPA_EAP];
+ } else if (wepTxKeyIndex >= 0 && wepTxKeyIndex < wepKeys.length
+ && wepKeys[wepTxKeyIndex] != null) {
+ key = "WEP";
+ } else if (allowedKeyManagement.get(KeyMgmt.OWE)) {
+ key = KeyMgmt.strings[KeyMgmt.OWE];
+ } else if (allowedKeyManagement.get(KeyMgmt.SAE)) {
+ key = KeyMgmt.strings[KeyMgmt.SAE];
+ } else if (allowedKeyManagement.get(KeyMgmt.SUITE_B_192)) {
+ key = KeyMgmt.strings[KeyMgmt.SUITE_B_192];
+ } else if (allowedKeyManagement.get(KeyMgmt.WAPI_PSK)) {
+ key = KeyMgmt.strings[KeyMgmt.WAPI_PSK];
+ } else if (allowedKeyManagement.get(KeyMgmt.WAPI_CERT)) {
+ key = KeyMgmt.strings[KeyMgmt.WAPI_CERT];
+ } else if (allowedKeyManagement.get(KeyMgmt.OSEN)) {
+ key = KeyMgmt.strings[KeyMgmt.OSEN];
+ } else {
+ key = KeyMgmt.strings[KeyMgmt.NONE];
+ }
+ return key;
}
}
diff --git a/framework/java/android/net/wifi/WifiEnterpriseConfig.java b/framework/java/android/net/wifi/WifiEnterpriseConfig.java
index 90edc45..e127ea9 100644
--- a/framework/java/android/net/wifi/WifiEnterpriseConfig.java
+++ b/framework/java/android/net/wifi/WifiEnterpriseConfig.java
@@ -1335,6 +1335,16 @@
}
/**
+ * Initialize the value of the app installed device key and cert flag.
+ *
+ * @param isAppInstalledDeviceKeyAndCert true or false
+ * @hide
+ */
+ public void initIsAppInstalledDeviceKeyAndCert(boolean isAppInstalledDeviceKeyAndCert) {
+ mIsAppInstalledDeviceKeyAndCert = isAppInstalledDeviceKeyAndCert;
+ }
+
+ /**
* Check if CA certificate was installed by an app, or manually (not by an app). If true,
* CA certificate will be removed from key storage when this network is removed. If not,
* then certificates and keys remain persistent until the user manually removes them.
@@ -1348,6 +1358,16 @@
}
/**
+ * Initialize the value of the app installed root CA cert flag.
+ *
+ * @param isAppInstalledCaCert true or false
+ * @hide
+ */
+ public void initIsAppInstalledCaCert(boolean isAppInstalledCaCert) {
+ mIsAppInstalledCaCert = isAppInstalledCaCert;
+ }
+
+ /**
* Set the OCSP type.
* @param ocsp is one of {@link ##OCSP_NONE}, {@link #OCSP_REQUEST_CERT_STATUS},
* {@link #OCSP_REQUIRE_CERT_STATUS} or
diff --git a/framework/java/android/net/wifi/WifiInfo.java b/framework/java/android/net/wifi/WifiInfo.java
index 5388367..6bd1ce5 100644
--- a/framework/java/android/net/wifi/WifiInfo.java
+++ b/framework/java/android/net/wifi/WifiInfo.java
@@ -25,8 +25,10 @@
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
+import android.telephony.SubscriptionManager;
import android.text.TextUtils;
+import com.android.modules.utils.build.SdkLevel;
import com.android.net.module.util.Inet4AddressUtils;
import java.net.Inet4Address;
@@ -159,6 +161,21 @@
private boolean mTrusted;
/**
+ * Whether the network is oem paid or not.
+ */
+ private boolean mOemPaid;
+
+ /**
+ * Whether the network is oem private or not.
+ */
+ private boolean mOemPrivate;
+
+ /**
+ * Whether the network is a carrier merged network.
+ */
+ private boolean mCarrierMerged;
+
+ /**
* OSU (Online Sign Up) AP for Passpoint R2.
*/
private boolean mOsuAp;
@@ -180,6 +197,11 @@
private String mRequestingPackageName;
/**
+ * Identify which Telephony subscription provides this network.
+ */
+ private int mSubscriptionId;
+
+ /**
* Running total count of lost (not ACKed) transmitted unicast data packets.
* @hide
*/
@@ -305,6 +327,7 @@
mRssi = INVALID_RSSI;
mLinkSpeed = LINK_SPEED_UNKNOWN;
mFrequency = -1;
+ mSubscriptionId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
}
/** @hide */
@@ -322,11 +345,16 @@
setFrequency(-1);
setMeteredHint(false);
setEphemeral(false);
+ setTrusted(false);
+ setOemPaid(false);
+ setOemPrivate(false);
+ setCarrierMerged(false);
setOsuAp(false);
setRequestingPackageName(null);
setFQDN(null);
setProviderFriendlyName(null);
setPasspointUniqueId(null);
+ setSubscriptionId(SubscriptionManager.INVALID_SUBSCRIPTION_ID);
txBad = 0;
txSuccess = 0;
rxSuccess = 0;
@@ -358,11 +386,15 @@
mMeteredHint = source.mMeteredHint;
mEphemeral = source.mEphemeral;
mTrusted = source.mTrusted;
+ mOemPaid = source.mOemPaid;
+ mOemPrivate = source.mOemPrivate;
+ mCarrierMerged = source.mCarrierMerged;
mRequestingPackageName =
source.mRequestingPackageName;
mOsuAp = source.mOsuAp;
mFqdn = source.mFqdn;
mProviderFriendlyName = source.mProviderFriendlyName;
+ mSubscriptionId = source.mSubscriptionId;
txBad = source.txBad;
txRetries = source.txRetries;
txSuccess = source.txSuccess;
@@ -716,12 +748,74 @@
mTrusted = trusted;
}
- /** {@hide} */
+ /**
+ * Returns true if the current Wifi network is a trusted network, false otherwise.
+ * @see WifiNetworkSuggestion.Builder#setUntrusted(boolean).
+ * {@hide}
+ */
+ @SystemApi
public boolean isTrusted() {
return mTrusted;
}
/** {@hide} */
+ public void setOemPaid(boolean oemPaid) {
+ mOemPaid = oemPaid;
+ }
+
+ /**
+ * Returns true if the current Wifi network is an oem paid network, false otherwise.
+ * @see WifiNetworkSuggestion.Builder#setOemPaid(boolean).
+ * {@hide}
+ */
+ @SystemApi
+ public boolean isOemPaid() {
+ if (!SdkLevel.isAtLeastS()) {
+ throw new UnsupportedOperationException();
+ }
+ return mOemPaid;
+ }
+
+ /** {@hide} */
+ public void setOemPrivate(boolean oemPrivate) {
+ mOemPrivate = oemPrivate;
+ }
+
+ /**
+ * Returns true if the current Wifi network is an oem private network, false otherwise.
+ * @see WifiNetworkSuggestion.Builder#setOemPrivate(boolean).
+ * {@hide}
+ */
+ @SystemApi
+ public boolean isOemPrivate() {
+ if (!SdkLevel.isAtLeastS()) {
+ throw new UnsupportedOperationException();
+ }
+ return mOemPrivate;
+ }
+
+ /**
+ * {@hide}
+ */
+ public void setCarrierMerged(boolean carrierMerged) {
+ mCarrierMerged = carrierMerged;
+ }
+
+ /**
+ * Returns true if the current Wifi network is a carrier merged network, false otherwise.
+ * @see WifiNetworkSuggestion.Builder#setCarrierMerged(boolean).
+ * {@hide}
+ */
+ @SystemApi
+ public boolean isCarrierMerged() {
+ if (!SdkLevel.isAtLeastS()) {
+ throw new UnsupportedOperationException();
+ }
+ return mCarrierMerged;
+ }
+
+
+ /** {@hide} */
public void setOsuAp(boolean osuAp) {
mOsuAp = osuAp;
}
@@ -789,6 +883,28 @@
return mRequestingPackageName;
}
+ /** {@hide} */
+ public void setSubscriptionId(int subId) {
+ mSubscriptionId = subId;
+ }
+
+ /**
+ * If this network is provisioned by a carrier, returns subscription Id corresponding to the
+ * associated SIM on the device. If this network is not provisioned by a carrier, returns
+ * {@link android.telephony.SubscriptionManager#INVALID_SUBSCRIPTION_ID}
+ *
+ * @see WifiNetworkSuggestion.Builder#setSubscriptionId(int)
+ * @see android.telephony.SubscriptionInfo#getSubscriptionId()
+ * {@hide}
+ */
+ @SystemApi
+ public int getSubscriptionId() {
+ if (!SdkLevel.isAtLeastS()) {
+ throw new UnsupportedOperationException();
+ }
+ return mSubscriptionId;
+ }
+
/** @hide */
@UnsupportedAppUsage
@@ -958,6 +1074,9 @@
dest.writeInt(mMeteredHint ? 1 : 0);
dest.writeInt(mEphemeral ? 1 : 0);
dest.writeInt(mTrusted ? 1 : 0);
+ dest.writeInt(mOemPaid ? 1 : 0);
+ dest.writeInt(mOemPrivate ? 1 : 0);
+ dest.writeInt(mCarrierMerged ? 1 : 0);
dest.writeInt(score);
dest.writeLong(txSuccess);
dest.writeDouble(mSuccessfulTxPacketsPerSecond);
@@ -976,6 +1095,7 @@
dest.writeInt(mMaxSupportedTxLinkSpeed);
dest.writeInt(mMaxSupportedRxLinkSpeed);
dest.writeString(mPasspointUniqueId);
+ dest.writeInt(mSubscriptionId);
}
/** Implement the Parcelable interface {@hide} */
@@ -1003,6 +1123,9 @@
info.mMeteredHint = in.readInt() != 0;
info.mEphemeral = in.readInt() != 0;
info.mTrusted = in.readInt() != 0;
+ info.mOemPaid = in.readInt() != 0;
+ info.mOemPrivate = in.readInt() != 0;
+ info.mCarrierMerged = in.readInt() != 0;
info.score = in.readInt();
info.txSuccess = in.readLong();
info.mSuccessfulTxPacketsPerSecond = in.readDouble();
@@ -1021,6 +1144,7 @@
info.mMaxSupportedTxLinkSpeed = in.readInt();
info.mMaxSupportedRxLinkSpeed = in.readInt();
info.mPasspointUniqueId = in.readString();
+ info.mSubscriptionId = in.readInt();
return info;
}
diff --git a/framework/java/android/net/wifi/WifiManager.java b/framework/java/android/net/wifi/WifiManager.java
index ccf8a80..5618ee8 100644
--- a/framework/java/android/net/wifi/WifiManager.java
+++ b/framework/java/android/net/wifi/WifiManager.java
@@ -34,7 +34,6 @@
import android.app.ActivityManager;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
-import android.content.pm.ParceledListSlice;
import android.net.ConnectivityManager;
import android.net.DhcpInfo;
import android.net.MacAddress;
@@ -53,6 +52,8 @@
import android.os.RemoteException;
import android.os.WorkSource;
import android.os.connectivity.WifiActivityEnergyInfo;
+import android.telephony.SubscriptionInfo;
+import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.CloseGuard;
import android.util.Log;
@@ -61,6 +62,8 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.modules.utils.ParceledListSlice;
+import com.android.modules.utils.build.SdkLevel;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -70,6 +73,7 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -263,6 +267,44 @@
public @interface SuggestionConnectionStatusCode {}
/**
+ * Status code if suggestion approval status is unknown, an App which hasn't made any
+ * suggestions will get this code.
+ */
+ public static final int STATUS_SUGGESTION_APPROVAL_UNKNOWN = 0;
+
+ /**
+ * Status code if the calling app is still pending user approval for suggestions.
+ */
+ public static final int STATUS_SUGGESTION_APPROVAL_PENDING = 1;
+
+ /**
+ * Status code if the calling app got the user approval for suggestions.
+ */
+ public static final int STATUS_SUGGESTION_APPROVAL_APPROVED_BY_USER = 2;
+
+ /**
+ * Status code if the calling app suggestions were rejected by the user.
+ */
+ public static final int STATUS_SUGGESTION_APPROVAL_REJECTED_BY_USER = 3;
+
+ /**
+ * Status code if the calling app was approved by virtue of being a carrier privileged app.
+ * @see TelephonyManager#hasCarrierPrivileges().
+ */
+ public static final int STATUS_SUGGESTION_APPROVAL_APPROVED_BY_CARRIER_PRIVILEGE = 4;
+
+ /** @hide */
+ @IntDef(prefix = {"STATUS_SUGGESTION_APPROVAL_"},
+ value = {STATUS_SUGGESTION_APPROVAL_UNKNOWN,
+ STATUS_SUGGESTION_APPROVAL_PENDING,
+ STATUS_SUGGESTION_APPROVAL_APPROVED_BY_USER,
+ STATUS_SUGGESTION_APPROVAL_REJECTED_BY_USER,
+ STATUS_SUGGESTION_APPROVAL_APPROVED_BY_CARRIER_PRIVILEGE
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface SuggestionUserApprovalStatus {}
+
+ /**
* Broadcast intent action indicating whether Wi-Fi scanning is currently available.
* Available extras:
* - {@link #EXTRA_SCAN_AVAILABLE}
@@ -931,9 +973,11 @@
* This can be as a result of adding/updating/deleting a network.
* <br />
* {@link #EXTRA_CHANGE_REASON} contains whether the configuration was added/changed/removed.
- * {@link #EXTRA_WIFI_CONFIGURATION} is never set starting in Android 11.
+ * {@link #EXTRA_WIFI_CONFIGURATION} is never set beginning in
+ * {@link android.os.Build.VERSION_CODES#R}.
* {@link #EXTRA_MULTIPLE_NETWORKS_CHANGED} is set for backwards compatibility reasons, but
- * its value is always true, even if only a single network changed.
+ * its value is always true beginning in {@link android.os.Build.VERSION_CODES#R}, even if only
+ * a single network changed.
* <br />
* The {@link android.Manifest.permission#ACCESS_WIFI_STATE ACCESS_WIFI_STATE} permission is
* required to receive this broadcast.
@@ -947,17 +991,22 @@
* The lookup key for a {@link android.net.wifi.WifiConfiguration} object representing
* the changed Wi-Fi configuration when the {@link #CONFIGURED_NETWORKS_CHANGED_ACTION}
* broadcast is sent.
- * Note: this extra is never set starting in Android 11.
+ * @deprecated This extra is never set beginning in {@link android.os.Build.VERSION_CODES#R},
+ * regardless of the target SDK version. Use {@link #getConfiguredNetworks} to get the full list
+ * of configured networks.
* @hide
*/
+ @Deprecated
@SystemApi
public static final String EXTRA_WIFI_CONFIGURATION = "wifiConfiguration";
/**
* Multiple network configurations have changed.
* @see #CONFIGURED_NETWORKS_CHANGED_ACTION
- * Note: this extra is always true starting in Android 11.
+ * @deprecated This extra's value is always true beginning in
+ * {@link android.os.Build.VERSION_CODES#R}, regardless of the target SDK version.
* @hide
*/
+ @Deprecated
@SystemApi
public static final String EXTRA_MULTIPLE_NETWORKS_CHANGED = "multipleChanges";
/**
@@ -1053,9 +1102,6 @@
/**
* Broadcast intent action indicating that the link configuration changed on wifi.
- * <br />Included Extras:
- * <br />{@link #EXTRA_LINK_PROPERTIES}: may not be set starting in Android 11. Check for
- * <br /> null before reading its value.
* <br /> No permissions are required to listen to this broadcast.
* @hide
*/
@@ -1072,11 +1118,11 @@
*
* Retrieve with {@link android.content.Intent#getParcelableExtra(String)}.
*
- * Note: this extra may not be set starting in Android 11. Check for null before reading its
- * value.
+ * @deprecated this extra is no longer populated.
*
* @hide
*/
+ @Deprecated
@SystemApi
public static final String EXTRA_LINK_PROPERTIES = "android.net.wifi.extra.LINK_PROPERTIES";
@@ -1444,7 +1490,7 @@
new ArrayList<>(results.keySet()));
for (WifiConfiguration configuration : wifiConfigurations) {
Map<Integer, List<ScanResult>> scanResultsPerNetworkType =
- results.get(configuration.getKey());
+ results.get(configuration.getProfileKey());
if (scanResultsPerNetworkType != null) {
configs.add(Pair.create(configuration, scanResultsPerNetworkType));
}
@@ -2005,6 +2051,26 @@
}
/**
+ * Get the Suggestion approval status of the calling app. When an app makes suggestions using
+ * the {@link #addNetworkSuggestions(List)} API they may trigger a user approval flow. This API
+ * provides the current approval status.
+ *
+ * @return Status code for the user approval. One of the STATUS_SUGGESTION_APPROVAL_ values.
+ * @throws {@link SecurityException} if the caller is missing required permissions.
+ */
+ @RequiresPermission(ACCESS_WIFI_STATE)
+ public @SuggestionUserApprovalStatus int getNetworkSuggestionUserApprovalStatus() {
+ if (!SdkLevel.isAtLeastS()) {
+ throw new UnsupportedOperationException();
+ }
+ try {
+ return mService.getNetworkSuggestionUserApprovalStatus(mContext.getOpPackageName());
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
+ }
+
+ /**
* Add or update a Passpoint configuration. The configuration provides a credential
* for connecting to Passpoint networks that are operated by the Passpoint
* service provider specified in the configuration.
@@ -2123,22 +2189,6 @@
}
/**
- * 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
- * @hide
- *
- * TODO (140167680): This needs to be removed, the implementation is empty!
- */
- public void deauthenticateNetwork(long holdoff, boolean ess) {
- try {
- mService.deauthenticateNetwork(holdoff, ess);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
* Remove the specified network from the list of configured networks.
* This may result in the asynchronous delivery of state change
* events.
@@ -2427,6 +2477,8 @@
public static final long WIFI_FEATURE_OCE = 0x1000000000L; // OCE Support
/** @hide */
public static final long WIFI_FEATURE_WAPI = 0x2000000000L; // WAPI
+ /** @hide */
+ public static final long WIFI_FEATURE_INFRA_60G = 0x4000000000L; // 60 GHz Band Support
/** @hide */
public static final long WIFI_FEATURE_FILS_SHA256 = 0x4000000000L; // FILS-SHA256
@@ -2434,6 +2486,15 @@
/** @hide */
public static final long WIFI_FEATURE_FILS_SHA384 = 0x8000000000L; // FILS-SHA384
+ /** @hide */
+ public static final long WIFI_FEATURE_SAE_PK = 0x10000000000L; // SAE-PK
+
+ /** @hide */
+ public static final long WIFI_FEATURE_STA_BRIDGED_AP = 0x20000000000L; // STA + Bridged AP
+
+ /** @hide */
+ public static final long WIFI_FEATURE_BRIDGED_AP = 0x40000000000L; // Bridged AP
+
private long getSupportedFeatures() {
try {
return mService.getSupportedFeatures();
@@ -2497,6 +2558,18 @@
}
/**
+ * Query whether the device supports 2 or more concurrent stations (STA) or not.
+ *
+ * @return true if this device supports multiple STA concurrency, false otherwise.
+ */
+ public boolean isMultiStaConcurrencySupported() {
+ if (!SdkLevel.isAtLeastS()) {
+ throw new UnsupportedOperationException();
+ }
+ return isFeatureSupported(WIFI_FEATURE_ADDITIONAL_STA);
+ }
+
+ /**
* @deprecated Please use {@link android.content.pm.PackageManager#hasSystemFeature(String)}
* with {@link android.content.pm.PackageManager#FEATURE_WIFI_RTT} and
* {@link android.content.pm.PackageManager#FEATURE_WIFI_AWARE}.
@@ -2529,14 +2602,6 @@
}
/**
- * @return true if this adapter supports multiple simultaneous connections
- * @hide
- */
- public boolean isAdditionalStaSupported() {
- return isFeatureSupported(WIFI_FEATURE_ADDITIONAL_STA);
- }
-
- /**
* @return true if this adapter supports Tunnel Directed Link Setup
*/
public boolean isTdlsSupported() {
@@ -2589,6 +2654,21 @@
}
/**
+ * Check if the chipset supports the 60GHz frequency band.
+ *
+ * @return {@code true} if supported, {@code false} otherwise.
+ * @hide
+ */
+ @SystemApi
+ public boolean is60GHzBandSupported() {
+ try {
+ return mService.is60GHzBandSupported();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Check if the chipset supports 6GHz band.
* @return {@code true} if supported, {@code false} otherwise.
*/
@@ -2615,6 +2695,40 @@
}
/**
+ * Query whether the device supports Station (STA) + Bridged access point (AP)
+ * concurrency or not.
+ *
+ * The bridged AP support means that the device supports AP + AP concurrency with the 2 APs
+ * bridged together.
+ *
+ * See {@link SoftApConfiguration.Builder#setBands(int[])}
+ * or {@link SoftApConfiguration.Builder#setChannels(SparseIntArray)} to configure bridged AP
+ * when the bridged AP supported.
+ *
+ * @return true if this device supports STA + bridged AP concurrency, false otherwise.
+ */
+ public boolean isStaBridgedApConcurrencySupported() {
+ return isFeatureSupported(WIFI_FEATURE_STA_BRIDGED_AP);
+ }
+
+ /**
+ * Query whether the device supports Bridged Access point (AP) concurrency or not.
+ *
+ * The bridged AP support means that the device supports AP + AP concurrency with the 2 APs
+ * bridged together.
+ *
+ * See {@link SoftApConfiguration.Builder#setBands(int[])}
+ * or {@link SoftApConfiguration.Builder#setChannels(SparseIntArray)} to configure bridged AP
+ * when the bridged AP supported.
+ *
+ * @return true if this device supports bridged AP concurrency, false otherwise.
+ */
+ public boolean isBridgedApConcurrencySupported() {
+ return isFeatureSupported(WIFI_FEATURE_BRIDGED_AP);
+ }
+
+
+ /**
* Interface for Wi-Fi activity energy info listener. Should be implemented by applications and
* set when calling {@link WifiManager#getWifiActivityEnergyInfoAsync}.
*
@@ -2822,7 +2936,7 @@
@RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
public void setScanAlwaysAvailable(boolean isAvailable) {
try {
- mService.setScanAlwaysAvailable(isAvailable);
+ mService.setScanAlwaysAvailable(isAvailable, mContext.getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -2927,6 +3041,37 @@
}
/**
+ * Restart the Wi-Fi subsystem.
+ *
+ * Restarts the Wi-Fi subsystem - effectively disabling it and re-enabling it. All existing
+ * Access Point (AP) associations are torn down, all Soft APs are disabled, Wi-Fi Direct and
+ * Wi-Fi Aware are disabled.
+ *
+ * The state of the system after restart is not guaranteed to match its state before the API is
+ * called - for instance the device may associate to a different Access Point (AP), and tethered
+ * hotspots may or may not be restored.
+ *
+ * @param reason If non-null, requests a bug report and attaches the reason string to it. A bug
+ * report may still not be generated based on framework criteria - for instance,
+ * build type or throttling. The WiFi subsystem is restarted whether or not a bug
+ * report is requested or generated.
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.NETWORK_AIRPLANE_MODE)
+ public void restartWifiSubsystem(@Nullable String reason) {
+ if (!SdkLevel.isAtLeastS()) {
+ throw new UnsupportedOperationException();
+ }
+ try {
+ mService.restartWifiSubsystem(reason);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Gets the Wi-Fi enabled state.
* @return One of {@link #WIFI_STATE_DISABLED},
* {@link #WIFI_STATE_DISABLING}, {@link #WIFI_STATE_ENABLED},
@@ -3038,6 +3183,251 @@
}
}
+ /* Wi-Fi/Cellular Coex */
+
+ /**
+ * Mandatory coex restriction flag for Wi-Fi Direct.
+ *
+ * @see #setCoexUnsafeChannels(Set, int)
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int COEX_RESTRICTION_WIFI_DIRECT = 0x1 << 0;
+
+ /**
+ * Mandatory coex restriction flag for SoftAP
+ *
+ * @see #setCoexUnsafeChannels(Set, int)
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int COEX_RESTRICTION_SOFTAP = 0x1 << 1;
+
+ /**
+ * Mandatory coex restriction flag for Wi-Fi Aware.
+ *
+ * @see #setCoexUnsafeChannels(Set, int)
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int COEX_RESTRICTION_WIFI_AWARE = 0x1 << 2;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(flag = true, prefix = {"COEX_RESTRICTION_"}, value = {
+ COEX_RESTRICTION_WIFI_DIRECT,
+ COEX_RESTRICTION_SOFTAP,
+ COEX_RESTRICTION_WIFI_AWARE
+ })
+ public @interface CoexRestriction {}
+
+ /**
+ * @return {@code true} if the default coex algorithm is enabled. {@code false} otherwise.
+ *
+ * @hide
+ */
+ public boolean isDefaultCoexAlgorithmEnabled() {
+ try {
+ return mService.isDefaultCoexAlgorithmEnabled();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Specify the set of {@link CoexUnsafeChannel} to propagate through the framework for
+ * Wi-Fi/Cellular coex channel avoidance if the default algorithm is disabled via overlay
+ * (i.e. config_wifiCoexDefaultAlgorithmEnabled = false). Otherwise do nothing.
+ *
+ * @param unsafeChannels Set of {@link CoexUnsafeChannel} to avoid.
+ * @param restrictions Bitmap of {@link CoexRestriction} specifying the mandatory restricted
+ * uses of the specified channels. If any restrictions are set, then the
+ * supplied CoexUnsafeChannels will be completely avoided for the
+ * specified modes, rather than be avoided with best effort.
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.WIFI_UPDATE_COEX_UNSAFE_CHANNELS)
+ public void setCoexUnsafeChannels(@NonNull Set<CoexUnsafeChannel> unsafeChannels,
+ int restrictions) {
+ if (unsafeChannels == null) {
+ throw new IllegalArgumentException("unsafeChannels must not be null");
+ }
+ try {
+ mService.setCoexUnsafeChannels(new ArrayList<>(unsafeChannels), restrictions);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Returns the set of current {@link CoexUnsafeChannel} being used for Wi-Fi/Cellular coex
+ * channel avoidance.
+ *
+ * This returns the set calculated by the default algorithm if
+ * config_wifiCoexDefaultAlgorithmEnabled is {@code true}. Otherwise, returns the set supplied
+ * in {@link #setCoexUnsafeChannels(Set, int)}.
+ *
+ * If any {@link CoexRestriction} flags are set in {@link #getCoexRestrictions()}, then the
+ * CoexUnsafeChannels should be totally avoided (i.e. not best effort) for the Wi-Fi modes
+ * specified by the flags.
+ *
+ * @return Set of current CoexUnsafeChannels.
+ *
+ * @hide
+ */
+ @NonNull
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.WIFI_ACCESS_COEX_UNSAFE_CHANNELS)
+ public Set<CoexUnsafeChannel> getCoexUnsafeChannels() {
+ try {
+ return new HashSet<>(mService.getCoexUnsafeChannels());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Returns the current coex restrictions being used for Wi-Fi/Cellular coex
+ * channel avoidance.
+ *
+ * This returns the restrictions calculated by the default algorithm if
+ * config_wifiCoexDefaultAlgorithmEnabled is {@code true}. Otherwise, returns the value supplied
+ * in {@link #setCoexUnsafeChannels(Set, int)}.
+ *
+ * @return int containing a bitwise-OR combination of {@link CoexRestriction}.
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.WIFI_ACCESS_COEX_UNSAFE_CHANNELS)
+ public int getCoexRestrictions() {
+ try {
+ return mService.getCoexRestrictions();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Registers a CoexCallback to listen on the current CoexUnsafeChannels and restrictions being
+ * used for Wi-Fi/cellular coex channel avoidance.
+ * @param executor Executor to execute listener callback on
+ * @param callback CoexCallback to register
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.WIFI_ACCESS_COEX_UNSAFE_CHANNELS)
+ public void registerCoexCallback(
+ @NonNull @CallbackExecutor Executor executor, @NonNull CoexCallback callback) {
+ if (executor == null) throw new IllegalArgumentException("executor must not be null");
+ if (callback == null) throw new IllegalArgumentException("callback must not be null");
+ CoexCallback.CoexCallbackProxy proxy = callback.getProxy();
+ proxy.initProxy(executor, callback);
+ try {
+ mService.registerCoexCallback(proxy);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Unregisters a CoexCallback from listening on the current CoexUnsafeChannels and restrictions
+ * being used for Wi-Fi/cellular coex channel avoidance.
+ * @param callback CoexCallback to unregister
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.WIFI_ACCESS_COEX_UNSAFE_CHANNELS)
+ public void unregisterCoexCallback(@NonNull CoexCallback callback) {
+ if (callback == null) throw new IllegalArgumentException("callback must not be null");
+ CoexCallback.CoexCallbackProxy proxy = callback.getProxy();
+ try {
+ mService.unregisterCoexCallback(proxy);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ } finally {
+ proxy.cleanUpProxy();
+ }
+ }
+
+ /**
+ * Abstract callback class for applications to receive updates about current CoexUnsafeChannels
+ * for Wi-Fi/Cellular coex channel avoidance.
+ *
+ * @hide
+ */
+ @SystemApi
+ public abstract static class CoexCallback {
+ private final CoexCallbackProxy mCoexCallbackProxy;
+
+ public CoexCallback() {
+ mCoexCallbackProxy = new CoexCallbackProxy();
+ }
+
+ /*package*/ @NonNull
+ CoexCallbackProxy getProxy() {
+ return mCoexCallbackProxy;
+ }
+
+ /**
+ * Indicates that the current CoexUnsafeChannels or restrictions have changed.
+ * Clients should call {@link #getCoexUnsafeChannels()} and {@link #getCoexRestrictions()}
+ * to get the updated values.
+ */
+ public abstract void onCoexUnsafeChannelsChanged();
+
+ /**
+ * Callback proxy for CoexCallback objects.
+ */
+ private static class CoexCallbackProxy extends ICoexCallback.Stub {
+ private final Object mLock = new Object();
+ @Nullable @GuardedBy("mLock") private Executor mExecutor;
+ @Nullable @GuardedBy("mLock") private CoexCallback mCallback;
+
+ CoexCallbackProxy() {
+ mExecutor = null;
+ mCallback = null;
+ }
+
+ /*package*/ void initProxy(@NonNull Executor executor,
+ @NonNull CoexCallback callback) {
+ synchronized (mLock) {
+ mExecutor = executor;
+ mCallback = callback;
+ }
+ }
+
+ /*package*/ void cleanUpProxy() {
+ synchronized (mLock) {
+ mExecutor = null;
+ mCallback = null;
+ }
+ }
+
+ @Override
+ public void onCoexUnsafeChannelsChanged() {
+ Executor executor;
+ CoexCallback callback;
+ synchronized (mLock) {
+ executor = mExecutor;
+ callback = mCallback;
+ }
+ if (executor == null || callback == null) {
+ return;
+ }
+ Binder.clearCallingIdentity();
+ executor.execute(callback::onCoexUnsafeChannelsChanged);
+ }
+ }
+ }
+
/**
* Start Soft AP (hotspot) mode for tethering purposes with the specified configuration.
* Note that starting Soft AP mode may disable station mode operation if the device does not
@@ -3055,7 +3445,7 @@
})
public boolean startSoftAp(@Nullable WifiConfiguration wifiConfig) {
try {
- return mService.startSoftAp(wifiConfig);
+ return mService.startSoftAp(wifiConfig, mContext.getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -3079,7 +3469,7 @@
})
public boolean startTetheredHotspot(@Nullable SoftApConfiguration softApConfig) {
try {
- return mService.startTetheredHotspot(softApConfig);
+ return mService.startTetheredHotspot(softApConfig, mContext.getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -3396,7 +3786,10 @@
*/
@NonNull
@SystemApi
- @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.OVERRIDE_WIFI_CONFIG
+ })
public SoftApConfiguration getSoftApConfiguration() {
try {
return mService.getSoftApConfiguration();
@@ -3444,7 +3837,10 @@
* @hide
*/
@SystemApi
- @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.OVERRIDE_WIFI_CONFIG
+ })
public boolean setSoftApConfiguration(@NonNull SoftApConfiguration softApConfig) {
try {
return mService.setSoftApConfiguration(
@@ -3630,9 +4026,34 @@
*/
default void onConnectedClientsChanged(@NonNull List<WifiClient> clients) {}
+
+ /**
+ * Called when the connected clients for a soft AP instance change.
+ *
+ * When the Soft AP is configured in single AP mode, this callback is invoked
+ * with the same {@link SoftApInfo} for all connected clients changes.
+ * When the Soft AP is configured in bridged mode, this callback is invoked with
+ * the corresponding {@link SoftApInfo} for the instance in which the connected clients
+ * changed.
+ *
+ * Use {@link #onConnectedClientsChanged(List<WifiClient>)} if you don't care about
+ * the mapping from SoftApInfo instance to connected clients.
+ *
+ * @param info The {@link SoftApInfo} of the AP.
+ * @param clients The currently connected clients on the AP instance specified by
+ * {@code info}.
+ */
+ default void onConnectedClientsChanged(@NonNull SoftApInfo info,
+ @NonNull List<WifiClient> clients) {}
+
/**
* Called when information of softap changes.
*
+ * Note: this API is only valid when the Soft AP is configured as a single AP
+ * - not as a bridged AP (2 Soft APs). When the Soft AP is configured as bridged AP
+ * this callback will not be triggered - use the
+ * {@link #onInfoChanged(List<SoftApInfo>)} callback in bridged AP mode.
+ *
* @param softApInfo is the softap information. {@link SoftApInfo}
*/
default void onInfoChanged(@NonNull SoftApInfo softApInfo) {
@@ -3640,6 +4061,28 @@
}
/**
+ * Called when information of softap changes.
+ *
+ * The number of the information elements in the list depends on Soft AP configuration
+ * and state.
+ * For instance, an empty list will be returned when the Soft AP is disabled.
+ * One information element will be returned in the list when the Soft AP is configured
+ * as a single AP, and two information elements will be returned in the list
+ * when the Soft AP is configured in bridged mode.
+ *
+ * Note: One of the Soft APs may be shut down independently of the other by the framework,
+ * for instance if no devices are connected to it for some duration.
+ * In that case, one information element will be returned in the list in bridged mode.
+ *
+ * See {@link #isBridgedApConcurrencySupported()} for the detail of the bridged AP.
+ *
+ * @param softApInfoList is the list of the softap information elements. {@link SoftApInfo}
+ */
+ default void onInfoChanged(@NonNull List<SoftApInfo> softApInfoList) {
+ // Do nothing: can be updated to add SoftApInfo details (e.g. channel) to the UI.
+ }
+
+ /**
* Called when capability of softap changes.
*
* @param softApCapability is the softap capability. {@link SoftApCapability}
@@ -3674,6 +4117,16 @@
private class SoftApCallbackProxy extends ISoftApCallback.Stub {
private final Executor mExecutor;
private final SoftApCallback mCallback;
+ private Map<String, List<WifiClient>> mCurrentClients = new HashMap<>();
+ private Map<String, SoftApInfo> mCurrentInfos = new HashMap<>();
+
+ private List<WifiClient> getConnectedClientList(Map<String, List<WifiClient>> clientsMap) {
+ List<WifiClient> connectedClientList = new ArrayList<>();
+ for (List<WifiClient> it : clientsMap.values()) {
+ connectedClientList.addAll(it);
+ }
+ return connectedClientList;
+ }
SoftApCallbackProxy(Executor executor, SoftApCallback callback) {
mExecutor = executor;
@@ -3694,28 +4147,84 @@
}
@Override
- public void onConnectedClientsChanged(List<WifiClient> clients) {
+ public void onConnectedClientsOrInfoChanged(Map<String, SoftApInfo> infos,
+ Map<String, List<WifiClient>> clients, boolean isBridged, boolean isRegistration) {
if (mVerboseLoggingEnabled) {
- Log.v(TAG, "SoftApCallbackProxy: onConnectedClientsChanged: clients="
- + clients.size() + " clients");
+ Log.v(TAG, "SoftApCallbackProxy: onConnectedClientsOrInfoChanged: clients: "
+ + clients + ", infos: " + infos + ", isBridged is " + isBridged
+ + ", isRegistration is " + isRegistration);
}
- Binder.clearCallingIdentity();
- mExecutor.execute(() -> {
- mCallback.onConnectedClientsChanged(clients);
- });
- }
-
- @Override
- public void onInfoChanged(SoftApInfo softApInfo) {
- if (mVerboseLoggingEnabled) {
- Log.v(TAG, "SoftApCallbackProxy: onInfoChange: softApInfo=" + softApInfo);
+ List<SoftApInfo> changedInfoList = new ArrayList<>(infos.values());
+ Map<SoftApInfo, List<WifiClient>> changedInfoClients = new HashMap<>();
+ boolean isInfoChanged = infos.size() != mCurrentInfos.size();
+ for (SoftApInfo info : mCurrentInfos.values()) {
+ String changedInstance = info.getApInstanceIdentifier();
+ if (!changedInfoList.contains(info)) {
+ isInfoChanged = true;
+ if (mCurrentClients.getOrDefault(changedInstance,
+ Collections.emptyList()).size() > 0) {
+ Log.d(TAG, "SoftApCallbackProxy: info changed on client connected"
+ + " instance(Shut Down case)");
+ //Here should notify client changed on old info
+ changedInfoClients.put(info, Collections.emptyList());
+ }
+ } else {
+ // info doesn't change, check client list
+ List<WifiClient> changedClientList = clients.getOrDefault(
+ changedInstance, Collections.emptyList());
+ if (changedClientList.size()
+ != mCurrentClients
+ .getOrDefault(changedInstance, Collections.emptyList()).size()) {
+ // Here should notify client changed on new info(same as old info)
+ changedInfoClients.put(info, changedClientList);
+ Log.d(TAG, "SoftApCallbackProxy: client changed on " + info
+ + " list: " + changedClientList);
+ }
+ }
}
+ if (!isInfoChanged && changedInfoClients.isEmpty()
+ && !isRegistration) {
+ Log.v(TAG, "SoftApCallbackProxy: No changed & Not Registration,"
+ + " don't need to notify the client");
+ return;
+ }
+ mCurrentClients = clients;
+ mCurrentInfos = infos;
Binder.clearCallingIdentity();
- mExecutor.execute(() -> {
- mCallback.onInfoChanged(softApInfo);
- });
+ // Notify the clients changed first for old info shutdown case
+ for (SoftApInfo changedInfo : changedInfoClients.keySet()) {
+ Log.v(TAG, "send onConnectedClientsChanged, changedInfo is " + changedInfo);
+ mExecutor.execute(() -> {
+ mCallback.onConnectedClientsChanged(
+ changedInfo, changedInfoClients.get(changedInfo));
+ });
+ }
+
+ if (isInfoChanged || isRegistration) {
+ if (!isBridged) {
+ SoftApInfo newInfo = changedInfoList.isEmpty()
+ ? new SoftApInfo() : changedInfoList.get(0);
+ Log.v(TAG, "SoftApCallbackProxy: send InfoChanged, newInfo: " + newInfo);
+ mExecutor.execute(() -> {
+ mCallback.onInfoChanged(newInfo);
+ });
+ }
+ Log.v(TAG, "SoftApCallbackProxy: send InfoChanged, changedInfoList: "
+ + changedInfoList);
+ mExecutor.execute(() -> {
+ mCallback.onInfoChanged(changedInfoList);
+ });
+ }
+
+ if (isRegistration || !changedInfoClients.isEmpty()) {
+ Log.v(TAG, "SoftApCallbackProxy: send onConnectedClientsChanged(clients): "
+ + getConnectedClientList(clients));
+ mExecutor.execute(() -> {
+ mCallback.onConnectedClientsChanged(getConnectedClientList(clients));
+ });
+ }
}
@Override
@@ -3752,8 +4261,20 @@
* <li> {@link SoftApCallback#onStateChanged(int, int)}</li>
* <li> {@link SoftApCallback#onConnectedClientsChanged(List<WifiClient>)}</li>
* <li> {@link SoftApCallback#onInfoChanged(SoftApInfo)}</li>
+ * <li> {@link SoftApCallback#onInfoChanged(List<SoftApInfo>)}</li>
* <li> {@link SoftApCallback#onCapabilityChanged(SoftApCapability)}</li>
* </ul>
+ *
+ * Use {@link SoftApCallback#onConnectedClientsChanged(List<WifiClient>)} to know if there are
+ * any clients connected to any of the bridged instances of this AP (if bridged AP is enabled).
+ * Use {@link SoftApCallback#onConnectedClientsChanged(SoftApInfo, List<WifiClient>)} to know
+ * if there are any clients connected to a specific bridged instance of this AP
+ * (if bridged AP is enabled).
+ *
+ * Note: Caller will receive the callback
+ * {@link SoftApCallback#onConnectedClientsChangedWithApInfo(SoftApInfo, List<WifiClient>)}
+ * on registration when there are clients connected to AP.
+ *
* These will be dispatched on registration to provide the caller with the current state
* (and are not an indication of any current change). Note that receiving an immediate
* WIFI_AP_STATE_FAILED value for soft AP state indicates that the latest attempt to start
@@ -4148,14 +4669,11 @@
private void connectInternal(@Nullable WifiConfiguration config, int networkId,
@Nullable ActionListener listener) {
ActionListenerProxy listenerProxy = null;
- Binder binder = null;
if (listener != null) {
listenerProxy = new ActionListenerProxy("connect", mLooper, listener);
- binder = new Binder();
}
try {
- mService.connect(config, networkId, binder, listenerProxy,
- listener == null ? 0 : listener.hashCode());
+ mService.connect(config, networkId, listenerProxy);
} catch (RemoteException e) {
if (listenerProxy != null) listenerProxy.onFailure(ERROR);
} catch (SecurityException e) {
@@ -4217,6 +4735,49 @@
}
/**
+ * Temporarily disable autojoin for all currently visible and provisioned (saved, suggested)
+ * wifi networks except merged carrier networks from the provided subscription ID.
+ *
+ * Disabled networks will get automatically re-enabled when they are out of range for a period
+ * of time, or after the maximum disable duration specified in the framework.
+ *
+ * Calling {@link #stopTemporarilyDisablingAllNonCarrierMergedWifi()} will immediately re-enable
+ * autojoin on all disabled networks.
+ *
+ * @param subscriptionId the subscription ID of the carrier whose merged wifi networks won't be
+ * disabled {@link android.telephony.SubscriptionInfo#getSubscriptionId()}
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD})
+ public void startTemporarilyDisablingAllNonCarrierMergedWifi(int subscriptionId) {
+ try {
+ mService.startTemporarilyDisablingAllNonCarrierMergedWifi(subscriptionId);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Re-enable autojoin for all non carrier merged wifi networks temporarily disconnected by
+ * {@link #startTemporarilyDisablingAllNonCarrierMergedWifi(int)}.
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD})
+ public void stopTemporarilyDisablingAllNonCarrierMergedWifi() {
+ try {
+ mService.stopTemporarilyDisablingAllNonCarrierMergedWifi();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Save the given network to the list of configured networks for the
* foreground user. If the network already exists, the configuration
* is updated. Any new network is enabled by default.
@@ -4246,14 +4807,11 @@
public void save(@NonNull WifiConfiguration config, @Nullable ActionListener listener) {
if (config == null) throw new IllegalArgumentException("config cannot be null");
ActionListenerProxy listenerProxy = null;
- Binder binder = null;
if (listener != null) {
listenerProxy = new ActionListenerProxy("save", mLooper, listener);
- binder = new Binder();
}
try {
- mService.save(config, binder, listenerProxy,
- listener == null ? 0 : listener.hashCode());
+ mService.save(config, listenerProxy);
} catch (RemoteException e) {
if (listenerProxy != null) listenerProxy.onFailure(ERROR);
} catch (SecurityException e) {
@@ -4283,14 +4841,11 @@
public void forget(int netId, @Nullable ActionListener listener) {
if (netId < 0) throw new IllegalArgumentException("Network id cannot be negative");
ActionListenerProxy listenerProxy = null;
- Binder binder = null;
if (listener != null) {
listenerProxy = new ActionListenerProxy("forget", mLooper, listener);
- binder = new Binder();
}
try {
- mService.forget(netId, binder, listenerProxy,
- listener == null ? 0 : listener.hashCode());
+ mService.forget(netId, listenerProxy);
} catch (RemoteException e) {
if (listenerProxy != null) listenerProxy.onFailure(ERROR);
} catch (SecurityException e) {
@@ -5323,6 +5878,13 @@
}
/**
+ * @return true if this device supports WPA3 AP validation.
+ */
+ public boolean isWpa3ApValidationSupported() {
+ return isFeatureSupported(WIFI_FEATURE_SAE_PK);
+ }
+
+ /**
* Gets the factory Wi-Fi MAC addresses.
* @return Array of String representing Wi-Fi MAC addresses sorted lexically or an empty Array
* if failed.
@@ -5436,6 +5998,89 @@
}
/**
+ * Easy Connect Device information maximum allowed length.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int EASY_CONNECT_DEVICE_INFO_MAXIMUM_LENGTH = 40;
+
+ /**
+ * Easy Connect Cryptography Curve name: prime256v1
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int EASY_CONNECT_CRYPTOGRAPHY_CURVE_PRIME256V1 = 0;
+
+ /**
+ * Easy Connect Cryptography Curve name: secp384r1
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int EASY_CONNECT_CRYPTOGRAPHY_CURVE_SECP384R1 = 1;
+
+ /**
+ * Easy Connect Cryptography Curve name: secp521r1
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int EASY_CONNECT_CRYPTOGRAPHY_CURVE_SECP521R1 = 2;
+
+
+ /**
+ * Easy Connect Cryptography Curve name: brainpoolP256r1
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int EASY_CONNECT_CRYPTOGRAPHY_CURVE_BRAINPOOLP256R1 = 3;
+
+
+ /**
+ * Easy Connect Cryptography Curve name: brainpoolP384r1
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int EASY_CONNECT_CRYPTOGRAPHY_CURVE_BRAINPOOLP384R1 = 4;
+
+
+ /**
+ * Easy Connect Cryptography Curve name: brainpoolP512r1
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int EASY_CONNECT_CRYPTOGRAPHY_CURVE_BRAINPOOLP512R1 = 5;
+
+ /**
+ * Easy Connect Cryptography Curve name: default
+ * This allows framework to choose manadatory curve prime256v1.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int EASY_CONNECT_CRYPTOGRAPHY_CURVE_DEFAULT =
+ EASY_CONNECT_CRYPTOGRAPHY_CURVE_PRIME256V1;
+
+ /** @hide */
+ @IntDef(prefix = {"EASY_CONNECT_CRYPTOGRAPHY_CURVE_"}, value = {
+ EASY_CONNECT_CRYPTOGRAPHY_CURVE_DEFAULT,
+ EASY_CONNECT_CRYPTOGRAPHY_CURVE_PRIME256V1,
+ EASY_CONNECT_CRYPTOGRAPHY_CURVE_SECP384R1,
+ EASY_CONNECT_CRYPTOGRAPHY_CURVE_SECP521R1,
+ EASY_CONNECT_CRYPTOGRAPHY_CURVE_BRAINPOOLP256R1,
+ EASY_CONNECT_CRYPTOGRAPHY_CURVE_BRAINPOOLP384R1,
+ EASY_CONNECT_CRYPTOGRAPHY_CURVE_BRAINPOOLP512R1,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface EasyConnectCryptographyCurve {
+ }
+
+ /**
* Start Easy Connect (DPP) in Configurator-Initiator role. The current device will initiate
* Easy Connect bootstrapping with a peer, and configure the peer with the SSID and password of
* the specified network using the Easy Connect protocol on an encrypted link.
@@ -5491,6 +6136,52 @@
}
/**
+ * Start Easy Connect (DPP) in Enrollee-Responder role.
+ * The device will:
+ * 1. Generate a DPP bootstrap URI and return it using the
+ * {@link EasyConnectStatusCallback#onBootstrapUriGenerated(String)} method.
+ * 2. Start DPP as a Responder, waiting for an Initiator device to start the DPP
+ * authentication process.
+ * The caller should use the URI provided in step #1, for instance display it as a QR code
+ * or communicate it in some other way to the initiator device.
+ *
+ * @param deviceInfo Device specific information to add to the DPP URI. This field allows
+ * the users of the configurators to identify the device.
+ * Optional - if not provided or in case of an empty string,
+ * Info field (I:) will be skipped in the generated DPP URI.
+ * Allowed Range of ASCII characters in deviceInfo - %x20-7E.
+ * semicolon and space are not allowed.
+ * Due to the limitation of maximum allowed characters in QR code,
+ * framework limits to a max of
+ * {@link #EASY_CONNECT_DEVICE_INFO_MAXIMUM_LENGTH} characters in
+ * deviceInfo.
+ * Violation of these rules will result in an exception.
+ * @param curve Elliptic curve cryptography used to generate DPP
+ * public/private key pair. If application is not interested in a
+ * specific curve, choose default curve
+ * {@link #EASY_CONNECT_CRYPTOGRAPHY_CURVE_DEFAULT}.
+ * @param callback Callback for status updates
+ * @param executor The Executor on which to run the callback.
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD})
+ public void startEasyConnectAsEnrolleeResponder(@Nullable String deviceInfo,
+ @EasyConnectCryptographyCurve int curve,
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull EasyConnectStatusCallback callback) {
+ Binder binder = new Binder();
+ try {
+ mService.startDppAsEnrolleeResponder(binder, deviceInfo, curve,
+ new EasyConnectCallbackProxy(executor, callback));
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Stop or abort a current Easy Connect (DPP) session. This call, once processed, will
* terminate any ongoing transaction, and clean up all associated resources. Caller should not
* expect any callbacks once this call is made. However, due to the asynchronous nature of
@@ -5564,6 +6255,15 @@
mEasyConnectStatusCallback.onProgress(status);
});
}
+
+ @Override
+ public void onBootstrapUriGenerated(String uri) {
+ Log.d(TAG, "Easy Connect onBootstrapUriGenerated callback");
+ Binder.clearCallingIdentity();
+ mExecutor.execute(() -> {
+ mEasyConnectStatusCallback.onBootstrapUriGenerated(uri);
+ });
+ }
}
/**
@@ -5738,7 +6438,6 @@
executor.execute(callback::onScanResultsAvailable);
}
}
-
}
/**
@@ -6236,4 +6935,154 @@
throw e.rethrowFromSystemServer();
}
}
+
+ /**
+ * Sets the state of carrier offload on merged or unmerged networks for specified subscription.
+ *
+ * <p>
+ * When a subscription's carrier network offload is disabled, all network suggestions related to
+ * this subscription will not be considered for auto join.
+ * <p>
+ * If calling app want disable all carrier network offload from a specified subscription, should
+ * call this API twice to disable both merged and unmerged carrier network suggestions.
+ *
+ * @param subscriptionId See {@link SubscriptionInfo#getSubscriptionId()}.
+ * @param merged True for carrier merged network, false otherwise.
+ * See {@link WifiNetworkSuggestion.Builder#setCarrierMerged(boolean)}
+ * @param enabled True for enable carrier network offload, false otherwise.
+ * @see #isCarrierNetworkOffloadEnabled(int, boolean)
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD})
+ public void setCarrierNetworkOffloadEnabled(int subscriptionId, boolean merged,
+ boolean enabled) {
+ if (!SdkLevel.isAtLeastS()) {
+ throw new UnsupportedOperationException();
+ }
+ try {
+ mService.setCarrierNetworkOffloadEnabled(subscriptionId, merged, enabled);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Get the carrier network offload state for merged or unmerged networks for specified
+ * subscription.
+ * @param subscriptionId subscription ID see {@link SubscriptionInfo#getSubscriptionId()}
+ * @param merged True for carrier merged network, false otherwise.
+ * See {@link WifiNetworkSuggestion.Builder#setCarrierMerged(boolean)}
+ * @return True to indicate that carrier network offload is enabled, false otherwise.
+ * @see #setCarrierNetworkOffloadEnabled(int, boolean, boolean)
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD})
+ public boolean isCarrierNetworkOffloadEnabled(int subscriptionId, boolean merged) {
+ if (!SdkLevel.isAtLeastS()) {
+ throw new UnsupportedOperationException();
+ }
+ try {
+ return mService.isCarrierNetworkOffloadEnabled(subscriptionId, merged);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Interface for network suggestion user approval status change listener.
+ * Should be implemented by applications and registered using
+ * {@link #addSuggestionUserApprovalStatusListener(Executor,
+ * SuggestionUserApprovalStatusListener)} (
+ */
+ public interface SuggestionUserApprovalStatusListener {
+
+ /**
+ * Called when the user approval status of the App has changed. The current status can be
+ * queried by {@link #getNetworkSuggestionUserApprovalStatus()}
+ */
+ void onUserApprovalStatusChange();
+ }
+
+ private class SuggestionUserApprovalStatusListenerProxy extends
+ ISuggestionUserApprovalStatusListener.Stub {
+ private final Executor mExecutor;
+ private final SuggestionUserApprovalStatusListener mListener;
+
+ SuggestionUserApprovalStatusListenerProxy(@NonNull Executor executor,
+ @NonNull SuggestionUserApprovalStatusListener listener) {
+ mExecutor = executor;
+ mListener = listener;
+ }
+
+ @Override
+ public void onUserApprovalStatusChange() {
+ mExecutor.execute(() -> mListener.onUserApprovalStatusChange());
+ }
+
+ }
+
+ /**
+ * Add a listener for Wi-Fi network suggestion user approval status.
+ * See {@link SuggestionUserApprovalStatusListener}.
+ * Caller will receive a callback when the user approval status of the caller has changed.
+ * Caller can remove a previously registered listener using
+ * {@link WifiManager#removeSuggestionUserApprovalStatusListener(
+ * SuggestionUserApprovalStatusListener)}
+ * A caller can add multiple listeners to monitor the event.
+ * @param executor The executor to execute the listener of the {@code listener} object.
+ * @param listener listener for suggestion user approval status changes.
+ * @return true if succeed otherwise false.
+ */
+ @RequiresPermission(ACCESS_WIFI_STATE)
+ public boolean addSuggestionUserApprovalStatusListener(
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull SuggestionUserApprovalStatusListener listener) {
+ if (!SdkLevel.isAtLeastS()) {
+ throw new UnsupportedOperationException();
+ }
+ if (listener == null) throw new IllegalArgumentException("Listener cannot be null");
+ if (executor == null) throw new IllegalArgumentException("Executor cannot be null");
+ Log.v(TAG, "addSuggestionUserApprovalStatusListener listener=" + listener
+ + ", executor=" + executor);
+ try {
+ return mService.addSuggestionUserApprovalStatusListener(new Binder(),
+ new SuggestionUserApprovalStatusListenerProxy(executor, listener),
+ listener.hashCode(), mContext.getOpPackageName(), mContext.getAttributionTag());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+
+ }
+
+ /**
+ * Allow callers to remove a previously registered listener using
+ * {@link #addSuggestionUserApprovalStatusListener(Executor,
+ * SuggestionUserApprovalStatusListener)}. After calling this method,
+ * applications will no longer receive network suggestion user approval status change through
+ * that listener.
+ *
+ * @param listener listener to remove.
+ */
+ @RequiresPermission(ACCESS_WIFI_STATE)
+ public void removeSuggestionUserApprovalStatusListener(
+ @NonNull SuggestionUserApprovalStatusListener listener) {
+ if (!SdkLevel.isAtLeastS()) {
+ throw new UnsupportedOperationException();
+ }
+ if (listener == null) throw new IllegalArgumentException("Listener cannot be null");
+ Log.v(TAG, "removeSuggestionUserApprovalStatusListener: listener=" + listener);
+ try {
+ mService.removeSuggestionUserApprovalStatusListener(listener.hashCode(),
+ mContext.getOpPackageName());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
}
diff --git a/framework/java/android/net/wifi/WifiNetworkSpecifier.java b/framework/java/android/net/wifi/WifiNetworkSpecifier.java
index e12bb91..be3b45d 100644
--- a/framework/java/android/net/wifi/WifiNetworkSpecifier.java
+++ b/framework/java/android/net/wifi/WifiNetworkSpecifier.java
@@ -56,6 +56,16 @@
MacAddress.BROADCAST_ADDRESS;
/**
+ * Set WPA Enterprise type according to certificate security level.
+ * This is for backward compatibility in R.
+ */
+ private static final int WPA3_ENTERPRISE_AUTO = 0;
+ /** Set WPA Enterprise type to standard mode only. */
+ private static final int WPA3_ENTERPRISE_STANDARD = 1;
+ /** Set WPA Enterprise type to 192 bit mode only. */
+ private static final int WPA3_ENTERPRISE_192_BIT = 2;
+
+ /**
* SSID pattern match specified by the app.
*/
private @Nullable PatternMatcher mSsidPatternMatcher;
@@ -87,6 +97,10 @@
*/
private @Nullable WifiEnterpriseConfig mWpa3EnterpriseConfig;
/**
+ * Indicate what type this WPA3-Enterprise network is.
+ */
+ private int mWpa3EnterpriseType = WPA3_ENTERPRISE_AUTO;
+ /**
* This is a network that does not broadcast its SSID, so an
* SSID-specific probe request must be used for scans.
*/
@@ -249,9 +263,14 @@
* sha384WithRSAEncryption (OID 1.2.840.113549.1.1.12) or ecdsa-with-SHA384
* (OID 1.2.840.10045.4.3.3).
*
+ * @deprecated use {@link #setWpa3EnterpriseStandardModeConfig(WifiEnterpriseConfig)} or
+ * {@link #setWpa3Enterprise192BitModeConfig(WifiEnterpriseConfig)} to specify
+ * WPA3-Enterprise type explicitly.
+ *
* @param enterpriseConfig Instance of {@link WifiEnterpriseConfig}.
* @return Instance of {@link Builder} to enable chaining of the builder method.
*/
+ @Deprecated
public @NonNull Builder setWpa3EnterpriseConfig(
@NonNull WifiEnterpriseConfig enterpriseConfig) {
checkNotNull(enterpriseConfig);
@@ -260,6 +279,58 @@
}
/**
+ * Set the associated enterprise configuration for this network. Needed for authenticating
+ * to standard WPA3-Enterprise networks. See {@link WifiEnterpriseConfig} for description.
+ * For WPA3-Enterprise in 192-bit security mode networks,
+ * see {@link #setWpa3Enterprise192BitModeConfig(WifiEnterpriseConfig)} for description.
+ *
+ * @param enterpriseConfig Instance of {@link WifiEnterpriseConfig}.
+ * @return Instance of {@link Builder} to enable chaining of the builder method.
+ */
+ public @NonNull Builder setWpa3EnterpriseStandardModeConfig(
+ @NonNull WifiEnterpriseConfig enterpriseConfig) {
+ checkNotNull(enterpriseConfig);
+ mWpa3EnterpriseConfig = new WifiEnterpriseConfig(enterpriseConfig);
+ mWpa3EnterpriseType = WPA3_ENTERPRISE_STANDARD;
+ return this;
+ }
+
+ /**
+ * Set the associated enterprise configuration for this network. Needed for authenticating
+ * to WPA3-Enterprise in 192-bit security mode networks. See {@link WifiEnterpriseConfig}
+ * for description. Both the client and CA certificates must be provided,
+ * and must be of type of either sha384WithRSAEncryption with key length of 3072bit or
+ * more (OID 1.2.840.113549.1.1.12), or ecdsa-with-SHA384 with key length of 384bit or
+ * more (OID 1.2.840.10045.4.3.3).
+ *
+ * @param enterpriseConfig Instance of {@link WifiEnterpriseConfig}.
+ * @return Instance of {@link Builder} to enable chaining of the builder method.
+ * @throws IllegalArgumentException if the EAP type or certificates do not
+ * meet 192-bit mode requirements.
+ */
+ public @NonNull Builder setWpa3Enterprise192BitModeConfig(
+ @NonNull WifiEnterpriseConfig enterpriseConfig) {
+ checkNotNull(enterpriseConfig);
+ if (enterpriseConfig.getEapMethod() != WifiEnterpriseConfig.Eap.TLS) {
+ throw new IllegalArgumentException("The 192-bit mode network type must be TLS");
+ }
+ if (!WifiEnterpriseConfig.isSuiteBCipherCert(
+ enterpriseConfig.getClientCertificate())) {
+ throw new IllegalArgumentException(
+ "The client certificate does not meet 192-bit mode requirements.");
+ }
+ if (!WifiEnterpriseConfig.isSuiteBCipherCert(
+ enterpriseConfig.getCaCertificate())) {
+ throw new IllegalArgumentException(
+ "The CA certificate does not meet 192-bit mode requirements.");
+ }
+
+ mWpa3EnterpriseConfig = new WifiEnterpriseConfig(enterpriseConfig);
+ mWpa3EnterpriseType = WPA3_ENTERPRISE_192_BIT;
+ return this;
+ }
+
+ /**
* Specifies whether this represents a hidden network.
* <p>
* <li>Setting this disallows the usage of {@link #setSsidPattern(PatternMatcher)} since
@@ -289,23 +360,23 @@
configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP);
configuration.enterpriseConfig = mWpa2EnterpriseConfig;
} else if (mWpa3EnterpriseConfig != null) { // WPA3-Enterprise
- if (mWpa3EnterpriseConfig.getEapMethod() == WifiEnterpriseConfig.Eap.TLS
+ if (mWpa3EnterpriseType == WPA3_ENTERPRISE_AUTO
+ && mWpa3EnterpriseConfig.getEapMethod() == WifiEnterpriseConfig.Eap.TLS
&& WifiEnterpriseConfig.isSuiteBCipherCert(
mWpa3EnterpriseConfig.getClientCertificate())
&& WifiEnterpriseConfig.isSuiteBCipherCert(
mWpa3EnterpriseConfig.getCaCertificate())) {
- // WPA3-Enterprise in 192-bit security mode (Suite-B)
- configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP_SUITE_B);
+ // WPA3-Enterprise in 192-bit security mode
+ configuration.setSecurityParams(
+ WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT);
+ } else if (mWpa3EnterpriseType == WPA3_ENTERPRISE_192_BIT) {
+ // WPA3-Enterprise in 192-bit security mode
+ configuration.setSecurityParams(
+ WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT);
} else {
// WPA3-Enterprise
- configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP);
- configuration.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
- configuration.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
- configuration.allowedPairwiseCiphers.set(
- WifiConfiguration.PairwiseCipher.GCMP_256);
- configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
- configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_256);
- configuration.requirePmf = true;
+ configuration.setSecurityParams(
+ WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE);
}
configuration.enterpriseConfig = mWpa3EnterpriseConfig;
} else if (mIsEnhancedOpen) { // OWE network
diff --git a/framework/java/android/net/wifi/WifiNetworkSuggestion.java b/framework/java/android/net/wifi/WifiNetworkSuggestion.java
index d8be1d2..b7450c5 100644
--- a/framework/java/android/net/wifi/WifiNetworkSuggestion.java
+++ b/framework/java/android/net/wifi/WifiNetworkSuggestion.java
@@ -24,12 +24,18 @@
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.net.MacAddress;
+import android.net.NetworkCapabilities;
+import android.net.NetworkRequest;
import android.net.wifi.hotspot2.PasspointConfiguration;
import android.os.Parcel;
import android.os.Parcelable;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
+import com.android.modules.utils.build.SdkLevel;
+
import java.nio.charset.CharsetEncoder;
import java.nio.charset.StandardCharsets;
import java.util.List;
@@ -51,6 +57,16 @@
private static final int UNASSIGNED_PRIORITY = -1;
/**
+ * Set WPA Enterprise type according to certificate security level.
+ * This is for backward compatibility in R.
+ */
+ private static final int WPA3_ENTERPRISE_AUTO = 0;
+ /** Set WPA Enterprise type to standard mode only. */
+ private static final int WPA3_ENTERPRISE_STANDARD = 1;
+ /** Set WPA Enterprise type to 192 bit mode only. */
+ private static final int WPA3_ENTERPRISE_192_BIT = 2;
+
+ /**
* SSID of the network.
*/
private String mSsid;
@@ -81,6 +97,10 @@
*/
private @Nullable WifiEnterpriseConfig mWpa3EnterpriseConfig;
/**
+ * Indicate what type this WPA3-Enterprise network is.
+ */
+ private int mWpa3EnterpriseType = WPA3_ENTERPRISE_AUTO;
+ /**
* The passpoint config for use with Hotspot 2.0 network
*/
private @Nullable PasspointConfiguration mPasspointConfiguration;
@@ -102,10 +122,15 @@
*/
private int mMeteredOverride;
/**
- * Priority of this network among other network suggestions provided by the app.
+ * Priority of this network among other network suggestions from same priority group
+ * provided by the app.
* The lower the number, the higher the priority (i.e value of 0 = highest priority).
*/
private int mPriority;
+ /**
+ * Priority group ID, while suggestion priority will only effect inside the priority group.
+ */
+ private int mPriorityGroup;
/**
* The carrier ID identifies the operator who provides this network configuration.
@@ -114,6 +139,12 @@
private int mCarrierId;
/**
+ * The Subscription ID identifies the SIM card for which this network configuration is
+ * valid.
+ */
+ private int mSubscriptionId;
+
+ /**
* Whether this network is shared credential with user to allow user manually connect.
*/
private boolean mIsSharedWithUser;
@@ -144,6 +175,27 @@
*/
private boolean mIsNetworkUntrusted;
+ /**
+ * Whether this network will be brought up as OEM paid (OEM_PAID capability bit added).
+ */
+ private boolean mIsNetworkOemPaid;
+
+ /**
+ * Whether this network will be brought up as OEM private (OEM_PRIVATE capability bit
+ * added).
+ */
+ private boolean mIsNetworkOemPrivate;
+
+ /**
+ * Whether this network is a carrier merged network.
+ */
+ private boolean mIsCarrierMerged;
+
+ /**
+ * Whether this network will use enhanced MAC randomization.
+ */
+ private boolean mIsEnhancedMacRandomizationEnabled;
+
public Builder() {
mSsid = null;
mBssid = null;
@@ -165,6 +217,12 @@
mWapiPskPassphrase = null;
mWapiEnterpriseConfig = null;
mIsNetworkUntrusted = false;
+ mIsNetworkOemPaid = false;
+ mIsNetworkOemPrivate = false;
+ mIsCarrierMerged = false;
+ mPriorityGroup = 0;
+ mIsEnhancedMacRandomizationEnabled = false;
+ mSubscriptionId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
}
/**
@@ -282,11 +340,16 @@
* sha384WithRSAEncryption (OID 1.2.840.113549.1.1.12) or ecdsa-with-SHA384
* (OID 1.2.840.10045.4.3.3).
*
+ * @deprecated use {@link #setWpa3EnterpriseStandardModeConfig(WifiEnterpriseConfig)} or
+ * {@link #setWpa3Enterprise192BitModeConfig(WifiEnterpriseConfig)} to specify
+ * WPA3-Enterprise type explicitly.
+ *
* @param enterpriseConfig Instance of {@link WifiEnterpriseConfig}.
* @return Instance of {@link Builder} to enable chaining of the builder method.
* @throws IllegalArgumentException if configuration CA certificate or
* AltSubjectMatch/DomainSuffixMatch is not set.
*/
+ @Deprecated
public @NonNull Builder setWpa3EnterpriseConfig(
@NonNull WifiEnterpriseConfig enterpriseConfig) {
checkNotNull(enterpriseConfig);
@@ -298,6 +361,63 @@
}
/**
+ * Set the associated enterprise configuration for this network. Needed for authenticating
+ * to WPA3-Enterprise standard networks. See {@link WifiEnterpriseConfig} for description.
+ * For WPA3-Enterprise in 192-bit security mode networks,
+ * see {@link #setWpa3Enterprise192BitModeConfig(WifiEnterpriseConfig)} for description.
+ *
+ * @param enterpriseConfig Instance of {@link WifiEnterpriseConfig}.
+ * @return Instance of {@link Builder} to enable chaining of the builder method.
+ * @throws IllegalArgumentException if configuration CA certificate or
+ * AltSubjectMatch/DomainSuffixMatch is not set.
+ */
+ public @NonNull Builder setWpa3EnterpriseStandardModeConfig(
+ @NonNull WifiEnterpriseConfig enterpriseConfig) {
+ checkNotNull(enterpriseConfig);
+ if (enterpriseConfig.isInsecure()) {
+ throw new IllegalArgumentException("Enterprise configuration is insecure");
+ }
+ mWpa3EnterpriseConfig = new WifiEnterpriseConfig(enterpriseConfig);
+ mWpa3EnterpriseType = WPA3_ENTERPRISE_STANDARD;
+ return this;
+ }
+
+ /**
+ * Set the associated enterprise configuration for this network. Needed for authenticating
+ * to WPA3-Enterprise in 192-bit security mode networks. See {@link WifiEnterpriseConfig}
+ * for description. Both the client and CA certificates must be provided,
+ * and must be of type of either sha384WithRSAEncryption with key length of 3072bit or
+ * more (OID 1.2.840.113549.1.1.12), or ecdsa-with-SHA384 with key length of 384bit or
+ * more (OID 1.2.840.10045.4.3.3).
+ *
+ * @param enterpriseConfig Instance of {@link WifiEnterpriseConfig}.
+ * @return Instance of {@link Builder} to enable chaining of the builder method.
+ * @throws IllegalArgumentException if the EAP type or certificates do not
+ * meet 192-bit mode requirements.
+ */
+ public @NonNull Builder setWpa3Enterprise192BitModeConfig(
+ @NonNull WifiEnterpriseConfig enterpriseConfig) {
+ checkNotNull(enterpriseConfig);
+ if (enterpriseConfig.getEapMethod() != WifiEnterpriseConfig.Eap.TLS) {
+ throw new IllegalArgumentException("The 192-bit mode network type must be TLS");
+ }
+ if (!WifiEnterpriseConfig.isSuiteBCipherCert(
+ enterpriseConfig.getClientCertificate())) {
+ throw new IllegalArgumentException(
+ "The client certificate does not meet 192-bit mode requirements.");
+ }
+ if (!WifiEnterpriseConfig.isSuiteBCipherCert(
+ enterpriseConfig.getCaCertificate())) {
+ throw new IllegalArgumentException(
+ "The CA certificate does not meet 192-bit mode requirements.");
+ }
+
+ mWpa3EnterpriseConfig = new WifiEnterpriseConfig(enterpriseConfig);
+ mWpa3EnterpriseType = WPA3_ENTERPRISE_192_BIT;
+ return this;
+ }
+
+ /**
* Set the associated Passpoint configuration for this network. Needed for authenticating
* to Hotspot 2.0 networks. See {@link PasspointConfiguration} for description.
*
@@ -333,6 +453,42 @@
}
/**
+ * Set the subscription ID of the SIM card for which this suggestion is targeted.
+ * The suggestion will only apply to that SIM card.
+ * <p>
+ * The subscription ID must belong to a carrier ID which meets either of the following
+ * conditions:
+ * <li>The carrier ID specified by the cross carrier provider, or</li>
+ * <li>The carrier ID which is used to validate the suggesting carrier-privileged app, see
+ * {@link TelephonyManager#hasCarrierPrivileges()}</li>
+ *
+ * @param subId subscription ID see {@link SubscriptionInfo#getSubscriptionId()}
+ * @return Instance of {@link Builder} to enable chaining of the builder method.
+ */
+ public @NonNull Builder setSubscriptionId(int subId) {
+ if (!SdkLevel.isAtLeastS()) {
+ throw new UnsupportedOperationException();
+ }
+ mSubscriptionId = subId;
+ return this;
+ }
+
+ /**
+ * Set the priority group ID, {@link #setPriority(int)} will only impact the network
+ * suggestions from the same priority group within the same app.
+ *
+ * @param priorityGroup priority group id, if not set default is 0.
+ * @return Instance of {@link Builder} to enable chaining of the builder method.
+ */
+ public @NonNull Builder setPriorityGroup(int priorityGroup) {
+ if (!SdkLevel.isAtLeastS()) {
+ throw new UnsupportedOperationException();
+ }
+ mPriorityGroup = priorityGroup;
+ return this;
+ }
+
+ /**
* Set the ASCII WAPI passphrase for this network. Needed for authenticating to
* WAPI-PSK networks.
*
@@ -380,6 +536,30 @@
}
/**
+ * Specifies the MAC randomization method.
+ * <p>
+ * Suggested networks will never use the device (factory) MAC address to associate to the
+ * network - instead they use a locally generated random MAC address. This method controls
+ * the strategy for generating the random MAC address:
+ * <li> Persisted MAC randomization (false - the default): generates the MAC address from a
+ * secret seed and information from the Wi-Fi configuration (SSID or Passpoint profile).
+ * This means that the same generated MAC address will be used for each subsequent
+ * association. </li>
+ * <li> Enhanced MAC randomization (true): periodically generates a new MAC
+ * address for new connections. Under this option, the randomized MAC address should change
+ * if the suggestion is removed and then added back. </li>
+ *
+ * @param enabled {@code true} to periodically change the randomized MAC address.
+ * {@code false} to use the same randomized MAC for all connections to this
+ * network.
+ * @return Instance of {@link Builder} to enable chaining of the builder method.
+ */
+ public @NonNull Builder setIsEnhancedMacRandomizationEnabled(boolean enabled) {
+ mIsEnhancedMacRandomizationEnabled = enabled;
+ return this;
+ }
+
+ /**
* Specifies whether the app needs to log in to a captive portal to obtain Internet access.
* <p>
* This will dictate if the directed broadcast
@@ -415,8 +595,9 @@
/**
* Specify the priority of this network among other network suggestions provided by the same
- * app (priorities have no impact on suggestions by different apps). The higher the number,
- * the higher the priority (i.e value of 0 = lowest priority).
+ * app (priorities have no impact on suggestions by different apps) and within the same
+ * priority group, see {@link #setPriorityGroup(int)}.
+ * The higher the number, the higher the priority (i.e value of 0 = lowest priority).
* <p>
* <li>If not set, defaults a lower priority than any assigned priority.</li>
*
@@ -494,12 +675,15 @@
/**
* Specifies whether the system will bring up the network (if selected) as untrusted. An
- * untrusted network has its {@link android.net.NetworkCapabilities#NET_CAPABILITY_TRUSTED}
+ * untrusted network has its {@link NetworkCapabilities#NET_CAPABILITY_TRUSTED}
* capability removed. The Wi-Fi network selection process may use this information to
* influence priority of the suggested network for Wi-Fi network selection (most likely to
* reduce it). The connectivity service may use this information to influence the overall
* network configuration of the device.
* <p>
+ * <li> These suggestions are only considered for network selection if a
+ * {@link NetworkRequest} without {@link NetworkCapabilities#NET_CAPABILITY_TRUSTED}
+ * capability is filed.
* <li> An untrusted network's credentials may not be shared with the user using
* {@link #setCredentialSharedWithUser(boolean)}.</li>
* <li> If not set, defaults to false (i.e. network is trusted).</li>
@@ -513,6 +697,118 @@
return this;
}
+ /**
+ * Specifies whether the system will bring up the network (if selected) as OEM paid. An
+ * OEM paid network has {@link NetworkCapabilities#NET_CAPABILITY_OEM_PAID} capability
+ * added.
+ * Note:
+ * <li>The connectivity service may use this information to influence the overall
+ * network configuration of the device. This network is typically only available to system
+ * apps.
+ * <li>On devices which do not support concurrent connection (indicated via
+ * {@link WifiManager#isMultiStaConcurrencySupported()}, Wi-Fi network selection process may
+ * use this information to influence priority of the suggested network for Wi-Fi network
+ * selection (most likely to reduce it).
+ * <li>On devices which support more than 1 concurrent connections (indicated via
+ * {@link WifiManager#isMultiStaConcurrencySupported()}, these OEM paid networks will be
+ * brought up as a secondary concurrent connection (primary connection will be used
+ * for networks available to the user and all apps.
+ * <p>
+ * <li> An OEM paid network's credentials may not be shared with the user using
+ * {@link #setCredentialSharedWithUser(boolean)}.</li>
+ * <li> These suggestions are only considered for network selection if a
+ * {@link NetworkRequest} with {@link NetworkCapabilities#NET_CAPABILITY_OEM_PAID}
+ * capability is filed.
+ * <li> Each suggestion can have both {@link #setOemPaid(boolean)} and
+ * {@link #setOemPrivate(boolean)} set if the app wants these suggestions considered
+ * for creating either an OEM paid network or OEM private network determined based on
+ * the {@link NetworkRequest} that is active.
+ * <li> If not set, defaults to false (i.e. network is not OEM paid).</li>
+ *
+ * @param isOemPaid Boolean indicating whether the network should be brought up as OEM paid
+ * (if true) or not OEM paid (if false).
+ * @return Instance of {@link Builder} to enable chaining of the builder method.
+ * @hide
+ */
+ @SystemApi
+ public @NonNull Builder setOemPaid(boolean isOemPaid) {
+ if (!SdkLevel.isAtLeastS()) {
+ throw new UnsupportedOperationException();
+ }
+ mIsNetworkOemPaid = isOemPaid;
+ return this;
+ }
+
+ /**
+ * Specifies whether the system will bring up the network (if selected) as OEM private. An
+ * OEM private network has {@link NetworkCapabilities#NET_CAPABILITY_OEM_PRIVATE} capability
+ * added.
+ * Note:
+ * <li>The connectivity service may use this information to influence the overall
+ * network configuration of the device. This network is typically only available to system
+ * apps.
+ * <li>On devices which do not support concurrent connection (indicated via
+ * {@link WifiManager#isMultiStaConcurrencySupported()}, Wi-Fi network selection process may
+ * use this information to influence priority of the suggested network for Wi-Fi network
+ * selection (most likely to reduce it).
+ * <li>On devices which support more than 1 concurrent connections (indicated via
+ * {@link WifiManager#isMultiStaConcurrencySupported()}, these OEM private networks will be
+ * brought up as a secondary concurrent connection (primary connection will be used
+ * for networks available to the user and all apps.
+ * <p>
+ * <li> An OEM private network's credentials may not be shared with the user using
+ * {@link #setCredentialSharedWithUser(boolean)}.</li>
+ * <li> These suggestions are only considered for network selection if a
+ * {@link NetworkRequest} with {@link NetworkCapabilities#NET_CAPABILITY_OEM_PRIVATE}
+ * capability is filed.
+ * <li> Each suggestion can have both {@link #setOemPaid(boolean)} and
+ * {@link #setOemPrivate(boolean)} set if the app wants these suggestions considered
+ * for creating either an OEM paid network or OEM private network determined based on
+ * the {@link NetworkRequest} that is active.
+ * <li> If not set, defaults to false (i.e. network is not OEM private).</li>
+ *
+ * @param isOemPrivate Boolean indicating whether the network should be brought up as OEM
+ * private (if true) or not OEM private (if false).
+ * @return Instance of {@link Builder} to enable chaining of the builder method.
+ * @hide
+ */
+ @SystemApi
+ public @NonNull Builder setOemPrivate(boolean isOemPrivate) {
+ if (!SdkLevel.isAtLeastS()) {
+ throw new UnsupportedOperationException();
+ }
+ mIsNetworkOemPrivate = isOemPrivate;
+ return this;
+ }
+
+ /**
+ * Specifies whether the suggestion represents a carrier merged network. A carrier merged
+ * Wi-Fi network is treated as part of the mobile carrier network. Such configuration may
+ * impact the user interface and data usage accounting.
+ * <p>
+ * <li>A suggestion marked as carrier merged must be metered enterprise network with a valid
+ * subscription Id set.
+ * @see #setIsMetered(boolean)
+ * @see #setSubscriptionId(int)
+ * @see #setWpa2EnterpriseConfig(WifiEnterpriseConfig)
+ * @see #setWpa3Enterprise192BitModeConfig(WifiEnterpriseConfig)
+ * @see #setWpa3EnterpriseStandardModeConfig(WifiEnterpriseConfig)
+ * @see #setPasspointConfig(PasspointConfiguration)
+ * </li>
+ * <li>If not set, defaults to false (i.e. not a carrier merged network.)</li>
+ * </p>
+ * @param isCarrierMerged Boolean indicating whether the network is treated a carrier
+ * merged network (if true) or non-merged network (if false);
+ * @return Instance of {@link Builder} to enable chaining of the builder method.
+ */
+ public @NonNull Builder setCarrierMerged(boolean isCarrierMerged) {
+ if (!SdkLevel.isAtLeastS()) {
+ throw new UnsupportedOperationException();
+ }
+ mIsCarrierMerged = isCarrierMerged;
+ return this;
+ }
+
private void setSecurityParamsInWifiConfiguration(
@NonNull WifiConfiguration configuration) {
if (!TextUtils.isEmpty(mWpa2PskPassphrase)) { // WPA-PSK network.
@@ -527,23 +823,23 @@
configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP);
configuration.enterpriseConfig = mWpa2EnterpriseConfig;
} else if (mWpa3EnterpriseConfig != null) { // WPA3-Enterprise
- if (mWpa3EnterpriseConfig.getEapMethod() == WifiEnterpriseConfig.Eap.TLS
+ if (mWpa3EnterpriseType == WPA3_ENTERPRISE_AUTO
+ && mWpa3EnterpriseConfig.getEapMethod() == WifiEnterpriseConfig.Eap.TLS
&& WifiEnterpriseConfig.isSuiteBCipherCert(
mWpa3EnterpriseConfig.getClientCertificate())
&& WifiEnterpriseConfig.isSuiteBCipherCert(
mWpa3EnterpriseConfig.getCaCertificate())) {
- // WPA3-Enterprise in 192-bit security mode (Suite-B)
- configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP_SUITE_B);
+ // WPA3-Enterprise in 192-bit security mode
+ configuration.setSecurityParams(
+ WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT);
+ } else if (mWpa3EnterpriseType == WPA3_ENTERPRISE_192_BIT) {
+ // WPA3-Enterprise in 192-bit security mode
+ configuration.setSecurityParams(
+ WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT);
} else {
// WPA3-Enterprise
- configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP);
- configuration.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
- configuration.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
- configuration.allowedPairwiseCiphers.set(
- WifiConfiguration.PairwiseCipher.GCMP_256);
- configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
- configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_256);
- configuration.requirePmf = true;
+ configuration.setSecurityParams(
+ WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE);
}
configuration.enterpriseConfig = mWpa3EnterpriseConfig;
} else if (mIsEnhancedOpen) { // OWE network
@@ -579,6 +875,13 @@
wifiConfiguration.meteredOverride = mMeteredOverride;
wifiConfiguration.carrierId = mCarrierId;
wifiConfiguration.trusted = !mIsNetworkUntrusted;
+ wifiConfiguration.oemPaid = mIsNetworkOemPaid;
+ wifiConfiguration.oemPrivate = mIsNetworkOemPrivate;
+ wifiConfiguration.carrierMerged = mIsCarrierMerged;
+ wifiConfiguration.macRandomizationSetting = mIsEnhancedMacRandomizationEnabled
+ ? WifiConfiguration.RANDOMIZATION_ENHANCED
+ : WifiConfiguration.RANDOMIZATION_PERSISTENT;
+ wifiConfiguration.subscriptionId = mSubscriptionId;
return wifiConfiguration;
}
@@ -607,8 +910,19 @@
wifiConfiguration.priority = mPriority;
wifiConfiguration.meteredOverride = mMeteredOverride;
wifiConfiguration.trusted = !mIsNetworkUntrusted;
+ wifiConfiguration.oemPaid = mIsNetworkOemPaid;
+ wifiConfiguration.oemPrivate = mIsNetworkOemPrivate;
+ wifiConfiguration.carrierMerged = mIsCarrierMerged;
+ wifiConfiguration.subscriptionId = mSubscriptionId;
mPasspointConfiguration.setCarrierId(mCarrierId);
+ mPasspointConfiguration.setSubscriptionId(mSubscriptionId);
mPasspointConfiguration.setMeteredOverride(wifiConfiguration.meteredOverride);
+ mPasspointConfiguration.setOemPrivate(mIsNetworkOemPrivate);
+ mPasspointConfiguration.setOemPaid(mIsNetworkOemPaid);
+ mPasspointConfiguration.setCarrierMerged(mIsCarrierMerged);
+ wifiConfiguration.macRandomizationSetting = mIsEnhancedMacRandomizationEnabled
+ ? WifiConfiguration.RANDOMIZATION_ENHANCED
+ : WifiConfiguration.RANDOMIZATION_PERSISTENT;
return wifiConfiguration;
}
@@ -677,6 +991,8 @@
+ "suggestion with Passpoint configuration");
}
wifiConfiguration = buildWifiConfigurationForPasspoint();
+ mPasspointConfiguration.setEnhancedMacRandomizationEnabled(
+ mIsEnhancedMacRandomizationEnabled);
} else {
if (mSsid == null) {
throw new IllegalStateException("setSsid should be invoked for suggestion");
@@ -707,20 +1023,52 @@
if (mIsSharedWithUserSet && mIsSharedWithUser) {
throw new IllegalStateException("Should not be both"
+ "setCredentialSharedWithUser and +"
- + "setIsNetworkAsUntrusted to true");
+ + "setUntrusted to true");
}
mIsSharedWithUser = false;
}
+ if (mIsNetworkOemPaid) {
+ if (mIsSharedWithUserSet && mIsSharedWithUser) {
+ throw new IllegalStateException("Should not be both"
+ + "setCredentialSharedWithUser and +"
+ + "setOemPaid to true");
+ }
+ mIsSharedWithUser = false;
+ }
+ if (mIsNetworkOemPrivate) {
+ if (mIsSharedWithUserSet && mIsSharedWithUser) {
+ throw new IllegalStateException("Should not be both"
+ + "setCredentialSharedWithUser and +"
+ + "setOemPrivate to true");
+ }
+ mIsSharedWithUser = false;
+ }
+ if (mIsCarrierMerged) {
+ if (mSubscriptionId == SubscriptionManager.INVALID_SUBSCRIPTION_ID
+ || mMeteredOverride != WifiConfiguration.METERED_OVERRIDE_METERED
+ || !isEnterpriseSuggestion()) {
+ throw new IllegalStateException("A carrier merged network must be a metered, "
+ + "enterprise network with valid subscription Id");
+ }
+ }
return new WifiNetworkSuggestion(
wifiConfiguration,
mPasspointConfiguration,
mIsAppInteractionRequired,
mIsUserInteractionRequired,
mIsSharedWithUser,
- mIsInitialAutojoinEnabled);
+ mIsInitialAutojoinEnabled,
+ mPriorityGroup);
+ }
+
+ private boolean isEnterpriseSuggestion() {
+ return !(mWpa2EnterpriseConfig == null && mWpa3EnterpriseConfig == null
+ && mWapiEnterpriseConfig == null && mPasspointConfiguration == null);
}
}
+
+
/**
* Network configuration for the provided network.
* @hide
@@ -760,6 +1108,12 @@
*/
public final boolean isInitialAutoJoinEnabled;
+ /**
+ * Priority group ID.
+ * @hide
+ */
+ public final int priorityGroup;
+
/** @hide */
public WifiNetworkSuggestion() {
this.wifiConfiguration = new WifiConfiguration();
@@ -768,6 +1122,7 @@
this.isUserInteractionRequired = false;
this.isUserAllowedToManuallyConnect = true;
this.isInitialAutoJoinEnabled = true;
+ this.priorityGroup = 0;
}
/** @hide */
@@ -776,7 +1131,7 @@
boolean isAppInteractionRequired,
boolean isUserInteractionRequired,
boolean isUserAllowedToManuallyConnect,
- boolean isInitialAutoJoinEnabled) {
+ boolean isInitialAutoJoinEnabled, int priorityGroup) {
checkNotNull(networkConfiguration);
this.wifiConfiguration = networkConfiguration;
this.passpointConfiguration = passpointConfiguration;
@@ -785,6 +1140,7 @@
this.isUserInteractionRequired = isUserInteractionRequired;
this.isUserAllowedToManuallyConnect = isUserAllowedToManuallyConnect;
this.isInitialAutoJoinEnabled = isInitialAutoJoinEnabled;
+ this.priorityGroup = priorityGroup;
}
public static final @NonNull Creator<WifiNetworkSuggestion> CREATOR =
@@ -797,7 +1153,8 @@
in.readBoolean(), // isAppInteractionRequired
in.readBoolean(), // isUserInteractionRequired
in.readBoolean(), // isSharedCredentialWithUser
- in.readBoolean() // isAutojoinEnabled
+ in.readBoolean(), // isAutojoinEnabled
+ in.readInt() // priorityGroup
);
}
@@ -820,12 +1177,15 @@
dest.writeBoolean(isUserInteractionRequired);
dest.writeBoolean(isUserAllowedToManuallyConnect);
dest.writeBoolean(isInitialAutoJoinEnabled);
+ dest.writeInt(priorityGroup);
}
@Override
public int hashCode() {
return Objects.hash(wifiConfiguration.SSID, wifiConfiguration.BSSID,
- wifiConfiguration.allowedKeyManagement, wifiConfiguration.getKey());
+ wifiConfiguration.getDefaultSecurityType(),
+ wifiConfiguration.getPasspointUniqueId(),
+ wifiConfiguration.subscriptionId, wifiConfiguration.carrierId);
}
/**
@@ -846,10 +1206,12 @@
return TextUtils.equals(this.wifiConfiguration.SSID, lhs.wifiConfiguration.SSID)
&& TextUtils.equals(this.wifiConfiguration.BSSID, lhs.wifiConfiguration.BSSID)
- && Objects.equals(this.wifiConfiguration.allowedKeyManagement,
- lhs.wifiConfiguration.allowedKeyManagement)
- && TextUtils.equals(this.wifiConfiguration.getKey(),
- lhs.wifiConfiguration.getKey());
+ && TextUtils.equals(this.wifiConfiguration.getDefaultSecurityType(),
+ lhs.wifiConfiguration.getDefaultSecurityType())
+ && TextUtils.equals(this.wifiConfiguration.getPasspointUniqueId(),
+ lhs.wifiConfiguration.getPasspointUniqueId())
+ && this.wifiConfiguration.carrierId == lhs.wifiConfiguration.carrierId
+ && this.wifiConfiguration.subscriptionId == lhs.wifiConfiguration.subscriptionId;
}
@Override
@@ -863,6 +1225,10 @@
.append(", isCredentialSharedWithUser=").append(isUserAllowedToManuallyConnect)
.append(", isInitialAutoJoinEnabled=").append(isInitialAutoJoinEnabled)
.append(", isUnTrusted=").append(!wifiConfiguration.trusted)
+ .append(", isOemPaid=").append(wifiConfiguration.oemPaid)
+ .append(", isOemPrivate=").append(wifiConfiguration.oemPrivate)
+ .append(", isCarrierMerged").append(wifiConfiguration.carrierMerged)
+ .append(", priorityGroup=").append(priorityGroup)
.append(" ]");
return sb.toString();
}
@@ -957,6 +1323,40 @@
}
/**
+ * @see Builder#setOemPaid(boolean)
+ * @hide
+ */
+ @SystemApi
+ public boolean isOemPaid() {
+ if (!SdkLevel.isAtLeastS()) {
+ throw new UnsupportedOperationException();
+ }
+ return wifiConfiguration.oemPaid;
+ }
+
+ /**
+ * @see Builder#setOemPrivate(boolean)
+ * @hide
+ */
+ @SystemApi
+ public boolean isOemPrivate() {
+ if (!SdkLevel.isAtLeastS()) {
+ throw new UnsupportedOperationException();
+ }
+ return wifiConfiguration.oemPrivate;
+ }
+
+ /**
+ * @see Builder#setCarrierMerged(boolean)
+ */
+ public boolean isCarrierMerged() {
+ if (!SdkLevel.isAtLeastS()) {
+ throw new UnsupportedOperationException();
+ }
+ return wifiConfiguration.carrierMerged;
+ }
+
+ /**
* Get the WifiEnterpriseConfig, or null if unset.
* @see Builder#setWapiEnterpriseConfig(WifiEnterpriseConfig)
* @see Builder#setWpa2EnterpriseConfig(WifiEnterpriseConfig)
@@ -983,4 +1383,24 @@
}
return WifiInfo.removeDoubleQuotes(wifiConfiguration.preSharedKey);
}
+
+ /**
+ * @see Builder#setPriorityGroup(int)
+ */
+ public int getPriorityGroup() {
+ if (!SdkLevel.isAtLeastS()) {
+ throw new UnsupportedOperationException();
+ }
+ return priorityGroup;
+ }
+
+ /**
+ * @see Builder#setSubscriptionId(int)
+ */
+ public int getSubscriptionId() {
+ if (!SdkLevel.isAtLeastS()) {
+ throw new UnsupportedOperationException();
+ }
+ return wifiConfiguration.subscriptionId;
+ }
}
diff --git a/framework/java/android/net/wifi/WifiScanner.java b/framework/java/android/net/wifi/WifiScanner.java
index 4163c88..7c051f0 100644
--- a/framework/java/android/net/wifi/WifiScanner.java
+++ b/framework/java/android/net/wifi/WifiScanner.java
@@ -68,7 +68,9 @@
/** @hide */
public static final int WIFI_BAND_INDEX_6_GHZ = 3;
/** @hide */
- public static final int WIFI_BAND_COUNT = 4;
+ public static final int WIFI_BAND_INDEX_60_GHZ = 4;
+ /** @hide */
+ public static final int WIFI_BAND_COUNT = 5;
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@@ -76,7 +78,8 @@
WIFI_BAND_INDEX_24_GHZ,
WIFI_BAND_INDEX_5_GHZ,
WIFI_BAND_INDEX_5_GHZ_DFS_ONLY,
- WIFI_BAND_INDEX_6_GHZ})
+ WIFI_BAND_INDEX_6_GHZ,
+ WIFI_BAND_INDEX_60_GHZ})
public @interface WifiBandIndex {}
/** no band specified; use channel list instead */
@@ -89,6 +92,8 @@
public static final int WIFI_BAND_5_GHZ_DFS_ONLY = 1 << WIFI_BAND_INDEX_5_GHZ_DFS_ONLY;
/** 6 GHz band */
public static final int WIFI_BAND_6_GHZ = 1 << WIFI_BAND_INDEX_6_GHZ;
+ /** 60 GHz band */
+ public static final int WIFI_BAND_60_GHZ = 1 << WIFI_BAND_INDEX_60_GHZ;
/**
* Combination of bands
@@ -113,6 +118,12 @@
/** 2.4 GHz band and 5 GHz band; with DFS channels and 6 GHz */
public static final int WIFI_BAND_24_5_WITH_DFS_6_GHZ =
WIFI_BAND_BOTH_WITH_DFS | WIFI_BAND_6_GHZ;
+ /** @hide */
+ public static final int WIFI_BAND_24_5_6_60_GHZ =
+ WIFI_BAND_24_5_6_GHZ | WIFI_BAND_60_GHZ;
+ /** @hide */
+ public static final int WIFI_BAND_24_5_WITH_DFS_6_60_GHZ =
+ WIFI_BAND_24_5_6_60_GHZ | WIFI_BAND_5_GHZ_DFS_ONLY;
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@@ -127,7 +138,10 @@
WIFI_BAND_BOTH_WITH_DFS,
WIFI_BAND_6_GHZ,
WIFI_BAND_24_5_6_GHZ,
- WIFI_BAND_24_5_WITH_DFS_6_GHZ})
+ WIFI_BAND_24_5_WITH_DFS_6_GHZ,
+ WIFI_BAND_60_GHZ,
+ WIFI_BAND_24_5_6_60_GHZ,
+ WIFI_BAND_24_5_WITH_DFS_6_60_GHZ})
public @interface WifiBand {}
/**
@@ -179,7 +193,8 @@
* @hide
*/
public static boolean isFullBandScan(@WifiBand int bandScanned, boolean excludeDfs) {
- return (bandScanned | WIFI_BAND_6_GHZ | (excludeDfs ? WIFI_BAND_5_GHZ_DFS_ONLY : 0))
+ return (bandScanned | WIFI_BAND_6_GHZ | WIFI_BAND_60_GHZ
+ | (excludeDfs ? WIFI_BAND_5_GHZ_DFS_ONLY : 0))
== WIFI_BAND_ALL;
}
@@ -571,6 +586,19 @@
}
}
+ /** {@hide} */
+ public void addResults(@NonNull ScanData s) {
+ mBandScanned |= s.mBandScanned;
+ mFlags |= s.mFlags;
+ addResults(s.getResults());
+ }
+
+ /** {@hide} */
+ public boolean isFullBandScanResults() {
+ return (mBandScanned & WifiScanner.WIFI_BAND_24_GHZ) != 0
+ && (mBandScanned & WifiScanner.WIFI_BAND_5_GHZ) != 0;
+ }
+
/** Implement the Parcelable interface {@hide} */
public int describeContents() {
return 0;
diff --git a/framework/java/android/net/wifi/aware/AwareResources.java b/framework/java/android/net/wifi/aware/AwareResources.java
new file mode 100644
index 0000000..cee1f40
--- /dev/null
+++ b/framework/java/android/net/wifi/aware/AwareResources.java
@@ -0,0 +1,146 @@
+/*
+ * 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.aware;
+
+import android.annotation.NonNull;
+import android.os.Handler;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * The resources of the Aware service.
+ */
+public final class AwareResources implements Parcelable {
+ /**
+ * Number of the NDPs are available.
+ */
+ private int mNumOfAvailableNdps;
+
+ /**
+ * Number of the publish sessions are available.
+ */
+ private int mNumOfAvailablePublishSessions;
+
+ /**
+ * Number of the subscribe sessions are available.
+ */
+ private int mNumOfAvailableSubscribeSessions;
+
+ /**
+ * @hide : should not be created by apps
+ */
+ public AwareResources() {
+ }
+
+ /**
+ * Return the number of Aware data-paths (also known as NDPs - NAN Data Paths) which an app
+ * could create. Please refer to the {@link WifiAwareNetworkSpecifier} to create
+ * a Network Specifier and request a data-path.
+ * <p>
+ * Note that these resources aren't reserved - other apps could use them by the time you
+ * attempt to create a data-path.
+ * </p>
+ * @return A Non-negative integer, number of data-paths that could be created.
+ */
+ public int getNumOfAvailableDataPaths() {
+ return mNumOfAvailableNdps;
+ }
+
+ /**
+ * Return the number of Aware publish sessions which an app could create. Please refer to the
+ * {@link WifiAwareSession#publish(PublishConfig, DiscoverySessionCallback, Handler)}
+ * to create a publish session.
+ * <p>
+ * Note that these resources aren't reserved - other apps could use them by the time you
+ * attempt to create a publish session.
+ * </p>
+ * @return A Non-negative integer, number of publish sessions that could be created.
+ */
+ public int getNumOfAvailablePublishSessions() {
+ return mNumOfAvailablePublishSessions;
+ }
+
+ /**
+ * Return the number of Aware subscribe sessions which an app could create. Please refer to the
+ * {@link WifiAwareSession#subscribe(SubscribeConfig, DiscoverySessionCallback, Handler)}
+ * to create a publish session.
+ * <p>
+ * Note that these resources aren't reserved - other apps could use them by the time you
+ * attempt to create a subscribe session.
+ * </p>
+ * @return A Non-negative integer, number of subscribe sessions that could be created.
+ */
+ public int getNumOfAvailableSubscribeSessions() {
+ return mNumOfAvailableSubscribeSessions;
+ }
+
+ /**
+ * Set the number of the available NDPs.
+ * @hide
+ * @param numOfAvailableNdps Number of available NDPs.
+ */
+ public void setNumOfAvailableDataPaths(int numOfAvailableNdps) {
+ mNumOfAvailableNdps = numOfAvailableNdps;
+ }
+
+ /**
+ * Set the number of the available publish sessions.
+ * @hide
+ * @param numOfAvailablePublishSessions Number of available publish sessions.
+ */
+ public void setNumOfAvailablePublishSessions(int numOfAvailablePublishSessions) {
+ mNumOfAvailablePublishSessions = numOfAvailablePublishSessions;
+ }
+
+ /**
+ * Set the number of the available subscribe sessions.
+ * @hide
+ * @param numOfAvailableSubscribeSessions Number of available subscribe sessions.
+ */
+ public void setNumOfAvailableSubscribeSessions(int numOfAvailableSubscribeSessions) {
+ mNumOfAvailableSubscribeSessions = numOfAvailableSubscribeSessions;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeInt(mNumOfAvailableNdps);
+ dest.writeInt(mNumOfAvailablePublishSessions);
+ dest.writeInt(mNumOfAvailableSubscribeSessions);
+ }
+
+ public static final @android.annotation.NonNull Creator<AwareResources> CREATOR =
+ new Creator<AwareResources>() {
+ @Override
+ public AwareResources createFromParcel(Parcel in) {
+ AwareResources awareResources = new AwareResources();
+ awareResources.setNumOfAvailableDataPaths(in.readInt());
+ awareResources.setNumOfAvailablePublishSessions(in.readInt());
+ awareResources.setNumOfAvailableSubscribeSessions(in.readInt());
+ return awareResources;
+ }
+
+ @Override
+ public AwareResources[] newArray(int size) {
+ return new AwareResources[size];
+ }
+ };
+}
diff --git a/framework/java/android/net/wifi/aware/Characteristics.java b/framework/java/android/net/wifi/aware/Characteristics.java
index d5fd48e..9bdda7f 100644
--- a/framework/java/android/net/wifi/aware/Characteristics.java
+++ b/framework/java/android/net/wifi/aware/Characteristics.java
@@ -21,6 +21,8 @@
import android.os.Parcel;
import android.os.Parcelable;
+import com.android.modules.utils.build.SdkLevel;
+
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -37,6 +39,9 @@
public static final String KEY_MAX_MATCH_FILTER_LENGTH = "key_max_match_filter_length";
/** @hide */
public static final String KEY_SUPPORTED_CIPHER_SUITES = "key_supported_cipher_suites";
+ /** @hide */
+ public static final String KEY_IS_INSTANT_COMMUNICATION_MODE_SUPPORTED =
+ "key_is_instant_communication_mode_supported";
private Bundle mCharacteristics = new Bundle();
@@ -83,6 +88,17 @@
return mCharacteristics.getInt(KEY_MAX_MATCH_FILTER_LENGTH);
}
+ /**
+ * Check if instant communication mode is supported by device.
+ * @return True if supported, false otherwise.
+ */
+ public boolean isInstantCommunicationModeSupported() {
+ if (!SdkLevel.isAtLeastS()) {
+ throw new UnsupportedOperationException();
+ }
+ return mCharacteristics.getBoolean(KEY_IS_INSTANT_COMMUNICATION_MODE_SUPPORTED);
+ }
+
/** @hide */
@IntDef(flag = true, prefix = { "WIFI_AWARE_CIPHER_SUITE_" }, value = {
WIFI_AWARE_CIPHER_SUITE_NCS_SK_128,
diff --git a/framework/java/android/net/wifi/aware/DiscoverySessionCallback.java b/framework/java/android/net/wifi/aware/DiscoverySessionCallback.java
index bfb0462..da8e17e 100644
--- a/framework/java/android/net/wifi/aware/DiscoverySessionCallback.java
+++ b/framework/java/android/net/wifi/aware/DiscoverySessionCallback.java
@@ -189,4 +189,20 @@
public void onMessageReceived(PeerHandle peerHandle, byte[] message) {
/* empty */
}
+
+ /**
+ * Called when the discovered service is not available. All further operations on this
+ * discovery session will fail. If the service is available again,
+ * {@link #onServiceDiscovered(PeerHandle, byte[], List)} or
+ * {@link #onServiceDiscoveredWithinRange(PeerHandle, byte[], List, int)} will be called.
+ *
+ * @param peerHandle An opaque handle to the peer matching our discovery operation.
+ * @param reason Discovered service lost reason code. One of
+ * {@link WifiAwareManager#WIFI_AWARE_DISCOVERY_LOST_REASON_PEER_NOT_VISIBLE},
+ * {@link WifiAwareManager#WIFI_AWARE_DISCOVERY_LOST_REASON_UNKNOWN
+ */
+ public void onServiceLost(@NonNull PeerHandle peerHandle,
+ @WifiAwareManager.DiscoveryLostReasonCode int reason) {
+ /* empty */
+ }
}
diff --git a/framework/java/android/net/wifi/aware/IWifiAwareDiscoverySessionCallback.aidl b/framework/java/android/net/wifi/aware/IWifiAwareDiscoverySessionCallback.aidl
index 421a8af..e3e7c8e 100644
--- a/framework/java/android/net/wifi/aware/IWifiAwareDiscoverySessionCallback.aidl
+++ b/framework/java/android/net/wifi/aware/IWifiAwareDiscoverySessionCallback.aidl
@@ -35,4 +35,5 @@
void onMessageSendSuccess(int messageId);
void onMessageSendFail(int messageId, int reason);
void onMessageReceived(int peerId, in byte[] message);
+ void onMatchExpired(int peerId);
}
diff --git a/framework/java/android/net/wifi/aware/IWifiAwareManager.aidl b/framework/java/android/net/wifi/aware/IWifiAwareManager.aidl
index 88f95ad..c90c4d8 100644
--- a/framework/java/android/net/wifi/aware/IWifiAwareManager.aidl
+++ b/framework/java/android/net/wifi/aware/IWifiAwareManager.aidl
@@ -25,6 +25,7 @@
import android.net.wifi.aware.PublishConfig;
import android.net.wifi.aware.SubscribeConfig;
import android.net.wifi.aware.Characteristics;
+import android.net.wifi.aware.AwareResources;
/**
* Interface that WifiAwareService implements
@@ -36,6 +37,10 @@
// Aware API
boolean isUsageEnabled();
Characteristics getCharacteristics();
+ AwareResources getAvailableAwareResources();
+ boolean isDeviceAttached();
+ void enableInstantCommunicationMode(in String callingPackage, boolean enable);
+ boolean isInstantCommunicationModeEnabled();
// client API
void connect(in IBinder binder, in String callingPackage, in String callingFeatureId,
diff --git a/framework/java/android/net/wifi/aware/WifiAwareManager.java b/framework/java/android/net/wifi/aware/WifiAwareManager.java
index c2ae17c..540bf2a 100644
--- a/framework/java/android/net/wifi/aware/WifiAwareManager.java
+++ b/framework/java/android/net/wifi/aware/WifiAwareManager.java
@@ -22,6 +22,7 @@
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.content.Context;
import android.net.ConnectivityManager;
@@ -37,6 +38,8 @@
import android.os.RemoteException;
import android.util.Log;
+import com.android.modules.utils.build.SdkLevel;
+
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.ref.WeakReference;
@@ -151,6 +154,27 @@
*/
public static final int WIFI_AWARE_DATA_PATH_ROLE_RESPONDER = 1;
+ /** @hide */
+ @IntDef({
+ WIFI_AWARE_DISCOVERY_LOST_REASON_UNKNOWN,
+ WIFI_AWARE_DISCOVERY_LOST_REASON_PEER_NOT_VISIBLE})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface DiscoveryLostReasonCode {
+ }
+
+ /**
+ * Reason code provided in {@link DiscoverySessionCallback#onServiceLost(PeerHandle, int)}
+ * indicating that the service was lost for unknown reason.
+ */
+ public static final int WIFI_AWARE_DISCOVERY_LOST_REASON_UNKNOWN = 0;
+
+ /**
+ * Reason code provided in {@link DiscoverySessionCallback#onServiceLost(PeerHandle, int)}
+ * indicating that the service advertised by the peer is no longer visible. This may be because
+ * the peer is out of range or because the peer stopped advertising this service.
+ */
+ public static final int WIFI_AWARE_DISCOVERY_LOST_REASON_PEER_NOT_VISIBLE = 1;
+
private final Context mContext;
private final IWifiAwareManager mService;
@@ -179,12 +203,67 @@
}
/**
+ * Return the current status of the Aware service: whether ot not the device is already attached
+ * to an Aware cluster. To attach to an Aware cluster, please use
+ * {@link #attach(AttachCallback, Handler)} or
+ * {@link #attach(AttachCallback, IdentityChangedListener, Handler)}.
+ * @return A boolean indicating whether the device is attached to a cluster at this time (true)
+ * or not (false).
+ */
+ public boolean isDeviceAttached() {
+ if (!SdkLevel.isAtLeastS()) {
+ throw new UnsupportedOperationException();
+ }
+ try {
+ return mService.isDeviceAttached();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Enable the Wifi Aware Instant communication mode. If the device doesn't support this feature
+ * calling this API will result no action.
+ * @see Characteristics#isInstantCommunicationModeSupported()
+ * @param enable true for enable, false otherwise.
+ * @hide
+ */
+ @SystemApi
+ public void enableInstantCommunicationMode(boolean enable) {
+ if (!SdkLevel.isAtLeastS()) {
+ throw new UnsupportedOperationException();
+ }
+ try {
+ mService.enableInstantCommunicationMode(mContext.getOpPackageName(), enable);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Return the current status of the Wifi Aware instant communication mode.
+ * If the device doesn't support this feature, return will always be false.
+ * @see Characteristics#isInstantCommunicationModeSupported()
+ * @return true if it is enabled, false otherwise.
+ */
+ public boolean isInstantCommunicationModeEnabled() {
+ if (!SdkLevel.isAtLeastS()) {
+ throw new UnsupportedOperationException();
+ }
+ try {
+ return mService.isInstantCommunicationModeEnabled();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Returns the characteristics of the Wi-Fi Aware interface: a set of parameters which specify
* limitations on configurations, e.g. the maximum service name length.
*
* @return An object specifying configuration limitations of Aware.
*/
- public Characteristics getCharacteristics() {
+ public @Nullable Characteristics getCharacteristics() {
try {
return mService.getCharacteristics();
} catch (RemoteException e) {
@@ -193,6 +272,23 @@
}
/**
+ * Return the available resources of the Wi-Fi aware service: a set of parameters which specify
+ * limitations on service usage, e.g the number of data-paths which could be created..
+ *
+ * @return An object specifying the currently available resource of the Wi-Fi Aware service.
+ */
+ public @Nullable AwareResources getAvailableAwareResources() {
+ if (!SdkLevel.isAtLeastS()) {
+ throw new UnsupportedOperationException();
+ }
+ try {
+ return mService.getAvailableAwareResources();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Attach to the Wi-Fi Aware service - enabling the application to create discovery sessions or
* create connections to peers. The device will attach to an existing cluster if it can find
* one or create a new cluster (if it is the first to enable Aware in its vicinity). Results
@@ -587,6 +683,7 @@
private static final int CALLBACK_MESSAGE_SEND_FAIL = 6;
private static final int CALLBACK_MESSAGE_RECEIVED = 7;
private static final int CALLBACK_MATCH_WITH_DISTANCE = 8;
+ private static final int CALLBACK_MATCH_EXPIRED = 9;
private static final String MESSAGE_BUNDLE_KEY_MESSAGE = "message";
private static final String MESSAGE_BUNDLE_KEY_MESSAGE2 = "message2";
@@ -676,6 +773,14 @@
mOriginalCallback.onMessageReceived(new PeerHandle(msg.arg1),
(byte[]) msg.obj);
break;
+ case CALLBACK_MATCH_EXPIRED:
+ if (!SdkLevel.isAtLeastS()) {
+ break;
+ }
+ mOriginalCallback
+ .onServiceLost(new PeerHandle(msg.arg1),
+ WIFI_AWARE_DISCOVERY_LOST_REASON_PEER_NOT_VISIBLE);
+ break;
}
}
};
@@ -746,6 +851,15 @@
onMatchCommon(CALLBACK_MATCH_WITH_DISTANCE, peerId, serviceSpecificInfo, matchFilter,
distanceMm);
}
+ @Override
+ public void onMatchExpired(int peerId) {
+ if (VDBG) {
+ Log.v(TAG, "onMatchExpired: peerId=" + peerId);
+ }
+ Message msg = mHandler.obtainMessage(CALLBACK_MATCH_EXPIRED);
+ msg.arg1 = peerId;
+ mHandler.sendMessage(msg);
+ }
@Override
public void onMessageSendSuccess(int messageId) {
diff --git a/framework/java/android/net/wifi/hotspot2/PasspointConfiguration.java b/framework/java/android/net/wifi/hotspot2/PasspointConfiguration.java
index d1d1780..006fbaa 100644
--- a/framework/java/android/net/wifi/hotspot2/PasspointConfiguration.java
+++ b/framework/java/android/net/wifi/hotspot2/PasspointConfiguration.java
@@ -30,6 +30,8 @@
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;
@@ -412,6 +414,12 @@
private int mCarrierId = TelephonyManager.UNKNOWN_CARRIER_ID;
/**
+ * The subscription ID identifies the SIM card who provides this network configuration.
+ * See {@link SubscriptionInfo#getSubscriptionId()}
+ */
+ private int mSubscriptionId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+
+ /**
* Set the carrier ID associated with current configuration.
* @param carrierId {@code mCarrierId}
* @hide
@@ -430,6 +438,24 @@
}
/**
+ * Set the subscription ID associated with current configuration.
+ * @param subscriptionId {@code mSubscriptionId}
+ * @hide
+ */
+ public void setSubscriptionId(int subscriptionId) {
+ this.mSubscriptionId = subscriptionId;
+ }
+
+ /**
+ * Get the carrier ID associated with current configuration.
+ * @return {@code mSubscriptionId}
+ * @hide
+ */
+ public int getSubscriptionId() {
+ return mSubscriptionId;
+ }
+
+ /**
* The auto-join configuration specifies whether or not the Passpoint Configuration is
* considered for auto-connection. If true then yes, if false then it isn't considered as part
* of auto-connection - but can still be manually connected to.
@@ -444,6 +470,32 @@
private boolean mIsMacRandomizationEnabled = true;
/**
+ * Whether this passpoint configuration should use enhanced MAC randomization.
+ */
+ private boolean mIsEnhancedMacRandomizationEnabled = false;
+
+
+ /**
+ * Indicate whether the network is oem paid or not. Networks are considered oem paid
+ * if the corresponding connection is only available to system apps.
+ * @hide
+ */
+ private boolean mIsOemPaid;
+
+ /**
+ * Indicate whether the network is oem private or not. Networks are considered oem private
+ * if the corresponding connection is only available to system apps.
+ * @hide
+ */
+ private boolean mIsOemPrivate;
+
+ /**
+ * Indicate whether or not the network is a carrier merged network.
+ * @hide
+ */
+ private boolean mIsCarrierMerged;
+
+ /**
* Indicates if the end user has expressed an explicit opinion about the
* meteredness of this network, such as through the Settings app.
* This value is one of {@link #METERED_OVERRIDE_NONE}, {@link #METERED_OVERRIDE_METERED},
@@ -481,6 +533,20 @@
}
/**
+ * This setting is only applicable if MAC randomization is enabled.
+ * If set to true, the framework will periodically generate new MAC addresses for new
+ * connections.
+ * If set to false (the default), the framework will use the same locally generated MAC address
+ * for connections to this passpoint configuration.
+ * @param enabled true to use enhanced MAC randomization, false to use persistent MAC
+ * randomization.
+ * @hide
+ */
+ public void setEnhancedMacRandomizationEnabled(boolean enabled) {
+ mIsEnhancedMacRandomizationEnabled = enabled;
+ }
+
+ /**
* Sets the metered override setting for this Passpoint configuration.
*
* @param meteredOverride One of the values in {@link MeteredOverride}
@@ -531,6 +597,67 @@
}
/**
+ * When MAC randomization is enabled, this indicates whether enhanced MAC randomization or
+ * persistent MAC randomization will be used for connections to this Passpoint network.
+ * If true, the MAC address used for connections will periodically change. Otherwise, the same
+ * locally generated MAC will be used for all connections to this passpoint configuration.
+ *
+ * @return true for enhanced MAC randomization enabled. False for disabled.
+ * @hide
+ */
+ public boolean isEnhancedMacRandomizationEnabled() {
+ return mIsEnhancedMacRandomizationEnabled;
+ }
+
+ /**
+ * Set whether the network is oem paid or not.
+ * @hide
+ */
+ public void setOemPaid(boolean isOemPaid) {
+ mIsOemPaid = isOemPaid;
+ }
+
+ /**
+ * Get whether the network is oem paid or not.
+ * @hide
+ */
+ public boolean isOemPaid() {
+ return mIsOemPaid;
+ }
+
+ /**
+ * Set whether the network is oem private or not.
+ * @hide
+ */
+ public void setOemPrivate(boolean isOemPrivate) {
+ mIsOemPrivate = isOemPrivate;
+ }
+
+ /**
+ * Get whether the network is oem private or not.
+ * @hide
+ */
+ public boolean isOemPrivate() {
+ return mIsOemPrivate;
+ }
+
+ /**
+ * Set whether the network is carrier merged or not.
+ * @hide
+ */
+ public void setCarrierMerged(boolean isCarrierMerged) {
+ mIsCarrierMerged = isCarrierMerged;
+ }
+
+ /**
+ * Get whether the network is carrier merged or not.
+ * @hide
+ */
+ public boolean isCarrierMerged() {
+ return mIsCarrierMerged;
+ }
+
+ /**
* Constructor for creating PasspointConfiguration with default values.
*/
public PasspointConfiguration() {}
@@ -572,9 +699,14 @@
mServiceFriendlyNames = source.mServiceFriendlyNames;
mAaaServerTrustedNames = source.mAaaServerTrustedNames;
mCarrierId = source.mCarrierId;
+ mSubscriptionId = source.mSubscriptionId;
mIsAutojoinEnabled = source.mIsAutojoinEnabled;
mIsMacRandomizationEnabled = source.mIsMacRandomizationEnabled;
+ mIsEnhancedMacRandomizationEnabled = source.mIsEnhancedMacRandomizationEnabled;
mMeteredOverride = source.mMeteredOverride;
+ mIsCarrierMerged = source.mIsCarrierMerged;
+ mIsOemPaid = source.mIsOemPaid;
+ mIsOemPrivate = source.mIsOemPrivate;
}
@Override
@@ -606,7 +738,12 @@
dest.writeInt(mCarrierId);
dest.writeBoolean(mIsAutojoinEnabled);
dest.writeBoolean(mIsMacRandomizationEnabled);
+ dest.writeBoolean(mIsEnhancedMacRandomizationEnabled);
dest.writeInt(mMeteredOverride);
+ dest.writeInt(mSubscriptionId);
+ dest.writeBoolean(mIsCarrierMerged);
+ dest.writeBoolean(mIsOemPaid);
+ dest.writeBoolean(mIsOemPrivate);
}
@Override
@@ -637,8 +774,13 @@
&& mUsageLimitDataLimit == that.mUsageLimitDataLimit
&& mUsageLimitTimeLimitInMinutes == that.mUsageLimitTimeLimitInMinutes
&& mCarrierId == that.mCarrierId
+ && mSubscriptionId == that.mSubscriptionId
+ && mIsOemPrivate == that.mIsOemPrivate
+ && mIsOemPaid == that.mIsOemPaid
+ && mIsCarrierMerged == that.mIsCarrierMerged
&& mIsAutojoinEnabled == that.mIsAutojoinEnabled
&& mIsMacRandomizationEnabled == that.mIsMacRandomizationEnabled
+ && mIsEnhancedMacRandomizationEnabled == that.mIsEnhancedMacRandomizationEnabled
&& mMeteredOverride == that.mMeteredOverride
&& (mServiceFriendlyNames == null ? that.mServiceFriendlyNames == null
: mServiceFriendlyNames.equals(that.mServiceFriendlyNames));
@@ -651,7 +793,8 @@
mSubscriptionExpirationTimeMillis, mUsageLimitUsageTimePeriodInMinutes,
mUsageLimitStartTimeInMillis, mUsageLimitDataLimit, mUsageLimitTimeLimitInMinutes,
mServiceFriendlyNames, mCarrierId, mIsAutojoinEnabled, mIsMacRandomizationEnabled,
- mMeteredOverride);
+ mIsEnhancedMacRandomizationEnabled, mMeteredOverride, mSubscriptionId,
+ mIsCarrierMerged, mIsOemPaid, mIsOemPrivate);
}
@Override
@@ -705,9 +848,14 @@
builder.append("ServiceFriendlyNames: ").append(mServiceFriendlyNames);
}
builder.append("CarrierId:" + mCarrierId);
+ builder.append("SubscriptionId:" + mSubscriptionId);
builder.append("IsAutojoinEnabled:" + mIsAutojoinEnabled);
builder.append("mIsMacRandomizationEnabled:" + mIsMacRandomizationEnabled);
+ builder.append("mIsEnhancedMacRandomizationEnabled:" + mIsEnhancedMacRandomizationEnabled);
builder.append("mMeteredOverride:" + mMeteredOverride);
+ builder.append("mIsCarrierMerged:" + mIsCarrierMerged);
+ builder.append("mIsOemPaid:" + mIsOemPaid);
+ builder.append("mIsOemPrivate" + mIsOemPrivate);
return builder.toString();
}
@@ -815,7 +963,13 @@
config.mCarrierId = in.readInt();
config.mIsAutojoinEnabled = in.readBoolean();
config.mIsMacRandomizationEnabled = in.readBoolean();
+ config.mIsEnhancedMacRandomizationEnabled = in.readBoolean();
config.mMeteredOverride = in.readInt();
+ config.mSubscriptionId = in.readInt();
+ config.mIsCarrierMerged = in.readBoolean();
+ config.mIsOemPaid = in.readBoolean();
+ config.mIsOemPrivate = in.readBoolean();
+
return config;
}
diff --git a/framework/java/android/net/wifi/hotspot2/pps/HomeSp.java b/framework/java/android/net/wifi/hotspot2/pps/HomeSp.java
index 8f34579..64aad61 100644
--- a/framework/java/android/net/wifi/hotspot2/pps/HomeSp.java
+++ b/framework/java/android/net/wifi/hotspot2/pps/HomeSp.java
@@ -16,6 +16,8 @@
package android.net.wifi.hotspot2.pps;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
@@ -23,6 +25,7 @@
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
+import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
@@ -139,16 +142,26 @@
* (MO) tree for more detail.
*/
private long[] mMatchAllOis = null;
+
/**
- * @hide
+ * Set a list of HomeOIs such that all OIs in the list must match an OI in the Roaming
+ * Consortium advertised by a hotspot operator. The list set by this API will have precedence
+ * over {@link #setMatchAnyOis(long[])}, meaning the list set in {@link #setMatchAnyOis(long[])}
+ * will only be used for matching if the list set by this API is null or empty.
+ *
+ * @param matchAllOis An array of longs containing the HomeOIs
*/
- public void setMatchAllOis(long[] matchAllOis) {
+ public void setMatchAllOis(@Nullable long[] matchAllOis) {
mMatchAllOis = matchAllOis;
}
+
/**
- * @hide
+ * Get the list of HomeOIs such that all OIs in the list must match an OI in the Roaming
+ * Consortium advertised by a hotspot operator.
+ *
+ * @return An array of longs containing the HomeOIs
*/
- public long[] getMatchAllOis() {
+ public @Nullable long[] getMatchAllOis() {
return mMatchAllOis;
}
@@ -159,23 +172,34 @@
* of that Hotspot provider (e.g. successful authentication with such Hotspot
* is possible).
*
- * {@link #mMatchAllOIs} will have precedence over this one, meaning this list will
- * only be used for matching if {@link #mMatchAllOIs} is null or empty.
+ * The list set by {@link #setMatchAllOis(long[])} will have precedence over this one, meaning
+ * this list will only be used for matching if the list set by {@link #setMatchAllOis(long[])}
+ * is null or empty.
*
* Refer to HomeSP/HomeOIList subtree in PerProviderSubscription (PPS) Management Object
* (MO) tree for more detail.
*/
private long[] mMatchAnyOis = null;
+
/**
- * @hide
+ * Set a list of HomeOIs such that any OI in the list matches an OI in the Roaming Consortium
+ * advertised by a hotspot operator. The list set by {@link #setMatchAllOis(long[])}
+ * will have precedence over this API, meaning this list will only be used for matching if the
+ * list set by {@link #setMatchAllOis(long[])} is null or empty.
+ *
+ * @param matchAnyOis An array of longs containing the HomeOIs
*/
- public void setMatchAnyOis(long[] matchAnyOis) {
+ public void setMatchAnyOis(@Nullable long[] matchAnyOis) {
mMatchAnyOis = matchAnyOis;
}
+
/**
- * @hide
+ * Get a list of HomeOIs such that any OI in the list matches an OI in the Roaming Consortium
+ * advertised by a hotspot operator.
+ *
+ * @return An array of longs containing the HomeOIs
*/
- public long[] getMatchAnyOis() {
+ public @Nullable long[] getMatchAnyOis() {
return mMatchAnyOis;
}
@@ -186,20 +210,58 @@
* operator merges between the providers.
*/
private String[] mOtherHomePartners = null;
+
/**
+ * Set the list of FQDN (Fully Qualified Domain Name) of other Home partner providers.
+ *
+ * @param otherHomePartners Array of Strings containing the FQDNs of other Home partner
+ * providers
* @hide
*/
- public void setOtherHomePartners(String[] otherHomePartners) {
+ public void setOtherHomePartners(@Nullable String[] otherHomePartners) {
mOtherHomePartners = otherHomePartners;
}
+
/**
+ * Set the list of FQDN (Fully Qualified Domain Name) of other Home partner providers.
+ *
+ * @param otherHomePartners Collection of Strings containing the FQDNs of other Home partner
+ * providers
+ */
+ public void setOtherHomePartnersList(@NonNull Collection<String> otherHomePartners) {
+ if (otherHomePartners == null) {
+ return;
+ }
+ mOtherHomePartners = otherHomePartners.toArray(new String[otherHomePartners.size()]);
+ }
+
+ /**
+ * Get the list of FQDN (Fully Qualified Domain Name) of other Home partner providers set in
+ * the profile.
+ *
+ * @return Array of Strings containing the FQDNs of other Home partner providers set in the
+ * profile
* @hide
*/
- public String[] getOtherHomePartners() {
+ public @Nullable String[] getOtherHomePartners() {
return mOtherHomePartners;
}
/**
+ * Get the list of FQDN (Fully Qualified Domain Name) of other Home partner providers set in
+ * the profile.
+ *
+ * @return Collection of Strings containing the FQDNs of other Home partner providers set in the
+ * profile
+ */
+ public @NonNull Collection<String> getOtherHomePartnersList() {
+ if (mOtherHomePartners == null) {
+ return Collections.emptyList();
+ }
+ return Arrays.asList(mOtherHomePartners);
+ }
+
+ /**
* List of Organization Identifiers (OIs) identifying a roaming consortium of
* which this provider is a member.
*/
diff --git a/framework/java/android/net/wifi/p2p/IWifiP2pManager.aidl b/framework/java/android/net/wifi/p2p/IWifiP2pManager.aidl
index bfdd45d..fd89d3b 100644
--- a/framework/java/android/net/wifi/p2p/IWifiP2pManager.aidl
+++ b/framework/java/android/net/wifi/p2p/IWifiP2pManager.aidl
@@ -25,7 +25,7 @@
*/
interface IWifiP2pManager
{
- Messenger getMessenger(in IBinder binder);
+ Messenger getMessenger(in IBinder binder, in String packageName);
Messenger getP2pStateMachineMessenger();
oneway void close(in IBinder binder);
void setMiracastMode(int mode);
diff --git a/framework/java/android/net/wifi/p2p/WifiP2pManager.java b/framework/java/android/net/wifi/p2p/WifiP2pManager.java
index 5a27087..13ac7a0 100644
--- a/framework/java/android/net/wifi/p2p/WifiP2pManager.java
+++ b/framework/java/android/net/wifi/p2p/WifiP2pManager.java
@@ -1156,8 +1156,8 @@
*/
public Channel initialize(Context srcContext, Looper srcLooper, ChannelListener listener) {
Binder binder = new Binder();
- Channel channel = initalizeChannel(srcContext, srcLooper, listener, getMessenger(binder),
- binder);
+ Channel channel = initializeChannel(srcContext, srcLooper, listener,
+ getMessenger(binder, srcContext.getOpPackageName()), binder);
return channel;
}
@@ -1167,12 +1167,12 @@
*/
public Channel initializeInternal(Context srcContext, Looper srcLooper,
ChannelListener listener) {
- return initalizeChannel(srcContext, srcLooper, listener, getP2pStateMachineMessenger(),
+ return initializeChannel(srcContext, srcLooper, listener, getP2pStateMachineMessenger(),
null);
}
- private Channel initalizeChannel(Context srcContext, Looper srcLooper, ChannelListener listener,
- Messenger messenger, Binder binder) {
+ private Channel initializeChannel(Context srcContext, Looper srcLooper,
+ ChannelListener listener, Messenger messenger, Binder binder) {
if (messenger == null) return null;
Channel c = new Channel(srcContext, srcLooper, listener, binder, this);
@@ -1814,6 +1814,14 @@
}
}
+ private Messenger getMessenger(@NonNull Binder binder, @Nullable String packageName) {
+ try {
+ return mService.getMessenger(binder, packageName);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
/**
* Get a reference to WifiP2pService handler. This is used to establish
* an AsyncChannel communication with WifiService
@@ -1824,11 +1832,8 @@
* @hide
*/
public Messenger getMessenger(Binder binder) {
- try {
- return mService.getMessenger(binder);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ // No way to determine package name in this case.
+ return getMessenger(binder, null);
}
/**
diff --git a/framework/java/android/net/wifi/rtt/RangingRequest.java b/framework/java/android/net/wifi/rtt/RangingRequest.java
index 318efa6..04dfcf2 100644
--- a/framework/java/android/net/wifi/rtt/RangingRequest.java
+++ b/framework/java/android/net/wifi/rtt/RangingRequest.java
@@ -30,8 +30,11 @@
import android.os.Parcel;
import android.os.Parcelable;
+import com.android.modules.utils.build.SdkLevel;
+
import java.util.ArrayList;
import java.util.List;
+import java.util.Objects;
import java.util.StringJoiner;
/**
@@ -46,6 +49,9 @@
*/
public final class RangingRequest implements Parcelable {
private static final int MAX_PEERS = 10;
+ private static final int DEFAULT_RTT_BURST_SIZE = 8;
+ private static final int MIN_RTT_BURST_SIZE = 2;
+ private static final int MAX_RTT_BURST_SIZE = 17;
/**
* Returns the maximum number of peers to range which can be specified in a single {@code
@@ -59,12 +65,80 @@
return MAX_PEERS;
}
+ /**
+ * Returns the default RTT burst size used to determine the average range.
+ *
+ * @return the RTT burst size used by default
+ */
+ public static int getDefaultRttBurstSize() {
+ if (!SdkLevel.isAtLeastS()) {
+ throw new UnsupportedOperationException();
+ }
+ return DEFAULT_RTT_BURST_SIZE;
+ }
+
+ /**
+ * Returns the minimum RTT burst size that can be used to determine a average range.
+ *
+ * @return the minimum RTT burst size that can be used
+ */
+ public static int getMinRttBurstSize() {
+ if (!SdkLevel.isAtLeastS()) {
+ throw new UnsupportedOperationException();
+ }
+ return MIN_RTT_BURST_SIZE;
+ }
+
+ /**
+ * Returns the minimum RTT burst size that can be used to determine a average range.
+ *
+ * @return the maximum RTT burst size that can be used
+ */
+ public static int getMaxRttBurstSize() {
+ if (!SdkLevel.isAtLeastS()) {
+ throw new UnsupportedOperationException();
+ }
+ return MAX_RTT_BURST_SIZE;
+ }
+
/** @hide */
public final List<ResponderConfig> mRttPeers;
/** @hide */
- private RangingRequest(List<ResponderConfig> rttPeers) {
+ public final int mRttBurstSize;
+
+ /** @hide */
+ private RangingRequest(List<ResponderConfig> rttPeers, int rttBurstSize) {
mRttPeers = rttPeers;
+ mRttBurstSize = rttBurstSize;
+ }
+
+ /**
+ * Returns the list of RTT capable peers.
+ *
+ * @return the list of RTT capable peers in a common system representation
+ *
+ * @hide
+ */
+ @SystemApi
+ @NonNull
+ public List<ResponderConfig> getRttPeers() {
+ if (!SdkLevel.isAtLeastS()) {
+ throw new UnsupportedOperationException();
+ }
+ return mRttPeers;
+ }
+
+ /**
+ * Returns the RTT burst size used to determine the average range.
+ *
+ * @return the RTT burst size used
+ */
+ public int getRttBurstSize() {
+ if (!SdkLevel.isAtLeastS()) {
+ throw new UnsupportedOperationException();
+ }
+ return mRttBurstSize;
}
@Override
@@ -75,6 +149,7 @@
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeList(mRttPeers);
+ dest.writeInt(mRttBurstSize);
}
public static final @android.annotation.NonNull Creator<RangingRequest> CREATOR = new Creator<RangingRequest>() {
@@ -85,7 +160,7 @@
@Override
public RangingRequest createFromParcel(Parcel in) {
- return new RangingRequest(in.readArrayList(null));
+ return new RangingRequest(in.readArrayList(null), in.readInt());
}
};
@@ -105,12 +180,20 @@
throw new IllegalArgumentException(
"Ranging to too many peers requested. Use getMaxPeers() API to get limit.");
}
-
for (ResponderConfig peer: mRttPeers) {
if (!peer.isValid(awareSupported)) {
throw new IllegalArgumentException("Invalid Responder specification");
}
}
+ if (SdkLevel.isAtLeastS()) {
+ if (mRttBurstSize < getMinRttBurstSize() || mRttBurstSize > getMaxRttBurstSize()) {
+ throw new IllegalArgumentException("RTT burst size is out of range");
+ }
+ } else {
+ if (mRttBurstSize != DEFAULT_RTT_BURST_SIZE) {
+ throw new IllegalArgumentException("RTT burst size is not the default value");
+ }
+ }
}
/**
@@ -118,6 +201,32 @@
*/
public static final class Builder {
private List<ResponderConfig> mRttPeers = new ArrayList<>();
+ private int mRttBurstSize = DEFAULT_RTT_BURST_SIZE;
+
+ /**
+ * Set the RTT Burst size for the ranging request.
+ * <p>
+ * If not set, the default RTT burst size given by
+ * {@link #getDefaultRttBurstSize()} is used to determine the default value.
+ * If set, the value must be in the range {@link #getMinRttBurstSize()} and
+ * {@link #getMaxRttBurstSize()} inclusively, or a
+ * {@link java.lang.IllegalArgumentException} will be thrown.
+ *
+ * @param rttBurstSize The number of FTM packets used to estimate a range.
+ * @return The builder to facilitate chaining
+ * {@code builder.setXXX(..).setXXX(..)}.
+ */
+ @NonNull
+ public Builder setRttBurstSize(int rttBurstSize) {
+ if (!SdkLevel.isAtLeastS()) {
+ throw new UnsupportedOperationException();
+ }
+ if (rttBurstSize < MIN_RTT_BURST_SIZE || rttBurstSize > MAX_RTT_BURST_SIZE) {
+ throw new IllegalArgumentException("RTT burst size out of range.");
+ }
+ mRttBurstSize = rttBurstSize;
+ return this;
+ }
/**
* Add the device specified by the {@link ScanResult} to the list of devices with
@@ -241,7 +350,7 @@
* builder.
*/
public RangingRequest build() {
- return new RangingRequest(mRttPeers);
+ return new RangingRequest(mRttPeers, mRttBurstSize);
}
}
@@ -257,11 +366,13 @@
RangingRequest lhs = (RangingRequest) o;
- return mRttPeers.size() == lhs.mRttPeers.size() && mRttPeers.containsAll(lhs.mRttPeers);
+ return mRttPeers.size() == lhs.mRttPeers.size()
+ && mRttPeers.containsAll(lhs.mRttPeers)
+ && mRttBurstSize == lhs.mRttBurstSize;
}
@Override
public int hashCode() {
- return mRttPeers.hashCode();
+ return Objects.hash(mRttPeers, mRttBurstSize);
}
}
diff --git a/framework/tests/Android.bp b/framework/tests/Android.bp
index 0e58740..c0be244 100644
--- a/framework/tests/Android.bp
+++ b/framework/tests/Android.bp
@@ -20,6 +20,9 @@
defaults: ["framework-wifi-test-defaults"],
+ min_sdk_version: "30",
+ target_sdk_version: "30",
+
srcs: ["**/*.java"],
jacoco: {
@@ -46,7 +49,7 @@
],
test_suites: [
- "device-tests",
+ "general-tests",
"mts",
],
diff --git a/framework/tests/AndroidManifest.xml b/framework/tests/AndroidManifest.xml
index b6c38bc..8fcf78f 100644
--- a/framework/tests/AndroidManifest.xml
+++ b/framework/tests/AndroidManifest.xml
@@ -1,5 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
-
<!--
~ Copyright (C) 2016 The Android Open Source Project
~
@@ -17,22 +16,23 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.net.wifi.test">
+ package="android.net.wifi.test">
<application>
- <uses-library android:name="android.test.runner" />
+ <uses-library android:name="android.test.runner"/>
<activity android:label="WifiTestDummyLabel"
- android:name="WifiTestDummyName">
+ android:name="WifiTestDummyName"
+ android:exported="true">
<intent-filter>
- <action android:name="android.intent.action.MAIN" />
+ <action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
<instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
- android:targetPackage="android.net.wifi.test"
- android:label="Frameworks Wifi API Tests">
+ android:targetPackage="android.net.wifi.test"
+ android:label="Frameworks Wifi API Tests">
</instrumentation>
</manifest>
diff --git a/framework/tests/AndroidTest.xml b/framework/tests/AndroidTest.xml
index 34e2e3a..2cdaddb 100644
--- a/framework/tests/AndroidTest.xml
+++ b/framework/tests/AndroidTest.xml
@@ -20,6 +20,8 @@
<option name="test-suite-tag" value="apct" />
<option name="test-tag" value="FrameworksWifiApiTests" />
+ <option name="config-descriptor:metadata" key="mainline-param"
+ value="com.google.android.wifi.apex" />
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="android.net.wifi.test" />
<option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
diff --git a/framework/tests/src/android/net/wifi/CoexUnsafeChannelTest.java b/framework/tests/src/android/net/wifi/CoexUnsafeChannelTest.java
new file mode 100644
index 0000000..320f25e
--- /dev/null
+++ b/framework/tests/src/android/net/wifi/CoexUnsafeChannelTest.java
@@ -0,0 +1,97 @@
+/*
+ * 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;
+
+import static android.net.wifi.WifiScanner.WIFI_BAND_24_GHZ;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.os.Parcel;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+
+/**
+ * Unit tests for {@link android.net.wifi.CoexUnsafeChannel}.
+ */
+@SmallTest
+public class CoexUnsafeChannelTest {
+ /**
+ * Verifies {@link CoexUnsafeChannel#isPowerCapAvailable()} returns false if no cap is set.
+ */
+ @Test
+ public void testIsPowerCapAvailable_noPowerCap_returnsFalse() {
+ CoexUnsafeChannel unsafeChannel = new CoexUnsafeChannel(WIFI_BAND_24_GHZ, 6);
+
+ assertThat(unsafeChannel.isPowerCapAvailable()).isFalse();
+ }
+
+ /**
+ * Verifies {@link CoexUnsafeChannel#isPowerCapAvailable()} returns true if a cap is set, and
+ * {@link CoexUnsafeChannel#getPowerCapDbm()} returns the set value.
+ */
+ @Test
+ public void testIsPowerCapAvailable_powerCapSet_returnsTrue() {
+ final int powerCapDbm = -50;
+ CoexUnsafeChannel unsafeChannel = new CoexUnsafeChannel(WIFI_BAND_24_GHZ, 6);
+
+ unsafeChannel.setPowerCapDbm(powerCapDbm);
+
+ assertThat(unsafeChannel.isPowerCapAvailable()).isTrue();
+ assertThat(unsafeChannel.getPowerCapDbm()).isEqualTo(powerCapDbm);
+ }
+
+ /**
+ * Verifies {@link CoexUnsafeChannel#getPowerCapDbm()} throws an IllegalStateException if
+ * {@link CoexUnsafeChannel#isPowerCapAvailable()} is {@code false}.
+ */
+ @Test(expected = IllegalStateException.class)
+ public void testGetPowerCap_powerCapUnavailable_throwsException() {
+ CoexUnsafeChannel unsafeChannel = new CoexUnsafeChannel(WIFI_BAND_24_GHZ, 6);
+
+ unsafeChannel.getPowerCapDbm();
+ }
+
+ /**
+ * Verify parcel read/write for CoexUnsafeChannel with or without power cap.
+ */
+ @Test
+ public void testParcelReadWrite_withOrWithoutCap_readEqualsWritten() throws Exception {
+ CoexUnsafeChannel writeUnsafeChannelNoCap =
+ new CoexUnsafeChannel(WIFI_BAND_24_GHZ, 6);
+ CoexUnsafeChannel writeUnsafeChannelCapped =
+ new CoexUnsafeChannel(WIFI_BAND_24_GHZ, 6, -50);
+
+ CoexUnsafeChannel readUnsafeChannelNoCap = parcelReadWrite(writeUnsafeChannelNoCap);
+ CoexUnsafeChannel readUnsafeChannelCapped = parcelReadWrite(writeUnsafeChannelCapped);
+
+ assertThat(writeUnsafeChannelNoCap).isEqualTo(readUnsafeChannelNoCap);
+ assertThat(writeUnsafeChannelCapped).isEqualTo(readUnsafeChannelCapped);
+ }
+
+ /**
+ * Write the provided {@link CoexUnsafeChannel} to a parcel and deserialize it.
+ */
+ private static CoexUnsafeChannel parcelReadWrite(CoexUnsafeChannel writeResult)
+ throws Exception {
+ Parcel parcel = Parcel.obtain();
+ writeResult.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0); // Rewind data position back to the beginning for read.
+ return CoexUnsafeChannel.CREATOR.createFromParcel(parcel);
+ }
+}
diff --git a/framework/tests/src/android/net/wifi/EasyConnectStatusCallbackTest.java b/framework/tests/src/android/net/wifi/EasyConnectStatusCallbackTest.java
index b101414..cf37b78 100644
--- a/framework/tests/src/android/net/wifi/EasyConnectStatusCallbackTest.java
+++ b/framework/tests/src/android/net/wifi/EasyConnectStatusCallbackTest.java
@@ -19,6 +19,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
+import android.annotation.NonNull;
import android.util.SparseArray;
import androidx.test.filters.SmallTest;
@@ -52,6 +53,11 @@
mOnFailureR1EventReceived = true;
mLastCode = code;
}
+
+ @Override
+ public void onBootstrapUriGenerated(@NonNull String uri) {
+
+ }
};
private boolean mOnFailureR1EventReceived;
private int mLastCode;
diff --git a/framework/tests/src/android/net/wifi/ScanResultTest.java b/framework/tests/src/android/net/wifi/ScanResultTest.java
index f1ec5e8..59b88a7 100644
--- a/framework/tests/src/android/net/wifi/ScanResultTest.java
+++ b/framework/tests/src/android/net/wifi/ScanResultTest.java
@@ -44,6 +44,7 @@
public static final long TEST_TSF = 04660l;
public static final @WifiAnnotations.WifiStandard int TEST_WIFI_STANDARD =
ScanResult.WIFI_STANDARD_11AC;
+ public static final String TEST_IFACE_NAME = "test_ifname";
/**
* Frequency to channel map. This include some frequencies used outside the US.
@@ -220,7 +221,7 @@
+ "passpoint: no, ChannelBandwidth: 0, centerFreq0: 0, centerFreq1: 0, "
+ "standard: 11ac, "
+ "80211mcResponder: is not supported, "
- + "Radio Chain Infos: null", scanResult.toString());
+ + "Radio Chain Infos: null, interface name: test_ifname", scanResult.toString());
}
/**
@@ -243,7 +244,8 @@
+ "standard: 11ac, "
+ "80211mcResponder: is not supported, "
+ "Radio Chain Infos: [RadioChainInfo: id=0, level=-45, "
- + "RadioChainInfo: id=1, level=-54]", scanResult.toString());
+ + "RadioChainInfo: id=1, level=-54], interface name: test_ifname",
+ scanResult.toString());
}
/**
@@ -284,6 +286,8 @@
result.frequency = TEST_FREQUENCY;
result.timestamp = TEST_TSF;
result.setWifiStandard(TEST_WIFI_STANDARD);
+ result.ifaceName = TEST_IFACE_NAME;
+
return result;
}
diff --git a/framework/tests/src/android/net/wifi/SecurityParamsTest.java b/framework/tests/src/android/net/wifi/SecurityParamsTest.java
new file mode 100644
index 0000000..c586ded
--- /dev/null
+++ b/framework/tests/src/android/net/wifi/SecurityParamsTest.java
@@ -0,0 +1,556 @@
+/*
+ * 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;
+
+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 android.net.wifi.WifiConfiguration.AuthAlgorithm;
+import android.net.wifi.WifiConfiguration.GroupCipher;
+import android.net.wifi.WifiConfiguration.GroupMgmtCipher;
+import android.net.wifi.WifiConfiguration.KeyMgmt;
+import android.net.wifi.WifiConfiguration.PairwiseCipher;
+import android.net.wifi.WifiConfiguration.Protocol;
+import android.os.Parcel;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+
+import java.util.BitSet;
+
+/**
+ * Unit tests for {@link android.net.wifi.WifiInfo}.
+ */
+@SmallTest
+public class SecurityParamsTest {
+
+ private void verifySecurityParams(SecurityParams params,
+ int expectedSecurityType,
+ int[] expectedAllowedKeyManagement,
+ int[] expectedAllowedProtocols,
+ int[] expectedAllowedAuthAlgorithms,
+ int[] expectedAllowedPairwiseCiphers,
+ int[] expectedAllowedGroupCiphers,
+ boolean expectedRequirePmf) {
+ assertTrue(params.isSecurityType(expectedSecurityType));
+ assertEquals(expectedSecurityType, params.getSecurityType());
+ for (int b: expectedAllowedKeyManagement) {
+ assertTrue(params.getAllowedKeyManagement().get(b));
+ }
+ for (int b: expectedAllowedProtocols) {
+ assertTrue(params.getAllowedProtocols().get(b));
+ }
+ for (int b: expectedAllowedAuthAlgorithms) {
+ assertTrue(params.getAllowedAuthAlgorithms().get(b));
+ }
+ for (int b: expectedAllowedPairwiseCiphers) {
+ assertTrue(params.getAllowedPairwiseCiphers().get(b));
+ }
+ for (int b: expectedAllowedGroupCiphers) {
+ assertTrue(params.getAllowedGroupCiphers().get(b));
+ }
+ assertEquals(expectedRequirePmf, params.isRequirePmf());
+ }
+
+ /** Verify the security params created by security type. */
+ @Test
+ public void testSecurityTypeCreator() throws Exception {
+ int[] securityTypes = new int[] {
+ WifiConfiguration.SECURITY_TYPE_WAPI_CERT,
+ WifiConfiguration.SECURITY_TYPE_WAPI_PSK,
+ WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT,
+ WifiConfiguration.SECURITY_TYPE_OWE,
+ WifiConfiguration.SECURITY_TYPE_SAE,
+ WifiConfiguration.SECURITY_TYPE_OSEN,
+ WifiConfiguration.SECURITY_TYPE_EAP,
+ WifiConfiguration.SECURITY_TYPE_PSK,
+ WifiConfiguration.SECURITY_TYPE_OPEN,
+ WifiConfiguration.SECURITY_TYPE_PASSPOINT_R1_R2,
+ WifiConfiguration.SECURITY_TYPE_PASSPOINT_R3,
+ };
+
+ for (int type: securityTypes) {
+ assertEquals(type,
+ SecurityParams.createSecurityParamsBySecurityType(type).getSecurityType());
+ }
+ }
+
+ /** Verify EAP params creator. */
+ @Test
+ public void testEapCreator() throws Exception {
+ int expectedSecurityType = WifiConfiguration.SECURITY_TYPE_EAP;
+ int[] expectedAllowedKeyManagement = new int[] {KeyMgmt.WPA_EAP, KeyMgmt.IEEE8021X};
+ int[] expectedAllowedProtocols = new int[] {};
+ int[] expectedAllowedAuthAlgorithms = new int[] {};
+ int[] expectedAllowedPairwiseCiphers = new int[] {};
+ int[] expectedAllowedGroupCiphers = new int[] {};
+ boolean expectedRequirePmf = false;
+ SecurityParams p = SecurityParams.createSecurityParamsBySecurityType(
+ expectedSecurityType);
+ verifySecurityParams(p, expectedSecurityType,
+ expectedAllowedKeyManagement, expectedAllowedProtocols,
+ expectedAllowedAuthAlgorithms, expectedAllowedPairwiseCiphers,
+ expectedAllowedGroupCiphers, expectedRequirePmf);
+ }
+
+ /** Verify Passpoint R1/R2 params creator. */
+ @Test
+ public void testEapPasspointR1R2Creator() throws Exception {
+ int expectedSecurityType = WifiConfiguration.SECURITY_TYPE_PASSPOINT_R1_R2;
+ int[] expectedAllowedKeyManagement = new int[] {KeyMgmt.WPA_EAP, KeyMgmt.IEEE8021X};
+ int[] expectedAllowedProtocols = new int[] {};
+ int[] expectedAllowedAuthAlgorithms = new int[] {};
+ int[] expectedAllowedPairwiseCiphers = new int[] {};
+ int[] expectedAllowedGroupCiphers = new int[] {};
+ boolean expectedRequirePmf = false;
+ SecurityParams p = SecurityParams.createSecurityParamsBySecurityType(
+ expectedSecurityType);
+ verifySecurityParams(p, expectedSecurityType,
+ expectedAllowedKeyManagement, expectedAllowedProtocols,
+ expectedAllowedAuthAlgorithms, expectedAllowedPairwiseCiphers,
+ expectedAllowedGroupCiphers, expectedRequirePmf);
+ }
+
+ /** Verify Passpoint R3 params creator. */
+ @Test
+ public void testEapPasspointR3Creator() throws Exception {
+ int expectedSecurityType = WifiConfiguration.SECURITY_TYPE_PASSPOINT_R3;
+ int[] expectedAllowedKeyManagement = new int[] {KeyMgmt.WPA_EAP, KeyMgmt.IEEE8021X};
+ int[] expectedAllowedProtocols = new int[] {};
+ int[] expectedAllowedAuthAlgorithms = new int[] {};
+ int[] expectedAllowedPairwiseCiphers = new int[] {};
+ int[] expectedAllowedGroupCiphers = new int[] {};
+ boolean expectedRequirePmf = true;
+ SecurityParams p = SecurityParams.createSecurityParamsBySecurityType(
+ expectedSecurityType);
+ verifySecurityParams(p, expectedSecurityType,
+ expectedAllowedKeyManagement, expectedAllowedProtocols,
+ expectedAllowedAuthAlgorithms, expectedAllowedPairwiseCiphers,
+ expectedAllowedGroupCiphers, expectedRequirePmf);
+ }
+
+ /** Verify Enhanced Open params creator. */
+ @Test
+ public void testEnhancedOpenCreator() throws Exception {
+ int expectedSecurityType = WifiConfiguration.SECURITY_TYPE_OWE;
+ int[] expectedAllowedKeyManagement = new int[] {KeyMgmt.OWE};
+ int[] expectedAllowedProtocols = new int[] {Protocol.RSN};
+ int[] expectedAllowedAuthAlgorithms = new int[] {};
+ int[] expectedAllowedPairwiseCiphers = new int[] {
+ PairwiseCipher.CCMP, PairwiseCipher.GCMP_128, PairwiseCipher.GCMP_256};
+ int[] expectedAllowedGroupCiphers = new int[] {
+ GroupCipher.CCMP, GroupCipher.GCMP_128, GroupCipher.GCMP_256};
+ boolean expectedRequirePmf = true;
+ SecurityParams p = SecurityParams.createSecurityParamsBySecurityType(
+ expectedSecurityType);
+ verifySecurityParams(p, expectedSecurityType,
+ expectedAllowedKeyManagement, expectedAllowedProtocols,
+ expectedAllowedAuthAlgorithms, expectedAllowedPairwiseCiphers,
+ expectedAllowedGroupCiphers, expectedRequirePmf);
+ }
+
+ /** Verify Open params creator. */
+ @Test
+ public void testOpenCreator() throws Exception {
+ int expectedSecurityType = WifiConfiguration.SECURITY_TYPE_OPEN;
+ int[] expectedAllowedKeyManagement = new int[] {KeyMgmt.NONE};
+ int[] expectedAllowedProtocols = new int[] {};
+ int[] expectedAllowedAuthAlgorithms = new int[] {};
+ int[] expectedAllowedPairwiseCiphers = new int[] {};
+ int[] expectedAllowedGroupCiphers = new int[] {};
+ boolean expectedRequirePmf = false;
+ SecurityParams p = SecurityParams.createSecurityParamsBySecurityType(
+ expectedSecurityType);
+ verifySecurityParams(p, expectedSecurityType,
+ expectedAllowedKeyManagement, expectedAllowedProtocols,
+ expectedAllowedAuthAlgorithms, expectedAllowedPairwiseCiphers,
+ expectedAllowedGroupCiphers, expectedRequirePmf);
+ }
+
+ /** Verify OSEN params creator. */
+ @Test
+ public void testOsenCreator() throws Exception {
+ int expectedSecurityType = WifiConfiguration.SECURITY_TYPE_OSEN;
+ int[] expectedAllowedKeyManagement = new int[] {KeyMgmt.OSEN};
+ int[] expectedAllowedProtocols = new int[] {Protocol.OSEN};
+ int[] expectedAllowedAuthAlgorithms = new int[] {};
+ int[] expectedAllowedPairwiseCiphers = new int[] {};
+ int[] expectedAllowedGroupCiphers = new int[] {};
+ boolean expectedRequirePmf = false;
+ SecurityParams p = SecurityParams.createSecurityParamsBySecurityType(
+ expectedSecurityType);
+ verifySecurityParams(p, expectedSecurityType,
+ expectedAllowedKeyManagement, expectedAllowedProtocols,
+ expectedAllowedAuthAlgorithms, expectedAllowedPairwiseCiphers,
+ expectedAllowedGroupCiphers, expectedRequirePmf);
+ }
+
+ /** Verify WAPI CERT params creator. */
+ @Test
+ public void testWapiCertCreator() throws Exception {
+ int expectedSecurityType = WifiConfiguration.SECURITY_TYPE_WAPI_CERT;
+ int[] expectedAllowedKeyManagement = new int[] {KeyMgmt.WAPI_CERT};
+ int[] expectedAllowedProtocols = new int[] {Protocol.WAPI};
+ int[] expectedAllowedAuthAlgorithms = new int[] {};
+ int[] expectedAllowedPairwiseCiphers = new int[] {PairwiseCipher.SMS4};
+ int[] expectedAllowedGroupCiphers = new int[] {GroupCipher.SMS4};
+ boolean expectedRequirePmf = false;
+ SecurityParams p = SecurityParams.createSecurityParamsBySecurityType(
+ expectedSecurityType);
+ verifySecurityParams(p, expectedSecurityType,
+ expectedAllowedKeyManagement, expectedAllowedProtocols,
+ expectedAllowedAuthAlgorithms, expectedAllowedPairwiseCiphers,
+ expectedAllowedGroupCiphers, expectedRequirePmf);
+ }
+
+ /** Verify WAPI PSK params creator. */
+ @Test
+ public void testWapiPskCreator() throws Exception {
+ int expectedSecurityType = WifiConfiguration.SECURITY_TYPE_WAPI_PSK;
+ int[] expectedAllowedKeyManagement = new int[] {KeyMgmt.WAPI_PSK};
+ int[] expectedAllowedProtocols = new int[] {Protocol.WAPI};
+ int[] expectedAllowedAuthAlgorithms = new int[] {};
+ int[] expectedAllowedPairwiseCiphers = new int[] {PairwiseCipher.SMS4};
+ int[] expectedAllowedGroupCiphers = new int[] {GroupCipher.SMS4};
+ boolean expectedRequirePmf = false;
+ SecurityParams p = SecurityParams.createSecurityParamsBySecurityType(
+ expectedSecurityType);
+ verifySecurityParams(p, expectedSecurityType,
+ expectedAllowedKeyManagement, expectedAllowedProtocols,
+ expectedAllowedAuthAlgorithms, expectedAllowedPairwiseCiphers,
+ expectedAllowedGroupCiphers, expectedRequirePmf);
+ }
+
+ /** Verify WEP params creator. */
+ @Test
+ public void testWepCreator() throws Exception {
+ int expectedSecurityType = WifiConfiguration.SECURITY_TYPE_WEP;
+ int[] expectedAllowedKeyManagement = new int[] {KeyMgmt.NONE};
+ int[] expectedAllowedProtocols = new int[] {};
+ int[] expectedAllowedAuthAlgorithms = new int[] {AuthAlgorithm.OPEN, AuthAlgorithm.SHARED};
+ int[] expectedAllowedPairwiseCiphers = new int[] {};
+ int[] expectedAllowedGroupCiphers = new int[] {};
+ boolean expectedRequirePmf = false;
+ SecurityParams p = SecurityParams.createSecurityParamsBySecurityType(
+ expectedSecurityType);
+ verifySecurityParams(p, expectedSecurityType,
+ expectedAllowedKeyManagement, expectedAllowedProtocols,
+ expectedAllowedAuthAlgorithms, expectedAllowedPairwiseCiphers,
+ expectedAllowedGroupCiphers, expectedRequirePmf);
+ }
+
+ /** Verify WPA3 Enterprise 192-bit params creator. */
+ @Test
+ public void testWpa3Enterprise192BitCreator() throws Exception {
+ int expectedSecurityType = WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT;
+ int[] expectedAllowedKeyManagement = new int[] {
+ KeyMgmt.WPA_EAP, KeyMgmt.IEEE8021X, KeyMgmt.SUITE_B_192};
+ int[] expectedAllowedProtocols = new int[] {Protocol.RSN};
+ int[] expectedAllowedAuthAlgorithms = new int[] {};
+ int[] expectedAllowedPairwiseCiphers = new int[] {
+ PairwiseCipher.GCMP_128, PairwiseCipher.GCMP_256};
+ int[] expectedAllowedGroupCiphers = new int[] {GroupCipher.GCMP_128, GroupCipher.GCMP_256};
+ boolean expectedRequirePmf = true;
+ SecurityParams p = SecurityParams.createSecurityParamsBySecurityType(
+ expectedSecurityType);
+ verifySecurityParams(p, expectedSecurityType,
+ expectedAllowedKeyManagement, expectedAllowedProtocols,
+ expectedAllowedAuthAlgorithms, expectedAllowedPairwiseCiphers,
+ expectedAllowedGroupCiphers, expectedRequirePmf);
+
+ assertTrue(p.getAllowedGroupManagementCiphers().get(GroupMgmtCipher.BIP_GMAC_256));
+ }
+
+ /** Verify WPA3 Enterprise params creator. */
+ @Test
+ public void testWpa3EnterpriseCreator() throws Exception {
+ int expectedSecurityType = WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE;
+ int[] expectedAllowedKeyManagement = new int[] {KeyMgmt.WPA_EAP, KeyMgmt.IEEE8021X};
+ int[] expectedAllowedProtocols = new int[] {Protocol.RSN};
+ int[] expectedAllowedAuthAlgorithms = new int[] {};
+ int[] expectedAllowedPairwiseCiphers = new int[] {
+ PairwiseCipher.CCMP, PairwiseCipher.GCMP_256};
+ int[] expectedAllowedGroupCiphers = new int[] {GroupCipher.CCMP, GroupCipher.GCMP_256};
+ boolean expectedRequirePmf = true;
+ SecurityParams p = SecurityParams.createSecurityParamsBySecurityType(
+ expectedSecurityType);
+ verifySecurityParams(p, expectedSecurityType,
+ expectedAllowedKeyManagement, expectedAllowedProtocols,
+ expectedAllowedAuthAlgorithms, expectedAllowedPairwiseCiphers,
+ expectedAllowedGroupCiphers, expectedRequirePmf);
+ }
+
+ /** Verify WPA3 Personal params creator. */
+ @Test
+ public void testWpa3PersonalCreator() throws Exception {
+ int expectedSecurityType = WifiConfiguration.SECURITY_TYPE_SAE;
+ int[] expectedAllowedKeyManagement = new int[] {KeyMgmt.SAE};
+ int[] expectedAllowedProtocols = new int[] {Protocol.RSN};
+ int[] expectedAllowedAuthAlgorithms = new int[] {};
+ int[] expectedAllowedPairwiseCiphers = new int[] {
+ PairwiseCipher.CCMP, PairwiseCipher.GCMP_128, PairwiseCipher.GCMP_256};
+ int[] expectedAllowedGroupCiphers = new int[] {
+ GroupCipher.CCMP, GroupCipher.GCMP_128, GroupCipher.GCMP_256};
+ boolean expectedRequirePmf = true;
+ SecurityParams p = SecurityParams.createSecurityParamsBySecurityType(
+ expectedSecurityType);
+ verifySecurityParams(p, expectedSecurityType,
+ expectedAllowedKeyManagement, expectedAllowedProtocols,
+ expectedAllowedAuthAlgorithms, expectedAllowedPairwiseCiphers,
+ expectedAllowedGroupCiphers, expectedRequirePmf);
+ }
+
+ /** Verify WPA2 Personal EAP params creator. */
+ @Test
+ public void testWpaWpa2PersonalCreator() throws Exception {
+ int expectedSecurityType = WifiConfiguration.SECURITY_TYPE_PSK;
+ int[] expectedAllowedKeyManagement = new int[] {KeyMgmt.WPA_PSK};
+ int[] expectedAllowedProtocols = new int[] {};
+ int[] expectedAllowedAuthAlgorithms = new int[] {};
+ int[] expectedAllowedPairwiseCiphers = new int[] {};
+ int[] expectedAllowedGroupCiphers = new int[] {};
+ boolean expectedRequirePmf = false;
+ SecurityParams p = SecurityParams.createSecurityParamsBySecurityType(
+ expectedSecurityType);
+ verifySecurityParams(p, expectedSecurityType,
+ expectedAllowedKeyManagement, expectedAllowedProtocols,
+ expectedAllowedAuthAlgorithms, expectedAllowedPairwiseCiphers,
+ expectedAllowedGroupCiphers, expectedRequirePmf);
+ }
+
+ /** Verify setter/getter methods */
+ @Test
+ public void testCommonSetterGetter() throws Exception {
+ SecurityParams params = SecurityParams.createSecurityParamsBySecurityType(
+ WifiConfiguration.SECURITY_TYPE_PSK);
+
+ // PSK setting
+ BitSet allowedKeyManagement = new BitSet();
+ allowedKeyManagement.set(KeyMgmt.WPA_PSK);
+
+ BitSet allowedProtocols = new BitSet();
+ allowedProtocols.set(Protocol.RSN);
+ allowedProtocols.set(Protocol.WPA);
+
+ BitSet allowedPairwiseCiphers = new BitSet();
+ allowedPairwiseCiphers.set(PairwiseCipher.CCMP);
+ allowedPairwiseCiphers.set(PairwiseCipher.TKIP);
+
+ BitSet allowedGroupCiphers = new BitSet();
+ allowedGroupCiphers.set(GroupCipher.CCMP);
+ allowedGroupCiphers.set(GroupCipher.TKIP);
+ allowedGroupCiphers.set(GroupCipher.WEP40);
+ allowedGroupCiphers.set(GroupCipher.WEP104);
+
+ assertEquals(allowedKeyManagement, params.getAllowedKeyManagement());
+ assertTrue(params.getAllowedKeyManagement().get(KeyMgmt.WPA_PSK));
+
+ assertEquals(allowedProtocols, params.getAllowedProtocols());
+ assertTrue(params.getAllowedProtocols().get(Protocol.RSN));
+ assertTrue(params.getAllowedProtocols().get(Protocol.WPA));
+
+ assertEquals(allowedPairwiseCiphers, params.getAllowedPairwiseCiphers());
+ assertTrue(params.getAllowedPairwiseCiphers().get(PairwiseCipher.CCMP));
+ assertTrue(params.getAllowedPairwiseCiphers().get(PairwiseCipher.TKIP));
+
+ assertEquals(allowedGroupCiphers, params.getAllowedGroupCiphers());
+ assertTrue(params.getAllowedGroupCiphers().get(GroupCipher.CCMP));
+ assertTrue(params.getAllowedGroupCiphers().get(GroupCipher.TKIP));
+ assertTrue(params.getAllowedGroupCiphers().get(GroupCipher.WEP40));
+ assertTrue(params.getAllowedGroupCiphers().get(GroupCipher.WEP104));
+
+ params.setEnabled(false);
+ assertFalse(params.isEnabled());
+ }
+
+ /** Verify SAE-specific methods */
+ @Test
+ public void testSaeMethods() throws Exception {
+ SecurityParams p = SecurityParams.createSecurityParamsBySecurityType(
+ WifiConfiguration.SECURITY_TYPE_SAE);
+
+ assertFalse(p.isAddedByAutoUpgrade());
+ p.setIsAddedByAutoUpgrade(true);
+ assertTrue(p.isAddedByAutoUpgrade());
+
+ assertFalse(p.isSaeH2eOnlyMode());
+ p.enableSaeH2eOnlyMode(true);
+ assertTrue(p.isSaeH2eOnlyMode());
+
+ assertFalse(p.isSaePkOnlyMode());
+ p.enableSaePkOnlyMode(true);
+ assertTrue(p.isSaePkOnlyMode());
+ }
+
+ /** Verify copy constructor. */
+ @Test
+ public void testCopyConstructor() throws Exception {
+ SecurityParams params = SecurityParams.createSecurityParamsBySecurityType(
+ WifiConfiguration.SECURITY_TYPE_PSK);
+ params.setEnabled(false);
+ params.setIsAddedByAutoUpgrade(true);
+
+ SecurityParams copiedParams = new SecurityParams(params);
+
+ assertTrue(params.isSameSecurityType(copiedParams));
+ assertEquals(params.getAllowedKeyManagement(), copiedParams.getAllowedKeyManagement());
+ assertEquals(params.getAllowedProtocols(), copiedParams.getAllowedProtocols());
+ assertEquals(params.getAllowedAuthAlgorithms(), copiedParams.getAllowedAuthAlgorithms());
+ assertEquals(params.getAllowedPairwiseCiphers(), copiedParams.getAllowedPairwiseCiphers());
+ assertEquals(params.getAllowedGroupCiphers(), copiedParams.getAllowedGroupCiphers());
+ assertEquals(params.getAllowedGroupManagementCiphers(),
+ copiedParams.getAllowedGroupManagementCiphers());
+ assertEquals(params.getAllowedSuiteBCiphers(), copiedParams.getAllowedSuiteBCiphers());
+ assertEquals(params.isRequirePmf(), copiedParams.isRequirePmf());
+ assertEquals(params.isEnabled(), copiedParams.isEnabled());
+ assertEquals(params.isSaeH2eOnlyMode(), copiedParams.isSaeH2eOnlyMode());
+ assertEquals(params.isSaePkOnlyMode(), copiedParams.isSaePkOnlyMode());
+ assertEquals(params.isAddedByAutoUpgrade(), copiedParams.isAddedByAutoUpgrade());
+ }
+
+ /** Check that two params are equal if and only if their types are the same. */
+ @Test
+ public void testEquals() {
+ SecurityParams saeParams1 = SecurityParams.createSecurityParamsBySecurityType(
+ WifiConfiguration.SECURITY_TYPE_SAE);
+ SecurityParams saeParams2 = SecurityParams.createSecurityParamsBySecurityType(
+ WifiConfiguration.SECURITY_TYPE_SAE);
+ SecurityParams pskParams = SecurityParams.createSecurityParamsBySecurityType(
+ WifiConfiguration.SECURITY_TYPE_PSK);
+ assertEquals(saeParams1, saeParams2);
+ assertNotEquals(saeParams1, pskParams);
+ }
+
+ /** Check that hash values are the same if and only if their types are the same. */
+ @Test
+ public void testHashCode() {
+ SecurityParams saeParams1 = SecurityParams.createSecurityParamsBySecurityType(
+ WifiConfiguration.SECURITY_TYPE_SAE);
+ SecurityParams saeParams2 = SecurityParams.createSecurityParamsBySecurityType(
+ WifiConfiguration.SECURITY_TYPE_SAE);
+ SecurityParams pskParams = SecurityParams.createSecurityParamsBySecurityType(
+ WifiConfiguration.SECURITY_TYPE_PSK);
+ assertEquals(saeParams1.hashCode(), saeParams2.hashCode());
+ assertNotEquals(saeParams1.hashCode(), pskParams.hashCode());
+ }
+
+ /** Verify open network check */
+ @Test
+ public void testIsOpenNetwork() {
+ SecurityParams[] openSecurityParams = new SecurityParams[] {
+ SecurityParams.createSecurityParamsBySecurityType(
+ WifiConfiguration.SECURITY_TYPE_OWE),
+ SecurityParams.createSecurityParamsBySecurityType(
+ WifiConfiguration.SECURITY_TYPE_OPEN),
+ };
+ for (SecurityParams p: openSecurityParams) {
+ assertTrue(p.isOpenSecurityType());
+ }
+
+ SecurityParams[] nonOpenSecurityParams = new SecurityParams[] {
+ SecurityParams.createSecurityParamsBySecurityType(
+ WifiConfiguration.SECURITY_TYPE_EAP),
+ SecurityParams.createSecurityParamsBySecurityType(
+ WifiConfiguration.SECURITY_TYPE_PASSPOINT_R1_R2),
+ SecurityParams.createSecurityParamsBySecurityType(
+ WifiConfiguration.SECURITY_TYPE_PASSPOINT_R3),
+ SecurityParams.createSecurityParamsBySecurityType(
+ WifiConfiguration.SECURITY_TYPE_OSEN),
+ SecurityParams.createSecurityParamsBySecurityType(
+ WifiConfiguration.SECURITY_TYPE_WAPI_PSK),
+ SecurityParams.createSecurityParamsBySecurityType(
+ WifiConfiguration.SECURITY_TYPE_WAPI_CERT),
+ SecurityParams.createSecurityParamsBySecurityType(
+ WifiConfiguration.SECURITY_TYPE_WEP),
+ SecurityParams.createSecurityParamsBySecurityType(
+ WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT),
+ SecurityParams.createSecurityParamsBySecurityType(
+ WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE),
+ SecurityParams.createSecurityParamsBySecurityType(
+ WifiConfiguration.SECURITY_TYPE_SAE),
+ SecurityParams.createSecurityParamsBySecurityType(
+ WifiConfiguration.SECURITY_TYPE_PSK),
+ };
+ for (SecurityParams p: nonOpenSecurityParams) {
+ assertFalse(p.isOpenSecurityType());
+ }
+ }
+
+ /** Verify enterprise network check */
+ @Test
+ public void testIsEnterpriseNetwork() {
+ SecurityParams[] enterpriseSecurityParams = new SecurityParams[] {
+ SecurityParams.createSecurityParamsBySecurityType(
+ WifiConfiguration.SECURITY_TYPE_EAP),
+ SecurityParams.createSecurityParamsBySecurityType(
+ WifiConfiguration.SECURITY_TYPE_PASSPOINT_R1_R2),
+ SecurityParams.createSecurityParamsBySecurityType(
+ WifiConfiguration.SECURITY_TYPE_PASSPOINT_R3),
+ SecurityParams.createSecurityParamsBySecurityType(
+ WifiConfiguration.SECURITY_TYPE_WAPI_CERT),
+ SecurityParams.createSecurityParamsBySecurityType(
+ WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT),
+ SecurityParams.createSecurityParamsBySecurityType(
+ WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE),
+ };
+ for (SecurityParams p: enterpriseSecurityParams) {
+ assertTrue(p.isEnterpriseSecurityType());
+ }
+
+ SecurityParams[] nonEnterpriseSecurityParams = new SecurityParams[] {
+ SecurityParams.createSecurityParamsBySecurityType(
+ WifiConfiguration.SECURITY_TYPE_OWE),
+ SecurityParams.createSecurityParamsBySecurityType(
+ WifiConfiguration.SECURITY_TYPE_OPEN),
+ SecurityParams.createSecurityParamsBySecurityType(
+ WifiConfiguration.SECURITY_TYPE_OSEN),
+ SecurityParams.createSecurityParamsBySecurityType(
+ WifiConfiguration.SECURITY_TYPE_WAPI_PSK),
+ SecurityParams.createSecurityParamsBySecurityType(
+ WifiConfiguration.SECURITY_TYPE_WEP),
+ SecurityParams.createSecurityParamsBySecurityType(
+ WifiConfiguration.SECURITY_TYPE_SAE),
+ SecurityParams.createSecurityParamsBySecurityType(
+ WifiConfiguration.SECURITY_TYPE_PSK),
+ };
+ for (SecurityParams p: nonEnterpriseSecurityParams) {
+ assertFalse(p.isEnterpriseSecurityType());
+ }
+ }
+
+ /** Check that parcel marshalling/unmarshalling works */
+ @Test
+ public void testParcelMethods() {
+ SecurityParams params = SecurityParams.createSecurityParamsBySecurityType(
+ WifiConfiguration.SECURITY_TYPE_SAE);
+
+ Parcel parcelW = Parcel.obtain();
+ params.writeToParcel(parcelW, 0);
+ byte[] bytes = parcelW.marshall();
+ parcelW.recycle();
+
+ Parcel parcelR = Parcel.obtain();
+ parcelR.unmarshall(bytes, 0, bytes.length);
+ parcelR.setDataPosition(0);
+
+ SecurityParams reParams = SecurityParams.createFromParcel(parcelR);
+ assertEquals(params, reParams);
+ }
+}
diff --git a/framework/tests/src/android/net/wifi/SoftApCapabilityTest.java b/framework/tests/src/android/net/wifi/SoftApCapabilityTest.java
index 73b501a..9e3b022 100644
--- a/framework/tests/src/android/net/wifi/SoftApCapabilityTest.java
+++ b/framework/tests/src/android/net/wifi/SoftApCapabilityTest.java
@@ -16,12 +16,15 @@
package android.net.wifi;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assume.assumeTrue;
+
import android.os.Parcel;
-import static org.junit.Assert.assertEquals;
-
import androidx.test.filters.SmallTest;
+import com.android.modules.utils.build.SdkLevel;
+
import org.junit.Test;
/**
@@ -37,8 +40,14 @@
public void testCopyOperator() throws Exception {
long testSoftApFeature = SoftApCapability.SOFTAP_FEATURE_CLIENT_FORCE_DISCONNECT
| SoftApCapability.SOFTAP_FEATURE_ACS_OFFLOAD;
+ int[] testSupported2Glist = {1, 2, 3, 4};
+ int[] testSupported5Glist = {36, 149};
+ int[] testSupported60Glist = {1, 2};
SoftApCapability capability = new SoftApCapability(testSoftApFeature);
capability.setMaxSupportedClients(10);
+ capability.setSupportedChannelList(SoftApConfiguration.BAND_2GHZ, testSupported2Glist);
+ capability.setSupportedChannelList(SoftApConfiguration.BAND_5GHZ, testSupported5Glist);
+ capability.setSupportedChannelList(SoftApConfiguration.BAND_60GHZ, testSupported60Glist);
SoftApCapability copiedCapability = new SoftApCapability(capability);
@@ -55,6 +64,13 @@
| SoftApCapability.SOFTAP_FEATURE_ACS_OFFLOAD;
SoftApCapability capability = new SoftApCapability(testSoftApFeature);
capability.setMaxSupportedClients(10);
+ int[] testSupported2Glist = {1, 2, 3, 4};
+ int[] testSupported5Glist = {36, 149};
+ int[] testSupported60Glist = {1, 2};
+
+ capability.setSupportedChannelList(SoftApConfiguration.BAND_2GHZ, testSupported2Glist);
+ capability.setSupportedChannelList(SoftApConfiguration.BAND_5GHZ, testSupported5Glist);
+ capability.setSupportedChannelList(SoftApConfiguration.BAND_60GHZ, testSupported60Glist);
Parcel parcelW = Parcel.obtain();
capability.writeToParcel(parcelW, 0);
@@ -70,4 +86,24 @@
assertEquals(capability.hashCode(), fromParcel.hashCode());
}
+ @Test(expected = IllegalArgumentException.class)
+ public void testSetSupportedChannelListWithInvalidBand() {
+ long testSoftApFeature = SoftApCapability.SOFTAP_FEATURE_CLIENT_FORCE_DISCONNECT
+ | SoftApCapability.SOFTAP_FEATURE_ACS_OFFLOAD;
+ SoftApCapability capability = new SoftApCapability(testSoftApFeature);
+ capability.setSupportedChannelList(
+ SoftApConfiguration.BAND_2GHZ | SoftApConfiguration.BAND_5GHZ, new int[0]);
+
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testGetSupportedChannelListWithInvalidBand() {
+ assumeTrue(SdkLevel.isAtLeastS());
+
+ long testSoftApFeature = SoftApCapability.SOFTAP_FEATURE_CLIENT_FORCE_DISCONNECT
+ | SoftApCapability.SOFTAP_FEATURE_ACS_OFFLOAD;
+ SoftApCapability capability = new SoftApCapability(testSoftApFeature);
+ capability.getSupportedChannelList(
+ SoftApConfiguration.BAND_2GHZ | SoftApConfiguration.BAND_5GHZ);
+ }
}
diff --git a/framework/tests/src/android/net/wifi/SoftApConfigurationTest.java b/framework/tests/src/android/net/wifi/SoftApConfigurationTest.java
index 2d7e535..a609a12 100644
--- a/framework/tests/src/android/net/wifi/SoftApConfigurationTest.java
+++ b/framework/tests/src/android/net/wifi/SoftApConfigurationTest.java
@@ -19,21 +19,28 @@
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
import android.net.MacAddress;
import android.os.Parcel;
+import android.util.SparseIntArray;
import androidx.test.filters.SmallTest;
+import com.android.modules.utils.build.SdkLevel;
+
import org.junit.Test;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import java.util.Random;
@SmallTest
public class SoftApConfigurationTest {
private static final String TEST_CHAR_SET_AS_STRING = "abcdefghijklmnopqrstuvwxyz0123456789";
+ private static final String TEST_BSSID = "aa:22:33:aa:bb:cc";
private SoftApConfiguration parcelUnparcel(SoftApConfiguration configIn) {
Parcel parcel = Parcel.obtain();
@@ -66,18 +73,23 @@
@Test
public void testBasicSettings() {
+ MacAddress testBssid = MacAddress.fromString(TEST_BSSID);
SoftApConfiguration original = new SoftApConfiguration.Builder()
.setSsid("ssid")
- .setBssid(MacAddress.fromString("11:22:33:44:55:66"))
+ .setBssid(testBssid)
.build();
assertThat(original.getSsid()).isEqualTo("ssid");
- assertThat(original.getBssid()).isEqualTo(MacAddress.fromString("11:22:33:44:55:66"));
+ assertThat(original.getBssid()).isEqualTo(testBssid);
assertThat(original.getPassphrase()).isNull();
assertThat(original.getSecurityType()).isEqualTo(SoftApConfiguration.SECURITY_TYPE_OPEN);
assertThat(original.getBand()).isEqualTo(SoftApConfiguration.BAND_2GHZ);
assertThat(original.getChannel()).isEqualTo(0);
assertThat(original.isHiddenSsid()).isEqualTo(false);
assertThat(original.getMaxNumberOfClients()).isEqualTo(0);
+ if (SdkLevel.isAtLeastS()) {
+ assertThat(original.getMacRandomizationSetting())
+ .isEqualTo(SoftApConfiguration.RANDOMIZATION_PERSISTENT);
+ }
SoftApConfiguration unparceled = parcelUnparcel(original);
assertThat(unparceled).isNotSameInstanceAs(original);
@@ -120,7 +132,7 @@
List<MacAddress> testAllowedClientList = new ArrayList<>();
testBlockedClientList.add(MacAddress.fromString("11:22:33:44:55:66"));
testAllowedClientList.add(MacAddress.fromString("aa:bb:cc:dd:ee:ff"));
- SoftApConfiguration original = new SoftApConfiguration.Builder()
+ SoftApConfiguration.Builder originalBuilder = new SoftApConfiguration.Builder()
.setPassphrase("secretsecret", SoftApConfiguration.SECURITY_TYPE_WPA2_PSK)
.setChannel(149, SoftApConfiguration.BAND_5GHZ)
.setHiddenSsid(true)
@@ -129,8 +141,11 @@
.setShutdownTimeoutMillis(500000)
.setClientControlByUserEnabled(true)
.setBlockedClientList(testBlockedClientList)
- .setAllowedClientList(testAllowedClientList)
- .build();
+ .setAllowedClientList(testAllowedClientList);
+ if (SdkLevel.isAtLeastS()) {
+ originalBuilder.setMacRandomizationSetting(SoftApConfiguration.RANDOMIZATION_NONE);
+ }
+ SoftApConfiguration original = originalBuilder.build();
assertThat(original.getPassphrase()).isEqualTo("secretsecret");
assertThat(original.getSecurityType()).isEqualTo(
SoftApConfiguration.SECURITY_TYPE_WPA2_PSK);
@@ -143,6 +158,10 @@
assertThat(original.isClientControlByUserEnabled()).isEqualTo(true);
assertThat(original.getBlockedClientList()).isEqualTo(testBlockedClientList);
assertThat(original.getAllowedClientList()).isEqualTo(testAllowedClientList);
+ if (SdkLevel.isAtLeastS()) {
+ assertThat(original.getMacRandomizationSetting())
+ .isEqualTo(SoftApConfiguration.RANDOMIZATION_NONE);
+ }
SoftApConfiguration unparceled = parcelUnparcel(original);
assertThat(unparceled).isNotSameInstanceAs(original);
@@ -209,6 +228,20 @@
}
@Test(expected = IllegalArgumentException.class)
+ public void testInvalidBroadcastBssid() {
+ SoftApConfiguration original = new SoftApConfiguration.Builder()
+ .setBssid(MacAddress.BROADCAST_ADDRESS)
+ .build();
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testInvalidMulticastBssid() {
+ SoftApConfiguration original = new SoftApConfiguration.Builder()
+ .setBssid(MacAddress.fromString("01:aa:bb:cc:dd:ee"))
+ .build();
+ }
+
+ @Test(expected = IllegalArgumentException.class)
public void testInvalidShortPasswordLengthForWpa2() {
SoftApConfiguration original = new SoftApConfiguration.Builder()
.setPassphrase(generateRandomString(SoftApConfiguration.PSK_MIN_LEN - 1),
@@ -336,4 +369,164 @@
.isEqualTo(WifiConfiguration.KeyMgmt.WPA2_PSK);
assertThat(wifiConfig_sae_transition.preSharedKey).isEqualTo("secretsecret");
}
+
+ @Test
+ public void testDualBands() {
+ assumeTrue(SdkLevel.isAtLeastS());
+ int[] dual_bands = new int[2];
+ dual_bands[0] = SoftApConfiguration.BAND_2GHZ;
+ dual_bands[1] = SoftApConfiguration.BAND_5GHZ;
+ SoftApConfiguration dual_bands_config = new SoftApConfiguration.Builder()
+ .setSsid("ssid")
+ .setBands(dual_bands)
+ .build();
+ assertTrue(Arrays.equals(dual_bands, dual_bands_config.getBands()));
+ assertThat(dual_bands_config.getBand()).isEqualTo(SoftApConfiguration.BAND_2GHZ);
+ }
+
+ @Test
+ public void testDualChannels() {
+ assumeTrue(SdkLevel.isAtLeastS());
+ int[] expected_dual_bands = new int[2];
+ expected_dual_bands[0] = SoftApConfiguration.BAND_2GHZ;
+ expected_dual_bands[1] = SoftApConfiguration.BAND_5GHZ;
+ SparseIntArray dual_channels = new SparseIntArray(2);
+ dual_channels.put(SoftApConfiguration.BAND_5GHZ, 149);
+ dual_channels.put(SoftApConfiguration.BAND_2GHZ, 2);
+ SoftApConfiguration dual_channels_config = new SoftApConfiguration.Builder()
+ .setSsid("ssid")
+ .setChannels(dual_channels)
+ .build();
+ assertTrue(Arrays.equals(expected_dual_bands, dual_channels_config.getBands()));
+ assertThat(dual_channels_config.getBand()).isEqualTo(SoftApConfiguration.BAND_2GHZ);
+ assertTrue(dual_channels.toString().equals(dual_channels_config.getChannels().toString()));
+ assertThat(dual_channels_config.getChannel()).isEqualTo(2);
+
+ // Test different parameters.
+ dual_channels.clear();
+ dual_channels.put(SoftApConfiguration.BAND_5GHZ, 149);
+ dual_channels.put(SoftApConfiguration.BAND_2GHZ | SoftApConfiguration.BAND_5GHZ, 0);
+ expected_dual_bands[0] = SoftApConfiguration.BAND_5GHZ;
+ expected_dual_bands[1] = SoftApConfiguration.BAND_2GHZ | SoftApConfiguration.BAND_5GHZ;
+ dual_channels_config = new SoftApConfiguration.Builder()
+ .setSsid("ssid")
+ .setChannels(dual_channels)
+ .build();
+ assertTrue(Arrays.equals(expected_dual_bands, dual_channels_config.getBands()));
+ assertThat(dual_channels_config.getBand()).isEqualTo(SoftApConfiguration.BAND_5GHZ);
+ assertTrue(dual_channels.toString().equals(dual_channels_config.getChannels().toString()));
+ assertThat(dual_channels_config.getChannel()).isEqualTo(149);
+ }
+
+ @Test
+ public void testInvalidBandWhenSetBands() {
+ assumeTrue(SdkLevel.isAtLeastS());
+ boolean isIllegalArgumentExceptionHappened = false;
+ int[] dual_bands = new int[2];
+ dual_bands[0] = SoftApConfiguration.BAND_2GHZ;
+ dual_bands[1] = -1;
+ try {
+ SoftApConfiguration dual_channels_config = new SoftApConfiguration.Builder()
+ .setSsid("ssid")
+ .setBands(dual_bands)
+ .build();
+ isIllegalArgumentExceptionHappened = false;
+ } catch (IllegalArgumentException iae) {
+ isIllegalArgumentExceptionHappened = true;
+ }
+ assertTrue(isIllegalArgumentExceptionHappened);
+
+ try {
+ SoftApConfiguration dual_channels_config = new SoftApConfiguration.Builder()
+ .setSsid("ssid")
+ .setBands(new int[0])
+ .build();
+ isIllegalArgumentExceptionHappened = false;
+ } catch (IllegalArgumentException iae) {
+ isIllegalArgumentExceptionHappened = true;
+ }
+ assertTrue(isIllegalArgumentExceptionHappened);
+
+ try {
+ SoftApConfiguration dual_channels_config = new SoftApConfiguration.Builder()
+ .setSsid("ssid")
+ .setBands(new int[3])
+ .build();
+ isIllegalArgumentExceptionHappened = false;
+ } catch (IllegalArgumentException iae) {
+ isIllegalArgumentExceptionHappened = true;
+ }
+ assertTrue(isIllegalArgumentExceptionHappened);
+ }
+
+ @Test
+ public void testInvalidConfigWhenSetChannels() {
+ assumeTrue(SdkLevel.isAtLeastS());
+ boolean isIllegalArgumentExceptionHappened = false;
+ SparseIntArray invalid_channels = new SparseIntArray();
+ try {
+ SoftApConfiguration zero_channels_config = new SoftApConfiguration.Builder()
+ .setSsid("ssid")
+ .setChannels(invalid_channels)
+ .build();
+ isIllegalArgumentExceptionHappened = false;
+ } catch (IllegalArgumentException iae) {
+ isIllegalArgumentExceptionHappened = true;
+ }
+ assertTrue(isIllegalArgumentExceptionHappened);
+
+ try {
+ invalid_channels.clear();
+ invalid_channels.put(SoftApConfiguration.BAND_2GHZ, 2);
+ invalid_channels.put(SoftApConfiguration.BAND_5GHZ, 11);
+ SoftApConfiguration invalid_band_channels_config = new SoftApConfiguration.Builder()
+ .setSsid("ssid")
+ .setChannels(invalid_channels)
+ .build();
+ isIllegalArgumentExceptionHappened = false;
+ } catch (IllegalArgumentException iae) {
+ isIllegalArgumentExceptionHappened = true;
+ }
+ assertTrue(isIllegalArgumentExceptionHappened);
+
+ try {
+ invalid_channels.clear();
+ invalid_channels.put(SoftApConfiguration.BAND_2GHZ, 2);
+ invalid_channels.put(SoftApConfiguration.BAND_2GHZ | SoftApConfiguration.BAND_5GHZ,
+ 149);
+ SoftApConfiguration invalid_dual_channels_config = new SoftApConfiguration.Builder()
+ .setSsid("ssid")
+ .setChannels(invalid_channels)
+ .build();
+ isIllegalArgumentExceptionHappened = false;
+ } catch (IllegalArgumentException iae) {
+ isIllegalArgumentExceptionHappened = true;
+ }
+ assertTrue(isIllegalArgumentExceptionHappened);
+
+ try {
+ invalid_channels.clear();
+ invalid_channels.put(SoftApConfiguration.BAND_2GHZ, 2);
+ invalid_channels.put(SoftApConfiguration.BAND_5GHZ, 149);
+ invalid_channels.put(SoftApConfiguration.BAND_6GHZ, 2);
+ SoftApConfiguration three_channels_config = new SoftApConfiguration.Builder()
+ .setSsid("ssid")
+ .setChannels(invalid_channels)
+ .build();
+ isIllegalArgumentExceptionHappened = false;
+ } catch (IllegalArgumentException iae) {
+ isIllegalArgumentExceptionHappened = true;
+ }
+ assertTrue(isIllegalArgumentExceptionHappened);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testInvalidConfigWhenSet60GhzChannels() throws Exception {
+ SparseIntArray invalid_channels = new SparseIntArray();
+ invalid_channels.put(SoftApConfiguration.BAND_60GHZ, 99);
+ SoftApConfiguration config = new SoftApConfiguration.Builder()
+ .setSsid("ssid")
+ .setChannels(invalid_channels)
+ .build();
+ }
}
diff --git a/framework/tests/src/android/net/wifi/SoftApInfoTest.java b/framework/tests/src/android/net/wifi/SoftApInfoTest.java
index 929f3ab..2121d10 100644
--- a/framework/tests/src/android/net/wifi/SoftApInfoTest.java
+++ b/framework/tests/src/android/net/wifi/SoftApInfoTest.java
@@ -16,12 +16,15 @@
package android.net.wifi;
-import android.os.Parcel;
-
import static org.junit.Assert.assertEquals;
+import android.net.MacAddress;
+import android.os.Parcel;
+
import androidx.test.filters.SmallTest;
+import com.android.modules.utils.build.SdkLevel;
+
import org.junit.Test;
/**
@@ -29,15 +32,23 @@
*/
@SmallTest
public class SoftApInfoTest {
-
+ private static final String TEST_AP_INSTANCE = "wlan1";
+ private static final int TEST_FREQUENCY = 2412;
+ private static final int TEST_BANDWIDTH = SoftApInfo.CHANNEL_WIDTH_20MHZ;
+ private static final int TEST_WIFI_STANDARD = ScanResult.WIFI_STANDARD_LEGACY;
+ private static final MacAddress TEST_AP_MAC = MacAddress.fromString("aa:bb:cc:dd:ee:ff");
/**
* Verifies copy constructor.
*/
@Test
public void testCopyOperator() throws Exception {
SoftApInfo info = new SoftApInfo();
- info.setFrequency(2412);
- info.setBandwidth(SoftApInfo.CHANNEL_WIDTH_20MHZ);
+ info.setFrequency(TEST_FREQUENCY);
+ info.setBandwidth(TEST_BANDWIDTH);
+ info.setBssid(TEST_AP_MAC);
+ info.setWifiStandard(TEST_WIFI_STANDARD);
+ info.setApInstanceIdentifier(TEST_AP_INSTANCE);
+
SoftApInfo copiedInfo = new SoftApInfo(info);
@@ -51,8 +62,11 @@
@Test
public void testParcelOperation() throws Exception {
SoftApInfo info = new SoftApInfo();
- info.setFrequency(2412);
- info.setBandwidth(SoftApInfo.CHANNEL_WIDTH_20MHZ);
+ info.setFrequency(TEST_FREQUENCY);
+ info.setBandwidth(TEST_BANDWIDTH);
+ info.setBssid(TEST_AP_MAC);
+ info.setWifiStandard(TEST_WIFI_STANDARD);
+ info.setApInstanceIdentifier(TEST_AP_INSTANCE);
Parcel parcelW = Parcel.obtain();
info.writeToParcel(parcelW, 0);
@@ -68,4 +82,40 @@
assertEquals(info.hashCode(), fromParcel.hashCode());
}
+
+ /**
+ * Verifies the initial value same as expected.
+ */
+ @Test
+ public void testInitialValue() throws Exception {
+ SoftApInfo info = new SoftApInfo();
+ assertEquals(info.getFrequency(), 0);
+ assertEquals(info.getBandwidth(), SoftApInfo.CHANNEL_WIDTH_INVALID);
+ if (SdkLevel.isAtLeastS()) {
+ assertEquals(info.getBssid(), null);
+ assertEquals(info.getWifiStandard(), ScanResult.WIFI_STANDARD_UNKNOWN);
+ assertEquals(info.getApInstanceIdentifier(), null);
+ }
+ }
+
+ /**
+ * Verifies the set/get method same as expected.
+ */
+ @Test
+ public void testGetXXXAlignedWithSetXXX() throws Exception {
+ SoftApInfo info = new SoftApInfo();
+ info.setFrequency(TEST_FREQUENCY);
+ info.setBandwidth(TEST_BANDWIDTH);
+ info.setBssid(TEST_AP_MAC);
+ info.setWifiStandard(TEST_WIFI_STANDARD);
+ info.setApInstanceIdentifier(TEST_AP_INSTANCE);
+ assertEquals(info.getFrequency(), TEST_FREQUENCY);
+ assertEquals(info.getBandwidth(), TEST_BANDWIDTH);
+ if (SdkLevel.isAtLeastS()) {
+ assertEquals(info.getBssid(), TEST_AP_MAC);
+ assertEquals(info.getWifiStandard(), TEST_WIFI_STANDARD);
+ assertEquals(info.getApInstanceIdentifier(), TEST_AP_INSTANCE);
+ }
+ }
+
}
diff --git a/framework/tests/src/android/net/wifi/WifiClientTest.java b/framework/tests/src/android/net/wifi/WifiClientTest.java
index 7a3baf9..7046563 100644
--- a/framework/tests/src/android/net/wifi/WifiClientTest.java
+++ b/framework/tests/src/android/net/wifi/WifiClientTest.java
@@ -42,9 +42,9 @@
*/
@Test
public void testWifiClientParcelWriteRead() throws Exception {
- WifiClient writeWifiClient = new WifiClient(MAC_ADDRESS);
+ WifiClient writeWifiClient = new WifiClient(MAC_ADDRESS, INTERFACE_NAME);
- assertParcelSane(writeWifiClient, 1);
+ assertParcelSane(writeWifiClient, 2);
}
/**
@@ -52,12 +52,12 @@
*/
@Test
public void testWifiClientEquals() throws Exception {
- WifiClient writeWifiClient = new WifiClient(MAC_ADDRESS);
- WifiClient writeWifiClientEquals = new WifiClient(MAC_ADDRESS);
+ WifiClient writeWifiClient = new WifiClient(MAC_ADDRESS, INTERFACE_NAME);
+ WifiClient writeWifiClientEquals = new WifiClient(MAC_ADDRESS, INTERFACE_NAME);
assertEquals(writeWifiClient, writeWifiClientEquals);
assertEquals(writeWifiClient.hashCode(), writeWifiClientEquals.hashCode());
- assertFieldCountEquals(1, WifiClient.class);
+ assertFieldCountEquals(2, WifiClient.class);
}
/**
@@ -66,8 +66,8 @@
@Test
public void testWifiClientNotEquals() throws Exception {
final MacAddress macAddressNotEquals = MacAddress.fromString("00:00:00:00:00:00");
- WifiClient writeWifiClient = new WifiClient(MAC_ADDRESS);
- WifiClient writeWifiClientNotEquals = new WifiClient(macAddressNotEquals);
+ WifiClient writeWifiClient = new WifiClient(MAC_ADDRESS, INTERFACE_NAME);
+ WifiClient writeWifiClientNotEquals = new WifiClient(macAddressNotEquals, INTERFACE_NAME);
assertNotEquals(writeWifiClient, writeWifiClientNotEquals);
assertNotEquals(writeWifiClient.hashCode(), writeWifiClientNotEquals.hashCode());
diff --git a/framework/tests/src/android/net/wifi/WifiConfigurationTest.java b/framework/tests/src/android/net/wifi/WifiConfigurationTest.java
index 890d3d3..bde44e7 100644
--- a/framework/tests/src/android/net/wifi/WifiConfigurationTest.java
+++ b/framework/tests/src/android/net/wifi/WifiConfigurationTest.java
@@ -17,12 +17,18 @@
package android.net.wifi;
import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_EAP;
-import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_EAP_SUITE_B;
+import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE;
+import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT;
import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_OPEN;
+import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_OSEN;
import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_OWE;
+import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_PASSPOINT_R1_R2;
+import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_PASSPOINT_R3;
import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_PSK;
import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_SAE;
+import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_WAPI_CERT;
import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_WAPI_PSK;
+import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_WEP;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
@@ -32,9 +38,13 @@
import static org.junit.Assert.assertTrue;
import android.net.MacAddress;
+import android.net.wifi.WifiConfiguration.GroupCipher;
import android.net.wifi.WifiConfiguration.KeyMgmt;
import android.net.wifi.WifiConfiguration.NetworkSelectionStatus;
+import android.net.wifi.WifiConfiguration.PairwiseCipher;
+import android.net.wifi.WifiConfiguration.Protocol;
import android.os.Parcel;
+import android.util.Pair;
import androidx.test.filters.SmallTest;
@@ -43,11 +53,19 @@
import org.junit.Before;
import org.junit.Test;
+import java.util.ArrayList;
+import java.util.BitSet;
+import java.util.List;
+
/**
* Unit tests for {@link android.net.wifi.WifiConfiguration}.
*/
@SmallTest
public class WifiConfigurationTest {
+ private static final String TEST_PASSPOINT_UNIQUE_ID = "uniqueId";
+ private static final int TEST_CARRIER_ID = 1234;
+ private static final int TEST_SUB_ID = 3;
+ private static final String TEST_PACKAGE_NAME = "google.com";
@Before
public void setUp() {
@@ -67,11 +85,16 @@
WifiConfiguration config = new WifiConfiguration();
config.setPasspointManagementObjectTree(cookie);
config.trusted = false;
+ config.oemPaid = true;
+ config.oemPrivate = true;
+ config.carrierMerged = true;
config.updateIdentifier = "1234";
config.fromWifiNetworkSpecifier = true;
config.fromWifiNetworkSuggestion = true;
config.setRandomizedMacAddress(MacAddressUtils.createRandomUnicastAddress());
MacAddress macBeforeParcel = config.getRandomizedMacAddress();
+ config.subscriptionId = 1;
+ config.carrierId = 1189;
Parcel parcelW = Parcel.obtain();
config.writeToParcel(parcelW, 0);
byte[] bytes = parcelW.marshall();
@@ -87,8 +110,11 @@
assertEquals(macBeforeParcel, reconfig.getRandomizedMacAddress());
assertEquals(config.updateIdentifier, reconfig.updateIdentifier);
assertFalse(reconfig.trusted);
- assertTrue(config.fromWifiNetworkSpecifier);
- assertTrue(config.fromWifiNetworkSuggestion);
+ assertTrue(reconfig.fromWifiNetworkSpecifier);
+ assertTrue(reconfig.fromWifiNetworkSuggestion);
+ assertTrue(reconfig.oemPaid);
+ assertTrue(reconfig.oemPrivate);
+ assertTrue(reconfig.carrierMerged);
Parcel parcelWW = Parcel.obtain();
reconfig.writeToParcel(parcelWW, 0);
@@ -99,6 +125,34 @@
}
@Test
+ public void testWifiConfigurationCopyConstructor() {
+ WifiConfiguration config = new WifiConfiguration();
+ config.trusted = false;
+ config.oemPaid = true;
+ config.oemPrivate = true;
+ config.carrierMerged = true;
+ config.updateIdentifier = "1234";
+ config.fromWifiNetworkSpecifier = true;
+ config.fromWifiNetworkSuggestion = true;
+ config.setRandomizedMacAddress(MacAddressUtils.createRandomUnicastAddress());
+ MacAddress macBeforeParcel = config.getRandomizedMacAddress();
+ config.subscriptionId = 1;
+ config.carrierId = 1189;
+
+ WifiConfiguration reconfig = new WifiConfiguration(config);
+
+ // lacking a useful config.equals, check two fields near the end.
+ assertEquals(macBeforeParcel, reconfig.getRandomizedMacAddress());
+ assertEquals(config.updateIdentifier, reconfig.updateIdentifier);
+ assertFalse(reconfig.trusted);
+ assertTrue(reconfig.fromWifiNetworkSpecifier);
+ assertTrue(reconfig.fromWifiNetworkSuggestion);
+ assertTrue(reconfig.oemPaid);
+ assertTrue(reconfig.oemPrivate);
+ assertTrue(reconfig.carrierMerged);
+ }
+
+ @Test
public void testIsOpenNetwork_IsOpen_NullWepKeys() {
WifiConfiguration config = new WifiConfiguration();
config.allowedKeyManagement.clear();
@@ -145,18 +199,24 @@
@Test
public void testIsOpenNetwork_NotOpen_HasAuthType() {
- for (int keyMgmt = 0; keyMgmt < WifiConfiguration.KeyMgmt.strings.length; keyMgmt++) {
- if (keyMgmt == WifiConfiguration.KeyMgmt.NONE
- || keyMgmt == WifiConfiguration.KeyMgmt.OWE) {
- continue;
- }
+ int[] securityTypes = new int [] {
+ SECURITY_TYPE_WEP,
+ SECURITY_TYPE_PSK,
+ SECURITY_TYPE_EAP,
+ SECURITY_TYPE_SAE,
+ SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT,
+ SECURITY_TYPE_WAPI_PSK,
+ SECURITY_TYPE_WAPI_CERT,
+ SECURITY_TYPE_EAP_WPA3_ENTERPRISE,
+ SECURITY_TYPE_OSEN,
+ };
+ for (int type: securityTypes) {
WifiConfiguration config = new WifiConfiguration();
- config.allowedKeyManagement.clear();
- config.allowedKeyManagement.set(keyMgmt);
+ config.setSecurityParams(type);
config.wepKeys = null;
- assertFalse("Open network reported when key mgmt was set to "
- + WifiConfiguration.KeyMgmt.strings[keyMgmt], config.isOpenNetwork());
+ assertFalse("Open network reported when security type was set to "
+ + type, config.isOpenNetwork());
}
}
@@ -166,6 +226,7 @@
config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP);
config.wepKeys = null;
+ config.convertLegacyFieldsToSecurityParamsIfNeeded();
assertFalse(config.isOpenNetwork());
}
@@ -388,6 +449,79 @@
}
/**
+ * Verifies that getNetworkKey returns the correct String for networks of
+ * various different security types, the result should be stable.
+ */
+ @Test
+ public void testGetNetworkKeyString() {
+ WifiConfiguration config = new WifiConfiguration();
+ final String mSsid = "TestAP";
+ config.SSID = mSsid;
+
+ // Test various combinations
+ config.allowedKeyManagement.set(KeyMgmt.WPA_PSK);
+ assertEquals(mSsid + KeyMgmt.strings[KeyMgmt.WPA_PSK],
+ config.getNetworkKey());
+
+ config.allowedKeyManagement.clear();
+ config.allowedKeyManagement.set(KeyMgmt.WPA_EAP);
+ assertEquals(mSsid + KeyMgmt.strings[KeyMgmt.WPA_EAP],
+ config.getNetworkKey());
+
+ config.wepKeys[0] = "TestWep";
+ config.allowedKeyManagement.clear();
+ assertEquals(mSsid + "WEP", config.getNetworkKey());
+
+ // set WEP key and give a valid index.
+ config.wepKeys[0] = null;
+ config.wepKeys[2] = "TestWep";
+ config.wepTxKeyIndex = 2;
+ config.allowedKeyManagement.clear();
+ assertEquals(mSsid + "WEP", config.getNetworkKey());
+
+ // set WEP key but does not give a valid index.
+ config.wepKeys[0] = null;
+ config.wepKeys[2] = "TestWep";
+ config.wepTxKeyIndex = 0;
+ config.allowedKeyManagement.clear();
+ config.allowedKeyManagement.set(KeyMgmt.OWE);
+ assertEquals(mSsid + KeyMgmt.strings[KeyMgmt.OWE], config.getNetworkKey());
+
+ config.wepKeys[0] = null;
+ config.wepTxKeyIndex = 0;
+ config.allowedKeyManagement.clear();
+ config.allowedKeyManagement.set(KeyMgmt.OWE);
+ assertEquals(mSsid + KeyMgmt.strings[KeyMgmt.OWE], config.getNetworkKey());
+
+ config.allowedKeyManagement.clear();
+ config.allowedKeyManagement.set(KeyMgmt.SAE);
+ assertEquals(mSsid + KeyMgmt.strings[KeyMgmt.SAE], config.getNetworkKey());
+
+ config.allowedKeyManagement.clear();
+ config.allowedKeyManagement.set(KeyMgmt.SUITE_B_192);
+ assertEquals(mSsid + KeyMgmt.strings[KeyMgmt.SUITE_B_192],
+ config.getNetworkKey());
+
+ config.allowedKeyManagement.clear();
+ config.allowedKeyManagement.set(KeyMgmt.NONE);
+ assertEquals(mSsid + KeyMgmt.strings[KeyMgmt.NONE], config.getNetworkKey());
+
+ config.allowedKeyManagement.clear();
+ config.allowedKeyManagement.set(KeyMgmt.WAPI_PSK);
+ assertEquals(mSsid + KeyMgmt.strings[KeyMgmt.WAPI_PSK],
+ config.getNetworkKey());
+
+ config.allowedKeyManagement.clear();
+ config.allowedKeyManagement.set(KeyMgmt.WAPI_CERT);
+ assertEquals(mSsid + KeyMgmt.strings[KeyMgmt.WAPI_CERT],
+ config.getNetworkKey());
+
+ config.allowedKeyManagement.clear();
+ config.setPasspointUniqueId(TEST_PASSPOINT_UNIQUE_ID);
+ assertEquals(TEST_PASSPOINT_UNIQUE_ID, config.getNetworkKey());
+ }
+
+ /**
* Ensure that the {@link NetworkSelectionStatus.DisableReasonInfo}s are populated in
* {@link NetworkSelectionStatus#DISABLE_REASON_INFOS} for reason codes from 0 to
* {@link NetworkSelectionStatus#NETWORK_SELECTION_DISABLED_MAX} - 1.
@@ -462,7 +596,7 @@
public void testSetSecurityParamsForSuiteB() throws Exception {
WifiConfiguration config = new WifiConfiguration();
- config.setSecurityParams(SECURITY_TYPE_EAP_SUITE_B);
+ config.setSecurityParams(SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT);
assertTrue(config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.SUITE_B_192));
assertTrue(config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_EAP));
@@ -475,6 +609,26 @@
}
/**
+ * Ensure that {@link WifiConfiguration#setSecurityParams(int)} sets up the
+ * {@link WifiConfiguration} object correctly for WPA3 Enterprise security type.
+ * @throws Exception
+ */
+ @Test
+ public void testSetSecurityParamsForWpa3Enterprise() throws Exception {
+ WifiConfiguration config = new WifiConfiguration();
+
+ config.setSecurityParams(SECURITY_TYPE_EAP_WPA3_ENTERPRISE);
+
+ assertTrue(config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_EAP));
+ assertTrue(config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.IEEE8021X));
+ assertTrue(config.allowedPairwiseCiphers.get(WifiConfiguration.PairwiseCipher.CCMP));
+ assertTrue(config.allowedPairwiseCiphers.get(WifiConfiguration.PairwiseCipher.GCMP_256));
+ assertTrue(config.allowedGroupCiphers.get(WifiConfiguration.GroupCipher.CCMP));
+ assertTrue(config.allowedGroupCiphers.get(WifiConfiguration.GroupCipher.GCMP_256));
+ assertTrue(config.requirePmf);
+ }
+
+ /**
* Test that the NetworkSelectionStatus Builder returns the same values that was set, and that
* calling build multiple times returns different instances.
*/
@@ -535,7 +689,512 @@
configuration.setSecurityParams(SECURITY_TYPE_EAP);
assertFalse(configuration.needsPreSharedKey());
- configuration.setSecurityParams(SECURITY_TYPE_EAP_SUITE_B);
+ configuration.setSecurityParams(SECURITY_TYPE_EAP_WPA3_ENTERPRISE);
assertFalse(configuration.needsPreSharedKey());
+
+ configuration.setSecurityParams(SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT);
+ assertFalse(configuration.needsPreSharedKey());
+ }
+
+ @Test
+ public void testGetAuthType() throws Exception {
+ WifiConfiguration configuration = new WifiConfiguration();
+
+ configuration.setSecurityParams(SECURITY_TYPE_PSK);
+ assertEquals(KeyMgmt.WPA_PSK, configuration.getAuthType());
+
+ configuration.setSecurityParams(SECURITY_TYPE_SAE);
+ assertEquals(KeyMgmt.SAE, configuration.getAuthType());
+
+ configuration.setSecurityParams(SECURITY_TYPE_WAPI_PSK);
+ assertEquals(KeyMgmt.WAPI_PSK, configuration.getAuthType());
+
+ configuration.setSecurityParams(SECURITY_TYPE_OPEN);
+ assertEquals(KeyMgmt.NONE, configuration.getAuthType());
+
+ configuration.setSecurityParams(SECURITY_TYPE_OWE);
+ assertEquals(KeyMgmt.OWE, configuration.getAuthType());
+
+ configuration.setSecurityParams(SECURITY_TYPE_EAP);
+ assertEquals(KeyMgmt.WPA_EAP, configuration.getAuthType());
+
+ configuration.setSecurityParams(SECURITY_TYPE_EAP_WPA3_ENTERPRISE);
+ assertEquals(KeyMgmt.WPA_EAP, configuration.getAuthType());
+
+ configuration.setSecurityParams(SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT);
+ assertEquals(KeyMgmt.SUITE_B_192, configuration.getAuthType());
+
+ configuration.setSecurityParams(SECURITY_TYPE_WAPI_CERT);
+ assertEquals(KeyMgmt.WAPI_CERT, configuration.getAuthType());
+ }
+
+ @Test (expected = IllegalStateException.class)
+ public void testGetAuthTypeFailure1() throws Exception {
+ WifiConfiguration configuration = new WifiConfiguration();
+
+ configuration.setSecurityParams(SECURITY_TYPE_PSK);
+ configuration.allowedKeyManagement.set(KeyMgmt.IEEE8021X);
+ configuration.getAuthType();
+ }
+
+ @Test (expected = IllegalStateException.class)
+ public void testGetAuthTypeFailure2() throws Exception {
+ WifiConfiguration configuration = new WifiConfiguration();
+
+ configuration.allowedKeyManagement.set(KeyMgmt.IEEE8021X);
+ configuration.allowedKeyManagement.set(KeyMgmt.WPA_EAP);
+ configuration.allowedKeyManagement.set(KeyMgmt.SAE);
+ configuration.getAuthType();
+ }
+
+ /**
+ * Verifies that getProfileKey returns the correct String for networks of
+ * various different security types, the result should be stable.
+ */
+ @Test
+ public void testGetProfileKeyString() {
+ WifiConfiguration config = new WifiConfiguration();
+ final String mSsid = "TestAP";
+ config.SSID = mSsid;
+ config.carrierId = TEST_CARRIER_ID;
+ config.subscriptionId = TEST_SUB_ID;
+ config.creatorName = TEST_PACKAGE_NAME;
+
+
+ // Test various combinations
+ config.allowedKeyManagement.set(KeyMgmt.WPA_PSK);
+ config.fromWifiNetworkSuggestion = false;
+ assertEquals(createProfileKey(mSsid, KeyMgmt.strings[KeyMgmt.WPA_PSK], TEST_PACKAGE_NAME,
+ TEST_CARRIER_ID, TEST_SUB_ID, false), config.getProfileKey());
+ config.fromWifiNetworkSuggestion = true;
+ assertEquals(createProfileKey(mSsid, KeyMgmt.strings[KeyMgmt.WPA_PSK], TEST_PACKAGE_NAME,
+ TEST_CARRIER_ID, TEST_SUB_ID, true), config.getProfileKey());
+
+ config.allowedKeyManagement.clear();
+ config.allowedKeyManagement.set(KeyMgmt.WPA_EAP);
+ config.fromWifiNetworkSuggestion = false;
+ assertEquals(createProfileKey(mSsid, KeyMgmt.strings[KeyMgmt.WPA_EAP], TEST_PACKAGE_NAME,
+ TEST_CARRIER_ID, TEST_SUB_ID, false), config.getProfileKey());
+ config.fromWifiNetworkSuggestion = true;
+ assertEquals(createProfileKey(mSsid, KeyMgmt.strings[KeyMgmt.WPA_EAP], TEST_PACKAGE_NAME,
+ TEST_CARRIER_ID, TEST_SUB_ID, true), config.getProfileKey());
+
+ config.wepKeys[0] = "TestWep";
+ config.allowedKeyManagement.clear();
+ config.fromWifiNetworkSuggestion = false;
+ assertEquals(createProfileKey(mSsid, "WEP", TEST_PACKAGE_NAME,
+ TEST_CARRIER_ID, TEST_SUB_ID, false), config.getProfileKey());
+ config.fromWifiNetworkSuggestion = true;
+ assertEquals(createProfileKey(mSsid, "WEP", TEST_PACKAGE_NAME,
+ TEST_CARRIER_ID, TEST_SUB_ID, true), config.getProfileKey());
+
+ // set WEP key and give a valid index.
+ config.wepKeys[0] = null;
+ config.wepKeys[2] = "TestWep";
+ config.wepTxKeyIndex = 2;
+ config.allowedKeyManagement.clear();
+ config.fromWifiNetworkSuggestion = false;
+ assertEquals(createProfileKey(mSsid, "WEP", TEST_PACKAGE_NAME,
+ TEST_CARRIER_ID, TEST_SUB_ID, false), config.getProfileKey());
+ config.fromWifiNetworkSuggestion = true;
+ assertEquals(createProfileKey(mSsid, "WEP", TEST_PACKAGE_NAME,
+ TEST_CARRIER_ID, TEST_SUB_ID, true), config.getProfileKey());
+
+ // set WEP key but does not give a valid index.
+ config.wepKeys[0] = null;
+ config.wepKeys[2] = "TestWep";
+ config.wepTxKeyIndex = 0;
+ config.allowedKeyManagement.clear();
+ config.allowedKeyManagement.set(KeyMgmt.OWE);
+ config.fromWifiNetworkSuggestion = false;
+ assertEquals(createProfileKey(mSsid, KeyMgmt.strings[KeyMgmt.OWE], TEST_PACKAGE_NAME,
+ TEST_CARRIER_ID, TEST_SUB_ID, false), config.getProfileKey());
+ config.fromWifiNetworkSuggestion = true;
+ assertEquals(createProfileKey(mSsid, KeyMgmt.strings[KeyMgmt.OWE], TEST_PACKAGE_NAME,
+ TEST_CARRIER_ID, TEST_SUB_ID, true), config.getProfileKey());
+
+ config.wepKeys[0] = null;
+ config.wepTxKeyIndex = 0;
+ config.allowedKeyManagement.clear();
+ config.allowedKeyManagement.set(KeyMgmt.OWE);
+ config.fromWifiNetworkSuggestion = false;
+ assertEquals(createProfileKey(mSsid, KeyMgmt.strings[KeyMgmt.OWE], TEST_PACKAGE_NAME,
+ TEST_CARRIER_ID, TEST_SUB_ID, false), config.getProfileKey());
+ config.fromWifiNetworkSuggestion = true;
+ assertEquals(createProfileKey(mSsid, KeyMgmt.strings[KeyMgmt.OWE], TEST_PACKAGE_NAME,
+ TEST_CARRIER_ID, TEST_SUB_ID, true), config.getProfileKey());
+
+ config.allowedKeyManagement.clear();
+ config.allowedKeyManagement.set(KeyMgmt.SAE);
+ config.fromWifiNetworkSuggestion = false;
+ assertEquals(createProfileKey(mSsid, KeyMgmt.strings[KeyMgmt.SAE], TEST_PACKAGE_NAME,
+ TEST_CARRIER_ID, TEST_SUB_ID, false), config.getProfileKey());
+ config.fromWifiNetworkSuggestion = true;
+ assertEquals(createProfileKey(mSsid, KeyMgmt.strings[KeyMgmt.SAE], TEST_PACKAGE_NAME,
+ TEST_CARRIER_ID, TEST_SUB_ID, true), config.getProfileKey());
+
+ config.allowedKeyManagement.clear();
+ config.allowedKeyManagement.set(KeyMgmt.SUITE_B_192);
+ config.fromWifiNetworkSuggestion = false;
+ assertEquals(createProfileKey(mSsid, KeyMgmt.strings[KeyMgmt.SUITE_B_192],
+ TEST_PACKAGE_NAME, TEST_CARRIER_ID, TEST_SUB_ID, false), config.getProfileKey());
+ config.fromWifiNetworkSuggestion = true;
+ assertEquals(createProfileKey(mSsid, KeyMgmt.strings[KeyMgmt.SUITE_B_192],
+ TEST_PACKAGE_NAME, TEST_CARRIER_ID, TEST_SUB_ID, true), config.getProfileKey());
+
+ config.allowedKeyManagement.clear();
+ config.allowedKeyManagement.set(KeyMgmt.NONE);
+ config.fromWifiNetworkSuggestion = false;
+ assertEquals(createProfileKey(mSsid, KeyMgmt.strings[KeyMgmt.NONE], TEST_PACKAGE_NAME,
+ TEST_CARRIER_ID, TEST_SUB_ID, false), config.getProfileKey());
+ config.fromWifiNetworkSuggestion = true;
+ assertEquals(createProfileKey(mSsid, KeyMgmt.strings[KeyMgmt.NONE], TEST_PACKAGE_NAME,
+ TEST_CARRIER_ID, TEST_SUB_ID, true), config.getProfileKey());
+
+ config.allowedKeyManagement.clear();
+ config.allowedKeyManagement.set(KeyMgmt.WAPI_PSK);
+ config.fromWifiNetworkSuggestion = false;
+ assertEquals(createProfileKey(mSsid, KeyMgmt.strings[KeyMgmt.WAPI_PSK], TEST_PACKAGE_NAME,
+ TEST_CARRIER_ID, TEST_SUB_ID, false), config.getProfileKey());
+ config.fromWifiNetworkSuggestion = true;
+ assertEquals(createProfileKey(mSsid, KeyMgmt.strings[KeyMgmt.WAPI_PSK], TEST_PACKAGE_NAME,
+ TEST_CARRIER_ID, TEST_SUB_ID, true), config.getProfileKey());
+
+ config.allowedKeyManagement.clear();
+ config.allowedKeyManagement.set(KeyMgmt.WAPI_CERT);
+ config.fromWifiNetworkSuggestion = false;
+ assertEquals(createProfileKey(mSsid, KeyMgmt.strings[KeyMgmt.WAPI_CERT], TEST_PACKAGE_NAME,
+ TEST_CARRIER_ID, TEST_SUB_ID, false), config.getProfileKey());
+ config.fromWifiNetworkSuggestion = true;
+ assertEquals(createProfileKey(mSsid, KeyMgmt.strings[KeyMgmt.WAPI_CERT], TEST_PACKAGE_NAME,
+ TEST_CARRIER_ID, TEST_SUB_ID, true), config.getProfileKey());
+
+ config.allowedKeyManagement.clear();
+ config.setPasspointUniqueId(TEST_PASSPOINT_UNIQUE_ID);
+ assertEquals(TEST_PASSPOINT_UNIQUE_ID, config.getProfileKey());
+ }
+
+ private String createProfileKey(String ssid, String keyMgmt, String providerName,
+ int carrierId, int subId, boolean isFromSuggestion) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(ssid).append(keyMgmt);
+ if (isFromSuggestion) {
+ sb.append("_").append(providerName).append('-')
+ .append(carrierId).append('-').append(subId);
+ }
+ return sb.toString();
+ }
+
+ private void verifyAllowedKeyManagement(WifiConfiguration config, int[] akms) {
+ for (int akm: akms) {
+ assertTrue(config.getSecurityParamsList().stream()
+ .anyMatch(params -> params.getAllowedKeyManagement().get(akm)));
+ }
+ }
+
+ private void verifyAllowedProtocols(WifiConfiguration config, int[] aps) {
+ for (int ap: aps) {
+ assertTrue(config.getSecurityParamsList().stream()
+ .anyMatch(params -> params.getAllowedProtocols().get(ap)));
+ }
+ }
+
+ private void verifyAllowedPairwiseCiphers(WifiConfiguration config, int[] apcs) {
+ for (int apc: apcs) {
+ assertTrue(config.getSecurityParamsList().stream()
+ .anyMatch(params -> params.getAllowedPairwiseCiphers().get(apc)));
+ }
+ }
+
+ private void verifyAllowedGroupCiphers(WifiConfiguration config, int[] agcs) {
+ for (int agc: agcs) {
+ assertTrue(config.getSecurityParamsList().stream()
+ .anyMatch(params -> params.getAllowedGroupCiphers().get(agc)));
+ }
+ }
+
+ /** Verify that adding security types works as expected. */
+ @Test
+ public void testAddSecurityTypes() {
+ WifiConfiguration config = new WifiConfiguration();
+ config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK);
+ config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_SAE);
+ config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_WAPI_PSK);
+ List<SecurityParams> paramsList = config.getSecurityParamsList();
+ assertEquals(3, paramsList.size());
+
+ verifyAllowedKeyManagement(config, new int[] {
+ KeyMgmt.WPA_PSK, KeyMgmt.SAE, KeyMgmt.WAPI_PSK});
+ verifyAllowedProtocols(config, new int[] {Protocol.WPA, Protocol.RSN, Protocol.WAPI});
+ verifyAllowedPairwiseCiphers(config, new int[] {
+ PairwiseCipher.CCMP, PairwiseCipher.TKIP,
+ PairwiseCipher.GCMP_128, PairwiseCipher.GCMP_256,
+ PairwiseCipher.SMS4});
+ verifyAllowedGroupCiphers(config, new int[] {
+ GroupCipher.CCMP, GroupCipher.TKIP,
+ GroupCipher.GCMP_128, GroupCipher.GCMP_256,
+ GroupCipher.SMS4});
+ }
+
+ /** Check that a personal security type can be added to a personal configuration. */
+ @Test
+ public void testAddPersonalTypeToPersonalConfiguration() {
+ WifiConfiguration config = new WifiConfiguration();
+ config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK);
+ config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_SAE);
+ }
+
+ /** Check that an enterprise security type can be added to an enterprise configuration. */
+ @Test
+ public void testAddEnterpriseTypeToEnterpriseConfiguration() {
+ WifiConfiguration config = new WifiConfiguration();
+ config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP);
+ config.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.SIM);
+ config.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.NONE);
+ config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE);
+ }
+
+ /** Verify that adding an enterprise type to a personal configuration. */
+ @Test (expected = IllegalArgumentException.class)
+ public void testAddEnterpriseTypeToPersonalConfig() {
+ WifiConfiguration config = new WifiConfiguration();
+ config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK);
+ config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP);
+ }
+
+ /** Verify that adding a personal type to an enterprise configuration. */
+ @Test (expected = IllegalArgumentException.class)
+ public void testAddPersonalTypeToEnterpriseConfig() {
+ WifiConfiguration config = new WifiConfiguration();
+ config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP);
+ config.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.SIM);
+ config.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.NONE);
+ config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK);
+ }
+
+ /** Check that an open security cannot be added to a non-open configuration. */
+ @Test(expected = IllegalArgumentException.class)
+ public void testAddOpenTypeToNonOpenConfiguration() {
+ WifiConfiguration config = new WifiConfiguration();
+ config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK);
+ config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_OPEN);
+ }
+
+ /** Check that a non-open security cannot be added to an open configuration. */
+ @Test(expected = IllegalArgumentException.class)
+ public void testAddNonOpenTypeToOpenConfiguration() {
+ WifiConfiguration config = new WifiConfiguration();
+ config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_OPEN);
+ config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK);
+ }
+
+ /** Check that a OSEN security cannot be added as additional type. */
+ @Test(expected = IllegalArgumentException.class)
+ public void testAddOsenTypeToConfiguration() {
+ WifiConfiguration config = new WifiConfiguration();
+ config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK);
+ config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_OSEN);
+ }
+
+ /** Verify that adding duplicate security types raises the exception. */
+ @Test (expected = IllegalArgumentException.class)
+ public void testAddDuplicateSecurityTypes() {
+ WifiConfiguration config = new WifiConfiguration();
+ config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK);
+ config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK);
+ }
+
+ /** Verify that adding duplicate security params raises the exception. */
+ @Test (expected = IllegalArgumentException.class)
+ public void testAddDuplicateSecurityParams() {
+ WifiConfiguration config = new WifiConfiguration();
+ config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK);
+ config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK);
+ }
+
+ /** Verify that Suite-B type works as expected. */
+ @Test
+ public void testAddSuiteBSecurityType() {
+ WifiConfiguration config = new WifiConfiguration();
+ config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE);
+ config.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.SIM);
+ config.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.NONE);
+ config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT);
+
+ assertFalse(config.isSuiteBCipherEcdheRsaEnabled());
+ config.enableSuiteBCiphers(false, true);
+ assertTrue(config.isSuiteBCipherEcdheRsaEnabled());
+ }
+
+ /** Verify that FILS bit can be set correctly. */
+ @Test
+ public void testFilsKeyMgmt() {
+ WifiConfiguration config = new WifiConfiguration();
+ config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK);
+ config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_SAE);
+
+ config.enableFils(false, true);
+ assertFalse(config.isFilsSha256Enabled());
+ assertTrue(config.isFilsSha384Enabled());
+ }
+
+ /** Verify that SAE mode can be configured correctly. */
+ @Test
+ public void testSaeTypeMethods() {
+ WifiConfiguration config = new WifiConfiguration();
+ config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK);
+ config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_SAE);
+
+ SecurityParams saeParams = config.getSecurityParams(WifiConfiguration.SECURITY_TYPE_SAE);
+ assertNotNull(saeParams);
+ assertFalse(saeParams.isSaeH2eOnlyMode());
+ assertFalse(saeParams.isSaePkOnlyMode());
+
+ config.enableSaeH2eOnlyMode(true);
+ config.enableSaePkOnlyMode(true);
+
+ saeParams = config.getSecurityParams(WifiConfiguration.SECURITY_TYPE_SAE);
+ assertNotNull(saeParams);
+ assertTrue(saeParams.isSaeH2eOnlyMode());
+ assertTrue(saeParams.isSaePkOnlyMode());
+ }
+
+ /** Verify the legacy configuration conversion */
+ @Test
+ public void testLegacyConfigurationConversion() {
+ Pair[] keyMgmtSecurityTypePairs = new Pair[] {
+ new Pair<>(KeyMgmt.WAPI_CERT, SECURITY_TYPE_WAPI_CERT),
+ new Pair<>(KeyMgmt.WAPI_PSK, SECURITY_TYPE_WAPI_PSK),
+ new Pair<>(KeyMgmt.SUITE_B_192, SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT),
+ new Pair<>(KeyMgmt.OWE, SECURITY_TYPE_OWE),
+ new Pair<>(KeyMgmt.SAE, SECURITY_TYPE_SAE),
+ new Pair<>(KeyMgmt.OSEN, SECURITY_TYPE_OSEN),
+ new Pair<>(KeyMgmt.WPA2_PSK, SECURITY_TYPE_PSK),
+ new Pair<>(KeyMgmt.WPA_EAP, SECURITY_TYPE_EAP),
+ new Pair<>(KeyMgmt.WPA_PSK, SECURITY_TYPE_PSK),
+ new Pair<>(KeyMgmt.NONE, SECURITY_TYPE_OPEN),
+ };
+
+ for (Pair pair: keyMgmtSecurityTypePairs) {
+ WifiConfiguration config = new WifiConfiguration();
+ config.allowedKeyManagement.set((int) pair.first);
+ config.convertLegacyFieldsToSecurityParamsIfNeeded();
+ assertNotNull(config.getSecurityParams((int) pair.second));
+ }
+
+ // If none of key management is set, it should be open.
+ WifiConfiguration emptyConfig = new WifiConfiguration();
+ emptyConfig.convertLegacyFieldsToSecurityParamsIfNeeded();
+ assertNotNull(emptyConfig.getSecurityParams(SECURITY_TYPE_OPEN));
+
+ // If EAP key management is set and requirePmf is true, it is WPA3 Enterprise.
+ WifiConfiguration wpa3EnterpriseConfig = new WifiConfiguration();
+ wpa3EnterpriseConfig.allowedKeyManagement.set(KeyMgmt.WPA_EAP);
+ wpa3EnterpriseConfig.requirePmf = true;
+ wpa3EnterpriseConfig.convertLegacyFieldsToSecurityParamsIfNeeded();
+ assertNotNull(wpa3EnterpriseConfig.getSecurityParams(SECURITY_TYPE_EAP_WPA3_ENTERPRISE));
+
+ // If key management is NONE and wep key is set, it is WEP type.
+ WifiConfiguration wepConfig = new WifiConfiguration();
+ wepConfig.allowedKeyManagement.set(KeyMgmt.NONE);
+ wepConfig.wepKeys = new String[] {"\"abcdef\""};
+ wepConfig.convertLegacyFieldsToSecurityParamsIfNeeded();
+ assertNotNull(wepConfig.getSecurityParams(SECURITY_TYPE_WEP));
+ }
+
+ /** Verify the set security params by SecurityParams objects. */
+ @Test
+ public void testSetBySecurityParamsObject() {
+ int[] securityTypes = new int[] {
+ SECURITY_TYPE_WAPI_CERT,
+ SECURITY_TYPE_WAPI_PSK,
+ SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT,
+ SECURITY_TYPE_OWE,
+ SECURITY_TYPE_SAE,
+ SECURITY_TYPE_OSEN,
+ SECURITY_TYPE_EAP,
+ SECURITY_TYPE_PSK,
+ SECURITY_TYPE_OPEN,
+ SECURITY_TYPE_PASSPOINT_R1_R2,
+ SECURITY_TYPE_PASSPOINT_R3,
+ };
+ for (int type: securityTypes) {
+ WifiConfiguration config = new WifiConfiguration();
+ config.setSecurityParams(type);
+ assertTrue(config.isSecurityType(type));
+ assertNotNull(config.getSecurityParams(type));
+ }
+ }
+
+ /** Verify the set security params by an allowed key management mask. */
+ @Test
+ public void testSetSecurityParamsByAllowedKeyManagement() {
+ Pair[] keyMgmtSecurityTypePairs = new Pair[] {
+ new Pair<>(KeyMgmt.WAPI_CERT, SECURITY_TYPE_WAPI_CERT),
+ new Pair<>(KeyMgmt.WAPI_PSK, SECURITY_TYPE_WAPI_PSK),
+ new Pair<>(KeyMgmt.SUITE_B_192, SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT),
+ new Pair<>(KeyMgmt.OWE, SECURITY_TYPE_OWE),
+ new Pair<>(KeyMgmt.SAE, SECURITY_TYPE_SAE),
+ new Pair<>(KeyMgmt.OSEN, SECURITY_TYPE_OSEN),
+ new Pair<>(KeyMgmt.WPA2_PSK, SECURITY_TYPE_PSK),
+ new Pair<>(KeyMgmt.WPA_EAP, SECURITY_TYPE_EAP),
+ new Pair<>(KeyMgmt.WPA_PSK, SECURITY_TYPE_PSK),
+ new Pair<>(KeyMgmt.NONE, SECURITY_TYPE_OPEN),
+ };
+
+ for (Pair pair: keyMgmtSecurityTypePairs) {
+ BitSet akm = new BitSet();
+ akm.set((int) pair.first);
+ WifiConfiguration config = new WifiConfiguration();
+ config.setSecurityParams(akm);
+ assertNotNull(config.getSecurityParams((int) pair.second));
+ }
+ }
+
+ /** Verify the set security params by an invalid allowed key management mask. */
+ @Test (expected = IllegalArgumentException.class)
+ public void testSetSecurityParamsByInvalidAllowedKeyManagement() {
+ WifiConfiguration config = new WifiConfiguration();
+ BitSet akm = null;
+ config.setSecurityParams(akm);
+ }
+
+ /** Verify the set security params by a security params list. */
+ @Test
+ public void testSetSecurityParamsBySecurityParamsList() {
+ WifiConfiguration config = new WifiConfiguration();
+ config.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.SIM);
+ config.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.NONE);
+ config.addSecurityParams(SECURITY_TYPE_EAP);
+ config.addSecurityParams(SECURITY_TYPE_EAP_WPA3_ENTERPRISE);
+ assertTrue(config.isSecurityType(SECURITY_TYPE_EAP));
+ assertTrue(config.isSecurityType(SECURITY_TYPE_EAP_WPA3_ENTERPRISE));
+ assertFalse(config.isSecurityType(SECURITY_TYPE_PSK));
+ assertFalse(config.isSecurityType(SECURITY_TYPE_SAE));
+
+ List<SecurityParams> list = new ArrayList<>();
+ list.add(SecurityParams.createSecurityParamsBySecurityType(SECURITY_TYPE_PSK));
+ list.add(SecurityParams.createSecurityParamsBySecurityType(SECURITY_TYPE_SAE));
+ config.setSecurityParams(list);
+ assertFalse(config.isSecurityType(SECURITY_TYPE_EAP));
+ assertFalse(config.isSecurityType(SECURITY_TYPE_EAP_WPA3_ENTERPRISE));
+ assertTrue(config.isSecurityType(SECURITY_TYPE_PSK));
+ assertTrue(config.isSecurityType(SECURITY_TYPE_SAE));
+ }
+
+ /** Verify the set security params by an empty security params list. */
+ @Test (expected = IllegalArgumentException.class)
+ public void testSetSecurityParamsByEmptySecurityParamsList() {
+ WifiConfiguration config = new WifiConfiguration();
+ List<SecurityParams> list = new ArrayList<>();
+ config.setSecurityParams(list);
+ }
+
+ /** Verify the set security params by a null security params list. */
+ @Test (expected = IllegalArgumentException.class)
+ public void testSetSecurityParamsByNullSecurityParamsList() {
+ WifiConfiguration config = new WifiConfiguration();
+ List<SecurityParams> list = null;
+ config.setSecurityParams(list);
}
}
diff --git a/framework/tests/src/android/net/wifi/WifiInfoTest.java b/framework/tests/src/android/net/wifi/WifiInfoTest.java
index 311bbc4..33438ed 100644
--- a/framework/tests/src/android/net/wifi/WifiInfoTest.java
+++ b/framework/tests/src/android/net/wifi/WifiInfoTest.java
@@ -17,11 +17,13 @@
package android.net.wifi;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertTrue;
import android.os.Parcel;
+import android.telephony.SubscriptionManager;
import androidx.test.filters.SmallTest;
@@ -49,6 +51,7 @@
private static final int TEST_RSSI = -60;
private static final int TEST_NETWORK_ID = 5;
private static final int TEST_NETWORK_ID2 = 6;
+ private static final int TEST_SUB_ID = 1;
/**
* Verify parcel write/read with WifiInfo.
@@ -61,6 +64,9 @@
writeWifiInfo.txBad = TEST_TX_BAD;
writeWifiInfo.rxSuccess = TEST_RX_SUCCESS;
writeWifiInfo.setTrusted(true);
+ writeWifiInfo.setOemPaid(true);
+ writeWifiInfo.setOemPrivate(true);
+ writeWifiInfo.setCarrierMerged(true);
writeWifiInfo.setOsuAp(true);
writeWifiInfo.setFQDN(TEST_FQDN);
writeWifiInfo.setProviderFriendlyName(TEST_PROVIDER_NAME);
@@ -68,6 +74,7 @@
writeWifiInfo.setWifiStandard(TEST_WIFI_STANDARD);
writeWifiInfo.setMaxSupportedTxLinkSpeedMbps(TEST_MAX_SUPPORTED_TX_LINK_SPEED_MBPS);
writeWifiInfo.setMaxSupportedRxLinkSpeedMbps(TEST_MAX_SUPPORTED_RX_LINK_SPEED_MBPS);
+ writeWifiInfo.setSubscriptionId(TEST_SUB_ID);
Parcel parcel = Parcel.obtain();
writeWifiInfo.writeToParcel(parcel, 0);
@@ -81,6 +88,9 @@
assertEquals(TEST_TX_BAD, readWifiInfo.txBad);
assertEquals(TEST_RX_SUCCESS, readWifiInfo.rxSuccess);
assertTrue(readWifiInfo.isTrusted());
+ assertTrue(readWifiInfo.isOemPaid());
+ assertTrue(readWifiInfo.isOemPrivate());
+ assertTrue(readWifiInfo.isCarrierMerged());
assertTrue(readWifiInfo.isOsuAp());
assertTrue(readWifiInfo.isPasspointAp());
assertEquals(TEST_PACKAGE_NAME, readWifiInfo.getRequestingPackageName());
@@ -91,6 +101,50 @@
readWifiInfo.getMaxSupportedTxLinkSpeedMbps());
assertEquals(TEST_MAX_SUPPORTED_RX_LINK_SPEED_MBPS,
readWifiInfo.getMaxSupportedRxLinkSpeedMbps());
+ assertEquals(TEST_SUB_ID, readWifiInfo.getSubscriptionId());
+ }
+
+ @Test
+ public void testWifiInfoCopyConstructor() throws Exception {
+ WifiInfo writeWifiInfo = new WifiInfo();
+ writeWifiInfo.txSuccess = TEST_TX_SUCCESS;
+ writeWifiInfo.txRetries = TEST_TX_RETRIES;
+ writeWifiInfo.txBad = TEST_TX_BAD;
+ writeWifiInfo.rxSuccess = TEST_RX_SUCCESS;
+ writeWifiInfo.setTrusted(true);
+ writeWifiInfo.setOemPaid(true);
+ writeWifiInfo.setOemPrivate(true);
+ writeWifiInfo.setCarrierMerged(true);
+ writeWifiInfo.setOsuAp(true);
+ writeWifiInfo.setFQDN(TEST_FQDN);
+ writeWifiInfo.setProviderFriendlyName(TEST_PROVIDER_NAME);
+ writeWifiInfo.setRequestingPackageName(TEST_PACKAGE_NAME);
+ writeWifiInfo.setWifiStandard(TEST_WIFI_STANDARD);
+ writeWifiInfo.setMaxSupportedTxLinkSpeedMbps(TEST_MAX_SUPPORTED_TX_LINK_SPEED_MBPS);
+ writeWifiInfo.setMaxSupportedRxLinkSpeedMbps(TEST_MAX_SUPPORTED_RX_LINK_SPEED_MBPS);
+ writeWifiInfo.setSubscriptionId(TEST_SUB_ID);
+
+ WifiInfo readWifiInfo = new WifiInfo(writeWifiInfo);
+
+ assertEquals(TEST_TX_SUCCESS, readWifiInfo.txSuccess);
+ assertEquals(TEST_TX_RETRIES, readWifiInfo.txRetries);
+ assertEquals(TEST_TX_BAD, readWifiInfo.txBad);
+ assertEquals(TEST_RX_SUCCESS, readWifiInfo.rxSuccess);
+ assertTrue(readWifiInfo.isTrusted());
+ assertTrue(readWifiInfo.isOemPaid());
+ assertTrue(readWifiInfo.isOemPrivate());
+ assertTrue(readWifiInfo.isCarrierMerged());
+ assertTrue(readWifiInfo.isOsuAp());
+ assertTrue(readWifiInfo.isPasspointAp());
+ assertEquals(TEST_PACKAGE_NAME, readWifiInfo.getRequestingPackageName());
+ assertEquals(TEST_FQDN, readWifiInfo.getPasspointFqdn());
+ assertEquals(TEST_PROVIDER_NAME, readWifiInfo.getPasspointProviderFriendlyName());
+ assertEquals(TEST_WIFI_STANDARD, readWifiInfo.getWifiStandard());
+ assertEquals(TEST_MAX_SUPPORTED_TX_LINK_SPEED_MBPS,
+ readWifiInfo.getMaxSupportedTxLinkSpeedMbps());
+ assertEquals(TEST_MAX_SUPPORTED_RX_LINK_SPEED_MBPS,
+ readWifiInfo.getMaxSupportedRxLinkSpeedMbps());
+ assertEquals(TEST_SUB_ID, readWifiInfo.getSubscriptionId());
}
/**
@@ -108,6 +162,10 @@
assertEquals(WifiManager.UNKNOWN_SSID, wifiInfo.getSSID());
assertEquals(null, wifiInfo.getBSSID());
assertEquals(-1, wifiInfo.getNetworkId());
+ assertFalse(wifiInfo.isOemPaid());
+ assertFalse(wifiInfo.isOemPrivate());
+ assertFalse(wifiInfo.isCarrierMerged());
+ assertEquals(SubscriptionManager.INVALID_SUBSCRIPTION_ID, wifiInfo.getSubscriptionId());
}
/**
diff --git a/framework/tests/src/android/net/wifi/WifiManagerTest.java b/framework/tests/src/android/net/wifi/WifiManagerTest.java
index 1398bfe..274cff2 100644
--- a/framework/tests/src/android/net/wifi/WifiManagerTest.java
+++ b/framework/tests/src/android/net/wifi/WifiManagerTest.java
@@ -19,6 +19,9 @@
import static android.net.wifi.WifiConfiguration.METERED_OVERRIDE_METERED;
import static android.net.wifi.WifiManager.ActionListener;
import static android.net.wifi.WifiManager.BUSY;
+import static android.net.wifi.WifiManager.COEX_RESTRICTION_SOFTAP;
+import static android.net.wifi.WifiManager.COEX_RESTRICTION_WIFI_AWARE;
+import static android.net.wifi.WifiManager.COEX_RESTRICTION_WIFI_DIRECT;
import static android.net.wifi.WifiManager.ERROR;
import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.ERROR_GENERIC;
import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.ERROR_INCOMPATIBLE_MODE;
@@ -33,6 +36,8 @@
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 android.net.wifi.WifiManager.WIFI_FEATURE_ADDITIONAL_STA;
+import static android.net.wifi.WifiManager.WIFI_FEATURE_AP_STA;
import static android.net.wifi.WifiManager.WIFI_FEATURE_DPP;
import static android.net.wifi.WifiManager.WIFI_FEATURE_OWE;
import static android.net.wifi.WifiManager.WIFI_FEATURE_P2P;
@@ -41,6 +46,7 @@
import static android.net.wifi.WifiManager.WIFI_FEATURE_WPA3_SAE;
import static android.net.wifi.WifiManager.WIFI_FEATURE_WPA3_SUITE_B;
import static android.net.wifi.WifiManager.WpsCallback;
+import static android.net.wifi.WifiScanner.WIFI_BAND_24_GHZ;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
@@ -49,6 +55,7 @@
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeTrue;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Mockito.any;
@@ -60,6 +67,7 @@
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.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
@@ -71,6 +79,7 @@
import android.content.pm.ApplicationInfo;
import android.net.DhcpInfo;
import android.net.MacAddress;
+import android.net.wifi.WifiManager.CoexCallback;
import android.net.wifi.WifiManager.LocalOnlyHotspotCallback;
import android.net.wifi.WifiManager.LocalOnlyHotspotObserver;
import android.net.wifi.WifiManager.LocalOnlyHotspotReservation;
@@ -81,9 +90,9 @@
import android.net.wifi.WifiManager.ScanResultsCallback;
import android.net.wifi.WifiManager.SoftApCallback;
import android.net.wifi.WifiManager.SuggestionConnectionStatusListener;
+import android.net.wifi.WifiManager.SuggestionUserApprovalStatusListener;
import android.net.wifi.WifiManager.TrafficStateCallback;
import android.net.wifi.WifiManager.WifiConnectedNetworkScorer;
-import android.os.Binder;
import android.os.Build;
import android.os.Handler;
import android.os.HandlerExecutor;
@@ -95,18 +104,23 @@
import androidx.test.filters.SmallTest;
+import com.android.modules.utils.build.SdkLevel;
+
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.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
+import java.util.Set;
import java.util.concurrent.Executor;
/**
@@ -123,8 +137,18 @@
private static final String TEST_FEATURE_ID = "TestFeature";
private static final String TEST_COUNTRY_CODE = "US";
private static final String[] TEST_MAC_ADDRESSES = {"da:a1:19:0:0:0"};
- private static final int TEST_AP_FREQUENCY = 2412;
- private static final int TEST_AP_BANDWIDTH = SoftApInfo.CHANNEL_WIDTH_20MHZ;
+ private static final int TEST_SUB_ID = 3;
+ private static final String[] TEST_AP_INSTANCES = new String[] {"wlan1", "wlan2"};
+ private static final int[] TEST_AP_FREQS = new int[] {2412, 5220};
+ private static final int[] TEST_AP_BWS = new int[] {SoftApInfo.CHANNEL_WIDTH_20MHZ_NOHT,
+ SoftApInfo.CHANNEL_WIDTH_80MHZ};
+ private static final MacAddress[] TEST_AP_BSSIDS = new MacAddress[] {
+ MacAddress.fromString("22:33:44:55:66:77"),
+ MacAddress.fromString("aa:bb:cc:dd:ee:ff")};
+ private static final MacAddress[] TEST_AP_CLIENTS = new MacAddress[] {
+ MacAddress.fromString("22:33:44:aa:aa:77"),
+ MacAddress.fromString("aa:bb:cc:11:11:ff"),
+ MacAddress.fromString("22:bb:cc:11:aa:ff")};
@Mock Context mContext;
@Mock android.net.wifi.IWifiManager mWifiService;
@@ -135,20 +159,27 @@
@Mock NetworkRequestMatchCallback mNetworkRequestMatchCallback;
@Mock OnWifiUsabilityStatsListener mOnWifiUsabilityStatsListener;
@Mock OnWifiActivityEnergyInfoListener mOnWifiActivityEnergyInfoListener;
- @Mock SuggestionConnectionStatusListener mListener;
+ @Mock SuggestionConnectionStatusListener mSuggestionConnectionListener;
@Mock Runnable mRunnable;
@Mock Executor mExecutor;
@Mock Executor mAnotherExecutor;
@Mock ActivityManager mActivityManager;
@Mock WifiConnectedNetworkScorer mWifiConnectedNetworkScorer;
+ @Mock SuggestionUserApprovalStatusListener mSuggestionUserApprovalStatusListener;
private Handler mHandler;
private TestLooper mLooper;
private WifiManager mWifiManager;
private WifiNetworkSuggestion mWifiNetworkSuggestion;
private ScanResultsCallback mScanResultsCallback;
+ private CoexCallback mCoexCallback;
private WifiActivityEnergyInfo mWifiActivityEnergyInfo;
+ private HashMap<String, SoftApInfo> mTestSoftApInfoMap = new HashMap<>();
+ private HashMap<String, List<WifiClient>> mTestWifiClientsMap = new HashMap<>();
+ private SoftApInfo mTestApInfo1 = new SoftApInfo();
+ private SoftApInfo mTestApInfo2 = new SoftApInfo();
+
/**
* Util function to check public field which used for softap in WifiConfiguration
* same as the value in SoftApConfiguration.
@@ -193,6 +224,31 @@
.build();
}
+ private void initTestInfoAndAddToTestMap(int numberOfInfos) {
+ if (numberOfInfos > 2) return;
+ for (int i = 0; i < numberOfInfos; i++) {
+ SoftApInfo info = mTestApInfo1;
+ if (i == 1) info = mTestApInfo2;
+ info.setFrequency(TEST_AP_FREQS[i]);
+ info.setBandwidth(TEST_AP_BWS[i]);
+ info.setBssid(TEST_AP_BSSIDS[i]);
+ info.setApInstanceIdentifier(TEST_AP_INSTANCES[i]);
+ mTestSoftApInfoMap.put(TEST_AP_INSTANCES[i], info);
+ }
+ }
+
+ private List<WifiClient> initWifiClientAndAddToTestMap(String targetInstance,
+ int numberOfClients, int startIdx) {
+ if (numberOfClients > 3) return null;
+ List<WifiClient> clients = new ArrayList<>();
+ for (int i = startIdx; i < startIdx + numberOfClients; i++) {
+ WifiClient client = new WifiClient(TEST_AP_CLIENTS[i], targetInstance);
+ clients.add(client);
+ }
+ mTestWifiClientsMap.put(targetInstance, clients);
+ return clients;
+ }
+
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
@@ -210,19 +266,160 @@
mRunnable.run();
}
};
+ mCoexCallback = new CoexCallback() {
+ @Override
+ public void onCoexUnsafeChannelsChanged() {
+ mRunnable.run();
+ }
+ };
mWifiActivityEnergyInfo = new WifiActivityEnergyInfo(0, 0, 0, 0, 0, 0);
+ mTestSoftApInfoMap.clear();
+ mTestWifiClientsMap.clear();
}
/**
+ * Check the call to setCoexUnsafeChannels calls WifiServiceImpl to setCoexUnsafeChannels with
+ * the provided CoexUnsafeChannels and restrictions bitmask.
+ */
+ @Test
+ public void testSetCoexUnsafeChannelsGoesToWifiServiceImpl() throws Exception {
+ Set<CoexUnsafeChannel> unsafeChannels = new HashSet<>();
+ int restrictions = COEX_RESTRICTION_WIFI_DIRECT | COEX_RESTRICTION_SOFTAP
+ | COEX_RESTRICTION_WIFI_AWARE;
+
+ mWifiManager.setCoexUnsafeChannels(unsafeChannels, restrictions);
+
+ verify(mWifiService).setCoexUnsafeChannels(new ArrayList<>(unsafeChannels), restrictions);
+ }
+
+ /**
+ * Verify an IllegalArgumentException if passed a null value for unsafeChannels.
+ */
+ @Test
+ public void testSetCoexUnsafeChannelsThrowsIllegalArgumentExceptionOnNullUnsafeChannels() {
+ try {
+ mWifiManager.setCoexUnsafeChannels(null, 0);
+ fail("expected IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
+ /**
+ * Check the call to getCoexUnsafeChannels calls WifiServiceImpl to return the values from
+ * getCoexUnsafeChannels.
+ */
+ @Test
+ public void testGetCoexUnsafeChannelsGoesToWifiServiceImpl() throws Exception {
+ Set<CoexUnsafeChannel> unsafeChannels = new HashSet<>();
+ unsafeChannels.add(new CoexUnsafeChannel(WIFI_BAND_24_GHZ, 6));
+ when(mWifiService.getCoexUnsafeChannels()).thenReturn(new ArrayList<>(unsafeChannels));
+
+ assertEquals(mWifiManager.getCoexUnsafeChannels(), unsafeChannels);
+ }
+
+ /**
+ * Verify call to getCoexRestrictions calls WifiServiceImpl to return the value from
+ * getCoexRestrictions.
+ */
+ @Test
+ public void testGetCoexRestrictionsGoesToWifiServiceImpl() throws Exception {
+ int restrictions = COEX_RESTRICTION_WIFI_DIRECT | COEX_RESTRICTION_SOFTAP
+ | COEX_RESTRICTION_WIFI_AWARE;
+ when(mWifiService.getCoexRestrictions()).thenReturn(restrictions);
+
+ assertEquals(mWifiService.getCoexRestrictions(), restrictions);
+ }
+
+
+ /**
+ * Verify an IllegalArgumentException is thrown if callback is not provided.
+ */
+ @Test(expected = IllegalArgumentException.class)
+ public void testRegisterCoexCallbackWithNullCallback() throws Exception {
+ mWifiManager.registerCoexCallback(mExecutor, null);
+ }
+
+ /**
+ * Verify an IllegalArgumentException is thrown if executor is not provided.
+ */
+ @Test(expected = IllegalArgumentException.class)
+ public void testRegisterCoexCallbackWithNullExecutor() throws Exception {
+ mWifiManager.registerCoexCallback(null, mCoexCallback);
+ }
+
+ /**
+ * Verify client provided callback is being called to the right callback.
+ */
+ @Test
+ public void testAddCoexCallbackAndReceiveEvent() throws Exception {
+ ArgumentCaptor<ICoexCallback.Stub> callbackCaptor =
+ ArgumentCaptor.forClass(ICoexCallback.Stub.class);
+ mWifiManager.registerCoexCallback(new SynchronousExecutor(), mCoexCallback);
+ verify(mWifiService).registerCoexCallback(callbackCaptor.capture());
+ callbackCaptor.getValue().onCoexUnsafeChannelsChanged();
+ verify(mRunnable).run();
+ }
+
+ /**
+ * Verify client provided callback is being called to the right executor.
+ */
+ @Test
+ public void testRegisterCoexCallbackWithTheTargetExecutor() throws Exception {
+ ArgumentCaptor<ICoexCallback.Stub> callbackCaptor =
+ ArgumentCaptor.forClass(ICoexCallback.Stub.class);
+ mWifiManager.registerCoexCallback(mExecutor, mCoexCallback);
+ verify(mWifiService).registerCoexCallback(callbackCaptor.capture());
+ mWifiManager.registerCoexCallback(mAnotherExecutor, mCoexCallback);
+ callbackCaptor.getValue().onCoexUnsafeChannelsChanged();
+ verify(mExecutor, never()).execute(any(Runnable.class));
+ verify(mAnotherExecutor).execute(any(Runnable.class));
+ }
+
+ /**
+ * Verify client register unregister then register again, to ensure callback still works.
+ */
+ @Test
+ public void testRegisterUnregisterThenRegisterAgainWithCoexCallback() throws Exception {
+ ArgumentCaptor<ICoexCallback.Stub> callbackCaptor =
+ ArgumentCaptor.forClass(ICoexCallback.Stub.class);
+ mWifiManager.registerCoexCallback(new SynchronousExecutor(), mCoexCallback);
+ verify(mWifiService).registerCoexCallback(callbackCaptor.capture());
+ mWifiManager.unregisterCoexCallback(mCoexCallback);
+ callbackCaptor.getValue().onCoexUnsafeChannelsChanged();
+ verify(mRunnable, never()).run();
+ mWifiManager.registerCoexCallback(new SynchronousExecutor(), mCoexCallback);
+ callbackCaptor.getValue().onCoexUnsafeChannelsChanged();
+ verify(mRunnable).run();
+ }
+
+ /**
+ * Verify client unregisterCoexCallback.
+ */
+ @Test
+ public void testUnregisterCoexCallback() throws Exception {
+ mWifiManager.unregisterCoexCallback(mCoexCallback);
+ verify(mWifiService).unregisterCoexCallback(any());
+ }
+
+ /**
+ * Verify client unregisterCoexCallback with null callback will cause an exception.
+ */
+ @Test(expected = IllegalArgumentException.class)
+ public void testUnregisterCoexCallbackWithNullCallback() throws Exception {
+ mWifiManager.unregisterCoexCallback(null);
+ }
+
+
+ /**
* Check the call to startSoftAp calls WifiService to startSoftAp with the provided
* WifiConfiguration. Verify that the return value is propagated to the caller.
*/
@Test
public void testStartSoftApCallsServiceWithWifiConfig() throws Exception {
- when(mWifiService.startSoftAp(eq(mApConfig))).thenReturn(true);
+ when(mWifiService.startSoftAp(mApConfig, TEST_PACKAGE_NAME)).thenReturn(true);
assertTrue(mWifiManager.startSoftAp(mApConfig));
- when(mWifiService.startSoftAp(eq(mApConfig))).thenReturn(false);
+ when(mWifiService.startSoftAp(mApConfig, TEST_PACKAGE_NAME)).thenReturn(false);
assertFalse(mWifiManager.startSoftAp(mApConfig));
}
@@ -232,10 +429,10 @@
*/
@Test
public void testStartSoftApCallsServiceWithNullConfig() throws Exception {
- when(mWifiService.startSoftAp(eq(null))).thenReturn(true);
+ when(mWifiService.startSoftAp(null, TEST_PACKAGE_NAME)).thenReturn(true);
assertTrue(mWifiManager.startSoftAp(null));
- when(mWifiService.startSoftAp(eq(null))).thenReturn(false);
+ when(mWifiService.startSoftAp(null, TEST_PACKAGE_NAME)).thenReturn(false);
assertFalse(mWifiManager.startSoftAp(null));
}
@@ -258,10 +455,12 @@
@Test
public void testStartTetheredHotspotCallsServiceWithSoftApConfig() throws Exception {
SoftApConfiguration softApConfig = generatorTestSoftApConfig();
- when(mWifiService.startTetheredHotspot(eq(softApConfig))).thenReturn(true);
+ when(mWifiService.startTetheredHotspot(softApConfig, TEST_PACKAGE_NAME))
+ .thenReturn(true);
assertTrue(mWifiManager.startTetheredHotspot(softApConfig));
- when(mWifiService.startTetheredHotspot(eq(softApConfig))).thenReturn(false);
+ when(mWifiService.startTetheredHotspot(softApConfig, TEST_PACKAGE_NAME))
+ .thenReturn(false);
assertFalse(mWifiManager.startTetheredHotspot(softApConfig));
}
@@ -271,10 +470,10 @@
*/
@Test
public void testStartTetheredHotspotCallsServiceWithNullConfig() throws Exception {
- when(mWifiService.startTetheredHotspot(eq(null))).thenReturn(true);
+ when(mWifiService.startTetheredHotspot(null, TEST_PACKAGE_NAME)).thenReturn(true);
assertTrue(mWifiManager.startTetheredHotspot(null));
- when(mWifiService.startTetheredHotspot(eq(null))).thenReturn(false);
+ when(mWifiService.startTetheredHotspot(null, TEST_PACKAGE_NAME)).thenReturn(false);
assertFalse(mWifiManager.startTetheredHotspot(null));
}
@@ -930,11 +1129,149 @@
mWifiManager.registerSoftApCallback(new HandlerExecutor(mHandler), mSoftApCallback);
verify(mWifiService).registerSoftApCallback(any(IBinder.class), callbackCaptor.capture(),
anyInt());
-
- final List<WifiClient> testClients = new ArrayList();
- callbackCaptor.getValue().onConnectedClientsChanged(testClients);
+ List<WifiClient> clientList;
+ // Verify the register callback in disable state.
+ callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
+ (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
+ (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), false, true);
mLooper.dispatchAll();
- verify(mSoftApCallback).onConnectedClientsChanged(testClients);
+ verify(mSoftApCallback).onConnectedClientsChanged(new ArrayList<WifiClient>());
+ verify(mSoftApCallback, never()).onConnectedClientsChanged(any(), any());
+ verify(mSoftApCallback).onInfoChanged(new SoftApInfo());
+ verify(mSoftApCallback).onInfoChanged(new ArrayList<SoftApInfo>());
+ // After verify, reset mSoftApCallback for nex test
+ reset(mSoftApCallback);
+
+ // Single AP mode Test
+ // Test info update
+ initTestInfoAndAddToTestMap(1);
+ callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
+ (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
+ (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), false, false);
+ mLooper.dispatchAll();
+ verify(mSoftApCallback).onInfoChanged(mTestApInfo1);
+ verify(mSoftApCallback).onInfoChanged(Mockito.argThat((List<SoftApInfo> infos) ->
+ infos.contains(mTestApInfo1)));
+ verify(mSoftApCallback, never()).onConnectedClientsChanged(any());
+ verify(mSoftApCallback, never()).onConnectedClientsChanged(any(), any());
+ // After verify, reset mSoftApCallback for nex test
+ reset(mSoftApCallback);
+
+ // Test first client connected
+ clientList = initWifiClientAndAddToTestMap(TEST_AP_INSTANCES[0], 1, 0);
+ callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
+ (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
+ (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), false, false);
+ mLooper.dispatchAll();
+ // checked NO any infoChanged, includes InfoChanged(SoftApInfo)
+ // and InfoChanged(List<SoftApInfo>)
+ verify(mSoftApCallback, never()).onInfoChanged(any(SoftApInfo.class));
+ verify(mSoftApCallback, never()).onInfoChanged(any(List.class));
+ verify(mSoftApCallback).onConnectedClientsChanged(mTestApInfo1, clientList);
+ verify(mSoftApCallback).onConnectedClientsChanged(clientList);
+ // After verify, reset mSoftApCallback for nex test
+ reset(mSoftApCallback);
+
+ // Test second client connected
+ mTestWifiClientsMap.clear();
+ clientList = initWifiClientAndAddToTestMap(TEST_AP_INSTANCES[0], 2, 0);
+ callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
+ (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
+ (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), false, false);
+ mLooper.dispatchAll();
+ // checked NO any infoChanged, includes InfoChanged(SoftApInfo)
+ // and InfoChanged(List<SoftApInfo>)
+ verify(mSoftApCallback, never()).onInfoChanged(any(SoftApInfo.class));
+ verify(mSoftApCallback, never()).onInfoChanged(any(List.class));
+ verify(mSoftApCallback).onConnectedClientsChanged(mTestApInfo1, clientList);
+ verify(mSoftApCallback).onConnectedClientsChanged(clientList);
+ // After verify, reset mSoftApCallback for nex test
+ reset(mSoftApCallback);
+
+ // Test second client disconnect
+ mTestWifiClientsMap.clear();
+ clientList = initWifiClientAndAddToTestMap(TEST_AP_INSTANCES[0], 1, 0);
+ callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
+ (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
+ (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), false, false);
+ mLooper.dispatchAll();
+ // checked NO any infoChanged, includes InfoChanged(SoftApInfo)
+ // and InfoChanged(List<SoftApInfo>)
+ verify(mSoftApCallback, never()).onInfoChanged(any(SoftApInfo.class));
+ verify(mSoftApCallback, never()).onInfoChanged(any(List.class));
+ verify(mSoftApCallback).onConnectedClientsChanged(mTestApInfo1, clientList);
+ verify(mSoftApCallback).onConnectedClientsChanged(clientList);
+ // After verify, reset mSoftApCallback for nex test
+ reset(mSoftApCallback);
+
+ // Test bridged mode case
+ mTestSoftApInfoMap.clear();
+ initTestInfoAndAddToTestMap(2);
+ callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
+ (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
+ (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), true, false);
+ mLooper.dispatchAll();
+ verify(mSoftApCallback, never()).onInfoChanged(any(SoftApInfo.class));
+ verify(mSoftApCallback).onInfoChanged(Mockito.argThat((List<SoftApInfo> infos) ->
+ infos.contains(mTestApInfo1) && infos.contains(mTestApInfo2)
+ ));
+ verify(mSoftApCallback, never()).onConnectedClientsChanged(any());
+ verify(mSoftApCallback, never()).onConnectedClientsChanged(any(), any());
+ // After verify, reset mSoftApCallback for nex test
+ reset(mSoftApCallback);
+
+ // Test client connect to second instance
+ List<WifiClient> clientListOnSecond =
+ initWifiClientAndAddToTestMap(TEST_AP_INSTANCES[1], 1, 2); // client3 to wlan2
+ List<WifiClient> totalList = new ArrayList<>();
+ totalList.addAll(clientList);
+ totalList.addAll(clientListOnSecond);
+ callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
+ (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
+ (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), true, false);
+ mLooper.dispatchAll();
+ // checked NO any infoChanged, includes InfoChanged(SoftApInfo)
+ // and InfoChanged(List<SoftApInfo>)
+ verify(mSoftApCallback, never()).onInfoChanged(any(SoftApInfo.class));
+ verify(mSoftApCallback, never()).onInfoChanged(any(List.class));
+ verify(mSoftApCallback).onConnectedClientsChanged(mTestApInfo2, clientListOnSecond);
+ verify(mSoftApCallback).onConnectedClientsChanged(totalList);
+ // After verify, reset mSoftApCallback for nex test
+ reset(mSoftApCallback);
+
+ // Test shutdown on second instance
+ mTestSoftApInfoMap.clear();
+ mTestWifiClientsMap.clear();
+ initTestInfoAndAddToTestMap(1);
+ clientList = initWifiClientAndAddToTestMap(TEST_AP_INSTANCES[0], 1, 0);
+ callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
+ (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
+ (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), true, false);
+ mLooper.dispatchAll();
+ verify(mSoftApCallback, never()).onInfoChanged(any(SoftApInfo.class));
+ verify(mSoftApCallback).onInfoChanged(Mockito.argThat((List<SoftApInfo> infos) ->
+ infos.contains(mTestApInfo1)));
+ // second instance have client connected before, thus it should send empty list
+ verify(mSoftApCallback).onConnectedClientsChanged(
+ mTestApInfo2, new ArrayList<WifiClient>());
+ verify(mSoftApCallback).onConnectedClientsChanged(clientList);
+ // After verify, reset mSoftApCallback for nex test
+ reset(mSoftApCallback);
+
+ // Test bridged mode disable when client connected
+ mTestSoftApInfoMap.clear();
+ mTestWifiClientsMap.clear();
+ callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
+ (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
+ (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), true, false);
+ mLooper.dispatchAll();
+ verify(mSoftApCallback, never()).onInfoChanged(any(SoftApInfo.class));
+ verify(mSoftApCallback).onInfoChanged(new ArrayList<SoftApInfo>());
+ verify(mSoftApCallback).onConnectedClientsChanged(new ArrayList<WifiClient>());
+ verify(mSoftApCallback).onConnectedClientsChanged(
+ mTestApInfo1, new ArrayList<WifiClient>());
+ // After verify, reset mSoftApCallback for nex test
+ reset(mSoftApCallback);
}
@@ -943,20 +1280,139 @@
*/
@Test
public void softApCallbackProxyCallsOnSoftApInfoChanged() throws Exception {
- SoftApInfo testSoftApInfo = new SoftApInfo();
- testSoftApInfo.setFrequency(TEST_AP_FREQUENCY);
- testSoftApInfo.setBandwidth(TEST_AP_BANDWIDTH);
+ ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor =
+ ArgumentCaptor.forClass(ISoftApCallback.Stub.class);
+ mWifiManager.registerSoftApCallback(new HandlerExecutor(mHandler), mSoftApCallback);
+ verify(mWifiService).registerSoftApCallback(any(IBinder.class), callbackCaptor.capture(),
+ anyInt());
+ // Verify the register callback in disable state.
+ callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
+ (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
+ (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), false, true);
+ mLooper.dispatchAll();
+ verify(mSoftApCallback).onConnectedClientsChanged(new ArrayList<WifiClient>());
+ verify(mSoftApCallback, never()).onConnectedClientsChanged(any(), any());
+ verify(mSoftApCallback).onInfoChanged(new SoftApInfo());
+ verify(mSoftApCallback).onInfoChanged(new ArrayList<SoftApInfo>());
+ // After verify, reset mSoftApCallback for nex test
+ reset(mSoftApCallback);
+
+ // Single AP mode Test
+ // Test info update
+ initTestInfoAndAddToTestMap(1);
+ callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
+ (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
+ (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), false, false);
+ mLooper.dispatchAll();
+ verify(mSoftApCallback).onInfoChanged(mTestApInfo1);
+ verify(mSoftApCallback).onInfoChanged(Mockito.argThat((List<SoftApInfo> infos) ->
+ infos.contains(mTestApInfo1)));
+ verify(mSoftApCallback, never()).onConnectedClientsChanged(any());
+ verify(mSoftApCallback, never()).onConnectedClientsChanged(any(), any());
+ // After verify, reset mSoftApCallback for nex test
+ reset(mSoftApCallback);
+
+ // Test info changed
+ SoftApInfo changedInfo = new SoftApInfo(mTestSoftApInfoMap.get(TEST_AP_INSTANCES[0]));
+ changedInfo.setFrequency(2422);
+ mTestSoftApInfoMap.put(TEST_AP_INSTANCES[0], changedInfo);
+ callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
+ (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
+ (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), false, false);
+ mLooper.dispatchAll();
+ verify(mSoftApCallback).onInfoChanged(changedInfo);
+ verify(mSoftApCallback).onInfoChanged(Mockito.argThat((List<SoftApInfo> infos) ->
+ infos.contains(changedInfo)));
+ verify(mSoftApCallback, never()).onConnectedClientsChanged(any());
+ verify(mSoftApCallback, never()).onConnectedClientsChanged(any(), any());
+
+ // Test Stop, all of infos is empty
+ mTestSoftApInfoMap.clear();
+ callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
+ (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
+ (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), false, false);
+ mLooper.dispatchAll();
+ verify(mSoftApCallback).onInfoChanged(new SoftApInfo());
+ verify(mSoftApCallback).onInfoChanged(new ArrayList<SoftApInfo>());
+ verify(mSoftApCallback, never()).onConnectedClientsChanged(any());
+ verify(mSoftApCallback, never()).onConnectedClientsChanged(any(), any());
+ // After verify, reset mSoftApCallback for nex test
+ reset(mSoftApCallback);
+ }
+
+ /*
+ * Verify client-provided callback is being called through callback proxy
+ */
+ @Test
+ public void softApCallbackProxyCallsOnSoftApInfoChangedInBridgedMode() throws Exception {
ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor =
ArgumentCaptor.forClass(ISoftApCallback.Stub.class);
mWifiManager.registerSoftApCallback(new HandlerExecutor(mHandler), mSoftApCallback);
verify(mWifiService).registerSoftApCallback(any(IBinder.class), callbackCaptor.capture(),
anyInt());
- callbackCaptor.getValue().onInfoChanged(testSoftApInfo);
+ // Test bridged mode case
+ initTestInfoAndAddToTestMap(2);
+ callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
+ (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
+ (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), true, false);
mLooper.dispatchAll();
- verify(mSoftApCallback).onInfoChanged(testSoftApInfo);
- }
+ verify(mSoftApCallback, never()).onInfoChanged(any(SoftApInfo.class));
+ verify(mSoftApCallback).onInfoChanged(Mockito.argThat((List<SoftApInfo> infos) ->
+ infos.contains(mTestApInfo1) && infos.contains(mTestApInfo2)
+ ));
+ verify(mSoftApCallback, never()).onConnectedClientsChanged(any());
+ verify(mSoftApCallback, never()).onConnectedClientsChanged(any(), any());
+ // After verify, reset mSoftApCallback for nex test
+ reset(mSoftApCallback);
+ // Test bridged mode case but an info changed
+ SoftApInfo changedInfoBridgedMode = new SoftApInfo(mTestSoftApInfoMap.get(
+ TEST_AP_INSTANCES[0]));
+ changedInfoBridgedMode.setFrequency(2422);
+ mTestSoftApInfoMap.put(TEST_AP_INSTANCES[0], changedInfoBridgedMode);
+ callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
+ (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
+ (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), true, false);
+ mLooper.dispatchAll();
+ verify(mSoftApCallback, never()).onInfoChanged(any(SoftApInfo.class));
+ verify(mSoftApCallback).onInfoChanged(Mockito.argThat((List<SoftApInfo> infos) ->
+ infos.contains(changedInfoBridgedMode) && infos.contains(mTestApInfo2)
+ ));
+ verify(mSoftApCallback, never()).onConnectedClientsChanged(any());
+ verify(mSoftApCallback, never()).onConnectedClientsChanged(any(), any());
+ // After verify, reset mSoftApCallback for nex test
+ reset(mSoftApCallback);
+
+ // Test bridged mode case but an instance shutdown
+ mTestSoftApInfoMap.clear();
+ initTestInfoAndAddToTestMap(1);
+ callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
+ (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
+ (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), true, false);
+ mLooper.dispatchAll();
+ verify(mSoftApCallback, never()).onInfoChanged(any(SoftApInfo.class));
+ verify(mSoftApCallback).onInfoChanged(Mockito.argThat((List<SoftApInfo> infos) ->
+ infos.contains(mTestApInfo1)
+ ));
+ verify(mSoftApCallback, never()).onConnectedClientsChanged(any());
+ verify(mSoftApCallback, never()).onConnectedClientsChanged(any(), any());
+ // After verify, reset mSoftApCallback for nex test
+ reset(mSoftApCallback);
+
+ // Test bridged mode disable case
+ mTestSoftApInfoMap.clear();
+ callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
+ (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
+ (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), true, false);
+ mLooper.dispatchAll();
+ verify(mSoftApCallback, never()).onInfoChanged(any(SoftApInfo.class));
+ verify(mSoftApCallback).onInfoChanged(new ArrayList<SoftApInfo>());
+ verify(mSoftApCallback, never()).onConnectedClientsChanged(any());
+ verify(mSoftApCallback, never()).onConnectedClientsChanged(any(), any());
+ // After verify, reset mSoftApCallback for nex test
+ reset(mSoftApCallback);
+ }
/*
* Verify client-provided callback is being called through callback proxy
@@ -981,7 +1437,8 @@
*/
@Test
public void softApCallbackProxyCallsOnBlockedClientConnecting() throws Exception {
- WifiClient testWifiClient = new WifiClient(MacAddress.fromString("22:33:44:55:66:77"));
+ WifiClient testWifiClient = new WifiClient(MacAddress.fromString("22:33:44:55:66:77"),
+ TEST_AP_INSTANCES[0]);
ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor =
ArgumentCaptor.forClass(ISoftApCallback.Stub.class);
mWifiManager.registerSoftApCallback(new HandlerExecutor(mHandler), mSoftApCallback);
@@ -1000,9 +1457,6 @@
*/
@Test
public void softApCallbackProxyCallsOnMultipleUpdates() throws Exception {
- SoftApInfo testSoftApInfo = new SoftApInfo();
- testSoftApInfo.setFrequency(TEST_AP_FREQUENCY);
- testSoftApInfo.setBandwidth(TEST_AP_BANDWIDTH);
SoftApCapability testSoftApCapability = new SoftApCapability(0);
testSoftApCapability.setMaxSupportedClients(10);
ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor =
@@ -1013,16 +1467,12 @@
final List<WifiClient> testClients = new ArrayList();
callbackCaptor.getValue().onStateChanged(WIFI_AP_STATE_ENABLING, 0);
- callbackCaptor.getValue().onConnectedClientsChanged(testClients);
- callbackCaptor.getValue().onInfoChanged(testSoftApInfo);
callbackCaptor.getValue().onStateChanged(WIFI_AP_STATE_FAILED, SAP_START_FAILURE_GENERAL);
callbackCaptor.getValue().onCapabilityChanged(testSoftApCapability);
mLooper.dispatchAll();
verify(mSoftApCallback).onStateChanged(WIFI_AP_STATE_ENABLING, 0);
- verify(mSoftApCallback).onConnectedClientsChanged(testClients);
- verify(mSoftApCallback).onInfoChanged(testSoftApInfo);
verify(mSoftApCallback).onStateChanged(WIFI_AP_STATE_FAILED, SAP_START_FAILURE_GENERAL);
verify(mSoftApCallback).onCapabilityChanged(testSoftApCapability);
}
@@ -1628,6 +2078,24 @@
}
/**
+ * Verify the call to startTemporarilyDisablingAllNonCarrierMergedWifi goes to WifiServiceImpl.
+ */
+ @Test
+ public void testStartTemporarilyDisablingAllNonCarrierMergedWifi() throws Exception {
+ mWifiManager.startTemporarilyDisablingAllNonCarrierMergedWifi(1);
+ verify(mWifiService).startTemporarilyDisablingAllNonCarrierMergedWifi(1);
+ }
+
+ /**
+ * Verify the call to stopTemporarilyDisablingAllNonCarrierMergedWifi goes to WifiServiceImpl.
+ */
+ @Test
+ public void testStopTemporarilyDisablingAllNonCarrierMergedWifi() throws Exception {
+ mWifiManager.stopTemporarilyDisablingAllNonCarrierMergedWifi();
+ verify(mWifiService).stopTemporarilyDisablingAllNonCarrierMergedWifi();
+ }
+
+ /**
* Verify the call to addOnWifiUsabilityStatsListener goes to WifiServiceImpl.
*/
@Test
@@ -1707,6 +2175,34 @@
}
/**
+ * Test behavior of isStaApConcurrencySupported
+ */
+ @Test
+ public void testIsStaApConcurrencyOpenSupported() throws Exception {
+ when(mWifiService.getSupportedFeatures())
+ .thenReturn(new Long(WIFI_FEATURE_AP_STA));
+ assertTrue(mWifiManager.isStaApConcurrencySupported());
+ when(mWifiService.getSupportedFeatures())
+ .thenReturn(new Long(~WIFI_FEATURE_AP_STA));
+ assertFalse(mWifiManager.isStaApConcurrencySupported());
+ }
+
+ /**
+ * Test behavior of isMultiStaConcurrencySupported
+ */
+ @Test
+ public void testIsMultiStaConcurrencyOpenSupported() throws Exception {
+ assumeTrue(SdkLevel.isAtLeastS());
+
+ when(mWifiService.getSupportedFeatures())
+ .thenReturn(new Long(WIFI_FEATURE_ADDITIONAL_STA));
+ assertTrue(mWifiManager.isMultiStaConcurrencySupported());
+ when(mWifiService.getSupportedFeatures())
+ .thenReturn(new Long(~WIFI_FEATURE_ADDITIONAL_STA));
+ assertFalse(mWifiManager.isMultiStaConcurrencySupported());
+ }
+
+ /**
* Test behavior of {@link WifiManager#addNetwork(WifiConfiguration)}
*/
@Test
@@ -1857,7 +2353,6 @@
assertFalse(mWifiManager.isDeviceToDeviceRttSupported());
assertFalse(mWifiManager.isDeviceToApRttSupported());
assertFalse(mWifiManager.isPreferredNetworkOffloadSupported());
- assertFalse(mWifiManager.isAdditionalStaSupported());
assertFalse(mWifiManager.isTdlsSupported());
assertFalse(mWifiManager.isOffChannelTdlsSupported());
assertFalse(mWifiManager.isEnhancedPowerReportingSupported());
@@ -1992,8 +2487,7 @@
ArgumentCaptor<IActionListener> binderListenerCaptor =
ArgumentCaptor.forClass(IActionListener.class);
- verify(mWifiService).connect(eq(null), eq(TEST_NETWORK_ID), any(Binder.class),
- binderListenerCaptor.capture(), anyInt());
+ verify(mWifiService).connect(eq(null), eq(TEST_NETWORK_ID), binderListenerCaptor.capture());
assertNotNull(binderListenerCaptor.getValue());
// Trigger on success.
@@ -2013,8 +2507,7 @@
@Test
public void testConnectWithListenerHandleSecurityException() throws Exception {
doThrow(new SecurityException()).when(mWifiService)
- .connect(eq(null), anyInt(), any(IBinder.class),
- any(IActionListener.class), anyInt());
+ .connect(eq(null), anyInt(), any(IActionListener.class));
ActionListener externalListener = mock(ActionListener.class);
mWifiManager.connect(TEST_NETWORK_ID, externalListener);
@@ -2028,8 +2521,7 @@
@Test
public void testConnectWithListenerHandleRemoteException() throws Exception {
doThrow(new RemoteException()).when(mWifiService)
- .connect(eq(null), anyInt(), any(IBinder.class),
- any(IActionListener.class), anyInt());
+ .connect(eq(null), anyInt(), any(IActionListener.class));
ActionListener externalListener = mock(ActionListener.class);
mWifiManager.connect(TEST_NETWORK_ID, externalListener);
@@ -2045,8 +2537,7 @@
WifiConfiguration configuration = new WifiConfiguration();
mWifiManager.connect(configuration, null);
- verify(mWifiService).connect(configuration, WifiConfiguration.INVALID_NETWORK_ID, null,
- null, 0);
+ verify(mWifiService).connect(configuration, WifiConfiguration.INVALID_NETWORK_ID, null);
}
/**
@@ -2132,7 +2623,7 @@
*/
@Test(expected = IllegalArgumentException.class)
public void testAddSuggestionConnectionStatusListenerWithNullExecutor() {
- mWifiManager.addSuggestionConnectionStatusListener(null, mListener);
+ mWifiManager.addSuggestionConnectionStatusListener(null, mSuggestionConnectionListener);
}
/**
@@ -2152,11 +2643,12 @@
ArgumentCaptor<ISuggestionConnectionStatusListener.Stub> callbackCaptor =
ArgumentCaptor.forClass(ISuggestionConnectionStatusListener.Stub.class);
Executor executor = new SynchronousExecutor();
- mWifiManager.addSuggestionConnectionStatusListener(executor, mListener);
+ mWifiManager.addSuggestionConnectionStatusListener(executor, mSuggestionConnectionListener);
verify(mWifiService).registerSuggestionConnectionStatusListener(any(IBinder.class),
callbackCaptor.capture(), anyInt(), anyString(), nullable(String.class));
callbackCaptor.getValue().onConnectionStatus(mWifiNetworkSuggestion, errorCode);
- verify(mListener).onConnectionStatus(any(WifiNetworkSuggestion.class), eq(errorCode));
+ verify(mSuggestionConnectionListener).onConnectionStatus(any(WifiNetworkSuggestion.class),
+ eq(errorCode));
}
/**
@@ -2167,7 +2659,8 @@
int errorCode = STATUS_SUGGESTION_CONNECTION_FAILURE_AUTHENTICATION;
ArgumentCaptor<ISuggestionConnectionStatusListener.Stub> callbackCaptor =
ArgumentCaptor.forClass(ISuggestionConnectionStatusListener.Stub.class);
- mWifiManager.addSuggestionConnectionStatusListener(mExecutor, mListener);
+ mWifiManager.addSuggestionConnectionStatusListener(mExecutor,
+ mSuggestionConnectionListener);
verify(mWifiService).registerSuggestionConnectionStatusListener(any(IBinder.class),
callbackCaptor.capture(), anyInt(), anyString(), nullable(String.class));
callbackCaptor.getValue().onConnectionStatus(any(WifiNetworkSuggestion.class), errorCode);
@@ -2187,7 +2680,7 @@
*/
@Test
public void testRemoveSuggestionConnectionListener() throws Exception {
- mWifiManager.removeSuggestionConnectionStatusListener(mListener);
+ mWifiManager.removeSuggestionConnectionStatusListener(mSuggestionConnectionListener);
verify(mWifiService).unregisterSuggestionConnectionStatusListener(anyInt(), anyString());
}
@@ -2380,10 +2873,118 @@
@Test
public void testScanAvailable() throws Exception {
mWifiManager.setScanAlwaysAvailable(true);
- verify(mWifiService).setScanAlwaysAvailable(true);
+ verify(mWifiService).setScanAlwaysAvailable(true, TEST_PACKAGE_NAME);
when(mWifiService.isScanAlwaysAvailable()).thenReturn(false);
assertFalse(mWifiManager.isScanAlwaysAvailable());
verify(mWifiService).isScanAlwaysAvailable();
}
+
+ @Test
+ public void testGetNetworkSuggestionUserApprovalStatus() throws Exception {
+ assumeTrue(SdkLevel.isAtLeastS());
+
+ when(mWifiService.getNetworkSuggestionUserApprovalStatus(TEST_PACKAGE_NAME))
+ .thenReturn(WifiManager.STATUS_SUGGESTION_APPROVAL_APPROVED_BY_USER);
+ assertEquals(WifiManager.STATUS_SUGGESTION_APPROVAL_APPROVED_BY_USER,
+ mWifiManager.getNetworkSuggestionUserApprovalStatus());
+ verify(mWifiService).getNetworkSuggestionUserApprovalStatus(TEST_PACKAGE_NAME);
+ }
+
+ @Test
+ public void testSetCarrierNetworkOffload() throws Exception {
+ assumeTrue(SdkLevel.isAtLeastS());
+ mWifiManager.setCarrierNetworkOffloadEnabled(TEST_SUB_ID, true, false);
+ verify(mWifiService).setCarrierNetworkOffloadEnabled(TEST_SUB_ID,
+ true, false);
+ }
+
+ @Test
+ public void testGetCarrierNetworkOffload() throws Exception {
+ assumeTrue(SdkLevel.isAtLeastS());
+ when(mWifiService.isCarrierNetworkOffloadEnabled(TEST_SUB_ID, false)).thenReturn(true);
+ assertTrue(mWifiManager.isCarrierNetworkOffloadEnabled(TEST_SUB_ID, false));
+ verify(mWifiService).isCarrierNetworkOffloadEnabled(TEST_SUB_ID, false);
+ }
+
+
+ /**
+ * Verify an IllegalArgumentException is thrown if listener is not provided.
+ */
+ @Test(expected = IllegalArgumentException.class)
+ public void testRemoveSuggestionUserApprovalStatusListenerWithNullListener() {
+ assumeTrue(SdkLevel.isAtLeastS());
+
+ mWifiManager.removeSuggestionUserApprovalStatusListener(null);
+ }
+
+
+ /**
+ * Verify removeSuggestionUserApprovalStatusListener.
+ */
+ @Test
+ public void testRemoveSuggestionUserApprovalStatusListener() throws Exception {
+ assumeTrue(SdkLevel.isAtLeastS());
+
+ mWifiManager.removeSuggestionUserApprovalStatusListener(
+ mSuggestionUserApprovalStatusListener);
+ verify(mWifiService).removeSuggestionUserApprovalStatusListener(anyInt(), anyString());
+ }
+
+ /**
+ * Verify an IllegalArgumentException is thrown if executor not provided.
+ */
+ @Test(expected = IllegalArgumentException.class)
+ public void testAddSuggestionUserApprovalStatusListenerWithNullExecutor() {
+ assumeTrue(SdkLevel.isAtLeastS());
+
+ mWifiManager.addSuggestionUserApprovalStatusListener(null,
+ mSuggestionUserApprovalStatusListener);
+ }
+
+ /**
+ * Verify an IllegalArgumentException is thrown if listener is not provided.
+ */
+ @Test(expected = IllegalArgumentException.class)
+ public void testAddSuggestionUserApprovalStatusListenerWithNullListener() {
+ assumeTrue(SdkLevel.isAtLeastS());
+
+ mWifiManager.addSuggestionUserApprovalStatusListener(mExecutor, null);
+ }
+
+ /**
+ * Verify client provided listener is being called to the right listener.
+ */
+ @Test
+ public void testAddSuggestionUserApprovalStatusListenerAndReceiveEvent() throws Exception {
+ assumeTrue(SdkLevel.isAtLeastS());
+
+ ArgumentCaptor<ISuggestionUserApprovalStatusListener.Stub> callbackCaptor =
+ ArgumentCaptor.forClass(ISuggestionUserApprovalStatusListener.Stub.class);
+ Executor executor = new SynchronousExecutor();
+ mWifiManager.addSuggestionUserApprovalStatusListener(executor,
+ mSuggestionUserApprovalStatusListener);
+ verify(mWifiService).addSuggestionUserApprovalStatusListener(any(IBinder.class),
+ callbackCaptor.capture(), anyInt(), anyString(), nullable(String.class));
+ callbackCaptor.getValue().onUserApprovalStatusChange();
+ verify(mSuggestionUserApprovalStatusListener).onUserApprovalStatusChange();
+ }
+
+ /**
+ * Verify client provided listener is being called to the right executor.
+ */
+ @Test
+ public void testAddSuggestionUserApprovalStatusListenerWithTheTargetExecutor()
+ throws Exception {
+ assumeTrue(SdkLevel.isAtLeastS());
+ ArgumentCaptor<ISuggestionUserApprovalStatusListener.Stub> callbackCaptor =
+ ArgumentCaptor.forClass(ISuggestionUserApprovalStatusListener.Stub.class);
+ mWifiManager.addSuggestionUserApprovalStatusListener(mExecutor,
+ mSuggestionUserApprovalStatusListener);
+ verify(mWifiService).addSuggestionUserApprovalStatusListener(any(IBinder.class),
+ callbackCaptor.capture(), anyInt(), anyString(), nullable(String.class));
+ callbackCaptor.getValue().onUserApprovalStatusChange();
+ verify(mExecutor).execute(any(Runnable.class));
+ }
+
}
diff --git a/framework/tests/src/android/net/wifi/WifiNetworkSpecifierTest.java b/framework/tests/src/android/net/wifi/WifiNetworkSpecifierTest.java
index 6f47f3d..464f462 100644
--- a/framework/tests/src/android/net/wifi/WifiNetworkSpecifierTest.java
+++ b/framework/tests/src/android/net/wifi/WifiNetworkSpecifierTest.java
@@ -141,11 +141,11 @@
}
/**
- * Validate correctness of WifiNetworkSuggestion object created by
- * {@link WifiNetworkSuggestion.Builder#build()} for WPA3-Enterprise network.
+ * Validate correctness of WifiNetworkSpecifier object created by
+ * {@link WifiNetworkSpecifier.Builder#build()} for WPA3-Enterprise network.
*/
@Test
- public void testWifiNetworkSuggestionBuilderForWpa3EapNetwork() {
+ public void testWifiNetworkSpecifierBuilderForWpa3EapNetwork() {
WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig();
enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS);
enterpriseConfig.setCaCertificate(FakeKeys.CA_CERT0);
@@ -174,11 +174,118 @@
}
/**
- * Validate correctness of WifiNetworkSuggestion object created by
- * {@link WifiNetworkSuggestion.Builder#build()} for WPA3-Enterprise 192-bit RSA SuiteB network.
+ * Validate correctness of WifiNetworkSpecifier object created by
+ * {@link WifiNetworkSpecifier.Builder#build()} for WPA3-Enterprise network.
*/
@Test
- public void testWifiNetworkSuggestionBuilderForWpa3SuiteBRsaEapNetwork() {
+ public void testWifiNetworkSpecifierBuilderForWpa3EapNetworkWithStandardApi() {
+ WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig();
+ enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS);
+ enterpriseConfig.setCaCertificate(FakeKeys.CA_CERT0);
+ enterpriseConfig.setDomainSuffixMatch(TEST_DOMAIN_SUFFIX_MATCH);
+
+ NetworkSpecifier specifier = new WifiNetworkSpecifier.Builder()
+ .setSsid(TEST_SSID)
+ .setWpa3EnterpriseStandardModeConfig(enterpriseConfig)
+ .build();
+
+ assertTrue(specifier instanceof WifiNetworkSpecifier);
+ WifiNetworkSpecifier wifiNetworkSpecifier = (WifiNetworkSpecifier) specifier;
+
+ assertEquals("\"" + TEST_SSID + "\"", wifiNetworkSpecifier.wifiConfiguration.SSID);
+ assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedKeyManagement
+ .get(WifiConfiguration.KeyMgmt.IEEE8021X));
+ assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedKeyManagement
+ .get(WifiConfiguration.KeyMgmt.WPA_EAP));
+ assertFalse(wifiNetworkSpecifier.wifiConfiguration.allowedKeyManagement
+ .get(WifiConfiguration.KeyMgmt.SUITE_B_192));
+ assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedGroupCiphers
+ .get(WifiConfiguration.GroupCipher.CCMP));
+ assertTrue(wifiNetworkSpecifier.wifiConfiguration.requirePmf);
+ assertNull(wifiNetworkSpecifier.wifiConfiguration.preSharedKey);
+ assertNotNull(wifiNetworkSpecifier.wifiConfiguration.enterpriseConfig);
+ }
+
+ /**
+ * Validate correctness of WifiNetworkSpecifier object created by
+ * {@link WifiNetworkSpecifier.Builder#build()} for WPA3-Enterprise network
+ * with 192-bit RSA certificates.
+ */
+ @Test
+ public void testWifiNetworkSpecifierBuilderForWpa3EapNetworkWithSuiteBRsaCerts() {
+ WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig();
+ enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS);
+ enterpriseConfig.setCaCertificate(FakeKeys.CA_SUITE_B_RSA3072_CERT);
+ enterpriseConfig.setClientKeyEntryWithCertificateChain(FakeKeys.CLIENT_SUITE_B_RSA3072_KEY,
+ new X509Certificate[] {FakeKeys.CLIENT_SUITE_B_RSA3072_CERT});
+
+ enterpriseConfig.setDomainSuffixMatch(TEST_DOMAIN_SUFFIX_MATCH);
+
+ NetworkSpecifier specifier = new WifiNetworkSpecifier.Builder()
+ .setSsid(TEST_SSID)
+ .setWpa3EnterpriseStandardModeConfig(enterpriseConfig)
+ .build();
+
+ assertTrue(specifier instanceof WifiNetworkSpecifier);
+ WifiNetworkSpecifier wifiNetworkSpecifier = (WifiNetworkSpecifier) specifier;
+
+ assertEquals("\"" + TEST_SSID + "\"", wifiNetworkSpecifier.wifiConfiguration.SSID);
+ assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedKeyManagement
+ .get(WifiConfiguration.KeyMgmt.IEEE8021X));
+ assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedKeyManagement
+ .get(WifiConfiguration.KeyMgmt.WPA_EAP));
+ assertFalse(wifiNetworkSpecifier.wifiConfiguration.allowedKeyManagement
+ .get(WifiConfiguration.KeyMgmt.SUITE_B_192));
+ assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedGroupCiphers
+ .get(WifiConfiguration.GroupCipher.CCMP));
+ assertTrue(wifiNetworkSpecifier.wifiConfiguration.requirePmf);
+ assertNull(wifiNetworkSpecifier.wifiConfiguration.preSharedKey);
+ assertNotNull(wifiNetworkSpecifier.wifiConfiguration.enterpriseConfig);
+ }
+
+ /**
+ * Validate correctness of WifiNetworkSpecifier object created by
+ * {@link WifiNetworkSpecifier.Builder#build()} for WPA3-Enterprise network
+ * with 192-bit ECC certificates.
+ */
+ @Test
+ public void testWifiNetworkSpecifierBuilderForWpa3EapNetworkWithSuiteBEccCerts() {
+ WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig();
+ enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS);
+ enterpriseConfig.setCaCertificate(FakeKeys.CA_SUITE_B_ECDSA_CERT);
+ enterpriseConfig.setClientKeyEntryWithCertificateChain(FakeKeys.CLIENT_SUITE_B_ECC_KEY,
+ new X509Certificate[] {FakeKeys.CLIENT_SUITE_B_ECDSA_CERT});
+
+ enterpriseConfig.setDomainSuffixMatch(TEST_DOMAIN_SUFFIX_MATCH);
+
+ NetworkSpecifier specifier = new WifiNetworkSpecifier.Builder()
+ .setSsid(TEST_SSID)
+ .setWpa3EnterpriseStandardModeConfig(enterpriseConfig)
+ .build();
+
+ assertTrue(specifier instanceof WifiNetworkSpecifier);
+ WifiNetworkSpecifier wifiNetworkSpecifier = (WifiNetworkSpecifier) specifier;
+
+ assertEquals("\"" + TEST_SSID + "\"", wifiNetworkSpecifier.wifiConfiguration.SSID);
+ assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedKeyManagement
+ .get(WifiConfiguration.KeyMgmt.IEEE8021X));
+ assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedKeyManagement
+ .get(WifiConfiguration.KeyMgmt.WPA_EAP));
+ assertFalse(wifiNetworkSpecifier.wifiConfiguration.allowedKeyManagement
+ .get(WifiConfiguration.KeyMgmt.SUITE_B_192));
+ assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedGroupCiphers
+ .get(WifiConfiguration.GroupCipher.CCMP));
+ assertTrue(wifiNetworkSpecifier.wifiConfiguration.requirePmf);
+ assertNull(wifiNetworkSpecifier.wifiConfiguration.preSharedKey);
+ assertNotNull(wifiNetworkSpecifier.wifiConfiguration.enterpriseConfig);
+ }
+
+ /**
+ * Validate correctness of WifiNetworkSpecifier object created by
+ * {@link WifiNetworkSpecifier.Builder#build()} for WPA3-Enterprise 192-bit RSA SuiteB network.
+ */
+ @Test
+ public void testWifiNetworkSpecifierBuilderForWpa3SuiteBRsaEapNetwork() {
WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig();
enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS);
enterpriseConfig.setCaCertificate(FakeKeys.CA_SUITE_B_RSA3072_CERT);
@@ -208,11 +315,11 @@
}
/**
- * Validate correctness of WifiNetworkSuggestion object created by
- * {@link WifiNetworkSuggestion.Builder#build()} for WPA3-Enterprise 192-bit ECC SuiteB network.
+ * Validate correctness of WifiNetworkSpecifier object created by
+ * {@link WifiNetworkSpecifier.Builder#build()} for WPA3-Enterprise 192-bit ECC SuiteB network.
*/
@Test
- public void testWifiNetworkSuggestionBuilderForWpa3SuiteBEccEapNetwork() {
+ public void testWifiNetworkSpecifierBuilderForWpa3SuiteBEccEapNetwork() {
WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig();
enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS);
enterpriseConfig.setCaCertificate(FakeKeys.CA_SUITE_B_ECDSA_CERT);
@@ -242,6 +349,74 @@
}
/**
+ * Validate correctness of WifiNetworkSpecifier object created by
+ * {@link WifiNetworkSpecifier.Builder#build()} for WPA3-Enterprise 192-bit RSA SuiteB network.
+ */
+ @Test
+ public void testWifiNetworkSpecifierBuilderForWpa3SuiteBRsaEapNetworkWith192BitApi() {
+ WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig();
+ enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS);
+ enterpriseConfig.setCaCertificate(FakeKeys.CA_SUITE_B_RSA3072_CERT);
+ enterpriseConfig.setClientKeyEntryWithCertificateChain(FakeKeys.CLIENT_SUITE_B_RSA3072_KEY,
+ new X509Certificate[] {FakeKeys.CLIENT_SUITE_B_RSA3072_CERT});
+
+ enterpriseConfig.setDomainSuffixMatch(TEST_DOMAIN_SUFFIX_MATCH);
+
+ NetworkSpecifier specifier = new WifiNetworkSpecifier.Builder()
+ .setSsid(TEST_SSID)
+ .setWpa3Enterprise192BitModeConfig(enterpriseConfig)
+ .build();
+
+ assertTrue(specifier instanceof WifiNetworkSpecifier);
+ WifiNetworkSpecifier wifiNetworkSpecifier = (WifiNetworkSpecifier) specifier;
+
+ assertEquals("\"" + TEST_SSID + "\"", wifiNetworkSpecifier.wifiConfiguration.SSID);
+ assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedKeyManagement
+ .get(WifiConfiguration.KeyMgmt.SUITE_B_192));
+ assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedGroupCiphers
+ .get(WifiConfiguration.GroupCipher.GCMP_256));
+ assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedGroupManagementCiphers
+ .get(WifiConfiguration.GroupMgmtCipher.BIP_GMAC_256));
+ assertTrue(wifiNetworkSpecifier.wifiConfiguration.requirePmf);
+ assertNull(wifiNetworkSpecifier.wifiConfiguration.preSharedKey);
+ assertNotNull(wifiNetworkSpecifier.wifiConfiguration.enterpriseConfig);
+ }
+
+ /**
+ * Validate correctness of WifiNetworkSpecifier object created by
+ * {@link WifiNetworkSpecifier.Builder#build()} for WPA3-Enterprise 192-bit ECC SuiteB network.
+ */
+ @Test
+ public void testWifiNetworkSpecifierBuilderForWpa3SuiteBEccEapNetworkWith192BitApi() {
+ WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig();
+ enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS);
+ enterpriseConfig.setCaCertificate(FakeKeys.CA_SUITE_B_ECDSA_CERT);
+ enterpriseConfig.setClientKeyEntryWithCertificateChain(FakeKeys.CLIENT_SUITE_B_ECC_KEY,
+ new X509Certificate[] {FakeKeys.CLIENT_SUITE_B_ECDSA_CERT});
+
+ enterpriseConfig.setDomainSuffixMatch(TEST_DOMAIN_SUFFIX_MATCH);
+
+ NetworkSpecifier specifier = new WifiNetworkSpecifier.Builder()
+ .setSsid(TEST_SSID)
+ .setWpa3Enterprise192BitModeConfig(enterpriseConfig)
+ .build();
+
+ assertTrue(specifier instanceof WifiNetworkSpecifier);
+ WifiNetworkSpecifier wifiNetworkSpecifier = (WifiNetworkSpecifier) specifier;
+
+ assertEquals("\"" + TEST_SSID + "\"", wifiNetworkSpecifier.wifiConfiguration.SSID);
+ assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedKeyManagement
+ .get(WifiConfiguration.KeyMgmt.SUITE_B_192));
+ assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedGroupCiphers
+ .get(WifiConfiguration.GroupCipher.GCMP_256));
+ assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedGroupManagementCiphers
+ .get(WifiConfiguration.GroupMgmtCipher.BIP_GMAC_256));
+ assertTrue(wifiNetworkSpecifier.wifiConfiguration.requirePmf);
+ assertNull(wifiNetworkSpecifier.wifiConfiguration.preSharedKey);
+ assertNotNull(wifiNetworkSpecifier.wifiConfiguration.enterpriseConfig);
+ }
+
+ /**
* Ensure {@link WifiNetworkSpecifier.Builder#setSsid(String)} throws an exception
* when the string is not Unicode.
*/
@@ -430,15 +605,16 @@
/**
* Ensure {@link WifiNetworkSpecifier.Builder#build()} throws an exception
* when both {@link WifiNetworkSpecifier.Builder#setWpa3Passphrase(String)} and
- * {@link WifiNetworkSpecifier.Builder#setWpa3EnterpriseConfig(WifiEnterpriseConfig)} are
- * invoked.
+ * {@link WifiNetworkSpecifier.Builder
+ * #setWpa3EnterpriseStandardModeConfig(WifiEnterpriseConfig)}
+ * are invoked.
*/
@Test(expected = IllegalStateException.class)
public void testWifiNetworkSpecifierBuilderWithBothWpa3PasphraseAndEnterprise() {
new WifiNetworkSpecifier.Builder()
.setSsidPattern(new PatternMatcher(TEST_SSID, PATTERN_LITERAL))
.setWpa3Passphrase(TEST_PRESHARED_KEY)
- .setWpa3EnterpriseConfig(new WifiEnterpriseConfig())
+ .setWpa3EnterpriseStandardModeConfig(new WifiEnterpriseConfig())
.build();
}
diff --git a/framework/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java b/framework/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java
index 00a0442..5e82918 100644
--- a/framework/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java
+++ b/framework/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java
@@ -16,7 +16,13 @@
package android.net.wifi;
-import static org.junit.Assert.*;
+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.junit.Assume.assumeTrue;
import android.net.MacAddress;
import android.net.wifi.hotspot2.PasspointConfiguration;
@@ -25,6 +31,8 @@
import androidx.test.filters.SmallTest;
+import com.android.modules.utils.build.SdkLevel;
+
import org.junit.Test;
import java.security.cert.X509Certificate;
@@ -41,6 +49,8 @@
private static final String TEST_FQDN = "fqdn";
private static final String TEST_WAPI_CERT_SUITE = "suite";
private static final String TEST_DOMAIN_SUFFIX_MATCH = "domainSuffixMatch";
+ private static final int DEFAULT_PRIORITY_GROUP = 0;
+ private static final int TEST_PRIORITY_GROUP = 1;
/**
* Validate correctness of WifiNetworkSuggestion object created by
@@ -64,6 +74,7 @@
assertEquals(-1, suggestion.wifiConfiguration.priority);
assertFalse(suggestion.isUserAllowedToManuallyConnect);
assertTrue(suggestion.isInitialAutoJoinEnabled);
+ assertNull(suggestion.getEnterpriseConfig());
}
/**
@@ -94,6 +105,7 @@
assertEquals(0, suggestion.wifiConfiguration.priority);
assertFalse(suggestion.isUserAllowedToManuallyConnect);
assertTrue(suggestion.isInitialAutoJoinEnabled);
+ assertNull(suggestion.getEnterpriseConfig());
}
/**
@@ -124,6 +136,7 @@
assertEquals(-1, suggestion.wifiConfiguration.priority);
assertTrue(suggestion.isUserAllowedToManuallyConnect);
assertFalse(suggestion.isInitialAutoJoinEnabled);
+ assertNull(suggestion.getEnterpriseConfig());
}
/**
@@ -154,6 +167,7 @@
assertEquals(-1, suggestion.wifiConfiguration.priority);
assertTrue(suggestion.isUserAllowedToManuallyConnect);
assertFalse(suggestion.isInitialAutoJoinEnabled);
+ assertNull(suggestion.getEnterpriseConfig());
}
/**
@@ -176,6 +190,63 @@
assertTrue(suggestion.wifiConfiguration.requirePmf);
assertFalse(suggestion.isUserAllowedToManuallyConnect);
assertTrue(suggestion.isInitialAutoJoinEnabled);
+ assertNull(suggestion.getEnterpriseConfig());
+ }
+
+ /**
+ * Validate correctness of WifiNetworkSuggestion object created by
+ * {@link WifiNetworkSuggestion.Builder#build()} for OWE network.
+ */
+ @Test
+ public void testWifiNetworkSuggestionBuilderForOemPaidEnhancedOpenNetworkWithBssid() {
+ assumeTrue(SdkLevel.isAtLeastS());
+
+ WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion.Builder()
+ .setSsid(TEST_SSID)
+ .setBssid(MacAddress.fromString(TEST_BSSID))
+ .setOemPaid(true)
+ .setIsEnhancedOpen(true)
+ .build();
+
+ assertEquals("\"" + TEST_SSID + "\"", suggestion.wifiConfiguration.SSID);
+ assertEquals(TEST_BSSID, suggestion.wifiConfiguration.BSSID);
+ assertTrue(suggestion.wifiConfiguration.allowedKeyManagement
+ .get(WifiConfiguration.KeyMgmt.OWE));
+ assertNull(suggestion.wifiConfiguration.preSharedKey);
+ assertTrue(suggestion.wifiConfiguration.requirePmf);
+ assertTrue(suggestion.wifiConfiguration.oemPaid);
+ assertTrue(suggestion.isOemPaid());
+ assertFalse(suggestion.isUserAllowedToManuallyConnect);
+ assertTrue(suggestion.isInitialAutoJoinEnabled);
+ assertNull(suggestion.getEnterpriseConfig());
+ }
+
+ /**
+ * Validate correctness of WifiNetworkSuggestion object created by
+ * {@link WifiNetworkSuggestion.Builder#build()} for OWE network.
+ */
+ @Test
+ public void testWifiNetworkSuggestionBuilderForOemPrivateEnhancedOpenNetworkWithBssid() {
+ assumeTrue(SdkLevel.isAtLeastS());
+
+ WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion.Builder()
+ .setSsid(TEST_SSID)
+ .setBssid(MacAddress.fromString(TEST_BSSID))
+ .setOemPrivate(true)
+ .setIsEnhancedOpen(true)
+ .build();
+
+ assertEquals("\"" + TEST_SSID + "\"", suggestion.wifiConfiguration.SSID);
+ assertEquals(TEST_BSSID, suggestion.wifiConfiguration.BSSID);
+ assertTrue(suggestion.wifiConfiguration.allowedKeyManagement
+ .get(WifiConfiguration.KeyMgmt.OWE));
+ assertNull(suggestion.wifiConfiguration.preSharedKey);
+ assertTrue(suggestion.wifiConfiguration.requirePmf);
+ assertTrue(suggestion.wifiConfiguration.oemPrivate);
+ assertTrue(suggestion.isOemPrivate());
+ assertFalse(suggestion.isUserAllowedToManuallyConnect);
+ assertTrue(suggestion.isInitialAutoJoinEnabled);
+ assertNull(suggestion.getEnterpriseConfig());
}
/**
@@ -199,6 +270,7 @@
assertTrue(suggestion.wifiConfiguration.requirePmf);
assertTrue(suggestion.isUserAllowedToManuallyConnect);
assertFalse(suggestion.isInitialAutoJoinEnabled);
+ assertNull(suggestion.getEnterpriseConfig());
}
/**
@@ -237,6 +309,116 @@
/**
* Validate correctness of WifiNetworkSuggestion object created by
+ * {@link WifiNetworkSuggestion.Builder#build()} for WPA3-Enterprise standard network.
+ */
+ @Test
+ public void testWifiNetworkSuggestionBuilderForWpa3EapNetworkWithStandardApi() {
+ WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig();
+ enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS);
+ enterpriseConfig.setCaCertificate(FakeKeys.CA_CERT0);
+ enterpriseConfig.setDomainSuffixMatch(TEST_DOMAIN_SUFFIX_MATCH);
+
+ WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion.Builder()
+ .setSsid(TEST_SSID)
+ .setWpa3EnterpriseStandardModeConfig(enterpriseConfig)
+ .build();
+
+ assertEquals("\"" + TEST_SSID + "\"", suggestion.wifiConfiguration.SSID);
+ assertTrue(suggestion.wifiConfiguration.allowedKeyManagement
+ .get(WifiConfiguration.KeyMgmt.IEEE8021X));
+ assertTrue(suggestion.wifiConfiguration.allowedKeyManagement
+ .get(WifiConfiguration.KeyMgmt.WPA_EAP));
+ assertFalse(suggestion.wifiConfiguration.allowedKeyManagement
+ .get(WifiConfiguration.KeyMgmt.SUITE_B_192));
+ assertTrue(suggestion.wifiConfiguration.allowedGroupCiphers
+ .get(WifiConfiguration.GroupCipher.CCMP));
+ assertTrue(suggestion.wifiConfiguration.requirePmf);
+ assertNull(suggestion.wifiConfiguration.preSharedKey);
+ // allowedSuiteBCiphers are set according to the loaded certificate and cannot be tested
+ // here.
+ assertTrue(suggestion.isUserAllowedToManuallyConnect);
+ assertTrue(suggestion.isInitialAutoJoinEnabled);
+ assertNotNull(suggestion.getEnterpriseConfig());
+ }
+
+ /**
+ * Validate correctness of WifiNetworkSuggestion object created by
+ * {@link WifiNetworkSuggestion.Builder#build()} for WPA3-Enterprise network
+ * with 192-bit RSA SuiteB certificates.
+ */
+ @Test
+ public void testWifiNetworkSuggestionBuilderForWpa3EapNetworkWithSuiteBRsaCerts() {
+ WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig();
+ enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS);
+ enterpriseConfig.setCaCertificate(FakeKeys.CA_SUITE_B_RSA3072_CERT);
+ enterpriseConfig.setClientKeyEntryWithCertificateChain(FakeKeys.CLIENT_SUITE_B_RSA3072_KEY,
+ new X509Certificate[] {FakeKeys.CLIENT_SUITE_B_RSA3072_CERT});
+
+ enterpriseConfig.setDomainSuffixMatch(TEST_DOMAIN_SUFFIX_MATCH);
+
+ WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion.Builder()
+ .setSsid(TEST_SSID)
+ .setWpa3EnterpriseStandardModeConfig(enterpriseConfig)
+ .build();
+
+ assertEquals("\"" + TEST_SSID + "\"", suggestion.wifiConfiguration.SSID);
+ assertTrue(suggestion.wifiConfiguration.allowedKeyManagement
+ .get(WifiConfiguration.KeyMgmt.IEEE8021X));
+ assertTrue(suggestion.wifiConfiguration.allowedKeyManagement
+ .get(WifiConfiguration.KeyMgmt.WPA_EAP));
+ assertFalse(suggestion.wifiConfiguration.allowedKeyManagement
+ .get(WifiConfiguration.KeyMgmt.SUITE_B_192));
+ assertTrue(suggestion.wifiConfiguration.allowedGroupCiphers
+ .get(WifiConfiguration.GroupCipher.CCMP));
+ assertTrue(suggestion.wifiConfiguration.requirePmf);
+ assertNull(suggestion.wifiConfiguration.preSharedKey);
+ // allowedSuiteBCiphers are set according to the loaded certificate and cannot be tested
+ // here.
+ assertTrue(suggestion.isUserAllowedToManuallyConnect);
+ assertTrue(suggestion.isInitialAutoJoinEnabled);
+ assertNotNull(suggestion.getEnterpriseConfig());
+ }
+
+ /**
+ * Validate correctness of WifiNetworkSuggestion object created by
+ * {@link WifiNetworkSuggestion.Builder#build()} for WPA3-Enterprise network
+ * with 192-bit ECC certificates.
+ */
+ @Test
+ public void testWifiNetworkSuggestionBuilderForWpa3EapNetworkWithSuiteBEccCerts() {
+ WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig();
+ enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS);
+ enterpriseConfig.setCaCertificate(FakeKeys.CA_SUITE_B_ECDSA_CERT);
+ enterpriseConfig.setClientKeyEntryWithCertificateChain(FakeKeys.CLIENT_SUITE_B_ECC_KEY,
+ new X509Certificate[] {FakeKeys.CLIENT_SUITE_B_ECDSA_CERT});
+
+ enterpriseConfig.setDomainSuffixMatch(TEST_DOMAIN_SUFFIX_MATCH);
+
+ WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion.Builder()
+ .setSsid(TEST_SSID)
+ .setWpa3EnterpriseStandardModeConfig(enterpriseConfig)
+ .build();
+
+ assertEquals("\"" + TEST_SSID + "\"", suggestion.wifiConfiguration.SSID);
+ assertTrue(suggestion.wifiConfiguration.allowedKeyManagement
+ .get(WifiConfiguration.KeyMgmt.IEEE8021X));
+ assertTrue(suggestion.wifiConfiguration.allowedKeyManagement
+ .get(WifiConfiguration.KeyMgmt.WPA_EAP));
+ assertFalse(suggestion.wifiConfiguration.allowedKeyManagement
+ .get(WifiConfiguration.KeyMgmt.SUITE_B_192));
+ assertTrue(suggestion.wifiConfiguration.allowedGroupCiphers
+ .get(WifiConfiguration.GroupCipher.CCMP));
+ assertTrue(suggestion.wifiConfiguration.requirePmf);
+ assertNull(suggestion.wifiConfiguration.preSharedKey);
+ // allowedSuiteBCiphers are set according to the loaded certificate and cannot be tested
+ // here.
+ assertTrue(suggestion.isUserAllowedToManuallyConnect);
+ assertTrue(suggestion.isInitialAutoJoinEnabled);
+ assertNotNull(suggestion.getEnterpriseConfig());
+ }
+
+ /**
+ * Validate correctness of WifiNetworkSuggestion object created by
* {@link WifiNetworkSuggestion.Builder#build()} for WPA3-Enterprise 192-bit RSA SuiteB network.
*/
@Test
@@ -272,6 +454,41 @@
/**
* Validate correctness of WifiNetworkSuggestion object created by
+ * {@link WifiNetworkSuggestion.Builder#build()} for WPA3-Enterprise 192-bit RSA SuiteB network.
+ */
+ @Test
+ public void testWifiNetworkSuggestionBuilderForWpa3SuiteBRsaEapNetworWith192BitApi() {
+ WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig();
+ enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS);
+ enterpriseConfig.setCaCertificate(FakeKeys.CA_SUITE_B_RSA3072_CERT);
+ enterpriseConfig.setClientKeyEntryWithCertificateChain(FakeKeys.CLIENT_SUITE_B_RSA3072_KEY,
+ new X509Certificate[] {FakeKeys.CLIENT_SUITE_B_RSA3072_CERT});
+
+ enterpriseConfig.setDomainSuffixMatch(TEST_DOMAIN_SUFFIX_MATCH);
+
+ WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion.Builder()
+ .setSsid(TEST_SSID)
+ .setWpa3Enterprise192BitModeConfig(enterpriseConfig)
+ .build();
+
+ assertEquals("\"" + TEST_SSID + "\"", suggestion.wifiConfiguration.SSID);
+ assertTrue(suggestion.wifiConfiguration.allowedKeyManagement
+ .get(WifiConfiguration.KeyMgmt.SUITE_B_192));
+ assertTrue(suggestion.wifiConfiguration.allowedGroupCiphers
+ .get(WifiConfiguration.GroupCipher.GCMP_256));
+ assertTrue(suggestion.wifiConfiguration.allowedGroupManagementCiphers
+ .get(WifiConfiguration.GroupMgmtCipher.BIP_GMAC_256));
+ assertTrue(suggestion.wifiConfiguration.requirePmf);
+ assertNull(suggestion.wifiConfiguration.preSharedKey);
+ // allowedSuiteBCiphers are set according to the loaded certificate and cannot be tested
+ // here.
+ assertTrue(suggestion.isUserAllowedToManuallyConnect);
+ assertTrue(suggestion.isInitialAutoJoinEnabled);
+ assertNotNull(suggestion.getEnterpriseConfig());
+ }
+
+ /**
+ * Validate correctness of WifiNetworkSuggestion object created by
* {@link WifiNetworkSuggestion.Builder#build()} for WPA3-Enterprise 192-bit ECC SuiteB network.
*/
@Test
@@ -302,6 +519,42 @@
// here.
assertTrue(suggestion.isUserAllowedToManuallyConnect);
assertTrue(suggestion.isInitialAutoJoinEnabled);
+ assertNotNull(suggestion.getEnterpriseConfig());
+ }
+
+ /**
+ * Validate correctness of WifiNetworkSuggestion object created by
+ * {@link WifiNetworkSuggestion.Builder#build()} for WPA3-Enterprise 192-bit ECC SuiteB network.
+ */
+ @Test
+ public void testWifiNetworkSuggestionBuilderForWpa3SuiteBEccEapNetworkWith192BitApi() {
+ WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig();
+ enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS);
+ enterpriseConfig.setCaCertificate(FakeKeys.CA_SUITE_B_ECDSA_CERT);
+ enterpriseConfig.setClientKeyEntryWithCertificateChain(FakeKeys.CLIENT_SUITE_B_ECC_KEY,
+ new X509Certificate[] {FakeKeys.CLIENT_SUITE_B_ECDSA_CERT});
+
+ enterpriseConfig.setDomainSuffixMatch(TEST_DOMAIN_SUFFIX_MATCH);
+
+ WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion.Builder()
+ .setSsid(TEST_SSID)
+ .setWpa3Enterprise192BitModeConfig(enterpriseConfig)
+ .build();
+
+ assertEquals("\"" + TEST_SSID + "\"", suggestion.wifiConfiguration.SSID);
+ assertTrue(suggestion.wifiConfiguration.allowedKeyManagement
+ .get(WifiConfiguration.KeyMgmt.SUITE_B_192));
+ assertTrue(suggestion.wifiConfiguration.allowedGroupCiphers
+ .get(WifiConfiguration.GroupCipher.GCMP_256));
+ assertTrue(suggestion.wifiConfiguration.allowedGroupManagementCiphers
+ .get(WifiConfiguration.GroupMgmtCipher.BIP_GMAC_256));
+ assertTrue(suggestion.wifiConfiguration.requirePmf);
+ assertNull(suggestion.wifiConfiguration.preSharedKey);
+ // allowedSuiteBCiphers are set according to the loaded certificate and cannot be tested
+ // here.
+ assertTrue(suggestion.isUserAllowedToManuallyConnect);
+ assertTrue(suggestion.isInitialAutoJoinEnabled);
+ assertNotNull(suggestion.getEnterpriseConfig());
}
/**
@@ -334,7 +587,7 @@
WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion.Builder()
.setSsid(TEST_SSID)
- .setWpa3EnterpriseConfig(enterpriseConfig)
+ .setWpa3EnterpriseStandardModeConfig(enterpriseConfig)
.build();
}
@@ -358,6 +611,7 @@
.get(WifiConfiguration.GroupCipher.SMS4));
assertEquals("\"" + TEST_PRESHARED_KEY + "\"",
suggestion.wifiConfiguration.preSharedKey);
+ assertNull(suggestion.getEnterpriseConfig());
}
@@ -388,6 +642,7 @@
suggestion.wifiConfiguration.enterpriseConfig.getEapMethod());
assertEquals(TEST_WAPI_CERT_SUITE,
suggestion.wifiConfiguration.enterpriseConfig.getWapiCertSuite());
+ assertNotNull(suggestion.getEnterpriseConfig());
}
/**
@@ -417,6 +672,7 @@
suggestion.wifiConfiguration.enterpriseConfig.getEapMethod());
assertEquals("",
suggestion.wifiConfiguration.enterpriseConfig.getWapiCertSuite());
+ assertNotNull(suggestion.getEnterpriseConfig());
}
/**
@@ -439,6 +695,7 @@
assertEquals(suggestion.getPasspointConfig().getMeteredOverride(),
WifiConfiguration.METERED_OVERRIDE_METERED);
assertTrue(suggestion.isUserAllowedToManuallyConnect);
+ assertNull(suggestion.getEnterpriseConfig());
}
/**
@@ -552,15 +809,16 @@
/**
* Ensure {@link WifiNetworkSuggestion.Builder#build()} throws an exception
* when both {@link WifiNetworkSuggestion.Builder#setWpa3Passphrase(String)} and
- * {@link WifiNetworkSuggestion.Builder#setWpa3EnterpriseConfig(WifiEnterpriseConfig)} are
- * invoked.
+ * {@link WifiNetworkSuggestion.Builder
+ * #setWpa3EnterpriseStandardModeConfig(WifiEnterpriseConfig)}
+ * are invoked.
*/
@Test(expected = IllegalStateException.class)
public void testWifiNetworkSuggestionBuilderWithBothWpa3PasphraseAndEnterprise() {
new WifiNetworkSuggestion.Builder()
.setSsid(TEST_SSID)
.setWpa3Passphrase(TEST_PRESHARED_KEY)
- .setWpa3EnterpriseConfig(new WifiEnterpriseConfig())
+ .setWpa3EnterpriseStandardModeConfig(new WifiEnterpriseConfig())
.build();
}
@@ -622,7 +880,9 @@
/**
* Ensure {@link WifiNetworkSuggestion.Builder#build()} throws an exception
- * when both {@link WifiNetworkSuggestion.Builder#setWpa3EnterpriseConfig(WifiEnterpriseConfig)}
+ * when both
+ * {@link WifiNetworkSuggestion.Builder
+ * #setWpa3EnterpriseStandardModeConfig(WifiEnterpriseConfig)}
* and {@link WifiNetworkSuggestion.Builder#setPasspointConfig(PasspointConfiguration)} are
* invoked.
*/
@@ -630,7 +890,7 @@
public void testWifiNetworkSuggestionBuilderWithBothEnterpriseAndPasspointConfig() {
PasspointConfiguration passpointConfiguration = PasspointTestUtils.createConfig();
new WifiNetworkSuggestion.Builder()
- .setWpa3EnterpriseConfig(new WifiEnterpriseConfig())
+ .setWpa3EnterpriseStandardModeConfig(new WifiEnterpriseConfig())
.setPasspointConfig(passpointConfiguration)
.build();
}
@@ -664,6 +924,84 @@
}
/**
+ * Verify that the macRandomizationSetting defaults to RANDOMIZATION_PERSISTENT and could be set
+ * to RANDOMIZATION_ENHANCED.
+ */
+ @Test
+ public void testWifiNetworkSuggestionBuilderSetMacRandomization() {
+ WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion.Builder()
+ .setSsid(TEST_SSID)
+ .build();
+ assertEquals(WifiConfiguration.RANDOMIZATION_PERSISTENT,
+ suggestion.wifiConfiguration.macRandomizationSetting);
+
+ suggestion = new WifiNetworkSuggestion.Builder()
+ .setSsid(TEST_SSID)
+ .setIsEnhancedMacRandomizationEnabled(false)
+ .build();
+ assertEquals(WifiConfiguration.RANDOMIZATION_PERSISTENT,
+ suggestion.wifiConfiguration.macRandomizationSetting);
+
+ suggestion = new WifiNetworkSuggestion.Builder()
+ .setSsid(TEST_SSID)
+ .setIsEnhancedMacRandomizationEnabled(true)
+ .build();
+ assertEquals(WifiConfiguration.RANDOMIZATION_ENHANCED,
+ suggestion.wifiConfiguration.macRandomizationSetting);
+ }
+
+ /**
+ * Verify that the builder creates the appropriate PasspointConfiguration according to the
+ * enhanced MAC randomization setting.
+ */
+ @Test
+ public void testWifiNetworkSuggestionBuilderSetMacRandomizationPasspoint() {
+ PasspointConfiguration passpointConfiguration = PasspointTestUtils.createConfig();
+ WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion.Builder()
+ .setPasspointConfig(passpointConfiguration)
+ .build();
+ assertEquals(false, suggestion.passpointConfiguration.isEnhancedMacRandomizationEnabled());
+
+ suggestion = new WifiNetworkSuggestion.Builder()
+ .setPasspointConfig(passpointConfiguration)
+ .setIsEnhancedMacRandomizationEnabled(false)
+ .build();
+ assertEquals(false, suggestion.passpointConfiguration.isEnhancedMacRandomizationEnabled());
+
+ suggestion = new WifiNetworkSuggestion.Builder()
+ .setPasspointConfig(passpointConfiguration)
+ .setIsEnhancedMacRandomizationEnabled(true)
+ .build();
+ assertEquals(true, suggestion.passpointConfiguration.isEnhancedMacRandomizationEnabled());
+ }
+
+ /**
+ * Verify that the builder creates the appropriate SIM credential suggestion with SubId, also
+ * verify {@link WifiNetworkSuggestion#equals(Object)} consider suggestion with different SubId
+ * as different suggestions.
+ */
+ @Test
+ public void testSimCredentialNetworkWithSubId() {
+ assumeTrue(SdkLevel.isAtLeastS());
+ WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig();
+ enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.SIM);
+ enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.NONE);
+ WifiNetworkSuggestion suggestion1 = new WifiNetworkSuggestion.Builder()
+ .setSsid(TEST_SSID)
+ .setWpa2EnterpriseConfig(enterpriseConfig)
+ .setSubscriptionId(1)
+ .build();
+ assertEquals(1, suggestion1.getSubscriptionId());
+ WifiNetworkSuggestion suggestion2 = new WifiNetworkSuggestion.Builder()
+ .setSsid(TEST_SSID)
+ .setWpa2EnterpriseConfig(enterpriseConfig)
+ .setSubscriptionId(2)
+ .build();
+ assertEquals(2, suggestion2.getSubscriptionId());
+ assertNotEquals(suggestion1, suggestion2);
+ }
+
+ /**
* Check that parcel marshalling/unmarshalling works
*/
@Test
@@ -673,7 +1011,7 @@
configuration.BSSID = TEST_BSSID;
configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion(
- configuration, null, false, true, true, true);
+ configuration, null, false, true, true, true, TEST_PRIORITY_GROUP);
Parcel parcelW = Parcel.obtain();
suggestion.writeToParcel(parcelW, 0);
@@ -744,14 +1082,16 @@
configuration.BSSID = TEST_BSSID;
configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
WifiNetworkSuggestion suggestion =
- new WifiNetworkSuggestion(configuration, null, true, false, true, true);
+ new WifiNetworkSuggestion(configuration, null, true, false, true, true,
+ TEST_PRIORITY_GROUP);
WifiConfiguration configuration1 = new WifiConfiguration();
configuration1.SSID = TEST_SSID;
configuration1.BSSID = TEST_BSSID;
configuration1.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
WifiNetworkSuggestion suggestion1 =
- new WifiNetworkSuggestion(configuration1, null, false, true, true, true);
+ new WifiNetworkSuggestion(configuration1, null, false, true, true, true,
+ DEFAULT_PRIORITY_GROUP);
assertEquals(suggestion, suggestion1);
assertEquals(suggestion.hashCode(), suggestion1.hashCode());
@@ -767,13 +1107,15 @@
configuration.SSID = TEST_SSID;
configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
WifiNetworkSuggestion suggestion =
- new WifiNetworkSuggestion(configuration, null, false, false, true, true);
+ new WifiNetworkSuggestion(configuration, null, false, false, true, true,
+ DEFAULT_PRIORITY_GROUP);
WifiConfiguration configuration1 = new WifiConfiguration();
configuration1.SSID = TEST_SSID_1;
configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
WifiNetworkSuggestion suggestion1 =
- new WifiNetworkSuggestion(configuration1, null, false, false, true, true);
+ new WifiNetworkSuggestion(configuration1, null, false, false, true, true,
+ DEFAULT_PRIORITY_GROUP);
assertNotEquals(suggestion, suggestion1);
}
@@ -789,13 +1131,15 @@
configuration.BSSID = TEST_BSSID;
configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
WifiNetworkSuggestion suggestion =
- new WifiNetworkSuggestion(configuration, null, false, false, true, true);
+ new WifiNetworkSuggestion(configuration, null, false, false, true, true,
+ DEFAULT_PRIORITY_GROUP);
WifiConfiguration configuration1 = new WifiConfiguration();
configuration1.SSID = TEST_SSID;
configuration1.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
WifiNetworkSuggestion suggestion1 =
- new WifiNetworkSuggestion(configuration1, null, false, false, true, true);
+ new WifiNetworkSuggestion(configuration1, null, false, false, true, true,
+ DEFAULT_PRIORITY_GROUP);
assertNotEquals(suggestion, suggestion1);
}
@@ -810,13 +1154,15 @@
configuration.SSID = TEST_SSID;
configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
WifiNetworkSuggestion suggestion =
- new WifiNetworkSuggestion(configuration, null, false, false, true, true);
+ new WifiNetworkSuggestion(configuration, null, false, false, true, true,
+ DEFAULT_PRIORITY_GROUP);
WifiConfiguration configuration1 = new WifiConfiguration();
configuration1.SSID = TEST_SSID;
configuration1.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
WifiNetworkSuggestion suggestion1 =
- new WifiNetworkSuggestion(configuration1, null, false, false, true, true);
+ new WifiNetworkSuggestion(configuration1, null, false, false, true, true,
+ DEFAULT_PRIORITY_GROUP);
assertNotEquals(suggestion, suggestion1);
}
@@ -932,6 +1278,78 @@
}
/**
+ * Validate {@link WifiNetworkSuggestion.Builder#setCredentialSharedWithUser(boolean)} set the
+ * correct value to the WifiConfiguration.
+ */
+ @Test
+ public void testSetIsNetworkAsOemPaid() {
+ assumeTrue(SdkLevel.isAtLeastS());
+
+ WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion.Builder()
+ .setSsid(TEST_SSID)
+ .setWpa2Passphrase(TEST_PRESHARED_KEY)
+ .setOemPaid(true)
+ .build();
+ assertTrue(suggestion.isOemPaid());
+ assertFalse(suggestion.isUserAllowedToManuallyConnect);
+ }
+
+ /**
+ * Validate {@link WifiNetworkSuggestion.Builder#setCredentialSharedWithUser(boolean)} set the
+ * correct value to the WifiConfiguration.
+ * Also the {@link WifiNetworkSuggestion#isUserAllowedToManuallyConnect} should be false;
+ */
+ @Test
+ public void testSetIsNetworkAsOemPaidOnPasspointNetwork() {
+ assumeTrue(SdkLevel.isAtLeastS());
+
+ PasspointConfiguration passpointConfiguration = PasspointTestUtils.createConfig();
+ WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion.Builder()
+ .setPasspointConfig(passpointConfiguration)
+ .setOemPaid(true)
+ .build();
+ assertTrue(suggestion.isOemPaid());
+ assertFalse(suggestion.isUserAllowedToManuallyConnect);
+ assertTrue(suggestion.getPasspointConfig().isOemPaid());
+ }
+
+ /**
+ * Validate {@link WifiNetworkSuggestion.Builder#setCredentialSharedWithUser(boolean)} set the
+ * correct value to the WifiConfiguration.
+ */
+ @Test
+ public void testSetIsNetworkAsOemPrivate() {
+ assumeTrue(SdkLevel.isAtLeastS());
+
+ WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion.Builder()
+ .setSsid(TEST_SSID)
+ .setWpa2Passphrase(TEST_PRESHARED_KEY)
+ .setOemPrivate(true)
+ .build();
+ assertTrue(suggestion.isOemPrivate());
+ assertFalse(suggestion.isUserAllowedToManuallyConnect);
+ }
+
+ /**
+ * Validate {@link WifiNetworkSuggestion.Builder#setCredentialSharedWithUser(boolean)} set the
+ * correct value to the WifiConfiguration.
+ * Also the {@link WifiNetworkSuggestion#isUserAllowedToManuallyConnect} should be false;
+ */
+ @Test
+ public void testSetIsNetworkAsOemPrivateOnPasspointNetwork() {
+ assumeTrue(SdkLevel.isAtLeastS());
+
+ PasspointConfiguration passpointConfiguration = PasspointTestUtils.createConfig();
+ WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion.Builder()
+ .setPasspointConfig(passpointConfiguration)
+ .setOemPrivate(true)
+ .build();
+ assertTrue(suggestion.isOemPrivate());
+ assertFalse(suggestion.isUserAllowedToManuallyConnect);
+ assertTrue(suggestion.getPasspointConfig().isOemPrivate());
+ }
+
+ /**
* Ensure {@link WifiNetworkSuggestion.Builder#build()} throws an exception
* when set {@link WifiNetworkSuggestion.Builder#setUntrusted(boolean)} to true and
* set {@link WifiNetworkSuggestion.Builder#setCredentialSharedWithUser(boolean)} to true
@@ -949,6 +1367,42 @@
/**
* Ensure {@link WifiNetworkSuggestion.Builder#build()} throws an exception
+ * when set {@link WifiNetworkSuggestion.Builder#setOemPaid(boolean)} to true and
+ * set {@link WifiNetworkSuggestion.Builder#setCredentialSharedWithUser(boolean)} to true
+ * together.
+ */
+ @Test(expected = IllegalStateException.class)
+ public void testSetCredentialSharedWithUserWithSetIsNetworkAsOemPaid() {
+ assumeTrue(SdkLevel.isAtLeastS());
+
+ new WifiNetworkSuggestion.Builder()
+ .setSsid(TEST_SSID)
+ .setWpa2Passphrase(TEST_PRESHARED_KEY)
+ .setCredentialSharedWithUser(true)
+ .setOemPaid(true)
+ .build();
+ }
+
+ /**
+ * Ensure {@link WifiNetworkSuggestion.Builder#build()} throws an exception
+ * when set {@link WifiNetworkSuggestion.Builder#setOemPrivate(boolean)} to true and
+ * set {@link WifiNetworkSuggestion.Builder#setCredentialSharedWithUser(boolean)} to true
+ * together.
+ */
+ @Test(expected = IllegalStateException.class)
+ public void testSetCredentialSharedWithUserWithSetIsNetworkAsOemPrivate() {
+ assumeTrue(SdkLevel.isAtLeastS());
+
+ new WifiNetworkSuggestion.Builder()
+ .setSsid(TEST_SSID)
+ .setWpa2Passphrase(TEST_PRESHARED_KEY)
+ .setCredentialSharedWithUser(true)
+ .setOemPrivate(true)
+ .build();
+ }
+
+ /**
+ * Ensure {@link WifiNetworkSuggestion.Builder#build()} throws an exception
* when set both {@link WifiNetworkSuggestion.Builder#setIsInitialAutojoinEnabled(boolean)}
* and {@link WifiNetworkSuggestion.Builder#setCredentialSharedWithUser(boolean)} (boolean)}
* to false on a passpoint suggestion.
@@ -962,4 +1416,109 @@
.setIsInitialAutojoinEnabled(false)
.build();
}
+
+ /**
+ * Validate {@link WifiNetworkSuggestion.Builder#setCarrierMerged(boolean)} (boolean)} set the
+ * correct value to the WifiConfiguration.
+ */
+ @Test
+ public void testSetCarrierMergedNetwork() {
+ assumeTrue(SdkLevel.isAtLeastS());
+
+ WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig();
+ enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS);
+ enterpriseConfig.setCaCertificate(FakeKeys.CA_CERT0);
+ enterpriseConfig.setDomainSuffixMatch(TEST_DOMAIN_SUFFIX_MATCH);
+ WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion.Builder()
+ .setSsid(TEST_SSID)
+ .setSubscriptionId(1)
+ .setWpa2EnterpriseConfig(enterpriseConfig)
+ .setCarrierMerged(true)
+ .setIsMetered(true)
+ .build();
+ assertTrue(suggestion.isCarrierMerged());
+ assertTrue(suggestion.wifiConfiguration.carrierMerged);
+ }
+
+ /**
+ * Validate {@link WifiNetworkSuggestion.Builder#setCarrierMerged(boolean)} (boolean)} set the
+ * correct value to the passpoint network.
+ */
+ @Test
+ public void testSetCarrierMergedNetworkOnPasspointNetwork() {
+ assumeTrue(SdkLevel.isAtLeastS());
+
+ PasspointConfiguration passpointConfiguration = PasspointTestUtils.createConfig();
+ WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion.Builder()
+ .setPasspointConfig(passpointConfiguration)
+ .setSubscriptionId(1)
+ .setCarrierMerged(true)
+ .setIsMetered(true)
+ .build();
+ assertTrue(suggestion.isCarrierMerged());
+ assertTrue(suggestion.getPasspointConfig().isCarrierMerged());
+ }
+
+ /**
+ * Ensure {@link WifiNetworkSuggestion.Builder#build()} throws an exception
+ * when set both {@link WifiNetworkSuggestion.Builder#setCarrierMerged(boolean)} (boolean)}
+ * to true on a network is not metered.
+ */
+ @Test(expected = IllegalStateException.class)
+ public void testSetCarrierMergedNetworkOnUnmeteredNetworkFail() {
+ assumeTrue(SdkLevel.isAtLeastS());
+
+ WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig();
+ enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS);
+ enterpriseConfig.setCaCertificate(FakeKeys.CA_CERT0);
+ enterpriseConfig.setDomainSuffixMatch(TEST_DOMAIN_SUFFIX_MATCH);
+ new WifiNetworkSuggestion.Builder()
+ .setSsid(TEST_SSID)
+ .setSubscriptionId(1)
+ .setWpa2EnterpriseConfig(enterpriseConfig)
+ .setCarrierMerged(true)
+ .build();
+ }
+
+ /**
+ * Ensure {@link WifiNetworkSuggestion.Builder#build()} throws an exception
+ * when set both {@link WifiNetworkSuggestion.Builder#setCarrierMerged(boolean)} (boolean)}
+ * to true on a network which {@link WifiNetworkSuggestion.Builder#setSubscriptionId(int)}
+ * is not set with a valid sub id.
+ */
+ @Test(expected = IllegalStateException.class)
+ public void testSetCarrierMergedNetworkWithoutValidSubscriptionIdFail() {
+ assumeTrue(SdkLevel.isAtLeastS());
+
+ WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig();
+ enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS);
+ enterpriseConfig.setCaCertificate(FakeKeys.CA_CERT0);
+ enterpriseConfig.setDomainSuffixMatch(TEST_DOMAIN_SUFFIX_MATCH);
+ WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion.Builder()
+ .setSsid(TEST_SSID)
+ .setWpa2EnterpriseConfig(enterpriseConfig)
+ .setCarrierMerged(true)
+ .setIsMetered(true)
+ .build();
+ assertTrue(suggestion.isCarrierMerged());
+ }
+
+ /**
+ * Ensure {@link WifiNetworkSuggestion.Builder#build()} throws an exception
+ * when set both {@link WifiNetworkSuggestion.Builder#setCarrierMerged(boolean)} (boolean)}
+ * to true on a non enterprise network.
+ */
+ @Test(expected = IllegalStateException.class)
+ public void testSetCarrierMergedNetworkWithNonEnterpriseNetworkFail() {
+ assumeTrue(SdkLevel.isAtLeastS());
+
+ WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion.Builder()
+ .setSsid(TEST_SSID)
+ .setSubscriptionId(1)
+ .setWpa2Passphrase(TEST_PRESHARED_KEY)
+ .setCarrierMerged(true)
+ .setIsMetered(true)
+ .build();
+ assertTrue(suggestion.isCarrierMerged());
+ }
}
diff --git a/framework/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java b/framework/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java
index 43d728b..1ecd325 100644
--- a/framework/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java
+++ b/framework/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java
@@ -16,11 +16,13 @@
package android.net.wifi.aware;
+import static android.net.wifi.aware.WifiAwareManager.WIFI_AWARE_DISCOVERY_LOST_REASON_PEER_NOT_VISIBLE;
import static android.net.wifi.aware.WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_IB;
import static org.hamcrest.core.IsEqual.equalTo;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
@@ -45,6 +47,8 @@
import androidx.test.filters.SmallTest;
+import com.android.modules.utils.build.SdkLevel;
+
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -146,6 +150,39 @@
verify(mockAwareService).getCharacteristics();
}
+ /**
+ * Validate pass-through of isDeviceAttached() API.
+ */
+ @Test
+ public void testIsAttached() throws Exception {
+ assumeTrue(SdkLevel.isAtLeastS());
+ mDut.isDeviceAttached();
+ verify(mockAwareService).isDeviceAttached();
+ }
+
+ /**
+ * Validate pass-through of isInstantCommunicationModeEnabled() and
+ * enableInstantCommunicationMode() API
+ */
+ @Test
+ public void testEnableInstantCommunicationMode() throws Exception {
+ assumeTrue(SdkLevel.isAtLeastS());
+ mDut.isInstantCommunicationModeEnabled();
+ verify(mockAwareService).isInstantCommunicationModeEnabled();
+ mDut.enableInstantCommunicationMode(true);
+ verify(mockAwareService).enableInstantCommunicationMode(anyString(), eq(true));
+ }
+
+ /**
+ * Validate pass-through of getAvailableAwareResources() API.
+ */
+ @Test
+ public void testGetAvailableAwareResource() throws Exception {
+ assumeTrue(SdkLevel.isAtLeastS());
+ mDut.getAvailableAwareResources();
+ verify(mockAwareService).getAvailableAwareResources();
+ }
+
/*
* WifiAwareEventCallbackProxy Tests
*/
@@ -360,12 +397,19 @@
eq(publishConfig));
inOrder.verify(mockSessionCallback).onSessionConfigFailed();
- // (5) terminate
+ // (5) discovery session is no longer visible
+ sessionProxyCallback.getValue().onMatchExpired(peerHandle.peerId);
+ mMockLooper.dispatchAll();
+ inOrder.verify(mockSessionCallback).onServiceLost(peerIdCaptor.capture(),
+ eq(WIFI_AWARE_DISCOVERY_LOST_REASON_PEER_NOT_VISIBLE));
+ assertEquals(peerHandle.peerId, peerIdCaptor.getValue().peerId);
+
+ // (6) terminate
publishSession.getValue().close();
mMockLooper.dispatchAll();
inOrder.verify(mockAwareService).terminateSession(clientId, sessionId);
- // (6) try an update (nothing)
+ // (7) try an update (nothing)
publishSession.getValue().updatePublish(publishConfig);
mMockLooper.dispatchAll();
@@ -502,12 +546,19 @@
eq(subscribeConfig));
inOrder.verify(mockSessionCallback).onSessionConfigFailed();
- // (5) terminate
+ // (5) discovery session is no longer visible
+ sessionProxyCallback.getValue().onMatchExpired(peerHandle.peerId);
+ mMockLooper.dispatchAll();
+ inOrder.verify(mockSessionCallback).onServiceLost(peerIdCaptor.capture(),
+ eq(WIFI_AWARE_DISCOVERY_LOST_REASON_PEER_NOT_VISIBLE));
+ assertEquals(peerHandle.peerId, peerIdCaptor.getValue().peerId);
+
+ // (6) terminate
subscribeSession.getValue().close();
mMockLooper.dispatchAll();
inOrder.verify(mockAwareService).terminateSession(clientId, sessionId);
- // (6) try an update (nothing)
+ // (7) try an update (nothing)
subscribeSession.getValue().updateSubscribe(subscribeConfig);
mMockLooper.dispatchAll();
diff --git a/framework/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java b/framework/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
index 8270d64..badcf52 100644
--- a/framework/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
+++ b/framework/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
@@ -186,6 +186,7 @@
assertFalse(config.validateForR2());
assertTrue(config.isAutojoinEnabled());
assertTrue(config.isMacRandomizationEnabled());
+ assertFalse(config.isEnhancedMacRandomizationEnabled());
assertTrue(config.getMeteredOverride() == METERED_OVERRIDE_NONE);
}
diff --git a/framework/tests/src/android/net/wifi/hotspot2/PasspointTestUtils.java b/framework/tests/src/android/net/wifi/hotspot2/PasspointTestUtils.java
index 8d55acb..5830a1e 100644
--- a/framework/tests/src/android/net/wifi/hotspot2/PasspointTestUtils.java
+++ b/framework/tests/src/android/net/wifi/hotspot2/PasspointTestUtils.java
@@ -30,6 +30,7 @@
public class PasspointTestUtils {
private static final int CERTIFICATE_FINGERPRINT_BYTES = 32;
+ private static final int TEST_SUB_ID = 1;
/**
* Utility function for creating a {@link android.net.wifi.hotspot2.pps.HomeSP}.
@@ -156,6 +157,7 @@
friendlyNames.put("en", "ServiceName1");
friendlyNames.put("kr", "ServiceName2");
config.setServiceFriendlyNames(friendlyNames);
+ config.setSubscriptionId(TEST_SUB_ID);
return config;
}
diff --git a/framework/tests/src/android/net/wifi/hotspot2/pps/HomeSpTest.java b/framework/tests/src/android/net/wifi/hotspot2/pps/HomeSpTest.java
index 93d471a..fe889fc 100644
--- a/framework/tests/src/android/net/wifi/hotspot2/pps/HomeSpTest.java
+++ b/framework/tests/src/android/net/wifi/hotspot2/pps/HomeSpTest.java
@@ -16,6 +16,7 @@
package android.net.wifi.hotspot2.pps;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
@@ -26,7 +27,9 @@
import org.junit.Test;
import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
@@ -35,6 +38,7 @@
*/
@SmallTest
public class HomeSpTest {
+ private static final String[] OTHER_HOME_PARTNER_LIST = new String[]{"partner1", "partner2"};
/**
* Helper function for creating a map of home network IDs for testing.
@@ -62,7 +66,7 @@
homeSp.setHomeNetworkIds(homeNetworkIds);
homeSp.setMatchAllOis(new long[] {0x11L, 0x22L});
homeSp.setMatchAnyOis(new long[] {0x33L, 0x44L});
- homeSp.setOtherHomePartners(new String[] {"partner1", "partner2"});
+ homeSp.setOtherHomePartners(OTHER_HOME_PARTNER_LIST);
homeSp.setRoamingConsortiumOis(new long[] {0x55, 0x66});
return homeSp;
}
@@ -218,4 +222,34 @@
HomeSp copySp = new HomeSp(sourceSp);
assertTrue(copySp.equals(sourceSp));
}
+
+ /**
+ * Verify that the getOtherHomePartnersList gets the list of partners as expected.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void validateGetOtherHomePartnersList() throws Exception {
+ HomeSp homeSp = createHomeSpWithoutHomeNetworkIds();
+
+ Collection<String> otherHomePartnersList = homeSp.getOtherHomePartnersList();
+ assertEquals(2, otherHomePartnersList.size());
+ assertTrue(Arrays.equals(OTHER_HOME_PARTNER_LIST, otherHomePartnersList.toArray()));
+ }
+
+ /**
+ * Verify that the setOtherHomePartnersList sets the list of partners as expected.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void validateSetOtherHomePartnersList() throws Exception {
+ HomeSp homeSp = createHomeSpWithoutHomeNetworkIds();
+
+ final Collection<String> homePartners =
+ new ArrayList<>(Arrays.asList(OTHER_HOME_PARTNER_LIST));
+
+ homeSp.setOtherHomePartnersList(homePartners);
+ assertTrue(Arrays.equals(homeSp.getOtherHomePartners(), OTHER_HOME_PARTNER_LIST));
+ }
}
diff --git a/framework/tests/src/android/net/wifi/rtt/WifiRttManagerTest.java b/framework/tests/src/android/net/wifi/rtt/WifiRttManagerTest.java
index e6eae41..c8006fe 100644
--- a/framework/tests/src/android/net/wifi/rtt/WifiRttManagerTest.java
+++ b/framework/tests/src/android/net/wifi/rtt/WifiRttManagerTest.java
@@ -16,6 +16,8 @@
package android.net.wifi.rtt;
+import static junit.framework.Assert.fail;
+
import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
@@ -143,6 +145,7 @@
PeerHandle peerHandle1 = new PeerHandle(12);
RangingRequest.Builder builder = new RangingRequest.Builder();
+ builder.setRttBurstSize(4);
builder.addAccessPoint(scanResult1);
builder.addAccessPoints(scanResults2and3);
builder.addWifiAwarePeer(mac1);
@@ -163,6 +166,60 @@
}
/**
+ * Validate the rtt burst size is set correctly when in range.
+ */
+ @Test
+ public void testRangingRequestSetBurstSize() {
+ ScanResult scanResult = new ScanResult();
+ scanResult.BSSID = "AA:BB:CC:DD:EE:FF";
+
+ // create request
+ RangingRequest.Builder builder = new RangingRequest.Builder();
+ builder.setRttBurstSize(4);
+ builder.addAccessPoint(scanResult);
+ RangingRequest request = builder.build();
+
+ // confirm rtt burst size is set correctly to default value
+ assertEquals(request.getRttBurstSize(), 4);
+ }
+
+ /**
+ * Validate the rtt burst size cannot be smaller than the minimum.
+ */
+ @Test
+ public void testRangingRequestMinBurstSizeIsEnforced() {
+ ScanResult scanResult = new ScanResult();
+ scanResult.BSSID = "AA:BB:CC:DD:EE:FF";
+
+ // create request
+ try {
+ RangingRequest.Builder builder = new RangingRequest.Builder();
+ builder.setRttBurstSize(RangingRequest.getMinRttBurstSize() - 1);
+ fail("RTT burst size was smaller than min value.");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+
+ /**
+ * Validate the rtt burst size cannot exceed the maximum.
+ */
+ @Test
+ public void testRangingRequestMaxBurstSizeIsEnforced() {
+ ScanResult scanResult = new ScanResult();
+ scanResult.BSSID = "AA:BB:CC:DD:EE:FF";
+
+ // create request
+ try {
+ RangingRequest.Builder builder = new RangingRequest.Builder();
+ builder.setRttBurstSize(RangingRequest.getMaxRttBurstSize() + 1);
+ fail("RTT Burst size exceeded max value.");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+
+ /**
* Validate that can request as many range operation as the upper limit on number of requests.
*/
@Test
@@ -175,7 +232,7 @@
}
MacAddress mac1 = MacAddress.fromString("00:01:02:03:04:05");
- // create request
+ // create request using max RTT Peers
RangingRequest.Builder builder = new RangingRequest.Builder();
builder.addAccessPoint(scanResult);
builder.addAccessPoints(scanResultList);
@@ -185,6 +242,18 @@
// verify request
request.enforceValidity(true);
+ // confirm rtt burst size is set correctly to default value
+ assertEquals(request.getRttBurstSize(), RangingRequest.getDefaultRttBurstSize());
+ // confirm the number of peers in the request is the max number of peers
+ List<ResponderConfig> rttPeers = request.getRttPeers();
+ int numRttPeers = rttPeers.size();
+ assertEquals(RangingRequest.getMaxPeers(), numRttPeers);
+ // confirm each peer has the correct mac address
+ for (int i = 0; i < numRttPeers - 1; ++i) {
+ assertEquals("AA:BB:CC:DD:EE:FF", rttPeers.get(i).macAddress.toString().toUpperCase());
+ }
+ assertEquals("00:01:02:03:04:05",
+ rttPeers.get(numRttPeers - 1).macAddress.toString().toUpperCase());
}
/**