Merge "Wifi P2p Manager Test Cases" into main
diff --git a/WifiDialog/src/com/android/wifi/dialog/WifiDialogActivity.java b/WifiDialog/src/com/android/wifi/dialog/WifiDialogActivity.java
index 4dab628..cf1b4cc 100644
--- a/WifiDialog/src/com/android/wifi/dialog/WifiDialogActivity.java
+++ b/WifiDialog/src/com/android/wifi/dialog/WifiDialogActivity.java
@@ -33,9 +33,6 @@
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.os.CountDownTimer;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.SystemClock;
import android.os.Vibrator;
import android.text.Editable;
import android.text.SpannableString;
@@ -62,8 +59,12 @@
import androidx.annotation.Nullable;
import androidx.core.os.BuildCompat;
+import com.android.wifi.x.com.android.wifi.flags.Flags;
+
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import java.util.Set;
/**
@@ -72,12 +73,9 @@
public class WifiDialogActivity extends Activity {
private static final String TAG = "WifiDialog";
private static final String KEY_DIALOG_INTENTS = "KEY_DIALOG_INTENTS";
- private static final String EXTRA_DIALOG_EXPIRATION_TIME_MS =
- "com.android.wifi.dialog.DIALOG_START_TIME_MS";
private static final String EXTRA_DIALOG_P2P_PIN_INPUT =
"com.android.wifi.dialog.DIALOG_P2P_PIN_INPUT";
- private @NonNull Handler mHandler = new Handler(Looper.getMainLooper());
private @Nullable WifiContext mWifiContext;
private @Nullable WifiManager mWifiManager;
private boolean mIsVerboseLoggingEnabled;
@@ -104,6 +102,10 @@
return getWifiContext().getString(getWifiResourceId(name, "string"));
}
+ private String getWifiString(@NonNull String name, @Nullable String arg) {
+ return getWifiContext().getString(getWifiResourceId(name, "string"), arg);
+ }
+
private int getWifiInteger(@NonNull String name) {
return getWifiContext().getResources().getInteger(getWifiResourceId(name, "integer"));
}
@@ -354,7 +356,8 @@
dialogId,
intent.getStringExtra(WifiManager.EXTRA_P2P_DEVICE_NAME),
intent.getBooleanExtra(WifiManager.EXTRA_P2P_PIN_REQUESTED, false),
- intent.getStringExtra(WifiManager.EXTRA_P2P_DISPLAY_PIN));
+ intent.getStringExtra(WifiManager.EXTRA_P2P_DISPLAY_PIN),
+ intent.getIntExtra(WifiManager.EXTRA_DIALOG_TIMEOUT_MS, 0));
break;
default:
if (mIsVerboseLoggingEnabled) {
@@ -378,50 +381,6 @@
dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG);
}
mActiveDialogsPerId.put(dialogId, dialog);
- long timeoutMs = intent.getLongExtra(WifiManager.EXTRA_DIALOG_TIMEOUT_MS, 0);
- if (timeoutMs > 0) {
- // Use the original expiration time in case we've reloaded this dialog after a
- // configuration change.
- long expirationTimeMs = intent.getLongExtra(EXTRA_DIALOG_EXPIRATION_TIME_MS, 0);
- if (expirationTimeMs > 0) {
- timeoutMs = expirationTimeMs - SystemClock.uptimeMillis();
- if (timeoutMs < 0) {
- timeoutMs = 0;
- }
- } else {
- intent.putExtra(
- EXTRA_DIALOG_EXPIRATION_TIME_MS, SystemClock.uptimeMillis() + timeoutMs);
- }
- CountDownTimer countDownTimer = new CountDownTimer(timeoutMs, 100) {
- @Override
- public void onTick(long millisUntilFinished) {
- if (dialogType == WifiManager.DIALOG_TYPE_P2P_INVITATION_RECEIVED) {
- int secondsRemaining = (int) millisUntilFinished / 1000;
- if (millisUntilFinished % 1000 != 0) {
- // Round up to the nearest whole second.
- secondsRemaining++;
- }
- TextView timeRemaining = dialog.getWindow().findViewById(
- getWifiViewId("time_remaining"));
- timeRemaining.setText(MessageFormat.format(
- getWifiString("wifi_p2p_invitation_seconds_remaining"),
- secondsRemaining));
- timeRemaining.setVisibility(View.VISIBLE);
- }
- }
-
- @Override
- public void onFinish() {
- removeIntentAndPossiblyFinish(dialogId);
- }
- }.start();
- mActiveCountDownTimersPerId.put(dialogId, countDownTimer);
- } else {
- if (dialogType == WifiManager.DIALOG_TYPE_P2P_INVITATION_RECEIVED) {
- // Set the message back to null if we aren't using a timeout.
- dialog.setMessage(null);
- }
- }
dialog.show();
if (mIsVerboseLoggingEnabled) {
Log.v(TAG, "Showing dialog " + dialogId);
@@ -540,6 +499,10 @@
final int dialogId,
@Nullable final String deviceName,
@Nullable final String displayPin) {
+ if (Flags.p2pDialog2()) {
+ return createP2pInvitationSentDialog2(dialogId, deviceName, displayPin);
+ }
+
final View textEntryView = getWifiLayoutInflater()
.inflate(getWifiLayoutId("wifi_p2p_dialog"), null);
ViewGroup group = textEntryView.findViewById(getWifiViewId("info"));
@@ -577,18 +540,78 @@
}
/**
+ * Returns a P2P Invitation Sent Dialog2 for the given Intent.
+ */
+ private @NonNull AlertDialog createP2pInvitationSentDialog2(
+ final int dialogId,
+ @Nullable final String deviceName,
+ @Nullable final String displayPin) {
+ if (TextUtils.isEmpty(deviceName)) {
+ Log.w(TAG, "P2P Invitation Sent dialog device name is null or empty."
+ + " id=" + dialogId
+ + " deviceName=" + deviceName
+ + " displayPin=" + displayPin);
+ }
+ final View customView;
+ final String title;
+ final String message;
+ if (displayPin != null) {
+ customView = getWifiLayoutInflater()
+ .inflate(getWifiLayoutId("wifi_p2p_dialog2_display_pin"), null);
+ ((TextView) customView.findViewById(getWifiViewId("wifi_p2p_dialog2_display_pin")))
+ .setText(displayPin);
+ title = getWifiString("wifi_p2p_dialog2_sent_title_display_pin", deviceName);
+ message = getWifiString("wifi_p2p_dialog2_sent_message_display_pin", deviceName);
+ } else {
+ customView = null;
+ title = getWifiString("wifi_p2p_dialog2_sent_title", deviceName);
+ message = getWifiString("wifi_p2p_dialog2_sent_message", deviceName);
+ }
+
+ AlertDialog.Builder builder = getWifiAlertDialogBuilder("wifi_p2p_dialog2")
+ .setTitle(title)
+ .setMessage(message)
+ .setPositiveButton(getWifiString("wifi_p2p_dialog2_sent_positive_button"),
+ (dialogPositive, which) -> {
+ // No-op
+ if (mIsVerboseLoggingEnabled) {
+ Log.v(TAG, "P2P Invitation Sent Dialog id=" + dialogId
+ + " accepted.");
+ }
+ });
+ if (customView != null) {
+ builder.setView(customView);
+ }
+ AlertDialog dialog = builder.create();
+ if (mIsVerboseLoggingEnabled) {
+ Log.v(TAG, "Created P2P Invitation Sent dialog."
+ + " id=" + dialogId
+ + " deviceName=" + deviceName
+ + " displayPin=" + displayPin);
+ }
+ return dialog;
+ }
+
+ /**
* Returns a P2P Invitation Received Dialog for the given Intent.
*/
private @NonNull AlertDialog createP2pInvitationReceivedDialog(
final int dialogId,
@Nullable final String deviceName,
final boolean isPinRequested,
- @Nullable final String displayPin) {
+ @Nullable final String displayPin,
+ int timeoutMs) {
+ if (Flags.p2pDialog2()) {
+ return createP2pInvitationReceivedDialog2(dialogId, deviceName, isPinRequested,
+ displayPin, timeoutMs);
+ }
+
if (TextUtils.isEmpty(deviceName)) {
Log.w(TAG, "P2P Invitation Received dialog device name is null or empty."
+ " id=" + dialogId
+ " deviceName=" + deviceName
- + " displayPin=" + displayPin);
+ + " displayPin=" + displayPin
+ + " timeoutMs=" + timeoutMs);
}
final View textEntryView = getWifiLayoutInflater()
.inflate(getWifiLayoutId("wifi_p2p_dialog"), null);
@@ -702,6 +725,41 @@
return true;
});
}
+ if (timeoutMs > 0) {
+ CountDownTimer countDownTimer = new CountDownTimer(timeoutMs, 100) {
+ @Override
+ public void onTick(long millisUntilFinished) {
+ Intent intent = mLaunchIntentsPerId.get(dialogId);
+ if (intent != null) {
+ // Store the updated timeout to use if we reload this dialog after a
+ // configuration change
+ intent.putExtra(WifiManager.EXTRA_DIALOG_TIMEOUT_MS,
+ (int) millisUntilFinished);
+ }
+
+ if (!getWifiBoolean("config_p2pInvitationReceivedDialogShowRemainingTime")) {
+ return;
+ }
+ int secondsRemaining = (int) millisUntilFinished / 1000;
+ if (millisUntilFinished % 1000 != 0) {
+ // Round up to the nearest whole second.
+ secondsRemaining++;
+ }
+ TextView timeRemaining = textEntryView.findViewById(
+ getWifiViewId("time_remaining"));
+ timeRemaining.setText(MessageFormat.format(
+ getWifiString("wifi_p2p_invitation_seconds_remaining"),
+ secondsRemaining));
+ timeRemaining.setVisibility(View.VISIBLE);
+ }
+
+ @Override
+ public void onFinish() {
+ removeIntentAndPossiblyFinish(dialogId);
+ }
+ }.start();
+ mActiveCountDownTimersPerId.put(dialogId, countDownTimer);
+ }
if (mIsVerboseLoggingEnabled) {
Log.v(TAG, "Created P2P Invitation Received dialog."
+ " id=" + dialogId
@@ -722,4 +780,195 @@
((TextView) row.findViewById(getWifiViewId("value"))).setText(value);
group.addView(row);
}
+
+ /**
+ * Returns a P2P Invitation Received Dialog2 for the given Intent.
+ */
+ private @NonNull AlertDialog createP2pInvitationReceivedDialog2(
+ final int dialogId,
+ @Nullable final String deviceName,
+ final boolean isPinRequested,
+ @Nullable final String displayPin,
+ final int timeoutMs) {
+ if (TextUtils.isEmpty(deviceName)) {
+ Log.w(TAG, "P2P Invitation Received dialog device name is null or empty."
+ + " id=" + dialogId
+ + " deviceName=" + deviceName
+ + " displayPin=" + displayPin);
+ }
+ final View customView;
+ String title = getWifiString("wifi_p2p_dialog2_received_title", deviceName);
+ final String message;
+ final String timeoutMessage;
+ final EditText pinEditText;
+ if (isPinRequested) {
+ customView = getWifiLayoutInflater()
+ .inflate(getWifiLayoutId("wifi_p2p_dialog2_enter_pin"), null);
+ pinEditText = customView.findViewById(getWifiViewId("wifi_p2p_dialog2_enter_pin"));
+ title = getWifiString("wifi_p2p_dialog2_received_title_enter_pin", deviceName);
+ message = getWifiString("wifi_p2p_dialog2_received_message_enter_pin", deviceName);
+ timeoutMessage = getWifiString("wifi_p2p_dialog2_received_message_enter_pin_countdown",
+ deviceName);
+ } else {
+ pinEditText = null;
+ if (!TextUtils.isEmpty(displayPin)) {
+ customView = getWifiLayoutInflater()
+ .inflate(getWifiLayoutId("wifi_p2p_dialog2_display_pin"), null);
+ ((TextView) customView.findViewById(getWifiViewId("wifi_p2p_dialog2_display_pin")))
+ .setText(displayPin);
+ title = getWifiString("wifi_p2p_dialog2_received_title_display_pin", deviceName);
+ message = getWifiString("wifi_p2p_dialog2_received_message_display_pin",
+ deviceName);
+ timeoutMessage = getWifiString(
+ "wifi_p2p_dialog2_received_message_display_pin_countdown", deviceName);
+ } else {
+ customView = null;
+ message = getWifiString("wifi_p2p_dialog2_received_message", deviceName);
+ timeoutMessage = getWifiString("wifi_p2p_dialog2_received_message_countdown",
+ deviceName);
+ }
+ }
+
+ AlertDialog.Builder builder = getWifiAlertDialogBuilder("wifi_p2p_dialog2")
+ .setTitle(title)
+ .setMessage(message)
+ .setPositiveButton(getWifiString("wifi_p2p_dialog2_received_positive_button"),
+ (dialogPositive, which) -> {
+ String pin = null;
+ if (pinEditText != null) {
+ pin = pinEditText.getText().toString();
+ }
+ if (mIsVerboseLoggingEnabled) {
+ Log.v(TAG, "P2P Invitation Received Dialog id=" + dialogId
+ + " accepted with pin=" + pin);
+ }
+ getWifiManager().replyToP2pInvitationReceivedDialog(dialogId, true,
+ pin);
+ })
+ .setNegativeButton(getWifiString("wifi_p2p_dialog2_received_negative_button"),
+ (dialogNegative, which) -> {
+ if (mIsVerboseLoggingEnabled) {
+ Log.v(TAG, "P2P Invitation Received dialog id=" + dialogId
+ + " declined.");
+ }
+ getWifiManager().replyToP2pInvitationReceivedDialog(dialogId, false,
+ null);
+ })
+ .setOnCancelListener((dialogCancel) -> {
+ if (mIsVerboseLoggingEnabled) {
+ Log.v(TAG, "P2P Invitation Received dialog id=" + dialogId
+ + " cancelled.");
+ }
+ getWifiManager().replyToP2pInvitationReceivedDialog(dialogId, false, null);
+ });
+ if (customView != null) {
+ builder.setView(customView);
+ }
+ AlertDialog dialog = builder.create();
+ if (isPinRequested) {
+ dialog.getWindow().setSoftInputMode(
+ WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
+ dialog.setOnShowListener(dialogShow -> {
+ Intent intent = mLaunchIntentsPerId.get(dialogId);
+ if (intent != null) {
+ // Populate the pin EditText with the previous user input if we're recreating
+ // the dialog after a configuration change.
+ CharSequence previousPin =
+ intent.getCharSequenceExtra(EXTRA_DIALOG_P2P_PIN_INPUT);
+ if (previousPin != null) {
+ pinEditText.setText(previousPin);
+ }
+ }
+ if (getResources().getConfiguration().orientation
+ == Configuration.ORIENTATION_PORTRAIT
+ || (getResources().getConfiguration().screenLayout
+ & Configuration.SCREENLAYOUT_SIZE_MASK)
+ >= Configuration.SCREENLAYOUT_SIZE_LARGE) {
+ pinEditText.requestFocus();
+ pinEditText.setSelection(pinEditText.getText().length());
+ }
+ dialog.getButton(Dialog.BUTTON_POSITIVE).setEnabled(
+ pinEditText.length() == 4 || pinEditText.length() == 8);
+ });
+ pinEditText.addTextChangedListener(new TextWatcher() {
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+ // No-op.
+ }
+
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+ // No-op.
+ }
+
+ @Override
+ public void afterTextChanged(Editable s) {
+ Intent intent = mLaunchIntentsPerId.get(dialogId);
+ if (intent != null) {
+ // Store the current input in the Intent in case we need to reload from a
+ // configuration change.
+ intent.putExtra(EXTRA_DIALOG_P2P_PIN_INPUT, s);
+ }
+ dialog.getButton(Dialog.BUTTON_POSITIVE).setEnabled(
+ s.length() == 4 || s.length() == 8);
+ }
+ });
+ } else {
+ dialog.setOnShowListener(dialogShow -> {
+ dialog.getButton(Dialog.BUTTON_NEGATIVE).requestFocus();
+ });
+ }
+ if ((getResources().getConfiguration().uiMode & Configuration.UI_MODE_TYPE_APPLIANCE)
+ == Configuration.UI_MODE_TYPE_APPLIANCE) {
+ // For appliance devices, add a key listener which accepts.
+ dialog.setOnKeyListener((dialogKey, keyCode, event) -> {
+ if (keyCode == KeyEvent.KEYCODE_VOLUME_MUTE) {
+ dialog.dismiss();
+ getWifiManager().replyToP2pInvitationReceivedDialog(dialogId, true, null);
+ }
+ return true;
+ });
+ }
+ if (timeoutMs > 0) {
+ CountDownTimer countDownTimer = new CountDownTimer(timeoutMs, 100) {
+ @Override
+ public void onTick(long millisUntilFinished) {
+ Intent intent = mLaunchIntentsPerId.get(dialogId);
+ if (intent != null) {
+ // Store the updated timeout to use if we reload this dialog after a
+ // configuration change
+ intent.putExtra(WifiManager.EXTRA_DIALOG_TIMEOUT_MS,
+ (int) millisUntilFinished);
+ }
+
+ if (!getWifiBoolean("config_p2pInvitationReceivedDialogShowRemainingTime")) {
+ return;
+ }
+ int secondsRemaining = (int) millisUntilFinished / 1000;
+ if (millisUntilFinished % 1000 != 0) {
+ // Round up to the nearest whole second.
+ secondsRemaining++;
+ }
+ Map<String, Object> messageArgs = new HashMap<>();
+ messageArgs.put("device", deviceName);
+ messageArgs.put("countdown", secondsRemaining);
+ dialog.setMessage(MessageFormat.format(timeoutMessage, messageArgs));
+ }
+
+ @Override
+ public void onFinish() {
+ removeIntentAndPossiblyFinish(dialogId);
+ }
+ }.start();
+ mActiveCountDownTimersPerId.put(dialogId, countDownTimer);
+ }
+ if (mIsVerboseLoggingEnabled) {
+ Log.v(TAG, "Created P2P Invitation Received dialog."
+ + " id=" + dialogId
+ + " deviceName=" + deviceName
+ + " isPinRequested=" + isPinRequested
+ + " displayPin=" + displayPin);
+ }
+ return dialog;
+ }
}
diff --git a/aidl/mainline_supplicant/Android.bp b/aidl/mainline_supplicant/Android.bp
new file mode 100644
index 0000000..285af3d
--- /dev/null
+++ b/aidl/mainline_supplicant/Android.bp
@@ -0,0 +1,42 @@
+// Copyright (C) 2024 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+aidl_interface {
+ name: "android.system.wifi.mainline_supplicant",
+ unstable: true,
+ srcs: [
+ "android/system/wifi/mainline_supplicant/*.aidl",
+ ],
+ backend: {
+ java: {
+ enabled: true,
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.wifi",
+ ],
+ min_sdk_version: "30",
+ },
+ ndk: {
+ enabled: true,
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.wifi",
+ ],
+ min_sdk_version: "30",
+ },
+ cpp: {
+ enabled: false,
+ },
+ },
+}
diff --git a/aidl/mainline_supplicant/android/system/wifi/mainline_supplicant/IMainlineSupplicant.aidl b/aidl/mainline_supplicant/android/system/wifi/mainline_supplicant/IMainlineSupplicant.aidl
new file mode 100644
index 0000000..4179b06
--- /dev/null
+++ b/aidl/mainline_supplicant/android/system/wifi/mainline_supplicant/IMainlineSupplicant.aidl
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.system.wifi.mainline_supplicant;
+
+/**
+ * Root of the mainline supplicant interface. This is an unstable AIDL interface used
+ * to interact with the supplicant binary stored in the mainline module.
+ */
+interface IMainlineSupplicant {
+ /**
+ * Register an interface for use by USD.
+ *
+ * @param ifaceName Name of the interface (ex. wlan0)
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|
+ */
+ void addUsdInterface(String ifaceName);
+
+ /**
+ * Remove an interface that is being used for USD.
+ *
+ * @param ifaceName Name of the interface (ex. wlan0)
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|
+ * |SupplicantStatusCode.FAILURE_IFACE_UNKNOWN|
+ */
+ void removeUsdInterface(String ifaceName);
+
+ /**
+ * Terminate the service.
+ */
+ oneway void terminate();
+}
diff --git a/aidl/mainline_supplicant/android/system/wifi/mainline_supplicant/SupplicantStatusCode.aidl b/aidl/mainline_supplicant/android/system/wifi/mainline_supplicant/SupplicantStatusCode.aidl
new file mode 100644
index 0000000..2086bc8
--- /dev/null
+++ b/aidl/mainline_supplicant/android/system/wifi/mainline_supplicant/SupplicantStatusCode.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.system.wifi.mainline_supplicant;
+
+/**
+ * Enum values indicating the status of any supplicant operation.
+ */
+enum SupplicantStatusCode {
+ /**
+ * No errors.
+ */
+ SUCCESS = 0,
+ /**
+ * Unknown failure occurred.
+ */
+ FAILURE_UNKNOWN = 1,
+ /**
+ * One of the provided arguments is invalid.
+ */
+ FAILURE_ARGS_INVALID = 2,
+ /**
+ * Interface with the provided name already exists.
+ */
+ FAILURE_IFACE_EXISTS = 3,
+ /**
+ * Interface with the provided name does not exist.
+ */
+ FAILURE_IFACE_UNKNOWN = 4,
+}
diff --git a/apex/Android.bp b/apex/Android.bp
index a878695..614777e 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -27,6 +27,8 @@
// from build rule `cacerts_wfa`
prebuilts: [
"cacerts_wfa",
+ "mainline_supplicant_conf",
+ "mainline_supplicant_rc",
],
key: "com.android.wifi.key",
certificate: ":com.android.wifi.certificate",
@@ -35,6 +37,13 @@
"ServiceWifiResources",
"WifiDialog",
],
+ binaries: select(release_flag("RELEASE_WIFI_MAINLINE_SUPPLICANT_BINARY"), {
+ true: ["wpa_supplicant_mainline"],
+ default: [],
+ }),
+ jni_libs: [
+ "libservice-wifi-jni",
+ ],
defaults: ["r-launched-apex-module"],
// Indicates that pre-installed version of this apex can be compressed.
// Whether it actually will be compressed is controlled on per-device basis.
@@ -122,6 +131,7 @@
"android.net.wifi.p2p",
"android.net.wifi.rtt",
"android.net.wifi.twt",
+ "android.net.wifi.usd",
"android.net.wifi.util",
"com.android.wifi",
],
diff --git a/flags/Android.bp b/flags/Android.bp
index 5deabc5..99ba39a 100644
--- a/flags/Android.bp
+++ b/flags/Android.bp
@@ -54,3 +54,9 @@
"aconfig_storage_stub",
],
}
+
+cc_aconfig_library {
+ name: "wifi_aconfig_flags_c_lib",
+ aconfig_declarations: "wifi_aconfig_flags",
+ vendor_available: true,
+}
diff --git a/flags/wifi_flags.aconfig b/flags/wifi_flags.aconfig
index 7b4decf..e914e9d 100644
--- a/flags/wifi_flags.aconfig
+++ b/flags/wifi_flags.aconfig
@@ -84,6 +84,7 @@
description: "Add new API to get channel width"
bug: "335358378"
is_fixed_read_only: true
+ is_exported: true
}
flag {
@@ -123,6 +124,7 @@
description: "optimize local-only connection API"
bug: "347117408"
is_fixed_read_only: true
+ is_exported: true
}
flag {
@@ -137,6 +139,15 @@
}
flag {
+ name: "autojoin_restriction_security_types_api"
+ is_exported: true
+ namespace: "wifi"
+ description: "Add new API to set or get Autojoin Restriction security types"
+ bug: "340351634"
+ is_fixed_read_only: true
+}
+
+flag {
name: "rsn_overriding"
namespace: "wifi"
description: "Wi-Fi Alliance RSN Overriding feature"
@@ -169,4 +180,102 @@
namespace: "wifi"
description: "Gate WiFi Scorer new stats collection"
bug: "367362809"
-}
\ No newline at end of file
+}
+
+flag {
+ name: "softap_disconnect_reason"
+ is_exported: true
+ namespace: "wifi"
+ description: "Add SoftAP disconnect reason code"
+ bug: "361651437"
+ is_fixed_read_only: true
+}
+
+flag {
+ name: "secure_ranging"
+ is_exported: true
+ namespace: "wifi"
+ description: "Add secure ranging support"
+ bug: "364722301"
+ is_fixed_read_only: true
+}
+
+flag {
+ name: "mainline_supplicant"
+ namespace: "wifi"
+ description: "Use the secondary supplicant binary stored in the mainline module"
+ bug: "365585450"
+ is_fixed_read_only: true
+}
+
+flag {
+ name: "mlo_sap"
+ is_exported: true
+ namespace: "wifi"
+ description: "Mlo SoftAp"
+ bug: "362355566"
+ is_fixed_read_only: true
+}
+
+flag {
+ name: "wifi_direct_r2"
+ is_exported: true
+ namespace: "wifi"
+ description: "Wi-Fi Alliance Wi-Fi Direct R2 feature"
+ bug: "341971059"
+ is_fixed_read_only: true
+}
+
+flag {
+ name: "wep_disabled_in_apm"
+ is_exported: true
+ namespace: "wifi"
+ description: "Wep should be disabled in advanced protection mode"
+ bug: "362586268"
+ is_fixed_read_only: true
+}
+
+flag {
+ name: "bssid_blocklist_for_suggestion"
+ is_exported: true
+ namespace: "wifi"
+ description: "Add BSSID to blocklist for network suggestion"
+ bug: "340263610"
+ is_fixed_read_only: true
+}
+
+flag {
+ name: "ap_isolate"
+ is_exported: true
+ namespace: "wifi"
+ description: "Supports Soft AP client isolation configuration"
+ bug: "364333929"
+ is_fixed_read_only: true
+}
+
+flag {
+ name: "public_bands_for_lohs"
+ is_exported: true
+ namespace: "wifi"
+ description: "Public bands api for local only hotspot from system api"
+ bug: "362355566"
+ is_fixed_read_only: true
+}
+
+flag {
+ name: "wifi_state_changed_listener"
+ is_exported: true
+ namespace: "wifi"
+ description: "Wifi state changed listener API"
+ bug: "349530934"
+ is_fixed_read_only: true
+}
+
+flag {
+ name: "p2p_dialog2"
+ is_exported: true
+ namespace: "wifi"
+ description: "Updated P2P dialogs"
+ bug: "349253691"
+ is_fixed_read_only: true
+}
diff --git a/framework/Android.bp b/framework/Android.bp
index f1186f4..c0280f0 100644
--- a/framework/Android.bp
+++ b/framework/Android.bp
@@ -109,6 +109,8 @@
"android.hardware.wifi-V1.0-java-constants",
"wifi-modules-utils",
"PlatformProperties",
+ "android.net.wifi.flags-aconfig-java",
+ "ranging_aconfig_flags_lib",
],
libs: [
"androidx.annotation_annotation",
@@ -119,6 +121,7 @@
// library for generated flag code read new storage
"aconfig_storage_stub",
"framework-configinfrastructure.stubs.module_lib",
+ "android.security.flags-aconfig-java-export",
],
aidl: {
generate_get_transaction_name: true,
diff --git a/framework/aidl-export/android/net/wifi/BlockingOption.aidl b/framework/aidl-export/android/net/wifi/BlockingOption.aidl
new file mode 100644
index 0000000..47d4627
--- /dev/null
+++ b/framework/aidl-export/android/net/wifi/BlockingOption.aidl
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2024, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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;
+
+parcelable BlockingOption;
diff --git a/framework/aidl-export/android/net/wifi/usd/Characteristics.aidl b/framework/aidl-export/android/net/wifi/usd/Characteristics.aidl
new file mode 100644
index 0000000..818426b
--- /dev/null
+++ b/framework/aidl-export/android/net/wifi/usd/Characteristics.aidl
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2024, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.usd;
+
+parcelable Characteristics;
diff --git a/framework/aidl-export/android/net/wifi/usd/PublishConfig.aidl b/framework/aidl-export/android/net/wifi/usd/PublishConfig.aidl
new file mode 100644
index 0000000..80e5421
--- /dev/null
+++ b/framework/aidl-export/android/net/wifi/usd/PublishConfig.aidl
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2024, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.usd;
+
+parcelable PublishConfig;
diff --git a/framework/aidl-export/android/net/wifi/usd/SubscribeConfig.aidl b/framework/aidl-export/android/net/wifi/usd/SubscribeConfig.aidl
new file mode 100644
index 0000000..71a1684
--- /dev/null
+++ b/framework/aidl-export/android/net/wifi/usd/SubscribeConfig.aidl
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2024, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.usd;
+
+parcelable SubscribeConfig;
diff --git a/framework/api/current.txt b/framework/api/current.txt
index 45ec47e..41062f1 100644
--- a/framework/api/current.txt
+++ b/framework/api/current.txt
@@ -1,6 +1,20 @@
// Signature format: 2.0
package android.net.wifi {
+ @FlaggedApi("com.android.wifi.flags.bssid_blocklist_for_suggestion") public final class BlockingOption implements android.os.Parcelable {
+ method public int describeContents();
+ method public int getBlockingTimeSeconds();
+ method public boolean isBlockingBssidOnly();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.BlockingOption> CREATOR;
+ }
+
+ @FlaggedApi("com.android.wifi.flags.bssid_blocklist_for_suggestion") public static final class BlockingOption.Builder {
+ ctor public BlockingOption.Builder(@IntRange(from=1, to=86400) int);
+ method @NonNull public android.net.wifi.BlockingOption build();
+ method @NonNull public android.net.wifi.BlockingOption.Builder setBlockingBssidOnly(boolean);
+ }
+
public abstract class EasyConnectStatusCallback {
field public static final int EASY_CONNECT_EVENT_FAILURE_AUTHENTICATION = -2; // 0xfffffffe
field public static final int EASY_CONNECT_EVENT_FAILURE_BUSY = -5; // 0xfffffffb
@@ -55,6 +69,8 @@
method @FlaggedApi("com.android.wifi.flags.android_v_wifi_api") public boolean is80211azNtbResponder();
method public boolean is80211mcResponder();
method public boolean isPasspointNetwork();
+ method @FlaggedApi("com.android.wifi.flags.secure_ranging") public boolean isRangingFrameProtectionRequired();
+ method @FlaggedApi("com.android.wifi.flags.secure_ranging") public boolean isSecureHeLtfSupported();
method @FlaggedApi("com.android.wifi.flags.android_v_wifi_api") public boolean isTwtResponder();
method public void writeToParcel(android.os.Parcel, int);
field public String BSSID;
@@ -108,12 +124,17 @@
public final class SoftApConfiguration implements android.os.Parcelable {
method public int describeContents();
method @Nullable public android.net.MacAddress getBssid();
+ method @FlaggedApi("com.android.wifi.flags.public_bands_for_lohs") @NonNull public android.util.SparseIntArray getChannels();
method @Nullable public String getPassphrase();
method public int getSecurityType();
method @Deprecated @Nullable public String getSsid();
method @Nullable public android.net.wifi.WifiSsid getWifiSsid();
method public boolean isHiddenSsid();
method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @FlaggedApi("com.android.wifi.flags.public_bands_for_lohs") public static final int BAND_2GHZ = 1; // 0x1
+ field @FlaggedApi("com.android.wifi.flags.public_bands_for_lohs") public static final int BAND_5GHZ = 2; // 0x2
+ field @FlaggedApi("com.android.wifi.flags.public_bands_for_lohs") public static final int BAND_60GHZ = 8; // 0x8
+ field @FlaggedApi("com.android.wifi.flags.public_bands_for_lohs") public static final int BAND_6GHZ = 4; // 0x4
field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.SoftApConfiguration> CREATOR;
field public static final int SECURITY_TYPE_OPEN = 0; // 0x0
field public static final int SECURITY_TYPE_WPA2_PSK = 1; // 0x1
@@ -123,6 +144,12 @@
field public static final int SECURITY_TYPE_WPA3_SAE_TRANSITION = 2; // 0x2
}
+ @FlaggedApi("com.android.wifi.flags.public_bands_for_lohs") public static final class SoftApConfiguration.Builder {
+ ctor public SoftApConfiguration.Builder();
+ method @NonNull public android.net.wifi.SoftApConfiguration build();
+ method @NonNull public android.net.wifi.SoftApConfiguration.Builder setChannels(@NonNull android.util.SparseIntArray);
+ }
+
public enum SupplicantState implements android.os.Parcelable {
method public int describeContents();
method public static boolean isValidState(android.net.wifi.SupplicantState);
@@ -442,6 +469,7 @@
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 void addSuggestionUserApprovalStatusListener(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.WifiManager.SuggestionUserApprovalStatusListener);
+ method @FlaggedApi("com.android.wifi.flags.wifi_state_changed_listener") @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public void addWifiStateChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.WifiManager.WifiStateChangedListener);
method public void allowAutojoinGlobal(boolean);
method @Deprecated public static int calculateSignalLevel(int, int);
method @IntRange(from=0) public int calculateSignalLevel(int);
@@ -451,6 +479,7 @@
method public android.net.wifi.WifiManager.WifiLock createWifiLock(int, String);
method @Deprecated public android.net.wifi.WifiManager.WifiLock createWifiLock(String);
method @Deprecated public boolean disableNetwork(int);
+ method @FlaggedApi("com.android.wifi.flags.bssid_blocklist_for_suggestion") @RequiresPermission(android.Manifest.permission.CHANGE_WIFI_STATE) public void disallowCurrentSuggestedNetwork(@NonNull android.net.wifi.BlockingOption);
method @Deprecated public boolean disconnect();
method @Deprecated public boolean enableNetwork(int, boolean);
method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_MANAGED_PROVISIONING, android.Manifest.permission.NETWORK_CARRIER_PROVISIONING}, conditional=true) public void flushPasspointAnqpCache();
@@ -532,6 +561,7 @@
method @FlaggedApi("com.android.wifi.flags.android_v_wifi_api") public void removePerSsidRoamingMode(@NonNull android.net.wifi.WifiSsid);
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 @FlaggedApi("com.android.wifi.flags.wifi_state_changed_listener") @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public void removeWifiStateChangedListener(@NonNull android.net.wifi.WifiManager.WifiStateChangedListener);
method @RequiresPermission(allOf={android.Manifest.permission.MANAGE_WIFI_INTERFACES, android.Manifest.permission.ACCESS_WIFI_STATE}) public void reportCreateInterfaceImpact(int, boolean, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.BiConsumer<java.lang.Boolean,java.util.Set<android.net.wifi.WifiManager.InterfaceCreationImpact>>);
method @Deprecated public boolean saveConfiguration();
method @FlaggedApi("com.android.wifi.flags.android_v_wifi_api") public void setPerSsidRoamingMode(@NonNull android.net.wifi.WifiSsid, int);
@@ -542,6 +572,7 @@
method public void setTdlsEnabledWithMacAddress(@NonNull String, boolean, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
method @Deprecated public boolean setWifiEnabled(boolean);
method @RequiresPermission(allOf={android.Manifest.permission.CHANGE_WIFI_STATE, android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.NEARBY_WIFI_DEVICES}, conditional=true) public void startLocalOnlyHotspot(android.net.wifi.WifiManager.LocalOnlyHotspotCallback, @Nullable android.os.Handler);
+ method @FlaggedApi("com.android.wifi.flags.public_bands_for_lohs") @RequiresPermission(allOf={android.Manifest.permission.CHANGE_WIFI_STATE, android.Manifest.permission.NEARBY_WIFI_DEVICES}) public void startLocalOnlyHotspotWithConfiguration(@NonNull android.net.wifi.SoftApConfiguration, @NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.WifiManager.LocalOnlyHotspotCallback);
method @Deprecated public boolean startScan();
method @Deprecated public void startWps(android.net.wifi.WpsInfo, android.net.wifi.WifiManager.WpsCallback);
method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public void unregisterScanResultsCallback(@NonNull android.net.wifi.WifiManager.ScanResultsCallback);
@@ -711,6 +742,10 @@
method public void setWorkSource(android.os.WorkSource);
}
+ @FlaggedApi("com.android.wifi.flags.wifi_state_changed_listener") public static interface WifiManager.WifiStateChangedListener {
+ method public void onWifiStateChanged();
+ }
+
@Deprecated public abstract static class WifiManager.WpsCallback {
ctor @Deprecated public WifiManager.WpsCallback();
method @Deprecated public abstract void onFailed(int);
@@ -1254,19 +1289,30 @@
method public int describeContents();
method public int getGroupClientIpProvisioningMode();
method public int getGroupOwnerBand();
+ method @FlaggedApi("com.android.wifi.flags.wifi_direct_r2") public int getGroupOwnerVersion();
method public int getNetworkId();
method @Nullable public String getNetworkName();
+ method @FlaggedApi("com.android.wifi.flags.wifi_direct_r2") @Nullable public android.net.wifi.p2p.WifiP2pPairingBootstrappingConfig getPairingBootstrappingConfig();
method @Nullable public String getPassphrase();
+ method @FlaggedApi("com.android.wifi.flags.wifi_direct_r2") public int getPccModeConnectionType();
+ method @FlaggedApi("com.android.wifi.flags.wifi_direct_r2") public boolean isAuthorizeConnectionFromPeer();
+ method @FlaggedApi("com.android.wifi.flags.wifi_direct_r2") public void setGroupOwnerVersion(int);
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.p2p.WifiP2pConfig> CREATOR;
field public static final int GROUP_CLIENT_IP_PROVISIONING_MODE_IPV4_DHCP = 0; // 0x0
field public static final int GROUP_CLIENT_IP_PROVISIONING_MODE_IPV6_LINK_LOCAL = 1; // 0x1
field public static final int GROUP_OWNER_BAND_2GHZ = 1; // 0x1
field public static final int GROUP_OWNER_BAND_5GHZ = 2; // 0x2
+ field @FlaggedApi("com.android.wifi.flags.wifi_direct_r2") public static final int GROUP_OWNER_BAND_6GHZ = 3; // 0x3
field public static final int GROUP_OWNER_BAND_AUTO = 0; // 0x0
field public static final int GROUP_OWNER_INTENT_AUTO = -1; // 0xffffffff
field public static final int GROUP_OWNER_INTENT_MAX = 15; // 0xf
field public static final int GROUP_OWNER_INTENT_MIN = 0; // 0x0
+ field @FlaggedApi("com.android.wifi.flags.wifi_direct_r2") public static final int P2P_VERSION_1 = 0; // 0x0
+ field @FlaggedApi("com.android.wifi.flags.wifi_direct_r2") public static final int P2P_VERSION_2 = 1; // 0x1
+ field @FlaggedApi("com.android.wifi.flags.wifi_direct_r2") public static final int PCC_MODE_CONNECTION_TYPE_LEGACY_ONLY = 0; // 0x0
+ field @FlaggedApi("com.android.wifi.flags.wifi_direct_r2") public static final int PCC_MODE_CONNECTION_TYPE_LEGACY_OR_R2 = 1; // 0x1
+ field @FlaggedApi("com.android.wifi.flags.wifi_direct_r2") public static final int PCC_MODE_CONNECTION_TYPE_R2_ONLY = 2; // 0x2
field public String deviceAddress;
field @IntRange(from=0, to=15) public int groupOwnerIntent;
field public android.net.wifi.WpsInfo wps;
@@ -1276,12 +1322,15 @@
ctor public WifiP2pConfig.Builder();
method @NonNull public android.net.wifi.p2p.WifiP2pConfig build();
method @NonNull public android.net.wifi.p2p.WifiP2pConfig.Builder enablePersistentMode(boolean);
+ method @FlaggedApi("com.android.wifi.flags.wifi_direct_r2") @NonNull public android.net.wifi.p2p.WifiP2pConfig.Builder setAuthorizeConnectionFromPeer(boolean);
method @NonNull public android.net.wifi.p2p.WifiP2pConfig.Builder setDeviceAddress(@Nullable android.net.MacAddress);
method @NonNull public android.net.wifi.p2p.WifiP2pConfig.Builder setGroupClientIpProvisioningMode(int);
method @NonNull public android.net.wifi.p2p.WifiP2pConfig.Builder setGroupOperatingBand(int);
method @NonNull public android.net.wifi.p2p.WifiP2pConfig.Builder setGroupOperatingFrequency(int);
method @NonNull public android.net.wifi.p2p.WifiP2pConfig.Builder setNetworkName(@NonNull String);
+ method @FlaggedApi("com.android.wifi.flags.wifi_direct_r2") @NonNull public android.net.wifi.p2p.WifiP2pConfig.Builder setPairingBootstrappingConfig(@NonNull android.net.wifi.p2p.WifiP2pPairingBootstrappingConfig);
method @NonNull public android.net.wifi.p2p.WifiP2pConfig.Builder setPassphrase(@NonNull String);
+ method @FlaggedApi("com.android.wifi.flags.wifi_direct_r2") @NonNull public android.net.wifi.p2p.WifiP2pConfig.Builder setPccModeConnectionType(int);
}
public class WifiP2pDevice implements android.os.Parcelable {
@@ -1292,6 +1341,11 @@
method @NonNull public java.util.List<android.net.wifi.ScanResult.InformationElement> getVendorElements();
method @Nullable public android.net.wifi.p2p.WifiP2pWfdInfo getWfdInfo();
method public boolean isGroupOwner();
+ method @FlaggedApi("com.android.wifi.flags.wifi_direct_r2") public boolean isOpportunisticBootstrappingMethodSupported();
+ method @FlaggedApi("com.android.wifi.flags.wifi_direct_r2") public boolean isPassphraseDisplayBootstrappingMethodSupported();
+ method @FlaggedApi("com.android.wifi.flags.wifi_direct_r2") public boolean isPassphraseKeypadBootstrappingMethodSupported();
+ method @FlaggedApi("com.android.wifi.flags.wifi_direct_r2") public boolean isPinCodeDisplayBootstrappingMethodSupported();
+ method @FlaggedApi("com.android.wifi.flags.wifi_direct_r2") public boolean isPinCodeKeypadBootstrappingMethodSupported();
method public boolean isServiceDiscoveryCapable();
method public void update(@NonNull android.net.wifi.p2p.WifiP2pDevice);
method public boolean wpsDisplaySupported();
@@ -1321,6 +1375,16 @@
field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.p2p.WifiP2pDeviceList> CREATOR;
}
+ @FlaggedApi("com.android.wifi.flags.wifi_direct_r2") public final class WifiP2pDirInfo implements android.os.Parcelable {
+ ctor public WifiP2pDirInfo(@NonNull android.net.MacAddress, @NonNull byte[], @NonNull byte[]);
+ method public int describeContents();
+ method @NonNull public byte[] getDirTag();
+ method @NonNull public android.net.MacAddress getMacAddress();
+ method @NonNull public byte[] getNonce();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.p2p.WifiP2pDirInfo> CREATOR;
+ }
+
@FlaggedApi("com.android.wifi.flags.android_v_wifi_api") public final class WifiP2pDiscoveryConfig implements android.os.Parcelable {
method @FlaggedApi("com.android.wifi.flags.android_v_wifi_api") public int describeContents();
method @FlaggedApi("com.android.wifi.flags.android_v_wifi_api") public int getFrequencyMhz();
@@ -1341,16 +1405,22 @@
method public int describeContents();
method public java.util.Collection<android.net.wifi.p2p.WifiP2pDevice> getClientList();
method public int getFrequency();
+ method @FlaggedApi("com.android.wifi.flags.wifi_direct_r2") @Nullable public android.net.MacAddress getGroupOwnerBssid();
method public String getInterface();
method public int getNetworkId();
method public String getNetworkName();
method public android.net.wifi.p2p.WifiP2pDevice getOwner();
method public String getPassphrase();
+ method @FlaggedApi("com.android.wifi.flags.wifi_direct_r2") public int getSecurityType();
method public boolean isGroupOwner();
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.p2p.WifiP2pGroup> CREATOR;
field public static final int NETWORK_ID_PERSISTENT = -2; // 0xfffffffe
field public static final int NETWORK_ID_TEMPORARY = -1; // 0xffffffff
+ field @FlaggedApi("com.android.wifi.flags.wifi_direct_r2") public static final int SECURITY_TYPE_UNKNOWN = -1; // 0xffffffff
+ field @FlaggedApi("com.android.wifi.flags.wifi_direct_r2") public static final int SECURITY_TYPE_WPA2_PSK = 0; // 0x0
+ field @FlaggedApi("com.android.wifi.flags.wifi_direct_r2") public static final int SECURITY_TYPE_WPA3_COMPATIBILITY = 1; // 0x1
+ field @FlaggedApi("com.android.wifi.flags.wifi_direct_r2") public static final int SECURITY_TYPE_WPA3_SAE = 2; // 0x2
}
public class WifiP2pInfo implements android.os.Parcelable {
@@ -1378,13 +1448,16 @@
method @RequiresPermission(allOf={android.Manifest.permission.NEARBY_WIFI_DEVICES, android.Manifest.permission.ACCESS_FINE_LOCATION}, conditional=true) public void discoverPeersOnSocialChannels(@NonNull android.net.wifi.p2p.WifiP2pManager.Channel, @Nullable android.net.wifi.p2p.WifiP2pManager.ActionListener);
method @RequiresPermission(allOf={android.Manifest.permission.NEARBY_WIFI_DEVICES, android.Manifest.permission.ACCESS_FINE_LOCATION}, conditional=true) public void discoverPeersOnSpecificFrequency(@NonNull android.net.wifi.p2p.WifiP2pManager.Channel, int, @Nullable android.net.wifi.p2p.WifiP2pManager.ActionListener);
method @RequiresPermission(allOf={android.Manifest.permission.NEARBY_WIFI_DEVICES, android.Manifest.permission.ACCESS_FINE_LOCATION}, conditional=true) public void discoverServices(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.ActionListener);
+ method @FlaggedApi("com.android.wifi.flags.wifi_direct_r2") @RequiresPermission(allOf={android.Manifest.permission.NEARBY_WIFI_DEVICES, android.Manifest.permission.ACCESS_FINE_LOCATION}, conditional=true) public void discoverUsdBasedServices(@NonNull android.net.wifi.p2p.WifiP2pManager.Channel, @NonNull android.net.wifi.p2p.WifiP2pUsdBasedServiceDiscoveryConfig, @Nullable android.net.wifi.p2p.WifiP2pManager.ActionListener);
method @RequiresPermission(allOf={android.Manifest.permission.NEARBY_WIFI_DEVICES, android.Manifest.permission.ACCESS_FINE_LOCATION}, conditional=true) public void getListenState(@NonNull android.net.wifi.p2p.WifiP2pManager.Channel, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
method public static int getP2pMaxAllowedVendorElementsLengthBytes();
method public android.net.wifi.p2p.WifiP2pManager.Channel initialize(android.content.Context, android.os.Looper, android.net.wifi.p2p.WifiP2pManager.ChannelListener);
method public boolean isChannelConstrainedDiscoverySupported();
method public boolean isGroupClientRemovalSupported();
method public boolean isGroupOwnerIPv6LinkLocalAddressProvided();
+ method @FlaggedApi("com.android.wifi.flags.wifi_direct_r2") public boolean isPccModeSupported();
method public boolean isSetVendorElementsSupported();
+ method @FlaggedApi("com.android.wifi.flags.wifi_direct_r2") public boolean isWiFiDirectR2Supported();
method @FlaggedApi("com.android.wifi.flags.android_v_wifi_api") @RequiresPermission(allOf={android.Manifest.permission.NEARBY_WIFI_DEVICES, android.Manifest.permission.ACCESS_WIFI_STATE}, conditional=true) public void registerWifiP2pListener(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.p2p.WifiP2pManager.WifiP2pListener);
method public void removeClient(@NonNull android.net.wifi.p2p.WifiP2pManager.Channel, @NonNull android.net.MacAddress, @Nullable android.net.wifi.p2p.WifiP2pManager.ActionListener);
method @RequiresPermission(android.Manifest.permission.MANAGE_WIFI_NETWORK_SELECTION) public void removeExternalApprover(@NonNull android.net.wifi.p2p.WifiP2pManager.Channel, @NonNull android.net.MacAddress, @Nullable android.net.wifi.p2p.WifiP2pManager.ActionListener);
@@ -1393,6 +1466,7 @@
method public void removeServiceRequest(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.nsd.WifiP2pServiceRequest, android.net.wifi.p2p.WifiP2pManager.ActionListener);
method public void requestConnectionInfo(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.ConnectionInfoListener);
method @RequiresPermission(allOf={android.Manifest.permission.NEARBY_WIFI_DEVICES, android.Manifest.permission.ACCESS_FINE_LOCATION}, conditional=true) public void requestDeviceInfo(@NonNull android.net.wifi.p2p.WifiP2pManager.Channel, @NonNull android.net.wifi.p2p.WifiP2pManager.DeviceInfoListener);
+ method @FlaggedApi("com.android.wifi.flags.wifi_direct_r2") @RequiresPermission(allOf={android.Manifest.permission.NEARBY_WIFI_DEVICES, android.Manifest.permission.ACCESS_FINE_LOCATION}, conditional=true) public void requestDirInfo(@NonNull android.net.wifi.p2p.WifiP2pManager.Channel, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<android.net.wifi.p2p.WifiP2pDirInfo,java.lang.Exception>);
method public void requestDiscoveryState(@NonNull android.net.wifi.p2p.WifiP2pManager.Channel, @NonNull android.net.wifi.p2p.WifiP2pManager.DiscoveryStateListener);
method @RequiresPermission(allOf={android.Manifest.permission.NEARBY_WIFI_DEVICES, android.Manifest.permission.ACCESS_FINE_LOCATION}, conditional=true) public void requestGroupInfo(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.GroupInfoListener);
method public void requestNetworkInfo(@NonNull android.net.wifi.p2p.WifiP2pManager.Channel, @NonNull android.net.wifi.p2p.WifiP2pManager.NetworkInfoListener);
@@ -1407,9 +1481,11 @@
method @RequiresPermission(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY) public void setWfdInfo(@NonNull android.net.wifi.p2p.WifiP2pManager.Channel, @NonNull android.net.wifi.p2p.WifiP2pWfdInfo, @Nullable android.net.wifi.p2p.WifiP2pManager.ActionListener);
method @RequiresPermission(allOf={android.Manifest.permission.NEARBY_WIFI_DEVICES, android.Manifest.permission.ACCESS_FINE_LOCATION}, conditional=true) public void startListening(@NonNull android.net.wifi.p2p.WifiP2pManager.Channel, @Nullable android.net.wifi.p2p.WifiP2pManager.ActionListener);
method @FlaggedApi("com.android.wifi.flags.android_v_wifi_api") @RequiresPermission(allOf={android.Manifest.permission.NEARBY_WIFI_DEVICES, android.Manifest.permission.ACCESS_FINE_LOCATION}, conditional=true) public void startPeerDiscovery(@NonNull android.net.wifi.p2p.WifiP2pManager.Channel, @NonNull android.net.wifi.p2p.WifiP2pDiscoveryConfig, @Nullable android.net.wifi.p2p.WifiP2pManager.ActionListener);
+ method @FlaggedApi("com.android.wifi.flags.wifi_direct_r2") @RequiresPermission(allOf={android.Manifest.permission.NEARBY_WIFI_DEVICES, android.Manifest.permission.ACCESS_FINE_LOCATION}, conditional=true) public void startUsdBasedLocalServiceAdvertisement(@NonNull android.net.wifi.p2p.WifiP2pManager.Channel, @NonNull android.net.wifi.p2p.nsd.WifiP2pServiceInfo, @NonNull android.net.wifi.p2p.WifiP2pUsdBasedLocalServiceAdvertisementConfig, @Nullable android.net.wifi.p2p.WifiP2pManager.ActionListener);
method public void stopListening(@NonNull android.net.wifi.p2p.WifiP2pManager.Channel, @Nullable android.net.wifi.p2p.WifiP2pManager.ActionListener);
method public void stopPeerDiscovery(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.ActionListener);
method @FlaggedApi("com.android.wifi.flags.android_v_wifi_api") public void unregisterWifiP2pListener(@NonNull android.net.wifi.p2p.WifiP2pManager.WifiP2pListener);
+ method @FlaggedApi("com.android.wifi.flags.wifi_direct_r2") @RequiresPermission(allOf={android.Manifest.permission.NEARBY_WIFI_DEVICES, android.Manifest.permission.ACCESS_FINE_LOCATION}, conditional=true) public void validateDirInfo(@NonNull android.net.wifi.p2p.WifiP2pManager.Channel, @NonNull android.net.wifi.p2p.WifiP2pDirInfo, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<java.lang.Boolean,java.lang.Exception>);
field public static final String ACTION_WIFI_P2P_LISTEN_STATE_CHANGED = "android.net.wifi.p2p.action.WIFI_P2P_LISTEN_STATE_CHANGED";
field public static final String ACTION_WIFI_P2P_REQUEST_RESPONSE_CHANGED = "android.net.wifi.p2p.action.WIFI_P2P_REQUEST_RESPONSE_CHANGED";
field public static final int BUSY = 2; // 0x2
@@ -1434,6 +1510,7 @@
field @FlaggedApi("com.android.wifi.flags.android_v_wifi_api") public static final int GROUP_CREATION_FAILURE_REASON_PROVISION_DISCOVERY_FAILED = 3; // 0x3
field @FlaggedApi("com.android.wifi.flags.android_v_wifi_api") public static final int GROUP_CREATION_FAILURE_REASON_TIMED_OUT = 1; // 0x1
field @FlaggedApi("com.android.wifi.flags.android_v_wifi_api") public static final int GROUP_CREATION_FAILURE_REASON_USER_REJECTED = 2; // 0x2
+ field @FlaggedApi("com.android.wifi.flags.wifi_direct_r2") public static final int NO_PERMISSION = 4; // 0x4
field public static final int NO_SERVICE_REQUESTS = 3; // 0x3
field public static final int P2P_UNSUPPORTED = 1; // 0x1
field public static final String WIFI_P2P_CONNECTION_CHANGED_ACTION = "android.net.wifi.p2p.CONNECTION_STATE_CHANGE";
@@ -1517,6 +1594,7 @@
public static interface WifiP2pManager.ServiceResponseListener {
method public void onServiceAvailable(int, byte[], android.net.wifi.p2p.WifiP2pDevice);
+ method @FlaggedApi("com.android.wifi.flags.wifi_direct_r2") public default void onUsdBasedServiceAvailable(@NonNull android.net.wifi.p2p.WifiP2pDevice, @NonNull android.net.wifi.p2p.nsd.WifiP2pUsdBasedServiceResponse);
}
public static interface WifiP2pManager.UpnpServiceResponseListener {
@@ -1539,6 +1617,47 @@
method @FlaggedApi("com.android.wifi.flags.android_v_wifi_api") public default void onPeerListChanged(@NonNull android.net.wifi.p2p.WifiP2pDeviceList);
}
+ @FlaggedApi("com.android.wifi.flags.wifi_direct_r2") public final class WifiP2pPairingBootstrappingConfig implements android.os.Parcelable {
+ ctor public WifiP2pPairingBootstrappingConfig(int, @Nullable String);
+ method public int describeContents();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.p2p.WifiP2pPairingBootstrappingConfig> CREATOR;
+ field public static final int PAIRING_BOOTSTRAPPING_METHOD_DISPLAY_PASSPHRASE = 4; // 0x4
+ field public static final int PAIRING_BOOTSTRAPPING_METHOD_DISPLAY_PINCODE = 2; // 0x2
+ field public static final int PAIRING_BOOTSTRAPPING_METHOD_KEYPAD_PASSPHRASE = 16; // 0x10
+ field public static final int PAIRING_BOOTSTRAPPING_METHOD_KEYPAD_PINCODE = 8; // 0x8
+ field public static final int PAIRING_BOOTSTRAPPING_METHOD_OPPORTUNISTIC = 1; // 0x1
+ field public static final int PAIRING_BOOTSTRAPPING_METHOD_OUT_OF_BAND = 32; // 0x20
+ }
+
+ @FlaggedApi("com.android.wifi.flags.wifi_direct_r2") public final class WifiP2pUsdBasedLocalServiceAdvertisementConfig implements android.os.Parcelable {
+ method public int describeContents();
+ method @IntRange(from=0) public int getFrequencyMhz();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.p2p.WifiP2pUsdBasedLocalServiceAdvertisementConfig> CREATOR;
+ }
+
+ public static final class WifiP2pUsdBasedLocalServiceAdvertisementConfig.Builder {
+ ctor public WifiP2pUsdBasedLocalServiceAdvertisementConfig.Builder();
+ method @NonNull public android.net.wifi.p2p.WifiP2pUsdBasedLocalServiceAdvertisementConfig build();
+ method @NonNull public android.net.wifi.p2p.WifiP2pUsdBasedLocalServiceAdvertisementConfig.Builder setFrequencyMhz(@IntRange(from=0) int);
+ }
+
+ @FlaggedApi("com.android.wifi.flags.wifi_direct_r2") public final class WifiP2pUsdBasedServiceDiscoveryConfig implements android.os.Parcelable {
+ method public int describeContents();
+ method public int getBand();
+ method @Nullable public int[] getFrequenciesMhz();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.p2p.WifiP2pUsdBasedServiceDiscoveryConfig> CREATOR;
+ }
+
+ public static final class WifiP2pUsdBasedServiceDiscoveryConfig.Builder {
+ ctor public WifiP2pUsdBasedServiceDiscoveryConfig.Builder();
+ method @NonNull public android.net.wifi.p2p.WifiP2pUsdBasedServiceDiscoveryConfig build();
+ method @NonNull public android.net.wifi.p2p.WifiP2pUsdBasedServiceDiscoveryConfig.Builder setBand(int);
+ method @NonNull public android.net.wifi.p2p.WifiP2pUsdBasedServiceDiscoveryConfig.Builder setFrequenciesMhz(@NonNull int[]);
+ }
+
public final class WifiP2pWfdInfo implements android.os.Parcelable {
ctor public WifiP2pWfdInfo();
ctor public WifiP2pWfdInfo(@Nullable android.net.wifi.p2p.WifiP2pWfdInfo);
@@ -1601,7 +1720,9 @@
}
public class WifiP2pServiceInfo implements android.os.Parcelable {
+ ctor @FlaggedApi("com.android.wifi.flags.wifi_direct_r2") public WifiP2pServiceInfo(@NonNull android.net.wifi.p2p.nsd.WifiP2pUsdBasedServiceConfig);
method public int describeContents();
+ method @FlaggedApi("com.android.wifi.flags.wifi_direct_r2") @Nullable public android.net.wifi.p2p.nsd.WifiP2pUsdBasedServiceConfig getWifiP2pUsdBasedServiceConfig();
method public void writeToParcel(android.os.Parcel, int);
field public static final int SERVICE_TYPE_ALL = 0; // 0x0
field public static final int SERVICE_TYPE_BONJOUR = 1; // 0x1
@@ -1610,7 +1731,9 @@
}
public class WifiP2pServiceRequest implements android.os.Parcelable {
+ ctor @FlaggedApi("com.android.wifi.flags.wifi_direct_r2") public WifiP2pServiceRequest(@NonNull android.net.wifi.p2p.nsd.WifiP2pUsdBasedServiceConfig);
method public int describeContents();
+ method @FlaggedApi("com.android.wifi.flags.wifi_direct_r2") @Nullable public android.net.wifi.p2p.nsd.WifiP2pUsdBasedServiceConfig getWifiP2pUsdBasedServiceConfig();
method public static android.net.wifi.p2p.nsd.WifiP2pServiceRequest newInstance(int, String);
method public static android.net.wifi.p2p.nsd.WifiP2pServiceRequest newInstance(int);
method public void writeToParcel(android.os.Parcel, int);
@@ -1625,6 +1748,33 @@
method public static android.net.wifi.p2p.nsd.WifiP2pUpnpServiceRequest newInstance(String);
}
+ @FlaggedApi("com.android.wifi.flags.wifi_direct_r2") public final class WifiP2pUsdBasedServiceConfig implements android.os.Parcelable {
+ ctor public WifiP2pUsdBasedServiceConfig();
+ method public int describeContents();
+ method @NonNull public String getServiceName();
+ method @IntRange(from=0, to=255) public int getServiceProtocolType();
+ method @Nullable public byte[] getServiceSpecificInfo();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.p2p.nsd.WifiP2pUsdBasedServiceConfig> CREATOR;
+ field public static final int SERVICE_PROTOCOL_TYPE_BONJOUR = 1; // 0x1
+ field public static final int SERVICE_PROTOCOL_TYPE_GENERIC = 2; // 0x2
+ }
+
+ public static final class WifiP2pUsdBasedServiceConfig.Builder {
+ ctor public WifiP2pUsdBasedServiceConfig.Builder(@NonNull String);
+ method @NonNull public android.net.wifi.p2p.nsd.WifiP2pUsdBasedServiceConfig build();
+ method @NonNull public android.net.wifi.p2p.nsd.WifiP2pUsdBasedServiceConfig.Builder setServiceProtocolType(@IntRange(from=0, to=255) int);
+ method @NonNull public android.net.wifi.p2p.nsd.WifiP2pUsdBasedServiceConfig.Builder setServiceSpecificInfo(@Nullable byte[]);
+ }
+
+ @FlaggedApi("com.android.wifi.flags.wifi_direct_r2") public final class WifiP2pUsdBasedServiceResponse implements android.os.Parcelable {
+ method public int describeContents();
+ method @IntRange(from=0, to=255) public int getServiceProtocolType();
+ method @Nullable public byte[] getServiceSpecificInfo();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.p2p.nsd.WifiP2pUsdBasedServiceResponse> CREATOR;
+ }
+
}
package android.net.wifi.rtt {
@@ -1664,6 +1814,39 @@
field public static final int TYPE_OF_PLACE = 29; // 0x1d
}
+ @FlaggedApi("com.android.wifi.flags.secure_ranging") public final class PasnConfig implements android.os.Parcelable {
+ method public int describeContents();
+ method public int getBaseAkms();
+ method public int getCiphers();
+ method @Nullable public byte[] getPasnComebackCookie();
+ method @Nullable public String getPassword();
+ method @Nullable public android.net.wifi.WifiSsid getWifiSsid();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field public static final int AKM_FILS_EAP_SHA256 = 64; // 0x40
+ field public static final int AKM_FILS_EAP_SHA384 = 128; // 0x80
+ field public static final int AKM_FT_EAP_SHA256 = 4; // 0x4
+ field public static final int AKM_FT_EAP_SHA384 = 16; // 0x10
+ field public static final int AKM_FT_PSK_SHA256 = 8; // 0x8
+ field public static final int AKM_FT_PSK_SHA384 = 32; // 0x20
+ field public static final int AKM_NONE = 0; // 0x0
+ field public static final int AKM_PASN = 1; // 0x1
+ field public static final int AKM_SAE = 2; // 0x2
+ field public static final int CIPHER_CCMP_128 = 1; // 0x1
+ field public static final int CIPHER_CCMP_256 = 2; // 0x2
+ field public static final int CIPHER_GCMP_128 = 4; // 0x4
+ field public static final int CIPHER_GCMP_256 = 8; // 0x8
+ field public static final int CIPHER_NONE = 0; // 0x0
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.rtt.PasnConfig> CREATOR;
+ }
+
+ @FlaggedApi("com.android.wifi.flags.secure_ranging") public static final class PasnConfig.Builder {
+ ctor public PasnConfig.Builder(int, int);
+ method @NonNull public android.net.wifi.rtt.PasnConfig build();
+ method @NonNull public android.net.wifi.rtt.PasnConfig.Builder setPasnComebackCookie(@NonNull byte[]);
+ method @NonNull public android.net.wifi.rtt.PasnConfig.Builder setPassword(@NonNull String);
+ method @NonNull public android.net.wifi.rtt.PasnConfig.Builder setWifiSsid(@NonNull android.net.wifi.WifiSsid);
+ }
+
public final class RangingRequest implements android.os.Parcelable {
method public int describeContents();
method public static int getDefaultRttBurstSize();
@@ -1671,8 +1854,12 @@
method public static int getMaxRttBurstSize();
method public static int getMinRttBurstSize();
method public int getRttBurstSize();
+ method @FlaggedApi("com.android.wifi.flags.secure_ranging") public int getSecurityMode();
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.rtt.RangingRequest> CREATOR;
+ field @FlaggedApi("com.android.wifi.flags.secure_ranging") public static final int SECURITY_MODE_OPEN = 0; // 0x0
+ field @FlaggedApi("com.android.wifi.flags.secure_ranging") public static final int SECURITY_MODE_OPPORTUNISTIC = 1; // 0x1
+ field @FlaggedApi("com.android.wifi.flags.secure_ranging") public static final int SECURITY_MODE_SECURE_AUTH = 2; // 0x2
}
public static final class RangingRequest.Builder {
@@ -1687,6 +1874,7 @@
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);
+ method @FlaggedApi("com.android.wifi.flags.secure_ranging") @NonNull public android.net.wifi.rtt.RangingRequest.Builder setSecurityMode(int);
}
public final class RangingResult implements android.os.Parcelable {
@@ -1706,13 +1894,19 @@
method @FlaggedApi("com.android.wifi.flags.android_v_wifi_api") public long getMinTimeBetweenNtbMeasurementsMicros();
method public int getNumAttemptedMeasurements();
method public int getNumSuccessfulMeasurements();
+ method @FlaggedApi("com.android.wifi.flags.secure_ranging") public long getPasnComebackAfterMillis();
+ method @FlaggedApi("com.android.wifi.flags.secure_ranging") @Nullable public byte[] getPasnComebackCookie();
method @Nullable public android.net.wifi.aware.PeerHandle getPeerHandle();
method public long getRangingTimestampMillis();
method public int getRssi();
+ method @FlaggedApi("com.android.wifi.flags.secure_ranging") @IntRange(from=0, to=7) public int getSecureHeLtfProtocolVersion();
method public int getStatus();
method @Nullable public android.net.wifi.rtt.ResponderLocation getUnverifiedResponderLocation();
method @FlaggedApi("com.android.wifi.flags.android_v_wifi_api") public boolean is80211azNtbMeasurement();
method public boolean is80211mcMeasurement();
+ method @FlaggedApi("com.android.wifi.flags.secure_ranging") public boolean isRangingAuthenticated();
+ method @FlaggedApi("com.android.wifi.flags.secure_ranging") public boolean isRangingFrameProtected();
+ method @FlaggedApi("com.android.wifi.flags.secure_ranging") public boolean isSecureHeLtfEnabled();
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.rtt.RangingResult> CREATOR;
field public static final int STATUS_FAIL = 1; // 0x1
@@ -1741,9 +1935,15 @@
method @FlaggedApi("com.android.wifi.flags.android_v_wifi_api") @NonNull public android.net.wifi.rtt.RangingResult.Builder setMinTimeBetweenNtbMeasurementsMicros(long);
method @FlaggedApi("com.android.wifi.flags.android_v_wifi_api") @NonNull public android.net.wifi.rtt.RangingResult.Builder setNumAttemptedMeasurements(int);
method @FlaggedApi("com.android.wifi.flags.android_v_wifi_api") @NonNull public android.net.wifi.rtt.RangingResult.Builder setNumSuccessfulMeasurements(int);
+ method @FlaggedApi("com.android.wifi.flags.secure_ranging") @NonNull public android.net.wifi.rtt.RangingResult.Builder setPasnComebackAfterMillis(long);
+ method @FlaggedApi("com.android.wifi.flags.secure_ranging") @NonNull public android.net.wifi.rtt.RangingResult.Builder setPasnComebackCookie(@NonNull byte[]);
method @FlaggedApi("com.android.wifi.flags.android_v_wifi_api") @NonNull public android.net.wifi.rtt.RangingResult.Builder setPeerHandle(@Nullable android.net.wifi.aware.PeerHandle);
+ method @FlaggedApi("com.android.wifi.flags.secure_ranging") @NonNull public android.net.wifi.rtt.RangingResult.Builder setRangingAuthenticated(boolean);
+ method @FlaggedApi("com.android.wifi.flags.secure_ranging") @NonNull public android.net.wifi.rtt.RangingResult.Builder setRangingFrameProtected(boolean);
method @FlaggedApi("com.android.wifi.flags.android_v_wifi_api") @NonNull public android.net.wifi.rtt.RangingResult.Builder setRangingTimestampMillis(long);
method @FlaggedApi("com.android.wifi.flags.android_v_wifi_api") @NonNull public android.net.wifi.rtt.RangingResult.Builder setRssi(int);
+ method @FlaggedApi("com.android.wifi.flags.secure_ranging") @NonNull public android.net.wifi.rtt.RangingResult.Builder setSecureHeLtfEnabled(boolean);
+ method @FlaggedApi("com.android.wifi.flags.secure_ranging") @NonNull public android.net.wifi.rtt.RangingResult.Builder setSecureHeLtfProtocolVersion(@IntRange(from=0, to=7) int);
method @FlaggedApi("com.android.wifi.flags.android_v_wifi_api") @NonNull public android.net.wifi.rtt.RangingResult.Builder setStatus(int);
method @FlaggedApi("com.android.wifi.flags.android_v_wifi_api") @NonNull public android.net.wifi.rtt.RangingResult.Builder setUnverifiedResponderLocation(@Nullable android.net.wifi.rtt.ResponderLocation);
}
@@ -1766,6 +1966,7 @@
method @Nullable public android.net.MacAddress getMacAddress();
method public int getPreamble();
method public int getResponderType();
+ method @FlaggedApi("com.android.wifi.flags.secure_ranging") @Nullable public android.net.wifi.rtt.SecureRangingConfig getSecureRangingConfig();
method @FlaggedApi("com.android.wifi.flags.android_v_wifi_api") public boolean is80211azNtbSupported();
method public boolean is80211mcSupported();
method public void writeToParcel(@NonNull android.os.Parcel, int);
@@ -1786,6 +1987,7 @@
method @NonNull public android.net.wifi.rtt.ResponderConfig.Builder setMacAddress(@NonNull android.net.MacAddress);
method @NonNull public android.net.wifi.rtt.ResponderConfig.Builder setPreamble(int);
method @NonNull public android.net.wifi.rtt.ResponderConfig.Builder setResponderType(int);
+ method @FlaggedApi("com.android.wifi.flags.secure_ranging") @NonNull public android.net.wifi.rtt.ResponderConfig.Builder setSecureRangingConfig(@NonNull android.net.wifi.rtt.SecureRangingConfig);
}
public final class ResponderLocation implements android.os.Parcelable {
@@ -1828,6 +2030,22 @@
field public static final int LOCATION_VARIABLE = 1; // 0x1
}
+ @FlaggedApi("com.android.wifi.flags.secure_ranging") public final class SecureRangingConfig implements android.os.Parcelable {
+ method @FlaggedApi("com.android.wifi.flags.secure_ranging") public int describeContents();
+ method @FlaggedApi("com.android.wifi.flags.secure_ranging") @NonNull public android.net.wifi.rtt.PasnConfig getPasnConfig();
+ method @FlaggedApi("com.android.wifi.flags.secure_ranging") public boolean isRangingFrameProtectionEnabled();
+ method @FlaggedApi("com.android.wifi.flags.secure_ranging") public boolean isSecureHeLtfEnabled();
+ method @FlaggedApi("com.android.wifi.flags.secure_ranging") public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @FlaggedApi("com.android.wifi.flags.secure_ranging") @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.rtt.SecureRangingConfig> CREATOR;
+ }
+
+ @FlaggedApi("com.android.wifi.flags.secure_ranging") public static final class SecureRangingConfig.Builder {
+ ctor @FlaggedApi("com.android.wifi.flags.secure_ranging") public SecureRangingConfig.Builder(@NonNull android.net.wifi.rtt.PasnConfig);
+ method @FlaggedApi("com.android.wifi.flags.secure_ranging") @NonNull public android.net.wifi.rtt.SecureRangingConfig build();
+ method @FlaggedApi("com.android.wifi.flags.secure_ranging") @NonNull public android.net.wifi.rtt.SecureRangingConfig.Builder setRangingFrameProtectionEnabled(boolean);
+ method @FlaggedApi("com.android.wifi.flags.secure_ranging") @NonNull public android.net.wifi.rtt.SecureRangingConfig.Builder setSecureHeLtfEnabled(boolean);
+ }
+
public class WifiRttManager {
method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public android.os.Bundle getRttCharacteristics();
method public boolean isAvailable();
@@ -1837,7 +2055,10 @@
field public static final String CHARACTERISTICS_KEY_BOOLEAN_LCR = "key_lcr";
field @FlaggedApi("com.android.wifi.flags.android_v_wifi_api") public static final String CHARACTERISTICS_KEY_BOOLEAN_NTB_INITIATOR = "key_ntb_initiator";
field public static final String CHARACTERISTICS_KEY_BOOLEAN_ONE_SIDED_RTT = "key_one_sided_rtt";
+ field @FlaggedApi("com.android.wifi.flags.secure_ranging") public static final String CHARACTERISTICS_KEY_BOOLEAN_RANGING_FRAME_PROTECTION_SUPPORTED = "key_rnm_mfp_supported";
+ field @FlaggedApi("com.android.wifi.flags.secure_ranging") public static final String CHARACTERISTICS_KEY_BOOLEAN_SECURE_HE_LTF_SUPPORTED = "key_secure_he_ltf_supported";
field public static final String CHARACTERISTICS_KEY_BOOLEAN_STA_RESPONDER = "key_sta_responder";
+ field @FlaggedApi("com.android.wifi.flags.secure_ranging") public static final String CHARACTERISTICS_KEY_INT_MAX_SUPPORTED_SECURE_HE_LTF_PROTO_VERSION = "key_max_supported_secure_he_ltf_proto_ver";
}
}
diff --git a/framework/api/system-current.txt b/framework/api/system-current.txt
index d06e48a..55bd9eb 100644
--- a/framework/api/system-current.txt
+++ b/framework/api/system-current.txt
@@ -13,6 +13,71 @@
field public static final int POWER_CAP_NONE = 2147483647; // 0x7fffffff
}
+ @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public final class DeauthenticationReasonCode {
+ field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_AKMP_NOT_VALID = 20; // 0x14
+ field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_AUTHORIZED_ACCESS_LIMIT_REACHED = 46; // 0x2e
+ field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_BAD_CIPHER_OR_AKM = 29; // 0x1d
+ field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_BSS_TRANSITION_DISASSOC = 12; // 0xc
+ field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_CIPHER_SUITE_REJECTED = 24; // 0x18
+ field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_CLASS2_FRAME_FROM_NONAUTH_STA = 6; // 0x6
+ field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_CLASS3_FRAME_FROM_NONASSOC_STA = 7; // 0x7
+ field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_DEAUTH_LEAVING = 3; // 0x3
+ field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_DISASSOC_AP_BUSY = 5; // 0x5
+ field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_DISASSOC_DUE_TO_INACTIVITY = 4; // 0x4
+ field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_DISASSOC_LOW_ACK = 34; // 0x22
+ field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_DISASSOC_STA_HAS_LEFT = 8; // 0x8
+ field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_END_TS_BA_DLS = 37; // 0x25
+ field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_EXCEEDED_TXOP = 35; // 0x23
+ field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_EXTERNAL_SERVICE_REQUIREMENTS = 47; // 0x2f
+ field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_FOURWAY_HANDSHAKE_TIMEOUT = 15; // 0xf
+ field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_GROUP_CIPHER_NOT_VALID = 18; // 0x12
+ field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_GROUP_KEY_UPDATE_TIMEOUT = 16; // 0x10
+ field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_IEEE_802_1X_AUTH_FAILED = 23; // 0x17
+ field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_IE_IN_4WAY_DIFFERS = 17; // 0x11
+ field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_INVALID_FTE = 51; // 0x33
+ field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_INVALID_FT_ACTION_FRAME_COUNT = 48; // 0x30
+ field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_INVALID_IE = 13; // 0xd
+ field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_INVALID_MDE = 50; // 0x32
+ field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_INVALID_PMKID = 49; // 0x31
+ field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_INVALID_RSN_IE_CAPAB = 22; // 0x16
+ field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_MAC_ADDRESS_ALREADY_EXISTS_IN_MBSS = 64; // 0x40
+ field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_MESH_CHANNEL_SWITCH_REGULATORY_REQ = 65; // 0x41
+ field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_MESH_CHANNEL_SWITCH_UNSPECIFIED = 66; // 0x42
+ field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_MESH_CLOSE_RCVD = 55; // 0x37
+ field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_MESH_CONFIG_POLICY_VIOLATION = 54; // 0x36
+ field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_MESH_CONFIRM_TIMEOUT = 57; // 0x39
+ field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_MESH_INCONSISTENT_PARAMS = 59; // 0x3b
+ field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_MESH_INVALID_GTK = 58; // 0x3a
+ field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_MESH_INVALID_SECURITY_CAP = 60; // 0x3c
+ field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_MESH_MAX_PEERS = 53; // 0x35
+ field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_MESH_MAX_RETRIES = 56; // 0x38
+ field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_MESH_PATH_ERROR_DEST_UNREACHABLE = 63; // 0x3f
+ field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_MESH_PATH_ERROR_NO_FORWARDING_INFO = 62; // 0x3e
+ field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_MESH_PATH_ERROR_NO_PROXY_INFO = 61; // 0x3d
+ field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_MESH_PEERING_CANCELLED = 52; // 0x34
+ field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_MICHAEL_MIC_FAILURE = 14; // 0xe
+ field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_NOT_AUTHORIZED_THIS_LOCATION = 30; // 0x1e
+ field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_NOT_ENOUGH_BANDWIDTH = 33; // 0x21
+ field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_NO_SSP_ROAMING_AGREEMENT = 28; // 0x1c
+ field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_PAIRWISE_CIPHER_NOT_VALID = 19; // 0x13
+ field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_PEERKEY_MISMATCH = 45; // 0x2d
+ field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_PREV_AUTH_NOT_VALID = 2; // 0x2
+ field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_PWR_CAPABILITY_NOT_VALID = 10; // 0xa
+ field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_SERVICE_CHANGE_PRECLUDES_TS = 31; // 0x1f
+ field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_SSP_REQUESTED_DISASSOC = 27; // 0x1b
+ field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_STA_LEAVING = 36; // 0x24
+ field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_STA_REQ_ASSOC_WITHOUT_AUTH = 9; // 0x9
+ field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_SUPPORTED_CHANNEL_NOT_VALID = 11; // 0xb
+ field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_TDLS_TEARDOWN_UNREACHABLE = 25; // 0x19
+ field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_TDLS_TEARDOWN_UNSPECIFIED = 26; // 0x1a
+ field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_TIMEOUT = 39; // 0x27
+ field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_UNKNOWN = 0; // 0x0
+ field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_UNKNOWN_TS_BA = 38; // 0x26
+ field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_UNSPECIFIED = 1; // 0x1
+ field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_UNSPECIFIED_QOS_REASON = 32; // 0x20
+ field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_UNSUPPORTED_RSN_IE_VERSION = 21; // 0x15
+ }
+
public abstract class EasyConnectStatusCallback {
ctor public EasyConnectStatusCallback();
method public void onBootstrapUriGenerated(@NonNull android.net.Uri);
@@ -411,6 +476,7 @@
field public static final long SOFTAP_FEATURE_IEEE80211_AX = 16L; // 0x10L
field public static final long SOFTAP_FEATURE_IEEE80211_BE = 512L; // 0x200L
field public static final long SOFTAP_FEATURE_MAC_ADDRESS_CUSTOMIZATION = 8L; // 0x8L
+ field @FlaggedApi("com.android.wifi.flags.mlo_sap") public static final long SOFTAP_FEATURE_MLO = 4096L; // 0x1000L
field public static final long SOFTAP_FEATURE_WPA3_OWE = 2048L; // 0x800L
field public static final long SOFTAP_FEATURE_WPA3_OWE_TRANSITION = 1024L; // 0x400L
field public static final long SOFTAP_FEATURE_WPA3_SAE = 4L; // 0x4L
@@ -423,7 +489,6 @@
method @NonNull public java.util.List<android.net.MacAddress> getBlockedClientList();
method public long getBridgedModeOpportunisticShutdownTimeoutMillis();
method @Deprecated public int getChannel();
- method @NonNull public android.util.SparseIntArray getChannels();
method public int getMacRandomizationSetting();
method public int getMaxChannelBandwidth();
method public int getMaxNumberOfClients();
@@ -434,14 +499,11 @@
method public boolean isAutoShutdownEnabled();
method public boolean isBridgedModeOpportunisticShutdownEnabled();
method public boolean isClientControlByUserEnabled();
+ method @FlaggedApi("com.android.wifi.flags.ap_isolate") public boolean isClientIsolationEnabled();
method public boolean isIeee80211axEnabled();
method public boolean isIeee80211beEnabled();
method public boolean isUserConfiguration();
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 @Deprecated public static final int BAND_ANY = 7; // 0x7
field public static final long DEFAULT_TIMEOUT = -1L; // 0xffffffffffffffffL
field public static final int RANDOMIZATION_NONE = 0; // 0x0
@@ -449,10 +511,8 @@
field public static final int RANDOMIZATION_PERSISTENT = 1; // 0x1
}
- public static final class SoftApConfiguration.Builder {
- ctor public SoftApConfiguration.Builder();
+ @FlaggedApi("com.android.wifi.flags.public_bands_for_lohs") public static final class SoftApConfiguration.Builder {
ctor public SoftApConfiguration.Builder(@NonNull android.net.wifi.SoftApConfiguration);
- method @NonNull public android.net.wifi.SoftApConfiguration build();
method @NonNull public android.net.wifi.SoftApConfiguration.Builder setAllowedAcsChannels(int, @NonNull int[]);
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);
@@ -463,8 +523,8 @@
method @NonNull public android.net.wifi.SoftApConfiguration.Builder setBridgedModeOpportunisticShutdownTimeoutMillis(@IntRange(from=0xffffffff) long);
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 @FlaggedApi("com.android.wifi.flags.ap_isolate") @NonNull public android.net.wifi.SoftApConfiguration.Builder setClientIsolationEnabled(boolean);
method @NonNull public android.net.wifi.SoftApConfiguration.Builder setHiddenSsid(boolean);
method @NonNull public android.net.wifi.SoftApConfiguration.Builder setIeee80211axEnabled(boolean);
method @NonNull public android.net.wifi.SoftApConfiguration.Builder setIeee80211beEnabled(boolean);
@@ -485,6 +545,7 @@
method public int getBandwidth();
method @Nullable public android.net.MacAddress getBssid();
method public int getFrequency();
+ method @FlaggedApi("com.android.wifi.flags.mlo_sap") @Nullable public android.net.MacAddress getMldAddress();
method @FlaggedApi("com.android.wifi.flags.android_v_wifi_api") @NonNull public java.util.List<android.net.wifi.OuiKeyedData> getVendorData();
method public int getWifiStandard();
method @FlaggedApi("com.android.wifi.flags.android_v_wifi_api") public void setVendorData(@NonNull java.util.List<android.net.wifi.OuiKeyedData>);
@@ -529,6 +590,7 @@
public final class WifiClient implements android.os.Parcelable {
method public int describeContents();
+ method @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public int getDisconnectReason();
method @NonNull public android.net.MacAddress getMacAddress();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.WifiClient> CREATOR;
@@ -719,6 +781,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 @FlaggedApi("com.android.wifi.flags.autojoin_restriction_security_types_api") @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.MANAGE_WIFI_NETWORK_SELECTION}) public void getAutojoinDisallowedSecurityTypes(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<int[]>);
+ method @FlaggedApi("android.security.aapm_api") @NonNull public java.util.List<android.security.advancedprotection.AdvancedProtectionFeature> getAvailableAdvancedProtectionFeatures();
method @FlaggedApi("com.android.wifi.flags.get_bssid_blocklist_api") @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void getBssidBlocklist(@NonNull java.util.List<android.net.wifi.WifiSsid>, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.util.List<android.net.MacAddress>>);
method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.ACCESS_COARSE_LOCATION}) public String getCountryCode();
method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public android.net.Network getCurrentNetwork();
@@ -753,6 +817,8 @@
method public boolean isPortableHotspotSupported();
method public boolean isStaConcurrencyForRestrictedConnectionsSupported();
method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public boolean isThirdPartyAppEnablingWifiConfirmationDialogEnabled();
+ method @FlaggedApi("android.net.wifi.flags.usd") @RequiresPermission(android.Manifest.permission.MANAGE_WIFI_NETWORK_SELECTION) public boolean isUsdPublisherSupported();
+ method @FlaggedApi("android.net.wifi.flags.usd") @RequiresPermission(android.Manifest.permission.MANAGE_WIFI_NETWORK_SELECTION) public boolean isUsdSubscriberSupported();
method public boolean isVerboseLoggingEnabled();
method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public boolean isWifiApEnabled();
method public boolean isWifiScannerSupported();
@@ -784,6 +850,7 @@
method @FlaggedApi("com.android.wifi.flags.android_v_wifi_api") @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void retrieveWifiBackupData(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<byte[]>);
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 @FlaggedApi("com.android.wifi.flags.autojoin_restriction_security_types_api") @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.MANAGE_WIFI_NETWORK_SELECTION}) public void setAutojoinDisallowedSecurityTypes(@NonNull int[]);
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.List<android.net.wifi.CoexUnsafeChannel>, int);
method @FlaggedApi("com.android.wifi.flags.android_v_wifi_api") @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void setD2dAllowedWhenInfraStaDisabled(boolean);
@@ -1024,6 +1091,7 @@
public static interface WifiManager.SoftApCallback {
method public default void onBlockedClientConnecting(@NonNull android.net.wifi.WifiClient, int);
method public default void onCapabilityChanged(@NonNull android.net.wifi.SoftApCapability);
+ method @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public default void onClientsDisconnected(@NonNull android.net.wifi.SoftApInfo, @NonNull java.util.List<android.net.wifi.WifiClient>);
method @Deprecated 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 @Deprecated public default void onInfoChanged(@NonNull android.net.wifi.SoftApInfo);
@@ -1459,6 +1527,17 @@
field public static final int UNSET_PARAMETER = -1; // 0xffffffff
}
+ public final class Characteristics implements android.os.Parcelable {
+ method @FlaggedApi("com.android.ranging.flags.ranging_rtt_enabled") public int getMaxSupportedRangingPktBandwidth();
+ method @FlaggedApi("com.android.ranging.flags.ranging_rtt_enabled") public int getMaxSupportedRxChains();
+ method @FlaggedApi("com.android.ranging.flags.ranging_rtt_enabled") public boolean isPeriodicRangingSupported();
+ field @FlaggedApi("com.android.ranging.flags.ranging_rtt_enabled") public static final int SUPPORTED_RX_CHAINS_1 = 1; // 0x1
+ field @FlaggedApi("com.android.ranging.flags.ranging_rtt_enabled") public static final int SUPPORTED_RX_CHAINS_2 = 2; // 0x2
+ field @FlaggedApi("com.android.ranging.flags.ranging_rtt_enabled") public static final int SUPPORTED_RX_CHAINS_3 = 3; // 0x3
+ field @FlaggedApi("com.android.ranging.flags.ranging_rtt_enabled") public static final int SUPPORTED_RX_CHAINS_4 = 4; // 0x4
+ field @FlaggedApi("com.android.ranging.flags.ranging_rtt_enabled") public static final int SUPPORTED_RX_CHAINS_UNSPECIFIED = 0; // 0x0
+ }
+
@FlaggedApi("com.android.wifi.flags.android_v_wifi_api") public final class ConfigRequest implements android.os.Parcelable {
method @FlaggedApi("com.android.wifi.flags.android_v_wifi_api") public int describeContents();
method @FlaggedApi("com.android.wifi.flags.android_v_wifi_api") @NonNull public java.util.List<android.net.wifi.OuiKeyedData> getVendorData();
@@ -1479,6 +1558,7 @@
}
public class DiscoverySessionCallback {
+ method @FlaggedApi("com.android.ranging.flags.ranging_rtt_enabled") public void onRangingResultsReceived(@NonNull java.util.List<android.net.wifi.rtt.RangingResult>);
method public void onSessionResumeFailed(int);
method public void onSessionResumeSucceeded();
method public void onSessionSuspendFailed(int);
@@ -1487,10 +1567,12 @@
public final class PublishConfig implements android.os.Parcelable {
method @FlaggedApi("com.android.wifi.flags.android_v_wifi_api") @NonNull public java.util.List<android.net.wifi.OuiKeyedData> getVendorData();
+ method @FlaggedApi("com.android.ranging.flags.ranging_rtt_enabled") public boolean isPeriodicRangingResultsEnabled();
method public boolean isSuspendable();
}
public static final class PublishConfig.Builder {
+ method @FlaggedApi("com.android.ranging.flags.ranging_rtt_enabled") @NonNull public android.net.wifi.aware.PublishConfig.Builder setPeriodicRangingResultsEnabled(boolean);
method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_WIFI_NETWORK_SELECTION) public android.net.wifi.aware.PublishConfig.Builder setSuspendable(boolean);
method @FlaggedApi("com.android.wifi.flags.android_v_wifi_api") @NonNull public android.net.wifi.aware.PublishConfig.Builder setVendorData(@NonNull java.util.List<android.net.wifi.OuiKeyedData>);
}
@@ -1500,11 +1582,35 @@
}
public final class SubscribeConfig implements android.os.Parcelable {
+ method @FlaggedApi("com.android.ranging.flags.ranging_rtt_enabled") @IntRange(from=0) public int getCenterFreq0Mhz();
+ method @FlaggedApi("com.android.ranging.flags.ranging_rtt_enabled") @IntRange(from=0) public int getCenterFreq1Mhz();
+ method @FlaggedApi("com.android.ranging.flags.ranging_rtt_enabled") public int getChannelWidth();
+ method @FlaggedApi("com.android.ranging.flags.ranging_rtt_enabled") @IntRange(from=0) public int getFrequencyMhz();
+ method @FlaggedApi("com.android.ranging.flags.ranging_rtt_enabled") public int getPeriodicRangingInterval();
+ method @FlaggedApi("com.android.ranging.flags.ranging_rtt_enabled") public int getPreamble();
+ method @FlaggedApi("com.android.ranging.flags.ranging_rtt_enabled") public int getRttBurstSize();
method @FlaggedApi("com.android.wifi.flags.android_v_wifi_api") @NonNull public java.util.List<android.net.wifi.OuiKeyedData> getVendorData();
+ method @FlaggedApi("com.android.ranging.flags.ranging_rtt_enabled") public boolean isPeriodicRangingEnabled();
method public boolean isSuspendable();
+ field @FlaggedApi("com.android.ranging.flags.ranging_rtt_enabled") public static final int PERIODIC_RANGING_INTERVAL_1024TU = 1024; // 0x400
+ field @FlaggedApi("com.android.ranging.flags.ranging_rtt_enabled") public static final int PERIODIC_RANGING_INTERVAL_128TU = 128; // 0x80
+ field @FlaggedApi("com.android.ranging.flags.ranging_rtt_enabled") public static final int PERIODIC_RANGING_INTERVAL_2048TU = 2048; // 0x800
+ field @FlaggedApi("com.android.ranging.flags.ranging_rtt_enabled") public static final int PERIODIC_RANGING_INTERVAL_256TU = 256; // 0x100
+ field @FlaggedApi("com.android.ranging.flags.ranging_rtt_enabled") public static final int PERIODIC_RANGING_INTERVAL_4096TU = 4096; // 0x1000
+ field @FlaggedApi("com.android.ranging.flags.ranging_rtt_enabled") public static final int PERIODIC_RANGING_INTERVAL_512TU = 512; // 0x200
+ field @FlaggedApi("com.android.ranging.flags.ranging_rtt_enabled") public static final int PERIODIC_RANGING_INTERVAL_8192TU = 8192; // 0x2000
+ field @FlaggedApi("com.android.ranging.flags.ranging_rtt_enabled") public static final int PERIODIC_RANGING_INTERVAL_NONE = 0; // 0x0
}
public static final class SubscribeConfig.Builder {
+ method @FlaggedApi("com.android.ranging.flags.ranging_rtt_enabled") @NonNull public android.net.wifi.aware.SubscribeConfig.Builder setCenterFreq0Mhz(@IntRange(from=0) int);
+ method @FlaggedApi("com.android.ranging.flags.ranging_rtt_enabled") @NonNull public android.net.wifi.aware.SubscribeConfig.Builder setCenterFreq1Mhz(@IntRange(from=0) int);
+ method @FlaggedApi("com.android.ranging.flags.ranging_rtt_enabled") @NonNull public android.net.wifi.aware.SubscribeConfig.Builder setChannelWidth(int);
+ method @FlaggedApi("com.android.ranging.flags.ranging_rtt_enabled") @NonNull public android.net.wifi.aware.SubscribeConfig.Builder setFrequencyMhz(@IntRange(from=0) int);
+ method @FlaggedApi("com.android.ranging.flags.ranging_rtt_enabled") @NonNull public android.net.wifi.aware.SubscribeConfig.Builder setPeriodicRangingEnabled(boolean);
+ method @FlaggedApi("com.android.ranging.flags.ranging_rtt_enabled") @NonNull public android.net.wifi.aware.SubscribeConfig.Builder setPeriodicRangingInterval(int);
+ method @FlaggedApi("com.android.ranging.flags.ranging_rtt_enabled") @NonNull public android.net.wifi.aware.SubscribeConfig.Builder setPreamble(int);
+ method @FlaggedApi("com.android.ranging.flags.ranging_rtt_enabled") @NonNull public android.net.wifi.aware.SubscribeConfig.Builder setRttBurstSize(int);
method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_WIFI_NETWORK_SELECTION) public android.net.wifi.aware.SubscribeConfig.Builder setSuspendable(boolean);
method @FlaggedApi("com.android.wifi.flags.android_v_wifi_api") @NonNull public android.net.wifi.aware.SubscribeConfig.Builder setVendorData(@NonNull java.util.List<android.net.wifi.OuiKeyedData>);
}
@@ -1779,3 +1885,148 @@
}
+package android.net.wifi.usd {
+
+ @FlaggedApi("android.net.wifi.flags.usd") public final class Characteristics implements android.os.Parcelable {
+ method public int describeContents();
+ method public int getMaxMatchFilterLength();
+ method public int getMaxNumberOfPublishSessions();
+ method public int getMaxNumberOfSubscribeSessions();
+ method public int getMaxServiceNameLength();
+ method public int getMaxServiceSpecificInfoLength();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.usd.Characteristics> CREATOR;
+ }
+
+ @FlaggedApi("android.net.wifi.flags.usd") public abstract class Config {
+ method @Nullable public int[] getOperatingFrequenciesMhz();
+ method @NonNull public java.util.List<byte[]> getRxMatchFilter();
+ method @NonNull public byte[] getServiceName();
+ method public int getServiceProtoType();
+ method @Nullable public byte[] getServiceSpecificInfo();
+ method @IntRange(from=0) public int getTtlSeconds();
+ method @NonNull public java.util.List<byte[]> getTxMatchFilter();
+ field public static final int SERVICE_PROTO_TYPE_CSA_MATTER = 1; // 0x1
+ field public static final int SERVICE_PROTO_TYPE_GENERIC = 0; // 0x0
+ field public static final int SUBSCRIBE_TYPE_ACTIVE = 1; // 0x1
+ field public static final int SUBSCRIBE_TYPE_PASSIVE = 0; // 0x0
+ field public static final int TRANSMISSION_TYPE_MULTICAST = 1; // 0x1
+ field public static final int TRANSMISSION_TYPE_UNICAST = 0; // 0x0
+ }
+
+ @FlaggedApi("android.net.wifi.flags.usd") public class DiscoveryResult {
+ method public int getPeerId();
+ method public int getServiceProtoType();
+ method @Nullable public byte[] getServiceSpecificInfo();
+ method public boolean isFsdEnabled();
+ }
+
+ @FlaggedApi("android.net.wifi.flags.usd") public static final class DiscoveryResult.Builder {
+ ctor public DiscoveryResult.Builder(int);
+ method @NonNull public android.net.wifi.usd.DiscoveryResult build();
+ method @NonNull public android.net.wifi.usd.DiscoveryResult.Builder setFsdEnabled(boolean);
+ method @NonNull public android.net.wifi.usd.DiscoveryResult.Builder setServiceProtoType(int);
+ method @NonNull public android.net.wifi.usd.DiscoveryResult.Builder setServiceSpecificInfo(@NonNull byte[]);
+ }
+
+ @FlaggedApi("android.net.wifi.flags.usd") public final class PublishConfig extends android.net.wifi.usd.Config implements android.os.Parcelable {
+ method public int describeContents();
+ method @IntRange(from=0) public int getAnnouncementPeriodMillis();
+ method public int getSolicitedTransmissionType();
+ method public boolean isEventsEnabled();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.usd.PublishConfig> CREATOR;
+ }
+
+ public static final class PublishConfig.Builder {
+ ctor public PublishConfig.Builder(@NonNull String);
+ method @NonNull public android.net.wifi.usd.PublishConfig build();
+ method @NonNull public android.net.wifi.usd.PublishConfig.Builder setAnnouncementPeriodMillis(@IntRange(from=0) int);
+ method @NonNull public android.net.wifi.usd.PublishConfig.Builder setEventsEnabled(boolean);
+ method @NonNull public android.net.wifi.usd.PublishConfig.Builder setOperatingFrequenciesMhz(@NonNull int[]);
+ method @NonNull public android.net.wifi.usd.PublishConfig.Builder setRxMatchFilter(@NonNull java.util.List<byte[]>);
+ method @NonNull public android.net.wifi.usd.PublishConfig.Builder setServiceProtoType(int);
+ method @NonNull public android.net.wifi.usd.PublishConfig.Builder setServiceSpecificInfo(@NonNull byte[]);
+ method @NonNull public android.net.wifi.usd.PublishConfig.Builder setSolicitedTransmissionType(int);
+ method @NonNull public android.net.wifi.usd.PublishConfig.Builder setTtlSeconds(@IntRange(from=0) int);
+ method @NonNull public android.net.wifi.usd.PublishConfig.Builder setTxMatchFilter(@NonNull java.util.List<byte[]>);
+ }
+
+ @FlaggedApi("android.net.wifi.flags.usd") public class PublishSession {
+ method @RequiresPermission(android.Manifest.permission.MANAGE_WIFI_NETWORK_SELECTION) public void cancel();
+ method @RequiresPermission(android.Manifest.permission.MANAGE_WIFI_NETWORK_SELECTION) public void sendMessage(int, @NonNull byte[], @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
+ method @RequiresPermission(android.Manifest.permission.MANAGE_WIFI_NETWORK_SELECTION) public void updatePublish(@NonNull byte[]);
+ }
+
+ @FlaggedApi("android.net.wifi.flags.usd") public class PublishSessionCallback extends android.net.wifi.usd.SessionCallback {
+ ctor public PublishSessionCallback();
+ method public void onPublishFailed(int);
+ method public void onPublishReplied(@NonNull android.net.wifi.usd.DiscoveryResult);
+ method public void onPublishStarted(@NonNull android.net.wifi.usd.PublishSession);
+ }
+
+ @FlaggedApi("android.net.wifi.flags.usd") public abstract class SessionCallback {
+ ctor public SessionCallback();
+ method public void onMessageReceived(int, @Nullable byte[]);
+ method public void onSessionTerminated(int);
+ field public static final int FAILURE_MAX_SESSIONS_REACHED = 3; // 0x3
+ field public static final int FAILURE_NOT_AVAILABLE = 2; // 0x2
+ field public static final int FAILURE_TIMEOUT = 1; // 0x1
+ field public static final int FAILURE_UNKNOWN = 0; // 0x0
+ field public static final int TERMINATION_REASON_NOT_AVAILABLE = 1; // 0x1
+ field public static final int TERMINATION_REASON_UNKNOWN = 0; // 0x0
+ field public static final int TERMINATION_REASON_USER_INITIATED = 2; // 0x2
+ }
+
+ @FlaggedApi("android.net.wifi.flags.usd") public final class SubscribeConfig extends android.net.wifi.usd.Config implements android.os.Parcelable {
+ method public int describeContents();
+ method @IntRange(from=0) public int getQueryPeriodMillis();
+ method @Nullable public int[] getRecommendedOperatingFrequenciesMhz();
+ method public int getSubscribeType();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.usd.SubscribeConfig> CREATOR;
+ }
+
+ @FlaggedApi("android.net.wifi.flags.usd") public static final class SubscribeConfig.Builder {
+ ctor public SubscribeConfig.Builder(@NonNull String);
+ method @NonNull public android.net.wifi.usd.SubscribeConfig build();
+ method @NonNull public android.net.wifi.usd.SubscribeConfig.Builder setOperatingFrequenciesMhz(@NonNull int[]);
+ method @NonNull public android.net.wifi.usd.SubscribeConfig.Builder setQueryPeriodMillis(@IntRange(from=0) int);
+ method @NonNull public android.net.wifi.usd.SubscribeConfig.Builder setRecommendedOperatingFrequenciesMhz(@NonNull int[]);
+ method @NonNull public android.net.wifi.usd.SubscribeConfig.Builder setRxMatchFilter(@NonNull java.util.List<byte[]>);
+ method @NonNull public android.net.wifi.usd.SubscribeConfig.Builder setServiceProtoType(int);
+ method @NonNull public android.net.wifi.usd.SubscribeConfig.Builder setServiceSpecificInfo(@NonNull byte[]);
+ method @NonNull public android.net.wifi.usd.SubscribeConfig.Builder setSubscribeType(int);
+ method @NonNull public android.net.wifi.usd.SubscribeConfig.Builder setTtlSeconds(@IntRange(from=0) int);
+ method @NonNull public android.net.wifi.usd.SubscribeConfig.Builder setTxMatchFilter(@NonNull java.util.List<byte[]>);
+ }
+
+ @FlaggedApi("android.net.wifi.flags.usd") public class SubscribeSession {
+ method @RequiresPermission(android.Manifest.permission.MANAGE_WIFI_NETWORK_SELECTION) public void cancel();
+ method @RequiresPermission(android.Manifest.permission.MANAGE_WIFI_NETWORK_SELECTION) public void sendMessage(int, @NonNull byte[], @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
+ }
+
+ @FlaggedApi("android.net.wifi.flags.usd") public class SubscribeSessionCallback extends android.net.wifi.usd.SessionCallback {
+ ctor public SubscribeSessionCallback();
+ method public void onServiceDiscovered(@NonNull android.net.wifi.usd.DiscoveryResult);
+ method public void onSubscribeFailed(int);
+ method public void onSubscribeStarted(@NonNull android.net.wifi.usd.SubscribeSession);
+ }
+
+ @FlaggedApi("android.net.wifi.flags.usd") public class UsdManager {
+ method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_WIFI_NETWORK_SELECTION) public android.net.wifi.usd.Characteristics getCharacteristics();
+ method @RequiresPermission(android.Manifest.permission.MANAGE_WIFI_NETWORK_SELECTION) public boolean isPublisherAvailable();
+ method @RequiresPermission(android.Manifest.permission.MANAGE_WIFI_NETWORK_SELECTION) public boolean isSubscriberAvailable();
+ method @RequiresPermission(android.Manifest.permission.MANAGE_WIFI_NETWORK_SELECTION) public void publish(@NonNull android.net.wifi.usd.PublishConfig, @NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.usd.PublishSessionCallback);
+ method @RequiresPermission(android.Manifest.permission.MANAGE_WIFI_NETWORK_SELECTION) public void registerAvailabilityCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.usd.UsdManager.AvailabilityCallback);
+ method @RequiresPermission(android.Manifest.permission.MANAGE_WIFI_NETWORK_SELECTION) public void subscribe(@NonNull android.net.wifi.usd.SubscribeConfig, @NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.usd.SubscribeSessionCallback);
+ method @RequiresPermission(android.Manifest.permission.MANAGE_WIFI_NETWORK_SELECTION) public void unregisterAvailabilityCallback(@NonNull android.net.wifi.usd.UsdManager.AvailabilityCallback);
+ }
+
+ public static interface UsdManager.AvailabilityCallback {
+ method public default void onPublisherAvailable();
+ method public default void onSubscriberAvailable();
+ }
+
+}
+
diff --git a/framework/jarjar-rules.txt b/framework/jarjar-rules.txt
index 598c014..dbd5811 100644
--- a/framework/jarjar-rules.txt
+++ b/framework/jarjar-rules.txt
@@ -86,6 +86,10 @@
rule android.util.LocalLog* com.android.wifi.x.@0
rule android.util.Rational* com.android.wifi.x.@0
+# Statically included ranging flags.
+rule com.android.ranging.flags.Flags com.android.wifi.x.@0
+rule com.android.ranging.flags.*Flags* com.android.wifi.x.@0
+
# Repackage generated flag classes.
# Need to specify the rule on classes to avoid transform the literals
rule com.android.wifi.flags.*FeatureFlags* com.android.wifi.x.@0
@@ -96,6 +100,10 @@
rule android.net.wifi.flags.FeatureFlags* com.android.wifi.x.@0
rule android.net.wifi.flags.Flags com.android.wifi.x.@0
+rule android.security.*FeatureFlags* com.android.wifi.x.@0
+rule android.security.FeatureFlags* com.android.wifi.x.@0
+rule android.security.Flags com.android.wifi.x.@0
+
# Use our statically linked bouncy castle library
rule org.bouncycastle.** com.android.wifi.x.@0
# Use our statically linked protobuf library
diff --git a/framework/java/android/net/wifi/BaseWifiService.java b/framework/java/android/net/wifi/BaseWifiService.java
deleted file mode 100644
index 0d3ae0a..0000000
--- a/framework/java/android/net/wifi/BaseWifiService.java
+++ /dev/null
@@ -1,1223 +0,0 @@
-/*
- * Copyright (c) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.wifi;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.net.DhcpInfo;
-import android.net.DhcpOption;
-import android.net.Network;
-import android.net.TetheringManager;
-import android.net.wifi.hotspot2.IProvisioningCallback;
-import android.net.wifi.hotspot2.OsuProvider;
-import android.net.wifi.hotspot2.PasspointConfiguration;
-import android.net.wifi.twt.TwtRequest;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.os.WorkSource;
-
-import com.android.modules.utils.ParceledListSlice;
-import com.android.modules.utils.StringParceledListSlice;
-
-import java.util.List;
-import java.util.Map;
-
-/**
- * Empty concrete class implementing IWifiManager with stub methods throwing runtime exceptions.
- *
- * This class is meant to be extended by real implementations of IWifiManager in order to facilitate
- * cross-repo changes to WiFi internal APIs, including the introduction of new APIs, the removal of
- * deprecated APIs, or the migration of existing API signatures.
- *
- * When an existing API is scheduled for removal, it can be removed from IWifiManager.aidl
- * immediately and marked as @Deprecated first in this class. Children inheriting this class are
- * then given a short grace period to update themselves before the @Deprecated stub is removed for
- * good. If the API scheduled for removal has a replacement or an overload (signature change),
- * these should be introduced before the stub is removed to allow children to migrate.
- *
- * When a new API is added to IWifiManager.aidl, a stub should be added in BaseWifiService as
- * well otherwise compilation will fail.
- *
- * @hide
- */
-public class BaseWifiService extends IWifiManager.Stub {
-
- private static final String TAG = BaseWifiService.class.getSimpleName();
-
- @Override
- public long getSupportedFeatures() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void getWifiActivityEnergyInfoAsync(IOnWifiActivityEnergyInfoListener listener) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public ParceledListSlice getConfiguredNetworks(String packageName, String featureId,
- boolean callerNetworksOnly) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public ParceledListSlice getPrivilegedConfiguredNetworks(String packageName, String featureId,
- Bundle extras) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public WifiConfiguration getPrivilegedConnectedNetwork(
- String packageName, String featureId, Bundle extras) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void setNetworkSelectionConfig(WifiNetworkSelectionConfig nsConfig) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void getNetworkSelectionConfig(@NonNull IWifiNetworkSelectionConfigListener listener) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void setThirdPartyAppEnablingWifiConfirmationDialogEnabled(boolean enable) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public boolean isThirdPartyAppEnablingWifiConfirmationDialogEnabled() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void setScreenOnScanSchedule(int[] scanScheduleSeconds, int[] scanType) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void setOneShotScreenOnConnectivityScanDelayMillis(int delayMs) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public Map<String, Map<Integer, List<ScanResult>>> getAllMatchingFqdnsForScanResults(
- List<ScanResult> scanResults) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void setSsidsAllowlist(String packageName, ParceledListSlice<WifiSsid> ssids) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public ParceledListSlice<WifiSsid> getSsidsAllowlist(String packageName) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public Map<OsuProvider, List<ScanResult>> getMatchingOsuProviders(
- ParceledListSlice<ScanResult> scanResults) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public Map<OsuProvider, PasspointConfiguration> getMatchingPasspointConfigsForOsuProviders(
- ParceledListSlice<OsuProvider> osuProviders) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public int addOrUpdateNetwork(WifiConfiguration config, String packageName, Bundle extras) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public WifiManager.AddNetworkResult addOrUpdateNetworkPrivileged(WifiConfiguration config,
- String packageName) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public boolean addOrUpdatePasspointConfiguration(
- PasspointConfiguration config, String packageName) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public boolean removePasspointConfiguration(String fqdn, String packageName) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public ParceledListSlice<PasspointConfiguration> getPasspointConfigurations(
- String packageName) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public ParceledListSlice<WifiConfiguration> getWifiConfigsForPasspointProfiles(
- StringParceledListSlice fqdnList) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void queryPasspointIcon(long bssid, String fileName) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public int matchProviderWithCurrentNetwork(String fqdn) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public boolean removeNetwork(int netId, String packageName) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public boolean removeNonCallerConfiguredNetworks(String packageName) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public boolean enableNetwork(int netId, boolean disableOthers, String packageName) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public boolean disableNetwork(int netId, String packageName) {
- throw new UnsupportedOperationException();
- }
-
- /** TO BE REMOVED */
- public void allowAutojoinGlobal(boolean choice) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void allowAutojoinGlobal(boolean choice, String packageName, Bundle extras) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void queryAutojoinGlobal(@NonNull IBooleanListener listener) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void allowAutojoin(int netId, boolean choice) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void allowAutojoinPasspoint(String fqdn, boolean enableAutoJoin) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void getBssidBlocklist(ParceledListSlice<WifiSsid> ssids,
- IMacAddressListListener listener) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void setMacRandomizationSettingPasspointEnabled(String fqdn, boolean enable) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void setPasspointMeteredOverride(String fqdn, int meteredOverride) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public boolean startScan(String packageName, String featureId) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public ParceledListSlice getScanResults(String callingPackage, String callingFeatureId) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void getChannelData(@NonNull IListListener listener, String packageName,
- Bundle extras) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public boolean disconnect(String packageName) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public boolean reconnect(String packageName) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public boolean reassociate(String packageName) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public WifiInfo getConnectionInfo(String callingPackage, String callingFeatureId) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public boolean setWifiEnabled(String packageName, boolean enable) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void registerSubsystemRestartCallback(ISubsystemRestartCallback callback) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void unregisterSubsystemRestartCallback(ISubsystemRestartCallback callback) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void addWifiNetworkStateChangedListener(IWifiNetworkStateChangedListener listener) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void removeWifiNetworkStateChangedListener(IWifiNetworkStateChangedListener listener) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void restartWifiSubsystem() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public int getWifiEnabledState() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void registerDriverCountryCodeChangedListener(
- @NonNull IOnWifiDriverCountryCodeChangedListener listener,
- @Nullable String packageName, @Nullable String featureId) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void unregisterDriverCountryCodeChangedListener(
- @NonNull IOnWifiDriverCountryCodeChangedListener listener) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public String getCountryCode(String packageName, String featureId) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void setOverrideCountryCode(@NonNull String countryCode) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void clearOverrideCountryCode() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void setDefaultCountryCode(@NonNull String countryCode) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public boolean is24GHzBandSupported() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public boolean is5GHzBandSupported() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public boolean is6GHzBandSupported() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public boolean is60GHzBandSupported() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public boolean isWifiStandardSupported(int standard) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public DhcpInfo getDhcpInfo(String packageName) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void setScanAlwaysAvailable(boolean isAvailable, String packageName) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public boolean isScanAlwaysAvailable() {
- throw new UnsupportedOperationException();
- }
-
- /**
- * Following method is deprecated with
- * {@link BaseWifiService#acquireWifiLock(IBinder, int, String, WorkSource, String, Bundle)}
- * @deprecated This is no longer supported.
- */
- @Deprecated
- public boolean acquireWifiLock(IBinder lock, int lockType, String tag, WorkSource ws) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public boolean acquireWifiLock(IBinder lock, int lockType, String tag, WorkSource ws,
- String packageName, Bundle extras) {
- throw new UnsupportedOperationException();
- }
-
- /**
- * Following method is deprecated with
- * {@link BaseWifiService#updateWifiLockWorkSource(IBinder, WorkSource, String, Bundle)}
- * @deprecated This is no longer supported.
- */
- @Deprecated
- public void updateWifiLockWorkSource(IBinder lock, WorkSource ws) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void updateWifiLockWorkSource(IBinder lock, WorkSource ws, String packageName,
- Bundle extras) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public boolean releaseWifiLock(IBinder lock) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void initializeMulticastFiltering() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public boolean isMulticastEnabled() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void acquireMulticastLock(IBinder binder, String tag) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void releaseMulticastLock(String tag) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void updateInterfaceIpState(String ifaceName, int mode) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public boolean isDefaultCoexAlgorithmEnabled() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void setCoexUnsafeChannels(List<CoexUnsafeChannel> unsafeChannels, int restrictions) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void registerCoexCallback(ICoexCallback callback) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void unregisterCoexCallback(ICoexCallback callback) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public boolean startSoftAp(WifiConfiguration wifiConfig, String packageName) {
- throw new UnsupportedOperationException();
- }
-
- /**
- * Following method is deprecated with
- * {@link #startTetheredHotspotRequest(TetheringManager.TetheringRequest, String)}
- * @deprecated This is no longer supported.
- */
- @Deprecated
- @Override
- public boolean startTetheredHotspot(SoftApConfiguration softApConfig, String packageName) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void startTetheredHotspotRequest(TetheringManager.TetheringRequest request,
- ISoftApCallback callback, String packageName) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public boolean stopSoftAp() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public boolean validateSoftApConfiguration(SoftApConfiguration config) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public int startLocalOnlyHotspot(ILocalOnlyHotspotCallback callback, String packageName,
- String featureId, SoftApConfiguration customConfig, Bundle extras) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void stopLocalOnlyHotspot() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void registerLocalOnlyHotspotSoftApCallback(ISoftApCallback callback, Bundle extras) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void unregisterLocalOnlyHotspotSoftApCallback(ISoftApCallback callback, Bundle extras) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void startWatchLocalOnlyHotspot(ILocalOnlyHotspotCallback callback) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void stopWatchLocalOnlyHotspot() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public int getWifiApEnabledState() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public WifiConfiguration getWifiApConfiguration() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public SoftApConfiguration getSoftApConfiguration() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void queryLastConfiguredTetheredApPassphraseSinceBoot(IStringListener listener) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public boolean setWifiApConfiguration(WifiConfiguration wifiConfig, String packageName) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public boolean setSoftApConfiguration(SoftApConfiguration softApConfig, String packageName) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void notifyUserOfApBandConversion(String packageName) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void enableTdls(String remoteIPAddress, boolean enable) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void enableTdlsWithRemoteIpAddress(String remoteIPAddress, boolean enable,
- @NonNull IBooleanListener listener) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void enableTdlsWithMacAddress(String remoteMacAddress, boolean enable) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void enableTdlsWithRemoteMacAddress(String remoteMacAddress, boolean enable,
- @NonNull IBooleanListener listener) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void isTdlsOperationCurrentlyAvailable(@NonNull IBooleanListener listener) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void getMaxSupportedConcurrentTdlsSessions(@NonNull IIntegerListener listener) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void getNumberOfEnabledTdlsSessions(@NonNull IIntegerListener listener) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public String getCurrentNetworkWpsNfcConfigurationToken() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void enableVerboseLogging(int verbose) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public int getVerboseLoggingLevel() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void disableEphemeralNetwork(String SSID, String packageName) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void factoryReset(String packageName) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public Network getCurrentNetwork() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void retrieveWifiBackupData(@NonNull IByteArrayListener listener) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void restoreWifiBackupData(byte[] data) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public byte[] retrieveBackupData() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void restoreBackupData(byte[] data) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public byte[] retrieveSoftApBackupData() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public SoftApConfiguration restoreSoftApBackupData(byte[] data) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void restoreSupplicantBackupData(byte[] supplicantData, byte[] ipConfigData) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void startSubscriptionProvisioning(
- OsuProvider provider, IProvisioningCallback callback) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void addWifiVerboseLoggingStatusChangedListener(
- IWifiVerboseLoggingStatusChangedListener callback) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void removeWifiVerboseLoggingStatusChangedListener(
- IWifiVerboseLoggingStatusChangedListener callback) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void registerSoftApCallback(ISoftApCallback callback) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void unregisterSoftApCallback(ISoftApCallback callback) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void registerTrafficStateCallback(ITrafficStateCallback callback) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void unregisterTrafficStateCallback(ITrafficStateCallback callback) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void registerNetworkRequestMatchCallback(INetworkRequestMatchCallback callback) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void unregisterNetworkRequestMatchCallback(INetworkRequestMatchCallback callback) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public int addNetworkSuggestions(
- ParceledListSlice<WifiNetworkSuggestion> networkSuggestions, String callingPackageName,
- String callingFeatureId) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public int removeNetworkSuggestions(
- ParceledListSlice<WifiNetworkSuggestion> networkSuggestions, String callingPackageName,
- int action) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public ParceledListSlice<WifiNetworkSuggestion> getNetworkSuggestions(String packageName) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void setCarrierNetworkOffloadEnabled(int subId, boolean merged, boolean enabled)
- throws RemoteException {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public boolean isCarrierNetworkOffloadEnabled(int subId, boolean merged)
- throws RemoteException {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public String[] getFactoryMacAddresses() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void setDeviceMobilityState(int state) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void startDppAsConfiguratorInitiator(IBinder binder, String packageName,
- String enrolleeUri, int selectedNetworkId, int netRole, IDppCallback callback) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void startDppAsEnrolleeInitiator(IBinder binder, String configuratorUri,
- IDppCallback callback) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void startDppAsEnrolleeResponder(IBinder binder, String deviceInfo,
- int curve, IDppCallback callback) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void stopDppSession() throws RemoteException {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void addOnWifiUsabilityStatsListener(IOnWifiUsabilityStatsListener listener) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void removeOnWifiUsabilityStatsListener(IOnWifiUsabilityStatsListener listener) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void updateWifiUsabilityScore(int seqNum, int score, int predictionHorizonSec) {
- throw new UnsupportedOperationException();
- }
-
- /** TO BE REMOVED */
- public void connect(WifiConfiguration config, int netId, IActionListener callback) {
- throw new UnsupportedOperationException();
- }
-
- /** TO BE REMOVED */
- public void connect(WifiConfiguration config, int netId, IActionListener callback,
- @NonNull String packageName) {
- throw new UnsupportedOperationException();
- }
- @Override
- public void connect(WifiConfiguration config, int netId, IActionListener callback,
- @NonNull String packageName, Bundle extras) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void startRestrictingAutoJoinToSubscriptionId(int subId) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void stopRestrictingAutoJoinToSubscriptionId() {
- throw new UnsupportedOperationException();
- }
-
- /** TO BE REMOVED */
- public void save(WifiConfiguration config, IActionListener callback) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void save(WifiConfiguration config, IActionListener callback,
- @NonNull String packageName) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void forget(int netId, IActionListener callback) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void registerScanResultsCallback(IScanResultsCallback callback) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void unregisterScanResultsCallback(IScanResultsCallback callback) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void registerSuggestionConnectionStatusListener(
- ISuggestionConnectionStatusListener listener, String packageName, String featureId) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void unregisterSuggestionConnectionStatusListener(
- ISuggestionConnectionStatusListener listener, String packageName) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public int calculateSignalLevel(int rssi) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void setPnoScanEnabled(boolean enabled, boolean enablePnoScanAfterWifiToggle,
- String packageName) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public ParceledListSlice<WifiConfiguration>
- getWifiConfigForMatchedNetworkSuggestionsSharedWithUser(
- ParceledListSlice<ScanResult> scanResults) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void setExternalPnoScanRequest(@NonNull IBinder binder,
- @NonNull IPnoScanResultsCallback callback,
- @NonNull List<WifiSsid> ssids, @NonNull int[] frequencies,
- @NonNull String packageName, @NonNull String featureId) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void clearExternalPnoScanRequest() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void getLastCallerInfoForApi(int apiType, @NonNull ILastCallerListener listener) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public boolean setWifiConnectedNetworkScorer(IBinder binder,
- IWifiConnectedNetworkScorer scorer) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void clearWifiConnectedNetworkScorer() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public Map<WifiNetworkSuggestion, List<ScanResult>> getMatchingScanResults(
- ParceledListSlice<WifiNetworkSuggestion> networkSuggestions,
- ParceledListSlice<ScanResult> scanResults,
- String callingPackage, String callingFeatureId) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void setScanThrottleEnabled(boolean enable) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public boolean isScanThrottleEnabled() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public Map<String, Map<Integer, List<ScanResult>>>
- getAllMatchingPasspointProfilesForScanResults(
- ParceledListSlice<ScanResult> scanResults) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void setAutoWakeupEnabled(boolean enable) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public boolean isAutoWakeupEnabled() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void addSuggestionUserApprovalStatusListener(
- ISuggestionUserApprovalStatusListener listener, String packageName) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void removeSuggestionUserApprovalStatusListener(
- ISuggestionUserApprovalStatusListener listener, String packageName) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void setEmergencyScanRequestInProgress(boolean inProgress) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void removeAppState(int targetAppUid, @NonNull String targetAppPackageName) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public boolean setWifiScoringEnabled(boolean enabled) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void flushPasspointAnqpCache(@NonNull String packageName) {
- throw new UnsupportedOperationException();
- }
-
- /** TO BE REMOVED */
- public List<WifiAvailableChannel> getUsableChannels(
- int band, int mode, int filter) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public List<WifiAvailableChannel> getUsableChannels(
- int band, int mode, int filter, String packageName, Bundle extras) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public boolean isWifiPasspointEnabled() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void setWifiPasspointEnabled(boolean enabled) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public @WifiManager.WifiMultiInternetMode int getStaConcurrencyForMultiInternetMode() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public boolean setStaConcurrencyForMultiInternetMode(
- @WifiManager.WifiMultiInternetMode int mode) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void notifyMinimumRequiredWifiSecurityLevelChanged(int level) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void notifyWifiSsidPolicyChanged(int policyType,
- @NonNull ParceledListSlice<WifiSsid> ssids) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public String[] getOemPrivilegedWifiAdminPackages() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void replyToP2pInvitationReceivedDialog(
- int dialogId, boolean accepted, @Nullable String optionalPin) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void replyToSimpleDialog(int dialogId, int button) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void addCustomDhcpOptions(WifiSsid ssid, byte[] oui,
- @NonNull ParceledListSlice<DhcpOption> options) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void removeCustomDhcpOptions(WifiSsid ssid, byte[] oui) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void reportCreateInterfaceImpact(String packageName, int interfaceType,
- boolean requireNewInterface, IInterfaceCreationInfoCallback callback) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public int getMaxNumberOfChannelsPerRequest() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void addQosPolicies(@NonNull ParceledListSlice<QosPolicyParams> policyParamsList,
- @NonNull IBinder binder, @NonNull String packageName, @NonNull IListListener listener) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void removeQosPolicies(@NonNull int[] policyIdList, @NonNull String packageName) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void removeAllQosPolicies(@NonNull String packageName) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void addLocalOnlyConnectionStatusListener(ILocalOnlyConnectionStatusListener listener,
- String packageName, String featureId) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void removeLocalOnlyConnectionStatusListener(ILocalOnlyConnectionStatusListener listener,
- String packageName) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void setLinkLayerStatsPollingInterval(int intervalMs) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void getLinkLayerStatsPollingInterval(@NonNull IIntegerListener listener) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void setMloMode(@WifiManager.MloMode int mode, IBooleanListener listener) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void getMloMode(IIntegerListener listener) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void addWifiLowLatencyLockListener(IWifiLowLatencyLockListener listener) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void removeWifiLowLatencyLockListener(IWifiLowLatencyLockListener listener) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void getMaxMloAssociationLinkCount(IIntegerListener listener, Bundle extras) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void getMaxMloStrLinkCount(IIntegerListener listener, Bundle extras) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void getSupportedSimultaneousBandCombinations(IWifiBandsListener listener,
- Bundle extras) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void setWepAllowed(boolean isAllowed) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void queryWepAllowed(@NonNull IBooleanListener listener) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void enableMscs(@NonNull MscsParams mscsParams) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void disableMscs() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void setSendDhcpHostnameRestriction(@NonNull String packageName,
- @WifiManager.SendDhcpHostnameRestriction int restriction) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void querySendDhcpHostnameRestriction(@NonNull String packageName,
- @NonNull IIntegerListener listener) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void setPerSsidRoamingMode(WifiSsid ssid, @WifiManager.RoamingMode int roamingMode,
- @NonNull String packageName) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void removePerSsidRoamingMode(WifiSsid ssid, @NonNull String packageName) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void getPerSsidRoamingModes(@NonNull String packageName, IMapListener listener) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void setupTwtSession(TwtRequest twtRequest, ITwtCallback iTwtCallback, Bundle extras) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void getTwtCapabilities(ITwtCapabilitiesListener listener, Bundle extras) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void getStatsTwtSession(int sessionId, ITwtStatsListener iTwtStatsListener,
- Bundle extras) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void teardownTwtSession(int sessionId, Bundle extras) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void setD2dAllowedWhenInfraStaDisabled(boolean isAllowed) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void queryD2dAllowedWhenInfraStaDisabled(@NonNull IBooleanListener listener) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public boolean isPnoSupported() {
- throw new UnsupportedOperationException();
- }
-}
diff --git a/framework/java/android/net/wifi/BlockingOption.java b/framework/java/android/net/wifi/BlockingOption.java
new file mode 100644
index 0000000..ee152d4
--- /dev/null
+++ b/framework/java/android/net/wifi/BlockingOption.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.FlaggedApi;
+import android.annotation.IntRange;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import androidx.annotation.NonNull;
+
+import com.android.wifi.flags.Flags;
+
+import java.util.Objects;
+
+/**
+ * Options for blocking a network through
+ * {@link WifiManager#disallowCurrentSuggestedNetwork(BlockingOption)}
+ */
+@FlaggedApi(Flags.FLAG_BSSID_BLOCKLIST_FOR_SUGGESTION)
+public final class BlockingOption implements Parcelable {
+ private final int mDisableTime;
+ private final boolean mBSSIDOnly;
+
+ /**
+ * @hide
+ */
+ public BlockingOption(int disableTime, boolean bssidOnly) {
+ mDisableTime = disableTime;
+ mBSSIDOnly = bssidOnly;
+ }
+
+ /**
+ * @hide
+ */
+ public BlockingOption(Parcel in) {
+ mDisableTime = in.readInt();
+ mBSSIDOnly = in.readBoolean();
+ }
+
+ /**
+ * Get the blocking time which is set by {@link Builder#Builder(int)}
+ * @return Blocking time in seconds
+ */
+ public int getBlockingTimeSeconds() {
+ return mDisableTime;
+ }
+
+ /**
+ * Return whether or not a single BSSID is being blocked, which is set by
+ * {@link Builder#setBlockingBssidOnly(boolean)}
+ * @return True for blocking single BSSID, false otherwise.
+ */
+ public boolean isBlockingBssidOnly() {
+ return mBSSIDOnly;
+ }
+
+ /**
+ * Builder used to create {@link BlockingOption} objects.
+ */
+ @FlaggedApi(Flags.FLAG_BSSID_BLOCKLIST_FOR_SUGGESTION)
+ public static final class Builder {
+ private int mDisableTime;
+ private boolean mBSSIDOnly;
+
+ /**
+ * Create a {@link Builder} with blocking time for the network
+ *
+ * @param blockingTimeSec Time period to block the network in seconds
+ * @throws IllegalArgumentException if input is invalid.
+ */
+ public Builder(@IntRange(from = 1, to = 86400) int blockingTimeSec) {
+ if (blockingTimeSec < 1 || blockingTimeSec > 86400) {
+ throw new IllegalArgumentException("blockingTimeSec should between 1 to 86400");
+ }
+ mDisableTime = blockingTimeSec;
+ mBSSIDOnly = false;
+ }
+
+ /**
+ * Set to configure blocking the whole network or a single BSSID. By default, the whole
+ * network will be blocked.
+ * @param bssidOnly True for a single BSSID, otherwise the whole network will be blocked
+ * @return Instance of {@link Builder} to enable chaining of the builder method.
+ */
+ @NonNull public Builder setBlockingBssidOnly(boolean bssidOnly) {
+ mBSSIDOnly = bssidOnly;
+ return this;
+ }
+
+ /**
+ * Create a BlockingOption object for use in
+ * {@link WifiManager#disallowCurrentSuggestedNetwork(BlockingOption)}.
+ */
+ @NonNull public BlockingOption build() {
+ return new BlockingOption(mDisableTime, mBSSIDOnly);
+ }
+ }
+
+ @NonNull
+ public static final Creator<BlockingOption> CREATOR = new Creator<BlockingOption>() {
+ @Override
+ public BlockingOption createFromParcel(Parcel in) {
+ return new BlockingOption(in);
+ }
+
+ @Override
+ public BlockingOption[] newArray(int size) {
+ return new BlockingOption[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeInt(mDisableTime);
+ dest.writeBoolean(mBSSIDOnly);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!(obj instanceof BlockingOption lhs)) {
+ return false;
+ }
+ return mBSSIDOnly == lhs.mBSSIDOnly && mDisableTime == lhs.mDisableTime;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mBSSIDOnly, mDisableTime);
+ }
+
+ @Override
+ public String toString() {
+ return "BlockingOption[ "
+ + "DisableTime=" + mDisableTime
+ + ", BSSIDOnly=" + mBSSIDOnly;
+ }
+}
diff --git a/framework/java/android/net/wifi/DeauthenticationReasonCode.java b/framework/java/android/net/wifi/DeauthenticationReasonCode.java
new file mode 100644
index 0000000..229ab45
--- /dev/null
+++ b/framework/java/android/net/wifi/DeauthenticationReasonCode.java
@@ -0,0 +1,283 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.FlaggedApi;
+import android.annotation.SystemApi;
+
+import com.android.wifi.flags.Flags;
+
+/**
+ * Defines integer constants for Soft AP deauthentication reason codes.
+ *
+ * <p>These reason codes provide information about why a client was disconnected from a Soft AP.
+ * Refer to Section 9.4.1.7 and Table 9-45 of the IEEE 802.11-2016 standard for more information.
+ * @hide
+ */
+@SystemApi
+@FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON)
+public final class DeauthenticationReasonCode {
+ /** Disconnected for an unknown reason. */
+ @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON)
+ public static final int REASON_UNKNOWN = 0;
+
+ /** Disconnected for an unspecified reason. */
+ @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON)
+ public static final int REASON_UNSPECIFIED = 1;
+
+ /** Disconnected because the previous authentication is no longer valid. */
+ @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON)
+ public static final int REASON_PREV_AUTH_NOT_VALID = 2;
+
+ /** Disconnected because the client is being de-authenticated. */
+ @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON)
+ public static final int REASON_DEAUTH_LEAVING = 3;
+
+ /** Disconnected due to inactivity. */
+ @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON)
+ public static final int REASON_DISASSOC_DUE_TO_INACTIVITY = 4;
+
+ /** Disconnected because the AP is unable to handle all currently associated stations. */
+ @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON)
+ public static final int REASON_DISASSOC_AP_BUSY = 5;
+
+ /** Disconnected because of a Class 2 frame received from a non-authenticated station. */
+ @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON)
+ public static final int REASON_CLASS2_FRAME_FROM_NONAUTH_STA = 6;
+
+ /** Disconnected because of a Class 3 frame received from a non-associated station. */
+ @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON)
+ public static final int REASON_CLASS3_FRAME_FROM_NONASSOC_STA = 7;
+
+ /** Disconnected because the STA has left the network. */
+ @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON)
+ public static final int REASON_DISASSOC_STA_HAS_LEFT = 8;
+
+ /** Disconnected because the STA requested association without authentication. */
+ @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON)
+ public static final int REASON_STA_REQ_ASSOC_WITHOUT_AUTH = 9;
+
+ /** Disconnected because the power capability element is not valid. */
+ @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON)
+ public static final int REASON_PWR_CAPABILITY_NOT_VALID = 10;
+
+ /** Disconnected because the supported channel element is not valid. */
+ @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON)
+ public static final int REASON_SUPPORTED_CHANNEL_NOT_VALID = 11;
+
+ /** Disconnected due to a BSS transition disassociation. */
+ @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON)
+ public static final int REASON_BSS_TRANSITION_DISASSOC = 12;
+
+ /** Disconnected because of an invalid information element. */
+ @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON)
+ public static final int REASON_INVALID_IE = 13;
+
+ /** Disconnected because of a message integrity code failure. */
+ @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON)
+ public static final int REASON_MICHAEL_MIC_FAILURE = 14;
+
+ /** Disconnected due to a four-way handshake timeout. */
+ @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON)
+ public static final int REASON_FOURWAY_HANDSHAKE_TIMEOUT = 15;
+
+ /** Disconnected due to a group key handshake timeout. */
+ @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON)
+ public static final int REASON_GROUP_KEY_UPDATE_TIMEOUT = 16;
+
+ /** Disconnected because an information element in the 4-way handshake differs. */
+ @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON)
+ public static final int REASON_IE_IN_4WAY_DIFFERS = 17;
+
+ /** Disconnected because the group cipher is not valid. */
+ @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON)
+ public static final int REASON_GROUP_CIPHER_NOT_VALID = 18;
+
+ /** Disconnected because the pairwise cipher is not valid. */
+ @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON)
+ public static final int REASON_PAIRWISE_CIPHER_NOT_VALID = 19;
+
+ /** Disconnected because the authentication and key management protocol is not valid. */
+ @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON)
+ public static final int REASON_AKMP_NOT_VALID = 20;
+
+ /** Disconnected because the robust security network IE version is not supported. */
+ @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON)
+ public static final int REASON_UNSUPPORTED_RSN_IE_VERSION = 21;
+
+ /** Disconnected because the robust security network IE capabilities are invalid. */
+ @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON)
+ public static final int REASON_INVALID_RSN_IE_CAPAB = 22;
+
+ /** Disconnected because the IEEE 802.1X authentication failed. */
+ @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON)
+ public static final int REASON_IEEE_802_1X_AUTH_FAILED = 23;
+
+ /** Disconnected because the cipher suite was rejected. */
+ @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON)
+ public static final int REASON_CIPHER_SUITE_REJECTED = 24;
+
+ /** Disconnected because the Tunneled Direct Link Setup teardown is unreachable. */
+ @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON)
+ public static final int REASON_TDLS_TEARDOWN_UNREACHABLE = 25;
+
+ /** Disconnected because of a Tunneled Direct Link Setup teardown for an unspecified reason. */
+ @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON)
+ public static final int REASON_TDLS_TEARDOWN_UNSPECIFIED = 26;
+
+ /** Disconnected because an session security protocol requested disassociation. */
+ @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON)
+ public static final int REASON_SSP_REQUESTED_DISASSOC = 27;
+
+ /** Disconnected because there is no session security protocol roaming agreement. */
+ @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON)
+ public static final int REASON_NO_SSP_ROAMING_AGREEMENT = 28;
+
+ /** Disconnected because of an unsupported cipher or authentication key management method. */
+ @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON)
+ public static final int REASON_BAD_CIPHER_OR_AKM = 29;
+
+ /** Disconnected because the client is not authorized at this location. */
+ @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON)
+ public static final int REASON_NOT_AUTHORIZED_THIS_LOCATION = 30;
+
+ /** Disconnected because a service change precludes traffic specification. */
+ @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON)
+ public static final int REASON_SERVICE_CHANGE_PRECLUDES_TS = 31;
+
+ /** Disconnected for an unspecified quality of service related reason. */
+ @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON)
+ public static final int REASON_UNSPECIFIED_QOS_REASON = 32;
+
+ /** Disconnected because there is not enough bandwidth. */
+ @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON)
+ public static final int REASON_NOT_ENOUGH_BANDWIDTH = 33;
+
+ /** Disconnected due to low acknowledgment rate. */
+ @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON)
+ public static final int REASON_DISASSOC_LOW_ACK = 34;
+
+ /** Disconnected for exceeding the transmission opportunity. */
+ @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON)
+ public static final int REASON_EXCEEDED_TXOP = 35;
+
+ /** Disconnected because the station is leaving the network. */
+ @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON)
+ public static final int REASON_STA_LEAVING = 36;
+
+ /** Disconnected because of the end of a traffic specification, block ack, or DLS session. */
+ @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON)
+ public static final int REASON_END_TS_BA_DLS = 37;
+
+ /** Disconnected because of an unknown traffic specification or block ack. */
+ @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON)
+ public static final int REASON_UNKNOWN_TS_BA = 38;
+
+ /** Disconnected due to a timeout. */
+ @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON)
+ public static final int REASON_TIMEOUT = 39;
+
+ /** Disconnected because of a peerkey mismatch. */
+ @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON)
+ public static final int REASON_PEERKEY_MISMATCH = 45;
+
+ /** Disconnected because the authorized access limit has been reached. */
+ @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON)
+ public static final int REASON_AUTHORIZED_ACCESS_LIMIT_REACHED = 46;
+
+ /** Disconnected due to external service requirements. */
+ @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON)
+ public static final int REASON_EXTERNAL_SERVICE_REQUIREMENTS = 47;
+
+ /** Disconnected because of an invalid fast transition action frame count. */
+ @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON)
+ public static final int REASON_INVALID_FT_ACTION_FRAME_COUNT = 48;
+
+ /** Disconnected because of an invalid pairwise master key identifier. */
+ @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON)
+ public static final int REASON_INVALID_PMKID = 49;
+
+ /** Disconnected because of an invalid management downlink endpoint. */
+ @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON)
+ public static final int REASON_INVALID_MDE = 50;
+
+ /** Disconnected because of an invalid fast transition endpoint. */
+ @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON)
+ public static final int REASON_INVALID_FTE = 51;
+
+ /** Disconnected because mesh peering was cancelled. */
+ @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON)
+ public static final int REASON_MESH_PEERING_CANCELLED = 52;
+
+ /** Disconnected because the maximum number of mesh peers has been reached. */
+ @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON)
+ public static final int REASON_MESH_MAX_PEERS = 53;
+
+ /** Disconnected because of a mesh configuration policy violation. */
+ @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON)
+ public static final int REASON_MESH_CONFIG_POLICY_VIOLATION = 54;
+
+ /** Disconnected because a mesh close message was received. */
+ @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON)
+ public static final int REASON_MESH_CLOSE_RCVD = 55;
+
+ /** Disconnected because the maximum number of mesh retries has been reached. */
+ @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON)
+ public static final int REASON_MESH_MAX_RETRIES = 56;
+
+ /** Disconnected due to a mesh confirmation timeout. */
+ @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON)
+ public static final int REASON_MESH_CONFIRM_TIMEOUT = 57;
+
+ /** Disconnected because of an invalid mesh group temporal key. */
+ @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON)
+ public static final int REASON_MESH_INVALID_GTK = 58;
+
+ /** Disconnected because of inconsistent mesh parameters. */
+ @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON)
+ public static final int REASON_MESH_INCONSISTENT_PARAMS = 59;
+
+ /** Disconnected because of an invalid mesh security capability. */
+ @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON)
+ public static final int REASON_MESH_INVALID_SECURITY_CAP = 60;
+
+ /** Disconnected because of a mesh path error: no proxy information. */
+ @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON)
+ public static final int REASON_MESH_PATH_ERROR_NO_PROXY_INFO = 61;
+
+ /** Disconnected because of a mesh path error: no forwarding information. */
+ @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON)
+ public static final int REASON_MESH_PATH_ERROR_NO_FORWARDING_INFO = 62;
+
+ /** Disconnected because of a mesh path error: destination unreachable. */
+ @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON)
+ public static final int REASON_MESH_PATH_ERROR_DEST_UNREACHABLE = 63;
+
+ /** Disconnected because the MAC address already exists in the mesh basic service set. */
+ @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON)
+ public static final int REASON_MAC_ADDRESS_ALREADY_EXISTS_IN_MBSS = 64;
+
+ /** Disconnected due to a mesh channel switch due to regulatory requirements. */
+ @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON)
+ public static final int REASON_MESH_CHANNEL_SWITCH_REGULATORY_REQ = 65;
+
+ /** Disconnected due to a mesh channel switch for an unspecified reason. */
+ @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON)
+ public static final int REASON_MESH_CHANNEL_SWITCH_UNSPECIFIED = 66;
+
+ private DeauthenticationReasonCode() {} // Private constructor to prevent instantiation
+}
diff --git a/framework/java/android/net/wifi/ISoftApCallback.aidl b/framework/java/android/net/wifi/ISoftApCallback.aidl
index 4190e4f..1710416 100644
--- a/framework/java/android/net/wifi/ISoftApCallback.aidl
+++ b/framework/java/android/net/wifi/ISoftApCallback.aidl
@@ -18,16 +18,15 @@
import android.net.wifi.SoftApCapability;
import android.net.wifi.SoftApInfo;
-import android.net.wifi.WifiClient;
import android.net.wifi.SoftApState;
+import android.net.wifi.WifiClient;
/**
* Interface for Soft AP callback.
*
* @hide
*/
-oneway interface ISoftApCallback
-{
+oneway interface ISoftApCallback {
/**
* Service to manager callback providing current soft AP state. The possible
* parameter values listed are defined in WifiManager.java
@@ -45,8 +44,7 @@
* @param isRegistration whether or not the callbackk was triggered when register.
*/
void onConnectedClientsOrInfoChanged(in Map<String, SoftApInfo> infos,
- in Map<String, List<WifiClient>> clients, boolean isBridged,
- boolean isRegistration);
+ in Map<String, List<WifiClient>> clients, boolean isBridged, boolean isRegistration);
/**
* Service to manager callback providing capability of softap.
@@ -62,4 +60,12 @@
* @param blockedReason one of blocked reason from {@link WifiManager.SapClientBlockedReason}
*/
void onBlockedClientConnecting(in WifiClient client, int blockedReason);
+
+ /**
+ * Service to manager callback providing clients that disconnected from the softap.
+ *
+ * @param info information about the AP instance
+ * @param clients the disconnected clients of the AP instance
+ */
+ void onClientsDisconnected(in SoftApInfo info, in List<WifiClient> clients);
}
diff --git a/framework/java/android/net/wifi/IWifiManager.aidl b/framework/java/android/net/wifi/IWifiManager.aidl
index dc8a444..2382f94 100644
--- a/framework/java/android/net/wifi/IWifiManager.aidl
+++ b/framework/java/android/net/wifi/IWifiManager.aidl
@@ -16,14 +16,11 @@
package android.net.wifi;
-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.DhcpOption;
import android.net.Network;
import android.net.TetheringManager.TetheringRequest;
+import android.net.wifi.BlockingOption;
import android.net.wifi.CoexUnsafeChannel;
import android.net.wifi.IActionListener;
import android.net.wifi.IBooleanListener;
@@ -34,14 +31,13 @@
import android.net.wifi.IInterfaceCreationInfoCallback;
import android.net.wifi.ILastCallerListener;
import android.net.wifi.IListListener;
-import android.net.wifi.ILocalOnlyHotspotCallback;
import android.net.wifi.ILocalOnlyConnectionStatusListener;
+import android.net.wifi.ILocalOnlyHotspotCallback;
+import android.net.wifi.IMacAddressListListener;
import android.net.wifi.IMapListener;
import android.net.wifi.INetworkRequestMatchCallback;
import android.net.wifi.IOnWifiActivityEnergyInfoListener;
import android.net.wifi.IOnWifiDriverCountryCodeChangedListener;
-import android.net.wifi.IWifiNetworkStateChangedListener;
-import android.net.wifi.IMacAddressListListener;
import android.net.wifi.IOnWifiUsabilityStatsListener;
import android.net.wifi.IPnoScanResultsCallback;
import android.net.wifi.IScanResultsCallback;
@@ -58,6 +54,8 @@
import android.net.wifi.IWifiConnectedNetworkScorer;
import android.net.wifi.IWifiLowLatencyLockListener;
import android.net.wifi.IWifiNetworkSelectionConfigListener;
+import android.net.wifi.IWifiNetworkStateChangedListener;
+import android.net.wifi.IWifiStateChangedListener;
import android.net.wifi.IWifiVerboseLoggingStatusChangedListener;
import android.net.wifi.MscsParams;
import android.net.wifi.QosPolicyParams;
@@ -70,14 +68,14 @@
import android.net.wifi.WifiNetworkSelectionConfig;
import android.net.wifi.WifiNetworkSuggestion;
import android.net.wifi.WifiSsid;
-
+import android.net.wifi.hotspot2.IProvisioningCallback;
+import android.net.wifi.hotspot2.OsuProvider;
+import android.net.wifi.hotspot2.PasspointConfiguration;
import android.net.wifi.twt.TwtRequest;
-
import android.os.Bundle;
import android.os.Messenger;
import android.os.ResultReceiver;
import android.os.WorkSource;
-
import com.android.modules.utils.ParceledListSlice;
import com.android.modules.utils.StringParceledListSlice;
@@ -86,9 +84,8 @@
*
* {@hide}
*/
-interface IWifiManager
-{
- long getSupportedFeatures();
+interface IWifiManager {
+ boolean isFeatureSupported(int feature);
oneway void getWifiActivityEnergyInfoAsync(in IOnWifiActivityEnergyInfoListener listener);
@@ -104,13 +101,14 @@
void setOneShotScreenOnConnectivityScanDelayMillis(int delayMs);
- ParceledListSlice getConfiguredNetworks(String packageName, String featureId, boolean callerNetworksOnly);
+ ParceledListSlice getConfiguredNetworks(
+ String packageName, String featureId, boolean callerNetworksOnly);
- ParceledListSlice getPrivilegedConfiguredNetworks(String packageName, String featureId, in Bundle extras);
+ ParceledListSlice getPrivilegedConfiguredNetworks(
+ String packageName, String featureId, in Bundle extras);
- WifiConfiguration getPrivilegedConnectedNetwork(String packageName, String featureId, in Bundle extras);
-
- Map getAllMatchingFqdnsForScanResults(in List<ScanResult> scanResult);
+ WifiConfiguration getPrivilegedConnectedNetwork(
+ String packageName, String featureId, in Bundle extras);
void setSsidsAllowlist(String packageName, in ParceledListSlice<WifiSsid> ssids);
@@ -122,7 +120,8 @@
int addOrUpdateNetwork(in WifiConfiguration config, String packageName, in Bundle extras);
- WifiManager.AddNetworkResult addOrUpdateNetworkPrivileged(in WifiConfiguration config, String packageName);
+ WifiManager.AddNetworkResult addOrUpdateNetworkPrivileged(
+ in WifiConfiguration config, String packageName);
boolean addOrUpdatePasspointConfiguration(in PasspointConfiguration config, String packageName);
@@ -130,7 +129,8 @@
ParceledListSlice<PasspointConfiguration> getPasspointConfigurations(in String packageName);
- ParceledListSlice<WifiConfiguration> getWifiConfigsForPasspointProfiles(in StringParceledListSlice fqdnList);
+ ParceledListSlice<WifiConfiguration> getWifiConfigsForPasspointProfiles(
+ in StringParceledListSlice fqdnList);
void queryPasspointIcon(long bssid, String fileName);
@@ -162,7 +162,8 @@
void getChannelData(in IListListener listener, String packageName, in Bundle extras);
- void getBssidBlocklist(in ParceledListSlice<WifiSsid> ssids, in IMacAddressListListener listener);
+ void getBssidBlocklist(
+ in ParceledListSlice<WifiSsid> ssids, in IMacAddressListListener listener);
boolean disconnect(String packageName);
@@ -176,6 +177,10 @@
int getWifiEnabledState();
+ void addWifiStateChangedListener(in IWifiStateChangedListener listener);
+
+ void removeWifiStateChangedListener(in IWifiStateChangedListener listener);
+
void registerDriverCountryCodeChangedListener(
in IOnWifiDriverCountryCodeChangedListener listener, String packageName,
String featureId);
@@ -211,9 +216,11 @@
boolean isScanAlwaysAvailable();
- boolean acquireWifiLock(IBinder lock, int lockType, String tag, in WorkSource ws, in String packageName, in Bundle extras);
+ boolean acquireWifiLock(IBinder lock, int lockType, String tag, in WorkSource ws,
+ in String packageName, in Bundle extras);
- void updateWifiLockWorkSource(IBinder lock, in WorkSource ws, in String packageName, in Bundle extras);
+ void updateWifiLockWorkSource(
+ IBinder lock, in WorkSource ws, in String packageName, in Bundle extras);
boolean releaseWifiLock(IBinder lock);
@@ -223,13 +230,14 @@
void acquireMulticastLock(IBinder binder, String tag);
- void releaseMulticastLock(String tag);
+ void releaseMulticastLock(IBinder binder, String tag);
void updateInterfaceIpState(String ifaceName, int mode);
boolean isDefaultCoexAlgorithmEnabled();
- void setCoexUnsafeChannels(in List<CoexUnsafeChannel> unsafeChannels, int mandatoryRestrictions);
+ void setCoexUnsafeChannels(
+ in List<CoexUnsafeChannel> unsafeChannels, int mandatoryRestrictions);
void registerCoexCallback(in ICoexCallback callback);
@@ -239,14 +247,16 @@
boolean startTetheredHotspot(in SoftApConfiguration softApConfig, String packageName);
- void startTetheredHotspotRequest(in TetheringRequest request, in ISoftApCallback callback, String packageName);
+ void startTetheredHotspotRequest(
+ in TetheringRequest request, in ISoftApCallback callback, String packageName);
boolean stopSoftAp();
boolean validateSoftApConfiguration(in SoftApConfiguration config);
int startLocalOnlyHotspot(in ILocalOnlyHotspotCallback callback, String packageName,
- String featureId, in SoftApConfiguration customConfig, in Bundle extras);
+ String featureId, in SoftApConfiguration customConfig, in Bundle extras,
+ boolean isCalledFromSystemApi);
void stopLocalOnlyHotspot();
@@ -258,11 +268,9 @@
void stopWatchLocalOnlyHotspot();
- @UnsupportedAppUsage
- int getWifiApEnabledState();
+ @UnsupportedAppUsage int getWifiApEnabledState();
- @UnsupportedAppUsage
- WifiConfiguration getWifiApConfiguration();
+ @UnsupportedAppUsage WifiConfiguration getWifiApConfiguration();
SoftApConfiguration getSoftApConfiguration();
@@ -272,15 +280,15 @@
boolean setSoftApConfiguration(in SoftApConfiguration softApConfig, String packageName);
- void notifyUserOfApBandConversion(String packageName);
-
void enableTdls(String remoteIPAddress, boolean enable);
- void enableTdlsWithRemoteIpAddress(String remoteIPAddress, boolean enable, in IBooleanListener listener);
+ void enableTdlsWithRemoteIpAddress(
+ String remoteIPAddress, boolean enable, in IBooleanListener listener);
void enableTdlsWithMacAddress(String remoteMacAddress, boolean enable);
- void enableTdlsWithRemoteMacAddress(String remoteMacAddress, boolean enable, in IBooleanListener listener);
+ void enableTdlsWithRemoteMacAddress(
+ String remoteMacAddress, boolean enable, in IBooleanListener listener);
void isTdlsOperationCurrentlyAvailable(in IBooleanListener listener);
@@ -298,8 +306,7 @@
void factoryReset(String packageName);
- @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
- Network getCurrentNetwork();
+ @UnsupportedAppUsage(maxTargetSdk=30, trackingBug=170729553) Network getCurrentNetwork();
byte[] retrieveBackupData();
@@ -317,9 +324,11 @@
void unregisterSoftApCallback(in ISoftApCallback callback);
- void addWifiVerboseLoggingStatusChangedListener(in IWifiVerboseLoggingStatusChangedListener listener);
+ void addWifiVerboseLoggingStatusChangedListener(
+ in IWifiVerboseLoggingStatusChangedListener listener);
- void removeWifiVerboseLoggingStatusChangedListener(in IWifiVerboseLoggingStatusChangedListener listener);
+ void removeWifiVerboseLoggingStatusChangedListener(
+ in IWifiVerboseLoggingStatusChangedListener listener);
void addOnWifiUsabilityStatsListener(in IOnWifiUsabilityStatsListener listener);
@@ -333,10 +342,11 @@
void unregisterNetworkRequestMatchCallback(in INetworkRequestMatchCallback callback);
- int addNetworkSuggestions(in ParceledListSlice<WifiNetworkSuggestion> networkSuggestions, in String packageName,
- in String featureId);
+ int addNetworkSuggestions(in ParceledListSlice<WifiNetworkSuggestion> networkSuggestions,
+ in String packageName, in String featureId);
- int removeNetworkSuggestions(in ParceledListSlice<WifiNetworkSuggestion> networkSuggestions, in String packageName, int action);
+ int removeNetworkSuggestions(in ParceledListSlice<WifiNetworkSuggestion> networkSuggestions,
+ in String packageName, int action);
ParceledListSlice<WifiNetworkSuggestion> getNetworkSuggestions(in String packageName);
@@ -345,21 +355,23 @@
void setDeviceMobilityState(int state);
void startDppAsConfiguratorInitiator(in IBinder binder, in String packageName,
- in String enrolleeUri, int selectedNetworkId, int netRole, in IDppCallback callback);
+ in String enrolleeUri, int selectedNetworkId, int netRole, in IDppCallback callback);
- void startDppAsEnrolleeInitiator(in IBinder binder, in String configuratorUri,
- in IDppCallback callback);
+ 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 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 IActionListener listener, in String packageName, in Bundle extras);
+ oneway void connect(in WifiConfiguration config, int netId, in IActionListener listener,
+ in String packageName, in Bundle extras);
- oneway void save(in WifiConfiguration config, in IActionListener listener, in String packageName);
+ oneway void save(
+ in WifiConfiguration config, in IActionListener listener, in String packageName);
oneway void forget(int netId, in IActionListener listener);
@@ -367,25 +379,32 @@
void unregisterScanResultsCallback(in IScanResultsCallback callback);
- void registerSuggestionConnectionStatusListener(in ISuggestionConnectionStatusListener listener, String packageName, String featureId);
+ void registerSuggestionConnectionStatusListener(
+ in ISuggestionConnectionStatusListener listener, String packageName, String featureId);
- void unregisterSuggestionConnectionStatusListener(in ISuggestionConnectionStatusListener listener, String packageName);
+ void unregisterSuggestionConnectionStatusListener(
+ in ISuggestionConnectionStatusListener listener, String packageName);
- void addLocalOnlyConnectionStatusListener(in ILocalOnlyConnectionStatusListener listener, String packageName, String featureId);
+ void addLocalOnlyConnectionStatusListener(
+ in ILocalOnlyConnectionStatusListener listener, String packageName, String featureId);
- void removeLocalOnlyConnectionStatusListener(in ILocalOnlyConnectionStatusListener listener, String packageName);
+ void removeLocalOnlyConnectionStatusListener(
+ in ILocalOnlyConnectionStatusListener listener, String packageName);
int calculateSignalLevel(int rssi);
- ParceledListSlice<WifiConfiguration> getWifiConfigForMatchedNetworkSuggestionsSharedWithUser(in ParceledListSlice<ScanResult> scanResults);
+ ParceledListSlice<WifiConfiguration> getWifiConfigForMatchedNetworkSuggestionsSharedWithUser(
+ in ParceledListSlice<ScanResult> scanResults);
boolean setWifiConnectedNetworkScorer(in IBinder binder, in IWifiConnectedNetworkScorer scorer);
void clearWifiConnectedNetworkScorer();
- void setExternalPnoScanRequest(in IBinder binder, in IPnoScanResultsCallback callback, in List<WifiSsid> ssids, in int[] frequencies, String packageName, String featureId);
+ void setExternalPnoScanRequest(in IBinder binder, in IPnoScanResultsCallback callback,
+ in List<WifiSsid> ssids, in int[] frequencies, String packageName, String featureId);
- void setPnoScanEnabled(boolean enabled, boolean enablePnoScanAfterWifiToggle, String packageName);
+ void setPnoScanEnabled(
+ boolean enabled, boolean enablePnoScanAfterWifiToggle, String packageName);
void clearExternalPnoScanRequest();
@@ -394,7 +413,9 @@
/**
* Return the Map of {@link WifiNetworkSuggestion} and the list of <ScanResult>
*/
- Map getMatchingScanResults(in ParceledListSlice<WifiNetworkSuggestion> networkSuggestions, in ParceledListSlice<ScanResult> scanResults, String callingPackage, String callingFeatureId);
+ Map getMatchingScanResults(in ParceledListSlice<WifiNetworkSuggestion> networkSuggestions,
+ in ParceledListSlice<ScanResult> scanResults, String callingPackage,
+ String callingFeatureId);
void setScanThrottleEnabled(boolean enable);
@@ -420,9 +441,11 @@
void restartWifiSubsystem();
- void addSuggestionUserApprovalStatusListener(in ISuggestionUserApprovalStatusListener listener, String packageName);
+ void addSuggestionUserApprovalStatusListener(
+ in ISuggestionUserApprovalStatusListener listener, String packageName);
- void removeSuggestionUserApprovalStatusListener(in ISuggestionUserApprovalStatusListener listener, String packageName);
+ void removeSuggestionUserApprovalStatusListener(
+ in ISuggestionUserApprovalStatusListener listener, String packageName);
void setEmergencyScanRequestInProgress(boolean inProgress);
@@ -432,7 +455,8 @@
void flushPasspointAnqpCache(String packageName);
- List<WifiAvailableChannel> getUsableChannels(int band, int mode, int filter, String packageName, in Bundle extras);
+ List<WifiAvailableChannel> getUsableChannels(
+ int band, int mode, int filter, String packageName, in Bundle extras);
boolean isWifiPasspointEnabled();
@@ -452,15 +476,18 @@
void replyToSimpleDialog(int dialogId, int reply);
- void addCustomDhcpOptions(in WifiSsid ssid, in byte[] oui, in ParceledListSlice<DhcpOption> options);
+ void addCustomDhcpOptions(
+ in WifiSsid ssid, in byte[] oui, in ParceledListSlice<DhcpOption> options);
void removeCustomDhcpOptions(in WifiSsid ssid, in byte[] oui);
- void reportCreateInterfaceImpact(String packageName, int interfaceType, boolean requireNewInterface, in IInterfaceCreationInfoCallback callback);
+ void reportCreateInterfaceImpact(String packageName, int interfaceType,
+ boolean requireNewInterface, in IInterfaceCreationInfoCallback callback);
int getMaxNumberOfChannelsPerRequest();
- void addQosPolicies(in ParceledListSlice<QosPolicyParams> policyParamsList, in IBinder binder, String packageName, in IListListener callback);
+ void addQosPolicies(in ParceledListSlice<QosPolicyParams> policyParamsList, in IBinder binder,
+ String packageName, in IListListener callback);
void removeQosPolicies(in int[] policyIdList, String packageName);
@@ -500,7 +527,7 @@
void removePerSsidRoamingMode(in WifiSsid ssid, String packageName);
- void getPerSsidRoamingModes(String packageName,in IMapListener listener);
+ void getPerSsidRoamingModes(String packageName, in IMapListener listener);
void getTwtCapabilities(in ITwtCapabilitiesListener listener, in Bundle extras);
@@ -519,4 +546,15 @@
void restoreWifiBackupData(in byte[] data);
boolean isPnoSupported();
+
+ void setAutojoinDisallowedSecurityTypes(int restrictions, in Bundle extras);
+
+ void getAutojoinDisallowedSecurityTypes(in IIntegerListener listener, in Bundle extras);
+
+ void disallowCurrentSuggestedNetwork(in BlockingOption option, String packageName);
+
+ void storeCapturedData(int triggerType, boolean isFullCapture, long triggerStartTimeMillis,
+ long triggerStopTimeMillis, in IIntegerListener listener);
+ boolean isUsdSubscriberSupported();
+ boolean isUsdPublisherSupported();
}
diff --git a/framework/java/android/net/wifi/IWifiStateChangedListener.aidl b/framework/java/android/net/wifi/IWifiStateChangedListener.aidl
new file mode 100644
index 0000000..2b5cdfd
--- /dev/null
+++ b/framework/java/android/net/wifi/IWifiStateChangedListener.aidl
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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;
+
+/**
+ * Interface for Wi-Fi state changed listener.
+ * @hide
+ */
+oneway interface IWifiStateChangedListener {
+ void onWifiStateChanged();
+}
diff --git a/framework/java/android/net/wifi/ScanResult.java b/framework/java/android/net/wifi/ScanResult.java
index 161928f..a93ab7b 100644
--- a/framework/java/android/net/wifi/ScanResult.java
+++ b/framework/java/android/net/wifi/ScanResult.java
@@ -360,9 +360,26 @@
public static final int KEY_MGMT_FT_SAE_EXT_KEY = 19;
/**
* @hide
+ * Security key management scheme: PASN.
+ */
+ public static final int KEY_MGMT_PASN = 20;
+
+ /**
+ * Security key management scheme: FT authentication negotiated over IEEE Std 802.1X using
+ * SHA-384.
+ * @hide
+ */
+ public static final int KEY_MGMT_EAP_FT_SHA384 = 21;
+ /**
+ * Security key management scheme: FT authentication using PSK (SHA-384).
+ * @hide
+ */
+ public static final int KEY_MGMT_FT_PSK_SHA384 = 22;
+ /**
+ * @hide
* Security key management scheme: any unknown AKM.
*/
- public static final int KEY_MGMT_UNKNOWN = 20;
+ public static final int KEY_MGMT_UNKNOWN = 23;
/**
* @hide
* No cipher suite.
@@ -736,6 +753,13 @@
/** @hide */
public static final long FLAG_TWT_RESPONDER = 0x0000000000000008;
+
+ /** @hide */
+ public static final long FLAG_SECURE_HE_LTF_SUPPORTED = 0x0000000000000010;
+
+ /** @hide */
+ public static final long FLAG_RANGING_FRAME_PROTECTION_REQUIRED = 0x0000000000000020;
+
/*
* These flags are specific to the ScanResult class, and are not related to the |flags|
* field of the per-BSS scan results from WPA supplicant.
@@ -790,6 +814,33 @@
}
/**
+ * Returns whether the AP supports secure HE-LTF for ranging measurement.
+ *
+ * Secure HE-LTF (High Efficiency Long Training Field), is a security enhancement for the HE
+ * PHY (High Efficiency Physical Layer) that aims to protect ranging measurements by using
+ * randomized HE-LTF sequences. This prevents attackers from exploiting predictable HE-LTF
+ * patterns. IEEE 802.11az adds secure HE-LTF support in Extended RSN capabilities.
+ */
+ @FlaggedApi(Flags.FLAG_SECURE_RANGING)
+ public boolean isSecureHeLtfSupported() {
+ return (flags & FLAG_SECURE_HE_LTF_SUPPORTED) != 0;
+ }
+
+ /**
+ * Returns whether the AP requires frame protection for ranging measurement.
+ *
+ * Ranging frame protection in IEEE 802.11az, also known as URNM-MFPR (Unassociated Range
+ * Negotiation and Measurement Management Frame Protection Required), is a security policy
+ * that dictates whether ranging frames are required to be protected even without a formal
+ * association between the Initiating STA (ISTA) and Responding STA (RSTA)
+ */
+ @FlaggedApi(Flags.FLAG_SECURE_RANGING)
+ public boolean isRangingFrameProtectionRequired() {
+ return (flags & FLAG_RANGING_FRAME_PROTECTION_REQUIRED) != 0;
+ }
+
+
+ /**
* Indicates venue name (such as 'San Francisco Airport') published by access point; only
* available on Passpoint network and if published by access point.
* @deprecated - This information is not provided
@@ -1219,6 +1270,8 @@
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public static final int EID_RSN = 48;
/** @hide */
+ public static final int EID_RSN_EXTENSION = 244;
+ /** @hide */
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public static final int EID_EXTENDED_SUPPORTED_RATES = 50;
/** @hide */
@@ -1456,6 +1509,9 @@
private boolean mIs80211McRTTResponder = false;
private boolean mIs80211azNtbRTTResponder = false;
private boolean mIsTwtResponder = false;
+ private boolean mIsSecureHeLtfSupported = false;
+ private boolean mIsRangingFrameProtectionRequired = false;
+
/** @hide */
@NonNull
public Builder setHessid(long hessid) {
@@ -1618,6 +1674,18 @@
public ScanResult build() {
return new ScanResult(this);
}
+
+ /** @hide */
+ public Builder setSecureHeLtfSupported(boolean supported) {
+ mIsSecureHeLtfSupported = supported;
+ return this;
+ }
+
+ /** @hide */
+ public Builder setRangingFrameProtectionRequired(boolean required) {
+ mIsRangingFrameProtectionRequired = required;
+ return this;
+ }
}
/**
@@ -1656,6 +1724,9 @@
this.flags |= (builder.mIsTwtResponder) ? FLAG_TWT_RESPONDER : 0;
this.radioChainInfos = null;
this.mApMldMacAddress = null;
+ this.flags |= (builder.mIsSecureHeLtfSupported) ? FLAG_SECURE_HE_LTF_SUPPORTED : 0;
+ this.flags |= (builder.mIsRangingFrameProtectionRequired)
+ ? FLAG_RANGING_FRAME_PROTECTION_REQUIRED : 0;
}
/**
diff --git a/framework/java/android/net/wifi/SoftApCapability.java b/framework/java/android/net/wifi/SoftApCapability.java
index 0607db4..e52ed53 100644
--- a/framework/java/android/net/wifi/SoftApCapability.java
+++ b/framework/java/android/net/wifi/SoftApCapability.java
@@ -16,6 +16,7 @@
package android.net.wifi;
+import android.annotation.FlaggedApi;
import android.annotation.LongDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -25,6 +26,8 @@
import android.os.Parcel;
import android.os.Parcelable;
+import com.android.wifi.flags.Flags;
+
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Arrays;
@@ -142,6 +145,14 @@
*/
public static final long SOFTAP_FEATURE_WPA3_OWE = 1 << 11;
+ /*
+ * Support for multiple link operation on a single multiple link device.
+ * Flag when {@code R.Integer.config_wifiSoftApMaxNumberMLDSupported} is configured
+ * to non zero value and chip report MLO SoftAP is supported.
+ */
+ @FlaggedApi(Flags.FLAG_MLO_SAP)
+ public static final long SOFTAP_FEATURE_MLO = 1 << 12;
+
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@LongDef(flag = true, prefix = { "SOFTAP_FEATURE_" }, value = {
@@ -157,6 +168,7 @@
SOFTAP_FEATURE_BAND_60G_SUPPORTED,
SOFTAP_FEATURE_WPA3_OWE_TRANSITION,
SOFTAP_FEATURE_WPA3_OWE,
+ SOFTAP_FEATURE_MLO,
})
public @interface HotspotFeatures {}
diff --git a/framework/java/android/net/wifi/SoftApConfiguration.java b/framework/java/android/net/wifi/SoftApConfiguration.java
index 5432484..2a51231 100644
--- a/framework/java/android/net/wifi/SoftApConfiguration.java
+++ b/framework/java/android/net/wifi/SoftApConfiguration.java
@@ -26,6 +26,7 @@
import android.compat.annotation.ChangeId;
import android.compat.annotation.EnabledAfter;
import android.net.MacAddress;
+import android.net.wifi.util.Environment;
import android.net.wifi.util.HexEncoding;
import android.os.Build;
import android.os.Parcel;
@@ -74,30 +75,26 @@
/**
* 2GHz band.
- * @hide
*/
- @SystemApi
+ @FlaggedApi(Flags.FLAG_PUBLIC_BANDS_FOR_LOHS)
public static final int BAND_2GHZ = 1 << 0;
/**
* 5GHz band.
- * @hide
*/
- @SystemApi
+ @FlaggedApi(Flags.FLAG_PUBLIC_BANDS_FOR_LOHS)
public static final int BAND_5GHZ = 1 << 1;
/**
* 6GHz band.
- * @hide
*/
- @SystemApi
+ @FlaggedApi(Flags.FLAG_PUBLIC_BANDS_FOR_LOHS)
public static final int BAND_6GHZ = 1 << 2;
/**
* 60GHz band.
- * @hide
*/
- @SystemApi
+ @FlaggedApi(Flags.FLAG_PUBLIC_BANDS_FOR_LOHS)
public static final int BAND_60GHZ = 1 << 3;
/**
@@ -406,6 +403,11 @@
private @NonNull List<OuiKeyedData> mVendorData;
/**
+ * Whether connected clients can communicate with each other or not.
+ */
+ private boolean mIsClientIsolationEnabled;
+
+ /**
* THe definition of security type OPEN.
*/
public static final int SECURITY_TYPE_OPEN = 0;
@@ -473,7 +475,8 @@
@NonNull Set<Integer> allowedAcsChannels5g,
@NonNull Set<Integer> allowedAcsChannels6g,
@WifiAnnotations.Bandwidth int maxChannelBandwidth,
- @Nullable List<OuiKeyedData> vendorData) {
+ @Nullable List<OuiKeyedData> vendorData,
+ boolean isClientIsolationEnabled) {
mWifiSsid = ssid;
mBssid = bssid;
mPassphrase = passphrase;
@@ -505,6 +508,7 @@
mAllowedAcsChannels6g = new HashSet<>(allowedAcsChannels6g);
mMaxChannelBandwidth = maxChannelBandwidth;
mVendorData = new ArrayList<>(vendorData);
+ mIsClientIsolationEnabled = isClientIsolationEnabled;
}
@Override
@@ -543,7 +547,8 @@
&& Objects.equals(mAllowedAcsChannels5g, other.mAllowedAcsChannels5g)
&& Objects.equals(mAllowedAcsChannels6g, other.mAllowedAcsChannels6g)
&& mMaxChannelBandwidth == other.mMaxChannelBandwidth
- && Objects.equals(mVendorData, other.mVendorData);
+ && Objects.equals(mVendorData, other.mVendorData)
+ && mIsClientIsolationEnabled == other.mIsClientIsolationEnabled;
}
@Override
@@ -573,7 +578,8 @@
mAllowedAcsChannels5g,
mAllowedAcsChannels6g,
mMaxChannelBandwidth,
- mVendorData);
+ mVendorData,
+ mIsClientIsolationEnabled);
}
@Override
@@ -608,6 +614,7 @@
sbuf.append(" \n mAllowedAcsChannels6g = ").append(mAllowedAcsChannels6g);
sbuf.append(" \n mMaxChannelBandwidth = ").append(mMaxChannelBandwidth);
sbuf.append(" \n mVendorData = ").append(mVendorData);
+ sbuf.append(" \n mIsClientIsolationEnabled = ").append(mIsClientIsolationEnabled);
return sbuf.toString();
}
@@ -638,6 +645,7 @@
writeHashSetInt(dest, mAllowedAcsChannels6g);
dest.writeInt(mMaxChannelBandwidth);
dest.writeList(mVendorData);
+ dest.writeBoolean(mIsClientIsolationEnabled);
}
/* Reference from frameworks/base/core/java/android/os/Parcel.java */
@@ -749,7 +757,8 @@
readHashSetInt(in),
readHashSetInt(in),
in.readInt(),
- readOuiKeyedDataList(in));
+ readOuiKeyedDataList(in),
+ in.readBoolean());
}
@Override
@@ -895,11 +904,9 @@
*
* Note: return array may only include one channel when current setting is single AP mode.
* See also {@link Builder#setChannels(SparseIntArray)}.
- *
- * @hide
*/
+ @FlaggedApi(Flags.FLAG_PUBLIC_BANDS_FOR_LOHS)
@RequiresApi(Build.VERSION_CODES.S)
- @SystemApi
public @NonNull SparseIntArray getChannels() {
if (!SdkLevel.isAtLeastS()) {
throw new UnsupportedOperationException();
@@ -967,6 +974,8 @@
* (true: authorization required) or not (false: not required).
* See also {@link Builder#setClientControlByUserEnabled(Boolean)}.
*
+ * @return true when client isolation is enable.
+ *
* @hide
*/
@SystemApi
@@ -1218,6 +1227,24 @@
}
/**
+ * Returns whether client isolation is enabled or not.
+ *
+ * Client isolation is used to disallow a connected Soft AP
+ * client to communicate with other connected clients.
+ *
+ * @hide
+ */
+ @RequiresApi(Build.VERSION_CODES.BAKLAVA)
+ @FlaggedApi(Flags.FLAG_AP_ISOLATE)
+ @SystemApi
+ public boolean isClientIsolationEnabled() {
+ if (!Environment.isSdkAtLeastB()) {
+ throw new UnsupportedOperationException();
+ }
+ return mIsClientIsolationEnabled;
+ }
+
+ /**
* 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.
@@ -1282,10 +1309,8 @@
*
* All fields are optional. By default, SSID and BSSID are automatically chosen by the
* framework, and an open network is created.
- *
- * @hide
*/
- @SystemApi
+ @FlaggedApi(Flags.FLAG_PUBLIC_BANDS_FOR_LOHS)
public static final class Builder {
private WifiSsid mWifiSsid;
private MacAddress mBssid;
@@ -1312,6 +1337,7 @@
private Set<Integer> mAllowedAcsChannels6g;
private @WifiAnnotations.Bandwidth int mMaxChannelBandwidth;
private @Nullable List<OuiKeyedData> mVendorData;
+ private boolean mIsClientIsolationEnabled;
/**
* Constructs a Builder with default values (see {@link Builder}).
@@ -1347,11 +1373,15 @@
mAllowedAcsChannels6g = new HashSet<>();
mMaxChannelBandwidth = SoftApInfo.CHANNEL_WIDTH_AUTO;
mVendorData = new ArrayList<>();
+ mIsClientIsolationEnabled = false;
}
/**
* Constructs a Builder initialized from an existing {@link SoftApConfiguration} instance.
+ *
+ * @hide
*/
+ @SystemApi
public Builder(@NonNull SoftApConfiguration other) {
if (other == null) {
Log.e(TAG, "Cannot provide a null SoftApConfiguration");
@@ -1391,6 +1421,7 @@
mMacRandomizationSetting = RANDOMIZATION_NONE;
}
mVendorData = new ArrayList<>(other.mVendorData);
+ mIsClientIsolationEnabled = other.mIsClientIsolationEnabled;
}
/**
@@ -1443,7 +1474,8 @@
mAllowedAcsChannels5g,
mAllowedAcsChannels6g,
mMaxChannelBandwidth,
- mVendorData);
+ mVendorData,
+ mIsClientIsolationEnabled);
}
/**
@@ -1460,9 +1492,12 @@
* representation is longer than 32 bytes.
*
* @deprecated Use {@link #setWifiSsid(WifiSsid)} instead.
+ *
+ * @hide
*/
@NonNull
@Deprecated
+ @SystemApi
public Builder setSsid(@Nullable String ssid) {
if (ssid == null) {
mWifiSsid = null;
@@ -1484,9 +1519,12 @@
*
* @param wifiSsid SSID, or null ot have the SSID automatically chosen by the framework.
* @return Builder for chaining.
+ *
+ * @hide
*/
@NonNull
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
+ @SystemApi
public Builder setWifiSsid(@Nullable WifiSsid wifiSsid) {
if (!SdkLevel.isAtLeastT()) {
throw new UnsupportedOperationException();
@@ -1503,9 +1541,12 @@
*
* @param vendorElements VendorElements
* @return Builder for chaining.
+ *
+ * @hide
*/
@NonNull
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
+ @SystemApi
public Builder setVendorElements(
@NonNull List<ScanResult.InformationElement> vendorElements) {
if (!SdkLevel.isAtLeastT()) {
@@ -1561,8 +1602,11 @@
* @return Builder for chaining.
* @throws IllegalArgumentException when the given BSSID is the all-zero
* , multicast or broadcast MAC address.
+ *
+ * @hide
*/
@NonNull
+ @SystemApi
public Builder setBssid(@Nullable MacAddress bssid) {
if (bssid != null) {
Preconditions.checkArgument(!bssid.equals(WifiManager.ALL_ZEROS_MAC_ADDRESS));
@@ -1602,8 +1646,11 @@
* when the passphrase is not between 8 and 63 bytes (inclusive) for
* - {@link #SECURITY_TYPE_WPA2_PSK}
* - {@link #SECURITY_TYPE_WPA3_SAE_TRANSITION}
+ *
+ * @hide
*/
@NonNull
+ @SystemApi
public Builder setPassphrase(@Nullable String passphrase, @SecurityType int securityType) {
if (!SdkLevel.isAtLeastT()
&& (securityType == SECURITY_TYPE_WPA3_OWE_TRANSITION
@@ -1646,8 +1693,11 @@
*
* @param hiddenSsid true for a hidden SSID, false otherwise.
* @return Builder for chaining.
+ *
+ * @hide
*/
@NonNull
+ @SystemApi
public Builder setHiddenSsid(boolean hiddenSsid) {
mHiddenSsid = hiddenSsid;
return this;
@@ -1662,8 +1712,11 @@
* {@link #BAND_2GHZ}, {@link #BAND_5GHZ}, {@link #BAND_6GHZ}.
* @return Builder for chaining.
* @throws IllegalArgumentException when an invalid band type is provided.
+ *
+ * @hide
*/
@NonNull
+ @SystemApi
public Builder setBand(@BandType int band) {
if (!isBandValid(band)) {
throw new IllegalArgumentException("Invalid band type: " + band);
@@ -1694,9 +1747,12 @@
* @return Builder for chaining.
* @throws IllegalArgumentException when more than 2 bands are set or an invalid band type
* is provided.
+ *
+ * @hide
*/
@RequiresApi(Build.VERSION_CODES.S)
@NonNull
+ @SystemApi
public Builder setBands(@NonNull int[] bands) {
if (!SdkLevel.isAtLeastS()) {
throw new UnsupportedOperationException();
@@ -1744,8 +1800,11 @@
* @param band containing this channel.
* @return Builder for chaining.
* @throws IllegalArgumentException when the invalid channel or band type is configured.
+ *
+ * @hide
*/
@NonNull
+ @SystemApi
public Builder setChannel(int channel, @BandType int band) {
if (!isChannelBandPairValid(channel, band)) {
throw new IllegalArgumentException("Invalid channel(" + channel
@@ -1758,40 +1817,40 @@
/**
* Specifies the channels and associated bands for the APs.
- *
+ * <p>
* When more than 1 channel is set, this will bring up concurrent APs on the requested
* channels and bands (if possible).
- *
+ * <p>
* Valid channels are country dependent.
- * The {@link SoftApCapability#getSupportedChannelList(int)} can be used to obtain
+ * The {@code SoftApCapability#getSupportedChannelList(int)} can be used to obtain
* valid channels in each band.
- *
+ * <p>
* 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[])}.
- *
+ * auto-select a valid channel from the band configured with {@code #setBands(int[])}.
+ * <p>
* The channel auto selection will be offloaded to driver when
- * {@link SoftApCapability#areFeaturesSupported(long)}
- * with {@link SoftApCapability.SOFTAP_FEATURE_ACS_OFFLOAD}
+ * {@code SoftApCapability#areFeaturesSupported(long)}
+ * with {@code 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.
- *
- * Requires the driver to support {@link SoftApCapability.SOFTAP_FEATURE_ACS_OFFLOAD}
+ * based on environment interference. Check {@code SoftApCapability} for more detail.
+ * <p>
+ * Requires the driver to support {@code SoftApCapability.SOFTAP_FEATURE_ACS_OFFLOAD}
* when multiple bands are configured without specified channel value (i.e. channel is
* the special value 0). Otherwise,
- * {@link WifiManager#startTetheredHotspot(SoftApConfiguration)} will report error code
- * {@link WifiManager#SAP_START_FAILURE_UNSUPPORTED_CONFIGURATION}.
- *
+ * {@code WifiManager#startTetheredHotspot(SoftApConfiguration)} will report error code
+ * {@code WifiManager#SAP_START_FAILURE_UNSUPPORTED_CONFIGURATION}.
+ * <p>
* Note: Only supports 2.4GHz + 5GHz bands. If any other band is set, will report error
- * {@link WifiManager#SAP_START_FAILURE_UNSUPPORTED_CONFIGURATION}.
- *
+ * {@code WifiManager#SAP_START_FAILURE_UNSUPPORTED_CONFIGURATION}.
+ * <p>
* 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>
* Reference the Wi-Fi channel numbering and the channelization in IEEE 802.11-2016
* specifications, section 17.3.8.4.2, 17.3.8.4.3 and Table 15-6.
*
@@ -1859,8 +1918,11 @@
*
* @param maxNumberOfClients maximum client number of the AP.
* @return Builder for chaining.
+ *
+ * @hide
*/
@NonNull
+ @SystemApi
public Builder setMaxNumberOfClients(@IntRange(from = 0) int maxNumberOfClients) {
if (maxNumberOfClients < 0) {
throw new IllegalArgumentException("maxNumberOfClients should be not negative");
@@ -1881,8 +1943,11 @@
* @return Builder for chaining.
*
* @see #setShutdownTimeoutMillis(long)
+ *
+ * @hide
*/
@NonNull
+ @SystemApi
public Builder setAutoShutdownEnabled(boolean enable) {
mAutoShutdownEnabled = enable;
return this;
@@ -1907,8 +1972,11 @@
* @return Builder for chaining.
*
* @see #setAutoShutdownEnabled(boolean)
+ *
+ * @hide
*/
@NonNull
+ @SystemApi
public Builder setShutdownTimeoutMillis(@IntRange(from = -1) long timeoutMillis) {
if (CompatChanges.isChangeEnabled(
REMOVE_ZERO_FOR_TIMEOUT_SETTING) && timeoutMillis < 1) {
@@ -1950,8 +2018,11 @@
*
* @param enabled true for enabling the control by user, false otherwise.
* @return Builder for chaining.
+ *
+ * @hide
*/
@NonNull
+ @SystemApi
public Builder setClientControlByUserEnabled(boolean enabled) {
mClientControlByUser = enabled;
return this;
@@ -1975,9 +2046,12 @@
* <p>
*
* @return Builder for chaining.
+ *
+ * @hide
*/
@NonNull
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
+ @SystemApi
public Builder setAllowedAcsChannels(@BandType int band, @NonNull int[] channels) {
if (!SdkLevel.isAtLeastT()) {
throw new UnsupportedOperationException();
@@ -2031,9 +2105,12 @@
* or {@link SoftApInfo#CHANNEL_WIDTH_320MHZ}
*
* @return builder for chaining
+ *
+ * @hide
*/
@NonNull
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
+ @SystemApi
public Builder setMaxChannelBandwidth(@WifiAnnotations.Bandwidth int maxChannelBandwidth) {
if (!SdkLevel.isAtLeastT()) {
throw new UnsupportedOperationException();
@@ -2076,8 +2153,11 @@
* @param allowedClientList list of clients which are allowed to associate to the AP
* without user pre-approval.
* @return Builder for chaining.
+ *
+ * @hide
*/
@NonNull
+ @SystemApi
public Builder setAllowedClientList(@NonNull List<MacAddress> allowedClientList) {
mAllowedClientList = new ArrayList<>(allowedClientList);
return this;
@@ -2100,8 +2180,11 @@
*
* @param blockedClientList list of clients which are not allowed to associate to the AP.
* @return Builder for chaining.
+ *
+ * @hide
*/
@NonNull
+ @SystemApi
public Builder setBlockedClientList(@NonNull List<MacAddress> blockedClientList) {
mBlockedClientList = new ArrayList<>(blockedClientList);
return this;
@@ -2133,9 +2216,12 @@
* @return Builder for chaining.
*
* @see #setBssid(MacAddress)
+ *
+ * @hide
*/
@RequiresApi(Build.VERSION_CODES.S)
@NonNull
+ @SystemApi
public Builder setMacRandomizationSetting(
@MacRandomizationSetting int macRandomizationSetting) {
if (!SdkLevel.isAtLeastS()) {
@@ -2175,9 +2261,11 @@
* @param enable true to enable, false to disable.
* @return Builder for chaining.
*
+ * @hide
*/
@RequiresApi(Build.VERSION_CODES.S)
@NonNull
+ @SystemApi
public Builder setBridgedModeOpportunisticShutdownEnabled(boolean enable) {
if (!SdkLevel.isAtLeastS()) {
throw new UnsupportedOperationException();
@@ -2203,9 +2291,11 @@
* @param enable true to enable, false to disable.
* @return Builder for chaining.
*
+ * @hide
*/
@RequiresApi(Build.VERSION_CODES.S)
@NonNull
+ @SystemApi
public Builder setIeee80211axEnabled(boolean enable) {
if (!SdkLevel.isAtLeastS()) {
throw new UnsupportedOperationException();
@@ -2231,9 +2321,11 @@
* @param enable true to enable, false to disable.
* @return Builder for chaining.
*
+ * @hide
*/
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
@NonNull
+ @SystemApi
public Builder setIeee80211beEnabled(boolean enable) {
if (!SdkLevel.isAtLeastT()) {
throw new UnsupportedOperationException();
@@ -2276,9 +2368,12 @@
* @return Builder for chaining.
*
* @see #setBridgedModeOpportunisticShutdownEnabled(boolean)
+ *
+ * @hide
*/
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
@NonNull
+ @SystemApi
public Builder setBridgedModeOpportunisticShutdownTimeoutMillis(
@IntRange(from = -1) long timeoutMillis) {
if (!SdkLevel.isAtLeastT()) {
@@ -2311,10 +2406,13 @@
* @param vendorData List of {@link OuiKeyedData} containing the vendor-provided
* configuration data. Note that multiple elements with the same OUI are allowed.
* @return Builder for chaining.
+ *
+ * @hide
*/
@RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
@NonNull
+ @SystemApi
public Builder setVendorData(@NonNull List<OuiKeyedData> vendorData) {
if (!SdkLevel.isAtLeastV()) {
throw new UnsupportedOperationException();
@@ -2325,5 +2423,28 @@
mVendorData = vendorData;
return this;
}
+
+ /**
+ * Specifies whether or not client isolation is enabled.
+ *
+ * Client isolation can be used to disallow a connected Soft AP
+ * client to communicate with other connected clients.
+ *
+ * @param isClientIsolationEnabled true when enabling client isolation.
+ * @return Builder for chaining.
+ *
+ * @hide
+ */
+ @FlaggedApi(Flags.FLAG_AP_ISOLATE)
+ @RequiresApi(Build.VERSION_CODES.BAKLAVA)
+ @NonNull
+ @SystemApi
+ public Builder setClientIsolationEnabled(boolean isClientIsolationEnabled) {
+ if (!Environment.isSdkAtLeastB()) {
+ throw new UnsupportedOperationException();
+ }
+ mIsClientIsolationEnabled = isClientIsolationEnabled;
+ return this;
+ }
}
}
diff --git a/framework/java/android/net/wifi/SoftApInfo.java b/framework/java/android/net/wifi/SoftApInfo.java
index f4440e9..fac3fd4 100644
--- a/framework/java/android/net/wifi/SoftApInfo.java
+++ b/framework/java/android/net/wifi/SoftApInfo.java
@@ -166,6 +166,10 @@
/** List of {@link OuiKeyedData} containing vendor-specific configuration data. */
private List<OuiKeyedData> mVendorData = Collections.emptyList();
+ /** The multiple link device (MLD) MAC Address which Wi-Fi 7 AP resides on. */
+ @Nullable
+ private MacAddress mMldAddress;
+
/**
* Get the frequency which AP resides on.
*/
@@ -355,6 +359,28 @@
}
/**
+ * Get the multiple link device MAC address which Wi-Fi AP resides on.
+ * Null when AP disabled or non Wi-Fi 7 AP.
+ */
+ @FlaggedApi(Flags.FLAG_MLO_SAP)
+ @Nullable
+ public MacAddress getMldAddress() {
+ return mMldAddress;
+ }
+
+ /**
+ * Set the multi-link address (MLA) of the multi-link device (MLD) on the Wi-Fi AP.
+ * <p>
+ * <li>If not set (non Wi-Fi 7 Soft AP), defaults to null.</li>
+ * @param mldAddress multiple link device MAC address.
+ *
+ * @hide
+ */
+ public void setMldAddress(@Nullable MacAddress mldAddress) {
+ mMldAddress = mldAddress;
+ }
+
+ /**
* @hide
*/
public SoftApInfo(@Nullable SoftApInfo source) {
@@ -366,6 +392,7 @@
mApInstanceIdentifier = source.mApInstanceIdentifier;
mIdleShutdownTimeoutMillis = source.mIdleShutdownTimeoutMillis;
mVendorData = new ArrayList<>(source.mVendorData);
+ mMldAddress = source.mMldAddress;
}
}
@@ -391,6 +418,7 @@
dest.writeString(mApInstanceIdentifier);
dest.writeLong(mIdleShutdownTimeoutMillis);
dest.writeList(mVendorData);
+ dest.writeParcelable(mMldAddress, flags);
}
@NonNull
@@ -405,6 +433,7 @@
info.mApInstanceIdentifier = in.readString();
info.mIdleShutdownTimeoutMillis = in.readLong();
info.mVendorData = ParcelUtil.readOuiKeyedDataList(in);
+ info.mMldAddress = in.readParcelable(MacAddress.class.getClassLoader());
return info;
}
@@ -425,6 +454,7 @@
sbuf.append(", mApInstanceIdentifier= ").append(mApInstanceIdentifier);
sbuf.append(", mIdleShutdownTimeoutMillis= ").append(mIdleShutdownTimeoutMillis);
sbuf.append(", mVendorData= ").append(mVendorData);
+ if (mMldAddress != null) sbuf.append(",mMldAddress=").append(mBssid.toString());
sbuf.append("}");
return sbuf.toString();
}
@@ -440,12 +470,13 @@
&& mWifiStandard == softApInfo.mWifiStandard
&& Objects.equals(mApInstanceIdentifier, softApInfo.mApInstanceIdentifier)
&& mIdleShutdownTimeoutMillis == softApInfo.mIdleShutdownTimeoutMillis
- && Objects.equals(mVendorData, softApInfo.mVendorData);
+ && Objects.equals(mVendorData, softApInfo.mVendorData)
+ && Objects.equals(mMldAddress, softApInfo.mMldAddress);
}
@Override
public int hashCode() {
return Objects.hash(mFrequency, mBandwidth, mBssid, mWifiStandard, mApInstanceIdentifier,
- mIdleShutdownTimeoutMillis, mVendorData);
+ mIdleShutdownTimeoutMillis, mVendorData, mMldAddress);
}
}
diff --git a/framework/java/android/net/wifi/WifiAnnotations.java b/framework/java/android/net/wifi/WifiAnnotations.java
index 2a92c31..7013b2b 100644
--- a/framework/java/android/net/wifi/WifiAnnotations.java
+++ b/framework/java/android/net/wifi/WifiAnnotations.java
@@ -176,4 +176,71 @@
UriParserResults.URI_SCHEME_DPP,
})
public @interface UriScheme {}
+
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = {"REASON_"}, value = {
+ DeauthenticationReasonCode.REASON_UNKNOWN,
+ DeauthenticationReasonCode.REASON_UNSPECIFIED,
+ DeauthenticationReasonCode.REASON_PREV_AUTH_NOT_VALID,
+ DeauthenticationReasonCode.REASON_DEAUTH_LEAVING,
+ DeauthenticationReasonCode.REASON_DISASSOC_DUE_TO_INACTIVITY,
+ DeauthenticationReasonCode.REASON_DISASSOC_AP_BUSY,
+ DeauthenticationReasonCode.REASON_CLASS2_FRAME_FROM_NONAUTH_STA,
+ DeauthenticationReasonCode.REASON_CLASS3_FRAME_FROM_NONASSOC_STA,
+ DeauthenticationReasonCode.REASON_DISASSOC_STA_HAS_LEFT,
+ DeauthenticationReasonCode.REASON_STA_REQ_ASSOC_WITHOUT_AUTH,
+ DeauthenticationReasonCode.REASON_PWR_CAPABILITY_NOT_VALID,
+ DeauthenticationReasonCode.REASON_SUPPORTED_CHANNEL_NOT_VALID,
+ DeauthenticationReasonCode.REASON_BSS_TRANSITION_DISASSOC,
+ DeauthenticationReasonCode.REASON_INVALID_IE,
+ DeauthenticationReasonCode.REASON_MICHAEL_MIC_FAILURE,
+ DeauthenticationReasonCode.REASON_FOURWAY_HANDSHAKE_TIMEOUT,
+ DeauthenticationReasonCode.REASON_GROUP_KEY_UPDATE_TIMEOUT,
+ DeauthenticationReasonCode.REASON_IE_IN_4WAY_DIFFERS,
+ DeauthenticationReasonCode.REASON_GROUP_CIPHER_NOT_VALID,
+ DeauthenticationReasonCode.REASON_PAIRWISE_CIPHER_NOT_VALID,
+ DeauthenticationReasonCode.REASON_AKMP_NOT_VALID,
+ DeauthenticationReasonCode.REASON_UNSUPPORTED_RSN_IE_VERSION,
+ DeauthenticationReasonCode.REASON_INVALID_RSN_IE_CAPAB,
+ DeauthenticationReasonCode.REASON_IEEE_802_1X_AUTH_FAILED,
+ DeauthenticationReasonCode.REASON_CIPHER_SUITE_REJECTED,
+ DeauthenticationReasonCode.REASON_TDLS_TEARDOWN_UNREACHABLE,
+ DeauthenticationReasonCode.REASON_TDLS_TEARDOWN_UNSPECIFIED,
+ DeauthenticationReasonCode.REASON_SSP_REQUESTED_DISASSOC,
+ DeauthenticationReasonCode.REASON_NO_SSP_ROAMING_AGREEMENT,
+ DeauthenticationReasonCode.REASON_BAD_CIPHER_OR_AKM,
+ DeauthenticationReasonCode.REASON_NOT_AUTHORIZED_THIS_LOCATION,
+ DeauthenticationReasonCode.REASON_SERVICE_CHANGE_PRECLUDES_TS,
+ DeauthenticationReasonCode.REASON_UNSPECIFIED_QOS_REASON,
+ DeauthenticationReasonCode.REASON_NOT_ENOUGH_BANDWIDTH,
+ DeauthenticationReasonCode.REASON_DISASSOC_LOW_ACK,
+ DeauthenticationReasonCode.REASON_EXCEEDED_TXOP,
+ DeauthenticationReasonCode.REASON_STA_LEAVING,
+ DeauthenticationReasonCode.REASON_END_TS_BA_DLS,
+ DeauthenticationReasonCode.REASON_UNKNOWN_TS_BA,
+ DeauthenticationReasonCode.REASON_TIMEOUT,
+ DeauthenticationReasonCode.REASON_PEERKEY_MISMATCH,
+ DeauthenticationReasonCode.REASON_AUTHORIZED_ACCESS_LIMIT_REACHED,
+ DeauthenticationReasonCode.REASON_EXTERNAL_SERVICE_REQUIREMENTS,
+ DeauthenticationReasonCode.REASON_INVALID_FT_ACTION_FRAME_COUNT,
+ DeauthenticationReasonCode.REASON_INVALID_PMKID,
+ DeauthenticationReasonCode.REASON_INVALID_MDE,
+ DeauthenticationReasonCode.REASON_INVALID_FTE,
+ DeauthenticationReasonCode.REASON_MESH_PEERING_CANCELLED,
+ DeauthenticationReasonCode.REASON_MESH_MAX_PEERS,
+ DeauthenticationReasonCode.REASON_MESH_CONFIG_POLICY_VIOLATION,
+ DeauthenticationReasonCode.REASON_MESH_CLOSE_RCVD,
+ DeauthenticationReasonCode.REASON_MESH_MAX_RETRIES,
+ DeauthenticationReasonCode.REASON_MESH_CONFIRM_TIMEOUT,
+ DeauthenticationReasonCode.REASON_MESH_INVALID_GTK,
+ DeauthenticationReasonCode.REASON_MESH_INCONSISTENT_PARAMS,
+ DeauthenticationReasonCode.REASON_MESH_INVALID_SECURITY_CAP,
+ DeauthenticationReasonCode.REASON_MESH_PATH_ERROR_NO_PROXY_INFO,
+ DeauthenticationReasonCode.REASON_MESH_PATH_ERROR_NO_FORWARDING_INFO,
+ DeauthenticationReasonCode.REASON_MESH_PATH_ERROR_DEST_UNREACHABLE,
+ DeauthenticationReasonCode.REASON_MAC_ADDRESS_ALREADY_EXISTS_IN_MBSS,
+ DeauthenticationReasonCode.REASON_MESH_CHANNEL_SWITCH_REGULATORY_REQ,
+ DeauthenticationReasonCode.REASON_MESH_CHANNEL_SWITCH_UNSPECIFIED,
+ })
+ public @interface SoftApDisconnectReason {}
}
diff --git a/framework/java/android/net/wifi/WifiClient.java b/framework/java/android/net/wifi/WifiClient.java
index c69b039..cd3e8c5 100644
--- a/framework/java/android/net/wifi/WifiClient.java
+++ b/framework/java/android/net/wifi/WifiClient.java
@@ -16,6 +16,7 @@
package android.net.wifi;
+import android.annotation.FlaggedApi;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
@@ -24,6 +25,8 @@
import android.os.Parcelable;
import android.util.Log;
+import com.android.wifi.flags.Flags;
+
import java.util.Objects;
/** @hide */
@@ -38,6 +41,15 @@
private final String mApInstanceIdentifier;
/**
+ * Reason for disconnection, if known.
+ *
+ * <p>This field is only meaningful when a client disconnects.
+ * It will not be updated while a client is connected.
+ */
+ @WifiAnnotations.SoftApDisconnectReason
+ private final int mDisconnectReason;
+
+ /**
* The mac address of this client.
*/
@NonNull
@@ -58,13 +70,35 @@
return mApInstanceIdentifier;
}
+ /**
+ * Get the reason the client disconnected from the AP.
+ *
+ * <p>This field is only populated when the WifiClient is returned via
+ * {@link WifiManager.SoftApCallback#onClientsDisconnected}.
+ * The value {@link DeauthenticationReasonCode#REASON_UNKNOWN} is used as the default value
+ * and in the case where a client connects.
+ * @return a disconnection reason code to provide information on why the disconnect happened.
+ */
+ @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON)
+ @WifiAnnotations.SoftApDisconnectReason
+ public int getDisconnectReason() {
+ return mDisconnectReason;
+ }
+
private WifiClient(Parcel in) {
mMacAddress = in.readParcelable(null);
mApInstanceIdentifier = in.readString();
+ mDisconnectReason = in.readInt();
}
/** @hide */
public WifiClient(@NonNull MacAddress macAddress, @NonNull String apInstanceIdentifier) {
+ this(macAddress, apInstanceIdentifier, DeauthenticationReasonCode.REASON_UNKNOWN);
+ }
+
+ /** @hide */
+ public WifiClient(@NonNull MacAddress macAddress, @NonNull String apInstanceIdentifier,
+ @WifiAnnotations.SoftApDisconnectReason int disconnectReason) {
if (macAddress == null) {
Log.wtf(TAG, "Null MacAddress provided");
this.mMacAddress = WifiManager.ALL_ZEROS_MAC_ADDRESS;
@@ -72,6 +106,7 @@
this.mMacAddress = macAddress;
}
this.mApInstanceIdentifier = apInstanceIdentifier;
+ this.mDisconnectReason = disconnectReason;
}
@Override
@@ -83,6 +118,7 @@
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeParcelable(mMacAddress, flags);
dest.writeString(mApInstanceIdentifier);
+ dest.writeInt(mDisconnectReason);
}
@NonNull
@@ -102,20 +138,21 @@
return "WifiClient{"
+ "mMacAddress=" + mMacAddress
+ "mApInstanceIdentifier=" + mApInstanceIdentifier
+ + "mDisconnectReason=" + mDisconnectReason
+ '}';
}
@Override
public boolean equals(@Nullable Object o) {
if (this == o) return true;
- if (!(o instanceof WifiClient)) return false;
- WifiClient client = (WifiClient) o;
+ if (!(o instanceof WifiClient client)) return false;
return Objects.equals(mMacAddress, client.mMacAddress)
- && mApInstanceIdentifier.equals(client.mApInstanceIdentifier);
+ && mApInstanceIdentifier.equals(client.mApInstanceIdentifier)
+ && mDisconnectReason == client.mDisconnectReason;
}
@Override
public int hashCode() {
- return Objects.hash(mMacAddress, mApInstanceIdentifier);
+ return Objects.hash(mMacAddress, mApInstanceIdentifier, mDisconnectReason);
}
}
diff --git a/framework/java/android/net/wifi/WifiFrameworkInitializer.java b/framework/java/android/net/wifi/WifiFrameworkInitializer.java
index 8b59393..d6117ba 100644
--- a/framework/java/android/net/wifi/WifiFrameworkInitializer.java
+++ b/framework/java/android/net/wifi/WifiFrameworkInitializer.java
@@ -21,10 +21,14 @@
import android.content.pm.PackageManager;
import android.net.wifi.aware.IWifiAwareManager;
import android.net.wifi.aware.WifiAwareManager;
+import android.net.wifi.flags.Flags;
import android.net.wifi.p2p.IWifiP2pManager;
import android.net.wifi.p2p.WifiP2pManager;
import android.net.wifi.rtt.IWifiRttManager;
import android.net.wifi.rtt.WifiRttManager;
+import android.net.wifi.usd.IUsdManager;
+import android.net.wifi.usd.UsdManager;
+import android.net.wifi.util.Environment;
import android.os.HandlerThread;
import android.os.Looper;
@@ -145,5 +149,19 @@
return new RttManager(context, wifiRttManager);
}
);
+ if (Flags.usd() && Environment.isSdkAtLeastB()) {
+ SystemServiceRegistry.registerContextAwareService(
+ Context.WIFI_USD_SERVICE,
+ UsdManager.class,
+ (context, serviceBinder) -> {
+ if (!context.getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_WIFI)) {
+ return null;
+ }
+ IUsdManager service = IUsdManager.Stub.asInterface(serviceBinder);
+ return new UsdManager(context, service);
+ }
+ );
+ }
}
}
diff --git a/framework/java/android/net/wifi/WifiInfo.java b/framework/java/android/net/wifi/WifiInfo.java
index 8e233d7..11be211 100644
--- a/framework/java/android/net/wifi/WifiInfo.java
+++ b/framework/java/android/net/wifi/WifiInfo.java
@@ -794,8 +794,9 @@
* @return the SSID.
*/
public String getSSID() {
- if (mWifiSsid != null) {
- String ssidString = mWifiSsid.toString();
+ WifiSsid ssid = mWifiSsid;
+ if (ssid != null) {
+ String ssidString = ssid.toString();
if (!TextUtils.isEmpty(ssidString)) {
return ssidString;
}
diff --git a/framework/java/android/net/wifi/WifiManager.java b/framework/java/android/net/wifi/WifiManager.java
index 4ab897e..c1e6646 100644
--- a/framework/java/android/net/wifi/WifiManager.java
+++ b/framework/java/android/net/wifi/WifiManager.java
@@ -68,6 +68,7 @@
import android.net.wifi.twt.TwtRequest;
import android.net.wifi.twt.TwtSession;
import android.net.wifi.twt.TwtSessionCallback;
+import android.net.wifi.util.Environment;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
@@ -79,6 +80,7 @@
import android.os.RemoteException;
import android.os.WorkSource;
import android.os.connectivity.WifiActivityEnergyInfo;
+import android.security.advancedprotection.AdvancedProtectionFeature;
import android.telephony.SubscriptionInfo;
import android.text.TextUtils;
import android.util.ArraySet;
@@ -1130,6 +1132,17 @@
*/
public static final String EXTRA_PREVIOUS_WIFI_STATE = "previous_wifi_state";
+ /** @hide */
+ @IntDef(flag = false, prefix = { "WIFI_STATE_" }, value = {
+ WIFI_STATE_DISABLING,
+ WIFI_STATE_DISABLED,
+ WIFI_STATE_ENABLING,
+ WIFI_STATE_ENABLED,
+ WIFI_STATE_UNKNOWN,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface WifiState {}
+
/**
* Wi-Fi is currently being disabled. The state will change to {@link #WIFI_STATE_DISABLED} if
* it finishes successfully.
@@ -2108,6 +2121,8 @@
sOnWifiNetworkStateChangedListenerMap = new SparseArray<>();
private static final SparseArray<IWifiLowLatencyLockListener>
sWifiLowLatencyLockListenerMap = new SparseArray<>();
+ private static final SparseArray<IWifiStateChangedListener>
+ sWifiStateChangedListenerMap = new SparseArray<>();
/**
* Multi-link operation (MLO) will allow Wi-Fi devices to operate on multiple links at the same
@@ -3852,208 +3867,210 @@
}
/** @hide */
- public static final long WIFI_FEATURE_INFRA = 1L << 0; // Basic infrastructure mode
+ public static final int WIFI_FEATURE_INFRA = 0; // Basic infrastructure mode
/** @hide */
- public static final long WIFI_FEATURE_PASSPOINT = 1L << 2; // Support for GAS/ANQP
+ public static final int WIFI_FEATURE_PASSPOINT = 2; // Support for GAS/ANQP
/** @hide */
- public static final long WIFI_FEATURE_P2P = 1L << 3; // Wifi-Direct
+ public static final int WIFI_FEATURE_P2P = 3; // Wifi-Direct
/** @hide */
- public static final long WIFI_FEATURE_MOBILE_HOTSPOT = 1L << 4; // Soft AP
+ public static final int WIFI_FEATURE_MOBILE_HOTSPOT = 4; // Soft AP
/** @hide */
- public static final long WIFI_FEATURE_SCANNER = 1L << 5; // WifiScanner APIs
+ public static final int WIFI_FEATURE_SCANNER = 5; // WifiScanner APIs
/** @hide */
- public static final long WIFI_FEATURE_AWARE = 1L << 6; // Wi-Fi Aware networking
+ public static final int WIFI_FEATURE_AWARE = 6; // Wi-Fi Aware networking
/** @hide */
- public static final long WIFI_FEATURE_D2D_RTT = 1L << 7; // Device-to-device RTT
+ public static final int WIFI_FEATURE_D2D_RTT = 7; // Device-to-device RTT
/** @hide */
- public static final long WIFI_FEATURE_D2AP_RTT = 1L << 8; // Device-to-AP RTT
+ public static final int WIFI_FEATURE_D2AP_RTT = 8; // Device-to-AP RTT
/** @hide */
- public static final long WIFI_FEATURE_PNO = 1L << 10; // Preferred network offload
+ public static final int WIFI_FEATURE_PNO = 10; // Preferred network offload
/** @hide */
- public static final long WIFI_FEATURE_TDLS = 1L << 12; // Tunnel directed link setup
+ public static final int WIFI_FEATURE_TDLS = 12; // Tunnel directed link setup
/** @hide */
- public static final long WIFI_FEATURE_TDLS_OFFCHANNEL = 1L << 13; // TDLS off channel
+ public static final int WIFI_FEATURE_TDLS_OFFCHANNEL = 13; // TDLS off channel
/** @hide */
- public static final long WIFI_FEATURE_AP_STA = 1L << 15; // AP STA Concurrency
+ public static final int WIFI_FEATURE_AP_STA = 15; // AP STA Concurrency
/** @hide */
- public static final long WIFI_FEATURE_LINK_LAYER_STATS = 1L << 16; // Link layer stats
+ public static final int WIFI_FEATURE_LINK_LAYER_STATS = 16; // Link layer stats
/** @hide */
- public static final long WIFI_FEATURE_LOGGER = 1L << 17; // WiFi Logger
+ public static final int WIFI_FEATURE_LOGGER = 17; // WiFi Logger
/** @hide */
- public static final long WIFI_FEATURE_RSSI_MONITOR = 1L << 19; // RSSI Monitor
+ public static final int WIFI_FEATURE_RSSI_MONITOR = 19; // RSSI Monitor
/** @hide */
- public static final long WIFI_FEATURE_MKEEP_ALIVE = 1L << 20; // mkeep_alive
+ public static final int WIFI_FEATURE_MKEEP_ALIVE = 20; // mkeep_alive
/** @hide */
- public static final long WIFI_FEATURE_CONFIG_NDO = 1L << 21; // ND offload
+ public static final int WIFI_FEATURE_CONFIG_NDO = 21; // ND offload
/** @hide */
- public static final long WIFI_FEATURE_CONTROL_ROAMING = 1L << 23; // Control firmware roaming
+ public static final int WIFI_FEATURE_CONTROL_ROAMING = 23; // Control firmware roaming
/** @hide */
- public static final long WIFI_FEATURE_IE_WHITELIST = 1L << 24; // Probe IE white listing
+ public static final int WIFI_FEATURE_IE_WHITELIST = 24; // Probe IE white listing
/** @hide */
- public static final long WIFI_FEATURE_SCAN_RAND = 1L << 25; // Random MAC & Probe seq
+ public static final int WIFI_FEATURE_SCAN_RAND = 25; // Random MAC & Probe seq
/** @hide */
- public static final long WIFI_FEATURE_TX_POWER_LIMIT = 1L << 26; // Set Tx power limit
+ public static final int WIFI_FEATURE_TX_POWER_LIMIT = 26; // Set Tx power limit
/** @hide */
- public static final long WIFI_FEATURE_WPA3_SAE = 1L << 27; // WPA3-Personal SAE
+ public static final int WIFI_FEATURE_WPA3_SAE = 27; // WPA3-Personal SAE
/** @hide */
- public static final long WIFI_FEATURE_WPA3_SUITE_B = 1L << 28; // WPA3-Enterprise Suite-B
+ public static final int WIFI_FEATURE_WPA3_SUITE_B = 28; // WPA3-Enterprise Suite-B
/** @hide */
- public static final long WIFI_FEATURE_OWE = 1L << 29; // Enhanced Open
+ public static final int WIFI_FEATURE_OWE = 29; // Enhanced Open
/** @hide */
- public static final long WIFI_FEATURE_LOW_LATENCY = 1L << 30; // Low Latency modes
+ public static final int WIFI_FEATURE_LOW_LATENCY = 30; // Low Latency modes
/** @hide */
- public static final long WIFI_FEATURE_DPP = 1L << 31; // DPP (Easy-Connect)
+ public static final int WIFI_FEATURE_DPP = 31; // DPP (Easy-Connect)
/** @hide */
- public static final long WIFI_FEATURE_P2P_RAND_MAC = 1L << 32; // Random P2P MAC
+ public static final int WIFI_FEATURE_P2P_RAND_MAC = 32; // Random P2P MAC
/** @hide */
- public static final long WIFI_FEATURE_CONNECTED_RAND_MAC = 1L << 33; // Random STA MAC
+ public static final int WIFI_FEATURE_CONNECTED_RAND_MAC = 33; // Random STA MAC
/** @hide */
- public static final long WIFI_FEATURE_AP_RAND_MAC = 1L << 34; // Random AP MAC
+ public static final int WIFI_FEATURE_AP_RAND_MAC = 34; // Random AP MAC
/** @hide */
- public static final long WIFI_FEATURE_MBO = 1L << 35; // MBO Support
+ public static final int WIFI_FEATURE_MBO = 35; // MBO Support
/** @hide */
- public static final long WIFI_FEATURE_OCE = 1L << 36; // OCE Support
+ public static final int WIFI_FEATURE_OCE = 36; // OCE Support
/** @hide */
- public static final long WIFI_FEATURE_WAPI = 1L << 37; // WAPI
+ public static final int WIFI_FEATURE_WAPI = 37; // WAPI
/** @hide */
- public static final long WIFI_FEATURE_FILS_SHA256 = 1L << 38; // FILS-SHA256
+ public static final int WIFI_FEATURE_FILS_SHA256 = 38; // FILS-SHA256
/** @hide */
- public static final long WIFI_FEATURE_FILS_SHA384 = 1L << 39; // FILS-SHA384
+ public static final int WIFI_FEATURE_FILS_SHA384 = 39; // FILS-SHA384
/** @hide */
- public static final long WIFI_FEATURE_SAE_PK = 1L << 40; // SAE-PK
+ public static final int WIFI_FEATURE_SAE_PK = 40; // SAE-PK
/** @hide */
- public static final long WIFI_FEATURE_STA_BRIDGED_AP = 1L << 41; // STA + Bridged AP
+ public static final int WIFI_FEATURE_STA_BRIDGED_AP = 41; // STA + Bridged AP
/** @hide */
- public static final long WIFI_FEATURE_BRIDGED_AP = 1L << 42; // Bridged AP
+ public static final int WIFI_FEATURE_BRIDGED_AP = 42; // Bridged AP
/** @hide */
- public static final long WIFI_FEATURE_INFRA_60G = 1L << 43; // 60 GHz Band Support
+ public static final int WIFI_FEATURE_INFRA_60G = 43; // 60 GHz Band Support
/**
* Support for 2 STA's for the local-only (peer to peer) connection + internet connection
* concurrency.
* @hide
*/
- public static final long WIFI_FEATURE_ADDITIONAL_STA_LOCAL_ONLY = 1L << 44;
+ public static final int WIFI_FEATURE_ADDITIONAL_STA_LOCAL_ONLY = 44;
/**
* Support for 2 STA's for the make before break concurrency.
* @hide
*/
- public static final long WIFI_FEATURE_ADDITIONAL_STA_MBB = 1L << 45;
+ public static final int WIFI_FEATURE_ADDITIONAL_STA_MBB = 45;
/**
* Support for 2 STA's for the restricted connection + internet connection concurrency.
* @hide
*/
- public static final long WIFI_FEATURE_ADDITIONAL_STA_RESTRICTED = 1L << 46;
+ public static final int WIFI_FEATURE_ADDITIONAL_STA_RESTRICTED = 46;
/**
* DPP (Easy-Connect) Enrollee Responder mode support
* @hide
*/
- public static final long WIFI_FEATURE_DPP_ENROLLEE_RESPONDER = 1L << 47;
+ public static final int WIFI_FEATURE_DPP_ENROLLEE_RESPONDER = 47;
/**
* Passpoint Terms and Conditions feature support
* @hide
*/
- public static final long WIFI_FEATURE_PASSPOINT_TERMS_AND_CONDITIONS = 1L << 48;
+ public static final int WIFI_FEATURE_PASSPOINT_TERMS_AND_CONDITIONS = 48;
/** @hide */
- public static final long WIFI_FEATURE_SAE_H2E = 1L << 49; // Hash-to-Element
+ public static final int WIFI_FEATURE_SAE_H2E = 49; // Hash-to-Element
/** @hide */
- public static final long WIFI_FEATURE_WFD_R2 = 1L << 50; // Wi-Fi Display R2
+ public static final int WIFI_FEATURE_WFD_R2 = 50; // Wi-Fi Display R2
/**
* RFC 7542 decorated identity support
* @hide */
- public static final long WIFI_FEATURE_DECORATED_IDENTITY = 1L << 51;
+ public static final int WIFI_FEATURE_DECORATED_IDENTITY = 51;
/**
* Trust On First Use support for WPA Enterprise network
* @hide
*/
- public static final long WIFI_FEATURE_TRUST_ON_FIRST_USE = 1L << 52;
+ public static final int WIFI_FEATURE_TRUST_ON_FIRST_USE = 52;
/**
* Support for 2 STA's multi internet concurrency.
* @hide
*/
- public static final long WIFI_FEATURE_ADDITIONAL_STA_MULTI_INTERNET = 1L << 53;
+ public static final int WIFI_FEATURE_ADDITIONAL_STA_MULTI_INTERNET = 53;
/**
* Support for DPP (Easy-Connect) AKM.
* @hide
*/
- public static final long WIFI_FEATURE_DPP_AKM = 1L << 54;
+ public static final int WIFI_FEATURE_DPP_AKM = 54;
/**
* Support for setting TLS minimum version.
* @hide
*/
- public static final long WIFI_FEATURE_SET_TLS_MINIMUM_VERSION = 1L << 55;
+ public static final int WIFI_FEATURE_SET_TLS_MINIMUM_VERSION = 55;
/**
* Support for TLS v.13.
* @hide
*/
- public static final long WIFI_FEATURE_TLS_V1_3 = 1L << 56;
+ public static final int WIFI_FEATURE_TLS_V1_3 = 56;
/**
* Support for Dual Band Simultaneous (DBS) operation.
* @hide
*/
- public static final long WIFI_FEATURE_DUAL_BAND_SIMULTANEOUS = 1L << 57;
+ public static final int WIFI_FEATURE_DUAL_BAND_SIMULTANEOUS = 57;
/**
* Support for TID-To-Link Mapping negotiation.
* @hide
*/
- public static final long WIFI_FEATURE_T2LM_NEGOTIATION = 1L << 58;
+ public static final int WIFI_FEATURE_T2LM_NEGOTIATION = 58;
/**
* Support for WEP Wi-Fi Network
* @hide
*/
- public static final long WIFI_FEATURE_WEP = 1L << 59;
+ public static final int WIFI_FEATURE_WEP = 59;
/**
* Support for WPA PERSONAL Wi-Fi Network
* @hide
*/
- public static final long WIFI_FEATURE_WPA_PERSONAL = 1L << 60;
+ public static final int WIFI_FEATURE_WPA_PERSONAL = 60;
/**
* Support for Roaming Mode
* @hide
*/
- public static final long WIFI_FEATURE_AGGRESSIVE_ROAMING_MODE_SUPPORT = 1L << 61;
+ public static final int WIFI_FEATURE_AGGRESSIVE_ROAMING_MODE_SUPPORT = 61;
/**
* Supports device-to-device connections when infra STA is disabled.
* @hide
*/
- public static final long WIFI_FEATURE_D2D_WHEN_INFRA_STA_DISABLED = 1L << 62;
+ public static final int WIFI_FEATURE_D2D_WHEN_INFRA_STA_DISABLED = 62;
- private long getSupportedFeatures() {
+ /**
+ * Support for Soft AP multi-links operation.
+ * @hide
+ */
+ public static final int WIFI_FEATURE_SOFTAP_MLO = 63;
+
+ private boolean isFeatureSupported(int feature) {
try {
- return mService.getSupportedFeatures();
+ return mService.isFeatureSupported(feature);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
- private boolean isFeatureSupported(long feature) {
- return (getSupportedFeatures() & feature) == feature;
- }
-
/**
* @return true if this adapter supports Passpoint
* @hide
@@ -5372,6 +5389,107 @@
}
/**
+ * Register a callback for Wi-Fi state. See {@link WifiStateChangedListener}.
+ * Caller will receive the event when the Wi-Fi state changes.
+ * Caller can remove a previously registered callback using
+ * {@link WifiManager#removeWifiStateChangedListener(WifiStateChangedListener)}
+ *
+ * @param executor Executor to execute listener callback on
+ * @param listener Listener to register
+ */
+ @FlaggedApi(Flags.FLAG_WIFI_STATE_CHANGED_LISTENER)
+ @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE)
+ public void addWifiStateChangedListener(@NonNull @CallbackExecutor Executor executor,
+ @NonNull WifiStateChangedListener listener) {
+ Objects.requireNonNull(executor);
+ Objects.requireNonNull(listener);
+ if (mVerboseLoggingEnabled) {
+ Log.d(TAG, "addWifiStateChangedListener: listener=" + listener
+ + ", executor=" + executor);
+ }
+ final int listenerIdentifier = System.identityHashCode(listener);
+ synchronized (sWifiStateChangedListenerMap) {
+ try {
+ if (sWifiStateChangedListenerMap.contains(listenerIdentifier)) {
+ Log.w(TAG, "Same listener already registered");
+ return;
+ }
+ IWifiStateChangedListener.Stub listenerProxy =
+ new WifiStateChangedListenerProxy(executor, listener);
+ sWifiStateChangedListenerMap.put(listenerIdentifier, listenerProxy);
+ mService.addWifiStateChangedListener(listenerProxy);
+ } catch (RemoteException e) {
+ sWifiStateChangedListenerMap.remove(listenerIdentifier);
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ }
+
+ /**
+ * Unregisters a WifiStateChangedListener from listening on the current Wi-Fi state.
+ *
+ * @param listener WifiStateChangedListener to unregister
+ */
+ @FlaggedApi(Flags.FLAG_WIFI_STATE_CHANGED_LISTENER)
+ @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE)
+ public void removeWifiStateChangedListener(@NonNull WifiStateChangedListener listener) {
+ Objects.requireNonNull(listener);
+ if (mVerboseLoggingEnabled) {
+ Log.d(TAG, "removeWifiStateChangedListener: listener=" + listener);
+ }
+ final int listenerIdentifier = System.identityHashCode(listener);
+ synchronized (sWifiStateChangedListenerMap) {
+ try {
+ if (!sWifiStateChangedListenerMap.contains(listenerIdentifier)) {
+ Log.w(TAG, "Unknown external listener " + listenerIdentifier);
+ return;
+ }
+ mService.removeWifiStateChangedListener(
+ sWifiStateChangedListenerMap.get(listenerIdentifier));
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ } finally {
+ sWifiStateChangedListenerMap.remove(listenerIdentifier);
+ }
+ }
+ }
+
+ /**
+ * Listener interface for applications to be notified when the Wi-Fi enabled state changes.
+ */
+ @FlaggedApi(Flags.FLAG_WIFI_STATE_CHANGED_LISTENER)
+ public interface WifiStateChangedListener {
+ /**
+ * Called when the Wi-Fi enabled state changes.
+ * The new value can be queried via {@link WifiManager#getWifiState()}.
+ */
+ void onWifiStateChanged();
+ }
+
+ /**
+ * Listener proxy for WifiStateChangedListener objects.
+ */
+ private static class WifiStateChangedListenerProxy extends IWifiStateChangedListener.Stub {
+ private Executor mExecutor;
+ private WifiStateChangedListener mListener;
+
+ WifiStateChangedListenerProxy(@NonNull Executor executor,
+ @NonNull WifiStateChangedListener listener) {
+ Objects.requireNonNull(executor);
+ Objects.requireNonNull(listener);
+ mExecutor = executor;
+ mListener = listener;
+ }
+
+ @Override
+ public void onWifiStateChanged() {
+ Log.i(TAG, "WifiStateChangedListenerProxy: onWifiStateChanged");
+ Binder.clearCallingIdentity();
+ mExecutor.execute(() -> mListener.onWifiStateChanged());
+ }
+ }
+
+ /**
* Calculates the level of the signal. This should be used any time a signal
* is being shown.
*
@@ -5864,9 +5982,37 @@
public void startLocalOnlyHotspot(LocalOnlyHotspotCallback callback,
@Nullable Handler handler) {
Executor executor = handler == null ? null : new HandlerExecutor(handler);
- startLocalOnlyHotspotInternal(null, executor, callback);
+ startLocalOnlyHotspotInternal(null, executor, callback, false);
}
+ /**
+ * Starts a local-only hotspot with a specific configuration applied. See
+ * {@link #startLocalOnlyHotspot(LocalOnlyHotspotCallback, Handler)}.
+ *
+ * Since custom configuration settings may be incompatible with each other, the hotspot started
+ * through this method cannot coexist with another hotspot created through
+ * {@link #startLocalOnlyHotspot(LocalOnlyHotspotCallback, Handler)}. If this is attempted,
+ * the first hotspot request wins and others receive
+ * {@link LocalOnlyHotspotCallback#ERROR_GENERIC} through
+ * {@link LocalOnlyHotspotCallback#onFailed}.
+ *
+ * @param config Custom configuration for the hotspot. See {@link SoftApConfiguration}.
+ * @param executor Executor to run callback methods on.
+ * @param callback LocalOnlyHotspotCallback for the application to receive updates about
+ * operating status.
+ */
+ @RequiresPermission(allOf = {CHANGE_WIFI_STATE, NEARBY_WIFI_DEVICES})
+ @FlaggedApi(Flags.FLAG_PUBLIC_BANDS_FOR_LOHS)
+ public void startLocalOnlyHotspotWithConfiguration(@NonNull SoftApConfiguration config,
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull LocalOnlyHotspotCallback callback) {
+ Objects.requireNonNull(config);
+ Objects.requireNonNull(executor);
+ Objects.requireNonNull(callback);
+ startLocalOnlyHotspotInternal(config, executor, callback, false);
+ }
+
+
/**
* Starts a local-only hotspot with a specific configuration applied. See
* {@link #startLocalOnlyHotspot(LocalOnlyHotspotCallback, Handler)}.
@@ -5895,7 +6041,7 @@
@Nullable @CallbackExecutor Executor executor,
@Nullable LocalOnlyHotspotCallback callback) {
Objects.requireNonNull(config);
- startLocalOnlyHotspotInternal(config, executor, callback);
+ startLocalOnlyHotspotInternal(config, executor, callback, true);
}
/**
@@ -5909,7 +6055,8 @@
private void startLocalOnlyHotspotInternal(
@Nullable SoftApConfiguration config,
@Nullable @CallbackExecutor Executor executor,
- @Nullable LocalOnlyHotspotCallback callback) {
+ @Nullable LocalOnlyHotspotCallback callback,
+ boolean isCalledFromSystemApi) {
if (executor == null) {
executor = mContext.getMainExecutor();
}
@@ -5925,7 +6072,7 @@
mContext.getAttributionSource());
}
int returnCode = mService.startLocalOnlyHotspot(proxy, packageName, featureId,
- config, extras);
+ config, extras, isCalledFromSystemApi);
if (returnCode != LocalOnlyHotspotCallback.REQUEST_REGISTERED) {
// Send message to the proxy to make sure we call back on the correct thread
proxy.onHotspotFailed(returnCode);
@@ -6772,6 +6919,17 @@
@SapClientBlockedReason int blockedReason) {
// Do nothing: can be used to ask user to update client to allowed list or blocked list.
}
+
+ /**
+ * Called when clients disconnect from a soft AP instance.
+ *
+ * @param info The {@link SoftApInfo} of the AP.
+ * @param clients The clients that have disconnected from the AP instance specified by
+ * {@code info}.
+ */
+ @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON)
+ default void onClientsDisconnected(@NonNull SoftApInfo info,
+ @NonNull List<WifiClient> clients) {}
}
/**
@@ -6949,6 +7107,18 @@
mCallback.onBlockedClientConnecting(client, blockedReason);
});
}
+
+ @Override
+ public void onClientsDisconnected(SoftApInfo info, List<WifiClient> clients) {
+ if (mVerboseLoggingEnabled) {
+ Log.v(TAG, "SoftApCallbackProxy on mode " + mIpMode
+ + ", onClientsDisconnected: info =" + info
+ + " with clients = " + clients);
+ }
+
+ Binder.clearCallingIdentity();
+ mExecutor.execute(() -> mCallback.onClientsDisconnected(info, clients));
+ }
}
/**
@@ -8282,7 +8452,7 @@
mService.acquireMulticastLock(mBinder, mTag);
synchronized (WifiManager.this) {
if (mActiveLockCount >= MAX_ACTIVE_LOCKS) {
- mService.releaseMulticastLock(mTag);
+ mService.releaseMulticastLock(mBinder, mTag);
throw new UnsupportedOperationException(
"Exceeded maximum number of wifi locks");
}
@@ -8324,7 +8494,7 @@
synchronized (mBinder) {
if (mRefCounted ? (--mRefCount == 0) : (mHeld)) {
try {
- mService.releaseMulticastLock(mTag);
+ mService.releaseMulticastLock(mBinder, mTag);
synchronized (WifiManager.this) {
mActiveLockCount--;
}
@@ -10157,6 +10327,46 @@
}
/**
+ * If isFullCapture is true, capture everything in ring buffer
+ *
+ * If isFullCapture is false, extract WifiUsabilityStatsEntries from ring buffer whose
+ * timestamps are within [triggerStartTimeMillis, triggerStopTimeMillis) in WiFiMetrics, and
+ * store them as upload candidates.
+ *
+ * Source of elapsed time since boot will be android.os.SystemClock.elapsedRealtime()
+ *
+ * @param executor The executor on which callback will be invoked.
+ * @param resultsCallback An asynchronous callback that will return a execution result of
+ * mWifiMetrics.storeCapturedData
+ * @param triggerType data capture trigger type
+ * @param isFullCapture if we do full capture on ring buffer or not
+ * @param triggerStartTimeMillis data capture start timestamp, elapsed time since boot
+ * @param triggerStopTimeMillis data capture stop timestamp, elapsed time since boot
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE)
+ public void storeCapturedData(@NonNull @CallbackExecutor Executor executor,
+ @NonNull IntConsumer resultsCallback, int triggerType, boolean isFullCapture,
+ long triggerStartTimeMillis, long triggerStopTimeMillis) {
+ Objects.requireNonNull(executor, "executor cannot be null");
+ Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null");
+ try {
+ mService.storeCapturedData(triggerType, isFullCapture, triggerStartTimeMillis,
+ triggerStopTimeMillis, new IIntegerListener.Stub() {
+ @Override
+ public void onResult(int value) {
+ Binder.clearCallingIdentity();
+ executor.execute(() -> {
+ resultsCallback.accept(value);
+ });
+ }
+ });
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Callback interface for framework to receive network status updates and trigger of updating
* {@link WifiUsabilityStatsEntry}.
*
@@ -12868,4 +13078,213 @@
throw e.rethrowFromSystemServer();
}
}
+
+ /**
+ * Disallow Wi-Fi autojoin on ScanResults matching the selected security types.
+ * This does not restrict manual connections.
+ *
+ * @param restrictions An array of {@code WifiInfo.SECURITY_TYPE_*} values to disallow autojoin.
+ * An empty array will clear all restrictions. Note, certain combinations of
+ * restricted security types are not valid.
+ * 1. restrictions contains WifiInfo.SECURITY_TYPE_OWE,
+ * but not WifiInfo.SECURITY_TYPE_OPEN.
+ * 2. restrictions contains WifiInfo.SECURITY_TYPE_SAE,
+ * but not WifiInfo.SECURITY_TYPE_PSK.
+ * 3. restrictions contains WifiInfo.SECURITY_TYPE_EAP_WPA3_ENTERPRISE,
+ * but not WifiInfo.SECURITY_TYPE_EAP.
+ *
+ * Usage example:
+ * <pre>
+ * To disallow autojoin to Wi-Fi networks with security type, OPEN, WEP
+ * or OWE, use following argument.
+ *
+ * {@code
+ * int[] restrictions = {
+ * WifiInfo.SECURITY_TYPE_OPEN,
+ * WifiInfo.SECURITY_TYPE_WEP,
+ * WifiInfo.SECURITY_TYPE_OWE };
+ * wifiManager.setAutojoinDisallowedSecurityTypes(restrictions);
+ * }
+ *
+ * To clear autojoin restriction on all security types, use following
+ * argument.
+ *
+ * {@code
+ * wifiManager.setAutojoinDisallowedSecurityTypes(new int[0]);
+ * }
+ * </pre>
+ * @throws UnsupportedOperationException if the API is not supported.
+ * @hide
+ */
+ @SystemApi
+ @FlaggedApi(Flags.FLAG_AUTOJOIN_RESTRICTION_SECURITY_TYPES_API)
+ @RequiresApi(Build.VERSION_CODES.TIRAMISU)
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.NETWORK_SETTINGS,
+ MANAGE_WIFI_NETWORK_SELECTION
+ })
+ public void setAutojoinDisallowedSecurityTypes(
+ @NonNull @WifiAnnotations.SecurityType int[] restrictions) {
+ if (!SdkLevel.isAtLeastT()) {
+ throw new UnsupportedOperationException();
+ }
+ Objects.requireNonNull(restrictions, "restrictions cannot be null");
+ try {
+ Bundle extras = new Bundle();
+ extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE,
+ mContext.getAttributionSource());
+ int restrictionBitmap = 0;
+ for (int securityType : restrictions) {
+ restrictionBitmap |= 0x1 << securityType;
+ }
+ mService.setAutojoinDisallowedSecurityTypes(restrictionBitmap, extras);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Retrieves the autojoin disallowed Wi-Fi security types currently set for the device.
+ *
+ * @param executor The executor to run the callback on.
+ * @param resultsCallback The callback to receive the result. It will be called with an array
+ * of autojoin disallowedse security types from
+ * {@code WifiInfo.SECURITY_TYPE_*}.
+ * @throws UnsupportedOperationException if the API is not supported.
+ * @hide
+ */
+ @SystemApi
+ @FlaggedApi(Flags.FLAG_AUTOJOIN_RESTRICTION_SECURITY_TYPES_API)
+ @RequiresApi(Build.VERSION_CODES.TIRAMISU)
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.NETWORK_SETTINGS,
+ MANAGE_WIFI_NETWORK_SELECTION
+ })
+ public void getAutojoinDisallowedSecurityTypes(@NonNull @CallbackExecutor Executor executor,
+ @NonNull Consumer<int[]> resultsCallback) {
+ if (!SdkLevel.isAtLeastT()) {
+ throw new UnsupportedOperationException();
+ }
+ Objects.requireNonNull(executor, "executor cannot be null");
+ Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null");
+ try {
+ Bundle extras = new Bundle();
+ extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE,
+ mContext.getAttributionSource());
+ mService.getAutojoinDisallowedSecurityTypes(new IIntegerListener.Stub() {
+ @Override
+ public void onResult(int value) {
+ Binder.clearCallingIdentity();
+ executor.execute(() -> {
+ List<Integer> restrictions = new ArrayList<>();
+ for (int i = 0; i < Integer.SIZE; i++) {
+ if (((0x1 << i) & value) != 0) {
+ restrictions.add(i);
+ }
+ }
+ int[] results = new int[restrictions.size()];
+ for (int i = 0; i < restrictions.size(); i++) {
+ results[i] = restrictions.get(i);
+ }
+ resultsCallback.accept(results);
+ });
+ }
+ }, extras);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Indicates what {@link AdvancedProtectionFeature} are supported over Wi-Fi.
+ *
+ * The {@link AdvancedProtectionFeature} is the advanced protection feature
+ * providing protections which works when Android Advanced Protection Mode (AAPM)
+ * is enabled.
+ *
+ * @return a list of the supported features.
+ * @hide
+ */
+ @SystemApi
+ @FlaggedApi(android.security.Flags.FLAG_AAPM_API)
+ @RequiresApi(Build.VERSION_CODES.BAKLAVA)
+ @NonNull
+ public List<AdvancedProtectionFeature> getAvailableAdvancedProtectionFeatures() {
+ if (!Environment.isSdkAtLeastB()) {
+ throw new UnsupportedOperationException();
+ }
+ List<AdvancedProtectionFeature> features = new ArrayList<>();
+ if (Flags.wepDisabledInApm()) {
+ // TODO: b/362586268 Change to AdvancedProtectionManager.FEATURE_ID_DISALLOW_WEP
+ features.add(new AdvancedProtectionFeature("WEP"));
+ }
+ return features;
+ }
+
+ /**
+ * When the device is connected to a network suggested by calling app
+ * {@link #addNetworkSuggestions(List)}, this API provide a way to avoid the current connection
+ * without {@link #removeNetworkSuggestions(List)}. The disallowed network will be disconnected
+ * or roam to other networks.
+ * App can only use this API to control the current connected network
+ * which was suggested by this app.
+ *
+ * @param blockingOption Option to change for the network blocking {@link BlockingOption}
+ */
+ @FlaggedApi(Flags.FLAG_BSSID_BLOCKLIST_FOR_SUGGESTION)
+ @RequiresPermission(CHANGE_WIFI_STATE)
+ public void disallowCurrentSuggestedNetwork(@NonNull BlockingOption blockingOption) {
+ Objects.requireNonNull(blockingOption, "blockingOption cannot be null");
+ try {
+ mService.disallowCurrentSuggestedNetwork(blockingOption, mContext.getOpPackageName());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Return whether Unsynchronized Service Discovery (USD) subscriber is supported or not.
+ * @hide
+ */
+ @android.annotation.RequiresApi(Build.VERSION_CODES.BAKLAVA)
+ @SystemApi
+ @FlaggedApi(android.net.wifi.flags.Flags.FLAG_USD)
+ @RequiresPermission(MANAGE_WIFI_NETWORK_SELECTION)
+ public boolean isUsdSubscriberSupported() {
+ if (!Environment.isSdkAtLeastB()) {
+ throw new UnsupportedOperationException();
+ }
+ try {
+ return mService.isUsdSubscriberSupported();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Return whether Unsynchronized Service Discovery (USD) publisher is supported or not.
+ * <p>
+ * The USD publisher support is controlled by an overlay config_wifiUsdPublisherSupported.
+ * By default, the feature will be disabled because the publisher operation impacts other
+ * concurrency operation such as Station. The USD publisher switches channels and dwells a
+ * longer time (500 milliseconds to 1 second) on non-home channel which disrupts other
+ * concurrency operation.
+ *
+ * @return true if publisher feature is supported, otherwise false.
+ * @hide
+ */
+ @android.annotation.RequiresApi(Build.VERSION_CODES.BAKLAVA)
+ @SystemApi
+ @FlaggedApi(android.net.wifi.flags.Flags.FLAG_USD)
+ @RequiresPermission(MANAGE_WIFI_NETWORK_SELECTION)
+ public boolean isUsdPublisherSupported() {
+ if (!Environment.isSdkAtLeastB()) {
+ throw new UnsupportedOperationException();
+ }
+ try {
+ return mService.isUsdPublisherSupported();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
}
diff --git a/framework/java/android/net/wifi/WifiUsabilityStatsEntry.java b/framework/java/android/net/wifi/WifiUsabilityStatsEntry.java
index 435bf4f..0b86c1d 100644
--- a/framework/java/android/net/wifi/WifiUsabilityStatsEntry.java
+++ b/framework/java/android/net/wifi/WifiUsabilityStatsEntry.java
@@ -152,6 +152,42 @@
/** @see #getTimeSliceDutyCycleInPercent() */
private final int mTimeSliceDutyCycleInPercent;
+ private final int mWifiLinkCount;
+ /** Refer to WifiManager.MloMode */
+ private @WifiManager.MloMode int mMloMode;
+ /** The number of tx bytes transmitted on current interface */
+ private final long mTxTransmittedBytes;
+ /** The number of rx bytes transmitted on current interface */
+ private final long mRxTransmittedBytes;
+ /** The total number of LABEL_BAD event happens */
+ private final int mLabelBadEventCount;
+ /** The current WiFi state in framework */
+ private final int mWifiFrameworkState;
+ /** Downstream throughput estimation provided by Network Capabilities */
+ private final int mIsNetworkCapabilitiesDownstreamSufficient;
+ /** Upstream throughput estimation provided by Network Capabilities */
+ private final int mIsNetworkCapabilitiesUpstreamSufficient;
+ /** Downstream throughput estimation used in Network Selection */
+ private final int mIsThroughputPredictorDownstreamSufficient;
+ /** Upstream throughput estimation used in Network Selection */
+ private final int mIsThroughputPredictorUpstreamSufficient;
+ /** If bluetooth is connected */
+ private final boolean mIsBluetoothConnected;
+ /** UWB Adapter state */
+ private final int mUwbAdapterState;
+ /** Low Latency mode state */
+ private final boolean mIsLowLatencyActivated;
+ /** Maximum supported tx link speed in Mbps */
+ private final int mMaxSupportedTxLinkSpeed;
+ /** Maximum supported rx link speed in Mbps */
+ private final int mMaxSupportedRxLinkSpeed;
+ /** WiFi Voip mode state */
+ private final int mVoipMode;
+ /** Thread device role */
+ private final int mThreadDeviceRole;
+ /** Data stall status */
+ private final int mStatusDataStall;
+
/** {@hide} */
@Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = {"WME_ACCESS_CATEGORY_"}, value = {
@@ -265,6 +301,83 @@
}
private final ContentionTimeStats[] mContentionTimeStats;
+ /**
+ * Packet statistics.
+ */
+ /** @hide */
+ public static final class PacketStats implements Parcelable {
+ private long mTxSuccess;
+ private long mTxRetries;
+ private long mTxBad;
+ private long mRxSuccess;
+
+ public PacketStats() {
+ }
+
+ /**
+ * Constructor function
+ * @param txSuccess Number of successfully transmitted unicast data pkts (ACK rcvd)
+ * @param txRetries Number of transmitted unicast data retry pkts
+ * @param txBad Number of transmitted unicast data pkt losses (no ACK)
+ * @param rxSuccess Number of received unicast data packets
+ */
+ public PacketStats(long txSuccess, long txRetries, long txBad, long rxSuccess) {
+ this.mTxSuccess = txSuccess;
+ this.mTxRetries = txRetries;
+ this.mTxBad = txBad;
+ this.mRxSuccess = rxSuccess;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeLong(mTxSuccess);
+ dest.writeLong(mTxRetries);
+ dest.writeLong(mTxBad);
+ dest.writeLong(mRxSuccess);
+ }
+
+ /** Implement the Parcelable interface */
+ public static final @NonNull Creator<PacketStats> CREATOR =
+ new Creator<PacketStats>() {
+ public PacketStats createFromParcel(Parcel in) {
+ PacketStats stats = new PacketStats();
+ stats.mTxSuccess = in.readLong();
+ stats.mTxRetries = in.readLong();
+ stats.mTxBad = in.readLong();
+ stats.mRxSuccess = in.readLong();
+ return stats;
+ }
+ public PacketStats[] newArray(int size) {
+ return new PacketStats[size];
+ }
+ };
+
+ /** Number of successfully transmitted unicast data pkts (ACK rcvd) */
+ public long getTxSuccess() {
+ return mTxSuccess;
+ }
+
+ /** Number of transmitted unicast data retry pkts */
+ public long getTxRetries() {
+ return mTxRetries;
+ }
+
+ /** Number of transmitted unicast data pkt losses (no ACK) */
+ public long getTxBad() {
+ return mTxBad;
+ }
+
+ /** Number of received unicast data packets */
+ public long getRxSuccess() {
+ return mRxSuccess;
+ }
+ }
+
/** {@hide} */
@Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = {"WIFI_PREAMBLE_"}, value = {
@@ -481,6 +594,145 @@
private final RateStats[] mRateStats;
/**
+ * Per peer statistics for WiFi the link
+ */
+ /** @hide */
+ public static final class PeerInfo implements Parcelable {
+ private int mStaCount;
+ private int mChanUtil;
+ private RateStats[] mRateStats;
+
+ public PeerInfo() {
+ }
+
+ /**
+ * Constructor function.
+ * @param staCount Station count
+ * @param chanUtil Channel utilization
+ * @param rateStats Per rate statistics on this WiFi peer
+ */
+ public PeerInfo(int staCount, int chanUtil, RateStats[] rateStats) {
+ this.mStaCount = staCount;
+ this.mChanUtil = chanUtil;
+ this.mRateStats = rateStats;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeInt(mStaCount);
+ dest.writeInt(mChanUtil);
+ dest.writeTypedArray(mRateStats, flags);
+ }
+
+ /** Implement the Parcelable interface */
+ public static final @NonNull Creator<PeerInfo> CREATOR = new Creator<PeerInfo>() {
+ public PeerInfo createFromParcel(Parcel in) {
+ PeerInfo stats = new PeerInfo();
+ stats.mStaCount = in.readInt();
+ stats.mChanUtil = in.readInt();
+ stats.mRateStats = in.createTypedArray(RateStats.CREATOR);
+ return stats;
+ }
+ public PeerInfo[] newArray(int size) {
+ return new PeerInfo[size];
+ }
+ };
+
+ /** Station count */
+ public int getStaCount() {
+ return mStaCount;
+ }
+
+ /** Channel utilization */
+ public int getChanUtil() {
+ return mChanUtil;
+ }
+
+ /** Per rate statistics */
+ public List<RateStats> getRateStats() {
+ if (mRateStats != null) {
+ return Arrays.asList(mRateStats);
+ }
+ return Collections.emptyList();
+ }
+ }
+
+ /**
+ * Scan Results who have the same freq with current WiFi link
+ */
+ /** @hide */
+ public static final class ScanResultWithSameFreq implements Parcelable {
+ private long mScanResultTimestampMicros;
+ private int mRssi;
+ private int mFrequencyMhz;
+
+ public ScanResultWithSameFreq() {
+ }
+
+ /**
+ * Constructor function.
+ * @param scanResultTimestampMicros Timestamp in microseconds (since boot) when this result
+ * was last seen.
+ * @param rssi The detected signal level in dBm
+ * @param frequencyMhz The center frequency of the primary 20 MHz frequency
+ * (in MHz) of the channel
+ */
+ public ScanResultWithSameFreq(long scanResultTimestampMicros, int rssi, int frequencyMhz) {
+ this.mScanResultTimestampMicros = scanResultTimestampMicros;
+ this.mRssi = rssi;
+ this.mFrequencyMhz = frequencyMhz;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeLong(mScanResultTimestampMicros);
+ dest.writeInt(mRssi);
+ dest.writeInt(mFrequencyMhz);
+ }
+
+ /** Implement the Parcelable interface */
+ public static final @NonNull Creator<ScanResultWithSameFreq> CREATOR =
+ new Creator<ScanResultWithSameFreq>() {
+ public ScanResultWithSameFreq createFromParcel(Parcel in) {
+ ScanResultWithSameFreq scanResultWithSameFreq =
+ new ScanResultWithSameFreq();
+ scanResultWithSameFreq.mScanResultTimestampMicros = in.readLong();
+ scanResultWithSameFreq.mRssi = in.readInt();
+ scanResultWithSameFreq.mFrequencyMhz = in.readInt();
+ return scanResultWithSameFreq;
+ }
+ public ScanResultWithSameFreq[] newArray(int size) {
+ return new ScanResultWithSameFreq[size];
+ }
+ };
+
+ /** timestamp in microseconds (since boot) when this result was last seen */
+ public long getScanResultTimestampMicros() {
+ return mScanResultTimestampMicros;
+ }
+
+ /** The detected signal level in dBm */
+ public int getRssi() {
+ return mRssi;
+ }
+
+ /** The center frequency of the primary 20 MHz frequency (in MHz) of the channel */
+ public int getFrequency() {
+ return mFrequencyMhz;
+ }
+ }
+
+ /**
* Wifi link layer radio stats.
*/
public static final class RadioStats implements Parcelable {
@@ -499,6 +751,7 @@
private long mTotalRoamScanTimeMillis;
private long mTotalPnoScanTimeMillis;
private long mTotalHotspot2ScanTimeMillis;
+ private int[] mTxTimeMsPerLevel;
/** @hide */
public RadioStats() {
@@ -542,6 +795,47 @@
this.mTotalHotspot2ScanTimeMillis = onTimeHs20Scan;
}
+ /**
+ * Constructor function
+ * @param radioId Firmware/Hardware implementation specific persistent value for this
+ * device, identifying the radio interface for which the stats are produced.
+ * @param onTime The total time the wifi radio is on in ms counted from the last radio
+ * chip reset
+ * @param txTime The total time the wifi radio is transmitting in ms counted from the last
+ * radio chip reset
+ * @param rxTime The total time the wifi radio is receiving in ms counted from the last
+ * radio chip reset
+ * @param onTimeScan The total time spent on all types of scans in ms counted from the
+ * last radio chip reset
+ * @param onTimeNanScan The total time spent on nan scans in ms counted from the last radio
+ * chip reset
+ * @param onTimeBackgroundScan The total time spent on background scans in ms counted from
+ * the last radio chip reset
+ * @param onTimeRoamScan The total time spent on roam scans in ms counted from the last
+ * radio chip reset
+ * @param onTimePnoScan The total time spent on pno scans in ms counted from the last radio
+ * chip reset
+ * @param onTimeHs20Scan The total time spent on hotspot2.0 scans and GAS exchange in ms
+ * counted from the last radio chip reset
+ * @param txTimeMsPerLevel Time for which the radio is in active tranmission per tx level
+ */
+ /** @hide */
+ public RadioStats(int radioId, long onTime, long txTime, long rxTime, long onTimeScan,
+ long onTimeNanScan, long onTimeBackgroundScan, long onTimeRoamScan,
+ long onTimePnoScan, long onTimeHs20Scan, int[] txTimeMsPerLevel) {
+ this.mRadioId = radioId;
+ this.mTotalRadioOnTimeMillis = onTime;
+ this.mTotalRadioTxTimeMillis = txTime;
+ this.mTotalRadioRxTimeMillis = rxTime;
+ this.mTotalScanTimeMillis = onTimeScan;
+ this.mTotalNanScanTimeMillis = onTimeNanScan;
+ this.mTotalBackgroundScanTimeMillis = onTimeBackgroundScan;
+ this.mTotalRoamScanTimeMillis = onTimeRoamScan;
+ this.mTotalPnoScanTimeMillis = onTimePnoScan;
+ this.mTotalHotspot2ScanTimeMillis = onTimeHs20Scan;
+ this.mTxTimeMsPerLevel = txTimeMsPerLevel;
+ }
+
@Override
public int describeContents() {
return 0;
@@ -559,6 +853,7 @@
dest.writeLong(mTotalRoamScanTimeMillis);
dest.writeLong(mTotalPnoScanTimeMillis);
dest.writeLong(mTotalHotspot2ScanTimeMillis);
+ dest.writeIntArray(mTxTimeMsPerLevel);
}
/** Implement the Parcelable interface */
@@ -576,6 +871,7 @@
stats.mTotalRoamScanTimeMillis = in.readLong();
stats.mTotalPnoScanTimeMillis = in.readLong();
stats.mTotalHotspot2ScanTimeMillis = in.readLong();
+ stats.mTxTimeMsPerLevel = in.createIntArray();
return stats;
}
public RadioStats[] newArray(int size) {
@@ -645,6 +941,13 @@
public long getTotalHotspot2ScanTimeMillis() {
return mTotalHotspot2ScanTimeMillis;
}
+ /**
+ * Time for which the radio is in active tranmission per tx level
+ */
+ /** @hide */
+ public int[] getTxTimeMsPerLevel() {
+ return mTxTimeMsPerLevel;
+ }
}
private final RadioStats[] mRadioStats;
private final int mChannelUtilizationRatio;
@@ -670,6 +973,16 @@
private final int mRadioId;
/** The RSSI (in dBm) at the sample time */
private final int mRssi;
+ /** Frequency of the link in MHz */
+ private final int mFrequencyMhz;
+ /** RSSI of management frames on this WiFi link */
+ private final int mRssiMgmt;
+ /** Channel bandwidth on this WiFi link */
+ @WifiChannelBandwidth private int mChannelWidth;
+ /** Center frequency (MHz) first segment on this WiFi link */
+ private final int mCenterFreqFirstSegment;
+ /** Center frequency (MHz) second segment on this WiFi link */
+ private final int mCenterFreqSecondSegment;
/** Tx Link speed at the sample time in Mbps */
private final int mTxLinkSpeedMbps;
/** Rx link speed at the sample time in Mbps */
@@ -697,6 +1010,12 @@
private final ContentionTimeStats[] mContentionTimeStats;
/** Rate information and statistics */
private final RateStats[] mRateStats;
+ /** Packet statistics */
+ private final PacketStats[] mPacketStats;
+ /** Peer statistics */
+ private final PeerInfo[] mPeerInfo;
+ /** Scan results who have the same frequency with this WiFi link */
+ private final ScanResultWithSameFreq[] mScanResultsWithSameFreq;
/** @hide */
public LinkStats() {
@@ -704,6 +1023,11 @@
mState = LINK_STATE_UNKNOWN;
mRssi = WifiInfo.INVALID_RSSI;
mRadioId = RadioStats.INVALID_RADIO_ID;
+ mFrequencyMhz = 0;
+ mRssiMgmt = 0;
+ mChannelWidth = WIFI_BANDWIDTH_20_MHZ;
+ mCenterFreqFirstSegment = 0;
+ mCenterFreqSecondSegment = 0;
mTxLinkSpeedMbps = WifiInfo.LINK_SPEED_UNKNOWN;
mRxLinkSpeedMbps = WifiInfo.LINK_SPEED_UNKNOWN;
mTotalTxSuccess = 0;
@@ -716,6 +1040,9 @@
mTotalRadioOnFreqTimeMillis = 0;
mContentionTimeStats = null;
mRateStats = null;
+ mPacketStats = null;
+ mPeerInfo = null;
+ mScanResultsWithSameFreq = null;
}
/** @hide
@@ -725,6 +1052,11 @@
* @param radioId Identifier of the radio on which the link is operating
* currently.
* @param rssi Link Rssi (in dBm) at sample time.
+ * @param frequencyMhz Frequency of the link in MHz
+ * @param rssiMgmt RSSI of management frames on this WiFi link
+ * @param channelWidth channel width of WiFi link
+ * @param centerFreqFirstSegment Center frequency (MHz) of first segment
+ * @param centerFreqSecondSegment Center frequency (MHz) of second segment
* @param txLinkSpeedMpbs Transmit link speed in Mpbs at sample time.
* @param rxLinkSpeedMpbs Receive link speed in Mbps at sample time.
* @param totalTxSuccess Total number of Tx success.
@@ -739,16 +1071,29 @@
* last radio chip reset.
* @param contentionTimeStats Data packet contention time statistics.
* @param rateStats Rate information.
+ * @param packetStats Packet statistics.
+ * @param peerInfo Peer statistics.
+ * @param scanResultsWithSameFreq Scan results who have the same frequency with this
+ * WiFi link.
*/
- public LinkStats(int linkId, int state, int radioId, int rssi, int txLinkSpeedMpbs,
- int rxLinkSpeedMpbs, long totalTxSuccess, long totalTxRetries, long totalTxBad,
- long totalRxSuccess, long totalBeaconRx, int timeSliceDutyCycleInPercent,
- long totalCcaBusyFreqTimeMillis, long totalRadioOnFreqTimeMillis,
- ContentionTimeStats[] contentionTimeStats, RateStats[] rateStats) {
+ public LinkStats(int linkId, int state, int radioId, int rssi, int frequencyMhz,
+ int rssiMgmt, @WifiChannelBandwidth int channelWidth, int centerFreqFirstSegment,
+ int centerFreqSecondSegment, int txLinkSpeedMpbs, int rxLinkSpeedMpbs,
+ long totalTxSuccess, long totalTxRetries, long totalTxBad, long totalRxSuccess,
+ long totalBeaconRx, int timeSliceDutyCycleInPercent,
+ long totalCcaBusyFreqTimeMillis, long totalRadioOnFreqTimeMillis,
+ ContentionTimeStats[] contentionTimeStats, RateStats[] rateStats,
+ PacketStats[] packetStats, PeerInfo[] peerInfo,
+ ScanResultWithSameFreq[] scanResultsWithSameFreq) {
this.mLinkId = linkId;
this.mState = state;
this.mRadioId = radioId;
this.mRssi = rssi;
+ this.mFrequencyMhz = frequencyMhz;
+ this.mRssiMgmt = rssiMgmt;
+ this.mChannelWidth = channelWidth;
+ this.mCenterFreqFirstSegment = centerFreqFirstSegment;
+ this.mCenterFreqSecondSegment = centerFreqSecondSegment;
this.mTxLinkSpeedMbps = txLinkSpeedMpbs;
this.mRxLinkSpeedMbps = rxLinkSpeedMpbs;
this.mTotalTxSuccess = totalTxSuccess;
@@ -761,6 +1106,9 @@
this.mTotalRadioOnFreqTimeMillis = totalRadioOnFreqTimeMillis;
this.mContentionTimeStats = contentionTimeStats;
this.mRateStats = rateStats;
+ this.mPacketStats = packetStats;
+ this.mPeerInfo = peerInfo;
+ this.mScanResultsWithSameFreq = scanResultsWithSameFreq;
}
@Override
@@ -774,6 +1122,11 @@
dest.writeInt(mState);
dest.writeInt(mRadioId);
dest.writeInt(mRssi);
+ dest.writeInt(mFrequencyMhz);
+ dest.writeInt(mRssiMgmt);
+ dest.writeInt(mChannelWidth);
+ dest.writeInt(mCenterFreqFirstSegment);
+ dest.writeInt(mCenterFreqSecondSegment);
dest.writeInt(mTxLinkSpeedMbps);
dest.writeInt(mRxLinkSpeedMbps);
dest.writeLong(mTotalTxSuccess);
@@ -786,6 +1139,9 @@
dest.writeLong(mTotalRadioOnFreqTimeMillis);
dest.writeTypedArray(mContentionTimeStats, flags);
dest.writeTypedArray(mRateStats, flags);
+ dest.writeTypedArray(mPacketStats, flags);
+ dest.writeTypedArray(mPeerInfo, flags);
+ dest.writeTypedArray(mScanResultsWithSameFreq, flags);
}
/** Implement the Parcelable interface */
@@ -794,11 +1150,15 @@
new Creator<>() {
public LinkStats createFromParcel(Parcel in) {
return new LinkStats(in.readInt(), in.readInt(), in.readInt(), in.readInt(),
- in.readInt(), in.readInt(), in.readLong(), in.readLong(),
- in.readLong(), in.readLong(), in.readLong(), in.readInt(),
- in.readLong(), in.readLong(),
+ in.readInt(), in.readInt(), in.readInt(), in.readInt(),
+ in.readInt(), in.readInt(), in.readInt(), in.readLong(),
+ in.readLong(), in.readLong(), in.readLong(), in.readLong(),
+ in.readInt(), in.readLong(), in.readLong(),
in.createTypedArray(ContentionTimeStats.CREATOR),
- in.createTypedArray(RateStats.CREATOR));
+ in.createTypedArray(RateStats.CREATOR),
+ in.createTypedArray(PacketStats.CREATOR),
+ in.createTypedArray(PeerInfo.CREATOR),
+ in.createTypedArray(ScanResultWithSameFreq.CREATOR));
}
public LinkStats[] newArray(int size) {
@@ -826,7 +1186,15 @@
boolean isThroughputSufficient, boolean isWifiScoringEnabled,
boolean isCellularDataAvailable, @NetworkType int cellularDataNetworkType,
int cellularSignalStrengthDbm, int cellularSignalStrengthDb,
- boolean isSameRegisteredCell, SparseArray<LinkStats> linkStats) {
+ boolean isSameRegisteredCell, SparseArray<LinkStats> linkStats,
+ int wifiLinkCount, @WifiManager.MloMode int mloMode,
+ long txTransmittedBytes, long rxTransmittedBytes, int labelBadEventCount,
+ int wifiFrameworkState, int isNetworkCapabilitiesDownstreamSufficient,
+ int isNetworkCapabilitiesUpstreamSufficient,
+ int isThroughputPredictorDownstreamSufficient,
+ int isThroughputPredictorUpstreamSufficient, boolean isBluetoothConnected,
+ int uwbAdapterState, boolean isLowLatencyActivated, int maxSupportedTxLinkSpeed,
+ int maxSupportedRxLinkSpeed, int voipMode, int threadDeviceRole, int statusDataStall) {
mTimeStampMillis = timeStampMillis;
mRssi = rssi;
mLinkSpeedMbps = linkSpeedMbps;
@@ -863,6 +1231,24 @@
mCellularSignalStrengthDb = cellularSignalStrengthDb;
mIsSameRegisteredCell = isSameRegisteredCell;
mLinkStats = linkStats;
+ mWifiLinkCount = wifiLinkCount;
+ mMloMode = mloMode;
+ mTxTransmittedBytes = txTransmittedBytes;
+ mRxTransmittedBytes = rxTransmittedBytes;
+ mLabelBadEventCount = labelBadEventCount;
+ mWifiFrameworkState = wifiFrameworkState;
+ mIsNetworkCapabilitiesDownstreamSufficient = isNetworkCapabilitiesDownstreamSufficient;
+ mIsNetworkCapabilitiesUpstreamSufficient = isNetworkCapabilitiesUpstreamSufficient;
+ mIsThroughputPredictorDownstreamSufficient = isThroughputPredictorDownstreamSufficient;
+ mIsThroughputPredictorUpstreamSufficient = isThroughputPredictorUpstreamSufficient;
+ mIsBluetoothConnected = isBluetoothConnected;
+ mUwbAdapterState = uwbAdapterState;
+ mIsLowLatencyActivated = isLowLatencyActivated;
+ mMaxSupportedTxLinkSpeed = maxSupportedTxLinkSpeed;
+ mMaxSupportedRxLinkSpeed = maxSupportedRxLinkSpeed;
+ mVoipMode = voipMode;
+ mThreadDeviceRole = threadDeviceRole;
+ mStatusDataStall = statusDataStall;
}
/** Implement the Parcelable interface */
@@ -908,6 +1294,24 @@
dest.writeInt(mCellularSignalStrengthDb);
dest.writeBoolean(mIsSameRegisteredCell);
dest.writeSparseArray(mLinkStats);
+ dest.writeInt(mWifiLinkCount);
+ dest.writeInt(mMloMode);
+ dest.writeLong(mTxTransmittedBytes);
+ dest.writeLong(mRxTransmittedBytes);
+ dest.writeInt(mLabelBadEventCount);
+ dest.writeInt(mWifiFrameworkState);
+ dest.writeInt(mIsNetworkCapabilitiesDownstreamSufficient);
+ dest.writeInt(mIsNetworkCapabilitiesUpstreamSufficient);
+ dest.writeInt(mIsThroughputPredictorDownstreamSufficient);
+ dest.writeInt(mIsThroughputPredictorUpstreamSufficient);
+ dest.writeBoolean(mIsBluetoothConnected);
+ dest.writeInt(mUwbAdapterState);
+ dest.writeBoolean(mIsLowLatencyActivated);
+ dest.writeInt(mMaxSupportedTxLinkSpeed);
+ dest.writeInt(mMaxSupportedRxLinkSpeed);
+ dest.writeInt(mVoipMode);
+ dest.writeInt(mThreadDeviceRole);
+ dest.writeInt(mStatusDataStall);
}
/** Implement the Parcelable interface */
@@ -929,7 +1333,11 @@
in.readInt(), in.readBoolean(), in.readBoolean(),
in.readBoolean(), in.readInt(), in.readInt(),
in.readInt(), in.readBoolean(),
- in.readSparseArray(LinkStats.class.getClassLoader())
+ in.readSparseArray(LinkStats.class.getClassLoader()), in.readInt(),
+ in.readInt(), in.readLong(), in.readLong(), in.readInt(), in.readInt(),
+ in.readInt(), in.readInt(), in.readInt(), in.readInt(), in.readBoolean(),
+ in.readInt(), in.readBoolean(), in.readInt(), in.readInt(), in.readInt(),
+ in.readInt(), in.readInt()
);
}
@@ -1003,6 +1411,77 @@
throw new NoSuchElementException("linkId is invalid - " + linkId);
}
+ /**
+ * Get frequency of specific WiFi link
+ *
+ * @param linkId Identifier of the link.
+ * @return Frequency in Mhz
+ * @throws NoSuchElementException if linkId is invalid.
+ */
+ /** @hide */
+ public int getFrequencyMhz(int linkId) {
+ if (mLinkStats.contains(linkId)) return mLinkStats.get(linkId).mFrequencyMhz;
+ throw new NoSuchElementException("linkId is invalid - " + linkId);
+ }
+
+ /**
+ * Get RSSI of management frames on this WiFi link
+ *
+ * @param linkId Identifier of the link.
+ * @return RSSI of management frames on this WiFi link
+ * @throws NoSuchElementException if linkId is invalid.
+ */
+ /** @hide */
+ public int getRssiMgmt(int linkId) {
+ if (mLinkStats.contains(linkId)) return mLinkStats.get(linkId).mRssiMgmt;
+ throw new NoSuchElementException("linkId is invalid - " + linkId);
+ }
+
+ /**
+ * Get channel width of this WiFi link
+ *
+ * @param linkId Identifier of the link.
+ * @return channel width of this WiFi link
+ * @throws NoSuchElementException if linkId is invalid.
+ */
+ /** @hide */
+ public int getChannelWidth(int linkId) {
+ if (mLinkStats.contains(linkId)) {
+ return mLinkStats.get(linkId).mChannelWidth;
+ }
+ throw new NoSuchElementException("linkId is invalid - " + linkId);
+ }
+
+ /**
+ * Get center frequency (MHz) of first segment of this WiFi link
+ *
+ * @param linkId Identifier of the link.
+ * @return center frequency (MHz) of first segment of this WiFi link
+ * @throws NoSuchElementException if linkId is invalid.
+ */
+ /** @hide */
+ public int getCenterFreqFirstSegment(int linkId) {
+ if (mLinkStats.contains(linkId)) {
+ return mLinkStats.get(linkId).mCenterFreqFirstSegment;
+ }
+ throw new NoSuchElementException("linkId is invalid - " + linkId);
+ }
+
+ /**
+ * Get center frequency (MHz) of second segment of this WiFi link
+ *
+ * @param linkId Identifier of the link.
+ * @return center frequency (MHz) of second segment of this WiFi link
+ * @throws NoSuchElementException if linkId is invalid.
+ */
+ /** @hide */
+ public int getCenterFreqSecondSegment(int linkId) {
+ if (mLinkStats.contains(linkId)) {
+ return mLinkStats.get(linkId).mCenterFreqSecondSegment;
+ }
+ throw new NoSuchElementException("linkId is invalid - " + linkId);
+ }
+
/** Link speed at the sample time in Mbps. In case of Multi Link Operation (MLO), returned value
* is the current link speed of the associated link with the highest RSSI.
*
@@ -1356,6 +1835,30 @@
}
/**
+ * Packet statistics of a WiFi link for Access Category.
+ *
+ * @param linkId Identifier of the link.
+ * @param ac The access category, see {@link WmeAccessCategory}.
+ * @return The packet statistics, see {@link PacketStats}.
+ * @throws NoSuchElementException if linkId is invalid.
+ */
+ /** @hide */
+ @NonNull
+ public PacketStats getPacketStats(int linkId, @WmeAccessCategory int ac) {
+ if (!mLinkStats.contains(linkId)) {
+ throw new NoSuchElementException("linkId is invalid - " + linkId);
+ }
+ PacketStats[] linkPacketStats = mLinkStats.get(
+ linkId).mPacketStats;
+ if (linkPacketStats != null
+ && linkPacketStats.length == NUM_WME_ACCESS_CATEGORIES) {
+ return linkPacketStats[ac];
+ }
+ Log.e(TAG, "The PacketStats is not filled out correctly");
+ return new PacketStats();
+ }
+
+ /**
* Rate information and statistics, which are ordered by preamble, modulation and coding scheme
* (MCS), and number of spatial streams (NSS). In case of Multi Link Operation (MLO), the
* returned rate information is that of the associated link with the highest RSSI.
@@ -1407,6 +1910,73 @@
}
/**
+ * Rate information and statistics, which are ordered by preamble, modulation and coding scheme
+ * (MCS), and number of spatial streams (NSS) for WiFi peer.
+ *
+ * @param linkId Identifier of the link.
+ * @param peerIndex Identifier of PeerInfo.
+ * @return A list of rate statistics in the form of a list of {@link RateStats} objects.
+ * Depending on the link type, the list is created following the order of:
+ * - HT (IEEE Std 802.11-2020, Section 19): LEGACY rates (1Mbps, ..., 54Mbps),
+ * HT MCS0, ..., MCS15;
+ * - VHT (IEEE Std 802.11-2020, Section 21): LEGACY rates (1Mbps, ..., 54Mbps),
+ * VHT MCS0/NSS1, ..., VHT MCS11/NSS1, VHT MCSO/NSS2, ..., VHT MCS11/NSS2;
+ * - HE (IEEE Std 802.11ax-2020, Section 27): LEGACY rates (1Mbps, ..., 54Mbps),
+ * HE MCS0/NSS1, ..., HE MCS11/NSS1, HE MCSO/NSS2, ..., HE MCS11/NSS2.
+ * - EHT (IEEE std 802.11be-2021, Section 36): Legacy rates (1Mbps, ..., 54Mbps),
+ * EHT MSC0/NSS1, ..., EHT MCS14/NSS1, EHT MCS0/NSS2, ..., EHT MCS14/NSS2.
+ * @throws NoSuchElementException if linkId is invalid.
+ */
+ /** @hide */
+ @NonNull
+ public List<RateStats> getRateStats(int linkId, int peerIndex) {
+ if (mLinkStats.contains(linkId)) {
+ if (getPeerInfo(linkId).size() > 0 && peerIndex < getPeerInfo(linkId).size()) {
+ RateStats[] rateStats = mLinkStats.get(linkId).mPeerInfo[peerIndex].mRateStats;
+ if (rateStats != null) return Arrays.asList(rateStats);
+ }
+ return Collections.emptyList();
+ }
+ throw new NoSuchElementException("linkId is invalid - " + linkId);
+ }
+
+ /**
+ * Peer information and statistics
+ *
+ * @param linkId Identifier of the link.
+ * @return A list of peer statistics in the form of a list of {@link PeerInfo} objects.
+ * @throws NoSuchElementException if linkId is invalid.
+ */
+ /** @hide */
+ @NonNull
+ public List<PeerInfo> getPeerInfo(int linkId) {
+ if (mLinkStats.contains(linkId)) {
+ PeerInfo[] peerInfo = mLinkStats.get(linkId).mPeerInfo;
+ if (peerInfo != null) return Arrays.asList(peerInfo);
+ return Collections.emptyList();
+ }
+ throw new NoSuchElementException("linkId is invalid - " + linkId);
+ }
+
+ /**
+ * Scan results who have the same frequency with this WiFi link
+ *
+ * @param linkId Identifier of the link.
+ * @return An array of Scan results who have the same frequency with this WiFi link
+ * @throws NoSuchElementException if linkId is invalid.
+ */
+ /** @hide */
+ @NonNull
+ public ScanResultWithSameFreq[] getScanResultsWithSameFreq(int linkId) {
+ if (mLinkStats.contains(linkId)) {
+ ScanResultWithSameFreq[] scanResultsWithSameFreq =
+ mLinkStats.get(linkId).mScanResultsWithSameFreq;
+ return scanResultsWithSameFreq;
+ }
+ throw new NoSuchElementException("linkId is invalid - " + linkId);
+ }
+
+ /**
* Radio stats from all the radios, see {@link RadioStats#getRadioId()}
* @return A list of Wifi link layer radio stats, see {@link RadioStats}
*/
@@ -1485,4 +2055,94 @@
public boolean isSameRegisteredCell() {
return mIsSameRegisteredCell;
}
+
+ /** @hide */
+ public int getWifiLinkCount() {
+ return mWifiLinkCount;
+ }
+
+ /** @hide */
+ public int getMloMode() {
+ return mMloMode;
+ }
+
+ /** @hide */
+ public long getTxTransmittedBytes() {
+ return mTxTransmittedBytes;
+ }
+
+ /** @hide */
+ public long getRxTransmittedBytes() {
+ return mRxTransmittedBytes;
+ }
+
+ /** @hide */
+ public long getLabelBadEventCount() {
+ return mLabelBadEventCount;
+ }
+
+ /** @hide */
+ public int getWifiFrameworkState() {
+ return mWifiFrameworkState;
+ }
+
+ /** @hide */
+ public int isNetworkCapabilitiesDownstreamSufficient() {
+ return mIsNetworkCapabilitiesDownstreamSufficient;
+ }
+
+ /** @hide */
+ public int isNetworkCapabilitiesUpstreamSufficient() {
+ return mIsNetworkCapabilitiesUpstreamSufficient;
+ }
+
+ /** @hide */
+ public int isThroughputPredictorDownstreamSufficient() {
+ return mIsThroughputPredictorDownstreamSufficient;
+ }
+
+ /** @hide */
+ public int isThroughputPredictorUpstreamSufficient() {
+ return mIsThroughputPredictorUpstreamSufficient;
+ }
+
+ /** @hide */
+ public boolean isBluetoothConnected() {
+ return mIsBluetoothConnected;
+ }
+
+ /** @hide */
+ public int getUwbAdapterState() {
+ return mUwbAdapterState;
+ }
+
+ /** @hide */
+ public boolean getLowLatencyModeState() {
+ return mIsLowLatencyActivated;
+ }
+
+ /** @hide */
+ public int getMaxSupportedTxLinkSpeed() {
+ return mMaxSupportedTxLinkSpeed;
+ }
+
+ /** @hide */
+ public int getMaxSupportedRxLinkSpeed() {
+ return mMaxSupportedRxLinkSpeed;
+ }
+
+ /** @hide */
+ public int getVoipMode() {
+ return mVoipMode;
+ }
+
+ /** @hide */
+ public int getThreadDeviceRole() {
+ return mThreadDeviceRole;
+ }
+
+ /** @hide */
+ public int getStatusDataStall() {
+ return mStatusDataStall;
+ }
}
diff --git a/framework/java/android/net/wifi/aware/Characteristics.java b/framework/java/android/net/wifi/aware/Characteristics.java
index df36140..fa8c4ed 100644
--- a/framework/java/android/net/wifi/aware/Characteristics.java
+++ b/framework/java/android/net/wifi/aware/Characteristics.java
@@ -16,8 +16,13 @@
package android.net.wifi.aware;
+import static com.android.ranging.flags.Flags.FLAG_RANGING_RTT_ENABLED;
+
+import android.annotation.FlaggedApi;
import android.annotation.IntDef;
import android.annotation.IntRange;
+import android.annotation.SystemApi;
+import android.net.wifi.WifiAnnotations;
import android.os.Build;
import android.os.Bundle;
import android.os.Parcel;
@@ -62,6 +67,16 @@
public static final String KEY_SUPPORT_NAN_PAIRING = "key_support_nan_pairing";
/** @hide */
public static final String KEY_SUPPORT_SUSPENSION = "key_support_suspension";
+ /** @hide */
+ @FlaggedApi(FLAG_RANGING_RTT_ENABLED)
+ public static final String KEY_SUPPORT_PERIODIC_RANGING = "key_support_periodic_ranging";
+ /** @hide */
+ @FlaggedApi(FLAG_RANGING_RTT_ENABLED)
+ public static final String KEY_MAX_SUPPORTED_RANGING_PKT_BANDWIDTH =
+ "key_max_supported_ranging_pkt_bandwidth";
+ /** @hide */
+ @FlaggedApi(FLAG_RANGING_RTT_ENABLED)
+ public static final String KEY_MAX_SUPPORTED_RX_CHAINS = "key_max_supported_rx_chains";
private final Bundle mCharacteristics;
@@ -187,6 +202,78 @@
return mCharacteristics.getBoolean(KEY_SUPPORT_SUSPENSION);
}
+ /**
+ * Check if Periodic Ranging is supported.
+ * Periodic Ranging on Aware allows applications to get the asynchronous ranging
+ * report periodically.
+ * @return True if supported, false otherwise.
+ * @hide
+ */
+ @FlaggedApi(FLAG_RANGING_RTT_ENABLED)
+ @SystemApi
+ public boolean isPeriodicRangingSupported() {
+ return mCharacteristics.getBoolean(KEY_SUPPORT_PERIODIC_RANGING);
+ }
+
+ /** @hide */
+ @IntDef(flag = true, prefix = { "SUPPORTED_RX_CHAINS_" }, value = {
+ SUPPORTED_RX_CHAINS_UNSPECIFIED,
+ SUPPORTED_RX_CHAINS_1,
+ SUPPORTED_RX_CHAINS_2,
+ SUPPORTED_RX_CHAINS_3,
+ SUPPORTED_RX_CHAINS_4,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface SupportedRxChains {}
+
+ /** @hide */
+ @FlaggedApi(FLAG_RANGING_RTT_ENABLED)
+ @SystemApi
+ public static final int SUPPORTED_RX_CHAINS_1 = 1;
+ /** @hide */
+ @FlaggedApi(FLAG_RANGING_RTT_ENABLED)
+ @SystemApi
+ public static final int SUPPORTED_RX_CHAINS_2 = 2;
+ /** @hide */
+ @FlaggedApi(FLAG_RANGING_RTT_ENABLED)
+ @SystemApi
+ public static final int SUPPORTED_RX_CHAINS_3 = 3;
+ /** @hide */
+ @FlaggedApi(FLAG_RANGING_RTT_ENABLED)
+ @SystemApi
+ public static final int SUPPORTED_RX_CHAINS_4 = 4;
+ /** @hide */
+ @FlaggedApi(FLAG_RANGING_RTT_ENABLED)
+ @SystemApi
+ public static final int SUPPORTED_RX_CHAINS_UNSPECIFIED = 0;
+
+ /**
+ * Get the supported number of receive chains.
+ *
+ * @return Number of supported receive chains.
+ * @hide
+ */
+ @FlaggedApi(FLAG_RANGING_RTT_ENABLED)
+ @SystemApi
+ public @SupportedRxChains int getMaxSupportedRxChains() {
+ return mCharacteristics.getInt(KEY_MAX_SUPPORTED_RX_CHAINS);
+ }
+
+ /**
+ * Get Max supported ranging per packet Bandwidth
+ *
+ * @return the bandwidth representation of the Wi-Fi channel from
+ * {@link ScanResult#CHANNEL_WIDTH_20MHZ}, {@link ScanResult#CHANNEL_WIDTH_40MHZ},
+ * {@link ScanResult#CHANNEL_WIDTH_80MHZ}, {@link ScanResult#CHANNEL_WIDTH_160MHZ},
+ * or {@link ScanResult#CHANNEL_WIDTH_320MHZ}.
+ * @hide
+ */
+ @FlaggedApi(FLAG_RANGING_RTT_ENABLED)
+ @SystemApi
+ public @WifiAnnotations.ChannelWidth int getMaxSupportedRangingPktBandwidth() {
+ return mCharacteristics.getInt(KEY_MAX_SUPPORTED_RANGING_PKT_BANDWIDTH);
+ }
+
/** @hide */
@IntDef(flag = true, prefix = { "WIFI_AWARE_CIPHER_SUITE_" }, value = {
WIFI_AWARE_CIPHER_SUITE_NONE,
diff --git a/framework/java/android/net/wifi/aware/DiscoverySessionCallback.java b/framework/java/android/net/wifi/aware/DiscoverySessionCallback.java
index 80bce68..ad37287 100644
--- a/framework/java/android/net/wifi/aware/DiscoverySessionCallback.java
+++ b/framework/java/android/net/wifi/aware/DiscoverySessionCallback.java
@@ -16,8 +16,12 @@
package android.net.wifi.aware;
+import static com.android.ranging.flags.Flags.FLAG_RANGING_RTT_ENABLED;
+
+import android.annotation.FlaggedApi;
import android.annotation.NonNull;
import android.annotation.SystemApi;
+import android.net.wifi.rtt.RangingResult;
import java.util.List;
@@ -382,4 +386,16 @@
public void onBootstrappingFailed(@NonNull PeerHandle peerHandle) {
}
+
+ /**
+ * Callback indicating that ranging results have been received.
+ *
+ * @param rangingResults List of range measurements.
+ * @hide
+ */
+ @FlaggedApi(FLAG_RANGING_RTT_ENABLED)
+ @SystemApi
+ public void onRangingResultsReceived(@NonNull List<RangingResult> rangingResults) {
+
+ }
}
diff --git a/framework/java/android/net/wifi/aware/IWifiAwareDiscoverySessionCallback.aidl b/framework/java/android/net/wifi/aware/IWifiAwareDiscoverySessionCallback.aidl
index 392ec6c..326f236 100644
--- a/framework/java/android/net/wifi/aware/IWifiAwareDiscoverySessionCallback.aidl
+++ b/framework/java/android/net/wifi/aware/IWifiAwareDiscoverySessionCallback.aidl
@@ -16,16 +16,16 @@
package android.net.wifi.aware;
-import android.net.wifi.aware.AwarePairingConfig;
import android.net.wifi.OuiKeyedData;
+import android.net.wifi.aware.AwarePairingConfig;
+import android.net.wifi.rtt.RangingResult;
/**
* Callback interface that WifiAwareManager implements
*
* {@hide}
*/
-oneway interface IWifiAwareDiscoverySessionCallback
-{
+oneway interface IWifiAwareDiscoverySessionCallback {
void onSessionStarted(int discoverySessionId);
void onSessionConfigSuccess();
void onSessionConfigFail(int reason);
@@ -50,4 +50,5 @@
void onPairingSetupConfirmed(int peerId, boolean accept, String alias);
void onPairingVerificationConfirmed(int peerId, boolean accept, String alias);
void onBootstrappingVerificationConfirmed(int peerId, boolean accept, int method);
+ void onRangingResultsReceived(in List<RangingResult> rangingResults);
}
diff --git a/framework/java/android/net/wifi/aware/PublishConfig.java b/framework/java/android/net/wifi/aware/PublishConfig.java
index b429fac..774708f 100644
--- a/framework/java/android/net/wifi/aware/PublishConfig.java
+++ b/framework/java/android/net/wifi/aware/PublishConfig.java
@@ -18,6 +18,8 @@
import static android.Manifest.permission.MANAGE_WIFI_NETWORK_SELECTION;
+import static com.android.ranging.flags.Flags.FLAG_RANGING_RTT_ENABLED;
+
import android.annotation.FlaggedApi;
import android.annotation.IntDef;
import android.annotation.NonNull;
@@ -112,12 +114,15 @@
private final List<OuiKeyedData> mVendorData;
/** @hide */
+ public final boolean mEnablePeriodicRangingResults;
+
+ /** @hide */
public PublishConfig(byte[] serviceName, byte[] serviceSpecificInfo, byte[] matchFilter,
int publishType, int ttlSec, boolean enableTerminateNotification,
boolean enableRanging, boolean enableInstantMode, @WifiScanner.WifiBand int
band, WifiAwareDataPathSecurityConfig securityConfig,
AwarePairingConfig pairingConfig, boolean isSuspendable,
- @NonNull List<OuiKeyedData> vendorData) {
+ @NonNull List<OuiKeyedData> vendorData, boolean enablePeriodicRangingResults) {
mServiceName = serviceName;
mServiceSpecificInfo = serviceSpecificInfo;
mMatchFilter = matchFilter;
@@ -131,6 +136,7 @@
mPairingConfig = pairingConfig;
mIsSuspendable = isSuspendable;
mVendorData = vendorData;
+ mEnablePeriodicRangingResults = enablePeriodicRangingResults;
}
@Override
@@ -152,7 +158,8 @@
+ ", mSecurityConfig" + mSecurityConfig
+ ", mPairingConfig" + mPairingConfig
+ ", mIsSuspendable=" + mIsSuspendable
- + ", mVendorData=" + mVendorData + "]";
+ + ", mVendorData=" + mVendorData + "]"
+ + ", mEnablePeriodicRangingResults=" + mEnablePeriodicRangingResults;
}
@Override
@@ -175,6 +182,7 @@
dest.writeParcelable(mPairingConfig, flags);
dest.writeBoolean(mIsSuspendable);
dest.writeList(mVendorData);
+ dest.writeBoolean(mEnablePeriodicRangingResults);
}
@NonNull
@@ -201,10 +209,12 @@
.readParcelable(AwarePairingConfig.class.getClassLoader());
boolean isSuspendable = in.readBoolean();
List<OuiKeyedData> vendorData = ParcelUtil.readOuiKeyedDataList(in);
+ boolean enablePeriodicRangingResults = in.readBoolean();
return new PublishConfig(serviceName, ssi, matchFilter, publishType, ttlSec,
enableTerminateNotification, enableRanging, enableInstantMode,
- band, securityConfig, pairingConfig, isSuspendable, vendorData);
+ band, securityConfig, pairingConfig, isSuspendable, vendorData,
+ enablePeriodicRangingResults);
}
};
@@ -226,6 +236,7 @@
&& mTtlSec == lhs.mTtlSec
&& mEnableTerminateNotification == lhs.mEnableTerminateNotification
&& mEnableRanging == lhs.mEnableRanging
+ && mEnablePeriodicRangingResults == lhs.mEnablePeriodicRangingResults
&& mEnableInstantMode == lhs.mEnableInstantMode
&& mBand == lhs.mBand
&& mIsSuspendable == lhs.mIsSuspendable
@@ -239,7 +250,7 @@
return Objects.hash(Arrays.hashCode(mServiceName), Arrays.hashCode(mServiceSpecificInfo),
Arrays.hashCode(mMatchFilter), mPublishType, mTtlSec, mEnableTerminateNotification,
mEnableRanging, mEnableInstantMode, mBand, mSecurityConfig, mPairingConfig,
- mIsSuspendable, mVendorData);
+ mIsSuspendable, mVendorData, mEnablePeriodicRangingResults);
}
/**
@@ -310,6 +321,11 @@
if (!rttSupported && mEnableRanging) {
throw new IllegalArgumentException("Ranging is not supported");
}
+
+ if ((!rttSupported || !characteristics.isPeriodicRangingSupported())
+ && mEnablePeriodicRangingResults) {
+ throw new IllegalArgumentException("Periodic Ranging is not supported");
+ }
}
/**
@@ -387,6 +403,18 @@
}
/**
+ * Check if periodic ranging reporting is enabled for publish session
+ * @see Builder#setPeriodicRangingResultsEnabled(boolean)
+ * @return true for enabled, false otherwise.
+ * @hide
+ */
+ @FlaggedApi(FLAG_RANGING_RTT_ENABLED)
+ @SystemApi
+ public boolean isPeriodicRangingResultsEnabled() {
+ return mEnablePeriodicRangingResults;
+ }
+
+ /**
* Builder used to build {@link PublishConfig} objects.
*/
public static final class Builder {
@@ -403,6 +431,7 @@
private AwarePairingConfig mPairingConfig = null;
private boolean mIsSuspendable = false;
private @NonNull List<OuiKeyedData> mVendorData = Collections.emptyList();
+ private boolean mEnablePeriodicRangingResults = false;
/**
* Specify the service name of the publish session. The actual on-air
@@ -555,6 +584,33 @@
}
/**
+ * Configure whether periodic ranging results need to be notified to Publisher
+ * <p>
+ * Optional. Disabled by default - i.e. any ranging result will not be notified to
+ * the Publisher.
+ * <p>
+ * The device must support Periodic Ranging for this feature to be used.
+ * Feature support check is determined by
+ * {@link Characteristics#isPeriodicRangingSupported()}.
+ * <p>
+ * The ranging result will be notified to Publisher via
+ * {@link DiscoverySessionCallback#onRangingResultsReceived(RangingResults)}.
+ *
+ * @param enable If true, ranging result will be notified to Publisher.
+ *
+ * @return The builder to facilitate chaining
+ * {@code builder.setXXX(..).setXXX(..)}.
+ * @hide
+ */
+ @FlaggedApi(FLAG_RANGING_RTT_ENABLED)
+ @SystemApi
+ @NonNull
+ public Builder setPeriodicRangingResultsEnabled(boolean enable) {
+ mEnablePeriodicRangingResults = enable;
+ return this;
+ }
+
+ /**
* Configure whether to enable and use instant communication for this publish session.
* Instant communication will speed up service discovery and any data-path set up as part of
* this session. Use {@link Characteristics#isInstantCommunicationModeSupported()} to check
@@ -694,7 +750,8 @@
public PublishConfig build() {
return new PublishConfig(mServiceName, mServiceSpecificInfo, mMatchFilter, mPublishType,
mTtlSec, mEnableTerminateNotification, mEnableRanging, mEnableInstantMode,
- mBand, mSecurityConfig, mPairingConfig, mIsSuspendable, mVendorData);
+ mBand, mSecurityConfig, mPairingConfig, mIsSuspendable, mVendorData,
+ mEnablePeriodicRangingResults);
}
}
}
diff --git a/framework/java/android/net/wifi/aware/SubscribeConfig.java b/framework/java/android/net/wifi/aware/SubscribeConfig.java
index ea99d81..e9d6806 100644
--- a/framework/java/android/net/wifi/aware/SubscribeConfig.java
+++ b/framework/java/android/net/wifi/aware/SubscribeConfig.java
@@ -18,8 +18,11 @@
import static android.Manifest.permission.MANAGE_WIFI_NETWORK_SELECTION;
+import static com.android.ranging.flags.Flags.FLAG_RANGING_RTT_ENABLED;
+
import android.annotation.FlaggedApi;
import android.annotation.IntDef;
+import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
@@ -27,7 +30,10 @@
import android.net.wifi.OuiKeyedData;
import android.net.wifi.ParcelUtil;
import android.net.wifi.ScanResult;
+import android.net.wifi.WifiAnnotations;
import android.net.wifi.WifiScanner;
+import android.net.wifi.rtt.RangingRequest;
+import android.net.wifi.rtt.ResponderConfig;
import android.net.wifi.util.HexEncoding;
import android.os.Build;
import android.os.Parcel;
@@ -76,6 +82,72 @@
*/
public static final int SUBSCRIBE_TYPE_ACTIVE = 1;
+ private static final int AWARE_BAND_2_DISCOVERY_CHANNEL = 2437;
+ private static final int MIN_RTT_BURST_SIZE = RangingRequest.getMinRttBurstSize();
+ private static final int MAX_RTT_BURST_SIZE = RangingRequest.getMaxRttBurstSize();
+
+ /**
+ * Ranging Interval's are in binary Time Unit (TU). As per IEEE 802.11-1999 1 TU equals
+ * 1024 microseconds.
+ *
+ * @hide
+ */
+ @IntDef({
+ PERIODIC_RANGING_INTERVAL_NONE, PERIODIC_RANGING_INTERVAL_128TU,
+ PERIODIC_RANGING_INTERVAL_256TU, PERIODIC_RANGING_INTERVAL_512TU,
+ PERIODIC_RANGING_INTERVAL_1024TU, PERIODIC_RANGING_INTERVAL_2048TU,
+ PERIODIC_RANGING_INTERVAL_4096TU, PERIODIC_RANGING_INTERVAL_8192TU})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface PeriodicRangingInterval {
+ }
+ /* Ranging is not repeated */
+ /** @hide */
+ @FlaggedApi(FLAG_RANGING_RTT_ENABLED)
+ @SystemApi
+ public static final int PERIODIC_RANGING_INTERVAL_NONE = 0;
+
+ /* Ranging interval is 128TU [= (128 * 1024) / 1000 = 131.072 ms] */
+ /** @hide */
+ @FlaggedApi(FLAG_RANGING_RTT_ENABLED)
+ @SystemApi
+ public static final int PERIODIC_RANGING_INTERVAL_128TU = 128;
+
+ /* Ranging interval is 256TU [= (256 * 1024) / 1000 = 262.144 ms] */
+ /** @hide */
+ @FlaggedApi(FLAG_RANGING_RTT_ENABLED)
+ @SystemApi
+ public static final int PERIODIC_RANGING_INTERVAL_256TU = 256;
+
+ /* Ranging interval is 512TU [= (512 * 1024) / 1000 = 524.288 ms] */
+ /** @hide */
+ @FlaggedApi(FLAG_RANGING_RTT_ENABLED)
+ @SystemApi
+ public static final int PERIODIC_RANGING_INTERVAL_512TU = 512;
+
+ /* Ranging interval is 1024TU [= (1024 * 1024) / 1000 = 1048.576 ms] */
+ /** @hide */
+ @FlaggedApi(FLAG_RANGING_RTT_ENABLED)
+ @SystemApi
+ public static final int PERIODIC_RANGING_INTERVAL_1024TU = 1024;
+
+ /* Ranging interval is 2048TU [= (2048 * 1024) / 1000 = 2097.152 ms] */
+ /** @hide */
+ @FlaggedApi(FLAG_RANGING_RTT_ENABLED)
+ @SystemApi
+ public static final int PERIODIC_RANGING_INTERVAL_2048TU = 2048;
+
+ /* Ranging interval is 4096TU [= (4096 * 1024) / 1000 = 4194.304 ms] */
+ /** @hide */
+ @FlaggedApi(FLAG_RANGING_RTT_ENABLED)
+ @SystemApi
+ public static final int PERIODIC_RANGING_INTERVAL_4096TU = 4096;
+
+ /* Ranging interval is 8192TU [= (8192 * 1024) / 1000 = 8388.608 ms] */
+ /** @hide */
+ @FlaggedApi(FLAG_RANGING_RTT_ENABLED)
+ @SystemApi
+ public static final int PERIODIC_RANGING_INTERVAL_8192TU = 8192;
+
/** @hide */
public final byte[] mServiceName;
@@ -116,12 +188,39 @@
private final List<OuiKeyedData> mVendorData;
/** @hide */
+ public final int mPeriodicRangingInterval;
+
+ /** @hide */
+ public final boolean mPeriodicRangingEnabled;
+
+ /** @hide */
+ public final int mRttBurstSize;
+
+ /** @hide */
+ public final int mFrequencyMhz;
+
+ /** @hide */
+ public final int mCenterFrequency0Mhz;
+
+ /** @hide */
+ public final int mCenterFrequency1Mhz;
+
+ /** @hide */
+ public final int mPreamble;
+
+ /** @hide */
+ public final int mChannelWidth;
+
+ /** @hide */
public SubscribeConfig(byte[] serviceName, byte[] serviceSpecificInfo, byte[] matchFilter,
int subscribeType, int ttlSec, boolean enableTerminateNotification,
boolean minDistanceMmSet, int minDistanceMm, boolean maxDistanceMmSet,
int maxDistanceMm, boolean enableInstantMode, @WifiScanner.WifiBand int band,
AwarePairingConfig pairingConfig, boolean isSuspendable,
- @NonNull List<OuiKeyedData> vendorData) {
+ @NonNull List<OuiKeyedData> vendorData, int rangingInterval,
+ boolean enablePeriodicRanging, int rttBurstSize, int frequencyMhz,
+ int centerFrequency0Mhz, int centerFrequency1Mhz, int preamble,
+ int channelWidth) {
mServiceName = serviceName;
mServiceSpecificInfo = serviceSpecificInfo;
mMatchFilter = matchFilter;
@@ -137,6 +236,14 @@
mPairingConfig = pairingConfig;
mIsSuspendable = isSuspendable;
mVendorData = vendorData;
+ mPeriodicRangingInterval = rangingInterval;
+ mPeriodicRangingEnabled = enablePeriodicRanging;
+ mRttBurstSize = rttBurstSize;
+ mFrequencyMhz = frequencyMhz;
+ mCenterFrequency0Mhz = centerFrequency0Mhz;
+ mCenterFrequency1Mhz = centerFrequency1Mhz;
+ mPreamble = preamble;
+ mChannelWidth = channelWidth;
}
@Override
@@ -160,7 +267,15 @@
+ ", mBand=" + mBand
+ ", mPairingConfig" + mPairingConfig
+ ", mIsSuspendable=" + mIsSuspendable
- + ", mVendorData=" + mVendorData + "]";
+ + ", mVendorData=" + mVendorData + "]"
+ + ", mPeriodicRangingInterval" + mPeriodicRangingInterval
+ + ", mPeriodicRangingEnabled" + mPeriodicRangingEnabled
+ + ", mRttBurstSize" + mRttBurstSize
+ + ", mFrequencyMhz" + mFrequencyMhz
+ + ", mCenterFrequency0Mhz" + mCenterFrequency0Mhz
+ + ", mCenterFrequency1Mhz" + mCenterFrequency1Mhz
+ + ", mPreamble" + mPreamble
+ + ", mChannelWidth" + mChannelWidth;
}
@Override
@@ -185,6 +300,14 @@
dest.writeParcelable(mPairingConfig, flags);
dest.writeBoolean(mIsSuspendable);
dest.writeList(mVendorData);
+ dest.writeInt(mPeriodicRangingInterval);
+ dest.writeBoolean(mPeriodicRangingEnabled);
+ dest.writeInt(mRttBurstSize);
+ dest.writeInt(mFrequencyMhz);
+ dest.writeInt(mCenterFrequency0Mhz);
+ dest.writeInt(mCenterFrequency1Mhz);
+ dest.writeInt(mPreamble);
+ dest.writeInt(mChannelWidth);
}
@NonNull
@@ -212,11 +335,21 @@
AwarePairingConfig.class.getClassLoader());
boolean isSuspendable = in.readBoolean();
List<OuiKeyedData> vendorData = ParcelUtil.readOuiKeyedDataList(in);
+ int rangingInterval = in.readInt();
+ boolean enablePeriodicRanging = in.readBoolean();
+ int burstSize = in.readInt();
+ int frequencyMhz = in.readInt();
+ int centerFrequency0Mhz = in.readInt();
+ int centerFrequency1Mhz = in.readInt();
+ int preamble = in.readInt();
+ int channelWidth = in.readInt();
return new SubscribeConfig(serviceName, ssi, matchFilter, subscribeType, ttlSec,
enableTerminateNotification, minDistanceMmSet, minDistanceMm, maxDistanceMmSet,
maxDistanceMm, enableInstantMode, band, pairingConfig, isSuspendable,
- vendorData);
+ vendorData, rangingInterval, enablePeriodicRanging, burstSize,
+ frequencyMhz, centerFrequency0Mhz, centerFrequency1Mhz, preamble,
+ channelWidth);
}
};
@@ -241,7 +374,14 @@
&& mEnableInstantMode == lhs.mEnableInstantMode
&& mBand == lhs.mBand
&& mIsSuspendable == lhs.mIsSuspendable
- && Objects.equals(mVendorData, lhs.mVendorData))) {
+ && Objects.equals(mVendorData, lhs.mVendorData)
+ && mPeriodicRangingEnabled == lhs.mPeriodicRangingEnabled
+ && mRttBurstSize == lhs.mRttBurstSize
+ && mFrequencyMhz == lhs.mFrequencyMhz
+ && mCenterFrequency0Mhz == lhs.mCenterFrequency0Mhz
+ && mCenterFrequency1Mhz == lhs.mCenterFrequency1Mhz
+ && mPreamble == lhs.mPreamble
+ && mChannelWidth == lhs.mChannelWidth)) {
return false;
}
@@ -253,6 +393,9 @@
return false;
}
+ if (mPeriodicRangingEnabled && mPeriodicRangingInterval != lhs.mPeriodicRangingInterval) {
+ return false;
+ }
return true;
}
@@ -261,7 +404,9 @@
int result = Objects.hash(Arrays.hashCode(mServiceName),
Arrays.hashCode(mServiceSpecificInfo), Arrays.hashCode(mMatchFilter),
mSubscribeType, mTtlSec, mEnableTerminateNotification, mMinDistanceMmSet,
- mMaxDistanceMmSet, mEnableInstantMode, mBand, mIsSuspendable, mVendorData);
+ mMaxDistanceMmSet, mEnableInstantMode, mBand, mIsSuspendable, mVendorData,
+ mPeriodicRangingEnabled, mRttBurstSize, mFrequencyMhz, mCenterFrequency0Mhz,
+ mCenterFrequency1Mhz, mPreamble, mChannelWidth);
if (mMinDistanceMmSet) {
result = Objects.hash(result, mMinDistanceMm);
@@ -269,6 +414,9 @@
if (mMaxDistanceMmSet) {
result = Objects.hash(result, mMaxDistanceMm);
}
+ if (mPeriodicRangingEnabled) {
+ result = Objects.hash(result, mPeriodicRangingInterval);
+ }
return result;
}
@@ -339,9 +487,39 @@
"Maximum distance must be greater than minimum distance");
}
+ if (mPeriodicRangingEnabled && (mMinDistanceMmSet || mMaxDistanceMmSet)) {
+ throw new IllegalArgumentException(
+ "Either Periodic Ranging or Min/Max distance is allowed. Not both.");
+ }
+
if (!rttSupported && (mMinDistanceMmSet || mMaxDistanceMmSet)) {
throw new IllegalArgumentException("Ranging is not supported");
}
+ if ((!rttSupported || !characteristics.isPeriodicRangingSupported())
+ && mPeriodicRangingEnabled) {
+ throw new IllegalArgumentException("Periodic ranging is not supported");
+ }
+ if (mPeriodicRangingEnabled && mPeriodicRangingInterval < 0) {
+ throw new IllegalArgumentException("Periodic ranging interval must be non-negative");
+ }
+ if (mPeriodicRangingEnabled && mRttBurstSize < 0) {
+ throw new IllegalArgumentException("Rtt Burst size must be non-negative");
+ }
+ if (mPeriodicRangingEnabled && mFrequencyMhz < 0) {
+ throw new IllegalArgumentException(" Frequency must be non-negative");
+ }
+ if (mPeriodicRangingEnabled && mCenterFrequency0Mhz < 0) {
+ throw new IllegalArgumentException("Center Frequency0 must be non-negative");
+ }
+ if (mPeriodicRangingEnabled && mCenterFrequency1Mhz < 0) {
+ throw new IllegalArgumentException("Center Frequency1 must be non-negative");
+ }
+ if (mPeriodicRangingEnabled && mPreamble < 0) {
+ throw new IllegalArgumentException("Preamble must be non-negative");
+ }
+ if (mPeriodicRangingEnabled && mChannelWidth < 0) {
+ throw new IllegalArgumentException("Channel width must be non-negative");
+ }
}
/**
@@ -409,6 +587,108 @@
}
/**
+ * Check if periodic range reporting is enabled for subscribe session
+ * @see Builder#setPeriodicRangingEnabled(boolean)
+ * @return true for enabled, false otherwise.
+ * @hide
+ */
+ @FlaggedApi(FLAG_RANGING_RTT_ENABLED)
+ @SystemApi
+ public boolean isPeriodicRangingEnabled() {
+ return mPeriodicRangingEnabled;
+ }
+
+ /**
+ * Get periodic range reporting interval for subscribe session
+ * @see Builder#setPeriodicRangingInterval(int)
+ * @return interval of reporting.
+ * @hide
+ */
+ @FlaggedApi(FLAG_RANGING_RTT_ENABLED)
+ @SystemApi
+ public @PeriodicRangingInterval int getPeriodicRangingInterval() {
+ return mPeriodicRangingInterval;
+ }
+
+ /**
+ * Get the RTT burst size used to determine the average range.
+ * @see Builder#setRttBurstSize(int)
+ * @return the RTT burst size.
+ * @hide
+ */
+ @FlaggedApi(FLAG_RANGING_RTT_ENABLED)
+ @SystemApi
+ public int getRttBurstSize() {
+ return mRttBurstSize;
+ }
+
+ /**
+ * Get the frequency in MHz of the Wi-Fi channel
+ * @see Builder#setFrequencyMhz(int)
+ * @return frequency in MHz.
+ * @hide
+ */
+ @FlaggedApi(FLAG_RANGING_RTT_ENABLED)
+ @SystemApi
+ @IntRange(from = 0)
+ public int getFrequencyMhz() {
+ return mFrequencyMhz;
+ }
+
+ /**
+ * Get the center frequency in MHz of the first channel segment
+ * @see Builder#setCenterFreq0Mhz(int)
+ * @return the center frequency in MHz of the first channel segment.
+ * @hide
+ */
+ @FlaggedApi(FLAG_RANGING_RTT_ENABLED)
+ @SystemApi
+ @IntRange(from = 0)
+ public int getCenterFreq0Mhz() {
+ return mCenterFrequency0Mhz;
+ }
+
+ /**
+ * Get the center frequency in MHz of the second channel segment (if used)
+ * @see Builder#setCenterFreq1Mhz(int)
+ * @return the center frequency in MHz of the second channel segment
+ * @hide
+ */
+ @FlaggedApi(FLAG_RANGING_RTT_ENABLED)
+ @SystemApi
+ @IntRange(from = 0)
+ public int getCenterFreq1Mhz() {
+ return mCenterFrequency1Mhz;
+ }
+
+ /**
+ * Get the preamble type of the channel.
+ * @see Builder#setPreamble(int)
+ * @return the preamble used for this channel.
+ * @hide
+ */
+ @FlaggedApi(FLAG_RANGING_RTT_ENABLED)
+ @SystemApi
+ public @WifiAnnotations.PreambleType int getPreamble() {
+ return ResponderConfig.translateFromLocalToScanResultPreamble(mPreamble);
+ }
+
+ /**
+ * Channel bandwidth; one of {@link ScanResult#CHANNEL_WIDTH_20MHZ},
+ * {@link ScanResult#CHANNEL_WIDTH_40MHZ},
+ * {@link ScanResult#CHANNEL_WIDTH_80MHZ}, {@link ScanResult#CHANNEL_WIDTH_160MHZ},
+ * {@link ScanResult #CHANNEL_WIDTH_80MHZ_PLUS_MHZ} or {@link ScanResult#CHANNEL_WIDTH_320MHZ}.
+ * @see Builder#setChannelWidth(int)
+ * @return the bandwidth repsentation of the Wi-Fi channel
+ * @hide
+ */
+ @FlaggedApi(FLAG_RANGING_RTT_ENABLED)
+ @SystemApi
+ public @WifiAnnotations.ChannelWidth int getChannelWidth() {
+ return ResponderConfig.translateFromLocalToScanResultChannelWidth(mChannelWidth);
+ }
+
+ /**
* Builder used to build {@link SubscribeConfig} objects.
*/
public static final class Builder {
@@ -427,6 +707,14 @@
private AwarePairingConfig mPairingConfig;
private boolean mIsSuspendable = false;
private @NonNull List<OuiKeyedData> mVendorData = Collections.emptyList();
+ private boolean mPeriodicRangingEnabled = false;
+ private int mPeriodicRangingInterval = PERIODIC_RANGING_INTERVAL_512TU;
+ private int mRttBurstSize = RangingRequest.getDefaultRttBurstSize();
+ private int mFrequencyMhz = AWARE_BAND_2_DISCOVERY_CHANNEL;
+ private int mCenterFrequency0Mhz = 0;
+ private int mCenterFrequency1Mhz = 0;
+ private int mPreamble = ResponderConfig.PREAMBLE_HT;
+ private int mChannelWidth = ResponderConfig.CHANNEL_WIDTH_20MHZ;
/**
* Specify the service name of the subscribe session. The actual on-air
@@ -724,6 +1012,194 @@
}
/**
+ * Configure the interval for Wifi Aware periodic ranging.
+ * <p>
+ * To get the periodic ranging support use
+ * {@link Characteristics#isPeriodicRangingSupported()}
+ * When interval is not configured, default interval {@link PERIODIC_RANGING_INTERVAL_512TU}
+ * is used.
+ * </p>
+ *
+ * @param interval Ranging interval as described in {@link PeriodicRangingInterval}
+ * @return The builder to facilitate chaining
+ * {@code builder.setXXX(..).setXXX(..)}.
+ * @hide
+ */
+ @NonNull
+ @FlaggedApi(FLAG_RANGING_RTT_ENABLED)
+ @SystemApi
+ public Builder setPeriodicRangingInterval(@PeriodicRangingInterval int interval) {
+ if (interval != PERIODIC_RANGING_INTERVAL_NONE
+ && interval != PERIODIC_RANGING_INTERVAL_128TU
+ && interval != PERIODIC_RANGING_INTERVAL_256TU
+ && interval != PERIODIC_RANGING_INTERVAL_512TU
+ && interval != PERIODIC_RANGING_INTERVAL_1024TU
+ && interval != PERIODIC_RANGING_INTERVAL_2048TU
+ && interval != PERIODIC_RANGING_INTERVAL_4096TU
+ && interval != PERIODIC_RANGING_INTERVAL_8192TU) {
+ throw new IllegalArgumentException("Invalid Ranging interval - " + interval);
+ }
+ mPeriodicRangingInterval = interval;
+ return this;
+ }
+
+ /**
+ * Enable Wifi Aware periodic ranging.
+ * <p>
+ * To get the periodic ranging support use
+ * {@link Characteristics#isPeriodicRangingSupported()}
+ *
+ * Wifi aware based periodic ranging allows continuous ranging report based on configured
+ * interval through {@link #setPeriodicRangingInterval()}. To stop continuous ranging
+ * results, reset the {@link #setPeriodicRangingEnabled()} and reconfigure using updated
+ * {@link SubscribeDiscoverySession#updateSubscribe(SubscribeConfig)}
+ * </p>
+ *
+ * @param enable Enable or disable periodic ranging report
+ * @return The builder to facilitate chaining
+ * {@code builder.setXXX(..).setXXX(..)}.
+ * @hide
+ */
+ @NonNull
+ @FlaggedApi(FLAG_RANGING_RTT_ENABLED)
+ @SystemApi
+ public Builder setPeriodicRangingEnabled(boolean enable) {
+ mPeriodicRangingEnabled = enable;
+ return this;
+ }
+
+ /**
+ * Set the RTT Burst size for the Aware Periodic Ranging.
+ * <p>
+ * If not set, the default RTT burst size given by
+ * {@link RangingRequest#getDefaultRttBurstSize()} is used to determine the default value.
+ * If set, the value must be in the range {@link RangingRequest#getMinRttBurstSize()} and
+ * {@link RangingRequest#getMaxRttBurstSize()} inclusively, or a
+ * {@link java.lang.IllegalArgumentException} will be thrown.
+ * </p>
+ *
+ * @param burstSize The number of FTM packets used to estimate a range
+ * @return The builder to facilitate chaining
+ * {@code builder.setXXX(..).setXXX(..)}.
+ * @hide
+ */
+ @NonNull
+ @FlaggedApi(FLAG_RANGING_RTT_ENABLED)
+ @SystemApi
+ public Builder setRttBurstSize(int burstSize) {
+ if (burstSize < MIN_RTT_BURST_SIZE || burstSize > MAX_RTT_BURST_SIZE) {
+ throw new IllegalArgumentException("RTT burst size out of range.");
+ }
+ mRttBurstSize = burstSize;
+ return this;
+ }
+
+ /**
+ * Sets the frequency of the channel in MHz.
+ * <p>
+ * Note: The frequency is used as a hint, and the underlying WiFi subsystem may use it, or
+ * select an alternate if its own connectivity scans have determined the frequency of the
+ * Peer/Publisher has changed.
+ * </p>
+ *
+ * @param frequency the frequency of the channel in MHz
+ * @return The builder to facilitate chaining
+ * {@code builder.setXXX(..).setXXX(..)}.
+ * @hide
+ */
+ @NonNull
+ @FlaggedApi(FLAG_RANGING_RTT_ENABLED)
+ @SystemApi
+ public Builder setFrequencyMhz(@IntRange(from = 0) int frequency) {
+ mFrequencyMhz = frequency;
+ return this;
+ }
+
+ /**
+ * Sets the center frequency in MHz of the first segment of the channel.
+ * <p>
+ * Note: The frequency is used as a hint, and the underlying WiFi subsystem may use it, or
+ * select an alternate if its own connectivity scans have determined the frequency of the
+ * Peer/Publisher has changed.
+ * </p>
+ *
+ * @param centerFreq0 the center frequency in MHz of first channel segment
+ * @return The builder to facilitate chaining
+ * {@code builder.setXXX(..).setXXX(..)}.
+ * @hide
+ */
+ @NonNull
+ @FlaggedApi(FLAG_RANGING_RTT_ENABLED)
+ @SystemApi
+ public Builder setCenterFreq0Mhz(@IntRange(from = 0) int centerFreq0) {
+ mCenterFrequency0Mhz = centerFreq0;
+ return this;
+ }
+
+ /**
+ * Sets the center frequency in MHz of the second segment of the channel, if used.
+ * <p>
+ * Note: The frequency is used as a hint, and the underlying WiFi subsystem may use it, or
+ * select an alternate if its own connectivity scans have determined the frequency of the
+ * Peer/Publisher has changed.
+ * </p>
+ *
+ * @param centerFreq1 the center frequency in MHz of second channel segment
+ * @return The builder to facilitate chaining
+ * {@code builder.setXXX(..).setXXX(..)}.
+ * @hide
+ */
+ @NonNull
+ @FlaggedApi(FLAG_RANGING_RTT_ENABLED)
+ @SystemApi
+ public Builder setCenterFreq1Mhz(@IntRange(from = 0) int centerFreq1) {
+ mCenterFrequency1Mhz = centerFreq1;
+ return this;
+ }
+
+ /**
+ * Sets the preamble encoding for the protocol.
+ * <p>
+ * Note: The preamble is used as a hint, and the underlying WiFi subsystem may use it, or
+ * select an alternate based on negotiation of Peer capability or concurrency management.
+ * </p>
+ *
+ * @param preamble the preamble encoding
+ * @return The builder to facilitate chaining
+ * {@code builder.setXXX(..).setXXX(..)}.
+ * @hide
+ */
+ @NonNull
+ @FlaggedApi(FLAG_RANGING_RTT_ENABLED)
+ @SystemApi
+ public Builder setPreamble(@WifiAnnotations.PreambleType int preamble) {
+ mPreamble = ResponderConfig.translateFromScanResultToLocalPreamble(preamble);
+ return this;
+ }
+
+ /**
+ * Sets the channel bandwidth.
+ * <p>
+ * Note: The channel bandwidth is used as a hint, and the underlying WiFi subsystem may use
+ * it, or select an alternate based on negotiation of Peer capability or concurrency
+ * management.
+ * </p>
+ *
+ * @param channelWidth the bandwidth of the channel in MHz
+ * @return The builder to facilitate chaining
+ * {@code builder.setXXX(..).setXXX(..)}.
+ * @hide
+ */
+ @NonNull
+ @FlaggedApi(FLAG_RANGING_RTT_ENABLED)
+ @SystemApi
+ public Builder setChannelWidth(@WifiAnnotations.ChannelWidth int channelWidth) {
+ mChannelWidth =
+ ResponderConfig.translateFromScanResultToLocalChannelWidth(channelWidth);
+ return this;
+ }
+
+ /**
* Build {@link SubscribeConfig} given the current requests made on the
* builder.
*/
@@ -731,7 +1207,11 @@
return new SubscribeConfig(mServiceName, mServiceSpecificInfo, mMatchFilter,
mSubscribeType, mTtlSec, mEnableTerminateNotification,
mMinDistanceMmSet, mMinDistanceMm, mMaxDistanceMmSet, mMaxDistanceMm,
- mEnableInstantMode, mBand, mPairingConfig, mIsSuspendable, mVendorData);
+ mEnableInstantMode, mBand, mPairingConfig, mIsSuspendable, mVendorData,
+ mPeriodicRangingInterval, mPeriodicRangingEnabled, mRttBurstSize,
+ mFrequencyMhz, mCenterFrequency0Mhz, mCenterFrequency1Mhz, mPreamble,
+ mChannelWidth);
+
}
}
}
diff --git a/framework/java/android/net/wifi/aware/WifiAwareManager.java b/framework/java/android/net/wifi/aware/WifiAwareManager.java
index 2edf792..d74052c 100644
--- a/framework/java/android/net/wifi/aware/WifiAwareManager.java
+++ b/framework/java/android/net/wifi/aware/WifiAwareManager.java
@@ -45,6 +45,7 @@
import android.net.wifi.IListListener;
import android.net.wifi.OuiKeyedData;
import android.net.wifi.WifiManager;
+import android.net.wifi.rtt.RangingResult;
import android.net.wifi.util.HexEncoding;
import android.os.Binder;
import android.os.Build;
@@ -1227,6 +1228,11 @@
}
}
+ @Override
+ public void onRangingResultsReceived(List<RangingResult> rangingResults) {
+ mHandler.post(() -> mOriginalCallback.onRangingResultsReceived(rangingResults));
+ }
+
/*
* Proxies methods
*/
diff --git a/framework/java/android/net/wifi/p2p/WifiP2pConfig.java b/framework/java/android/net/wifi/p2p/WifiP2pConfig.java
index d2775fe..67f1e6c 100644
--- a/framework/java/android/net/wifi/p2p/WifiP2pConfig.java
+++ b/framework/java/android/net/wifi/p2p/WifiP2pConfig.java
@@ -27,6 +27,7 @@
import android.net.wifi.OuiKeyedData;
import android.net.wifi.ParcelUtil;
import android.net.wifi.WpsInfo;
+import android.net.wifi.util.Environment;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
@@ -43,6 +44,7 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.Objects;
import java.util.regex.PatternSyntaxException;
/**
@@ -52,6 +54,10 @@
*/
public class WifiP2pConfig implements Parcelable {
+ static final int PSK_PASSWORD_MIN_LEN = 8;
+ static final int PSK_PASSWORD_MAX_LEN = 63;
+ static final int SAE_PASSWORD_MAX_LEN = 128;
+
/**
* The device MAC address uniquely identifies a Wi-Fi p2p device
*/
@@ -85,7 +91,8 @@
* The result will be one of the following:
* {@link #GROUP_OWNER_BAND_AUTO},
* {@link #GROUP_OWNER_BAND_2GHZ},
- * {@link #GROUP_OWNER_BAND_5GHZ}
+ * {@link #GROUP_OWNER_BAND_5GHZ},
+ * {@link #GROUP_OWNER_BAND_6GHZ}
*/
@GroupOperatingBandType
public int getGroupOwnerBand() {
@@ -98,9 +105,10 @@
/** @hide */
@IntDef(flag = false, prefix = { "GROUP_OWNER_BAND_" }, value = {
- GROUP_OWNER_BAND_AUTO,
- GROUP_OWNER_BAND_2GHZ,
- GROUP_OWNER_BAND_5GHZ
+ GROUP_OWNER_BAND_AUTO,
+ GROUP_OWNER_BAND_2GHZ,
+ GROUP_OWNER_BAND_5GHZ,
+ GROUP_OWNER_BAND_6GHZ,
})
@Retention(RetentionPolicy.SOURCE)
public @interface GroupOperatingBandType {}
@@ -127,6 +135,11 @@
* Allow the system to pick the operating frequency from the 5 GHz band.
*/
public static final int GROUP_OWNER_BAND_5GHZ = 2;
+ /**
+ * Allow the system to pick the operating frequency from the 6 GHz band.
+ */
+ @FlaggedApi(Flags.FLAG_WIFI_DIRECT_R2)
+ public static final int GROUP_OWNER_BAND_6GHZ = 3;
/**
* The least inclination to be a group owner, to be filled in the field
@@ -243,6 +256,165 @@
return mVendorData;
}
+ /**
+ * Default connection type used internally by the P2P service.
+ *
+ * @hide
+ */
+ public static final int PCC_MODE_DEFAULT_CONNECTION_TYPE_LEGACY_ONLY = 0;
+
+ /**
+ * Legacy connection type.
+ * <p>Group Owner: Configured to support WPA2-Personal connections.
+ * <p>Group Client: Configured to connect to Group Owner using WPA2-Personal.
+ */
+ @FlaggedApi(Flags.FLAG_WIFI_DIRECT_R2)
+ public static final int PCC_MODE_CONNECTION_TYPE_LEGACY_ONLY =
+ PCC_MODE_DEFAULT_CONNECTION_TYPE_LEGACY_ONLY;
+
+ /**
+ * Wi-Fi Direct R1/R2 compatible mode connection type.
+ * <p>Group Owner: Configured in WPA3-Personal Compatibility Mode to support WPA3-Personal and
+ * WPA2-Personal connections simultaneously.
+ * <p>Group Client: Configured to connect to Group Owner using WPA3-Personal or WPA2-Personal.
+ * The system will choose WPA3-Personal if Group Owner support WPA3-Personal.
+ */
+ @FlaggedApi(Flags.FLAG_WIFI_DIRECT_R2)
+ public static final int PCC_MODE_CONNECTION_TYPE_LEGACY_OR_R2 = 1;
+
+ /**
+ * This configuration allows only Wi-Fi Direct R2 supported devices to establish connection.
+ * <p>Group Owner: Configured to support WPA3-Personal connections.
+ * <p>Group Client: Configured to connect to Group Owner using WPA3-Personal.
+ */
+ @FlaggedApi(Flags.FLAG_WIFI_DIRECT_R2)
+ public static final int PCC_MODE_CONNECTION_TYPE_R2_ONLY = 2;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = { "PCC_MODE_CONNECTION_TYPE_" }, value = {
+ PCC_MODE_DEFAULT_CONNECTION_TYPE_LEGACY_ONLY,
+ PCC_MODE_CONNECTION_TYPE_LEGACY_ONLY,
+ PCC_MODE_CONNECTION_TYPE_LEGACY_OR_R2,
+ PCC_MODE_CONNECTION_TYPE_R2_ONLY,
+ })
+ public @interface PccModeConnectionType {}
+
+ @PccModeConnectionType
+ private int mPccModeConnectionType = PCC_MODE_DEFAULT_CONNECTION_TYPE_LEGACY_ONLY;
+
+ /**
+ * Get the PCC Mode connection type.
+ *
+ * @return One of the {@code PCC_MODE_CONNECTION_TYPE_*}.
+ */
+ @RequiresApi(Build.VERSION_CODES.BAKLAVA)
+ @FlaggedApi(Flags.FLAG_WIFI_DIRECT_R2)
+ public @PccModeConnectionType int getPccModeConnectionType() {
+ if (!Environment.isSdkAtLeastB()) {
+ throw new UnsupportedOperationException();
+ }
+ return mPccModeConnectionType;
+ }
+
+ /**
+ * Default P2P version used internally by the P2P service.
+ *
+ * @hide
+ */
+ public static final int P2P_DEFAULT_VERSION_1 = 0;
+
+ /**
+ * P2P Protocol version 1
+ */
+ @FlaggedApi(Flags.FLAG_WIFI_DIRECT_R2)
+ public static final int P2P_VERSION_1 = P2P_DEFAULT_VERSION_1;
+
+ /**
+ * P2P Protocol version 2
+ */
+ @FlaggedApi(Flags.FLAG_WIFI_DIRECT_R2)
+ public static final int P2P_VERSION_2 = 1;
+
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(flag = false, prefix = { "P2P_VERSION_" }, value = {
+ P2P_DEFAULT_VERSION_1,
+ P2P_VERSION_1,
+ P2P_VERSION_2,
+ })
+ public @interface P2pVersion {}
+
+ @P2pVersion
+ private int mGroupOwnerVersion = P2P_DEFAULT_VERSION_1;
+
+ /**
+ * Get the P2P Group Owner version.
+ * See also {@link #setGroupOwnerVersion(int)}.
+ *
+ * @return The P2P Group Owner protocol version.
+ */
+ @RequiresApi(Build.VERSION_CODES.BAKLAVA)
+ @FlaggedApi(Flags.FLAG_WIFI_DIRECT_R2)
+ public @P2pVersion int getGroupOwnerVersion() {
+ if (!Environment.isSdkAtLeastB()) {
+ throw new UnsupportedOperationException();
+ }
+ return mGroupOwnerVersion;
+ }
+
+ /**
+ * Set the P2P Group Owner version.
+ *
+ * @param version The P2P Group Owner protocol version.
+ */
+ @RequiresApi(Build.VERSION_CODES.BAKLAVA)
+ @FlaggedApi(Flags.FLAG_WIFI_DIRECT_R2)
+ public void setGroupOwnerVersion(
+ @P2pVersion int version) {
+ if (!Environment.isSdkAtLeastB()) {
+ throw new UnsupportedOperationException();
+ }
+ mGroupOwnerVersion = version;
+ }
+
+ private @Nullable WifiP2pPairingBootstrappingConfig mPairingBootstrappingConfig;
+
+ /**
+ * Get the pairing bootstrapping configuration , or null if unset.
+ */
+ @RequiresApi(Build.VERSION_CODES.BAKLAVA)
+ @FlaggedApi(Flags.FLAG_WIFI_DIRECT_R2)
+ @Nullable
+ public WifiP2pPairingBootstrappingConfig getPairingBootstrappingConfig() {
+ if (!Environment.isSdkAtLeastB()) {
+ throw new UnsupportedOperationException();
+ }
+ return mPairingBootstrappingConfig;
+ }
+
+ /**
+ * Used to authorize a connection request from the peer device.
+ */
+ private boolean mAuthorizeConnectionFromPeer = false;
+
+ /**
+ * Query to check if the configuration is for authorizing a connection request
+ * from the peer device. @see {@link Builder#setAuthorizeConnectionFromPeer(boolean)}
+ *
+ * @return true if configured to authorize a connection request from the Peer device,
+ * False otherwise.
+ */
+ @RequiresApi(Build.VERSION_CODES.BAKLAVA)
+ @FlaggedApi(Flags.FLAG_WIFI_DIRECT_R2)
+ public boolean isAuthorizeConnectionFromPeer() {
+ if (!Environment.isSdkAtLeastB()) {
+ throw new UnsupportedOperationException();
+ }
+ return mAuthorizeConnectionFromPeer;
+ }
+
public WifiP2pConfig() {
//set defaults
wps = new WpsInfo();
@@ -315,10 +487,18 @@
sbuf.append("\n networkName: ").append(networkName);
sbuf.append("\n passphrase: ").append(
TextUtils.isEmpty(passphrase) ? "<empty>" : "<non-empty>");
+ sbuf.append("\n pccModeConnectionType: ").append(mPccModeConnectionType);
sbuf.append("\n groupOwnerBand: ").append(groupOwnerBand);
sbuf.append("\n groupClientIpProvisioningMode: ").append(mGroupClientIpProvisioningMode);
sbuf.append("\n joinExistingGroup: ").append(mJoinExistingGroup);
sbuf.append("\n vendorData: ").append(mVendorData);
+ sbuf.append("\n Group Owner Version: ").append(mGroupOwnerVersion);
+ if (Environment.isSdkAtLeastB() && Flags.wifiDirectR2()) {
+ sbuf.append("\n Pairing bootstrapping config : ")
+ .append((mPairingBootstrappingConfig == null)
+ ? "<null>" : mPairingBootstrappingConfig.toString());
+ }
+ sbuf.append("\n authorizeConnectionFromPeer: ").append(mAuthorizeConnectionFromPeer);
return sbuf.toString();
}
@@ -336,10 +516,14 @@
netId = source.netId;
networkName = source.networkName;
passphrase = source.passphrase;
+ mPccModeConnectionType = source.mPccModeConnectionType;
groupOwnerBand = source.groupOwnerBand;
mGroupClientIpProvisioningMode = source.mGroupClientIpProvisioningMode;
mJoinExistingGroup = source.mJoinExistingGroup;
mVendorData = new ArrayList<>(source.mVendorData);
+ mGroupOwnerVersion = source.mGroupOwnerVersion;
+ mPairingBootstrappingConfig = source.mPairingBootstrappingConfig;
+ mAuthorizeConnectionFromPeer = source.mAuthorizeConnectionFromPeer;
}
}
@@ -351,10 +535,16 @@
dest.writeInt(netId);
dest.writeString(networkName);
dest.writeString(passphrase);
+ dest.writeInt(mPccModeConnectionType);
dest.writeInt(groupOwnerBand);
dest.writeInt(mGroupClientIpProvisioningMode);
dest.writeBoolean(mJoinExistingGroup);
dest.writeList(mVendorData);
+ dest.writeInt(mGroupOwnerVersion);
+ if (Environment.isSdkAtLeastB() && Flags.wifiDirectR2()) {
+ dest.writeParcelable(mPairingBootstrappingConfig, flags);
+ }
+ dest.writeBoolean(mAuthorizeConnectionFromPeer);
}
/** Implement the Parcelable interface */
@@ -362,18 +552,25 @@
public static final Creator<WifiP2pConfig> CREATOR =
new Creator<WifiP2pConfig>() {
public WifiP2pConfig createFromParcel(Parcel in) {
- WifiP2pConfig config = new WifiP2pConfig();
- config.deviceAddress = in.readString();
- config.wps = (WpsInfo) in.readParcelable(null);
- config.groupOwnerIntent = in.readInt();
- config.netId = in.readInt();
- config.networkName = in.readString();
- config.passphrase = in.readString();
- config.groupOwnerBand = in.readInt();
- config.mGroupClientIpProvisioningMode = in.readInt();
- config.mJoinExistingGroup = in.readBoolean();
- config.mVendorData = ParcelUtil.readOuiKeyedDataList(in);
- return config;
+ WifiP2pConfig config = new WifiP2pConfig();
+ config.deviceAddress = in.readString();
+ config.wps = (WpsInfo) in.readParcelable(WpsInfo.class.getClassLoader());
+ config.groupOwnerIntent = in.readInt();
+ config.netId = in.readInt();
+ config.networkName = in.readString();
+ config.passphrase = in.readString();
+ config.mPccModeConnectionType = in.readInt();
+ config.groupOwnerBand = in.readInt();
+ config.mGroupClientIpProvisioningMode = in.readInt();
+ config.mJoinExistingGroup = in.readBoolean();
+ config.mVendorData = ParcelUtil.readOuiKeyedDataList(in);
+ config.mGroupOwnerVersion = in.readInt();
+ if (Environment.isSdkAtLeastB() && Flags.wifiDirectR2()) {
+ config.mPairingBootstrappingConfig = in.readParcelable(
+ WifiP2pPairingBootstrappingConfig.class.getClassLoader());
+ }
+ config.mAuthorizeConnectionFromPeer = in.readBoolean();
+ return config;
}
public WifiP2pConfig[] newArray(int size) {
@@ -410,6 +607,10 @@
private int mNetId = WifiP2pGroup.NETWORK_ID_TEMPORARY;
private int mGroupClientIpProvisioningMode = GROUP_CLIENT_IP_PROVISIONING_MODE_IPV4_DHCP;
private boolean mJoinExistingGroup = false;
+ @PccModeConnectionType
+ private int mPccModeConnectionType = PCC_MODE_DEFAULT_CONNECTION_TYPE_LEGACY_ONLY;
+ private @Nullable WifiP2pPairingBootstrappingConfig mPairingBootstrappingConfig;
+ private boolean mAuthorizeConnectionFromPeer = false;
/**
* Specify the peer's MAC address. If not set, the device will
@@ -477,8 +678,11 @@
/**
* Specify the passphrase for creating or joining a group.
* <p>
- * The passphrase must be an ASCII string whose length is between 8
- * and 63.
+ * The passphrase must be an ASCII string whose length is,
+ * 1. Between 8 and 63 for {@link #PCC_MODE_CONNECTION_TYPE_LEGACY_ONLY} and
+ * {@link #PCC_MODE_CONNECTION_TYPE_LEGACY_OR_R2}.
+ * 2. Less than 128 for {@link #PCC_MODE_CONNECTION_TYPE_R2_ONLY}.
+ *
* <p>
* Must be called - an empty passphrase is not valid.
*
@@ -488,29 +692,60 @@
*/
@NonNull
public Builder setPassphrase(@NonNull String passphrase) {
+ Objects.requireNonNull(passphrase, "passphrase cannot be null");
if (TextUtils.isEmpty(passphrase)) {
throw new IllegalArgumentException(
"passphrase must be non-empty.");
}
- if (passphrase.length() < 8 || passphrase.length() > 63) {
+ if (passphrase.length() > SAE_PASSWORD_MAX_LEN) {
throw new IllegalArgumentException(
- "The length of a passphrase must be between 8 and 63.");
+ "The length of a passphrase must be less than 128");
}
mPassphrase = passphrase;
return this;
}
/**
+ * Specifies the PCC Mode connection type.
+ *
+ * @param connectionType One of the {@code PCC_MODE_CONNECTION_TYPE_*}.
+ * @return Builder for chaining.
+ *
+ * @throws IllegalArgumentException when the connectionType is invalid.
+ */
+ @RequiresApi(Build.VERSION_CODES.BAKLAVA)
+ @FlaggedApi(Flags.FLAG_WIFI_DIRECT_R2)
+ @NonNull
+ public Builder setPccModeConnectionType(
+ @PccModeConnectionType int connectionType) {
+ if (!Environment.isSdkAtLeastB()) {
+ throw new UnsupportedOperationException();
+ }
+ switch (connectionType) {
+ case PCC_MODE_CONNECTION_TYPE_LEGACY_ONLY:
+ case PCC_MODE_CONNECTION_TYPE_LEGACY_OR_R2:
+ case PCC_MODE_CONNECTION_TYPE_R2_ONLY:
+ mPccModeConnectionType = connectionType;
+ break;
+ default:
+ throw new IllegalArgumentException(
+ "Invalid constant for the PCC Mode connection type!");
+ }
+ return this;
+ }
+
+ /**
* Specify the band to use for creating the group or joining the group. The band should
* be {@link #GROUP_OWNER_BAND_2GHZ}, {@link #GROUP_OWNER_BAND_5GHZ} or
- * {@link #GROUP_OWNER_BAND_AUTO}.
+ * {@link #GROUP_OWNER_BAND_6GHZ} or {@link #GROUP_OWNER_BAND_AUTO}.
* <p>
* When creating a group as Group Owner using {@link
* WifiP2pManager#createGroup(WifiP2pManager.Channel,
* WifiP2pConfig, WifiP2pManager.ActionListener)},
* specifying {@link #GROUP_OWNER_BAND_AUTO} allows the system to pick the operating
* frequency from all supported bands.
- * Specifying {@link #GROUP_OWNER_BAND_2GHZ} or {@link #GROUP_OWNER_BAND_5GHZ}
+ * Specifying {@link #GROUP_OWNER_BAND_2GHZ} or {@link #GROUP_OWNER_BAND_5GHZ} or
+ * {@link #GROUP_OWNER_BAND_6GHZ}
* only allows the system to pick the operating frequency in the specified band.
* If the Group Owner cannot create a group in the specified band, the operation will fail.
* <p>
@@ -519,7 +754,8 @@
* WifiP2pManager.ActionListener)},
* specifying {@link #GROUP_OWNER_BAND_AUTO} allows the system to scan all supported
* frequencies to find the desired group. Specifying {@link #GROUP_OWNER_BAND_2GHZ} or
- * {@link #GROUP_OWNER_BAND_5GHZ} only allows the system to scan the specified band.
+ * {@link #GROUP_OWNER_BAND_5GHZ} or {@link #GROUP_OWNER_BAND_6GHZ} only allows the
+ * system to scan the specified band.
* <p>
* {@link #setGroupOperatingBand(int)} and {@link #setGroupOperatingFrequency(int)} are
* mutually exclusive. Setting operating band and frequency both is invalid.
@@ -528,20 +764,21 @@
*
* @param band the operating band of the group.
* This should be one of {@link #GROUP_OWNER_BAND_AUTO},
- * {@link #GROUP_OWNER_BAND_2GHZ}, {@link #GROUP_OWNER_BAND_5GHZ}.
+ * {@link #GROUP_OWNER_BAND_2GHZ}, {@link #GROUP_OWNER_BAND_5GHZ},
+ * {@link #GROUP_OWNER_BAND_6GHZ}.
* @return The builder to facilitate chaining
* {@code builder.setXXX(..).setXXX(..)}.
*/
@NonNull
public Builder setGroupOperatingBand(@GroupOperatingBandType int band) {
- switch (band) {
- case GROUP_OWNER_BAND_AUTO:
- case GROUP_OWNER_BAND_2GHZ:
- case GROUP_OWNER_BAND_5GHZ:
- mGroupOperatingBand = band;
- break;
- default:
- throw new IllegalArgumentException(
+ if (GROUP_OWNER_BAND_AUTO == band
+ || GROUP_OWNER_BAND_2GHZ == band
+ || GROUP_OWNER_BAND_5GHZ == band
+ || (Environment.isSdkAtLeastB() && Flags.wifiDirectR2()
+ && GROUP_OWNER_BAND_6GHZ == band)) {
+ mGroupOperatingBand = band;
+ } else {
+ throw new IllegalArgumentException(
"Invalid constant for the group operating band!");
}
return this;
@@ -682,6 +919,54 @@
}
/**
+ * Set the pairing bootstrapping configuration for connecting using P2P pairing
+ * Protocol.
+ *
+ * @param config See {@link WifiP2pPairingBootstrappingConfig }
+ * @return The builder to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
+ */
+ @RequiresApi(Build.VERSION_CODES.BAKLAVA)
+ @FlaggedApi(Flags.FLAG_WIFI_DIRECT_R2)
+ @NonNull
+ public Builder setPairingBootstrappingConfig(
+ @NonNull WifiP2pPairingBootstrappingConfig config) {
+ if (!Environment.isSdkAtLeastB()) {
+ throw new UnsupportedOperationException();
+ }
+ Objects.requireNonNull(config, "config cannot be null");
+ mPairingBootstrappingConfig = config;
+ return this;
+ }
+
+ /**
+ * Specify that the configuration is to authorize a connection request from a peer device.
+ * The MAC address of the peer device is specified using
+ * {@link WifiP2pConfig.Builder#setDeviceAddress(MacAddress)}.
+ * <p>
+ * Optional. false by default. The default configuration is to join a group or to initiate
+ * a group formation.
+ * <p>
+ * This configuration is typically used in Bluetooth LE assisted P2P pairing protocol
+ * defined in Wi-Fi Direct R2 specification, section 3.9. The collocated Bluetooth Provider
+ * sends the pairing password to the peer device (Seeker) and direct the system to
+ * authorize the connection request from the peer device using {@link
+ * WifiP2pManager#connect(WifiP2pManager.Channel, WifiP2pConfig,
+ * WifiP2pManager.ActionListener)}. The device will then wait for the connection request
+ * from the peer device.
+ *
+ * @param authorize true to authorize a connection request from the peer device, false to
+ * let the device join a group or form a group.
+ * @return The builder to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
+ */
+ @RequiresApi(Build.VERSION_CODES.BAKLAVA)
+ @FlaggedApi(Flags.FLAG_WIFI_DIRECT_R2)
+ @NonNull
+ public Builder setAuthorizeConnectionFromPeer(boolean authorize) {
+ mAuthorizeConnectionFromPeer = authorize;
+ return this;
+ }
+
+ /**
* Build {@link WifiP2pConfig} given the current requests made on the builder.
* @return {@link WifiP2pConfig} constructed based on builder method calls.
*/
@@ -695,7 +980,21 @@
if (TextUtils.isEmpty(mNetworkName)
&& mDeviceAddress.equals(MAC_ANY_ADDRESS)) {
throw new IllegalStateException(
- "peer address must be set if network name and pasphrase are not set.");
+ "peer address must be set if network name and passphrase are not set.");
+ }
+
+ if (!TextUtils.isEmpty(mNetworkName)
+ && !TextUtils.isEmpty(mPassphrase)) {
+ if (mPccModeConnectionType == PCC_MODE_CONNECTION_TYPE_LEGACY_ONLY
+ || mPccModeConnectionType == PCC_MODE_CONNECTION_TYPE_LEGACY_OR_R2) {
+ if (mPassphrase.length() < PSK_PASSWORD_MIN_LEN
+ || mPassphrase.length() > PSK_PASSWORD_MAX_LEN) {
+ throw new IllegalArgumentException(
+ "The length of a passphrase must be between "
+ + PSK_PASSWORD_MIN_LEN + " and "
+ + PSK_PASSWORD_MAX_LEN + " for legacy connection type");
+ }
+ }
}
if (mGroupOperatingFrequency > 0 && mGroupOperatingBand > 0) {
@@ -707,6 +1006,7 @@
config.deviceAddress = mDeviceAddress.toString();
config.networkName = mNetworkName;
config.passphrase = mPassphrase;
+ config.mPccModeConnectionType = mPccModeConnectionType;
config.groupOwnerBand = GROUP_OWNER_BAND_AUTO;
if (mGroupOperatingFrequency > 0) {
config.groupOwnerBand = mGroupOperatingFrequency;
@@ -716,6 +1016,8 @@
config.netId = mNetId;
config.mGroupClientIpProvisioningMode = mGroupClientIpProvisioningMode;
config.mJoinExistingGroup = mJoinExistingGroup;
+ config.mPairingBootstrappingConfig = mPairingBootstrappingConfig;
+ config.mAuthorizeConnectionFromPeer = mAuthorizeConnectionFromPeer;
return config;
}
}
diff --git a/framework/java/android/net/wifi/p2p/WifiP2pDevice.java b/framework/java/android/net/wifi/p2p/WifiP2pDevice.java
index 75ae83d..a6d8048 100644
--- a/framework/java/android/net/wifi/p2p/WifiP2pDevice.java
+++ b/framework/java/android/net/wifi/p2p/WifiP2pDevice.java
@@ -25,6 +25,7 @@
import android.net.wifi.OuiKeyedData;
import android.net.wifi.ParcelUtil;
import android.net.wifi.ScanResult;
+import android.net.wifi.util.Environment;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
@@ -214,6 +215,11 @@
}
return mVendorData;
}
+ /**
+ * The bitmask of supported {@code PAIRING_BOOTSTRAPPING_METHOD_*} methods used to enable
+ * the pairing bootstrapping between bootstrapping initiator and a bootstrapping responder.
+ */
+ private int mPairingBootstrappingMethods;
public WifiP2pDevice() {
}
@@ -467,6 +473,91 @@
mIpAddress = ipAddress;
}
+ /**
+ * Returns true if opportunistic bootstrapping method is supported.
+ * Defined in Wi-Fi Alliance Wi-Fi Direct R2 Specification Table 10 - Bootstrapping Methods.
+ */
+ @RequiresApi(Build.VERSION_CODES.BAKLAVA)
+ @FlaggedApi(Flags.FLAG_WIFI_DIRECT_R2)
+ public boolean isOpportunisticBootstrappingMethodSupported() {
+ if (!Environment.isSdkAtLeastB()) {
+ throw new UnsupportedOperationException();
+ }
+ return (mPairingBootstrappingMethods & WifiP2pPairingBootstrappingConfig
+ .PAIRING_BOOTSTRAPPING_METHOD_OPPORTUNISTIC) != 0;
+ }
+
+ /**
+ * Returns true if pin-code display bootstrapping method is supported.
+ * Defined in Wi-Fi Alliance Wi-Fi Direct R2 Specification Table 10 - Bootstrapping Methods.
+ */
+ @RequiresApi(Build.VERSION_CODES.BAKLAVA)
+ @FlaggedApi(Flags.FLAG_WIFI_DIRECT_R2)
+ public boolean isPinCodeDisplayBootstrappingMethodSupported() {
+ if (!Environment.isSdkAtLeastB()) {
+ throw new UnsupportedOperationException();
+ }
+ return (mPairingBootstrappingMethods & WifiP2pPairingBootstrappingConfig
+ .PAIRING_BOOTSTRAPPING_METHOD_DISPLAY_PINCODE) != 0;
+ }
+
+ /**
+ * Returns true if passphrase display bootstrapping method is supported.
+ * Defined in Wi-Fi Alliance Wi-Fi Direct R2 Specification Table 10 - Bootstrapping Methods.
+ */
+ @RequiresApi(Build.VERSION_CODES.BAKLAVA)
+ @FlaggedApi(Flags.FLAG_WIFI_DIRECT_R2)
+ public boolean isPassphraseDisplayBootstrappingMethodSupported() {
+ if (!Environment.isSdkAtLeastB()) {
+ throw new UnsupportedOperationException();
+ }
+ return (mPairingBootstrappingMethods & WifiP2pPairingBootstrappingConfig
+ .PAIRING_BOOTSTRAPPING_METHOD_DISPLAY_PASSPHRASE) != 0;
+ }
+
+ /**
+ * Returns true if pin-code keypad bootstrapping method is supported.
+ * Defined in Wi-Fi Alliance Wi-Fi Direct R2 Specification Table 10 - Bootstrapping Methods.
+ */
+ @RequiresApi(Build.VERSION_CODES.BAKLAVA)
+ @FlaggedApi(Flags.FLAG_WIFI_DIRECT_R2)
+ public boolean isPinCodeKeypadBootstrappingMethodSupported() {
+ if (!Environment.isSdkAtLeastB()) {
+ throw new UnsupportedOperationException();
+ }
+ return (mPairingBootstrappingMethods & WifiP2pPairingBootstrappingConfig
+ .PAIRING_BOOTSTRAPPING_METHOD_KEYPAD_PINCODE) != 0;
+ }
+
+ /**
+ * Returns true if passphrase keypad bootstrapping method is supported.
+ * Defined in Wi-Fi Alliance Wi-Fi Direct R2 Specification Table 10 - Bootstrapping Methods.
+ */
+ @RequiresApi(Build.VERSION_CODES.BAKLAVA)
+ @FlaggedApi(Flags.FLAG_WIFI_DIRECT_R2)
+ public boolean isPassphraseKeypadBootstrappingMethodSupported() {
+ if (!Environment.isSdkAtLeastB()) {
+ throw new UnsupportedOperationException();
+ }
+ return (mPairingBootstrappingMethods & WifiP2pPairingBootstrappingConfig
+ .PAIRING_BOOTSTRAPPING_METHOD_KEYPAD_PASSPHRASE) != 0;
+ }
+
+ /**
+ * Set the supported pairing bootstrapping methods.
+ *
+ * @param methods Bitmask of supported
+ * {@code WifiP2pPairingBootstrappingConfig.PAIRING_BOOTSTRAPPING_METHOD_*}
+ * @hide
+ */
+ public void setPairingBootStrappingMethods(
+ @WifiP2pPairingBootstrappingConfig.PairingBootstrappingMethod int methods) {
+ if (!Environment.isSdkAtLeastB()) {
+ throw new UnsupportedOperationException();
+ }
+ mPairingBootstrappingMethods = methods;
+ }
+
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
@@ -502,6 +593,7 @@
sbuf.append("\n wfdInfo: ").append(wfdInfo);
sbuf.append("\n vendorElements: ").append(mVendorElements);
sbuf.append("\n vendorData: ").append(mVendorData);
+ sbuf.append("\n Pairing Bootstrapping Methods: ").append(mPairingBootstrappingMethods);
return sbuf.toString();
}
@@ -531,6 +623,7 @@
mVendorElements = new ArrayList<>(source.mVendorElements);
}
mVendorData = new ArrayList<>(source.mVendorData);
+ mPairingBootstrappingMethods = source.mPairingBootstrappingMethods;
}
}
@@ -560,6 +653,7 @@
}
dest.writeTypedList(mVendorElements);
dest.writeList(mVendorData);
+ dest.writeInt(mPairingBootstrappingMethods);
}
/** Implement the Parcelable interface */
@@ -567,31 +661,33 @@
new Creator<WifiP2pDevice>() {
@Override
public WifiP2pDevice createFromParcel(Parcel in) {
- WifiP2pDevice device = new WifiP2pDevice();
- device.deviceName = in.readString();
- device.deviceAddress = in.readString();
- device.mInterfaceMacAddress = in.readParcelable(MacAddress.class.getClassLoader());
- if (in.readByte() == 1) {
- try {
- device.mIpAddress = InetAddress.getByAddress(in.createByteArray());
- } catch (UnknownHostException e) {
- e.printStackTrace();
- return new WifiP2pDevice();
+ WifiP2pDevice device = new WifiP2pDevice();
+ device.deviceName = in.readString();
+ device.deviceAddress = in.readString();
+ device.mInterfaceMacAddress =
+ in.readParcelable(MacAddress.class.getClassLoader());
+ if (in.readByte() == 1) {
+ try {
+ device.mIpAddress = InetAddress.getByAddress(in.createByteArray());
+ } catch (UnknownHostException e) {
+ e.printStackTrace();
+ return new WifiP2pDevice();
+ }
}
- }
- device.primaryDeviceType = in.readString();
- device.secondaryDeviceType = in.readString();
- device.wpsConfigMethodsSupported = in.readInt();
- device.deviceCapability = in.readInt();
- device.groupCapability = in.readInt();
- device.status = in.readInt();
- if (in.readInt() == 1) {
- device.wfdInfo = WifiP2pWfdInfo.CREATOR.createFromParcel(in);
- }
- device.mVendorElements = in.createTypedArrayList(
- ScanResult.InformationElement.CREATOR);
- device.mVendorData = ParcelUtil.readOuiKeyedDataList(in);
- return device;
+ device.primaryDeviceType = in.readString();
+ device.secondaryDeviceType = in.readString();
+ device.wpsConfigMethodsSupported = in.readInt();
+ device.deviceCapability = in.readInt();
+ device.groupCapability = in.readInt();
+ device.status = in.readInt();
+ if (in.readInt() == 1) {
+ device.wfdInfo = WifiP2pWfdInfo.CREATOR.createFromParcel(in);
+ }
+ device.mVendorElements = in.createTypedArrayList(
+ ScanResult.InformationElement.CREATOR);
+ device.mVendorData = ParcelUtil.readOuiKeyedDataList(in);
+ device.mPairingBootstrappingMethods = in.readInt();
+ return device;
}
@Override
diff --git a/framework/java/android/net/wifi/p2p/WifiP2pDirInfo.java b/framework/java/android/net/wifi/p2p/WifiP2pDirInfo.java
new file mode 100644
index 0000000..0292628
--- /dev/null
+++ b/framework/java/android/net/wifi/p2p/WifiP2pDirInfo.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.p2p;
+
+import android.annotation.FlaggedApi;
+import android.annotation.NonNull;
+import android.annotation.RequiresApi;
+import android.net.MacAddress;
+import android.os.Build;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.wifi.flags.Flags;
+
+import java.util.Arrays;
+
+/**
+ * This object contains the Device Identity Resolution (DIR) Info to check if the device is a
+ * previously paired device.
+ * The device advertises this information in Bluetooth LE advertising packets
+ * and Unsynchronized Service Discovery (USD) frames. The device receiving DIR
+ * Info uses this information to identify that the peer device is a previously paired device.
+ * For Details, refer Wi-Fi Alliance Wi-Fi Direct R2 specification section 3.8.2 Pairing Identity
+ * and section 3.9.2.3.2 Optional Advertising Data Elements.
+ */
+@RequiresApi(Build.VERSION_CODES.BAKLAVA)
+@FlaggedApi(Flags.FLAG_WIFI_DIRECT_R2)
+public final class WifiP2pDirInfo implements Parcelable {
+ /**
+ * The MAC address of the P2P device interface.
+ */
+ private MacAddress mMacAddress;
+
+ /**
+ * Random number of 8 octets.
+ */
+ private byte[] mNonce;
+
+ /**
+ * A resolvable identity value of 8 octets.
+ */
+ private byte[] mDirTag;
+
+ /**
+ * @return the MAC address of the P2P device interface.
+ */
+ @NonNull
+ public MacAddress getMacAddress() {
+ return mMacAddress;
+ }
+
+ /**
+ * Get the nonce value used to derive DIR Tag.
+ * See {@link WifiP2pDirInfo}
+ *
+ * @return A byte-array of random number of size 8 octets.
+ */
+ @NonNull
+ public byte[] getNonce() {
+ return mNonce;
+ }
+
+ /**
+ * Get the DIR Tag value.
+ * See {@link WifiP2pDirInfo}
+ *
+ * @return A byte-array of Tag value of size 8 octets.
+ */
+ @NonNull
+ public byte[] getDirTag() {
+ return mDirTag;
+ }
+
+ /**
+ * Constructor for Device Identity Resolution (DIR) Info generated based on the 128 bit Device
+ * Identity key. For details, refer Wi-Fi Alliance Wi-Fi Direct R2 specification Table 8.
+ *
+ * @param macAddress The MAC address of the P2P device interface.
+ * @param nonce Random number of 8 octets.
+ * @param dirTag Resolvable identity value of 8 octets derived based on the device MAC address,
+ * device identity key and P2P device MAC address.
+ * Tag = Truncate-64(HMAC-SHA-256(DevIk, "DIR" || P2P Device Address || Nonce))
+ *
+ */
+ public WifiP2pDirInfo(@NonNull MacAddress macAddress, @NonNull byte[] nonce,
+ @NonNull byte[] dirTag) {
+ mMacAddress = macAddress;
+ mNonce = nonce;
+ mDirTag = dirTag;
+ }
+
+ /**
+ * Generates a string of all the defined elements.
+ *
+ * @return a compiled string representing all elements
+ */
+ public String toString() {
+ StringBuilder sbuf = new StringBuilder("WifiP2pDirInfo:");
+ sbuf.append("\n Mac Address: ").append(mMacAddress);
+ sbuf.append("\n Nonce : ").append((mNonce == null)
+ ? "<null>" : Arrays.toString(mNonce));
+ sbuf.append("\n DIR Tag : ").append((mDirTag == null)
+ ? "<null>" : Arrays.toString(mDirTag));
+ return sbuf.toString();
+ }
+
+ /** Implement the Parcelable interface */
+ public int describeContents() {
+ return 0;
+ }
+
+ /** Implement the Parcelable interface */
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ mMacAddress.writeToParcel(dest, flags);
+ dest.writeByteArray(mNonce);
+ dest.writeByteArray(mDirTag);
+ }
+
+ /** Implement the Parcelable interface */
+ @NonNull
+ public static final Creator<WifiP2pDirInfo> CREATOR =
+ new Creator<WifiP2pDirInfo>() {
+ public WifiP2pDirInfo createFromParcel(Parcel in) {
+ return new WifiP2pDirInfo(MacAddress.CREATOR.createFromParcel(in),
+ in.createByteArray(), in.createByteArray());
+ }
+
+ public WifiP2pDirInfo[] newArray(int size) {
+ return new WifiP2pDirInfo[size];
+ }
+ };
+}
diff --git a/framework/java/android/net/wifi/p2p/WifiP2pGroup.java b/framework/java/android/net/wifi/p2p/WifiP2pGroup.java
index 1edc97b..43dc26f 100644
--- a/framework/java/android/net/wifi/p2p/WifiP2pGroup.java
+++ b/framework/java/android/net/wifi/p2p/WifiP2pGroup.java
@@ -17,6 +17,7 @@
package android.net.wifi.p2p;
import android.annotation.FlaggedApi;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
@@ -24,6 +25,7 @@
import android.net.MacAddress;
import android.net.wifi.OuiKeyedData;
import android.net.wifi.ParcelUtil;
+import android.net.wifi.util.Environment;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
@@ -34,6 +36,8 @@
import com.android.modules.utils.build.SdkLevel;
import com.android.wifi.flags.Flags;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.util.ArrayList;
@@ -75,6 +79,41 @@
public static final int NETWORK_ID_PERSISTENT = -2;
/**
+ * The definition of security type unknown. It is set when framework fails to derive the
+ * security type from the authentication key management provided by wpa_supplicant.
+ */
+ @FlaggedApi(Flags.FLAG_WIFI_DIRECT_R2)
+ public static final int SECURITY_TYPE_UNKNOWN = -1;
+
+ /**
+ * The definition of security type WPA2-PSK.
+ */
+ @FlaggedApi(Flags.FLAG_WIFI_DIRECT_R2)
+ public static final int SECURITY_TYPE_WPA2_PSK = 0;
+
+ /**
+ * The definition of security type WPA3-Compatibility Mode.
+ */
+ @FlaggedApi(Flags.FLAG_WIFI_DIRECT_R2)
+ public static final int SECURITY_TYPE_WPA3_COMPATIBILITY = 1;
+
+ /**
+ * The definition of security type WPA3-SAE.
+ */
+ @FlaggedApi(Flags.FLAG_WIFI_DIRECT_R2)
+ public static final int SECURITY_TYPE_WPA3_SAE = 2;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = { "SECURITY_TYPE_" }, value = {
+ SECURITY_TYPE_UNKNOWN,
+ SECURITY_TYPE_WPA2_PSK,
+ SECURITY_TYPE_WPA3_COMPATIBILITY,
+ SECURITY_TYPE_WPA3_SAE,
+ })
+ public @interface SecurityType {}
+
+ /**
* Group owner P2P interface MAC address.
* @hide
*/
@@ -96,6 +135,10 @@
/** The passphrase used for WPA2-PSK */
private String mPassphrase;
+ /** The security type of the group */
+ @SecurityType
+ private int mSecurityType;
+
private String mInterface;
/** The network ID in wpa_supplicant */
@@ -363,6 +406,30 @@
return mPassphrase;
}
+ /**
+ * Set the security type of the group.
+ *
+ * @param securityType One of the {@code SECURITY_TYPE_*}.
+ * @hide
+ */
+ public void setSecurityType(@SecurityType int securityType) {
+ mSecurityType = securityType;
+ }
+
+ /**
+ * Get the security type of the group.
+ *
+ * @return One of the {@code SECURITY_TYPE_*}.
+ */
+ @RequiresApi(Build.VERSION_CODES.BAKLAVA)
+ @FlaggedApi(Flags.FLAG_WIFI_DIRECT_R2)
+ public @SecurityType int getSecurityType() {
+ if (!Environment.isSdkAtLeastB()) {
+ throw new UnsupportedOperationException();
+ }
+ return mSecurityType;
+ }
+
/** @hide */
@UnsupportedAppUsage
public void setInterface(String intf) {
@@ -433,6 +500,31 @@
mVendorData = new ArrayList<>(vendorData);
}
+ /**
+ * Returns the BSSID, if this device is the group owner of the P2P group supporting Wi-Fi
+ * Direct R2 protocol.
+ * <p>
+ * The interface address of a Wi-Fi Direct R2 supported device is randomized. So for every
+ * group owner session a randomized interface address will be returned.
+ * <p>
+ * The BSSID returned will be {@code null}, if this device is a client device or a group owner
+ * which doesn't support Wi-Fi Direct R2 protocol.
+ * @return the BSSID.
+ */
+ @RequiresApi(Build.VERSION_CODES.BAKLAVA)
+ @FlaggedApi(Flags.FLAG_WIFI_DIRECT_R2)
+ @Nullable
+ public MacAddress getGroupOwnerBssid() {
+ if (!Environment.isSdkAtLeastB()) {
+ throw new UnsupportedOperationException();
+ }
+ if (isGroupOwner() && getSecurityType() == SECURITY_TYPE_WPA3_SAE
+ && interfaceAddress != null) {
+ return MacAddress.fromBytes(interfaceAddress);
+ }
+ return null;
+ }
+
public String toString() {
StringBuffer sbuf = new StringBuffer();
sbuf.append("network: ").append(mNetworkName);
@@ -443,6 +535,8 @@
}
sbuf.append("\n interface: ").append(mInterface);
sbuf.append("\n networkId: ").append(mNetId);
+ sbuf.append("\n securityType: ").append(mSecurityType);
+
sbuf.append("\n frequency: ").append(mFrequency);
sbuf.append("\n vendorData: ").append(mVendorData);
return sbuf.toString();
@@ -463,6 +557,9 @@
mPassphrase = source.getPassphrase();
mInterface = source.getInterface();
mNetId = source.getNetworkId();
+ if (Environment.isSdkAtLeastB() && Flags.wifiDirectR2()) {
+ mSecurityType = source.getSecurityType();
+ }
mFrequency = source.getFrequency();
if (SdkLevel.isAtLeastV()) {
mVendorData = new ArrayList<>(source.getVendorData());
@@ -482,6 +579,9 @@
dest.writeString(mPassphrase);
dest.writeString(mInterface);
dest.writeInt(mNetId);
+ if (Environment.isSdkAtLeastB() && Flags.wifiDirectR2()) {
+ dest.writeInt(mSecurityType);
+ }
dest.writeInt(mFrequency);
if (SdkLevel.isAtLeastV()) {
dest.writeList(mVendorData);
@@ -490,28 +590,33 @@
/** Implement the Parcelable interface */
public static final @android.annotation.NonNull Creator<WifiP2pGroup> CREATOR =
- new Creator<WifiP2pGroup>() {
- public WifiP2pGroup createFromParcel(Parcel in) {
- WifiP2pGroup group = new WifiP2pGroup();
- group.setNetworkName(in.readString());
- group.setOwner((WifiP2pDevice)in.readParcelable(null));
- group.setIsGroupOwner(in.readByte() == (byte)1);
- int clientCount = in.readInt();
- for (int i=0; i<clientCount; i++) {
- group.addClient((WifiP2pDevice) in.readParcelable(null));
+ new Creator<WifiP2pGroup>() {
+ public WifiP2pGroup createFromParcel(Parcel in) {
+ WifiP2pGroup group = new WifiP2pGroup();
+ group.setNetworkName(in.readString());
+ group.setOwner((WifiP2pDevice) in.readParcelable(
+ WifiP2pDevice.class.getClassLoader()));
+ group.setIsGroupOwner(in.readByte() == (byte) 1);
+ int clientCount = in.readInt();
+ for (int i = 0; i < clientCount; i++) {
+ group.addClient((WifiP2pDevice) in.readParcelable(
+ WifiP2pDevice.class.getClassLoader()));
+ }
+ group.setPassphrase(in.readString());
+ group.setInterface(in.readString());
+ group.setNetworkId(in.readInt());
+ if (Environment.isSdkAtLeastB() && Flags.wifiDirectR2()) {
+ group.setSecurityType(in.readInt());
+ }
+ group.setFrequency(in.readInt());
+ if (SdkLevel.isAtLeastV()) {
+ group.setVendorData(ParcelUtil.readOuiKeyedDataList(in));
+ }
+ return group;
}
- group.setPassphrase(in.readString());
- group.setInterface(in.readString());
- group.setNetworkId(in.readInt());
- group.setFrequency(in.readInt());
- if (SdkLevel.isAtLeastV()) {
- group.setVendorData(ParcelUtil.readOuiKeyedDataList(in));
- }
- return group;
- }
- public WifiP2pGroup[] newArray(int size) {
- return new WifiP2pGroup[size];
- }
+ public WifiP2pGroup[] newArray(int size) {
+ return new WifiP2pGroup[size];
+ }
};
}
diff --git a/framework/java/android/net/wifi/p2p/WifiP2pManager.java b/framework/java/android/net/wifi/p2p/WifiP2pManager.java
index 0969060..717bde6 100644
--- a/framework/java/android/net/wifi/p2p/WifiP2pManager.java
+++ b/framework/java/android/net/wifi/p2p/WifiP2pManager.java
@@ -41,6 +41,9 @@
import android.net.wifi.p2p.nsd.WifiP2pServiceResponse;
import android.net.wifi.p2p.nsd.WifiP2pUpnpServiceInfo;
import android.net.wifi.p2p.nsd.WifiP2pUpnpServiceResponse;
+import android.net.wifi.p2p.nsd.WifiP2pUsdBasedServiceConfig;
+import android.net.wifi.p2p.nsd.WifiP2pUsdBasedServiceResponse;
+import android.net.wifi.util.Environment;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
@@ -48,6 +51,7 @@
import android.os.Looper;
import android.os.Message;
import android.os.Messenger;
+import android.os.OutcomeReceiver;
import android.os.RemoteException;
import android.text.TextUtils;
import android.util.CloseGuard;
@@ -170,6 +174,13 @@
public static final long FEATURE_GROUP_CLIENT_REMOVAL = 1L << 2;
/** @hide */
public static final long FEATURE_GROUP_OWNER_IPV6_LINK_LOCAL_ADDRESS_PROVIDED = 1L << 3;
+ /** @hide */
+ public static final long FEATURE_WIFI_DIRECT_R2 = 1L << 4; // Wi-Fi Direct R2 Support
+ /**
+ * Wi-Fi Direct R1/R2 Compatibility Mode support.
+ * @hide
+ */
+ public static final long FEATURE_PCC_MODE_ALLOW_LEGACY_AND_R2_CONNECTION = 1L << 5;
/**
* Extra for transporting a WifiP2pConfig
@@ -183,6 +194,23 @@
*/
public static final String EXTRA_PARAM_KEY_SERVICE_INFO =
"android.net.wifi.p2p.EXTRA_PARAM_KEY_SERVICE_INFO";
+
+ /**
+ * Extra for transporting Un-synchronized service discovery (USD) based service discovery
+ * configuration.
+ * @hide
+ */
+ public static final String EXTRA_PARAM_KEY_USD_BASED_SERVICE_DISCOVERY_CONFIG =
+ "android.net.wifi.p2p.EXTRA_PARAM_KEY_USD_BASED_SERVICE_DISCOVERY_CONFIG";
+
+ /**
+ * Extra for transporting Un-synchronized service discovery (USD) based local service
+ * advertisement configuration.
+ * @hide
+ */
+ public static final String EXTRA_PARAM_KEY_USD_BASED_LOCAL_SERVICE_ADVERTISEMENT_CONFIG =
+ "android.net.wifi.p2p.EXTRA_PARAM_KEY_USD_BASED_LOCAL_SERVICE_ADVERTISEMENT_CONFIG";
+
/**
* Extra for transporting a peer discovery frequency.
* @hide
@@ -590,6 +618,25 @@
*/
private static final int WIFI_P2P_VENDOR_ELEMENTS_MAXIMUM_LENGTH = 512;
+ /**
+ * Run USD based P2P service discovery with a service discovery configuration.
+ * @hide
+ */
+ public static final int WIFI_P2P_USD_BASED_SERVICE_DISCOVERY = 1;
+
+ /**
+ * Add P2P local service with advertisement configuration.
+ * @hide
+ */
+ public static final int WIFI_P2P_USD_BASED_ADD_LOCAL_SERVICE = 1;
+
+ /**
+ * Extra for transporting DIR Information.
+ * @hide
+ */
+ public static final String EXTRA_PARAM_KEY_DIR_INFO =
+ "android.net.wifi.p2p.EXTRA_PARAM_KEY_DIR_INFO";
+
private Context mContext;
IWifiP2pManager mService;
@@ -865,6 +912,20 @@
/** @hide */
public static final int RESPONSE_GET_LISTEN_STATE = BASE + 118;
+ /** @hide */
+ public static final int GET_DIR_INFO = BASE + 119;
+ /** @hide */
+ public static final int GET_DIR_INFO_FAILED = BASE + 120;
+ /** @hide */
+ public static final int RESPONSE_GET_DIR_INFO = BASE + 121;
+
+ /** @hide */
+ public static final int VALIDATE_DIR_INFO = BASE + 122;
+ /** @hide */
+ public static final int VALIDATE_DIR_INFO_FAILED = BASE + 123;
+ /** @hide */
+ public static final int RESPONSE_VALIDATE_DIR_INFO = BASE + 124;
+
private static final SparseArray<IWifiP2pListener> sWifiP2pListenerMap = new SparseArray<>();
/**
* Create a new WifiP2pManager instance. Applications use
@@ -906,6 +967,14 @@
*/
public static final int NO_SERVICE_REQUESTS = 3;
+ /**
+ * Passed with {@link ActionListener#onFailure}.
+ * Indicates that the operation failed due to calling app doesn't have permission to call the
+ * API.
+ */
+ @FlaggedApi(Flags.FLAG_WIFI_DIRECT_R2)
+ public static final int NO_PERMISSION = 4;
+
/** Interface for callback invocation when framework channel is lost */
public interface ChannelListener {
/**
@@ -971,6 +1040,15 @@
*/
public void onServiceAvailable(int protocolType,
byte[] responseData, WifiP2pDevice srcDevice);
+ /**
+ * The requested USD based service response is available.
+ * @param srcDevice source device.
+ * @param usdResponseData {@link WifiP2pUsdBasedServiceResponse}.
+ */
+ @FlaggedApi(Flags.FLAG_WIFI_DIRECT_R2)
+ default void onUsdBasedServiceAvailable(@NonNull WifiP2pDevice srcDevice,
+ @NonNull WifiP2pUsdBasedServiceResponse usdResponseData) {
+ }
}
/**
@@ -1902,6 +1980,31 @@
.onPinGenerated(deviceAddress, pin);
}
break;
+ case RESPONSE_GET_DIR_INFO:
+ if (listener != null) {
+ if (Flags.wifiDirectR2()) {
+ ((WifiP2pDirInfoListener) listener)
+ .onDirInfoReceived((WifiP2pDirInfo) message.obj);
+ }
+ }
+ break;
+ case GET_DIR_INFO_FAILED:
+ if (listener != null) {
+ ((WifiP2pDirInfoListener) listener)
+ .onFailure(message.arg1);
+ }
+ break;
+ case RESPONSE_VALIDATE_DIR_INFO:
+ if (listener != null) {
+ ((WifiP2pDirInfoValidationListener) listener)
+ .onDirInfoValidation(message.arg1 == 1);
+ }
+ break;
+ case VALIDATE_DIR_INFO_FAILED:
+ if (listener != null) {
+ ((WifiP2pDirInfoValidationListener) listener)
+ .onFailure(message.arg1);
+ }
default:
Log.d(TAG, "Ignored " + message);
break;
@@ -2625,6 +2728,60 @@
}
/**
+ * Start a service discovery advertisement using Un-synchronized service discovery (USD).
+ * Once {@link #startUsdBasedLocalServiceAdvertisement(Channel, WifiP2pServiceInfo,
+ * WifiP2pUsdBasedLocalServiceAdvertisementConfig, ActionListener)} is called, the device will
+ * go to the channel frequency requested via
+ * {@link WifiP2pUsdBasedLocalServiceAdvertisementConfig} and responds to a service discovery
+ * request from a peer.
+ *
+ * <p> The service information is set through
+ * {@link WifiP2pServiceInfo#WifiP2pServiceInfo(WifiP2pUsdBasedServiceConfig)}
+ *
+ * <p> The function call immediately returns after sending a request to start the service
+ * advertisement to the framework. The application is notified of a success or failure to
+ * start service advertisement through listener callbacks {@link ActionListener#onSuccess} or
+ * {@link ActionListener#onFailure}.
+ *
+ * <p>The service information can be cleared with calls to
+ * {@link #removeLocalService} or {@link #clearLocalServices}.
+ * <p>
+ * The application must have {@link android.Manifest.permission#NEARBY_WIFI_DEVICES} with
+ * android:usesPermissionFlags="neverForLocation". If the application does not declare
+ * android:usesPermissionFlags="neverForLocation", then it must also have
+ * {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
+ *
+ * @param channel is the channel created at {@link #initialize}
+ * @param servInfo is a local service information.
+ * @param config is the configuration for this service discovery advertisement.
+ * @param listener for callbacks on success or failure. Can be null.
+ */
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.NEARBY_WIFI_DEVICES,
+ android.Manifest.permission.ACCESS_FINE_LOCATION
+ }, conditional = true)
+ @RequiresApi(Build.VERSION_CODES.BAKLAVA)
+ @FlaggedApi(Flags.FLAG_WIFI_DIRECT_R2)
+ @SuppressLint("ExecutorRegistration") // initialize creates a channel and requires a Looper
+ public void startUsdBasedLocalServiceAdvertisement(@NonNull Channel channel,
+ @NonNull WifiP2pServiceInfo servInfo,
+ @NonNull WifiP2pUsdBasedLocalServiceAdvertisementConfig config,
+ @Nullable ActionListener listener) {
+ if (!Environment.isSdkAtLeastB()) {
+ throw new UnsupportedOperationException();
+ }
+ checkChannel(channel);
+ Objects.requireNonNull(servInfo, "service info cannot be null");
+ Objects.requireNonNull(config, "Advertisement config cannot be null");
+ Bundle extras = prepareExtrasBundle(channel);
+ extras.putParcelable(EXTRA_PARAM_KEY_SERVICE_INFO, servInfo);
+ extras.putParcelable(EXTRA_PARAM_KEY_USD_BASED_LOCAL_SERVICE_ADVERTISEMENT_CONFIG, config);
+ channel.mAsyncChannel.sendMessage(prepareMessage(ADD_LOCAL_SERVICE,
+ WIFI_P2P_USD_BASED_ADD_LOCAL_SERVICE,
+ channel.putListener(listener), extras, channel.mContext));
+ }
+
+ /**
* Remove a registered local service added with {@link #addLocalService}
*
* <p> The function call immediately returns after sending a request to remove a
@@ -2749,6 +2906,61 @@
}
/**
+ * Initiate Un-synchronized service discovery (USD) based service discovery. A discovery
+ * process involves scanning for requested services for the purpose of establishing a
+ * connection to a peer that supports an available service using USD protocol.
+ *
+ * This method accepts a {@link WifiP2pUsdBasedServiceDiscoveryConfig} object specifying the
+ * desired parameters for the service discovery. The configuration object allows to specify
+ * either a band or frequency list to scan for service.
+ *
+ * <p> The function call immediately returns after sending a request to start service
+ * discovery to the framework. The application is notified of a success or failure to initiate
+ * discovery through listener callbacks {@link ActionListener#onSuccess} or
+ * {@link ActionListener#onFailure}.
+ *
+ * <p> The USD based services to be discovered are specified with calls to
+ * {@link #addServiceRequest} with the service request information set through
+ * {@link WifiP2pServiceRequest#WifiP2pServiceRequest(WifiP2pUsdBasedServiceConfig)}
+ *
+ * <p>The application is notified of the response against the service discovery request
+ * via {@link ServiceResponseListener#onUsdBasedServiceAvailable(WifiP2pDevice,
+ * WifiP2pUsdBasedServiceResponse)} listener callback registered by
+ * {@link #setServiceResponseListener(Channel, ServiceResponseListener)} .
+ *
+ * <p>
+ * The application must have {@link android.Manifest.permission#NEARBY_WIFI_DEVICES} with
+ * android:usesPermissionFlags="neverForLocation". If the application does not declare
+ * android:usesPermissionFlags="neverForLocation", then it must also have
+ * {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
+ *
+ * @param channel is the channel created at {@link #initialize}
+ * @param config is the configuration for this USD based service discovery
+ * @param listener for callbacks on success or failure. Can be null.
+ */
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.NEARBY_WIFI_DEVICES,
+ android.Manifest.permission.ACCESS_FINE_LOCATION
+ }, conditional = true)
+ @RequiresApi(Build.VERSION_CODES.BAKLAVA)
+ @FlaggedApi(Flags.FLAG_WIFI_DIRECT_R2)
+ @SuppressLint("ExecutorRegistration") // initialize creates a channel and requires a Looper
+ public void discoverUsdBasedServices(@NonNull Channel channel,
+ @NonNull WifiP2pUsdBasedServiceDiscoveryConfig config,
+ @Nullable ActionListener listener) {
+ if (!Environment.isSdkAtLeastB()) {
+ throw new UnsupportedOperationException();
+ }
+ checkChannel(channel);
+ Objects.requireNonNull(config, "Service discovery config cannot be null");
+ Bundle extras = prepareExtrasBundle(channel);
+ extras.putParcelable(EXTRA_PARAM_KEY_USD_BASED_SERVICE_DISCOVERY_CONFIG, config);
+ channel.mAsyncChannel.sendMessage(prepareMessage(DISCOVER_SERVICES,
+ WIFI_P2P_USD_BASED_SERVICE_DISCOVERY,
+ channel.putListener(listener), extras, channel.mContext));
+ }
+
+ /**
* Add a service discovery request.
*
* <p> The function call immediately returns after sending a request to add service
@@ -3205,6 +3417,32 @@
}
/**
+ * Check if this device supports Wi-Fi Direct R2 (P2P2).
+ *
+ * @return true if this device supports Wi-Fi Alliance Wi-Fi Direct R2 (Support for P2P2 IE and
+ * establishing connection by using the P2P pairing protocol), false otherwise.
+ * For more details, visit <a href="https://www.wi-fi.org/">https://www.wi-fi.org/</a> and
+ * search for "Wi-Fi Direct" .
+ */
+ @FlaggedApi(Flags.FLAG_WIFI_DIRECT_R2)
+ public boolean isWiFiDirectR2Supported() {
+ return isFeatureSupported(FEATURE_WIFI_DIRECT_R2);
+ }
+
+ /**
+ * Check if this device supports P2P Connection Compatibility Mode(R1/R2 compatibility mode).
+ *
+ * @return true if this device supports hosting an autonomous Group Owner which allows
+ * legacy P2P clients and R2 clients to join the group in PCC Mode and also supports connecting
+ * to a Group Owner either using legacy security mode (WPA2-PSK) or R2 mandated security
+ * mode(WPA3-SAE) in PCC Mode.
+ */
+ @FlaggedApi(Flags.FLAG_WIFI_DIRECT_R2)
+ public boolean isPccModeSupported() {
+ return isFeatureSupported(FEATURE_PCC_MODE_ALLOW_LEGACY_AND_R2_CONNECTION);
+ }
+
+ /**
* Get a handover request message for use in WFA NFC Handover transfer.
* @hide
*/
@@ -3652,4 +3890,186 @@
public static int getP2pMaxAllowedVendorElementsLengthBytes() {
return WIFI_P2P_VENDOR_ELEMENTS_MAXIMUM_LENGTH;
}
+
+ private static Exception reasonCodeToException(int reason) {
+ if (reason == ERROR) {
+ return new IllegalStateException("Internal error");
+ } else if (reason == BUSY) {
+ return new IllegalStateException("Framework is busy");
+ } else if (Flags.wifiDirectR2() && reason == NO_PERMISSION) {
+ return new SecurityException("Application doesn't have required permission");
+ } else {
+ return new IllegalStateException();
+ }
+ }
+
+ /**
+ * Interface for callback invocation in response to {@link #requestDirInfo}.
+ * @hide
+ */
+ public interface WifiP2pDirInfoListener {
+ /**
+ * The callback to indicate that the system searched for DIR information.
+ * @param dirInfo {@link WifiP2pDirInfo} if exists, otherwise null.
+ */
+ void onDirInfoReceived(@Nullable WifiP2pDirInfo dirInfo);
+
+ /**
+ * The operation failed.
+ * @param reason The reason for failure.
+ */
+ void onFailure(int reason);
+ }
+
+ /**
+ * Get the Device Identity Resolution (DIR) Information.
+ * See {@link WifiP2pDirInfo} for details
+ *
+ * Note: The results callback returns null if the device doesn't have any persistent group
+ * with device identity key information.
+ *
+ * <p>
+ * Use {@link #isWiFiDirectR2Supported()} to determine whether the device supports
+ * this feature. If {@link #isWiFiDirectR2Supported()} return {@code false} then
+ * this method will throw {@link UnsupportedOperationException}.
+ * <p>
+ * The application must have {@link android.Manifest.permission#NEARBY_WIFI_DEVICES} with
+ * android:usesPermissionFlags="neverForLocation". If the application does not declare
+ * android:usesPermissionFlags="neverForLocation", then it must also have
+ * {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
+ *
+ * @param c It is the channel created at {@link #initialize}.
+ * @param executor The executor on which callback will be invoked.
+ * @param callback An OutcomeReceiver callback for receiving {@link WifiP2pDirInfo} via
+ * {@link OutcomeReceiver#onResult(Object)}. This callback will return
+ * null when DIR info doesn't exist.
+ * When this API call fails due to permission issues, state machine
+ * is busy etc., {@link OutcomeReceiver#onError(Throwable)} is called.
+ */
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.NEARBY_WIFI_DEVICES,
+ android.Manifest.permission.ACCESS_FINE_LOCATION
+ }, conditional = true)
+ @RequiresApi(Build.VERSION_CODES.BAKLAVA)
+ @FlaggedApi(Flags.FLAG_WIFI_DIRECT_R2)
+ public void requestDirInfo(@NonNull Channel c, @NonNull @CallbackExecutor Executor executor,
+ @NonNull OutcomeReceiver<WifiP2pDirInfo, Exception> callback) {
+ if (!Environment.isSdkAtLeastB()) {
+ throw new UnsupportedOperationException();
+ }
+ if (!isWiFiDirectR2Supported()) {
+ throw new UnsupportedOperationException();
+ }
+ Objects.requireNonNull(c, "channel cannot be null and needs to be initialized)");
+ Objects.requireNonNull(executor, "executor cannot be null");
+ Objects.requireNonNull(callback, "callback cannot be null");
+ Bundle extras = prepareExtrasBundle(c);
+ c.mAsyncChannel.sendMessage(prepareMessage(GET_DIR_INFO, 0,
+ c.putListener(new WifiP2pDirInfoListener() {
+ @Override
+ public void onDirInfoReceived(WifiP2pDirInfo result) {
+ Binder.clearCallingIdentity();
+ executor.execute(() -> {
+ callback.onResult(result);
+ });
+ }
+
+ @Override
+ public void onFailure(int reason) {
+ Binder.clearCallingIdentity();
+ executor.execute(() -> {
+ callback.onError(reasonCodeToException(reason));
+ });
+ }
+ }), extras, c.mContext));
+ }
+
+ /**
+ * Interface for callback invocation when the received DIR information is validated
+ * in response to {@link #validateDirInfo}.
+ * @hide
+ */
+ public interface WifiP2pDirInfoValidationListener {
+ /**
+ * The requested DIR information is validated.
+ * @param result True if a match is found, false otherwise.
+ */
+ void onDirInfoValidation(boolean result);
+
+ /**
+ * The operation failed.
+ * @param reason The reason for failure.
+ */
+ void onFailure(int reason);
+ }
+
+ /**
+ * Validate the Device Identity Resolution (DIR) Information of a P2P device.
+ * See {@link WifiP2pDirInfo} for details.
+ * Framework takes the {@link WifiP2pDirInfo} and derives a set of Tag values based on
+ * the cached Device Identity Keys (DevIK) of all paired peers saved in the device.
+ * If a derived Tag value matches the Tag value received in the {@link WifiP2pDirInfo}, the
+ * device is identified as a paired peer and returns true.
+ *
+ * <p>
+ * Use {@link #isWiFiDirectR2Supported()} to determine whether the device supports
+ * this feature. If {@link #isWiFiDirectR2Supported()} return {@code false} then
+ * this method will throw {@link UnsupportedOperationException}.
+ * <p>
+ * The application must have {@link android.Manifest.permission#NEARBY_WIFI_DEVICES} with
+ * android:usesPermissionFlags="neverForLocation". If the application does not declare
+ * android:usesPermissionFlags="neverForLocation", then it must also have
+ * {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
+ *
+ * @param c It is the channel created at {@link #initialize}.
+ * @param dirInfo {@link WifiP2pDirInfo} to validate.
+ * @param executor The executor on which callback will be invoked.
+ * @param callback An OutcomeReceiver callback for receiving the result via
+ * {@link OutcomeReceiver#onResult(Object)} indicating whether the DIR
+ * info of P2P device is of a paired device. {code true} for paired,
+ * {@code false} for not paired.
+ * When this API call fails due to permission issues, state machine
+ * is busy etc., {@link OutcomeReceiver#onError(Throwable)} is called.
+ */
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.NEARBY_WIFI_DEVICES,
+ android.Manifest.permission.ACCESS_FINE_LOCATION
+ }, conditional = true)
+ @RequiresApi(Build.VERSION_CODES.BAKLAVA)
+ @FlaggedApi(Flags.FLAG_WIFI_DIRECT_R2)
+ public void validateDirInfo(@NonNull Channel c, @NonNull WifiP2pDirInfo dirInfo,
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull OutcomeReceiver<Boolean, Exception> callback) {
+ if (!Environment.isSdkAtLeastB()) {
+ throw new UnsupportedOperationException();
+ }
+ if (!isWiFiDirectR2Supported()) {
+ throw new UnsupportedOperationException();
+ }
+ Objects.requireNonNull(c, "channel cannot be null and needs to be initialized)");
+ Objects.requireNonNull(dirInfo, "dirInfo cannot be null");
+ Objects.requireNonNull(executor, "executor cannot be null");
+ Objects.requireNonNull(callback, "resultsCallback cannot be null");
+ Bundle extras = prepareExtrasBundle(c);
+
+ extras.putParcelable(EXTRA_PARAM_KEY_DIR_INFO, dirInfo);
+ c.mAsyncChannel.sendMessage(prepareMessage(VALIDATE_DIR_INFO, 0,
+ c.putListener(new WifiP2pDirInfoValidationListener() {
+ @Override
+ public void onDirInfoValidation(boolean result) {
+ Binder.clearCallingIdentity();
+ executor.execute(() -> {
+ callback.onResult(result);
+ });
+ }
+
+ @Override
+ public void onFailure(int reason) {
+ Binder.clearCallingIdentity();
+ executor.execute(() -> {
+ callback.onError(reasonCodeToException(reason));
+ });
+ }
+ }), extras, c.mContext));
+ }
}
diff --git a/framework/java/android/net/wifi/p2p/WifiP2pPairingBootstrappingConfig.java b/framework/java/android/net/wifi/p2p/WifiP2pPairingBootstrappingConfig.java
new file mode 100644
index 0000000..4579cd2
--- /dev/null
+++ b/framework/java/android/net/wifi/p2p/WifiP2pPairingBootstrappingConfig.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.p2p;
+
+import android.annotation.FlaggedApi;
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Build;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import androidx.annotation.RequiresApi;
+
+import com.android.wifi.flags.Flags;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * A class representing Wi-Fi Direct pairing bootstrapping config
+ *
+ * @see android.net.wifi.p2p.WifiP2pConfig
+ */
+@RequiresApi(Build.VERSION_CODES.BAKLAVA)
+@FlaggedApi(Flags.FLAG_WIFI_DIRECT_R2)
+public final class WifiP2pPairingBootstrappingConfig implements Parcelable {
+
+ /**
+ * Pairing bootstrapping method opportunistic
+ */
+ public static final int PAIRING_BOOTSTRAPPING_METHOD_OPPORTUNISTIC = 1 << 0;
+
+ /**
+ * Pairing bootstrapping method display pin-code - The pin-code is displayed on the connection
+ * initiating device. The user enters the displayed pin-code on the other device.
+ */
+ public static final int PAIRING_BOOTSTRAPPING_METHOD_DISPLAY_PINCODE = 1 << 1;
+
+ /**
+ * Pairing bootstrapping method display passphrase - The passphrase is displayed on the
+ * connection initiating device. The user enters the displayed passphrase on the other device.
+ */
+ public static final int PAIRING_BOOTSTRAPPING_METHOD_DISPLAY_PASSPHRASE = 1 << 2;
+
+ /**
+ * Pairing bootstrapping method keypad pin-code - The pin-code is displayed on the other
+ * device. The user enters the displayed pin-code on the connection initiating device.
+ */
+ public static final int PAIRING_BOOTSTRAPPING_METHOD_KEYPAD_PINCODE = 1 << 3;
+
+ /**
+ * Pairing bootstrapping method keypad passphrase - The passphrase is displayed on the other
+ * device. The user enters the displayed passphrase on the connection initiating device.
+ */
+ public static final int PAIRING_BOOTSTRAPPING_METHOD_KEYPAD_PASSPHRASE = 1 << 4;
+
+ /**
+ * Pairing bootstrapping done out of band (For example: Over Bluetooth LE.
+ * Refer Wi-Fi Alliance Wi-Fi Direct R2 specification Section 3.9 for the details).
+ */
+ public static final int PAIRING_BOOTSTRAPPING_METHOD_OUT_OF_BAND = 1 << 5;
+
+
+ /** @hide */
+ @IntDef(flag = true, prefix = {"PAIRING_BOOTSTRAPPING_METHOD_"}, value = {
+ PAIRING_BOOTSTRAPPING_METHOD_OPPORTUNISTIC,
+ PAIRING_BOOTSTRAPPING_METHOD_DISPLAY_PINCODE,
+ PAIRING_BOOTSTRAPPING_METHOD_DISPLAY_PASSPHRASE,
+ PAIRING_BOOTSTRAPPING_METHOD_KEYPAD_PINCODE,
+ PAIRING_BOOTSTRAPPING_METHOD_KEYPAD_PASSPHRASE,
+ PAIRING_BOOTSTRAPPING_METHOD_OUT_OF_BAND,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface PairingBootstrappingMethod {
+ }
+ /** One of the {@code PAIRING_BOOTSTRAPPING_METHOD_*}. */
+ private int mPairingBootstrappingMethod;
+
+ /**
+ * Password for pairing setup, if |pairingBootstrappingMethod| uses one of the
+ * |PAIRING_BOOTSTRAPPING_METHOD_*| methods other than
+ * PAIRING_BOOTSTRAPPING_METHOD_OPPORTUNISTIC, null otherwise.
+ */
+ @Nullable private String mPassword;
+
+ /**
+ * Constructor for a WifiP2pPairingBootstrappingConfig.
+ */
+ public WifiP2pPairingBootstrappingConfig(
+ @WifiP2pPairingBootstrappingConfig.PairingBootstrappingMethod int method,
+ @Nullable String password) {
+ mPairingBootstrappingMethod = method;
+ mPassword = password;
+ }
+
+ /**
+ * Generates a string of all the defined elements.
+ *
+ * @return a compiled string representing all elements
+ */
+ public String toString() {
+ StringBuilder sbuf = new StringBuilder("WifiP2pPairingBootstrappingConfig:");
+ sbuf.append("\n BootstrappingMethod: ").append(mPairingBootstrappingMethod);
+ return sbuf.toString();
+ }
+
+ /** Implement the Parcelable interface */
+ public int describeContents() {
+ return 0;
+ }
+
+ /**
+ * Copy Constructor
+ *
+ * @hide
+ */
+ public WifiP2pPairingBootstrappingConfig(@NonNull WifiP2pPairingBootstrappingConfig source) {
+ if (source != null) {
+ mPairingBootstrappingMethod = source.mPairingBootstrappingMethod;
+ mPassword = source.mPassword;
+ }
+ }
+
+ /** Implement the Parcelable interface */
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeInt(mPairingBootstrappingMethod);
+ dest.writeString(mPassword);
+ }
+
+ /** Implement the Parcelable interface */
+ public static final @android.annotation.NonNull
+ Creator<WifiP2pPairingBootstrappingConfig> CREATOR =
+ new Creator<WifiP2pPairingBootstrappingConfig>() {
+ public WifiP2pPairingBootstrappingConfig createFromParcel(Parcel in) {
+ int pairingBootstrappingMethod = in.readInt();
+ String password = in.readString();
+ WifiP2pPairingBootstrappingConfig config =
+ new WifiP2pPairingBootstrappingConfig(
+ pairingBootstrappingMethod, password);
+ return config;
+ }
+
+ public WifiP2pPairingBootstrappingConfig[] newArray(int size) {
+ return new WifiP2pPairingBootstrappingConfig[size];
+ }
+ };
+}
diff --git a/framework/java/android/net/wifi/p2p/WifiP2pUsdBasedLocalServiceAdvertisementConfig.java b/framework/java/android/net/wifi/p2p/WifiP2pUsdBasedLocalServiceAdvertisementConfig.java
new file mode 100644
index 0000000..4d5a369
--- /dev/null
+++ b/framework/java/android/net/wifi/p2p/WifiP2pUsdBasedLocalServiceAdvertisementConfig.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.p2p;
+
+import android.annotation.FlaggedApi;
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.annotation.RequiresApi;
+import android.os.Build;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.wifi.flags.Flags;
+
+/**
+ * A class representing a Wi-Fi P2P USD based service advertisement configuration for advertising
+ * the services.
+ */
+@RequiresApi(Build.VERSION_CODES.BAKLAVA)
+@FlaggedApi(Flags.FLAG_WIFI_DIRECT_R2)
+public final class WifiP2pUsdBasedLocalServiceAdvertisementConfig implements Parcelable {
+ /**
+ * Default channel frequency for USD based service discovery.
+ */
+ private static final int USD_DEFAULT_DISCOVERY_CHANNEL_MHZ = 2437;
+
+ /**
+ * Frequency on which the service needs to be advertised.
+ */
+ private int mFrequencyMhz;
+
+ private WifiP2pUsdBasedLocalServiceAdvertisementConfig(int frequencyMhz) {
+ mFrequencyMhz = frequencyMhz;
+ }
+
+ /**
+ * Get the frequency on which the service is advertised.
+ */
+ @IntRange(from = 0)
+ public int getFrequencyMhz() {
+ return mFrequencyMhz;
+ }
+
+ /**
+ * Generates a string of all the defined elements.
+ *
+ * @return a compiled string representing all elements
+ */
+ public String toString() {
+ StringBuilder sbuf = new StringBuilder("WifiP2pUsdBasedLocalServiceAdvertisementConfig:");
+ sbuf.append("\n Frequency: ").append(mFrequencyMhz);
+ return sbuf.toString();
+ }
+
+ /** Implement the Parcelable interface */
+ public int describeContents() {
+ return 0;
+ }
+
+ /** Implement the Parcelable interface */
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeInt(mFrequencyMhz);
+ }
+
+ /** Implement the Parcelable interface */
+ private WifiP2pUsdBasedLocalServiceAdvertisementConfig(@NonNull Parcel in) {
+ this.mFrequencyMhz = in.readInt();
+ }
+
+ /** Implement the Parcelable interface */
+ @NonNull
+ public static final Creator<WifiP2pUsdBasedLocalServiceAdvertisementConfig> CREATOR =
+ new Creator<WifiP2pUsdBasedLocalServiceAdvertisementConfig>() {
+ public WifiP2pUsdBasedLocalServiceAdvertisementConfig createFromParcel(Parcel in) {
+ return new WifiP2pUsdBasedLocalServiceAdvertisementConfig(in);
+ }
+
+ public WifiP2pUsdBasedLocalServiceAdvertisementConfig[] newArray(int size) {
+ return new WifiP2pUsdBasedLocalServiceAdvertisementConfig[size];
+ }
+ };
+
+ /**
+ * Builder for {@link WifiP2pUsdBasedLocalServiceAdvertisementConfig}.
+ */
+ public static final class Builder {
+ private int mFrequencyMhz;
+
+ /**
+ * Constructs a Builder with default values.
+ */
+ public Builder() {
+ mFrequencyMhz = USD_DEFAULT_DISCOVERY_CHANNEL_MHZ;
+ }
+
+ /**
+ * Specifies the frequency requested for advertising the service.
+ *
+ * @param frequencyMhz The requested frequency on which the service needs to be advertised.
+ * If not set, the default frequency is
+ * {@link #USD_DEFAULT_DISCOVERY_CHANNEL_MHZ} MHz.
+ *
+ * @return The builder to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
+ *
+ */
+ @NonNull
+ public Builder setFrequencyMhz(@IntRange(from = 0) int frequencyMhz) {
+ if (frequencyMhz <= 0) {
+ throw new IllegalArgumentException("Frequency must be greater than 0");
+ }
+ mFrequencyMhz = frequencyMhz;
+ return this;
+ }
+
+ /**
+ * Build {@link WifiP2pUsdBasedLocalServiceAdvertisementConfig} given the
+ * current requests made on the builder.
+ * @return {@link WifiP2pUsdBasedLocalServiceAdvertisementConfig} constructed based on
+ * builder method calls.
+ */
+ @NonNull
+ public WifiP2pUsdBasedLocalServiceAdvertisementConfig build() {
+ return new WifiP2pUsdBasedLocalServiceAdvertisementConfig(mFrequencyMhz);
+ }
+ }
+}
diff --git a/framework/java/android/net/wifi/p2p/WifiP2pUsdBasedServiceDiscoveryConfig.java b/framework/java/android/net/wifi/p2p/WifiP2pUsdBasedServiceDiscoveryConfig.java
new file mode 100644
index 0000000..ed0d9b8
--- /dev/null
+++ b/framework/java/android/net/wifi/p2p/WifiP2pUsdBasedServiceDiscoveryConfig.java
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.p2p;
+
+import android.annotation.FlaggedApi;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.RequiresApi;
+import android.net.wifi.ScanResult;
+import android.os.Build;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.wifi.flags.Flags;
+
+import java.util.Arrays;
+import java.util.Objects;
+
+/**
+ * A class representing a Wi-Fi P2P USD based service discovery configuration for
+ * discovering the services.
+ */
+@RequiresApi(Build.VERSION_CODES.BAKLAVA)
+@FlaggedApi(Flags.FLAG_WIFI_DIRECT_R2)
+public final class WifiP2pUsdBasedServiceDiscoveryConfig implements Parcelable {
+ /**
+ * Default channel frequency for USD based service discovery.
+ */
+ private static final int USD_DEFAULT_DISCOVERY_CHANNEL_MHZ = 2437;
+
+ /** One of the WIFI_BAND */
+ private @ScanResult.WifiBand int mBand;
+
+ /**
+ * Frequencies on which the service needs to be scanned for.
+ * Used when band is set to WIFI_BAND_UNSPECIFIED.
+ */
+ private int[] mFrequenciesMhz;
+
+
+ private WifiP2pUsdBasedServiceDiscoveryConfig(int band, @NonNull int[] frequencies) {
+ mBand = band;
+ mFrequenciesMhz = frequencies;
+ }
+
+ /**
+ * Get the band to scan for services. See {@link Builder#setBand(int)}
+ */
+ @ScanResult.WifiBand
+ public int getBand() {
+ return mBand;
+ }
+
+ /**
+ * Get the frequencies to scan for services. See {@link Builder#setFrequenciesMhz(int[])}
+ */
+ @Nullable
+ public int[] getFrequenciesMhz() {
+ return mFrequenciesMhz;
+ }
+
+ /**
+ * Generates a string of all the defined elements.
+ *
+ * @return a compiled string representing all elements
+ */
+ public String toString() {
+ StringBuilder sbuf = new StringBuilder("WifiP2pUsdBasedServiceDiscoveryConfig:");
+ sbuf.append("\n Band: ").append(mBand);
+ sbuf.append("\n Frequencies: ").append((mFrequenciesMhz == null)
+ ? "<null>" : Arrays.toString(mFrequenciesMhz));
+ return sbuf.toString();
+ }
+
+ /** Implement the Parcelable interface */
+ public int describeContents() {
+ return 0;
+ }
+
+ /** Implement the Parcelable interface */
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeInt(mBand);
+ dest.writeIntArray(mFrequenciesMhz);
+ }
+
+ private WifiP2pUsdBasedServiceDiscoveryConfig(@NonNull Parcel in) {
+ this.mBand = in.readInt();
+ this.mFrequenciesMhz = in.createIntArray();
+ }
+
+ private static boolean isBandValid(@ScanResult.WifiBand int band) {
+ int bandAny = ScanResult.WIFI_BAND_24_GHZ | ScanResult.WIFI_BAND_5_GHZ
+ | ScanResult.WIFI_BAND_6_GHZ;
+ return ((band != 0) && ((band & ~bandAny) == 0));
+ }
+
+ /** Implement the Parcelable interface */
+ @NonNull
+ public static final Creator<WifiP2pUsdBasedServiceDiscoveryConfig> CREATOR =
+ new Creator<WifiP2pUsdBasedServiceDiscoveryConfig>() {
+ public WifiP2pUsdBasedServiceDiscoveryConfig createFromParcel(Parcel in) {
+ return new WifiP2pUsdBasedServiceDiscoveryConfig(in);
+ }
+
+ public WifiP2pUsdBasedServiceDiscoveryConfig[] newArray(int size) {
+ return new WifiP2pUsdBasedServiceDiscoveryConfig[size];
+ }
+ };
+
+ /**
+ * Builder for {@link WifiP2pUsdBasedServiceDiscoveryConfig}.
+ */
+ public static final class Builder {
+ private int mBand;
+ private int[] mFrequenciesMhz;
+
+ /**
+ * Constructs a Builder with default values.
+ */
+ public Builder() {
+ mBand = ScanResult.UNSPECIFIED;
+ mFrequenciesMhz = new int[] {USD_DEFAULT_DISCOVERY_CHANNEL_MHZ};
+ }
+
+ /**
+ * Specifies the band requested for service discovery. The band should
+ * be one of the following band constants defined in {@code ScanResult#WIFI_BAND_24_GHZ},
+ * {@code ScanResult#WIFI_BAND_5_GHZ} or {@code ScanResult#WIFI_BAND_6_GHZ}
+ *
+ * <p>
+ * {@link #setBand(int)} and {@link #setFrequenciesMhz(int[])} are
+ * mutually exclusive. Setting operating band and frequency both is invalid.
+ * <p>
+ * Optional. {@code ScanResult#UNSPECIFIED} by default.
+ *
+ * @param band The requested band.
+ * @return Instance of {@link Builder} to enable chaining of the builder method.
+ *
+ * @throws IllegalArgumentException - if the band specified is not one among the list
+ * of bands mentioned above.
+ */
+ public @NonNull Builder setBand(int band) {
+ if (!isBandValid(band)) {
+ throw new IllegalArgumentException("Invalid band: " + band);
+ }
+ mBand = band;
+ return this;
+ }
+
+ /**
+ * Set the frequencies requested for service discovery.
+ *
+ * <p>
+ * {@link #setBand(int)} and {@link #setFrequenciesMhz(int[])} are
+ * mutually exclusive. Setting band and frequencies both is invalid.
+ * <p>
+ * Optional. 2437 by default.
+ * @param frequenciesMhz Frequencies in MHz to scan for services.
+ * @return Instance of {@link Builder} to enable chaining of the builder method.
+ */
+ @NonNull
+ public Builder setFrequenciesMhz(@NonNull int[] frequenciesMhz) {
+ Objects.requireNonNull(frequenciesMhz, "Frequencies cannot be null");
+ mFrequenciesMhz = frequenciesMhz;
+ return this;
+ }
+
+ /**
+ * Build {@link WifiP2pUsdBasedServiceDiscoveryConfig} given the current requests made
+ * on the builder.
+ * @return {@link WifiP2pUsdBasedServiceDiscoveryConfig} constructed based on builder
+ * method calls.
+ */
+ @NonNull
+ public WifiP2pUsdBasedServiceDiscoveryConfig build() {
+ if (mBand != ScanResult.UNSPECIFIED && mFrequenciesMhz != null) {
+ throw new IllegalStateException(
+ "Frequencies and band are mutually exclusive.");
+ }
+ return new WifiP2pUsdBasedServiceDiscoveryConfig(mBand, mFrequenciesMhz);
+ }
+ }
+}
diff --git a/framework/java/android/net/wifi/p2p/nsd/WifiP2pServiceInfo.java b/framework/java/android/net/wifi/p2p/nsd/WifiP2pServiceInfo.java
index 5d018e7..6cf3031 100644
--- a/framework/java/android/net/wifi/p2p/nsd/WifiP2pServiceInfo.java
+++ b/framework/java/android/net/wifi/p2p/nsd/WifiP2pServiceInfo.java
@@ -16,13 +16,21 @@
package android.net.wifi.p2p.nsd;
+import android.annotation.FlaggedApi;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.RequiresApi;
import android.compat.annotation.UnsupportedAppUsage;
+import android.net.wifi.util.Environment;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
+import com.android.wifi.flags.Flags;
+
import java.util.ArrayList;
import java.util.List;
+import java.util.Objects;
/**
* A class for storing service information that is advertised
@@ -89,6 +97,13 @@
private List<String> mQueryList;
/**
+ * This field is used only when the service advertisement is using un-synchronized service
+ * discovery (USD) protocol. Refer Wi-Fi Alliance Wi-Fi Direct R2 specification section 3.7 -
+ * "Unsynchronized Service Discovery (USD)" for the details.
+ */
+ private WifiP2pUsdBasedServiceConfig mUsdServiceConfig;
+
+ /**
* This is only used in subclass.
*
* @param queryList query string for wpa_supplicant
@@ -102,6 +117,38 @@
mQueryList = queryList;
}
+ /**
+ * This constructor is only used in Parcelable.
+ *
+ * @param queryList query string for wpa_supplicant
+ * @param usdConfig See {@link WifiP2pUsdBasedServiceConfig}
+ *
+ */
+ private WifiP2pServiceInfo(List<String> queryList,
+ @NonNull WifiP2pUsdBasedServiceConfig usdConfig) {
+ mQueryList = queryList;
+ mUsdServiceConfig = usdConfig;
+ }
+
+ /**
+ * Constructor for creating a service information for advertising the service using
+ * un-synchronized service discovery (USD) protocol. Refer Wi-Fi Alliance Wi-Fi Direct R2
+ * specification section 3.7 - "Unsynchronized Service Discovery (USD)" for the details.
+ *
+ * @param usdConfig See {@link WifiP2pUsdBasedServiceConfig}
+ *
+ * @return service info containing USD based service configuration.
+ */
+ @RequiresApi(Build.VERSION_CODES.BAKLAVA)
+ @FlaggedApi(Flags.FLAG_WIFI_DIRECT_R2)
+ public WifiP2pServiceInfo(@NonNull WifiP2pUsdBasedServiceConfig usdConfig) {
+ if (!Environment.isSdkAtLeastB()) {
+ throw new UnsupportedOperationException();
+ }
+ Objects.requireNonNull(usdConfig, "usd based service config cannot be null");
+ mUsdServiceConfig = usdConfig;
+ }
+
/**
* Return the list of the query string for wpa_supplicant.
*
@@ -112,6 +159,25 @@
return mQueryList;
}
+ /**
+ * Get the service information configured to advertise using un-synchronized service discovery
+ * (USD) protocol.
+ * See {@link #WifiP2pServiceInfo(WifiP2pUsdBasedServiceConfig)}
+ *
+ * @return A valid or not null {@link WifiP2pUsdBasedServiceConfig} if the service information
+ * is configured to advertise using un-synchronized service discovery (USD) protocol.
+ * Otherwise, it is null.
+ */
+ @RequiresApi(Build.VERSION_CODES.BAKLAVA)
+ @FlaggedApi(Flags.FLAG_WIFI_DIRECT_R2)
+ @Nullable
+ public WifiP2pUsdBasedServiceConfig getWifiP2pUsdBasedServiceConfig() {
+ if (!Environment.isSdkAtLeastB()) {
+ throw new UnsupportedOperationException();
+ }
+ return mUsdServiceConfig;
+ }
+
/**
* Converts byte array to hex string.
*
@@ -141,23 +207,25 @@
@Override
public boolean equals(Object o) {
- if (o == this) {
- return true;
- }
- if (!(o instanceof WifiP2pServiceInfo)) {
- return false;
- }
+ if (o == this) {
+ return true;
+ }
+ if (!(o instanceof WifiP2pServiceInfo)) {
+ return false;
+ }
- WifiP2pServiceInfo servInfo = (WifiP2pServiceInfo)o;
- return mQueryList.equals(servInfo.mQueryList);
+ WifiP2pServiceInfo servInfo = (WifiP2pServiceInfo) o;
+ return Objects.equals(mQueryList, servInfo.mQueryList)
+ && Objects.equals(mUsdServiceConfig, servInfo.mUsdServiceConfig);
}
- @Override
- public int hashCode() {
- int result = 17;
- result = 31 * result + (mQueryList == null ? 0 : mQueryList.hashCode());
- return result;
- }
+ @Override
+ public int hashCode() {
+ int result = 17;
+ result = 31 * result + (mQueryList == null ? 0 : mQueryList.hashCode());
+ result = 31 * result + (mUsdServiceConfig == null ? 0 : mUsdServiceConfig.hashCode());
+ return result;
+ }
/** Implement the Parcelable interface {@hide} */
public int describeContents() {
@@ -167,21 +235,27 @@
/** Implement the Parcelable interface {@hide} */
public void writeToParcel(Parcel dest, int flags) {
dest.writeStringList(mQueryList);
+ if (Environment.isSdkAtLeastB() && Flags.wifiDirectR2()) {
+ dest.writeParcelable(mUsdServiceConfig, flags);
+ }
}
/** Implement the Parcelable interface {@hide} */
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public static final @android.annotation.NonNull Creator<WifiP2pServiceInfo> CREATOR =
- new Creator<WifiP2pServiceInfo>() {
- public WifiP2pServiceInfo createFromParcel(Parcel in) {
-
- List<String> data = new ArrayList<String>();
- in.readStringList(data);
- return new WifiP2pServiceInfo(data);
- }
-
- public WifiP2pServiceInfo[] newArray(int size) {
- return new WifiP2pServiceInfo[size];
- }
- };
+ new Creator<WifiP2pServiceInfo>() {
+ public WifiP2pServiceInfo createFromParcel(Parcel in) {
+ List<String> data = new ArrayList<String>();
+ in.readStringList(data);
+ WifiP2pUsdBasedServiceConfig config = null;
+ if (Environment.isSdkAtLeastB() && Flags.wifiDirectR2()) {
+ config = in.readParcelable(
+ WifiP2pUsdBasedServiceConfig.class.getClassLoader());
+ }
+ return new WifiP2pServiceInfo(data, config);
+ }
+ public WifiP2pServiceInfo[] newArray(int size) {
+ return new WifiP2pServiceInfo[size];
+ }
+ };
}
diff --git a/framework/java/android/net/wifi/p2p/nsd/WifiP2pServiceRequest.java b/framework/java/android/net/wifi/p2p/nsd/WifiP2pServiceRequest.java
index dea0477..039d93d 100644
--- a/framework/java/android/net/wifi/p2p/nsd/WifiP2pServiceRequest.java
+++ b/framework/java/android/net/wifi/p2p/nsd/WifiP2pServiceRequest.java
@@ -16,13 +16,21 @@
package android.net.wifi.p2p.nsd;
+import android.annotation.FlaggedApi;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.RequiresApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.net.wifi.p2p.WifiP2pManager;
+import android.net.wifi.util.Environment;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
+import com.android.wifi.flags.Flags;
+
import java.util.Locale;
+import java.util.Objects;
/**
* A class for creating a service discovery request for use with
@@ -68,6 +76,13 @@
private String mQuery;
/**
+ * This field is used only when the service discovery request is using un-synchronized service
+ * discovery (USD) protocol. Refer Wi-Fi Alliance Wi-Fi Direct R2 specification section 3.7 -
+ * "Unsynchronized Service Discovery (USD)" for the details.
+ */
+ private WifiP2pUsdBasedServiceConfig mUsdServiceConfig;
+
+ /**
* This constructor is only used in newInstance().
*
* @param protocolType service discovery protocol.
@@ -88,19 +103,21 @@
}
/**
- * This constructor is only used in Parcelable.
+ * This constructor is only used in parcelable.
*
* @param serviceType service discovery type.
* @param length the length of service discovery packet.
* @param transId the transaction id
* @param query The part of service specific query.
+ * @param usdConfig The USD based service config.
*/
private WifiP2pServiceRequest(int serviceType, int length,
- int transId, String query) {
+ int transId, String query, @NonNull WifiP2pUsdBasedServiceConfig usdConfig) {
mProtocolType = serviceType;
mLength = length;
mTransId = transId;
mQuery = query;
+ mUsdServiceConfig = usdConfig;
}
/**
@@ -151,6 +168,26 @@
}
/**
+ /**
+ * Get the service information configured to discover a service using un-synchronized service
+ * discovery (USD) protocol.
+ * See {@link #WifiP2pServiceRequest(WifiP2pUsdBasedServiceConfig)}.
+ *
+ * @return A valid or not null {@link WifiP2pUsdBasedServiceConfig} if the service information
+ * is configured to discover a service using un-synchronized service discovery (USD) protocol.
+ * Otherwise, it is null.
+ */
+ @RequiresApi(Build.VERSION_CODES.BAKLAVA)
+ @FlaggedApi(Flags.FLAG_WIFI_DIRECT_R2)
+ @Nullable
+ public WifiP2pUsdBasedServiceConfig getWifiP2pUsdBasedServiceConfig() {
+ if (!Environment.isSdkAtLeastB()) {
+ throw new UnsupportedOperationException();
+ }
+ return mUsdServiceConfig;
+ }
+
+ /**
* Validate query.
*
* <p>If invalid, throw IllegalArgumentException.
@@ -214,6 +251,25 @@
return new WifiP2pServiceRequest(protocolType, null);
}
+ /**
+ * Constructor for creating a service discovery request for discovering the service using
+ * un-synchronized service discovery (USD) protocol. Refer Wi-Fi Alliance Wi-Fi Direct R2
+ * specification section 3.7 - "Unsynchronized Service Discovery (USD)" for the details.
+ *
+ * @param usdConfig See {@link WifiP2pUsdBasedServiceConfig}
+ *
+ * @return service discovery request containing USD based service configuration.
+ */
+ @RequiresApi(Build.VERSION_CODES.BAKLAVA)
+ @FlaggedApi(Flags.FLAG_WIFI_DIRECT_R2)
+ public WifiP2pServiceRequest(@NonNull WifiP2pUsdBasedServiceConfig usdConfig) {
+ if (!Environment.isSdkAtLeastB()) {
+ throw new UnsupportedOperationException();
+ }
+ Objects.requireNonNull(usdConfig, "usdConfig cannot be null");
+ mUsdServiceConfig = usdConfig;
+ }
+
@Override
public boolean equals(Object o) {
if (o == this) {
@@ -229,17 +285,10 @@
* Not compare transaction id.
* Transaction id may be changed on each service discovery operation.
*/
- if ((req.mProtocolType != mProtocolType) ||
- (req.mLength != mLength)) {
- return false;
- }
-
- if (req.mQuery == null && mQuery == null) {
- return true;
- } else if (req.mQuery != null) {
- return req.mQuery.equals(mQuery);
- }
- return false;
+ return mProtocolType == req.mProtocolType
+ && mLength == req.mLength
+ && Objects.equals(mQuery, req.mQuery)
+ && Objects.equals(mUsdServiceConfig, req.mUsdServiceConfig);
}
@Override
@@ -248,6 +297,7 @@
result = 31 * result + mProtocolType;
result = 31 * result + mLength;
result = 31 * result + (mQuery == null ? 0 : mQuery.hashCode());
+ result = 31 * result + (mUsdServiceConfig == null ? 0 : mUsdServiceConfig.hashCode());
return result;
}
@@ -262,22 +312,29 @@
dest.writeInt(mLength);
dest.writeInt(mTransId);
dest.writeString(mQuery);
+ if (Environment.isSdkAtLeastB() && Flags.wifiDirectR2()) {
+ dest.writeParcelable(mUsdServiceConfig, flags);
+ }
}
/** Implement the Parcelable interface {@hide} */
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public static final @android.annotation.NonNull Creator<WifiP2pServiceRequest> CREATOR =
- new Creator<WifiP2pServiceRequest>() {
- public WifiP2pServiceRequest createFromParcel(Parcel in) {
- int servType = in.readInt();
- int length = in.readInt();
- int transId = in.readInt();
- String query = in.readString();
- return new WifiP2pServiceRequest(servType, length, transId, query);
- }
-
- public WifiP2pServiceRequest[] newArray(int size) {
- return new WifiP2pServiceRequest[size];
- }
- };
+ new Creator<WifiP2pServiceRequest>() {
+ public WifiP2pServiceRequest createFromParcel(Parcel in) {
+ int servType = in.readInt();
+ int length = in.readInt();
+ int transId = in.readInt();
+ String query = in.readString();
+ WifiP2pUsdBasedServiceConfig config = null;
+ if (Environment.isSdkAtLeastB() && Flags.wifiDirectR2()) {
+ config = in.readParcelable(
+ WifiP2pUsdBasedServiceConfig.class.getClassLoader());
+ }
+ return new WifiP2pServiceRequest(servType, length, transId, query, config);
+ }
+ public WifiP2pServiceRequest[] newArray(int size) {
+ return new WifiP2pServiceRequest[size];
+ }
+ };
}
diff --git a/framework/java/android/net/wifi/p2p/nsd/WifiP2pServiceResponse.java b/framework/java/android/net/wifi/p2p/nsd/WifiP2pServiceResponse.java
index 1b9c080..b0ef358 100644
--- a/framework/java/android/net/wifi/p2p/nsd/WifiP2pServiceResponse.java
+++ b/framework/java/android/net/wifi/p2p/nsd/WifiP2pServiceResponse.java
@@ -16,16 +16,22 @@
package android.net.wifi.p2p.nsd;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.net.wifi.p2p.WifiP2pDevice;
+import android.net.wifi.util.Environment;
import android.os.Parcel;
import android.os.Parcelable;
+import com.android.wifi.flags.Flags;
+
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.Objects;
/**
* The class for a response of service discovery.
@@ -65,6 +71,11 @@
*/
protected byte[] mData;
+ /**
+ * This field is used only for USD based service discovery response.
+ */
+ private WifiP2pUsdBasedServiceResponse mUsdBasedServiceResponse;
+
/**
* The status code of service discovery response.
@@ -125,6 +136,23 @@
}
/**
+ * Hidden constructor. This is only used in framework.
+ *
+ * @param device source device.
+ * @param usdResponseData USD based service response data.
+ * @hide
+ */
+ public WifiP2pServiceResponse(WifiP2pDevice device,
+ @NonNull WifiP2pUsdBasedServiceResponse usdResponseData) {
+ mServiceType = 0;
+ mStatus = 0;
+ mTransId = 0;
+ mDevice = device;
+ mData = null;
+ mUsdBasedServiceResponse = usdResponseData;
+ }
+
+ /**
* Return the service type of service discovery response.
*
* @return service discovery type.<br>
@@ -182,6 +210,20 @@
this.mDevice = dev;
}
+ /**
+ * Get the service response data received through un-synchronized service
+ * discovery (USD) protocol.
+ *
+ * @return A valid or not null {@link WifiP2pUsdBasedServiceResponse} if the service response
+ * data is received through un-synchronized service discovery (USD) protocol.
+ * Otherwise, it is null.
+ * @hide
+ */
+ @Nullable
+ public WifiP2pUsdBasedServiceResponse getWifiP2pUsdBasedServiceResponse() {
+ return mUsdBasedServiceResponse;
+ }
+
/**
* Create the list of WifiP2pServiceResponse instance from supplicant event.
@@ -289,6 +331,11 @@
sbuf.append(" status:").append(Status.toString(mStatus));
sbuf.append(" srcAddr:").append(mDevice.deviceAddress);
sbuf.append(" data:").append(Arrays.toString(mData));
+ if (Environment.isSdkAtLeastB() && Flags.wifiDirectR2()) {
+ sbuf.append(" USD based service response:")
+ .append((mUsdBasedServiceResponse == null)
+ ? "<null>" : mUsdBasedServiceResponse.toString());
+ }
return sbuf.toString();
}
@@ -303,10 +350,11 @@
WifiP2pServiceResponse req = (WifiP2pServiceResponse)o;
- return (req.mServiceType == mServiceType) &&
- (req.mStatus == mStatus) &&
- equals(req.mDevice.deviceAddress, mDevice.deviceAddress) &&
- Arrays.equals(req.mData, mData);
+ return mServiceType == req.mServiceType
+ && mStatus == req.mStatus
+ && Objects.equals(mDevice.deviceAddress, req.mDevice.deviceAddress)
+ && Arrays.equals(mData, req.mData)
+ && Objects.equals(mUsdBasedServiceResponse, req.mUsdBasedServiceResponse);
}
private boolean equals(Object a, Object b) {
@@ -327,6 +375,8 @@
result = 31 * result + (mDevice.deviceAddress == null ?
0 : mDevice.deviceAddress.hashCode());
result = 31 * result + (mData == null ? 0 : Arrays.hashCode(mData));
+ result = 31 * result + (mUsdBasedServiceResponse == null
+ ? 0 : mUsdBasedServiceResponse.hashCode());
return result;
}
@@ -347,35 +397,41 @@
dest.writeInt(mData.length);
dest.writeByteArray(mData);
}
+ if (Environment.isSdkAtLeastB() && Flags.wifiDirectR2()) {
+ dest.writeParcelable(mUsdBasedServiceResponse, flags);
+ }
}
/** Implement the Parcelable interface {@hide} */
public static final @android.annotation.NonNull Creator<WifiP2pServiceResponse> CREATOR =
- new Creator<WifiP2pServiceResponse>() {
- public WifiP2pServiceResponse createFromParcel(Parcel in) {
-
- int type = in.readInt();
- int status = in.readInt();
- int transId = in.readInt();
- WifiP2pDevice dev = (WifiP2pDevice)in.readParcelable(null);
- int len = in.readInt();
- byte[] data = null;
- if (len > 0) {
- data = new byte[len];
- in.readByteArray(data);
+ new Creator<WifiP2pServiceResponse>() {
+ public WifiP2pServiceResponse createFromParcel(Parcel in) {
+ int type = in.readInt();
+ int status = in.readInt();
+ int transId = in.readInt();
+ WifiP2pDevice dev = in.readParcelable(WifiP2pDevice.class.getClassLoader());
+ int len = in.readInt();
+ byte[] data = null;
+ if (len > 0) {
+ data = new byte[len];
+ in.readByteArray(data);
+ }
+ WifiP2pUsdBasedServiceResponse response = null;
+ if (Environment.isSdkAtLeastB() && Flags.wifiDirectR2()) {
+ response = in.readParcelable(
+ WifiP2pUsdBasedServiceResponse.class.getClassLoader());
+ }
+ if (type == WifiP2pServiceInfo.SERVICE_TYPE_BONJOUR) {
+ return WifiP2pDnsSdServiceResponse.newInstance(status, transId, dev, data);
+ } else if (type == WifiP2pServiceInfo.SERVICE_TYPE_UPNP) {
+ return WifiP2pUpnpServiceResponse.newInstance(status, transId, dev, data);
+ } else if (response != null) {
+ return new WifiP2pServiceResponse(dev, response);
+ }
+ return new WifiP2pServiceResponse(type, status, transId, dev, data);
}
- if (type == WifiP2pServiceInfo.SERVICE_TYPE_BONJOUR) {
- return WifiP2pDnsSdServiceResponse.newInstance(status,
- transId, dev, data);
- } else if (type == WifiP2pServiceInfo.SERVICE_TYPE_UPNP) {
- return WifiP2pUpnpServiceResponse.newInstance(status,
- transId, dev, data);
+ public WifiP2pServiceResponse[] newArray(int size) {
+ return new WifiP2pServiceResponse[size];
}
- return new WifiP2pServiceResponse(type, status, transId, dev, data);
- }
-
- public WifiP2pServiceResponse[] newArray(int size) {
- return new WifiP2pServiceResponse[size];
- }
- };
+ };
}
diff --git a/framework/java/android/net/wifi/p2p/nsd/WifiP2pUsdBasedServiceConfig.java b/framework/java/android/net/wifi/p2p/nsd/WifiP2pUsdBasedServiceConfig.java
new file mode 100644
index 0000000..41b8783
--- /dev/null
+++ b/framework/java/android/net/wifi/p2p/nsd/WifiP2pUsdBasedServiceConfig.java
@@ -0,0 +1,247 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.p2p.nsd;
+
+import android.annotation.FlaggedApi;
+import android.annotation.IntDef;
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.RequiresApi;
+import android.os.Build;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+
+import com.android.wifi.flags.Flags;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Arrays;
+import java.util.Objects;
+
+/**
+ * A class for creating a USD based service discovery configuration for use with
+ * {@link WifiP2pServiceInfo}.<br> or {@link WifiP2pServiceRequest}.<br>
+ * For the details of the configuration, refer Wi-Fi Alliance Wi-Fi Direct R2 specification
+ * - Appendix H - Unsynchronized Service Discovery (as defined in Wi-Fi Aware) and section
+ * 4.2.13 USD frame format.
+ */
+@RequiresApi(Build.VERSION_CODES.BAKLAVA)
+@FlaggedApi(Flags.FLAG_WIFI_DIRECT_R2)
+public final class WifiP2pUsdBasedServiceConfig implements Parcelable {
+ /** Bonjour service protocol type */
+ public static final int SERVICE_PROTOCOL_TYPE_BONJOUR = 1;
+
+ /** Generic service protocol type */
+ public static final int SERVICE_PROTOCOL_TYPE_GENERIC = 2;
+
+ /**
+ * Currently for Wi-Fi Direct R2, status codes are defined in Wi-Fi Direct R2 specification
+ * (Table 129).
+ * @hide
+ */
+ @IntDef(flag = false, prefix = { "SERVICE_PROTOCOL_TYPE_" }, value = {
+ SERVICE_PROTOCOL_TYPE_BONJOUR,
+ SERVICE_PROTOCOL_TYPE_GENERIC,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ServiceProtocolType {}
+
+ /**
+ * Service protocol type.
+ */
+ private int mServiceProtocolType;
+ /**
+ * UTF-8 string defining the service.
+ */
+ private String mServiceName;
+ /**
+ * Optional Service specific information content determined by the application.
+ */
+ private byte[] mServiceSpecificInfo;
+
+ /** Get the service protocol type of this USD service configuration. See also
+ * {@link Builder#setServiceProtocolType(int)}.
+ *
+ * @return A non-negative service layer protocol type.
+ */
+ @IntRange(from = 0, to = 255)
+ public int getServiceProtocolType() {
+ return mServiceProtocolType;
+ }
+
+ /** Get the service name of this USD service configuration. See also
+ * {@link Builder}.
+ *
+ * @return UTF-8 string defining the service.
+ */
+ @NonNull
+ public String getServiceName() {
+ return mServiceName;
+ }
+
+ /** Get the service specific info of this USD service configuration. see also
+ * {@link Builder#setServiceSpecificInfo(byte[])} .
+ *
+ *
+ * @return A byte-array of service specification information, or null if unset.
+ */
+ @Nullable
+ public byte[] getServiceSpecificInfo() {
+ return mServiceSpecificInfo;
+ }
+
+ /**
+ * Generates a string of all the defined elements.
+ *
+ * @return a compiled string representing all elements
+ */
+ public String toString() {
+ StringBuilder sbuf = new StringBuilder("WifiP2pUsdBasedServiceConfig:");
+ sbuf.append("\n Protocol type: ").append(mServiceProtocolType);
+ sbuf.append("\n Service name : ").append(mServiceName);
+ sbuf.append("\n Service specific info : ").append((mServiceSpecificInfo == null)
+ ? "<null>" : Arrays.toString(mServiceSpecificInfo));
+ return sbuf.toString();
+ }
+
+ /** Implement the Parcelable interface */
+ public int describeContents() {
+ return 0;
+ }
+
+ /** Implement the Parcelable interface */
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeInt(mServiceProtocolType);
+ dest.writeString(mServiceName);
+ dest.writeByteArray(mServiceSpecificInfo);
+ }
+
+ /** Implement the Parcelable interface */
+ @NonNull
+ public static final Creator<WifiP2pUsdBasedServiceConfig> CREATOR =
+ new Creator<WifiP2pUsdBasedServiceConfig>() {
+ public WifiP2pUsdBasedServiceConfig createFromParcel(Parcel in) {
+ WifiP2pUsdBasedServiceConfig config = new WifiP2pUsdBasedServiceConfig();
+ config.mServiceProtocolType = in.readInt();
+ config.mServiceName = in.readString();
+ config.mServiceSpecificInfo = in.createByteArray();
+ return config;
+ }
+
+ public WifiP2pUsdBasedServiceConfig[] newArray(int size) {
+ return new WifiP2pUsdBasedServiceConfig[size];
+ }
+ };
+
+ /**
+ * Builder used to build {@link WifiP2pUsdBasedServiceConfig} objects for
+ * USD based service discovery and advertisement.
+ */
+ public static final class Builder {
+ /** Maximum allowed length of service name */
+ private static final int SERVICE_NAME_MAXIMUM_LENGTH = 100;
+
+ /** Maximum allowed length of service specific information */
+ private static final int SERVICE_SPECIFIC_INFO_MAXIMUM_LENGTH = 1024;
+ private int mServiceProtocolType = SERVICE_PROTOCOL_TYPE_GENERIC;
+ private @NonNull String mServiceName;
+ byte[] mServiceSpecificInfo;
+
+ /**
+ * Constructor for {@link Builder}.
+ *
+ * @param serviceName The service name defining the service. The maximum
+ * allowed length of the service name is 100 bytes.
+ */
+ public Builder(@NonNull String serviceName) {
+ Objects.requireNonNull(serviceName, "Service name cannot be null");
+ if (TextUtils.isEmpty(serviceName)) {
+ throw new IllegalArgumentException("Service name cannot be empty!");
+ }
+ if (serviceName.length() > SERVICE_NAME_MAXIMUM_LENGTH) {
+ throw new IllegalArgumentException("Service name length: " + serviceName.length()
+ + " must be less than " + SERVICE_NAME_MAXIMUM_LENGTH);
+ }
+ mServiceName = serviceName;
+ }
+
+
+ /**
+ * Specify the service discovery protocol type.
+ *
+ * <p>
+ * Optional. {@code SERVICE_PROTOCOL_TYPE_GENERIC} by default.
+ *
+ * @param serviceProtocolType One of the {@code SERVICE_PROTOCOL_TYPE_*} or a non-negative
+ * number set by the service layer.
+ * @return The builder to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
+ */
+ @NonNull
+ public Builder setServiceProtocolType(
+ @IntRange(from = 0, to = 255) int serviceProtocolType) {
+ if (serviceProtocolType < 0 || serviceProtocolType > 255) {
+ throw new IllegalArgumentException(
+ "serviceProtocolType must be between 0-255 (inclusive)");
+ }
+ mServiceProtocolType = serviceProtocolType;
+ return this;
+ }
+
+ /**
+ * Specify service specific information content determined by the application.
+ * <p>
+ * Optional. Empty by default.
+ *
+ * @param serviceSpecificInfo A byte-array of service-specific information available to the
+ * application to send additional information. The maximum
+ * allowed length of this byte-array is 1024 bytes.
+ *
+ * @return The builder to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
+ */
+ @NonNull
+ public Builder setServiceSpecificInfo(@Nullable byte[] serviceSpecificInfo) {
+ if (serviceSpecificInfo != null
+ && serviceSpecificInfo.length > SERVICE_SPECIFIC_INFO_MAXIMUM_LENGTH) {
+ throw new IllegalArgumentException("Service specific info length: "
+ + serviceSpecificInfo.length
+ + " must be less than " + SERVICE_SPECIFIC_INFO_MAXIMUM_LENGTH);
+ }
+ mServiceSpecificInfo = serviceSpecificInfo;
+ return this;
+ }
+
+ /**
+ * Build {@link WifiP2pUsdBasedServiceConfig} given the current requests made on the
+ * builder.
+ * @return {@link WifiP2pUsdBasedServiceConfig} constructed based on builder method calls.
+ */
+ @NonNull
+ public WifiP2pUsdBasedServiceConfig build() {
+ if (TextUtils.isEmpty(mServiceName)) {
+ throw new IllegalStateException(
+ "Service name must be non-empty");
+ }
+ WifiP2pUsdBasedServiceConfig config = new WifiP2pUsdBasedServiceConfig();
+ config.mServiceName = mServiceName;
+ config.mServiceProtocolType = mServiceProtocolType;
+ config.mServiceSpecificInfo = mServiceSpecificInfo;
+ return config;
+ }
+ }
+}
diff --git a/framework/java/android/net/wifi/p2p/nsd/WifiP2pUsdBasedServiceResponse.java b/framework/java/android/net/wifi/p2p/nsd/WifiP2pUsdBasedServiceResponse.java
new file mode 100644
index 0000000..279a6f4
--- /dev/null
+++ b/framework/java/android/net/wifi/p2p/nsd/WifiP2pUsdBasedServiceResponse.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.p2p.nsd;
+
+import android.annotation.FlaggedApi;
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.RequiresApi;
+import android.os.Build;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.wifi.flags.Flags;
+
+import java.util.Arrays;
+
+/**
+ * A class for a response for USD based service discovery.
+ * For the details of the configuration, refer Wi-Fi Alliance Wi-Fi Direct R2 specification
+ * - Appendix H - Unsynchronized Service Discovery (as defined in Wi-Fi Aware) and section
+ * 4.2.13 USD frame format.
+ */
+@RequiresApi(Build.VERSION_CODES.BAKLAVA)
+@FlaggedApi(Flags.FLAG_WIFI_DIRECT_R2)
+public final class WifiP2pUsdBasedServiceResponse implements Parcelable {
+ /**
+ * Service discovery protocol tye. It's defined in table 129 in Wi-Fi Direct R2 specification.
+ */
+ private int mServiceProtocolType = -1;
+
+ /**
+ * Optional Service specific information content send in the response frame.
+ */
+ private byte[] mServiceSpecificInfo;
+
+ /**
+ * Hidden constructor. This is only used in framework.
+ *
+ * @param serviceProtocolType The service protocol type.
+ * @param serviceSpecificInfo The service specific information.
+ * @hide
+ *
+ */
+ public WifiP2pUsdBasedServiceResponse(int serviceProtocolType,
+ @Nullable byte[] serviceSpecificInfo) {
+ mServiceProtocolType = serviceProtocolType;
+ mServiceSpecificInfo = serviceSpecificInfo;
+ }
+
+ /**
+ * Get the service protocol type provided by the peer device in the USD service response.
+ * See also {@link WifiP2pUsdBasedServiceConfig.Builder#setServiceProtocolType(int)}
+ *
+ * @return A non-negative service layer protocol type.
+ */
+ @IntRange(from = 0, to = 255)
+ public int getServiceProtocolType() {
+ return mServiceProtocolType;
+ }
+
+ /** Get the service specific information provided by the peer device in the USD service
+ * response.
+ * See also {@link WifiP2pUsdBasedServiceConfig.Builder#setServiceSpecificInfo(byte[])}
+ *
+ * @return A byte-array of service specification information, or null if unset.
+ */
+ @Nullable
+ public byte[] getServiceSpecificInfo() {
+ return mServiceSpecificInfo;
+ }
+
+ /**
+ * Generates a string of all the defined elements.
+ *
+ * @return a compiled string representing all elements
+ */
+ public String toString() {
+ StringBuilder sbuf = new StringBuilder("WifiP2pUsdBasedServiceResponse:");
+ sbuf.append("\n Protocol type: ").append(mServiceProtocolType);
+ sbuf.append("\n Service specific info : ").append((mServiceSpecificInfo == null)
+ ? "<null>" : Arrays.toString(mServiceSpecificInfo));
+ return sbuf.toString();
+ }
+
+ /** Implement the Parcelable interface */
+ public int describeContents() {
+ return 0;
+ }
+
+ /** Implement the Parcelable interface */
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeInt(mServiceProtocolType);
+ dest.writeByteArray(mServiceSpecificInfo);
+ }
+
+ /** Implement the Parcelable interface */
+ @NonNull
+ public static final Creator<WifiP2pUsdBasedServiceResponse> CREATOR =
+ new Creator<WifiP2pUsdBasedServiceResponse>() {
+ public WifiP2pUsdBasedServiceResponse createFromParcel(Parcel in) {
+ int serviceProtocolType = in.readInt();
+ byte[] ssi = in.createByteArray();
+ return new WifiP2pUsdBasedServiceResponse(serviceProtocolType, ssi);
+ }
+
+ public WifiP2pUsdBasedServiceResponse[] newArray(int size) {
+ return new WifiP2pUsdBasedServiceResponse[size];
+ }
+ };
+}
diff --git a/framework/java/android/net/wifi/rtt/PasnConfig.java b/framework/java/android/net/wifi/rtt/PasnConfig.java
new file mode 100644
index 0000000..9688f5e
--- /dev/null
+++ b/framework/java/android/net/wifi/rtt/PasnConfig.java
@@ -0,0 +1,432 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.rtt;
+
+import android.annotation.FlaggedApi;
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.net.wifi.ScanResult;
+import android.net.wifi.WifiSsid;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.modules.utils.build.SdkLevel;
+import com.android.wifi.flags.Flags;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * Pre-association security negotiation (PASN) configuration.
+ * <p>
+ * PASN configuration in IEEE 802.11az focuses on securing the ranging process before a device
+ * fully associates with a Wi-Fi network. IEEE 802.11az supports various based AKMs as in
+ * {@code AKM_*} for PASN and cipher as in {@code CIPHER_*}. Password is also another input to
+ * some base AKMs.
+ * <p>
+ * Once PASN is initiated, the AP and the client device exchange messages to authenticate each
+ * other and establish security keys. This process ensures that only authorized devices can
+ * participate in ranging.
+ * <p>
+ * After successful PASN authentication, ranging operations are performed using the established
+ * secure channel. This protects the ranging measurements from eavesdropping and tampering.
+ * <p>
+ * The keys derived during the PASN process are used to protect the LTFs exchanged during ranging.
+ * This ensures that the LTFs are encrypted and authenticated, preventing unauthorized access
+ * and manipulation.
+ */
+@FlaggedApi(Flags.FLAG_SECURE_RANGING)
+public final class PasnConfig implements Parcelable {
+
+ /**
+ * Various base Authentication and Key Management (AKM) protocol supported by the PASN.
+ *
+ * @hide
+ */
+ @IntDef(prefix = {"AKM_"}, flag = true, value = {
+ AKM_NONE,
+ AKM_PASN,
+ AKM_SAE,
+ AKM_FT_EAP_SHA256,
+ AKM_FT_PSK_SHA256,
+ AKM_FT_EAP_SHA384,
+ AKM_FT_PSK_SHA384,
+ AKM_FILS_EAP_SHA256,
+ AKM_FILS_EAP_SHA384})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface AkmType {
+ }
+
+ /**
+ * No authentication and key management.
+ */
+ public static final int AKM_NONE = 0;
+ /**
+ * Pre-association security negotiation (PASN).
+ */
+ public static final int AKM_PASN = 1 << 0;
+ /**
+ * Simultaneous authentication of equals (SAE).
+ */
+ public static final int AKM_SAE = 1 << 1;
+ /**
+ * Fast BSS Transition (FT) with Extensible Authentication Protocol (EAP) and SHA-256.
+ */
+ public static final int AKM_FT_EAP_SHA256 = 1 << 2;
+ /**
+ * Fast BSS Transition (FT) with Pre-Shared Key (PSK) and SHA-256.
+ */
+ public static final int AKM_FT_PSK_SHA256 = 1 << 3;
+ /**
+ * Fast BSS Transition (FT) with Extensible Authentication Protocol (EAP) and SHA-384.
+ */
+ public static final int AKM_FT_EAP_SHA384 = 1 << 4;
+ /**
+ * Fast BSS Transition (FT) with Pre-Shared Key (PSK) and SHA-384.
+ */
+ public static final int AKM_FT_PSK_SHA384 = 1 << 5;
+ /**
+ * Fast Initial Link Setup (FILS) with Extensible Authentication Protocol (EAP) and SHA-256.
+ */
+ public static final int AKM_FILS_EAP_SHA256 = 1 << 6;
+ /**
+ * Fast Initial Link Setup (FILS) with Extensible Authentication Protocol (EAP) and SHA-384.
+ */
+ public static final int AKM_FILS_EAP_SHA384 = 1 << 7;
+
+ /**
+ * @hide
+ */
+ private static final Map<String, Integer> sStringToAkm = new HashMap<>();
+
+ static {
+ sStringToAkm.put("None", AKM_NONE);
+ sStringToAkm.put("PASN-", AKM_PASN);
+ // Transition mode. e.g. "[RSN-SAE+SAE_EXT_KEY-CCMP]"
+ sStringToAkm.put("SAE+", AKM_SAE);
+ // SAE mode only. e.g. "[RSN-PSK+SAE-CCMP]"
+ sStringToAkm.put("SAE-", AKM_SAE);
+ sStringToAkm.put("EAP-FILS-SHA256-", AKM_FILS_EAP_SHA256);
+ sStringToAkm.put("EAP-FILS-SHA384-", AKM_FILS_EAP_SHA384);
+ sStringToAkm.put("FT/EAP-", AKM_FT_EAP_SHA256);
+ sStringToAkm.put("FT/PSK-", AKM_FT_PSK_SHA256);
+ sStringToAkm.put("EAP-FT-SHA384-", AKM_FT_EAP_SHA384);
+ sStringToAkm.put("FT/PSK-SHA384-", AKM_FT_PSK_SHA384);
+ }
+
+ /**
+ * Pairwise cipher used for encryption.
+ *
+ * @hide
+ */
+ @IntDef(prefix = {"CIPHER_"}, flag = true, value = {
+ CIPHER_NONE,
+ CIPHER_CCMP_128,
+ CIPHER_CCMP_256,
+ CIPHER_GCMP_128,
+ CIPHER_GCMP_256})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Cipher {
+ }
+
+ /**
+ * No encryption.
+ */
+ public static final int CIPHER_NONE = 0;
+ /**
+ * Counter Mode with Cipher Block Chaining Message Authentication Code Protocol (CCMP) with
+ * 128-bit key.
+ */
+ public static final int CIPHER_CCMP_128 = 1 << 0;
+ /**
+ * Counter Mode with Cipher Block Chaining Message Authentication Code Protocol (CCMP) with
+ * 256-bit key.
+ */
+ public static final int CIPHER_CCMP_256 = 1 << 1;
+ /**
+ * Galois/Counter Mode Protocol (GCMP) with 128-bit key.
+ */
+ public static final int CIPHER_GCMP_128 = 1 << 2;
+ /**
+ * Galois/Counter Mode Protocol (GCMP) with 256-bit key.
+ */
+ public static final int CIPHER_GCMP_256 = 1 << 3;
+ private static final Map<String, Integer> sStringToCipher = new HashMap<>();
+
+ static {
+ sStringToCipher.put("None", CIPHER_NONE);
+ sStringToCipher.put("-CCMP]", CIPHER_CCMP_128);
+ sStringToCipher.put("-CCMP-256]", CIPHER_CCMP_256);
+ sStringToCipher.put("-GCMP-128]", CIPHER_GCMP_128);
+ sStringToCipher.put("-GCMP-256]", CIPHER_GCMP_256);
+ }
+
+ @AkmType
+ private final int mBaseAkms;
+ @Cipher
+ private final int mCiphers;
+ private final String mPassword;
+ private final WifiSsid mWifiSsid;
+ private final byte[] mPasnComebackCookie;
+
+ /**
+ * Return base AKMs (Authentication and Key Management).
+ */
+ public @AkmType int getBaseAkms() {
+ return mBaseAkms;
+ }
+
+ /**
+ * Return pairwise ciphers.
+ */
+ public @Cipher int getCiphers() {
+ return mCiphers;
+ }
+
+ /**
+ * Get password used by base AKM. If null, password is retrieved from the saved network
+ * profile for the PASN authentication. See {@link #getWifiSsid()} on retrieving saved
+ * network profile.
+ */
+ @Nullable
+ public String getPassword() {
+ return mPassword;
+ }
+
+ /**
+ * Get Wifi SSID which is used to retrieve saved network profile if {@link #getPassword()}
+ * is null. If Wifi SSID and password are not set and there is no saved profile corresponding to
+ * the responder, unauthenticated PASN will be used if {@link RangingRequest#getSecurityMode()}
+ * allows. See {@code SECURITY_MODE_*} for more details.
+ */
+ @Nullable
+ public WifiSsid getWifiSsid() {
+ return mWifiSsid;
+ }
+
+ /**
+ * Get PASN comeback cookie. See {@link Builder#setPasnComebackCookie(byte[])}.
+ **/
+ @Nullable
+ public byte[] getPasnComebackCookie() {
+ return mPasnComebackCookie;
+ }
+
+
+ private PasnConfig(@NonNull Parcel in) {
+ mBaseAkms = in.readInt();
+ mCiphers = in.readInt();
+ mPassword = in.readString();
+ mWifiSsid = (SdkLevel.isAtLeastT()) ? in.readParcelable(WifiSsid.class.getClassLoader(),
+ WifiSsid.class) : in.readParcelable(WifiSsid.class.getClassLoader());
+ mPasnComebackCookie = in.createByteArray();
+ }
+
+ public static final @NonNull Creator<PasnConfig> CREATOR = new Creator<PasnConfig>() {
+ @Override
+ public PasnConfig createFromParcel(Parcel in) {
+ return new PasnConfig(in);
+ }
+
+ @Override
+ public PasnConfig[] newArray(int size) {
+ return new PasnConfig[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@androidx.annotation.NonNull Parcel dest, int flags) {
+ dest.writeInt(mBaseAkms);
+ dest.writeInt(mCiphers);
+ dest.writeString(mPassword);
+ dest.writeByteArray(mPasnComebackCookie);
+ }
+
+ /**
+ * Convert capability string from {@link ScanResult} to a set of
+ * {@code AKM_*} supported by the PASN.
+ *
+ * @hide
+ */
+ public @AkmType static int getBaseAkmsFromCapabilities(String capabilities) {
+ @AkmType int akms = AKM_NONE;
+ if (capabilities == null) return akms;
+ for (String akm : sStringToAkm.keySet()) {
+ if (capabilities.contains(akm)) {
+ akms |= sStringToAkm.get(akm);
+ }
+ }
+ return akms;
+ }
+
+ /**
+ * Convert capability string from {@link ScanResult} to a set of
+ * {@code CIPHER_*}.
+ *
+ * @hide
+ */
+ public @Cipher static int getCiphersFromCapabilities(String capabilities) {
+ @Cipher int ciphers = CIPHER_NONE;
+ if (capabilities == null) return ciphers;
+ for (String cipher : sStringToCipher.keySet()) {
+ if (capabilities.contains(cipher)) {
+ ciphers |= sStringToCipher.get(cipher);
+ }
+ }
+ return ciphers;
+ }
+
+ private PasnConfig(Builder builder) {
+ mBaseAkms = builder.mBaseAkms;
+ mCiphers = builder.mCiphers;
+ mPassword = builder.mPassword;
+ mWifiSsid = builder.mWifiSsid;
+ mPasnComebackCookie = builder.mPasnComebackCookie;
+ }
+
+ /**
+ * @hide
+ */
+ public static boolean isAkmRequiresPassword(int akms) {
+ return (akms & AKM_SAE) != 0;
+ }
+
+ /**
+ * Builder for {@link PasnConfig}
+ */
+ @FlaggedApi(Flags.FLAG_SECURE_RANGING)
+ public static final class Builder {
+ private final int mBaseAkms;
+ private final int mCiphers;
+ private String mPassword = null;
+ private WifiSsid mWifiSsid = null;
+ byte[] mPasnComebackCookie = null;
+
+ /**
+ * Builder
+ *
+ * @param baseAkms The AKMs that PASN is configured to use. PASN will use the most secure
+ * AKM in the configuration.
+ * @param ciphers The CIPHERs that PASN is configured to use. PASN will use the most
+ * secure CIPHER in the configuration which is applicable to the base AKM
+ */
+ public Builder(@AkmType int baseAkms, @Cipher int ciphers) {
+ mBaseAkms = baseAkms;
+ mCiphers = ciphers;
+ }
+
+ /**
+ * Sets the password if needed by the base AKM of the PASN. If not set, password is
+ * retrieved from the saved profile identified by the SSID. See
+ * {@link #setWifiSsid(WifiSsid)}.
+ *
+ * Note: If password and SSID is not set, secure ranging will use unauthenticated PASN.
+ *
+ * @param password password string
+ * @return a reference to this Builder
+ */
+ @NonNull
+ public Builder setPassword(@NonNull String password) {
+ Objects.requireNonNull(password, "Password must not be null");
+ this.mPassword = password;
+ return this;
+ }
+
+ /**
+ * Sets the Wi-Fi Service Set Identifier (SSID). This is used to get the saved profile to
+ * retrieve password if password is not set using {@link #setPassword(String)}.
+ *
+ * Note: If password and SSID is not set, secure ranging will use unauthenticated PASN.
+ *
+ * @param wifiSsid Wi-Fi Service Set Identifier (SSID)
+ * @return a reference to this Builder
+ */
+ @NonNull
+ public Builder setWifiSsid(@NonNull WifiSsid wifiSsid) {
+ Objects.requireNonNull(wifiSsid, "SSID must not be null");
+ this.mWifiSsid = wifiSsid;
+ return this;
+ }
+
+ /**
+ * Set PASN comeback cookie. PASN authentication allows the station to provide comeback
+ * cookie which was indicated in the {@link RangingResult} by the AP with a deferral time.
+ * <p>
+ * When an AP receives a large volume of initial PASN Authentication frames, it can use
+ * the comeback after field in the PASN Parameters element to indicate a deferral time
+ * and optionally provide a comeback cookie which is an opaque sequence of octets. Upon
+ * receiving this response, the ranging initiator (STA) must wait for the specified time
+ * before retrying secure authentication, presenting the received cookie to the AP. See
+ * {@link RangingResult#getPasnComebackCookie()} and
+ * {@link RangingResult#getPasnComebackAfterMillis()}.
+ *
+ * @param pasnComebackCookie an opaque sequence of octets
+ * @return a reference to this Builder
+ */
+ @NonNull
+ public Builder setPasnComebackCookie(@NonNull byte[] pasnComebackCookie) {
+ Objects.requireNonNull(pasnComebackCookie, "PASN comeback cookie must not be null");
+ if (pasnComebackCookie.length > 255 || pasnComebackCookie.length == 0) {
+ throw new IllegalArgumentException("Cookie with invalid length "
+ + pasnComebackCookie.length);
+ }
+ mPasnComebackCookie = pasnComebackCookie;
+ return this;
+ }
+
+ /**
+ * Builds a {@link PasnConfig} object.
+ */
+ @NonNull
+ public PasnConfig build() {
+ return new PasnConfig(this);
+ }
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof PasnConfig that)) return false;
+ return mBaseAkms == that.mBaseAkms && mCiphers == that.mCiphers && Objects.equals(
+ mPassword, that.mPassword) && Objects.equals(mWifiSsid, that.mWifiSsid)
+ && Arrays.equals(mPasnComebackCookie, that.mPasnComebackCookie);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = Objects.hash(mBaseAkms, mCiphers, mPassword, mWifiSsid);
+ result = 31 * result + Arrays.hashCode(mPasnComebackCookie);
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "PasnConfig{" + "mBaseAkms=" + mBaseAkms + ", mCiphers=" + mCiphers + ", mPassword='"
+ + mPassword + '\'' + ", mWifiSsid=" + mWifiSsid + ", mPasnComebackCookie="
+ + Arrays.toString(mPasnComebackCookie) + '}';
+ }
+}
diff --git a/framework/java/android/net/wifi/rtt/RangingRequest.java b/framework/java/android/net/wifi/rtt/RangingRequest.java
index 8360dc4..31c0715 100644
--- a/framework/java/android/net/wifi/rtt/RangingRequest.java
+++ b/framework/java/android/net/wifi/rtt/RangingRequest.java
@@ -17,6 +17,7 @@
package android.net.wifi.rtt;
import android.annotation.FlaggedApi;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
@@ -39,6 +40,8 @@
import com.android.modules.utils.build.SdkLevel;
import com.android.wifi.flags.Flags;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -62,6 +65,44 @@
private static final int MAX_RTT_BURST_SIZE = 31;
/**
+ * In this mode, the ranging is performed with all available responders in open mode. If a
+ * responder does not allow open mode ranging, the responder will be skipped from the
+ * ranging request.
+ *<p>
+ * Note: If {@link ScanResult#isRangingFrameProtectionRequired()} is {@code true}, then open
+ * mode ranging is not supported by the AP.
+ */
+ @FlaggedApi(Flags.FLAG_SECURE_RANGING)
+ public static final int SECURITY_MODE_OPEN = 0;
+
+ /**
+ * In this mode, secure ranging is enabled automatically for compatible responders,
+ * simplifying the user experience and requiring no configuration. If the secure ranging is not
+ * possible for any of the responders, open mode ranging is used instead as in
+ * {@link #SECURITY_MODE_OPEN}. This mode is backward compatible with existing applications.
+ *
+ * Note: This is the default mode
+ */
+ @FlaggedApi(Flags.FLAG_SECURE_RANGING)
+ public static final int SECURITY_MODE_OPPORTUNISTIC = 1;
+
+ /**
+ * To ensure maximum security, this mode only ranges with responders using PASN with base AKM
+ * (Authenticated). This necessitates an authenticated PASN handshake with a shared key
+ * between the initiator and responder. Consequently, all responders in the ranging request
+ * must support secure authentication. If not supported, the responder will be skipped from the
+ * ranging request.
+ */
+ @FlaggedApi(Flags.FLAG_SECURE_RANGING)
+ public static final int SECURITY_MODE_SECURE_AUTH = 2;
+
+ /** @hide */
+ @IntDef(prefix = {"SECURITY_MODE_"}, value = {SECURITY_MODE_OPEN, SECURITY_MODE_OPPORTUNISTIC,
+ SECURITY_MODE_SECURE_AUTH})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface SecurityMode {}
+
+ /**
* Returns the maximum number of peers to range which can be specified in a single {@code
* RangingRequest}. The limit applies no matter how the peers are added to the request, e.g.
* through {@link RangingRequest.Builder#addAccessPoint(ScanResult)} or
@@ -106,6 +147,9 @@
/** @hide */
public final int mRttBurstSize;
+ /** @hide */
+ public final int mSecurityMode;
+
/**
* List of {@link OuiKeyedData} providing vendor-specific configuration data.
*/
@@ -113,9 +157,10 @@
/** @hide */
private RangingRequest(List<ResponderConfig> rttPeers, int rttBurstSize,
- @NonNull List<OuiKeyedData> vendorData) {
+ @SecurityMode int securityMode, @NonNull List<OuiKeyedData> vendorData) {
mRttPeers = rttPeers;
mRttBurstSize = rttBurstSize;
+ mSecurityMode = securityMode;
mVendorData = new ArrayList<>(vendorData);
}
@@ -142,6 +187,16 @@
}
/**
+ * Returns security mode for the ranging request. See {@code SECURITY_MODE_*} for more details.
+ *
+ * @return security mode for the ranging request
+ */
+ @FlaggedApi(Flags.FLAG_SECURE_RANGING)
+ public @SecurityMode int getSecurityMode() {
+ return mSecurityMode;
+ }
+
+ /**
* Return the vendor-provided configuration data, if it exists. See also {@link
* Builder#setVendorData(List)}
*
@@ -168,6 +223,7 @@
public void writeToParcel(Parcel dest, int flags) {
dest.writeList(mRttPeers);
dest.writeInt(mRttBurstSize);
+ dest.writeInt(mSecurityMode);
dest.writeList(mVendorData);
}
@@ -179,7 +235,7 @@
@Override
public RangingRequest createFromParcel(Parcel in) {
- return new RangingRequest(in.readArrayList(null), in.readInt(),
+ return new RangingRequest(in.readArrayList(null), in.readInt(), in.readInt(),
ParcelUtil.readOuiKeyedDataList(in));
}
};
@@ -192,6 +248,7 @@
sj.add(rc.toString());
}
sj.add("mRttBurstSize=" + mRttBurstSize);
+ sj.add("mSecurityMode=" + mSecurityMode);
sj.add("mVendorData=" + mVendorData);
return sj.toString();
}
@@ -222,6 +279,7 @@
private List<ResponderConfig> mRttPeers = new ArrayList<>();
private int mRttBurstSize = DEFAULT_RTT_BURST_SIZE;
private @NonNull List<OuiKeyedData> mVendorData = Collections.emptyList();
+ private @SecurityMode int mSecurityMode = SECURITY_MODE_OPPORTUNISTIC;
/**
* Set the RTT Burst size for the ranging request.
@@ -524,11 +582,30 @@
}
/**
+ * Sets the overall security mode for ranging, determining if secure ranging is attempted
+ * with each responder and if fallback to unauthenticated secure ranging is permitted. The
+ * mode also permits retry with no security when secure ranging fails. If not set, default
+ * mode will be {@link #SECURITY_MODE_OPPORTUNISTIC}.
+ * <p>
+ * See {@code SECURITY_MODE_*} for different modes of operation.
+ *
+ * @param securityMode security mode for ranging
+ * @return The builder, to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
+ */
+ @FlaggedApi(Flags.FLAG_SECURE_RANGING)
+ @NonNull
+ public Builder setSecurityMode(@SecurityMode int securityMode) {
+ mSecurityMode = securityMode;
+ return this;
+ }
+
+
+ /**
* Build {@link RangingRequest} given the current configurations made on the
* builder.
*/
public RangingRequest build() {
- return new RangingRequest(mRttPeers, mRttBurstSize, mVendorData);
+ return new RangingRequest(mRttPeers, mRttBurstSize, mSecurityMode, mVendorData);
}
}
@@ -547,11 +624,12 @@
return mRttPeers.size() == lhs.mRttPeers.size()
&& mRttPeers.containsAll(lhs.mRttPeers)
&& mRttBurstSize == lhs.mRttBurstSize
+ && mSecurityMode == lhs.mSecurityMode
&& Objects.equals(mVendorData, lhs.mVendorData);
}
@Override
public int hashCode() {
- return Objects.hash(mRttPeers, mRttBurstSize, mVendorData);
+ return Objects.hash(mRttPeers, mRttBurstSize, mSecurityMode, mVendorData);
}
}
diff --git a/framework/java/android/net/wifi/rtt/RangingResult.java b/framework/java/android/net/wifi/rtt/RangingResult.java
index 6739291..604c879 100644
--- a/framework/java/android/net/wifi/rtt/RangingResult.java
+++ b/framework/java/android/net/wifi/rtt/RangingResult.java
@@ -19,6 +19,7 @@
import android.annotation.ElapsedRealtimeLong;
import android.annotation.FlaggedApi;
import android.annotation.IntDef;
+import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
@@ -32,6 +33,7 @@
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
+import android.util.Log;
import androidx.annotation.RequiresApi;
@@ -40,6 +42,7 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@@ -114,6 +117,12 @@
private final int mNumTxSpatialStreams;
private final int mNumRxSpatialStreams;
private List<OuiKeyedData> mVendorData;
+ private final boolean mIsRangingAuthenticated;
+ private final boolean mIsRangingFrameProtected;
+ private final boolean mIsSecureHeLtfEnabled;
+ private final int mSecureHeLtfProtocolVersion;
+ private final byte[] mPasnComebackCookie;
+ private final long mPasnComebackAfterMillis;
/**
* Builder class used to construct {@link RangingResult} objects.
@@ -143,6 +152,53 @@
private int mNumTxSpatialStreams = UNSPECIFIED;
private int mNumRxSpatialStreams = UNSPECIFIED;
private List<OuiKeyedData> mVendorData = Collections.emptyList();
+ private boolean mIsRangingAuthenticated;
+ private boolean mIsRangingFrameProtected;
+ private boolean mIsSecureHeLtfEnabled;
+ private int mSecureHeLtfProtocolVersion;
+ private byte[] mPasnComebackCookie = null;
+ private long mPasnComebackAfterMillis = UNSPECIFIED;
+
+ /**
+ * Constructs a Builder with default values (see {@link Builder}).
+ */
+ public Builder() {}
+
+ /**
+ * Constructs a Builder initialized from an existing {@link RangingResult} instance.
+ *
+ * @hide
+ */
+ public Builder(@NonNull RangingResult other) {
+ if (other == null) {
+ Log.e(TAG, "Cannot provide a null RangingResult");
+ return;
+ }
+
+ mStatus = other.mStatus;
+ mMac = other.mMac;
+ mPeerHandle = other.mPeerHandle;
+ mDistanceMm = other.mDistanceMm;
+ mDistanceStdDevMm = other.mDistanceStdDevMm;
+ mRssi = other.mRssi;
+ mNumAttemptedMeasurements = other.mNumAttemptedMeasurements;
+ mNumSuccessfulMeasurements = other.mNumSuccessfulMeasurements;
+ if (other.mLci != null) mLci = other.mLci.clone();
+ if (other.mLcr != null) mLcr = other.mLcr.clone();
+ mResponderLocation = new ResponderLocation(mLci, mLcr);
+ mTimestamp = other.mTimestamp;
+ mIs80211mcMeasurement = other.mIs80211mcMeasurement;
+ mFrequencyMHz = other.mFrequencyMHz;
+ mPacketBw = other.mPacketBw;
+ mIs80211azNtbMeasurement = other.mIs80211azNtbMeasurement;
+ mNtbMinMeasurementTime = other.mNtbMinMeasurementTime;
+ mNtbMaxMeasurementTime = other.mNtbMaxMeasurementTime;
+ mI2rTxLtfRepetitions = other.mI2rTxLtfRepetitions;
+ mR2iTxLtfRepetitions = other.mR2iTxLtfRepetitions;
+ mNumTxSpatialStreams = other.mNumTxSpatialStreams;
+ mNumRxSpatialStreams = other.mNumRxSpatialStreams;
+ mVendorData = new ArrayList<>(other.mVendorData);
+ }
/**
* Sets the Range result status.
@@ -496,6 +552,96 @@
}
/**
+ * Set whether mutual authentication is done for the ranging. Authentication of ranging
+ * enables frame protection also. See {@link #setRangingFrameProtected(boolean)}.
+ *
+ * @param isRangingAuthenticated true if ranging is mutually authenticated, otherwise false.
+ * @return The builder to facilitate chaining.
+ */
+ @NonNull
+ @FlaggedApi(Flags.FLAG_SECURE_RANGING)
+ public Builder setRangingAuthenticated(boolean isRangingAuthenticated) {
+ mIsRangingAuthenticated = isRangingAuthenticated;
+ return this;
+ }
+
+ /**
+ * Set whether ranging frames are protected. Frame protection provides both encryption and
+ * integrity protection to the ranging frames.
+ *
+ * @param isRangingFrameProtected true if ranging frames are protected, otherwise false.
+ * @return The builder to facilitate chaining.
+ */
+ @NonNull
+ @FlaggedApi(Flags.FLAG_SECURE_RANGING)
+ public Builder setRangingFrameProtected(boolean isRangingFrameProtected) {
+ mIsRangingFrameProtected = isRangingFrameProtected;
+ return this;
+ }
+
+ /**
+ * Set whether secure HE-LTF is used for this ranging.
+ *
+ * @param isSecureHeLtfEnabled true if secure HE-LTF is enabled, otherwise false.
+ * @return The builder to facilitate chaining.
+ */
+ @NonNull
+ @FlaggedApi(Flags.FLAG_SECURE_RANGING)
+ public Builder setSecureHeLtfEnabled(boolean isSecureHeLtfEnabled) {
+ mIsSecureHeLtfEnabled = isSecureHeLtfEnabled;
+ return this;
+ }
+
+ /**
+ * Set secure HE-LTF protocol version used for this ranging.
+ *
+ * The secure HE-LTF negotiation supports negotiation of the secure HE-LTF protocol version
+ * which allows a responder and an initiator to negotiate the highest mutually supported
+ * secure HE-LTF protocol version.
+ *
+ * Refer IEEE 802.11az-2022 spec, section 9.4.2.298 Ranging Parameters element.
+ *
+ * @param secureHeLtfProtocolVersion Secure HE-LTF protocol version.
+ * @return The builder to facilitate chaining.
+ */
+ @NonNull
+ @FlaggedApi(Flags.FLAG_SECURE_RANGING)
+ public Builder setSecureHeLtfProtocolVersion(
+ @IntRange(from = 0, to = 7) int secureHeLtfProtocolVersion) {
+ mSecureHeLtfProtocolVersion = secureHeLtfProtocolVersion;
+ return this;
+ }
+
+ /**
+ * Set comeback cookie. See {@link #getPasnComebackCookie()}. If not set, default value
+ * is null.
+ *
+ * @param pasnComebackCookie an opaque sequence of octets
+ * @return The builder to facilitate chaining.
+ */
+ @NonNull
+ @FlaggedApi(Flags.FLAG_SECURE_RANGING)
+ public Builder setPasnComebackCookie(@NonNull byte[] pasnComebackCookie) {
+ mPasnComebackCookie = pasnComebackCookie;
+ return this;
+ }
+
+ /**
+ * Set comeback after time. See {@link #getPasnComebackAfterMillis()}. If not set default
+ * value is {@link RangingResult#UNSPECIFIED}.
+ *
+ * @param comebackAfterMillis the ranging initiator (STA) must wait for the specified
+ * time before retrying secure ranging
+ * @return The builder to facilitate chaining.
+ */
+ @NonNull
+ @FlaggedApi(Flags.FLAG_SECURE_RANGING)
+ public Builder setPasnComebackAfterMillis(long comebackAfterMillis) {
+ mPasnComebackAfterMillis = comebackAfterMillis;
+ return this;
+ }
+
+ /**
* Build {@link RangingResult}
* @return an instance of {@link RangingResult}
*/
@@ -539,6 +685,12 @@
mNumRxSpatialStreams = builder.mNumRxSpatialStreams;
mNumTxSpatialStreams = builder.mNumTxSpatialStreams;
mVendorData = builder.mVendorData;
+ mIsRangingAuthenticated = builder.mIsRangingAuthenticated;
+ mIsRangingFrameProtected = builder.mIsRangingFrameProtected;
+ mIsSecureHeLtfEnabled = builder.mIsSecureHeLtfEnabled;
+ mSecureHeLtfProtocolVersion = builder.mSecureHeLtfProtocolVersion;
+ mPasnComebackCookie = builder.mPasnComebackCookie;
+ mPasnComebackAfterMillis = builder.mPasnComebackAfterMillis;
}
/**
@@ -904,6 +1056,76 @@
return mVendorData;
}
+ /**
+ * @return whether the ranging is authenticated or not.
+ *
+ * Refer IEEE 802.11az-2022 spec, section 12 Security.
+ */
+ @FlaggedApi(Flags.FLAG_SECURE_RANGING)
+ public boolean isRangingAuthenticated() {
+ return mIsRangingAuthenticated;
+ }
+
+ /**
+ * @return whether the ranging frames are protected or not.
+ *
+ * Refer IEEE 802.11az-2022 spec, section 12 Security.
+ */
+ @FlaggedApi(Flags.FLAG_SECURE_RANGING)
+ public boolean isRangingFrameProtected() {
+ return mIsRangingFrameProtected;
+ }
+
+ /**
+ * @return whether the secure HE-LTF is enabled or not.
+ *
+ * Refer IEEE 802.11az-2022 spec, section 9.4.2.298 Ranging Parameters element.
+ */
+ @FlaggedApi(Flags.FLAG_SECURE_RANGING)
+ public boolean isSecureHeLtfEnabled() {
+ return mIsSecureHeLtfEnabled;
+ }
+
+ /**
+ * Get Secure HE-LTF protocol version used.
+ *
+ * The secure HE-LTF negotiation supports negotiation of the secure HE-LTF protocol version
+ * which allows a responder and an initiator to negotiate the highest mutually supported
+ * secure HE-LTF protocol version.
+ *
+ * Refer IEEE 802.11az-2022 spec, section 9.4.2.298 Ranging Parameters element.
+ */
+ @FlaggedApi(Flags.FLAG_SECURE_RANGING)
+ @IntRange(from = 0, to = 7)
+ public int getSecureHeLtfProtocolVersion() {
+ return mSecureHeLtfProtocolVersion;
+ }
+
+ /**
+ * Get PASN comeback cookie. PASN authentication allows an AP to indicate the deferral time
+ * and optionally a Cookie. See {@link #getPasnComebackAfterMillis()}
+ * <p>
+ * When an AP receives a large volume of initial PASN Authentication frames, it can use
+ * the comeback after field in the PASN Parameters element to indicate a deferral time
+ * and optionally provide a comeback cookie which is an opaque sequence of octets. Upon
+ * receiving this response, the ranging initiator (STA) must wait for the specified time
+ * before retrying secure authentication, presenting the received cookie to the AP.
+ **/
+ @FlaggedApi(Flags.FLAG_SECURE_RANGING)
+ @Nullable
+ public byte[] getPasnComebackCookie() {
+ return mPasnComebackCookie;
+ }
+
+ /**
+ * Get Comeback after time in milliseconds. See {@link #getPasnComebackCookie()}. A value 0
+ * indicates the ranging request operation can be tried immediately with the cookie.
+ */
+ @FlaggedApi(Flags.FLAG_SECURE_RANGING)
+ public long getPasnComebackAfterMillis() {
+ return mPasnComebackAfterMillis;
+ }
+
@Override
public int describeContents() {
return 0;
@@ -1017,6 +1239,11 @@
.append(", numTxSpatialStreams=").append(mNumTxSpatialStreams)
.append(", numRxSpatialStreams=").append(mNumRxSpatialStreams)
.append(", vendorData=").append(mVendorData)
+ .append(", isRangingAuthenticated").append(mIsRangingAuthenticated)
+ .append(", isRangingFrameProtected").append(mIsRangingFrameProtected)
+ .append(", isSecureHeLtfEnabled").append(mIsSecureHeLtfEnabled)
+ .append(", pasnComebackCookie").append(Arrays.toString(mPasnComebackCookie))
+ .append(", pasnComebackAfterMillis").append(mPasnComebackAfterMillis)
.append("]").toString();
}
@@ -1050,7 +1277,13 @@
&& mR2iTxLtfRepetitions == lhs.mR2iTxLtfRepetitions
&& mNumTxSpatialStreams == lhs.mNumTxSpatialStreams
&& mNumRxSpatialStreams == lhs.mNumRxSpatialStreams
- && Objects.equals(mVendorData, lhs.mVendorData);
+ && Objects.equals(mVendorData, lhs.mVendorData)
+ && mIsRangingAuthenticated == lhs.mIsRangingAuthenticated
+ && mIsRangingFrameProtected == lhs.mIsRangingFrameProtected
+ && mIsSecureHeLtfEnabled == lhs.isSecureHeLtfEnabled()
+ && mPasnComebackAfterMillis == lhs.mPasnComebackAfterMillis
+ && Arrays.equals(mPasnComebackCookie, lhs.mPasnComebackCookie);
+
}
@Override
@@ -1060,6 +1293,8 @@
Arrays.hashCode(mLcr), mResponderLocation, mTimestamp, mIs80211mcMeasurement,
mFrequencyMHz, mPacketBw, mIs80211azNtbMeasurement, mNtbMinMeasurementTime,
mNtbMaxMeasurementTime, mI2rTxLtfRepetitions, mR2iTxLtfRepetitions,
- mNumTxSpatialStreams, mR2iTxLtfRepetitions, mVendorData);
+ mNumTxSpatialStreams, mR2iTxLtfRepetitions, mVendorData, mIsRangingAuthenticated,
+ mIsRangingFrameProtected, mIsSecureHeLtfEnabled, mPasnComebackAfterMillis,
+ Arrays.hashCode(mPasnComebackCookie));
}
}
diff --git a/framework/java/android/net/wifi/rtt/ResponderConfig.java b/framework/java/android/net/wifi/rtt/ResponderConfig.java
index 5db9290..a8fd2d5 100644
--- a/framework/java/android/net/wifi/rtt/ResponderConfig.java
+++ b/framework/java/android/net/wifi/rtt/ResponderConfig.java
@@ -264,6 +264,7 @@
private long mNtbMinMeasurementTime = DEFAULT_NTB_MIN_TIME_BETWEEN_MEASUREMENTS_MICROS;
private long mNtbMaxMeasurementTime = DEFAULT_NTB_MAX_TIME_BETWEEN_MEASUREMENTS_MICROS;
+ private final SecureRangingConfig mSecureRangingConfig;
/**
* Constructs Responder configuration from the builder
@@ -287,6 +288,7 @@
this.preamble = builder.mPreamble;
this.mNtbMinMeasurementTime = builder.mNtbMinMeasurementTime;
this.mNtbMaxMeasurementTime = builder.mNtbMaxMeasurementTime;
+ this.mSecureRangingConfig = builder.mSecureRangingConfig;
}
/**
@@ -332,6 +334,7 @@
this.supports80211azNtb = false;
this.mNtbMinMeasurementTime = DEFAULT_NTB_MIN_TIME_BETWEEN_MEASUREMENTS_MICROS;
this.mNtbMaxMeasurementTime = DEFAULT_NTB_MAX_TIME_BETWEEN_MEASUREMENTS_MICROS;
+ this.mSecureRangingConfig = null;
}
/**
@@ -372,6 +375,7 @@
this.supports80211azNtb = false;
this.mNtbMinMeasurementTime = DEFAULT_NTB_MIN_TIME_BETWEEN_MEASUREMENTS_MICROS;
this.mNtbMaxMeasurementTime = DEFAULT_NTB_MAX_TIME_BETWEEN_MEASUREMENTS_MICROS;
+ this.mSecureRangingConfig = null;
}
/**
@@ -416,6 +420,7 @@
this.supports80211azNtb = false;
this.mNtbMinMeasurementTime = DEFAULT_NTB_MIN_TIME_BETWEEN_MEASUREMENTS_MICROS;
this.mNtbMaxMeasurementTime = DEFAULT_NTB_MAX_TIME_BETWEEN_MEASUREMENTS_MICROS;
+ this.mSecureRangingConfig = null;
}
/**
@@ -475,7 +480,7 @@
}
}
- return new ResponderConfig.Builder()
+ Builder builder = new Builder()
.setMacAddress(macAddress)
.setResponderType(responderType)
.set80211mcSupported(supports80211mc)
@@ -484,10 +489,33 @@
.setFrequencyMhz(frequency)
.setCenterFreq0Mhz(centerFreq0)
.setCenterFreq1Mhz(centerFreq1)
- .setPreamble(preamble)
+ .setPreamble(preamble);
+
+ if (isSecureRangingResponder(scanResult)) {
+ builder.setSecureRangingConfig(getSecureRangingConfig(scanResult));
+ }
+
+ return builder.build();
+ }
+
+ private static boolean isSecureRangingResponder(ScanResult scanResult) {
+ return ((scanResult.capabilities != null) && (scanResult.capabilities.contains("PASN")));
+ }
+
+ private static SecureRangingConfig getSecureRangingConfig(ScanResult scanResult) {
+ PasnConfig.Builder pasnConfigBuilder = new PasnConfig.Builder(
+ PasnConfig.getBaseAkmsFromCapabilities(scanResult.capabilities),
+ PasnConfig.getCiphersFromCapabilities(scanResult.capabilities));
+ if (scanResult.getWifiSsid() != null) {
+ pasnConfigBuilder.setWifiSsid(scanResult.getWifiSsid());
+ }
+ return new SecureRangingConfig.Builder(pasnConfigBuilder.build())
+ .setSecureHeLtfEnabled(scanResult.isSecureHeLtfSupported())
+ .setRangingFrameProtectionEnabled(true)
.build();
}
+
/**
* Creates a Responder configuration from a MAC address corresponding to a Wi-Fi Aware
* Responder. The Responder parameters are set to defaults.
@@ -690,6 +718,15 @@
}
/**
+ * Get secure ranging configuration.
+ * @return Secure ranging configuration. Returns null for non-secure ranging configuration.
+ */
+ @Nullable
+ @FlaggedApi(Flags.FLAG_SECURE_RANGING)
+ public SecureRangingConfig getSecureRangingConfig() {
+ return mSecureRangingConfig;
+ }
+ /**
* Builder class used to construct {@link ResponderConfig} objects.
*/
public static final class Builder {
@@ -705,6 +742,8 @@
private @PreambleType int mPreamble = PREAMBLE_LEGACY;
private long mNtbMinMeasurementTime = DEFAULT_NTB_MIN_TIME_BETWEEN_MEASUREMENTS_MICROS;
private long mNtbMaxMeasurementTime = DEFAULT_NTB_MAX_TIME_BETWEEN_MEASUREMENTS_MICROS;
+ private SecureRangingConfig mSecureRangingConfig = null;
+
/**
* Sets the Responder MAC Address.
@@ -909,6 +948,34 @@
}
/**
+ * Set secure ranging configuration. See {@link SecureRangingConfig} for more details.
+ * <p>
+ * Note: Secure ranging will get enabled only if the device and responder support. For
+ * device support see {@link WifiRttManager#getRttCharacteristics()}. Following capabilities
+ * needs to be enabled,
+ * <ul>
+ * <li>{@link WifiRttManager#CHARACTERISTICS_KEY_BOOLEAN_NTB_INITIATOR}
+ * <li>{@link WifiRttManager#CHARACTERISTICS_KEY_BOOLEAN_SECURE_HE_LTF_SUPPORTED} and/or
+ * <li>{@link WifiRttManager#CHARACTERISTICS_KEY_BOOLEAN_RANGING_FRAME_PROTECTION_SUPPORTED}
+ * </ul>
+ * For the responder support (from scan result),
+ * <ul>
+ * <li> {@link ScanResult#capabilities} string contains PASN and optionally a base AKM
+ * <li> {@link ScanResult#isSecureHeLtfSupported()}
+ * <li> {@link ScanResult#isRangingFrameProtectionRequired()}
+ * </ul>
+ * @param secureRangingConfig Secure ranging configuration
+ * @return the builder to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
+ */
+ @NonNull
+ @FlaggedApi(Flags.FLAG_SECURE_RANGING)
+ public Builder setSecureRangingConfig(@NonNull SecureRangingConfig secureRangingConfig) {
+ Objects.requireNonNull(secureRangingConfig, "secureRangingConfig cannot be null");
+ mSecureRangingConfig = secureRangingConfig;
+ return this;
+ }
+
+ /**
* Build {@link ResponderConfig} given the current configurations made on the builder.
* @return an instance of {@link ResponderConfig}
*/
@@ -1029,7 +1096,7 @@
@Override
public String toString() {
- return new StringBuffer("ResponderConfig: macAddress=").append(macAddress)
+ StringBuffer sb = new StringBuffer("ResponderConfig: macAddress=").append(macAddress)
.append(", peerHandle=").append(peerHandle == null ? "<null>" : peerHandle.peerId)
.append(", responderType=").append(responderType)
.append(", supports80211mc=").append(supports80211mc)
@@ -1039,9 +1106,15 @@
.append(", centerFreq1=").append(centerFreq1)
.append(", preamble=").append(preamble)
.append(", supports80211azNtb=").append(supports80211azNtb)
- .append(", mNtbMinMeasurementTime ").append(mNtbMinMeasurementTime)
- .append(", mNtbMaxMeasurementTime ").append(mNtbMaxMeasurementTime)
- .toString();
+ .append(", mNtbMinMeasurementTime=").append(mNtbMinMeasurementTime)
+ .append(", mNtbMaxMeasurementTime=").append(mNtbMaxMeasurementTime);
+
+ if (mSecureRangingConfig != null) {
+ sb.append(", mSecureRangingConfig=").append(mSecureRangingConfig);
+ }
+
+ return sb.toString();
+
}
/**
@@ -1052,7 +1125,7 @@
*
* @hide
*/
- static int translateFromScanResultToLocalChannelWidth(
+ public static int translateFromScanResultToLocalChannelWidth(
@WifiAnnotations.ChannelWidth int scanResultChannelWidth) {
switch (scanResultChannelWidth) {
case ScanResult.CHANNEL_WIDTH_20MHZ:
@@ -1081,7 +1154,8 @@
*
* @hide
*/
- static int translateFromLocalToScanResultChannelWidth(@ChannelWidth int localChannelWidth) {
+ public static int translateFromLocalToScanResultChannelWidth(
+ @ChannelWidth int localChannelWidth) {
switch (localChannelWidth) {
case CHANNEL_WIDTH_20MHZ:
return ScanResult.CHANNEL_WIDTH_20MHZ;
@@ -1109,7 +1183,7 @@
*
* @hide
*/
- static int translateFromScanResultToLocalPreamble(
+ public static int translateFromScanResultToLocalPreamble(
@WifiAnnotations.PreambleType int scanResultPreamble) {
switch (scanResultPreamble) {
case ScanResult.PREAMBLE_LEGACY:
@@ -1136,7 +1210,7 @@
*
* @hide
*/
- static int translateFromLocalToScanResultPreamble(@PreambleType int localPreamble) {
+ public static int translateFromLocalToScanResultPreamble(@PreambleType int localPreamble) {
switch (localPreamble) {
case PREAMBLE_LEGACY:
return ScanResult.PREAMBLE_LEGACY;
diff --git a/framework/java/android/net/wifi/rtt/SecureRangingConfig.java b/framework/java/android/net/wifi/rtt/SecureRangingConfig.java
new file mode 100644
index 0000000..68a47d3
--- /dev/null
+++ b/framework/java/android/net/wifi/rtt/SecureRangingConfig.java
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.rtt;
+
+import android.annotation.FlaggedApi;
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.modules.utils.build.SdkLevel;
+import com.android.wifi.flags.Flags;
+
+import java.util.Objects;
+
+/**
+ * Secure ranging configuration.
+ * Refer IEEE Std 802.11az-2022, section 12. Security.
+ */
+@FlaggedApi(Flags.FLAG_SECURE_RANGING)
+public final class SecureRangingConfig implements Parcelable {
+ private final boolean mEnableSecureHeLtf;
+ private final boolean mEnableRangingFrameProtection;
+ private final PasnConfig mPasnConfig;
+
+
+ private SecureRangingConfig(boolean enableSecureHeLtf, boolean enableRangingFrameProtection,
+ @NonNull PasnConfig pasnConfig) {
+ Objects.requireNonNull(pasnConfig, "pasnConfig cannot be null");
+ mEnableSecureHeLtf = enableSecureHeLtf;
+ mEnableRangingFrameProtection = enableRangingFrameProtection;
+ mPasnConfig = pasnConfig;
+ }
+
+ private SecureRangingConfig(@NonNull Parcel in) {
+ mEnableSecureHeLtf = in.readByte() != 0;
+ mEnableRangingFrameProtection = in.readByte() != 0;
+ mPasnConfig = (SdkLevel.isAtLeastT()) ? in.readParcelable(PasnConfig.class.getClassLoader(),
+ PasnConfig.class) : in.readParcelable(PasnConfig.class.getClassLoader());
+ }
+
+ @FlaggedApi(Flags.FLAG_SECURE_RANGING)
+ public static final @NonNull Creator<SecureRangingConfig> CREATOR =
+ new Creator<SecureRangingConfig>() {
+ @Override
+ public SecureRangingConfig createFromParcel(Parcel in) {
+ return new SecureRangingConfig(in);
+ }
+
+ @Override
+ public SecureRangingConfig[] newArray(int size) {
+ return new SecureRangingConfig[size];
+ }
+ };
+
+ private SecureRangingConfig(Builder builder) {
+ mEnableSecureHeLtf = builder.mEnableSecureHeLtf;
+ mEnableRangingFrameProtection = builder.mEnableRangingFrameProtection;
+ mPasnConfig = builder.mPasnConfig;
+ }
+
+ /**
+ * Returns whether secure HE-LTF is enabled or not.
+ */
+ @FlaggedApi(Flags.FLAG_SECURE_RANGING)
+ public boolean isSecureHeLtfEnabled() {
+ return mEnableSecureHeLtf;
+ }
+
+ /**
+ * Returns whether ranging frame protection is enabled or not.
+ */
+ @FlaggedApi(Flags.FLAG_SECURE_RANGING)
+ public boolean isRangingFrameProtectionEnabled() {
+ return mEnableRangingFrameProtection;
+ }
+
+ /**
+ * Returns Pre-association security negotiation (PASN) configuration used for secure
+ * ranging.
+ *
+ * @return {@link PasnConfig} object.
+ */
+ @FlaggedApi(Flags.FLAG_SECURE_RANGING)
+ @NonNull
+ public PasnConfig getPasnConfig() {
+ return mPasnConfig;
+ }
+
+ @FlaggedApi(Flags.FLAG_SECURE_RANGING)
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @FlaggedApi(Flags.FLAG_SECURE_RANGING)
+ @Override
+ public void writeToParcel(@androidx.annotation.NonNull Parcel dest, int flags) {
+ dest.writeByte((byte) (mEnableSecureHeLtf ? 1 : 0));
+ dest.writeByte((byte) (mEnableRangingFrameProtection ? 1 : 0));
+ dest.writeParcelable(mPasnConfig, flags);
+ }
+
+ @FlaggedApi(Flags.FLAG_SECURE_RANGING)
+ @Override
+ public String toString() {
+ return "SecureRangingConfig{" + "mEnableSecureHeLtf=" + mEnableSecureHeLtf
+ + ", mEnableRangingProtection=" + mEnableRangingFrameProtection + ", mPasnConfig="
+ + mPasnConfig + '}';
+ }
+
+ @FlaggedApi(Flags.FLAG_SECURE_RANGING)
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof SecureRangingConfig that)) return false;
+ return mEnableSecureHeLtf == that.mEnableSecureHeLtf
+ && mEnableRangingFrameProtection == that.mEnableRangingFrameProtection
+ && Objects.equals(mPasnConfig, that.mPasnConfig);
+ }
+
+ @FlaggedApi(Flags.FLAG_SECURE_RANGING)
+ @Override
+ public int hashCode() {
+ return Objects.hash(mEnableSecureHeLtf, mEnableRangingFrameProtection, mPasnConfig);
+ }
+
+ /**
+ * Builder for {@link SecureRangingConfig}
+ */
+ @FlaggedApi(Flags.FLAG_SECURE_RANGING)
+ public static final class Builder {
+ private boolean mEnableSecureHeLtf = true;
+ private boolean mEnableRangingFrameProtection = true;
+ private final PasnConfig mPasnConfig;
+
+ /**
+ * Builder constructor.
+ *
+ * @param pasnConfig PASN configuration
+ */
+ @FlaggedApi(Flags.FLAG_SECURE_RANGING)
+ public Builder(@NonNull PasnConfig pasnConfig) {
+ Objects.requireNonNull(pasnConfig, "pasnConfig must not be null");
+ mPasnConfig = pasnConfig;
+ }
+
+ /**
+ * Enable or disable secure HE-LTF and returns a reference to this Builder enabling
+ * method chaining. If not set, secure HE-LTF is enabled.
+ *
+ * @param enableSecureHeLtf the {@code enableSecureHeLtf} to set
+ * @return a reference to this Builder
+ */
+ @FlaggedApi(Flags.FLAG_SECURE_RANGING)
+ @NonNull
+ public Builder setSecureHeLtfEnabled(boolean enableSecureHeLtf) {
+ this.mEnableSecureHeLtf = enableSecureHeLtf;
+ return this;
+ }
+
+ /**
+ * Enable or disable ranging frame protection and returns a reference to this Builder
+ * enabling method chaining. If not set, ranging frame protection is enabled.
+ *
+ * @param enableRangingFrameProtection the {@code enableRangingFrameProtection} to set
+ * @return a reference to this Builder
+ */
+ @FlaggedApi(Flags.FLAG_SECURE_RANGING)
+ @NonNull
+ public Builder setRangingFrameProtectionEnabled(boolean enableRangingFrameProtection) {
+ this.mEnableRangingFrameProtection = enableRangingFrameProtection;
+ return this;
+ }
+
+ /**
+ * Returns a {@code SecureRangingConfig} built from the parameters previously set.
+ *
+ * @return a {@code SecureRangingConfig} built with parameters of this
+ * {@code SecureRangingConfig.Builder}
+ */
+ @FlaggedApi(Flags.FLAG_SECURE_RANGING)
+ @NonNull
+ public SecureRangingConfig build() {
+ return new SecureRangingConfig(this);
+ }
+ }
+}
diff --git a/framework/java/android/net/wifi/rtt/WifiRttManager.java b/framework/java/android/net/wifi/rtt/WifiRttManager.java
index f86eaa4..515e5b0 100644
--- a/framework/java/android/net/wifi/rtt/WifiRttManager.java
+++ b/framework/java/android/net/wifi/rtt/WifiRttManager.java
@@ -116,6 +116,31 @@
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
public static final String CHARACTERISTICS_KEY_BOOLEAN_NTB_INITIATOR = "key_ntb_initiator";
+ /**
+ * Bundle key to access if device supports secure HE-LTF (High Efficiency Long Training Field).
+ * Secure HE-LTF is a critical security enhancement in the IEEE 802.11az standard that aims to
+ * protect ranging measurements from spoofing and manipulation.
+ */
+ @FlaggedApi(Flags.FLAG_SECURE_RANGING)
+ public static final String CHARACTERISTICS_KEY_BOOLEAN_SECURE_HE_LTF_SUPPORTED =
+ "key_secure_he_ltf_supported";
+
+ /**
+ * Bundle key to access if device supports ranging frame protection. IEEE 802.11az introduces
+ * Protected Management Frames for FTM (Fine Timing Measurement), adding a layer of encryption
+ * and integrity protection to these frames.
+ */
+ @FlaggedApi(Flags.FLAG_SECURE_RANGING)
+ public static final String CHARACTERISTICS_KEY_BOOLEAN_RANGING_FRAME_PROTECTION_SUPPORTED =
+ "key_rnm_mfp_supported";
+
+ /**
+ * Bundle key to access the maximum supported secure HE-LTF protocol version.
+ */
+ @FlaggedApi(Flags.FLAG_SECURE_RANGING)
+ public static final String CHARACTERISTICS_KEY_INT_MAX_SUPPORTED_SECURE_HE_LTF_PROTO_VERSION =
+ "key_max_supported_secure_he_ltf_proto_ver";
+
/** @hide */
@StringDef(prefix = { "CHARACTERISTICS_KEY_"}, value = {
CHARACTERISTICS_KEY_BOOLEAN_ONE_SIDED_RTT,
@@ -123,6 +148,9 @@
CHARACTERISTICS_KEY_BOOLEAN_LCR,
CHARACTERISTICS_KEY_BOOLEAN_STA_RESPONDER,
CHARACTERISTICS_KEY_BOOLEAN_NTB_INITIATOR,
+ CHARACTERISTICS_KEY_BOOLEAN_SECURE_HE_LTF_SUPPORTED,
+ CHARACTERISTICS_KEY_BOOLEAN_RANGING_FRAME_PROTECTION_SUPPORTED,
+ CHARACTERISTICS_KEY_INT_MAX_SUPPORTED_SECURE_HE_LTF_PROTO_VERSION
})
@Retention(RetentionPolicy.SOURCE)
public @interface RttCharacteristicsKey {}
diff --git a/framework/java/android/net/wifi/usd/Characteristics.java b/framework/java/android/net/wifi/usd/Characteristics.java
new file mode 100644
index 0000000..3467eee
--- /dev/null
+++ b/framework/java/android/net/wifi/usd/Characteristics.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.usd;
+
+import android.annotation.FlaggedApi;
+import android.annotation.SystemApi;
+import android.net.wifi.flags.Flags;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import androidx.annotation.NonNull;
+
+import java.util.List;
+import java.util.concurrent.Executor;
+import java.util.function.Consumer;
+
+/**
+ * The characteristics of the USD implementation.
+ *
+ * @hide
+ */
+@SystemApi
+@FlaggedApi(Flags.FLAG_USD)
+public final class Characteristics implements Parcelable {
+ private final Bundle mCharacteristics;
+ /** @hide */
+ public static final String KEY_MAX_SERVICE_NAME_LENGTH = "key_max_service_name_length";
+ /** @hide */
+ public static final String KEY_MAX_SERVICE_SPECIFIC_INFO_LENGTH =
+ "key_max_service_specific_info_length";
+ /** @hide */
+ public static final String KEY_MAX_MATCH_FILTER_LENGTH = "key_max_match_filter_length";
+ /** @hide */
+ public static final String KEY_MAX_NUM_PUBLISH_SESSIONS = "key_max_num_publish_session";
+ /** @hide */
+ public static final String KEY_MAX_NUM_SUBSCRIBE_SESSIONS = "key_max_num_subscribe_session";
+
+
+ /** @hide : should not be created by apps */
+ public Characteristics(Bundle characteristics) {
+ mCharacteristics = characteristics;
+ }
+
+ private Characteristics(@NonNull Parcel in) {
+ mCharacteristics = in.readBundle(getClass().getClassLoader());
+ }
+
+ @NonNull
+ public static final Creator<Characteristics> CREATOR = new Creator<Characteristics>() {
+ @Override
+ public Characteristics createFromParcel(Parcel in) {
+ return new Characteristics(in);
+ }
+
+ @Override
+ public Characteristics[] newArray(int size) {
+ return new Characteristics[size];
+ }
+ };
+
+ /**
+ * Returns the maximum string length that can be used to specify a USD service name.
+ *
+ * @return A positive integer, maximum string length of USD service name.
+ */
+ public int getMaxServiceNameLength() {
+ return mCharacteristics.getInt(KEY_MAX_SERVICE_NAME_LENGTH);
+ }
+
+ /**
+ * Returns the maximum length of byte array that can be used to specify a service specific
+ * information field: the arbitrary load used in discovery or the message length of USD
+ * message exchange. Restricts the parameters of the
+ * {@link PublishConfig.Builder#setServiceSpecificInfo(byte[])},
+ * {@link SubscribeConfig.Builder#setServiceSpecificInfo(byte[])},
+ * {@link PublishSession#sendMessage(int, byte[], Executor, Consumer)} and
+ * {@link SubscribeSession#sendMessage(int, byte[], Executor, Consumer)}
+ * variants.
+ *
+ * @return A positive integer, maximum length of byte array for USD messaging.
+ */
+ public int getMaxServiceSpecificInfoLength() {
+ return mCharacteristics.getInt(KEY_MAX_SERVICE_SPECIFIC_INFO_LENGTH);
+ }
+
+ /**
+ * Returns the maximum length of byte array that can be used to specify a USD match filter.
+ * Restricts the parameters of the
+ * {@link PublishConfig.Builder#setTxMatchFilter(List)},
+ * {@link PublishConfig.Builder#setRxMatchFilter(List)},
+ * {@link SubscribeConfig.Builder#setTxMatchFilter(List)} and
+ * {@link SubscribeConfig.Builder#setRxMatchFilter(List)}
+ *
+ * @return A positive integer, maximum length of byte array for USD discovery match filter.
+ */
+ public int getMaxMatchFilterLength() {
+ return mCharacteristics.getInt(KEY_MAX_MATCH_FILTER_LENGTH);
+ }
+
+ /**
+ * Returns the maximum number of publish sessions supported by USD
+ *
+ * @return A positive integer
+ */
+ public int getMaxNumberOfPublishSessions() {
+ return mCharacteristics.getInt(KEY_MAX_NUM_PUBLISH_SESSIONS);
+ }
+
+ /**
+ * Returns the maximum number of subscribe sessions supported by USD
+ *
+ * @return A positive integer
+ */
+ public int getMaxNumberOfSubscribeSessions() {
+ return mCharacteristics.getInt(KEY_MAX_NUM_SUBSCRIBE_SESSIONS);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ /**
+ * Flatten this object in to a Parcel.
+ *
+ * @param dest The Parcel in which the object should be written.
+ * @param flags Additional flags about how the object should be written.
+ * May be 0 or {@link #PARCELABLE_WRITE_RETURN_VALUE}.
+ */
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeBundle(mCharacteristics);
+ }
+}
diff --git a/framework/java/android/net/wifi/usd/Config.java b/framework/java/android/net/wifi/usd/Config.java
new file mode 100644
index 0000000..be358fa
--- /dev/null
+++ b/framework/java/android/net/wifi/usd/Config.java
@@ -0,0 +1,279 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.usd;
+
+import android.annotation.FlaggedApi;
+import android.annotation.IntDef;
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.net.wifi.aware.TlvBufferUtils;
+import android.net.wifi.flags.Flags;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * USD configuration for publish and subscribe operation. This is the base class and not intended
+ * to be created directly.
+ *
+ * @hide
+ */
+@SystemApi
+@FlaggedApi(Flags.FLAG_USD)
+public abstract class Config {
+ /** @hide */
+ public static final int MAX_NUM_OF_OPERATING_FREQUENCIES = 32;
+
+ /**
+ * Transmission type.
+ *
+ * @hide
+ */
+ @IntDef({TRANSMISSION_TYPE_UNICAST, TRANSMISSION_TYPE_MULTICAST})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface TransmissionType {
+ }
+
+ /**
+ * A unicast transmission sends data from one device to a single, specific destination device.
+ */
+ public static final int TRANSMISSION_TYPE_UNICAST = 0;
+
+ /**
+ * A multicast transmission sends data from one device to a group of devices on the network
+ * simultaneously.
+ */
+ public static final int TRANSMISSION_TYPE_MULTICAST = 1;
+
+ /**
+ * Subscribe type.
+ *
+ * @hide
+ */
+ @IntDef({SUBSCRIBE_TYPE_PASSIVE, SUBSCRIBE_TYPE_ACTIVE})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface SubscribeType {
+ }
+
+ /**
+ * Defines a passive subscribe session - a subscribe session where subscribe packets are not
+ * transmitted over-the-air and the device listens and matches to received publish packets.
+ */
+ public static final int SUBSCRIBE_TYPE_PASSIVE = 0;
+
+ /**
+ * Defines an active subscribe session - a subscribe session where subscribe packets are
+ * transmitted over-the-air.
+ */
+ public static final int SUBSCRIBE_TYPE_ACTIVE = 1;
+
+ /**
+ * Service Protocol Type.
+ *
+ * @hide
+ */
+ @IntDef({SERVICE_PROTO_TYPE_GENERIC, SERVICE_PROTO_TYPE_CSA_MATTER})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ServiceProtoType {
+ }
+
+ /**
+ * Generic type.
+ */
+ public static final int SERVICE_PROTO_TYPE_GENERIC = 0;
+
+ /**
+ * CSA (Connectivity Standards Alliance) Matter.
+ * Note: CSA Matter is an open-source standard for smart home technology that allows devices to
+ * work with any Matter-certified ecosystem.
+ */
+ public static final int SERVICE_PROTO_TYPE_CSA_MATTER = 1;
+
+ private final byte[] mServiceName;
+ private final int mTtlSeconds;
+ @ServiceProtoType
+ private final int mServiceProtoType;
+ private final byte[] mTxMatchFilterTlv;
+ private final byte[] mRxMatchFilterTlv;
+ private final byte[] mServiceSpecificInfo;
+ private final int[] mOperatingFrequencies;
+
+ /**
+ * @hide
+ */
+ public Config(@NonNull byte[] serviceName, int ttlSeconds, int serviceProtoType,
+ @Nullable byte[] txMatchFilterTlv, @Nullable byte[] rxMatchFilterTlv,
+ @Nullable byte[] serviceSpecificInfo, @Nullable int[] operatingFrequencies) {
+ mServiceName = serviceName;
+ mTtlSeconds = ttlSeconds;
+ mServiceProtoType = serviceProtoType;
+ mTxMatchFilterTlv = txMatchFilterTlv;
+ mRxMatchFilterTlv = rxMatchFilterTlv;
+ mServiceSpecificInfo = serviceSpecificInfo;
+ mOperatingFrequencies = operatingFrequencies;
+ }
+
+ /**
+ * Gets the service name of the USD session.
+ * <p>
+ * The Service Name is a UTF-8 encoded string from 1 to 255 bytes in length.
+ * The only acceptable single-byte UTF-8 symbols for a Service Name are alphanumeric
+ * values (A-Z, a-z, 0-9), the hyphen ('-'), the period ('.') and the underscore ('_'). All
+ * valid multi-byte UTF-8 characters are acceptable in a Service Name.
+ *
+ * @return service name
+ */
+ @NonNull
+ public byte[] getServiceName() {
+ return mServiceName;
+ }
+
+ /**
+ * Gets the time interval (in seconds) a USD session will be alive. When the TTL is reached the
+ * session will be terminated with an event.
+ *
+ * @return ttl value in seconds
+ */
+ @IntRange(from = 0)
+ public int getTtlSeconds() {
+ return mTtlSeconds;
+ }
+
+ /**
+ * Get the Service protocol type for the USD session.
+ *
+ * @return service protocol type as defined in {@code SERVICE_PROTOCOL_TYPE_*}
+ */
+ @ServiceProtoType
+ public int getServiceProtoType() {
+ return mServiceProtoType;
+ }
+
+ /**
+ * Gets the Tx filter which is an ordered sequence of (length, value) pairs to be included in
+ * the USD discovery frame.
+ *
+ * @return tx match filter or empty list
+ */
+ @NonNull
+ public List<byte[]> getTxMatchFilter() {
+ return new TlvBufferUtils.TlvIterable(0, 1, mTxMatchFilterTlv).toList();
+ }
+
+ /**
+ * @return tx match filter in TLV format
+ * @hide
+ */
+ @Nullable
+ public byte[] getTxMatchFilterTlv() {
+ return mTxMatchFilterTlv;
+ }
+
+ /**
+ * Gets the Rx match filter, which is an ordered sequence of (length, value) pairs that specify
+ * further the response conditions beyond the service name used to filter subscribe messages.
+ *
+ * @return rx match filter or empty list
+ */
+ @NonNull
+ public List<byte[]> getRxMatchFilter() {
+ return new TlvBufferUtils.TlvIterable(0, 1, mRxMatchFilterTlv).toList();
+ }
+
+ /**
+ * @return receive match filter in TLV format.
+ * @hide
+ */
+ @Nullable
+ public byte[] getRxMatchFilterTlv() {
+ return mRxMatchFilterTlv;
+ }
+
+ /**
+ * Get the service specific information set for the USD session.
+ *
+ * @return byte array or null
+ */
+ @Nullable
+ public byte[] getServiceSpecificInfo() {
+ return mServiceSpecificInfo;
+ }
+
+ /**
+ * Get the frequencies where the USD session operates if overridden by {@code
+ * setOperatingFrequenciesMhz(int[])}. If null, the application has not set the operating
+ * frequencies using {@link PublishConfig.Builder#setOperatingFrequenciesMhz(int[])} for the
+ * publisher or {@link SubscribeConfig.Builder#setOperatingFrequenciesMhz(int[])} for the
+ * subscriber.
+ *
+ * <p>If the operating frequencies are not set the default behavior for the publisher and
+ * subscriber is,
+ * <ul>
+ * <li>The publisher defaults to channel 6 (in the 2.4 GHz band) and a list of allowed channels
+ * in the 2.4 GHz and 5 GHz bands for multichannel publishing. Publisher may prioritize the
+ * channel with Access Points having best RSSI.
+ * <li>The subscriber defaults to either channel 6 (in the 2.4 Ghz band) or Station channel or
+ * pick a channel from
+ * {@link SubscribeConfig.Builder#setRecommendedOperatingFrequenciesMhz(int[])} in given order
+ * of preference.
+ * </ul>
+ *
+ * @return an array of frequencies or null
+ */
+ @Nullable
+ public int[] getOperatingFrequenciesMhz() {
+ return mOperatingFrequencies;
+ }
+
+ @Override
+ public String toString() {
+ return "Config{" + "mServiceName=" + Arrays.toString(mServiceName) + ", mTtlSeconds="
+ + mTtlSeconds + ", mServiceProtoType=" + mServiceProtoType + ", mTxMatchFilterTlv="
+ + Arrays.toString(mTxMatchFilterTlv) + ", mRxMatchFilterTlv=" + Arrays.toString(
+ mRxMatchFilterTlv) + ", mServiceSpecificInfo=" + Arrays.toString(
+ mServiceSpecificInfo) + ", mOperatingFrequencies=" + Arrays.toString(
+ mOperatingFrequencies) + '}';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof Config config)) return false;
+ return mTtlSeconds == config.mTtlSeconds && mServiceProtoType == config.mServiceProtoType
+ && Arrays.equals(mServiceName, config.mServiceName)
+ && Arrays.equals(mTxMatchFilterTlv, config.mTxMatchFilterTlv)
+ && Arrays.equals(mRxMatchFilterTlv, config.mRxMatchFilterTlv)
+ && Arrays.equals(mServiceSpecificInfo, config.mServiceSpecificInfo)
+ && Arrays.equals(mOperatingFrequencies, config.mOperatingFrequencies);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = Objects.hash(mTtlSeconds, mServiceProtoType);
+ result = 31 * result + Arrays.hashCode(mServiceName);
+ result = 31 * result + Arrays.hashCode(mTxMatchFilterTlv);
+ result = 31 * result + Arrays.hashCode(mRxMatchFilterTlv);
+ result = 31 * result + Arrays.hashCode(mServiceSpecificInfo);
+ result = 31 * result + Arrays.hashCode(mOperatingFrequencies);
+ return result;
+ }
+}
diff --git a/framework/java/android/net/wifi/usd/DiscoveryResult.java b/framework/java/android/net/wifi/usd/DiscoveryResult.java
new file mode 100644
index 0000000..48ecbbe
--- /dev/null
+++ b/framework/java/android/net/wifi/usd/DiscoveryResult.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.usd;
+
+import android.annotation.FlaggedApi;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.net.wifi.flags.Flags;
+
+/**
+ * A class providing information about a USD discovery session with a specific peer.
+ *
+ * @hide
+ */
+@SystemApi
+@FlaggedApi(Flags.FLAG_USD)
+public class DiscoveryResult {
+ private final int mPeerId;
+ private final byte[] mServiceSpecificInfo;
+ @Config.ServiceProtoType
+ private final int mServiceProtoType;
+ private final boolean mIsFsdEnabled;
+
+ private DiscoveryResult(Builder builder) {
+ mPeerId = builder.mPeerId;
+ mServiceSpecificInfo = builder.mServiceSpecificInfo;
+ mServiceProtoType = builder.mServiceProtoType;
+ mIsFsdEnabled = builder.mIsFsdEnabled;
+ }
+
+ /**
+ * Get the peer id.
+ */
+ public int getPeerId() {
+ return mPeerId;
+ }
+
+ /**
+ * Get the service specific info from the peer. If null, service discovery is without service
+ * specific info.
+ */
+ @Nullable
+ public byte[] getServiceSpecificInfo() {
+ return mServiceSpecificInfo;
+ }
+
+ /**
+ * Get service specific protocol type {@code (SERVICE_PROTO_TYPE_*)}.
+ */
+ @Config.ServiceProtoType
+ public int getServiceProtoType() {
+ return mServiceProtoType;
+ }
+
+ /**
+ * Return whether Further Service Discovery (FSD) is enabled or not.
+ */
+ public boolean isFsdEnabled() {
+ return mIsFsdEnabled;
+ }
+
+ /**
+ * {@code DiscoveryResult} builder static inner class.
+ */
+ @FlaggedApi(Flags.FLAG_USD)
+ public static final class Builder {
+ private final int mPeerId;
+ private byte[] mServiceSpecificInfo;
+ private int mServiceProtoType;
+ private boolean mIsFsdEnabled;
+
+ /**
+ * Builder constructor.
+ *
+ * @param peerId an id of the peer
+ */
+ public Builder(int peerId) {
+ mPeerId = peerId;
+ }
+
+
+ /**
+ * Sets the service specific information and returns a reference to this Builder enabling
+ * method chaining.
+ *
+ * @param serviceSpecificInfo the {@code serviceSpecificInfo} to set
+ * @return a reference to this Builder
+ */
+ @NonNull
+ public Builder setServiceSpecificInfo(@NonNull byte[] serviceSpecificInfo) {
+ this.mServiceSpecificInfo = serviceSpecificInfo;
+ return this;
+ }
+
+ /**
+ * Sets the service protocol type and returns a reference to this Builder enabling method
+ * chaining.
+ *
+ * @param serviceProtoType the {@code serviceProtoType} to set
+ * @return a reference to this Builder
+ */
+ @NonNull
+ public Builder setServiceProtoType(@Config.ServiceProtoType int serviceProtoType) {
+ this.mServiceProtoType = serviceProtoType;
+ return this;
+ }
+
+ /**
+ * Sets whether Further Service Discovery (FSD) is enabled or not and returns a reference
+ * to this Builder enabling method chaining.
+ *
+ * @param isFsdEnabled the {@code isFsdEnabled} to set
+ * @return a reference to this Builder
+ */
+ @NonNull
+ public Builder setFsdEnabled(boolean isFsdEnabled) {
+ this.mIsFsdEnabled = isFsdEnabled;
+ return this;
+ }
+
+ /**
+ * Returns a {@code DiscoveryResult} built from the parameters previously set.
+ *
+ * @return a {@code DiscoveryResult} built with parameters of this {@code DiscoveryResult
+ * .Builder}
+ */
+ @NonNull
+ public DiscoveryResult build() {
+ return new DiscoveryResult(this);
+ }
+ }
+}
diff --git a/framework/java/android/net/wifi/usd/IAvailabilityCallback.aidl b/framework/java/android/net/wifi/usd/IAvailabilityCallback.aidl
new file mode 100644
index 0000000..691ec09
--- /dev/null
+++ b/framework/java/android/net/wifi/usd/IAvailabilityCallback.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.usd;
+
+/**
+ * Interface for USD availability callback.
+ *
+ * @hide
+ */
+oneway interface IAvailabilityCallback {
+ /**
+ * Called when subscriber is available
+ */
+ void onSubscriberAvailable();
+ /**
+ * Called when publisher is available
+ */
+ void onPublisherAvailable();
+}
diff --git a/framework/java/android/net/wifi/usd/IPublishSessionCallback.aidl b/framework/java/android/net/wifi/usd/IPublishSessionCallback.aidl
new file mode 100644
index 0000000..5037085
--- /dev/null
+++ b/framework/java/android/net/wifi/usd/IPublishSessionCallback.aidl
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.usd;
+
+/**
+ * Interface for USD publish session callback.
+ *
+ * @hide
+ */
+oneway interface IPublishSessionCallback {
+ void onPublishFailed(int reasonCode);
+ void onPublishStarted(int sessionId);
+ void onPublishReplied(int peerId, in byte[] ssi, int protoType, boolean isFsdEnabled);
+ void onPublishSessionTerminated(int reasonCode);
+ void onMessageReceived(int peerId, in byte[] message);
+}
diff --git a/framework/java/android/net/wifi/usd/ISubscribeSessionCallback.aidl b/framework/java/android/net/wifi/usd/ISubscribeSessionCallback.aidl
new file mode 100644
index 0000000..581d50d
--- /dev/null
+++ b/framework/java/android/net/wifi/usd/ISubscribeSessionCallback.aidl
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.usd;
+
+/**
+ * Interface for USD subscribe session callback.
+ *
+ * @hide
+ */
+oneway interface ISubscribeSessionCallback {
+ void onSubscribeFailed(int reasonCode);
+ void onSubscribeStarted(int sessionId);
+ void onSubscribeDiscovered(int peerId, in byte[] ssi, int protoType, boolean isFsdEnabled);
+ void onSubscribeSessionTerminated(int reasonCode);
+ void onMessageReceived(int peerId, in byte[] message);
+}
diff --git a/framework/java/android/net/wifi/usd/IUsdManager.aidl b/framework/java/android/net/wifi/usd/IUsdManager.aidl
new file mode 100644
index 0000000..030b240
--- /dev/null
+++ b/framework/java/android/net/wifi/usd/IUsdManager.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.usd;
+
+import android.net.wifi.IBooleanListener;
+import android.net.wifi.usd.Characteristics;
+import android.net.wifi.usd.IAvailabilityCallback;
+import android.net.wifi.usd.IPublishSessionCallback;
+import android.net.wifi.usd.ISubscribeSessionCallback;
+import android.net.wifi.usd.PublishConfig;
+import android.net.wifi.usd.SubscribeConfig;
+
+/**
+ * Interface that UsdService implements
+ *
+ * {@hide}
+ */
+interface IUsdManager {
+ boolean isSubscriberAvailable();
+ boolean isPublisherAvailable();
+ void registerAvailabilityCallback(IAvailabilityCallback callback);
+ void unregisterAvailabilityCallback(IAvailabilityCallback callback);
+ Characteristics getCharacteristics();
+ void sendMessage(int peerId, in byte[] message, in IBooleanListener listener);
+ void cancelSubscribe(int sessionId);
+ void cancelPublish(int sessionId);
+ void updatePublish(int sessionId, in byte[] ssi);
+ void publish(in PublishConfig publishConfig, IPublishSessionCallback callback);
+ void subscribe(in SubscribeConfig subscribeConfig, ISubscribeSessionCallback callback);
+}
diff --git a/framework/java/android/net/wifi/usd/PublishConfig.java b/framework/java/android/net/wifi/usd/PublishConfig.java
new file mode 100644
index 0000000..000235a
--- /dev/null
+++ b/framework/java/android/net/wifi/usd/PublishConfig.java
@@ -0,0 +1,385 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.usd;
+
+import android.annotation.FlaggedApi;
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.net.wifi.WifiNetworkSpecifier;
+import android.net.wifi.aware.TlvBufferUtils;
+import android.net.wifi.aware.WifiAwareUtils;
+import android.net.wifi.flags.Flags;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Defines the configuration of USD publish session
+ *
+ * @hide
+ */
+@SystemApi
+@FlaggedApi(Flags.FLAG_USD)
+public final class PublishConfig extends Config implements Parcelable {
+
+ @TransmissionType
+ private final int mSolicitedTransmissionType;
+ private final int mAnnouncementPeriodMillis;
+ private final boolean mEnableEvents;
+
+ private PublishConfig(Parcel in) {
+ super(in.createByteArray(), in.readInt(), in.readInt(), in.createByteArray(),
+ in.createByteArray(), in.createByteArray(), in.createIntArray());
+ mSolicitedTransmissionType = in.readInt();
+ mAnnouncementPeriodMillis = in.readInt();
+ mEnableEvents = in.readBoolean();
+ }
+
+ @NonNull
+ public static final Creator<PublishConfig> CREATOR = new Creator<PublishConfig>() {
+
+ @Override
+ public PublishConfig createFromParcel(Parcel in) {
+ return new PublishConfig(in);
+ }
+
+ @Override
+ public PublishConfig[] newArray(int size) {
+ return new PublishConfig[size];
+ }
+ };
+
+ private PublishConfig(Builder builder) {
+ super(builder.mServiceName, builder.mTtlSeconds, builder.mServiceProtoType,
+ builder.mTxMatchFilterTlv, builder.mRxMatchFilterTlv, builder.mServiceSpecificInfo,
+ builder.mOperatingFrequencies);
+ mSolicitedTransmissionType = builder.mSolicitedTransmissionType;
+ mAnnouncementPeriodMillis = builder.mAnnouncementPeriodMillis;
+ mEnableEvents = builder.mEnableEvents;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeByteArray(getServiceName());
+ dest.writeInt(getTtlSeconds());
+ dest.writeInt(getServiceProtoType());
+ dest.writeByteArray(getTxMatchFilterTlv());
+ dest.writeByteArray(getRxMatchFilterTlv());
+ dest.writeByteArray(getServiceSpecificInfo());
+ dest.writeIntArray(getOperatingFrequenciesMhz());
+ dest.writeInt(mSolicitedTransmissionType);
+ dest.writeInt(mAnnouncementPeriodMillis);
+ dest.writeBoolean(mEnableEvents);
+ }
+
+ /**
+ * @return whether a solicited transmission is an unicast or a multicast transmission
+ */
+ @TransmissionType
+ public int getSolicitedTransmissionType() {
+ return mSolicitedTransmissionType;
+ }
+
+ /**
+ * @return announcement period in milliseconds, which is the Recommended periodicity of
+ * unsolicited transmissions
+ */
+ @IntRange(from = 0)
+ public int getAnnouncementPeriodMillis() {
+ return mAnnouncementPeriodMillis;
+ }
+
+ /**
+ * @return whether publish events are enabled or not. See
+ * {@link Builder#setEventsEnabled(boolean)}.
+ */
+ public boolean isEventsEnabled() {
+ return mEnableEvents;
+ }
+
+ @Override
+ public String toString() {
+ return super.toString() + " PublishConfig{" + "mSolicitedTransmissionType="
+ + mSolicitedTransmissionType + ", mAnnouncementPeriodMillis="
+ + mAnnouncementPeriodMillis + ", mEnableEvents=" + mEnableEvents + '}';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof PublishConfig that)) return false;
+ if (!super.equals(o)) return false;
+ return mSolicitedTransmissionType == that.mSolicitedTransmissionType
+ && mAnnouncementPeriodMillis == that.mAnnouncementPeriodMillis
+ && mEnableEvents == that.mEnableEvents;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(super.hashCode(), mSolicitedTransmissionType, mAnnouncementPeriodMillis,
+ mEnableEvents);
+ }
+
+ /**
+ * {@code PublishConfig} builder static inner class.
+ */
+ public static final class Builder {
+ @TransmissionType
+ private int mSolicitedTransmissionType = TRANSMISSION_TYPE_UNICAST;
+ private int mAnnouncementPeriodMillis = 100;
+ private boolean mEnableEvents = false;
+ private final byte[] mServiceName;
+ private int mTtlSeconds = 3000;
+ @ServiceProtoType
+ private int mServiceProtoType = SERVICE_PROTO_TYPE_GENERIC;
+ private byte[] mTxMatchFilterTlv = null;
+ private byte[] mRxMatchFilterTlv = null;
+ private byte[] mServiceSpecificInfo = null;
+ private int[] mOperatingFrequencies = null;
+
+ /**
+ * Builder for {@link PublishConfig}
+ *
+ * @param serviceName Specify the service name of the USD session. The Service Name is a
+ * UTF-8 encoded string from 1 to
+ * {@link Characteristics#getMaxServiceNameLength()} bytes in length.
+ * The only acceptable single-byte UTF-8 symbols for a Service Name are
+ * alphanumeric values (A-Z, a-z, 0-9), the hyphen ('-'), the period
+ * ('.') and the underscore ('_'). All valid multi-byte UTF-8
+ * characters are acceptable in a Service Name.
+ */
+ public Builder(@NonNull String serviceName) {
+ Objects.requireNonNull(serviceName, "serviceName must not be null");
+ mServiceName = serviceName.getBytes(StandardCharsets.UTF_8);
+ WifiAwareUtils.validateServiceName(mServiceName);
+ }
+
+ /**
+ * Sets the time to live for the USD session and returns a reference to this Builder
+ * enabling method chaining. Default value is 3000 seconds.
+ *
+ * @param ttlSeconds Time to live in seconds. Value 0 indicating the session does not
+ * terminate on its own.
+ * @return a reference to this Builder
+ */
+ @NonNull
+ public Builder setTtlSeconds(@IntRange(from = 0) int ttlSeconds) {
+ if (ttlSeconds < 0) {
+ throw new IllegalArgumentException("Invalid ttlSec - must be non-negative");
+ }
+ mTtlSeconds = ttlSeconds;
+ return this;
+ }
+
+ /**
+ * Sets the {@code serviceProtoType} and returns a reference to this Builder enabling method
+ * chaining. Supported service protocol is defined as {@code SERVICE_PROTO_TYPE_*}. Default
+ * value is {@link #SERVICE_PROTO_TYPE_GENERIC}.
+ *
+ * @param serviceProtoType the {@code serviceProtoType} to set
+ * @return a reference to this Builder
+ */
+ @NonNull
+ public Builder setServiceProtoType(@ServiceProtoType int serviceProtoType) {
+ if (serviceProtoType < SERVICE_PROTO_TYPE_GENERIC
+ || serviceProtoType > SERVICE_PROTO_TYPE_CSA_MATTER) {
+ throw new IllegalArgumentException("Invalid serviceProtoType - "
+ + serviceProtoType);
+ }
+ mServiceProtoType = serviceProtoType;
+ return this;
+ }
+
+ /**
+ * Sets the {@code txMatchFilter} and returns a reference to this Builder enabling method
+ * chaining. The {@code txMatchFilter} is the ordered sequence of (length, value) pairs to
+ * be included in the subscribe frame. If not set, empty by default.
+ *
+ * <p>See Wi-Fi Aware Specification Version 4.0, section: Appendix H (Informative) Matching
+ * filter examples.
+ *
+ * @param txMatchFilter the {@code txMatchFilter} to set
+ * @return a reference to this Builder
+ */
+ @NonNull
+ public Builder setTxMatchFilter(@NonNull List<byte[]> txMatchFilter) {
+ Objects.requireNonNull(txMatchFilter, "txMatchFilter must not be null");
+ this.mTxMatchFilterTlv = new TlvBufferUtils.TlvConstructor(0, 1).allocateAndPut(
+ txMatchFilter).getArray();
+ if (!TlvBufferUtils.isValid(mTxMatchFilterTlv, 0, 1)) {
+ throw new IllegalArgumentException(
+ "Invalid txMatchFilter configuration - LV fields do not match up to "
+ + "length");
+ }
+ return this;
+ }
+
+ /**
+ * Sets the {@code rxMatchFilter} and returns a reference to this Builder enabling method
+ * chaining. The {@code rxMatchFilter} is the ordered sequence of (length, value) pairs
+ * that specify further the matching conditions beyond the service name used to filter
+ * the USD discovery messages. When a subscriber receives a publish message, it matches the
+ * matching filter field in the publish message against its own matching_filter_rx. If not
+ * set, empty by default.
+ *
+ * <p>See Wi-Fi Aware Specification Version 4.0, section: Appendix H (Informative) Matching
+ * filter examples.
+ *
+ * @param rxMatchFilter the {@code rxMatchFilter} to set
+ * @return a reference to this Builder
+ */
+ @NonNull
+ public Builder setRxMatchFilter(@NonNull List<byte[]> rxMatchFilter) {
+ Objects.requireNonNull(rxMatchFilter, "rxMatchFilter must not be null");
+ this.mRxMatchFilterTlv = new TlvBufferUtils.TlvConstructor(0, 1).allocateAndPut(
+ rxMatchFilter).getArray();
+ if (!TlvBufferUtils.isValid(mRxMatchFilterTlv, 0, 1)) {
+ throw new IllegalArgumentException(
+ "Invalid rxMatchFilter configuration - LV fields do not match up to "
+ + "length");
+ }
+ return this;
+ }
+
+ /**
+ * Sets the solicited transmission type and returns a reference to this Builder enabling
+ * method chaining. The type determines whether the transmission is unicast or multicast.
+ * Default is unicast.
+ *
+ * @param solicitedTransmissionType the transmission type {@code TRANSMISSION_TYPE_*} to
+ * set
+ * @return a reference to this Builder
+ */
+ @NonNull
+ public Builder setSolicitedTransmissionType(
+ @TransmissionType int solicitedTransmissionType) {
+ if (solicitedTransmissionType < TRANSMISSION_TYPE_UNICAST
+ || solicitedTransmissionType > TRANSMISSION_TYPE_MULTICAST) {
+ throw new IllegalArgumentException("Invalid solicitedTransmissionType - "
+ + solicitedTransmissionType);
+ }
+ this.mSolicitedTransmissionType = solicitedTransmissionType;
+ return this;
+ }
+
+ /**
+ * Sets announcement period and returns a reference to this Builder enabling method
+ * chaining. Announcement period is the recommended periodicity of unsolicited
+ * transmissions. Default value is 100 ms.
+ *
+ * @param announcementPeriodMillis announcement period in milliseconds to set
+ * @return a reference to this Builder
+ */
+ @NonNull
+ public Builder setAnnouncementPeriodMillis(
+ @IntRange(from = 0) int announcementPeriodMillis) {
+ if (announcementPeriodMillis < 0) {
+ throw new IllegalArgumentException(
+ "Invalid announcementPeriodMillis - must be non-negative");
+ }
+ this.mAnnouncementPeriodMillis = announcementPeriodMillis;
+ return this;
+ }
+
+ /**
+ * Enable or disable publish related events and returns a reference to this Builder
+ * enabling method chaining. If enabled, publish replied events are generated on each
+ * solicited transmission. By default, publish replied events are disabled.
+ * See {@link PublishSessionCallback#onPublishReplied(DiscoveryResult)}.
+ *
+ * @param enableEvents the publish related events are enabled
+ * @return a reference to this Builder
+ */
+ @NonNull
+ public Builder setEventsEnabled(boolean enableEvents) {
+ this.mEnableEvents = enableEvents;
+ return this;
+ }
+
+ /**
+ * Specify service specific information for the publish session. This is a free-form byte
+ * array available to the application to send additional information as part of the
+ * discovery operation - it will not be used to determine whether a publish/subscribe
+ * match occurs. Default value is null;
+ *
+ * Note: Maximum length is limited by
+ * {@link Characteristics#getMaxServiceSpecificInfoLength()}
+ *
+ * @param serviceSpecificInfo A byte-array for the service-specific
+ * information field.
+ * @return a reference to this Builder
+ */
+ @NonNull
+ public Builder setServiceSpecificInfo(@NonNull byte[] serviceSpecificInfo) {
+ Objects.requireNonNull(serviceSpecificInfo, "serviceSpecificInfo must not be null");
+ mServiceSpecificInfo = serviceSpecificInfo.clone();
+ return this;
+ }
+
+ /**
+ * Sets the operating frequencies used for publish operation. This overrides the default
+ * channel selection for publish. All frequencies have to be 20 Mhz channel in 2.4 Ghz or
+ * 5 Ghz band per regulation in the geographical location. In {@code operatingFrequencies},
+ * <ul>
+ * <li>The first frequency is the channel used for single channel publish.
+ * <li>Any additional frequencies enable multiple channel publish.
+ * </ul>
+ *
+ * <p>If not set or an empty array is provided, the system defaults to 2437 MHz (channel 6
+ * in the 2.4 GHz band) for single channel publish and a list of allowed channels in the 2.4
+ * GHz and 5 GHz bands for multichannel publishing.
+ *
+ * <p>Note: the dwell time for the single and multi publish channels are defined in the
+ * Wifi Aware Specification Version 4, section 4.5.1 Publisher behavior in USD.
+ *
+ * @param operatingFrequencies frequencies used for publish operation
+ * @return a reference to this Builder
+ * @throws IllegalArgumentException if frequencies are invalid or the number frequencies
+ * are more than the number of 20 Mhz channels in 2.4 Ghz and 5 Ghz as per regulatory.
+ */
+ @NonNull
+ public Builder setOperatingFrequenciesMhz(@NonNull int[] operatingFrequencies) {
+ Objects.requireNonNull(operatingFrequencies, "operatingFrequencies must not be null");
+ if ((operatingFrequencies.length > MAX_NUM_OF_OPERATING_FREQUENCIES)
+ || WifiNetworkSpecifier.validateChannelFrequencyInMhz(operatingFrequencies)) {
+ throw new IllegalArgumentException("Invalid operatingFrequencies");
+ }
+ mOperatingFrequencies = operatingFrequencies.clone();
+ return this;
+ }
+
+ /**
+ * Returns a {@code PublishConfig} built from the parameters previously set.
+ *
+ * @return a {@code PublishConfig} built with parameters of this {@code PublishConfig
+ * .Builder}
+ */
+ @NonNull
+ public PublishConfig build() {
+ return new PublishConfig(this);
+ }
+ }
+}
diff --git a/framework/java/android/net/wifi/usd/PublishSession.java b/framework/java/android/net/wifi/usd/PublishSession.java
new file mode 100644
index 0000000..5887c0c
--- /dev/null
+++ b/framework/java/android/net/wifi/usd/PublishSession.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.usd;
+
+import static android.Manifest.permission.MANAGE_WIFI_NETWORK_SELECTION;
+
+import android.annotation.CallbackExecutor;
+import android.annotation.FlaggedApi;
+import android.annotation.NonNull;
+import android.annotation.RequiresApi;
+import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
+import android.net.wifi.flags.Flags;
+import android.net.wifi.util.Environment;
+import android.os.Build;
+import android.util.Log;
+
+import java.lang.ref.WeakReference;
+import java.util.Objects;
+import java.util.concurrent.Executor;
+import java.util.function.Consumer;
+
+
+/**
+ * A class to represent the USD publish session
+ *
+ * @hide
+ */
+@RequiresApi(Build.VERSION_CODES.BAKLAVA)
+@SystemApi
+@FlaggedApi(Flags.FLAG_USD)
+public class PublishSession {
+ private static final String TAG = PublishSession.class.getName();
+ private final WeakReference<UsdManager> mUsdManager;
+ private final int mSessionId;
+
+ /** @hide */
+ public PublishSession(@NonNull UsdManager usdManager, int sessionId) {
+ mUsdManager = new WeakReference<>(usdManager);
+ mSessionId = sessionId;
+ }
+
+
+ /** @hide */
+ public int getSessionId() {
+ return mSessionId;
+ }
+
+ /**
+ * Cancel the Publish Session
+ *
+ */
+ @RequiresPermission(MANAGE_WIFI_NETWORK_SELECTION)
+ public void cancel() {
+ if (!Environment.isSdkAtLeastB()) {
+ throw new UnsupportedOperationException();
+ }
+ UsdManager usdManager = mUsdManager.get();
+ if (usdManager == null) {
+ Log.w(TAG, "cancel is called after the UsdManager has been garbage collected");
+ return;
+ }
+ usdManager.cancelPublish(mSessionId);
+ }
+
+ /**
+ * Update the publish session with service specific info. The new value will override any
+ * service specific information previously passed to the publish or updatePublish methods for
+ * this session. To clear service specific info, set an empty byte array.
+ *
+ * @param serviceSpecificInfo service specific info
+ */
+ @RequiresPermission(MANAGE_WIFI_NETWORK_SELECTION)
+ public void updatePublish(@NonNull byte[] serviceSpecificInfo) {
+ Objects.requireNonNull(serviceSpecificInfo, "serviceSpecificInfo must not be null");
+ if (!Environment.isSdkAtLeastB()) {
+ throw new UnsupportedOperationException();
+ }
+ UsdManager usdManager = mUsdManager.get();
+ if (usdManager == null) {
+ Log.w(TAG, "updatePublish is called after the UsdManager has been garbage collected");
+ return;
+ }
+ usdManager.updatePublish(mSessionId, serviceSpecificInfo);
+ }
+
+ /**
+ * Send a message to the peer. Message length is limited by
+ * {@link Characteristics#getMaxServiceSpecificInfoLength()}.
+ *
+ * @param peerId peer id obtained from {@link DiscoveryResult#getPeerId()}
+ * @param message byte array
+ * @param executor executor
+ * @param resultCallback result callback
+ */
+ @RequiresPermission(MANAGE_WIFI_NETWORK_SELECTION)
+ public void sendMessage(int peerId, @NonNull byte[] message,
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull Consumer<Boolean> resultCallback) {
+ Objects.requireNonNull(executor, "executor must not be null");
+ Objects.requireNonNull(resultCallback, "resultCallback must not be null");
+ Objects.requireNonNull(message, "message must not be null");
+ if (!Environment.isSdkAtLeastB()) {
+ throw new UnsupportedOperationException();
+ }
+ UsdManager usdManager = mUsdManager.get();
+ if (usdManager == null) {
+ Log.w(TAG, "sendMessage is called after the UsdManager has been garbage collected");
+ executor.execute(() -> resultCallback.accept(false));
+ return;
+ }
+ usdManager.sendMessage(peerId, message, executor, resultCallback);
+ }
+}
diff --git a/framework/java/android/net/wifi/usd/PublishSessionCallback.java b/framework/java/android/net/wifi/usd/PublishSessionCallback.java
new file mode 100644
index 0000000..e5d957e
--- /dev/null
+++ b/framework/java/android/net/wifi/usd/PublishSessionCallback.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.usd;
+
+import android.annotation.FlaggedApi;
+import android.annotation.NonNull;
+import android.annotation.RequiresApi;
+import android.annotation.SystemApi;
+import android.net.wifi.flags.Flags;
+import android.os.Build;
+
+
+/**
+ * USD publish session callbacks. Should be extended by applications wanting notifications.
+ *
+ * @hide
+ */
+@RequiresApi(Build.VERSION_CODES.BAKLAVA)
+@SystemApi
+@FlaggedApi(Flags.FLAG_USD)
+public class PublishSessionCallback extends SessionCallback {
+
+ /**
+ * Called when a publish session cannot be created.
+ *
+ * @param reason reason code as defined in {@code FAILURE_XXX}
+ */
+ public void onPublishFailed(@FailureCode int reason) {
+ }
+
+ /**
+ * Called when a publish operation is started successfully.
+ *
+ * @param session publish session
+ */
+ public void onPublishStarted(@NonNull PublishSession session) {
+ }
+
+ /**
+ * Called for each solicited publish transmission if
+ * {@link PublishConfig.Builder#setEventsEnabled(boolean)} is enabled.
+ */
+ public void onPublishReplied(@NonNull DiscoveryResult discoveryResult) {
+ }
+}
diff --git a/framework/java/android/net/wifi/usd/SessionCallback.java b/framework/java/android/net/wifi/usd/SessionCallback.java
new file mode 100644
index 0000000..d226cd4
--- /dev/null
+++ b/framework/java/android/net/wifi/usd/SessionCallback.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.usd;
+
+import android.annotation.FlaggedApi;
+import android.annotation.IntDef;
+import android.annotation.Nullable;
+import android.annotation.RequiresApi;
+import android.annotation.SystemApi;
+import android.net.wifi.flags.Flags;
+import android.os.Build;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+
+/**
+ * Base class for USD session events callbacks. Should be extended by applications wanting
+ * notifications. The callbacks are set when a publish or subscribe session is created.
+ *
+ * @hide
+ */
+@RequiresApi(Build.VERSION_CODES.BAKLAVA)
+@SystemApi
+@FlaggedApi(Flags.FLAG_USD)
+public abstract class SessionCallback {
+ /**
+ * Failure code
+ *
+ * @hide
+ */
+ @IntDef({FAILURE_UNKNOWN, FAILURE_TIMEOUT, FAILURE_NOT_AVAILABLE, FAILURE_MAX_SESSIONS_REACHED})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface FailureCode {
+ }
+
+ /**
+ * Failure is unknown.
+ */
+ public static final int FAILURE_UNKNOWN = 0;
+
+ /**
+ * Failure due to timeout in the requested operation.
+ */
+ public static final int FAILURE_TIMEOUT = 1;
+
+ /**
+ * Failure due to the requested operation is not available currently.
+ */
+ public static final int FAILURE_NOT_AVAILABLE = 2;
+ /**
+ * Failure due to the maximum session reached. Maximum number of publish and subscribe sessions
+ * are limited by {@link Characteristics#getMaxNumberOfPublishSessions()} and
+ * {@link Characteristics#getMaxNumberOfSubscribeSessions()} respectively.
+ */
+ public static final int FAILURE_MAX_SESSIONS_REACHED = 3;
+
+
+ /**
+ * Termination reason code
+ *
+ * @hide
+ */
+ @IntDef({TERMINATION_REASON_UNKNOWN, TERMINATION_REASON_NOT_AVAILABLE,
+ TERMINATION_REASON_USER_INITIATED})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface TerminationReasonCode {
+ }
+
+ /**
+ * Termination due to unknown reason.
+ */
+ public static final int TERMINATION_REASON_UNKNOWN = 0;
+
+ /**
+ * Termination due the USD session is not available.
+ */
+ public static final int TERMINATION_REASON_NOT_AVAILABLE = 1;
+
+ /**
+ * Termination due to user initiated {@link PublishSession#cancel()} or
+ * {@link SubscribeSession#cancel()}
+ */
+ public static final int TERMINATION_REASON_USER_INITIATED = 2;
+
+ /**
+ * Called when a publish or subscribe session terminates. Termination may be due to
+ * <ul>
+ * <li> user request e.g. {@link SubscribeSession#cancel()} or {@link PublishSession#cancel()}
+ * <li> application expiration e.g. {@link PublishConfig.Builder#setTtlSeconds(int)} or
+ * {@link SubscribeConfig.Builder#setTtlSeconds(int)}.
+ * </ul>
+ * @param reason reason code as in {@code TERMINATION_REASON_*}
+ */
+ public void onSessionTerminated(@TerminationReasonCode int reason) {
+ }
+
+ /**
+ * Called when a message is received from another USD peer.
+ *
+ * @param peerId an identifier of the remote peer
+ * @param message a byte array containing the message.
+ */
+ public void onMessageReceived(int peerId, @Nullable byte[] message) {
+ }
+}
diff --git a/framework/java/android/net/wifi/usd/SubscribeConfig.java b/framework/java/android/net/wifi/usd/SubscribeConfig.java
new file mode 100644
index 0000000..546d2dc
--- /dev/null
+++ b/framework/java/android/net/wifi/usd/SubscribeConfig.java
@@ -0,0 +1,407 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.usd;
+
+import android.annotation.FlaggedApi;
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.net.wifi.WifiNetworkSpecifier;
+import android.net.wifi.aware.TlvBufferUtils;
+import android.net.wifi.aware.WifiAwareUtils;
+import android.net.wifi.flags.Flags;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+
+
+/**
+ * Defines the configuration of USD subscribe session.
+ *
+ * @hide
+ */
+@SystemApi
+@FlaggedApi(Flags.FLAG_USD)
+public final class SubscribeConfig extends Config implements Parcelable {
+
+ private SubscribeConfig(Builder builder) {
+ super(builder.mServiceName, builder.mTtlSeconds, builder.mServiceProtoType,
+ builder.mTxMatchFilterTlv, builder.mRxMatchFilterTlv, builder.mServiceSpecificInfo,
+ builder.mOperatingFrequencies);
+ mSubscribeType = builder.mSubscribeType;
+ mQueryPeriodMillis = builder.mQueryPeriodMillis;
+ mRecommendedFrequencies = builder.mRecommendedFrequencies;
+ }
+
+ @SubscribeType
+ private final int mSubscribeType;
+ private final int mQueryPeriodMillis;
+ private final int[] mRecommendedFrequencies;
+
+ private SubscribeConfig(Parcel in) {
+ super(in.createByteArray(), in.readInt(), in.readInt(), in.createByteArray(),
+ in.createByteArray(), in.createByteArray(), in.createIntArray());
+ mSubscribeType = in.readInt();
+ mQueryPeriodMillis = in.readInt();
+ mRecommendedFrequencies = in.createIntArray();
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeByteArray(getServiceName());
+ dest.writeInt(getTtlSeconds());
+ dest.writeInt(getServiceProtoType());
+ dest.writeByteArray(getTxMatchFilterTlv());
+ dest.writeByteArray(getRxMatchFilterTlv());
+ dest.writeByteArray(getServiceSpecificInfo());
+ dest.writeIntArray(getOperatingFrequenciesMhz());
+ dest.writeInt(mSubscribeType);
+ dest.writeInt(mQueryPeriodMillis);
+ dest.writeIntArray(mRecommendedFrequencies);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @NonNull
+ public static final Creator<SubscribeConfig> CREATOR = new Creator<SubscribeConfig>() {
+
+ @Override
+ public SubscribeConfig createFromParcel(Parcel in) {
+ return new SubscribeConfig(in);
+ }
+
+ @Override
+ public SubscribeConfig[] newArray(int size) {
+ return new SubscribeConfig[size];
+ }
+ };
+
+ /**
+ * Gets the type of subscribe session. See {@code SUBSCRIBE_TYPE_XXX} for different types of
+ * subscribe.
+ *
+ * @return subscribe type
+ */
+ @SubscribeType
+ public int getSubscribeType() {
+ return mSubscribeType;
+ }
+
+ /**
+ * Gets the recommended periodicity of query transmissions for the subscribe session.
+ *
+ * @return Query period in milliseconds
+ */
+ @IntRange(from = 0)
+ public int getQueryPeriodMillis() {
+ return mQueryPeriodMillis;
+ }
+
+ /**
+ * Gets the recommended frequency list to be used for subscribe operation. See
+ * {@link Builder#setRecommendedOperatingFrequenciesMhz(int[])}.
+ *
+ * @return frequency list or null if not set
+ */
+ @Nullable
+ public int[] getRecommendedOperatingFrequenciesMhz() {
+ return mRecommendedFrequencies;
+ }
+
+ @Override
+ public String toString() {
+ return super.toString() + " SubscribeConfig{" + "mSubscribeType=" + mSubscribeType
+ + ", mQueryPeriodMillis=" + mQueryPeriodMillis + ", mRecommendedFrequencies="
+ + Arrays.toString(mRecommendedFrequencies) + '}';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof SubscribeConfig that)) return false;
+ if (!super.equals(o)) return false;
+ return mSubscribeType == that.mSubscribeType
+ && mQueryPeriodMillis == that.mQueryPeriodMillis
+ && Arrays.equals(mRecommendedFrequencies, that.mRecommendedFrequencies);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = Objects.hash(super.hashCode(), mSubscribeType, mQueryPeriodMillis);
+ result = 31 * result + Arrays.hashCode(mRecommendedFrequencies);
+ return result;
+ }
+
+ /**
+ * {@code SubscribeConfig} builder static inner class.
+ */
+ @FlaggedApi(Flags.FLAG_USD)
+ public static final class Builder {
+ @SubscribeType private int mSubscribeType = SUBSCRIBE_TYPE_ACTIVE;
+ private int mQueryPeriodMillis = 100;
+ private int[] mRecommendedFrequencies = null;
+ private final byte[] mServiceName;
+ private int mTtlSeconds = 3000;
+ @ServiceProtoType private int mServiceProtoType = SERVICE_PROTO_TYPE_GENERIC;
+ private byte[] mTxMatchFilterTlv = null;
+ private byte[] mRxMatchFilterTlv = null;
+ private byte[] mServiceSpecificInfo = null;
+ private int[] mOperatingFrequencies = null;
+
+ /**
+ * Builder for {@link SubscribeConfig}
+ *
+ * @param serviceName Specify the service name of the USD session. The Service Name is a
+ * UTF-8 encoded string from 1 to
+ * {@link Characteristics#getMaxServiceNameLength()} bytes in length.
+ * The only acceptable single-byte UTF-8 symbols for a Service Name are
+ * alphanumeric values (A-Z, a-z, 0-9), the hyphen ('-'), the period
+ * ('.') and the underscore ('_'). Allvalid multi-byte UTF-8
+ * characters are acceptable in a Service Name.
+ */
+ public Builder(@NonNull String serviceName) {
+ Objects.requireNonNull(serviceName, "serviceName must not be null");
+ mServiceName = serviceName.getBytes(StandardCharsets.UTF_8);
+ WifiAwareUtils.validateServiceName(mServiceName);
+ }
+
+ /**
+ * Sets the time to live for the USD session and returns a reference to this Builder
+ * enabling method chaining. Default value is 3000 seconds.
+ *
+ * @param ttlSeconds Time to live in seconds. Value 0 indicating the session does not
+ * terminate on its own.
+ * @return a reference to this Builder
+ */
+ @NonNull
+ public Builder setTtlSeconds(@IntRange(from = 0) int ttlSeconds) {
+ if (ttlSeconds < 0) {
+ throw new IllegalArgumentException("Invalid ttlSec - must be non-negative");
+ }
+ mTtlSeconds = ttlSeconds;
+ return this;
+ }
+
+ /**
+ * Sets the {@code serviceProtoType} and returns a reference to this Builder enabling method
+ * chaining. Supported service protocol is defined as {@code SERVICE_PROTO_TYPE_*}. Default
+ * value is {@link #SERVICE_PROTO_TYPE_GENERIC}.
+ *
+ * @param serviceProtoType the {@code serviceProtoType} to set
+ * @return a reference to this Builder
+ */
+ @NonNull
+ public Builder setServiceProtoType(@ServiceProtoType int serviceProtoType) {
+ if (serviceProtoType < SERVICE_PROTO_TYPE_GENERIC
+ || serviceProtoType > SERVICE_PROTO_TYPE_CSA_MATTER) {
+ throw new IllegalArgumentException("Invalid serviceProtoType - "
+ + serviceProtoType);
+ }
+ mServiceProtoType = serviceProtoType;
+ return this;
+ }
+
+ /**
+ * Sets the {@code txMatchFilter} and returns a reference to this Builder enabling method
+ * chaining. The {@code txMatchFilter} is the ordered sequence of (length, value) pairs to
+ * be included in the subscribe frame. If not set, empty by default.
+ *
+ * <p>See Wi-Fi Aware Specification Version 4.0, section: Appendix H (Informative) Matching
+ * filter examples.
+ *
+ * @param txMatchFilter the {@code txMatchFilter} to set
+ * @return a reference to this Builder
+ */
+ @NonNull
+ public Builder setTxMatchFilter(@NonNull List<byte[]> txMatchFilter) {
+ Objects.requireNonNull(txMatchFilter, "txMatchFilter must not be null");
+ mTxMatchFilterTlv = new TlvBufferUtils.TlvConstructor(0, 1).allocateAndPut(
+ txMatchFilter).getArray();
+ if (!TlvBufferUtils.isValid(mTxMatchFilterTlv, 0, 1)) {
+ throw new IllegalArgumentException(
+ "Invalid txMatchFilter configuration - LV fields do not match up to "
+ + "length");
+ }
+ return this;
+ }
+
+ /**
+ * Sets the {@code rxMatchFilter} and returns a reference to this Builder enabling method
+ * chaining. The {@code rxMatchFilter} is the ordered sequence of (length, value) pairs
+ * that specify further the matching conditions beyond the service name used to filter
+ * the USD discovery messages. When a subscriber receives a publish message, it matches the
+ * matching filter field in the publish message against its own matching_filter_rx. If not
+ * set, empty by default.
+ *
+ * <p>See Wi-Fi Aware Specification Version 4.0, section: Appendix H (Informative) Matching
+ * filter examples.
+ *
+ * @param rxMatchFilter the {@code rxMatchFilter} to set
+ * @return a reference to this Builder
+ */
+ @NonNull
+ public Builder setRxMatchFilter(@NonNull List<byte[]> rxMatchFilter) {
+ Objects.requireNonNull(rxMatchFilter, "rxMatchFilter must not be null");
+ mRxMatchFilterTlv = new TlvBufferUtils.TlvConstructor(0, 1).allocateAndPut(
+ rxMatchFilter).getArray();
+ if (!TlvBufferUtils.isValid(mRxMatchFilterTlv, 0, 1)) {
+ throw new IllegalArgumentException(
+ "Invalid rxMatchFilter configuration - LV fields do not match up to "
+ + "length");
+ }
+ return this;
+ }
+
+ /**
+ * Sets the susbcribe type and returns a reference to this Builder enabling method chaining.
+ *
+ * @param subscribeType the {@code subscribeType} to set
+ * @return a reference to this Builder
+ */
+ @NonNull
+ public Builder setSubscribeType(@SubscribeType int subscribeType) {
+ if (subscribeType < SUBSCRIBE_TYPE_PASSIVE || subscribeType > SUBSCRIBE_TYPE_ACTIVE) {
+ throw new IllegalArgumentException("Invalid subscribeType - " + subscribeType);
+ }
+ mSubscribeType = subscribeType;
+ return this;
+ }
+
+ /**
+ * Sets the query period and returns a reference to this Builder enabling method chaining.
+ * Default value is 100 ms.
+ *
+ * @param queryPeriodMillis the {@code queryPeriodMillis} to set
+ * @return a reference to this Builder
+ */
+ @NonNull
+ public Builder setQueryPeriodMillis(@IntRange(from = 0) int queryPeriodMillis) {
+ if (queryPeriodMillis < 0) {
+ throw new IllegalArgumentException(
+ "Invalid queryPeriodMillis - must be non-negative");
+ }
+ mQueryPeriodMillis = queryPeriodMillis;
+ return this;
+ }
+
+ /**
+ * Sets the recommended frequencies to use in case the framework couldn't pick a default
+ * channel for the subscriber operation. This will be a no-op if
+ * {@link #setOperatingFrequenciesMhz(int[])} is used.
+ *
+ * <p>Here is the default subscriber channel selection preference order with {@code
+ * recommendedFreqList}
+ * <ol>
+ * <li>Channel 6 in 2.4 Ghz if there is no multichannel concurrency.
+ * <li>Station channel if the station connected on non-DFS/Indoor channel.
+ * <li>Pick a channel from {@code recommendedFreqList} if regulatory permits.
+ * <li>Pick any available channel
+ * </ol>
+ *
+ * <p>Note: If multiple channels are available for the subscriber, the channel having AP
+ * with the best RSSI will be picked.
+ *
+ * @param recommendedFrequencies the {@code recommendedFreqList} to set
+ * @return a reference to this Builder
+ * @throws IllegalArgumentException if frequencies are invalid or the number frequencies
+ * are more than the number of 20 Mhz channels in 2.4 Ghz and 5 Ghz as per regulatory.
+ */
+ @NonNull
+ public Builder setRecommendedOperatingFrequenciesMhz(
+ @NonNull int[] recommendedFrequencies) {
+ Objects.requireNonNull(recommendedFrequencies,
+ "recommendedFrequencies must not be null");
+ if ((recommendedFrequencies.length > MAX_NUM_OF_OPERATING_FREQUENCIES)
+ || WifiNetworkSpecifier.validateChannelFrequencyInMhz(recommendedFrequencies)) {
+ throw new IllegalArgumentException("Invalid recommendedFrequencies");
+ }
+ this.mRecommendedFrequencies = recommendedFrequencies.clone();
+ return this;
+ }
+
+ /**
+ * Specify service specific information for the publish session. This is a free-form byte
+ * array available to the application to send additional information as part of the
+ * discovery operation - it will not be used to determine whether a publish/subscribe
+ * match occurs. Default value is null;
+ *
+ * Note: Maximum length is limited by
+ * {@link Characteristics#getMaxServiceSpecificInfoLength()}
+ *
+ * @param serviceSpecificInfo A byte-array for the service-specific
+ * information field.
+ * @return a reference to this Builder
+ */
+ @NonNull
+ public Builder setServiceSpecificInfo(@NonNull byte[] serviceSpecificInfo) {
+ Objects.requireNonNull(serviceSpecificInfo, "serviceSpecificInfo must not be null");
+ mServiceSpecificInfo = serviceSpecificInfo.clone();
+ return this;
+ }
+
+ /**
+ * Sets the frequencies used for subscribe operation. The subscriber picks one of the
+ * frequencies from this list. This overrides the default channel selection as described
+ * below.
+ *
+ * <p>If null, here is the default subscriber channel selection preference order,
+ * <ol>
+ * <li>Channel 6 in 2.4 Ghz if there is no multichannel concurrency.
+ * <li>Station channel if the station connected on non-DFS/Indoor channel.
+ * <li>Pick a channel from {@link #setRecommendedOperatingFrequenciesMhz(int[])} if
+ * regulatory permits.
+ * <li>Pick any available channel.
+ * </ol>
+ * <p>Note: the dwell time for subscriber operation is calculated internally based on
+ * existing concurrency operation (e.g. Station + USD).
+ *
+ * @param operatingFrequencies frequencies used for subscribe operation
+ * @return a reference to this Builder
+ * @throws IllegalArgumentException if frequencies are invalid or the number frequencies
+ * are more than the number of 20 Mhz channels in 2.4 Ghz and 5 Ghz as per regulatory.
+ */
+ @NonNull
+ public Builder setOperatingFrequenciesMhz(@NonNull int[] operatingFrequencies) {
+ Objects.requireNonNull(operatingFrequencies, "operatingFrequencies must not be null");
+ if ((operatingFrequencies.length > MAX_NUM_OF_OPERATING_FREQUENCIES)
+ || WifiNetworkSpecifier.validateChannelFrequencyInMhz(operatingFrequencies)) {
+ throw new IllegalArgumentException("Invalid operatingFrequencies");
+ }
+ mOperatingFrequencies = operatingFrequencies.clone();
+ return this;
+ }
+
+ /**
+ * Returns a {@code SubscribeConfig} built from the parameters previously set.
+ *
+ * @return a {@code SubscribeConfig} built with parameters of this {@code SubscribeConfig
+ * .Builder}
+ */
+ @NonNull
+ public SubscribeConfig build() {
+ return new SubscribeConfig(this);
+ }
+ }
+}
diff --git a/framework/java/android/net/wifi/usd/SubscribeSession.java b/framework/java/android/net/wifi/usd/SubscribeSession.java
new file mode 100644
index 0000000..ce039d1
--- /dev/null
+++ b/framework/java/android/net/wifi/usd/SubscribeSession.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.usd;
+
+import static android.Manifest.permission.MANAGE_WIFI_NETWORK_SELECTION;
+
+import android.annotation.CallbackExecutor;
+import android.annotation.FlaggedApi;
+import android.annotation.NonNull;
+import android.annotation.RequiresApi;
+import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
+import android.net.wifi.flags.Flags;
+import android.net.wifi.util.Environment;
+import android.os.Build;
+import android.util.Log;
+
+import java.lang.ref.WeakReference;
+import java.util.Objects;
+import java.util.concurrent.Executor;
+import java.util.function.Consumer;
+
+/**
+ * A class to represent the USD Subscribe session.
+ *
+ * @hide
+ */
+@RequiresApi(Build.VERSION_CODES.BAKLAVA)
+@SystemApi
+@FlaggedApi(Flags.FLAG_USD)
+public class SubscribeSession {
+ private static final String TAG = SubscribeSession.class.getName();
+ private final WeakReference<UsdManager> mUsdManager;
+ private final int mSessionId;
+
+ /** @hide */
+ public SubscribeSession(@NonNull UsdManager usdManager, int sessionId) {
+ mUsdManager = new WeakReference<>(usdManager);
+ mSessionId = sessionId;
+ }
+
+ /** @hide */
+ public int getSessionId() {
+ return mSessionId;
+ }
+
+ /**
+ * Cancel the Subscribe Session
+ *
+ */
+ @RequiresPermission(MANAGE_WIFI_NETWORK_SELECTION)
+ public void cancel() {
+ if (!Environment.isSdkAtLeastB()) {
+ throw new UnsupportedOperationException();
+ }
+ UsdManager usdManager = mUsdManager.get();
+ if (usdManager == null) {
+ Log.w(TAG, "cancelSubscribe is called after the UsdManager has been garbage collected");
+ return;
+ }
+ usdManager.cancelSubscribe(mSessionId);
+ }
+
+ /**
+ * Send a message to the peer. Message length is limited by
+ * {@link Characteristics#getMaxServiceSpecificInfoLength()}.
+ *
+ * @param peerId peer id obtained from {@link DiscoveryResult#getPeerId()}
+ * @param message byte array
+ * @param executor executor
+ * @param resultCallback result callback
+ */
+ @RequiresPermission(MANAGE_WIFI_NETWORK_SELECTION)
+ public void sendMessage(int peerId, @NonNull byte[] message,
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull Consumer<Boolean> resultCallback) {
+ Objects.requireNonNull(executor, "executor must not be null");
+ Objects.requireNonNull(resultCallback, "resultCallback must not be null");
+ Objects.requireNonNull(message, "message must not be null");
+ if (!Environment.isSdkAtLeastB()) {
+ throw new UnsupportedOperationException();
+ }
+ UsdManager usdManager = mUsdManager.get();
+ if (usdManager == null) {
+ Log.w(TAG, "sendMessage is called after the UsdManager has been garbage collected");
+ executor.execute(() -> resultCallback.accept(false));
+ return;
+ }
+ usdManager.sendMessage(peerId, message, executor, resultCallback);
+ }
+}
diff --git a/framework/java/android/net/wifi/usd/SubscribeSessionCallback.java b/framework/java/android/net/wifi/usd/SubscribeSessionCallback.java
new file mode 100644
index 0000000..659085d
--- /dev/null
+++ b/framework/java/android/net/wifi/usd/SubscribeSessionCallback.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.usd;
+
+import android.annotation.FlaggedApi;
+import android.annotation.NonNull;
+import android.annotation.RequiresApi;
+import android.annotation.SystemApi;
+import android.net.wifi.flags.Flags;
+import android.os.Build;
+
+
+/**
+ * USD subscribe session callbacks. Should be extended by applications wanting notifications.
+ *
+ * @hide
+ */
+@RequiresApi(Build.VERSION_CODES.BAKLAVA)
+@SystemApi
+@FlaggedApi(Flags.FLAG_USD)
+public class SubscribeSessionCallback extends SessionCallback {
+
+ /**
+ * Called when a subscribe session cannot be created.
+ *
+ * @param reason reason code as defined in {@code FAILURE_XXX}
+ */
+ public void onSubscribeFailed(@FailureCode int reason) {
+ }
+
+ /**
+ * Called when a subscribe operation is started successfully.
+ *
+ * @param session subscribe session
+ */
+ public void onSubscribeStarted(@NonNull SubscribeSession session) {
+ }
+
+ /**
+ * Called when a subscribe operation results in a service discovery.
+ *
+ * @param discoveryResult A structure containing information of the discovery session and
+ * discovered peer
+ */
+ public void onServiceDiscovered(@NonNull DiscoveryResult discoveryResult) {
+ }
+}
diff --git a/framework/java/android/net/wifi/usd/UsdManager.java b/framework/java/android/net/wifi/usd/UsdManager.java
new file mode 100644
index 0000000..98601ee
--- /dev/null
+++ b/framework/java/android/net/wifi/usd/UsdManager.java
@@ -0,0 +1,469 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.usd;
+
+import static android.Manifest.permission.MANAGE_WIFI_NETWORK_SELECTION;
+
+import android.annotation.CallbackExecutor;
+import android.annotation.FlaggedApi;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.RequiresApi;
+import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
+import android.annotation.SystemService;
+import android.content.Context;
+import android.net.wifi.IBooleanListener;
+import android.net.wifi.flags.Flags;
+import android.net.wifi.util.Environment;
+import android.os.Binder;
+import android.os.Build;
+import android.os.RemoteException;
+import android.util.Log;
+import android.util.SparseArray;
+
+import java.util.Objects;
+import java.util.concurrent.Executor;
+import java.util.function.Consumer;
+
+/**
+ * This class provides the APIs for managing Unsynchronized Service Discovery (USD). USD is a
+ * mechanism that allows devices to discover services offered by other devices without requiring
+ * prior time and channel synchronization. This feature is especially useful for quickly finding
+ * services on new devices entering the range.
+ *
+ * <p>A publisher device makes its services discoverable, and a subscriber device actively
+ * or passively searches for those services. Publishers in USD operate continuously, switching
+ * between single and multiple channel states to advertise their services. When a subscriber
+ * device receives a relevant service advertisement, it sends a follow-up message to the
+ * publisher, temporarily pausing the publisher on its current channel to facilitate further
+ * communication.
+ *
+ * <p>Once the discovery of device and service is complete, the subscriber and publisher perform
+ * further service discovery in which they exchange follow-up messages. The follow-up messages
+ * carry the service specific information useful for device and service configuration.
+ *
+ * <p>Note: This implementation adhere with Wi-Fi Aware Specification Version 4.0.
+ * @hide
+ */
+@RequiresApi(Build.VERSION_CODES.BAKLAVA)
+@SystemService(Context.WIFI_USD_SERVICE)
+@SystemApi
+@FlaggedApi(Flags.FLAG_USD)
+public class UsdManager {
+ private final Context mContext;
+ private final IUsdManager mService;
+ private static final String TAG = UsdManager.class.getName();
+
+ private static final SparseArray<IAvailabilityCallback> sAvailabilityCallbackMap =
+ new SparseArray<>();
+
+ /** @hide */
+ public UsdManager(@NonNull Context context, @NonNull IUsdManager service) {
+ mContext = context;
+ mService = service;
+ }
+
+ /** @hide */
+ public void sendMessage(int peerId, @NonNull byte[] message, @NonNull Executor executor,
+ @NonNull Consumer<Boolean> resultCallback) {
+ try {
+ mService.sendMessage(peerId, message, new IBooleanListener.Stub() {
+ @Override
+ public void onResult(boolean value) throws RemoteException {
+ Binder.clearCallingIdentity();
+ executor.execute(() -> resultCallback.accept(value));
+ }
+ });
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /** @hide */
+ public void cancelSubscribe(int sessionId) {
+ try {
+ mService.cancelSubscribe(sessionId);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /** @hide */
+ public void cancelPublish(int sessionId) {
+ try {
+ mService.cancelPublish(sessionId);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /** @hide */
+ public void updatePublish(int sessionId, byte[] serviceSpecificInfo) {
+ try {
+ mService.updatePublish(sessionId, serviceSpecificInfo);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Checks if the subscriber feature is currently available or not. Due to concurrent operations
+ * such as Station, SoftAP, Wi-Fi Aware, Wi-Fi Direct ..etc. the subscriber functionality
+ * may not be available.
+ *
+ * @return true if subscriber feature is available, otherwise false.
+ */
+ @RequiresPermission(MANAGE_WIFI_NETWORK_SELECTION)
+ public boolean isSubscriberAvailable() {
+ if (!Environment.isSdkAtLeastB()) {
+ throw new UnsupportedOperationException();
+ }
+ try {
+ return mService.isSubscriberAvailable();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+
+ /**
+ * Checks if the publisher feature is currently available or not. Due to concurrent
+ * operations such as Station, SoftAP, Wi-Fi Aware, Wi-Fi Direct ..etc. the publisher
+ * functionality may not be available.
+ *
+ * @return true if publisher feature is available, otherwise false.
+ */
+ @RequiresPermission(MANAGE_WIFI_NETWORK_SELECTION)
+ public boolean isPublisherAvailable() {
+ if (!Environment.isSdkAtLeastB()) {
+ throw new UnsupportedOperationException();
+ }
+ try {
+ return mService.isPublisherAvailable();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ private static class AvailabilityCallbackProxy extends IAvailabilityCallback.Stub {
+ private final Executor mExecutor;
+ private final AvailabilityCallback mAvailabilityCallback;
+
+ private AvailabilityCallbackProxy(Executor executor,
+ AvailabilityCallback availabilityCallback) {
+ mExecutor = executor;
+ mAvailabilityCallback = availabilityCallback;
+ }
+
+ @Override
+ public void onSubscriberAvailable() {
+ Log.d(TAG, "onSubscriberAvailable");
+ Binder.clearCallingIdentity();
+ mExecutor.execute(mAvailabilityCallback::onSubscriberAvailable);
+ }
+
+ @Override
+ public void onPublisherAvailable() {
+ Log.d(TAG, "onPublisherAvailable");
+ Binder.clearCallingIdentity();
+ mExecutor.execute(mAvailabilityCallback::onPublisherAvailable);
+ }
+ }
+
+ /**
+ * Interface for indicating publisher or subscriber availability.
+ */
+ public interface AvailabilityCallback {
+ /**
+ * Callback to notify subscriber functionality is available.
+ */
+ default void onSubscriberAvailable() {
+ }
+
+ /**
+ * Callback to notify publisher functionality is available.
+ */
+ default void onPublisherAvailable() {
+ }
+ }
+
+ /**
+ * Register for publisher or subscriber availability. Concurrent operations such as Station,
+ * SoftAP, Wi-Fi Aware, Wi-Fi Direct ..etc. impact the current availability of publisher or
+ * subscriber functionality.
+ *
+ * @param executor The Executor on whose thread to execute the callbacks of the {@code
+ * callback} object
+ * @param callback Callback for USD roles availability
+ * @throws NullPointerException if executor or callback is null
+ */
+ @RequiresPermission(MANAGE_WIFI_NETWORK_SELECTION)
+ public void registerAvailabilityCallback(@NonNull @CallbackExecutor Executor executor,
+ @NonNull AvailabilityCallback callback) {
+ Objects.requireNonNull(executor, "executor must not be null");
+ Objects.requireNonNull(callback, "callback must not be null");
+ if (!Environment.isSdkAtLeastB()) {
+ throw new UnsupportedOperationException();
+ }
+ final int callbackHash = System.identityHashCode(callback);
+ synchronized (sAvailabilityCallbackMap) {
+ try {
+ IAvailabilityCallback.Stub availabilityCallbackProxy =
+ new AvailabilityCallbackProxy(executor, callback);
+ sAvailabilityCallbackMap.put(callbackHash, availabilityCallbackProxy);
+ mService.registerAvailabilityCallback(availabilityCallbackProxy);
+ } catch (RemoteException e) {
+ sAvailabilityCallbackMap.remove(callbackHash);
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ }
+
+ /**
+ * Unregister the callback previously registered with
+ * {@link #registerAvailabilityCallback(Executor, AvailabilityCallback)}.
+ *
+ * @param callback a registered callback
+ * @throws NullPointerException if callback is null
+ */
+ @RequiresPermission(MANAGE_WIFI_NETWORK_SELECTION)
+ public void unregisterAvailabilityCallback(@NonNull AvailabilityCallback callback) {
+ Objects.requireNonNull(callback, "callback must not be null");
+ if (!Environment.isSdkAtLeastB()) {
+ throw new UnsupportedOperationException();
+ }
+ final int callbackHash = System.identityHashCode(callback);
+ synchronized (sAvailabilityCallbackMap) {
+ try {
+ if (!sAvailabilityCallbackMap.contains(callbackHash)) {
+ Log.w(TAG, "Unknown callback");
+ return;
+ }
+ mService.unregisterAvailabilityCallback(sAvailabilityCallbackMap.get(callbackHash));
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ } finally {
+ sAvailabilityCallbackMap.remove(callbackHash);
+ }
+ }
+ }
+
+ /**
+ * Gets the characteristics of USD: a set of parameters which specify limitations on
+ * configurations, e.g. maximum service name length.
+ *
+ * @return An object specifying the configuration limitation of USD. Return {@code null} if
+ * USD feature is not supported.
+ */
+ @RequiresPermission(MANAGE_WIFI_NETWORK_SELECTION)
+ public @Nullable Characteristics getCharacteristics() {
+ if (!Environment.isSdkAtLeastB()) {
+ throw new UnsupportedOperationException();
+ }
+ try {
+ return mService.getCharacteristics();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ private static class PublishSessionCallbackProxy extends IPublishSessionCallback.Stub {
+ private final Executor mExecutor;
+ private final PublishSessionCallback mPublishSessionCallback;
+ private final UsdManager mUsdManager;
+
+ private PublishSessionCallbackProxy(UsdManager usdManager, Executor executor,
+ PublishSessionCallback publishSessionCallback) {
+ mUsdManager = usdManager;
+ mExecutor = executor;
+ mPublishSessionCallback = publishSessionCallback;
+ }
+
+ @Override
+ public void onPublishFailed(int reasonCode) throws RemoteException {
+ Log.d(TAG, "onPublishFailed (reasonCode = " + reasonCode + " )");
+ Binder.clearCallingIdentity();
+ mExecutor.execute(() -> mPublishSessionCallback.onPublishFailed(reasonCode));
+ }
+
+ @Override
+ public void onPublishStarted(int sessionId) throws RemoteException {
+ Log.d(TAG, "onPublishStarted ( sessionId = " + sessionId + " )");
+ Binder.clearCallingIdentity();
+ mExecutor.execute(() -> mPublishSessionCallback.onPublishStarted(
+ new PublishSession(mUsdManager, sessionId)));
+ }
+
+ @Override
+ public void onPublishReplied(int peerId, byte[] ssi, int protoType, boolean isFsdEnabled)
+ throws RemoteException {
+ Log.d(TAG, "onPublishReplied ( peerId = " + peerId + ", protoType = " + protoType
+ + ", isFsdEnabled = " + isFsdEnabled + " )");
+ Binder.clearCallingIdentity();
+ DiscoveryResult discoveryResult = new DiscoveryResult.Builder(peerId)
+ .setServiceSpecificInfo(ssi)
+ .setServiceProtoType(protoType)
+ .setFsdEnabled(isFsdEnabled)
+ .build();
+ mExecutor.execute(() -> mPublishSessionCallback.onPublishReplied(discoveryResult));
+ }
+
+ @Override
+ public void onPublishSessionTerminated(int reasonCode) throws RemoteException {
+ Log.d(TAG, "onPublishSessionTerminated ( reasonCode = " + reasonCode + " )");
+ Binder.clearCallingIdentity();
+ mExecutor.execute(() -> mPublishSessionCallback.onSessionTerminated(reasonCode));
+ }
+
+ @Override
+ public void onMessageReceived(int peerId, byte[] message) throws RemoteException {
+ Log.d(TAG, "onMessageReceived ( peerId = " + peerId + " )");
+ Binder.clearCallingIdentity();
+ mExecutor.execute(() -> mPublishSessionCallback.onMessageReceived(peerId, message));
+ }
+ }
+
+
+ /**
+ * Issue a request to the USD service to create a new publish session using the specified
+ * {@link PublishConfig} configuration. The result of the publish operation are routed to the
+ * callbacks of {@link PublishSessionCallback}.
+ *
+ * <p>Note: Maximum number of publish sessions are limited by
+ * {@link Characteristics#getMaxNumberOfPublishSessions()}.
+ *
+ * @param publishConfig The {@link PublishConfig} specifying the configuration of the
+ * requested publish session.
+ * @param executor The Executor on whose thread to execute the callbacks of the
+ * {@link PublishSessionCallback}
+ * @param publishSessionCallback A {@link PublishSessionCallback} object to be used for session
+ * event callback
+ */
+ @RequiresPermission(MANAGE_WIFI_NETWORK_SELECTION)
+ public void publish(@NonNull PublishConfig publishConfig,
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull PublishSessionCallback publishSessionCallback) {
+ Objects.requireNonNull(publishConfig, "publishConfig must not be null");
+ Objects.requireNonNull(executor, "executor must not be null");
+ Objects.requireNonNull(publishSessionCallback, "publishSessionCallback must not be null");
+ if (!Environment.isSdkAtLeastB()) {
+ throw new UnsupportedOperationException();
+ }
+ try {
+ PublishSessionCallbackProxy publishSessionCallbackProxy =
+ new PublishSessionCallbackProxy(this, executor, publishSessionCallback);
+ mService.publish(publishConfig, publishSessionCallbackProxy);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ private static class SubscribeSessionCallbackProxy extends ISubscribeSessionCallback.Stub {
+ private final UsdManager mUsdManager;
+ private final Executor mExecutor;
+ private final SubscribeSessionCallback mSubscribeSessionCallback;
+
+ private SubscribeSessionCallbackProxy(UsdManager usdManager, Executor executor,
+ SubscribeSessionCallback subscribeSessionCallback) {
+ mUsdManager = usdManager;
+ mExecutor = executor;
+ mSubscribeSessionCallback = subscribeSessionCallback;
+ }
+
+ @Override
+ public void onSubscribeFailed(int reasonCode) throws RemoteException {
+ Log.d(TAG, "onSubscribeFailed (reasonCode = " + reasonCode + " )");
+ Binder.clearCallingIdentity();
+ mExecutor.execute(() -> mSubscribeSessionCallback.onSubscribeFailed(reasonCode));
+ }
+
+ @Override
+ public void onSubscribeStarted(int sessionId) throws RemoteException {
+ Log.d(TAG, "onSubscribeStarted ( sessionId = " + sessionId + " )");
+ Binder.clearCallingIdentity();
+ mExecutor.execute(() -> mSubscribeSessionCallback.onSubscribeStarted(
+ new SubscribeSession(mUsdManager, sessionId)));
+ }
+
+ @Override
+ public void onSubscribeDiscovered(int peerId, byte[] ssi, int protoType,
+ boolean isFsdEnabled)
+ throws RemoteException {
+ Log.d(TAG, "onSubscribeDiscovered ( peerId = " + peerId + ", protoType = " + protoType
+ + ", isFsdEnabled = " + isFsdEnabled + " )");
+ Binder.clearCallingIdentity();
+ DiscoveryResult discoveryResult = new DiscoveryResult.Builder(peerId)
+ .setServiceSpecificInfo(ssi)
+ .setServiceProtoType(protoType)
+ .setFsdEnabled(isFsdEnabled)
+ .build();
+ mExecutor.execute(() -> mSubscribeSessionCallback.onServiceDiscovered(discoveryResult));
+ }
+
+ @Override
+ public void onSubscribeSessionTerminated(int reasonCode) throws RemoteException {
+ Log.d(TAG, "onSubscribeSessionTerminated ( reasonCode = " + reasonCode + " )");
+ Binder.clearCallingIdentity();
+ mExecutor.execute(() -> mSubscribeSessionCallback.onSessionTerminated(reasonCode));
+ }
+
+ @Override
+ public void onMessageReceived(int peerId, byte[] message) throws RemoteException {
+ Log.d(TAG, "onMessageReceived ( peerId = " + peerId + " )");
+ Binder.clearCallingIdentity();
+ mExecutor.execute(() -> mSubscribeSessionCallback.onMessageReceived(peerId, message));
+ }
+ }
+
+
+ /**
+ * Issue a request to the USD service to create a new subscribe session using the specified
+ * {@link SubscribeConfig} configuration. The result of the subscribe operation are
+ * routed to
+ * the callbacks of {@link SubscribeSessionCallback}.
+ *
+ * <p>Note: Maximum number of subscribe sessions are limited by
+ * {@link Characteristics#getMaxNumberOfSubscribeSessions()}.
+ *
+ * @param subscribeConfig The {@link SubscribeConfig} specifying the
+ * configuration of the requested subscribe session.
+ * @param executor The Executor on whose thread to execute the callbacks of
+ * the {@link SubscribeSessionCallback}
+ * @param subscribeSessionCallback A {@link SubscribeSessionCallback} object to be used for
+ * session event callback
+ */
+ @RequiresPermission(MANAGE_WIFI_NETWORK_SELECTION)
+ public void subscribe(@NonNull SubscribeConfig subscribeConfig,
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull SubscribeSessionCallback subscribeSessionCallback) {
+ Objects.requireNonNull(subscribeConfig, "subscribeConfig must not be null");
+ Objects.requireNonNull(executor, "executor must not be null");
+ Objects.requireNonNull(subscribeSessionCallback,
+ "subscribeSessionCallback must not be null");
+ if (!Environment.isSdkAtLeastB()) {
+ throw new UnsupportedOperationException();
+ }
+ try {
+ SubscribeSessionCallbackProxy subscribeSessionCallbackProxy =
+ new SubscribeSessionCallbackProxy(this, executor, subscribeSessionCallback);
+ mService.subscribe(subscribeConfig, subscribeSessionCallbackProxy);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+}
diff --git a/framework/java/android/net/wifi/util/Environment.java b/framework/java/android/net/wifi/util/Environment.java
index f2e8266..f982658 100644
--- a/framework/java/android/net/wifi/util/Environment.java
+++ b/framework/java/android/net/wifi/util/Environment.java
@@ -90,4 +90,13 @@
}
return vndkApiLevel > apiLevel;
}
+
+ /**
+ * Check if the device has a SDK >= 36
+ * @return True if the SDK >= 36
+ */
+ public static boolean isSdkAtLeastB() {
+ return Build.VERSION.CODENAME.equals("Baklava")
+ || Build.VERSION.SDK_INT >= Build.VERSION_CODES.BAKLAVA;
+ }
}
diff --git a/framework/tests/Android.bp b/framework/tests/Android.bp
index 825fdab..0959110 100644
--- a/framework/tests/Android.bp
+++ b/framework/tests/Android.bp
@@ -42,6 +42,7 @@
"frameworks-base-testutils",
"guava",
"wifi-modules-utils",
+ "mockito-target-extended-minus-junit4",
"net-tests-utils",
"net-utils-framework-common",
"truth",
@@ -54,7 +55,6 @@
],
// These are required for mockito static/final mocking
- // mockito-target-extended-minus-junit4 is already included in frameworks-base-testutils
jni_libs: [
"libdexmakerjvmtiagent",
"libstaticjvmtiagent",
diff --git a/framework/tests/src/android/net/wifi/BlockingOptionTest.java b/framework/tests/src/android/net/wifi/BlockingOptionTest.java
new file mode 100644
index 0000000..99f0e54
--- /dev/null
+++ b/framework/tests/src/android/net/wifi/BlockingOptionTest.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.assertThrows;
+import static org.junit.Assert.assertTrue;
+
+import android.os.Parcel;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+
+@SmallTest
+public class BlockingOptionTest {
+
+ @Test
+ public void testBuilderWithValidInput() {
+ BlockingOption option = new BlockingOption.Builder(100)
+ .setBlockingBssidOnly(true)
+ .build();
+ assertEquals(100, option.getBlockingTimeSeconds());
+ assertTrue(option.isBlockingBssidOnly());
+ }
+
+ @Test
+ public void testBuilderWithInValidInput() {
+ assertThrows(IllegalArgumentException.class, () -> {
+ new BlockingOption.Builder(0)
+ .setBlockingBssidOnly(true)
+ .build();
+ });
+ assertThrows(IllegalArgumentException.class, () -> {
+ new BlockingOption.Builder(1000000)
+ .setBlockingBssidOnly(true)
+ .build();
+ });
+ }
+
+ @Test
+ public void testParcel() {
+ BlockingOption option = new BlockingOption.Builder(100)
+ .setBlockingBssidOnly(true)
+ .build();
+ Parcel parcelW = Parcel.obtain();
+ option.writeToParcel(parcelW, 0);
+ byte[] bytes = parcelW.marshall();
+ parcelW.recycle();
+
+ Parcel parcelR = Parcel.obtain();
+ parcelR.unmarshall(bytes, 0, bytes.length);
+ parcelR.setDataPosition(0);
+ BlockingOption parcelOption = BlockingOption.CREATOR.createFromParcel(parcelR);
+ assertEquals(option, parcelOption);
+ }
+}
diff --git a/framework/tests/src/android/net/wifi/SoftApConfigurationTest.java b/framework/tests/src/android/net/wifi/SoftApConfigurationTest.java
index b817177..7e4f5ea 100644
--- a/framework/tests/src/android/net/wifi/SoftApConfigurationTest.java
+++ b/framework/tests/src/android/net/wifi/SoftApConfigurationTest.java
@@ -22,6 +22,7 @@
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThrows;
@@ -32,6 +33,7 @@
import static org.mockito.Mockito.mock;
import android.net.MacAddress;
+import android.net.wifi.util.Environment;
import android.os.Parcel;
import android.os.PersistableBundle;
import android.util.SparseIntArray;
@@ -131,6 +133,9 @@
.isEqualTo(SoftApConfiguration.RANDOMIZATION_PERSISTENT);
}
}
+ if (Environment.isSdkAtLeastB()) {
+ assertFalse(original.isClientIsolationEnabled());
+ }
SoftApConfiguration unparceled = parcelUnparcel(original);
assertThat(unparceled).isNotSameInstanceAs(original);
@@ -229,7 +234,9 @@
originalBuilder.setBridgedModeOpportunisticShutdownTimeoutMillis(300_000);
originalBuilder.setVendorElements(TEST_TWO_VENDOR_ELEMENTS);
}
-
+ if (Environment.isSdkAtLeastB()) {
+ originalBuilder.setClientIsolationEnabled(true);
+ }
SoftApConfiguration original = originalBuilder.build();
assertThat(original.getPassphrase()).isEqualTo("secretsecret");
assertThat(original.getSecurityType()).isEqualTo(
@@ -261,6 +268,9 @@
assertThat(original.getVendorElements())
.isEqualTo(TEST_TWO_VENDOR_ELEMENTS);
}
+ if (Environment.isSdkAtLeastB()) {
+ assertTrue(original.isClientIsolationEnabled());
+ }
SoftApConfiguration unparceled = parcelUnparcel(original);
assertThat(unparceled).isNotSameInstanceAs(original);
diff --git a/framework/tests/src/android/net/wifi/SoftApInfoTest.java b/framework/tests/src/android/net/wifi/SoftApInfoTest.java
index b2f9e35..4a08492 100644
--- a/framework/tests/src/android/net/wifi/SoftApInfoTest.java
+++ b/framework/tests/src/android/net/wifi/SoftApInfoTest.java
@@ -41,6 +41,7 @@
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");
+ private static final MacAddress TEST_MLD_MAC = MacAddress.fromString("11:22:33:44:55:66");
private static final long TEST_SHUTDOWN_TIMEOUT_MILLIS = 100_000;
private static final List<OuiKeyedData> TEST_VENDOR_DATA =
OuiKeyedDataUtil.createTestOuiKeyedDataList(5);
@@ -56,6 +57,7 @@
info.setBssid(TEST_AP_MAC);
info.setWifiStandard(TEST_WIFI_STANDARD);
info.setApInstanceIdentifier(TEST_AP_INSTANCE);
+ info.setMldAddress(TEST_MLD_MAC);
if (SdkLevel.isAtLeastV()) {
info.setVendorData(TEST_VENDOR_DATA);
}
@@ -77,6 +79,7 @@
info.setBssid(TEST_AP_MAC);
info.setWifiStandard(TEST_WIFI_STANDARD);
info.setApInstanceIdentifier(TEST_AP_INSTANCE);
+ info.setMldAddress(TEST_MLD_MAC);
if (SdkLevel.isAtLeastV()) {
info.setVendorData(TEST_VENDOR_DATA);
}
@@ -112,6 +115,7 @@
if (SdkLevel.isAtLeastV()) {
assertNotNull(info.getVendorData());
}
+ assertEquals(info.getMldAddress(), null);
}
/**
@@ -126,6 +130,7 @@
info.setWifiStandard(TEST_WIFI_STANDARD);
info.setApInstanceIdentifier(TEST_AP_INSTANCE);
info.setAutoShutdownTimeoutMillis(TEST_SHUTDOWN_TIMEOUT_MILLIS);
+ info.setMldAddress(TEST_MLD_MAC);
assertEquals(info.getFrequency(), TEST_FREQUENCY);
assertEquals(info.getBandwidth(), TEST_BANDWIDTH);
if (SdkLevel.isAtLeastS()) {
@@ -138,6 +143,7 @@
info.setVendorData(TEST_VENDOR_DATA);
assertTrue(TEST_VENDOR_DATA.equals(info.getVendorData()));
}
+ assertEquals(info.getMldAddress(), TEST_MLD_MAC);
}
}
diff --git a/framework/tests/src/android/net/wifi/WifiClientTest.java b/framework/tests/src/android/net/wifi/WifiClientTest.java
index 7046563..2fa0d3c 100644
--- a/framework/tests/src/android/net/wifi/WifiClientTest.java
+++ b/framework/tests/src/android/net/wifi/WifiClientTest.java
@@ -34,17 +34,19 @@
@SmallTest
public class WifiClientTest {
private static final String INTERFACE_NAME = "wlan0";
+ private static final String INTERFACE_NAME_1 = "wlan1";
private static final String MAC_ADDRESS_STRING = "00:0a:95:9d:68:16";
private static final MacAddress MAC_ADDRESS = MacAddress.fromString(MAC_ADDRESS_STRING);
+ private static final int DISCONNECT_REASON = DeauthenticationReasonCode.REASON_DEAUTH_LEAVING;
/**
* Verify parcel write/read with WifiClient.
*/
@Test
public void testWifiClientParcelWriteRead() throws Exception {
- WifiClient writeWifiClient = new WifiClient(MAC_ADDRESS, INTERFACE_NAME);
+ WifiClient writeWifiClient = new WifiClient(MAC_ADDRESS, INTERFACE_NAME, DISCONNECT_REASON);
- assertParcelSane(writeWifiClient, 2);
+ assertParcelSane(writeWifiClient, 3);
}
/**
@@ -52,19 +54,20 @@
*/
@Test
public void testWifiClientEquals() throws Exception {
- WifiClient writeWifiClient = new WifiClient(MAC_ADDRESS, INTERFACE_NAME);
- WifiClient writeWifiClientEquals = new WifiClient(MAC_ADDRESS, INTERFACE_NAME);
+ WifiClient writeWifiClient = new WifiClient(MAC_ADDRESS, INTERFACE_NAME, DISCONNECT_REASON);
+ WifiClient writeWifiClientEquals = new WifiClient(MAC_ADDRESS, INTERFACE_NAME,
+ DISCONNECT_REASON);
assertEquals(writeWifiClient, writeWifiClientEquals);
assertEquals(writeWifiClient.hashCode(), writeWifiClientEquals.hashCode());
- assertFieldCountEquals(2, WifiClient.class);
+ assertFieldCountEquals(3, WifiClient.class);
}
/**
- * Verify not-equals with WifiClient.
+ * Verify not-equals for 2 WifiClients with different mac address.
*/
@Test
- public void testWifiClientNotEquals() throws Exception {
+ public void testWifiClientEqualsFailsWhenMacAddressIsDifferent() throws Exception {
final MacAddress macAddressNotEquals = MacAddress.fromString("00:00:00:00:00:00");
WifiClient writeWifiClient = new WifiClient(MAC_ADDRESS, INTERFACE_NAME);
WifiClient writeWifiClientNotEquals = new WifiClient(macAddressNotEquals, INTERFACE_NAME);
@@ -72,4 +75,51 @@
assertNotEquals(writeWifiClient, writeWifiClientNotEquals);
assertNotEquals(writeWifiClient.hashCode(), writeWifiClientNotEquals.hashCode());
}
+
+ /**
+ * Verify not-equals for 2 WifiClients with different interface name.
+ */
+ @Test
+ public void testWifiClientEqualsFailsWhenInstanceIsDifferent() throws Exception {
+ WifiClient writeWifiClient = new WifiClient(MAC_ADDRESS, INTERFACE_NAME);
+ WifiClient writeWifiClientNotEquals = new WifiClient(MAC_ADDRESS, INTERFACE_NAME_1);
+
+ assertNotEquals(writeWifiClient, writeWifiClientNotEquals);
+ assertNotEquals(writeWifiClient.hashCode(), writeWifiClientNotEquals.hashCode());
+ }
+
+ /**
+ * Verify not-equals for 2 WifiClients with different disconnect reason.
+ */
+ @Test
+ public void testWifiClientEqualsFailsWhenDisconnectReasonIsDifferent() throws Exception {
+ WifiClient writeWifiClient = new WifiClient(MAC_ADDRESS, INTERFACE_NAME, DISCONNECT_REASON);
+ WifiClient writeWifiClientNotEquals = new WifiClient(MAC_ADDRESS, INTERFACE_NAME,
+ DeauthenticationReasonCode.REASON_AKMP_NOT_VALID);
+
+ assertNotEquals(writeWifiClient, writeWifiClientNotEquals);
+ assertNotEquals(writeWifiClient.hashCode(), writeWifiClientNotEquals.hashCode());
+ }
+
+ /**
+ * Verify that getDisconnectReason() returns REASON_UNKNOWN as the default value.
+ */
+ @Test
+ public void testWifiClientGetDefaultDisconnectReason() throws Exception {
+ WifiClient wifiClient = new WifiClient(MAC_ADDRESS, INTERFACE_NAME);
+ assertEquals(wifiClient.getDisconnectReason(), DeauthenticationReasonCode.REASON_UNKNOWN);
+ }
+
+ /**
+ * Verify that all getter methods in WifiClient (getMacAddress(),
+ * getApInstanceIdentifier(), getDisconnectReason()) return the
+ * expected values when a WifiClient object is created with specific data.
+ */
+ @Test
+ public void testWifiClientGetMethods() throws Exception {
+ WifiClient wifiClient = new WifiClient(MAC_ADDRESS, INTERFACE_NAME, DISCONNECT_REASON);
+ assertEquals(wifiClient.getMacAddress(), MAC_ADDRESS);
+ assertEquals(wifiClient.getApInstanceIdentifier(), INTERFACE_NAME);
+ assertEquals(wifiClient.getDisconnectReason(), DISCONNECT_REASON);
+ }
}
diff --git a/framework/tests/src/android/net/wifi/WifiManagerTest.java b/framework/tests/src/android/net/wifi/WifiManagerTest.java
index 54c16f3..a029be2 100644
--- a/framework/tests/src/android/net/wifi/WifiManagerTest.java
+++ b/framework/tests/src/android/net/wifi/WifiManagerTest.java
@@ -53,10 +53,7 @@
import static android.net.wifi.WifiManager.WIFI_FEATURE_DPP_ENROLLEE_RESPONDER;
import static android.net.wifi.WifiManager.WIFI_FEATURE_DUAL_BAND_SIMULTANEOUS;
import static android.net.wifi.WifiManager.WIFI_FEATURE_OWE;
-import static android.net.wifi.WifiManager.WIFI_FEATURE_P2P;
-import static android.net.wifi.WifiManager.WIFI_FEATURE_PASSPOINT;
import static android.net.wifi.WifiManager.WIFI_FEATURE_PASSPOINT_TERMS_AND_CONDITIONS;
-import static android.net.wifi.WifiManager.WIFI_FEATURE_SCANNER;
import static android.net.wifi.WifiManager.WIFI_FEATURE_T2LM_NEGOTIATION;
import static android.net.wifi.WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE;
import static android.net.wifi.WifiManager.WIFI_FEATURE_WEP;
@@ -121,8 +118,11 @@
import android.net.wifi.WifiManager.WifiConnectedNetworkScorer;
import android.net.wifi.WifiUsabilityStatsEntry.ContentionTimeStats;
import android.net.wifi.WifiUsabilityStatsEntry.LinkStats;
+import android.net.wifi.WifiUsabilityStatsEntry.PacketStats;
+import android.net.wifi.WifiUsabilityStatsEntry.PeerInfo;
import android.net.wifi.WifiUsabilityStatsEntry.RadioStats;
import android.net.wifi.WifiUsabilityStatsEntry.RateStats;
+import android.net.wifi.WifiUsabilityStatsEntry.ScanResultWithSameFreq;
import android.net.wifi.twt.TwtRequest;
import android.net.wifi.twt.TwtSessionCallback;
import android.os.Build;
@@ -134,6 +134,7 @@
import android.os.test.TestLooper;
import android.util.ArraySet;
import android.util.SparseArray;
+import android.util.SparseIntArray;
import androidx.test.filters.SmallTest;
@@ -141,6 +142,8 @@
import com.android.modules.utils.build.SdkLevel;
import com.android.wifi.x.com.android.modules.utils.ParceledListSlice;
+import com.google.common.collect.ImmutableList;
+
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
@@ -190,6 +193,8 @@
private static final String TEST_SSID = "\"Test WiFi Networks\"";
private static final byte[] TEST_OUI = new byte[]{0x01, 0x02, 0x03};
private static final int TEST_LINK_LAYER_STATS_POLLING_INTERVAL_MS = 1000;
+ private static final int TEST_DISCONNECT_REASON =
+ DeauthenticationReasonCode.REASON_AUTHORIZED_ACCESS_LIMIT_REACHED;
private static final TetheringManager.TetheringRequest TEST_TETHERING_REQUEST =
new TetheringManager.TetheringRequest.Builder(TetheringManager.TETHERING_WIFI).build();
@@ -221,6 +226,7 @@
private WifiNetworkSuggestion mWifiNetworkSuggestion;
private ScanResultsCallback mScanResultsCallback;
private CoexCallback mCoexCallback;
+ private WifiManager.WifiStateChangedListener mWifiStateChangedListener;
private SubsystemRestartTrackingCallback mRestartCallback;
private int mRestartCallbackMethodRun = 0; // 1: restarting, 2: restarted
private WifiActivityEnergyInfo mWifiActivityEnergyInfo;
@@ -319,6 +325,7 @@
mRunnable.run();
}
};
+ mWifiStateChangedListener = () -> mRunnable.run();
if (SdkLevel.isAtLeastS()) {
mCoexCallback = new CoexCallback() {
@Override
@@ -597,7 +604,8 @@
SoftApConfiguration softApConfig = generatorTestSoftApConfig();
TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
when(mWifiService.startLocalOnlyHotspot(any(ILocalOnlyHotspotCallback.class), anyString(),
- nullable(String.class), eq(null), any())).thenReturn(REQUEST_REGISTERED);
+ nullable(String.class), eq(null), any(), anyBoolean()))
+ .thenReturn(REQUEST_REGISTERED);
mWifiManager.startLocalOnlyHotspot(callback, mHandler);
callback.onStarted(mWifiManager.new LocalOnlyHotspotReservation(softApConfig));
@@ -619,7 +627,8 @@
SoftApConfiguration softApConfig = generatorTestSoftApConfig();
TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
when(mWifiService.startLocalOnlyHotspot(any(ILocalOnlyHotspotCallback.class), anyString(),
- nullable(String.class), eq(null), any())).thenReturn(REQUEST_REGISTERED);
+ nullable(String.class), eq(null), any(), anyBoolean()))
+ .thenReturn(REQUEST_REGISTERED);
mWifiManager.startLocalOnlyHotspot(callback, mHandler);
callback.onStarted(mWifiManager.new LocalOnlyHotspotReservation(softApConfig));
@@ -797,7 +806,7 @@
mWifiManager.startLocalOnlyHotspot(callback, mHandler);
verify(mWifiService).startLocalOnlyHotspot(any(ILocalOnlyHotspotCallback.class),
- anyString(), nullable(String.class), eq(null), any());
+ anyString(), nullable(String.class), eq(null), any(), eq(false));
}
/**
@@ -809,7 +818,7 @@
TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
doThrow(new SecurityException()).when(mWifiService).startLocalOnlyHotspot(
any(ILocalOnlyHotspotCallback.class), anyString(), nullable(String.class),
- eq(null), any());
+ eq(null), any(), anyBoolean());
mWifiManager.startLocalOnlyHotspot(callback, mHandler);
}
@@ -822,7 +831,7 @@
TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
doThrow(new IllegalStateException()).when(mWifiService).startLocalOnlyHotspot(
any(ILocalOnlyHotspotCallback.class), anyString(), nullable(String.class),
- eq(null), any());
+ eq(null), any(), anyBoolean());
mWifiManager.startLocalOnlyHotspot(callback, mHandler);
}
@@ -833,7 +842,8 @@
public void testCorrectLooperIsUsedForHandler() throws Exception {
TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
when(mWifiService.startLocalOnlyHotspot(any(ILocalOnlyHotspotCallback.class), anyString(),
- nullable(String.class), eq(null), any())).thenReturn(ERROR_INCOMPATIBLE_MODE);
+ nullable(String.class), eq(null), any(), anyBoolean()))
+ .thenReturn(ERROR_INCOMPATIBLE_MODE);
mWifiManager.startLocalOnlyHotspot(callback, mHandler);
mLooper.dispatchAll();
assertEquals(ERROR_INCOMPATIBLE_MODE, callback.mFailureReason);
@@ -852,7 +862,8 @@
when(mContext.getMainExecutor()).thenReturn(altLooper.getNewExecutor());
TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
when(mWifiService.startLocalOnlyHotspot(any(ILocalOnlyHotspotCallback.class), anyString(),
- nullable(String.class), eq(null), any())).thenReturn(ERROR_INCOMPATIBLE_MODE);
+ nullable(String.class), eq(null), any(), anyBoolean()))
+ .thenReturn(ERROR_INCOMPATIBLE_MODE);
mWifiManager.startLocalOnlyHotspot(callback, null);
altLooper.dispatchAll();
assertEquals(ERROR_INCOMPATIBLE_MODE, callback.mFailureReason);
@@ -873,7 +884,8 @@
ArgumentCaptor<ILocalOnlyHotspotCallback> internalCallback =
ArgumentCaptor.forClass(ILocalOnlyHotspotCallback.class);
when(mWifiService.startLocalOnlyHotspot(internalCallback.capture(), anyString(),
- nullable(String.class), eq(null), any())).thenReturn(REQUEST_REGISTERED);
+ nullable(String.class), eq(null), any(), anyBoolean()))
+ .thenReturn(REQUEST_REGISTERED);
mWifiManager.startLocalOnlyHotspot(callback, callbackHandler);
callbackLooper.dispatchAll();
mLooper.dispatchAll();
@@ -905,7 +917,8 @@
ArgumentCaptor<ILocalOnlyHotspotCallback> internalCallback =
ArgumentCaptor.forClass(ILocalOnlyHotspotCallback.class);
when(mWifiService.startLocalOnlyHotspot(internalCallback.capture(), anyString(),
- nullable(String.class), eq(null), any())).thenReturn(REQUEST_REGISTERED);
+ nullable(String.class), eq(null), any(), anyBoolean()))
+ .thenReturn(REQUEST_REGISTERED);
mWifiManager.startLocalOnlyHotspot(callback, callbackHandler);
callbackLooper.dispatchAll();
mLooper.dispatchAll();
@@ -932,7 +945,8 @@
ArgumentCaptor<ILocalOnlyHotspotCallback> internalCallback =
ArgumentCaptor.forClass(ILocalOnlyHotspotCallback.class);
when(mWifiService.startLocalOnlyHotspot(internalCallback.capture(), anyString(),
- nullable(String.class), eq(null), any())).thenReturn(REQUEST_REGISTERED);
+ nullable(String.class), eq(null), any(), anyBoolean()))
+ .thenReturn(REQUEST_REGISTERED);
mWifiManager.startLocalOnlyHotspot(callback, callbackHandler);
callbackLooper.dispatchAll();
mLooper.dispatchAll();
@@ -957,7 +971,8 @@
ArgumentCaptor<ILocalOnlyHotspotCallback> internalCallback =
ArgumentCaptor.forClass(ILocalOnlyHotspotCallback.class);
when(mWifiService.startLocalOnlyHotspot(internalCallback.capture(), anyString(),
- nullable(String.class), eq(null), any())).thenReturn(REQUEST_REGISTERED);
+ nullable(String.class), eq(null), any(), anyBoolean()))
+ .thenReturn(REQUEST_REGISTERED);
mWifiManager.startLocalOnlyHotspot(callback, callbackHandler);
callbackLooper.dispatchAll();
mLooper.dispatchAll();
@@ -980,7 +995,8 @@
ArgumentCaptor<ILocalOnlyHotspotCallback> internalCallback =
ArgumentCaptor.forClass(ILocalOnlyHotspotCallback.class);
when(mWifiService.startLocalOnlyHotspot(internalCallback.capture(), anyString(),
- nullable(String.class), eq(null), any())).thenReturn(REQUEST_REGISTERED);
+ nullable(String.class), eq(null), any(), anyBoolean()))
+ .thenReturn(REQUEST_REGISTERED);
mWifiManager.startLocalOnlyHotspot(callback, callbackHandler);
callbackLooper.dispatchAll();
mLooper.dispatchAll();
@@ -999,7 +1015,8 @@
public void testLocalOnlyHotspotCallbackFullOnIncompatibleMode() throws Exception {
TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
when(mWifiService.startLocalOnlyHotspot(any(ILocalOnlyHotspotCallback.class), anyString(),
- nullable(String.class), eq(null), any())).thenReturn(ERROR_INCOMPATIBLE_MODE);
+ nullable(String.class), eq(null), any(), anyBoolean()))
+ .thenReturn(ERROR_INCOMPATIBLE_MODE);
mWifiManager.startLocalOnlyHotspot(callback, mHandler);
mLooper.dispatchAll();
assertEquals(ERROR_INCOMPATIBLE_MODE, callback.mFailureReason);
@@ -1015,7 +1032,8 @@
public void testLocalOnlyHotspotCallbackFullOnTetheringDisallowed() throws Exception {
TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
when(mWifiService.startLocalOnlyHotspot(any(ILocalOnlyHotspotCallback.class), anyString(),
- nullable(String.class), eq(null), any())).thenReturn(ERROR_TETHERING_DISALLOWED);
+ nullable(String.class), eq(null), any(), anyBoolean()))
+ .thenReturn(ERROR_TETHERING_DISALLOWED);
mWifiManager.startLocalOnlyHotspot(callback, mHandler);
mLooper.dispatchAll();
assertEquals(ERROR_TETHERING_DISALLOWED, callback.mFailureReason);
@@ -1033,7 +1051,7 @@
TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
doThrow(new SecurityException()).when(mWifiService).startLocalOnlyHotspot(
any(ILocalOnlyHotspotCallback.class), anyString(), nullable(String.class),
- eq(null), any());
+ eq(null), any(), anyBoolean());
try {
mWifiManager.startLocalOnlyHotspot(callback, mHandler);
} catch (SecurityException e) {
@@ -1054,7 +1072,8 @@
public void testLocalOnlyHotspotCallbackFullOnNoChannelError() throws Exception {
TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
when(mWifiService.startLocalOnlyHotspot(any(ILocalOnlyHotspotCallback.class), anyString(),
- nullable(String.class), eq(null), any())).thenReturn(REQUEST_REGISTERED);
+ nullable(String.class), eq(null), any(), anyBoolean()))
+ .thenReturn(REQUEST_REGISTERED);
mWifiManager.startLocalOnlyHotspot(callback, mHandler);
mLooper.dispatchAll();
//assertEquals(ERROR_NO_CHANNEL, callback.mFailureReason);
@@ -1070,7 +1089,8 @@
public void testCancelLocalOnlyHotspotRequestCallsStopOnWifiService() throws Exception {
TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
when(mWifiService.startLocalOnlyHotspot(any(ILocalOnlyHotspotCallback.class), anyString(),
- nullable(String.class), eq(null), any())).thenReturn(REQUEST_REGISTERED);
+ nullable(String.class), eq(null), any(), anyBoolean()))
+ .thenReturn(REQUEST_REGISTERED);
mWifiManager.startLocalOnlyHotspot(callback, mHandler);
mWifiManager.cancelLocalOnlyHotspotRequest();
verify(mWifiService).stopLocalOnlyHotspot();
@@ -1092,7 +1112,8 @@
public void testCallbackAfterLocalOnlyHotspotWasCancelled() throws Exception {
TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
when(mWifiService.startLocalOnlyHotspot(any(ILocalOnlyHotspotCallback.class), anyString(),
- nullable(String.class), eq(null), any())).thenReturn(REQUEST_REGISTERED);
+ nullable(String.class), eq(null), any(), anyBoolean()))
+ .thenReturn(REQUEST_REGISTERED);
mWifiManager.startLocalOnlyHotspot(callback, mHandler);
mWifiManager.cancelLocalOnlyHotspotRequest();
verify(mWifiService).stopLocalOnlyHotspot();
@@ -1111,7 +1132,8 @@
public void testCancelAfterLocalOnlyHotspotCallbackTriggered() throws Exception {
TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
when(mWifiService.startLocalOnlyHotspot(any(ILocalOnlyHotspotCallback.class), anyString(),
- nullable(String.class), eq(null), any())).thenReturn(ERROR_INCOMPATIBLE_MODE);
+ nullable(String.class), eq(null), any(), anyBoolean()))
+ .thenReturn(ERROR_INCOMPATIBLE_MODE);
mWifiManager.startLocalOnlyHotspot(callback, mHandler);
mLooper.dispatchAll();
assertEquals(ERROR_INCOMPATIBLE_MODE, callback.mFailureReason);
@@ -1130,7 +1152,7 @@
TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
mWifiManager.startLocalOnlyHotspot(customConfig, mExecutor, callback);
verify(mWifiService).startLocalOnlyHotspot(any(ILocalOnlyHotspotCallback.class),
- anyString(), nullable(String.class), eq(customConfig), any());
+ anyString(), nullable(String.class), eq(customConfig), any(), eq(true));
}
/**
@@ -1813,6 +1835,25 @@
}
/*
+ * Verify client-provided callback is being called through callback proxy.
+ */
+ @Test
+ public void softApCallbackProxyCallsOnClientsDisconnected() throws Exception {
+ WifiClient testWifiClient = new WifiClient(MacAddress.fromString("22:33:44:55:66:77"),
+ TEST_AP_INSTANCES[0], TEST_DISCONNECT_REASON);
+ ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor =
+ ArgumentCaptor.forClass(ISoftApCallback.Stub.class);
+ mWifiManager.registerSoftApCallback(new HandlerExecutor(mHandler), mSoftApCallback);
+ verify(mWifiService).registerSoftApCallback(callbackCaptor.capture());
+
+ callbackCaptor.getValue().onClientsDisconnected(mTestApInfo1,
+ ImmutableList.of(testWifiClient));
+ mLooper.dispatchAll();
+ verify(mSoftApCallback).onClientsDisconnected(mTestApInfo1,
+ ImmutableList.of(testWifiClient));
+ }
+
+ /*
* Verify client-provided callback is being called through callback proxy on multiple events
*/
@Test
@@ -2508,27 +2549,40 @@
contentionTimeStats[1] = new ContentionTimeStats(5, 6, 7, 8);
contentionTimeStats[2] = new ContentionTimeStats(9, 10, 11, 12);
contentionTimeStats[3] = new ContentionTimeStats(13, 14, 15, 16);
+ PacketStats[] packetStats = new PacketStats[4];
+ packetStats[0] = new PacketStats(1, 2, 3, 4);
+ packetStats[1] = new PacketStats(5, 6, 7, 8);
+ packetStats[2] = new PacketStats(9, 10, 11, 12);
+ packetStats[3] = new PacketStats(13, 14, 15, 16);
RateStats[] rateStats = new RateStats[2];
rateStats[0] = new RateStats(1, 3, 5, 7, 9, 11, 13, 15, 17);
rateStats[1] = new RateStats(2, 4, 6, 8, 10, 12, 14, 16, 18);
RadioStats[] radioStats = new RadioStats[2];
radioStats[0] = new RadioStats(0, 10, 11, 12, 13, 14, 15, 16, 17, 18);
- radioStats[1] = new RadioStats(1, 20, 21, 22, 23, 24, 25, 26, 27, 28);
+ radioStats[1] = new RadioStats(1, 20, 21, 22, 23, 24, 25, 26, 27, 28, new int[] {1, 2, 3});
+ PeerInfo[] peerInfo = new PeerInfo[1];
+ peerInfo[0] = new PeerInfo(1, 50, rateStats);
+ ScanResultWithSameFreq[] scanResultsWithSameFreq2G = new ScanResultWithSameFreq[1];
+ scanResultsWithSameFreq2G[0] = new ScanResultWithSameFreq(100, -50, 2412);
+ ScanResultWithSameFreq[] scanResultsWithSameFreq5G = new ScanResultWithSameFreq[1];
+ scanResultsWithSameFreq5G[0] = new ScanResultWithSameFreq(100, -50, 5500);
SparseArray<LinkStats> linkStats = new SparseArray<>();
linkStats.put(0,
- new LinkStats(0, WifiUsabilityStatsEntry.LINK_STATE_NOT_IN_USE, 0, -50, 300,
- 200,
- 188, 2, 2, 100, 300, 100, 100, 200,
- contentionTimeStats, rateStats));
+ new LinkStats(0, WifiUsabilityStatsEntry.LINK_STATE_NOT_IN_USE, 0, -50, 2412,
+ -50, 0, 0, 0, 300, 200, 188, 2, 2, 100, 300, 100, 100, 200,
+ contentionTimeStats, rateStats, packetStats, peerInfo,
+ scanResultsWithSameFreq2G));
linkStats.put(1,
- new LinkStats(0, WifiUsabilityStatsEntry.LINK_STATE_IN_USE, 0, -40, 860, 600,
- 388, 2, 2, 200, 400, 100, 100, 200,
- contentionTimeStats, rateStats));
+ new LinkStats(0, WifiUsabilityStatsEntry.LINK_STATE_IN_USE, 0, -40, 5500,
+ -40, 1, 0, 0, 860, 600, 388, 2, 2, 200, 400, 100, 100, 200,
+ contentionTimeStats, rateStats, packetStats, peerInfo,
+ scanResultsWithSameFreq5G));
callbackCaptor.getValue().onWifiUsabilityStats(1, true,
new WifiUsabilityStatsEntry(System.currentTimeMillis(), -50, 100, 10, 0, 5, 5,
100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 1, 100, 10,
100, 27, contentionTimeStats, rateStats, radioStats, 101, true, true, true,
- 0, 10, 10, true, linkStats));
+ 0, 10, 10, true, linkStats, 1, 0, 10, 20, 1, 2, 1, 1, 1, 1, false, 0,
+ false, 100, 100, 1, 3, 1));
verify(mOnWifiUsabilityStatsListener).onWifiUsabilityStats(anyInt(), anyBoolean(),
any(WifiUsabilityStatsEntry.class));
}
@@ -2553,11 +2607,11 @@
*/
@Test
public void testIsEnhancedOpenSupported() throws Exception {
- when(mWifiService.getSupportedFeatures())
- .thenReturn(new Long(WIFI_FEATURE_OWE));
+ when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_OWE)))
+ .thenReturn(true);
assertTrue(mWifiManager.isEnhancedOpenSupported());
- when(mWifiService.getSupportedFeatures())
- .thenReturn(new Long(~WIFI_FEATURE_OWE));
+ when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_OWE)))
+ .thenReturn(false);
assertFalse(mWifiManager.isEnhancedOpenSupported());
}
@@ -2566,11 +2620,11 @@
*/
@Test
public void testIsWpa3SaeSupported() throws Exception {
- when(mWifiService.getSupportedFeatures())
- .thenReturn(new Long(WIFI_FEATURE_WPA3_SAE));
+ when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_WPA3_SAE)))
+ .thenReturn(true);
assertTrue(mWifiManager.isWpa3SaeSupported());
- when(mWifiService.getSupportedFeatures())
- .thenReturn(new Long(~WIFI_FEATURE_WPA3_SAE));
+ when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_WPA3_SAE)))
+ .thenReturn(false);
assertFalse(mWifiManager.isWpa3SaeSupported());
}
@@ -2579,11 +2633,11 @@
*/
@Test
public void testIsWpa3SuiteBSupported() throws Exception {
- when(mWifiService.getSupportedFeatures())
- .thenReturn(new Long(WIFI_FEATURE_WPA3_SUITE_B));
+ when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_WPA3_SUITE_B)))
+ .thenReturn(true);
assertTrue(mWifiManager.isWpa3SuiteBSupported());
- when(mWifiService.getSupportedFeatures())
- .thenReturn(new Long(~WIFI_FEATURE_WPA3_SUITE_B));
+ when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_WPA3_SUITE_B)))
+ .thenReturn(false);
assertFalse(mWifiManager.isWpa3SuiteBSupported());
}
@@ -2592,11 +2646,11 @@
*/
@Test
public void testIsEasyConnectSupported() throws Exception {
- when(mWifiService.getSupportedFeatures())
- .thenReturn(new Long(WIFI_FEATURE_DPP));
+ when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_DPP)))
+ .thenReturn(true);
assertTrue(mWifiManager.isEasyConnectSupported());
- when(mWifiService.getSupportedFeatures())
- .thenReturn(new Long(~WIFI_FEATURE_DPP));
+ when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_DPP)))
+ .thenReturn(false);
assertFalse(mWifiManager.isEasyConnectSupported());
}
@@ -2605,11 +2659,11 @@
*/
@Test
public void testIsEasyConnectDppAkmSupported() throws Exception {
- when(mWifiService.getSupportedFeatures())
- .thenReturn(new Long(WIFI_FEATURE_DPP_AKM));
+ when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_DPP_AKM)))
+ .thenReturn(true);
assertTrue(mWifiManager.isEasyConnectDppAkmSupported());
- when(mWifiService.getSupportedFeatures())
- .thenReturn(new Long(~WIFI_FEATURE_DPP_AKM));
+ when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_DPP_AKM)))
+ .thenReturn(false);
assertFalse(mWifiManager.isEasyConnectDppAkmSupported());
}
@@ -2619,12 +2673,11 @@
@Test
public void testIsEasyConnectEnrolleeResponderModeSupported() throws Exception {
assumeTrue(SdkLevel.isAtLeastS());
-
- when(mWifiService.getSupportedFeatures())
- .thenReturn(new Long(WIFI_FEATURE_DPP_ENROLLEE_RESPONDER));
+ when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_DPP_ENROLLEE_RESPONDER)))
+ .thenReturn(true);
assertTrue(mWifiManager.isEasyConnectEnrolleeResponderModeSupported());
- when(mWifiService.getSupportedFeatures())
- .thenReturn(new Long(~WIFI_FEATURE_DPP_ENROLLEE_RESPONDER));
+ when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_DPP_ENROLLEE_RESPONDER)))
+ .thenReturn(false);
assertFalse(mWifiManager.isEasyConnectEnrolleeResponderModeSupported());
}
@@ -2633,11 +2686,11 @@
*/
@Test
public void testIsStaApConcurrencyOpenSupported() throws Exception {
- when(mWifiService.getSupportedFeatures())
- .thenReturn(new Long(WIFI_FEATURE_AP_STA));
+ when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_AP_STA)))
+ .thenReturn(true);
assertTrue(mWifiManager.isStaApConcurrencySupported());
- when(mWifiService.getSupportedFeatures())
- .thenReturn(new Long(~WIFI_FEATURE_AP_STA));
+ when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_AP_STA)))
+ .thenReturn(false);
assertFalse(mWifiManager.isStaApConcurrencySupported());
}
@@ -2646,23 +2699,27 @@
*/
@Test
public void testIsStaConcurrencySupported() throws Exception {
- when(mWifiService.getSupportedFeatures()).thenReturn(0L);
+ when(mWifiService.isFeatureSupported(anyInt())).thenReturn(false);
assertFalse(mWifiManager.isStaConcurrencyForLocalOnlyConnectionsSupported());
assertFalse(mWifiManager.isMakeBeforeBreakWifiSwitchingSupported());
assertFalse(mWifiManager.isStaConcurrencyForRestrictedConnectionsSupported());
assertFalse(mWifiManager.isStaConcurrencyForMultiInternetSupported());
- when(mWifiService.getSupportedFeatures())
- .thenReturn(new Long(WIFI_FEATURE_ADDITIONAL_STA_LOCAL_ONLY));
+ when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_ADDITIONAL_STA_LOCAL_ONLY)))
+ .thenReturn(true);
assertTrue(mWifiManager.isStaConcurrencyForLocalOnlyConnectionsSupported());
assertFalse(mWifiManager.isMakeBeforeBreakWifiSwitchingSupported());
assertFalse(mWifiManager.isStaConcurrencyForRestrictedConnectionsSupported());
assertFalse(mWifiManager.isStaConcurrencyForMultiInternetSupported());
- when(mWifiService.getSupportedFeatures())
- .thenReturn(new Long(WIFI_FEATURE_ADDITIONAL_STA_MBB
- | WIFI_FEATURE_ADDITIONAL_STA_RESTRICTED
- | WIFI_FEATURE_ADDITIONAL_STA_MULTI_INTERNET));
+ when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_ADDITIONAL_STA_LOCAL_ONLY)))
+ .thenReturn(false);
+ when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_ADDITIONAL_STA_MBB)))
+ .thenReturn(true);
+ when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_ADDITIONAL_STA_RESTRICTED)))
+ .thenReturn(true);
+ when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_ADDITIONAL_STA_MULTI_INTERNET)))
+ .thenReturn(true);
assertFalse(mWifiManager.isStaConcurrencyForLocalOnlyConnectionsSupported());
assertTrue(mWifiManager.isMakeBeforeBreakWifiSwitchingSupported());
assertTrue(mWifiManager.isStaConcurrencyForRestrictedConnectionsSupported());
@@ -2839,30 +2896,6 @@
}
/**
- * Test behavior of {@link WifiManager#getSupportedFeatures()}
- */
- @Test
- public void testGetSupportedFeatures() throws Exception {
- long supportedFeatures =
- WIFI_FEATURE_SCANNER
- | WIFI_FEATURE_PASSPOINT
- | WIFI_FEATURE_P2P;
- when(mWifiService.getSupportedFeatures())
- .thenReturn(Long.valueOf(supportedFeatures));
-
- assertTrue(mWifiManager.isWifiScannerSupported());
- assertTrue(mWifiManager.isPasspointSupported());
- assertTrue(mWifiManager.isP2pSupported());
- assertFalse(mWifiManager.isPortableHotspotSupported());
- assertFalse(mWifiManager.isDeviceToDeviceRttSupported());
- assertFalse(mWifiManager.isDeviceToApRttSupported());
- assertFalse(mWifiManager.isPreferredNetworkOffloadSupported());
- assertFalse(mWifiManager.isTdlsSupported());
- assertFalse(mWifiManager.isOffChannelTdlsSupported());
- assertFalse(mWifiManager.isEnhancedPowerReportingSupported());
- }
-
- /**
* Tests that passing a null Executor to {@link WifiManager#getWifiActivityEnergyInfoAsync}
* throws an exception.
*/
@@ -3245,11 +3278,9 @@
*/
@Test
public void testIsWapiSupported() throws Exception {
- when(mWifiService.getSupportedFeatures())
- .thenReturn(new Long(WifiManager.WIFI_FEATURE_WAPI));
+ when(mWifiService.isFeatureSupported(eq(WifiManager.WIFI_FEATURE_WAPI))).thenReturn(true);
assertTrue(mWifiManager.isWapiSupported());
- when(mWifiService.getSupportedFeatures())
- .thenReturn(new Long(~WifiManager.WIFI_FEATURE_WAPI));
+ when(mWifiService.isFeatureSupported(eq(WifiManager.WIFI_FEATURE_WAPI))).thenReturn(false);
assertFalse(mWifiManager.isWapiSupported());
}
@@ -3575,11 +3606,11 @@
*/
@Test
public void testIsPasspointTermsAndConditionsSupported() throws Exception {
- when(mWifiService.getSupportedFeatures())
- .thenReturn(new Long(WIFI_FEATURE_PASSPOINT_TERMS_AND_CONDITIONS));
+ when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_PASSPOINT_TERMS_AND_CONDITIONS)))
+ .thenReturn(true);
assertTrue(mWifiManager.isPasspointTermsAndConditionsSupported());
- when(mWifiService.getSupportedFeatures())
- .thenReturn(new Long(~WIFI_FEATURE_PASSPOINT_TERMS_AND_CONDITIONS));
+ when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_PASSPOINT_TERMS_AND_CONDITIONS)))
+ .thenReturn(false);
assertFalse(mWifiManager.isPasspointTermsAndConditionsSupported());
}
@@ -3643,11 +3674,11 @@
*/
@Test
public void testIsDecoratedIdentitySupported() throws Exception {
- when(mWifiService.getSupportedFeatures())
- .thenReturn(new Long(WIFI_FEATURE_DECORATED_IDENTITY));
+ when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_DECORATED_IDENTITY)))
+ .thenReturn(true);
assertTrue(mWifiManager.isDecoratedIdentitySupported());
- when(mWifiService.getSupportedFeatures())
- .thenReturn(new Long(~WIFI_FEATURE_DECORATED_IDENTITY));
+ when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_DECORATED_IDENTITY)))
+ .thenReturn(false);
assertFalse(mWifiManager.isDecoratedIdentitySupported());
}
@@ -3656,11 +3687,11 @@
*/
@Test
public void testIsTrustOnFirstUseSupported() throws Exception {
- when(mWifiService.getSupportedFeatures())
- .thenReturn(new Long(WIFI_FEATURE_TRUST_ON_FIRST_USE));
+ when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_TRUST_ON_FIRST_USE)))
+ .thenReturn(true);
assertTrue(mWifiManager.isTrustOnFirstUseSupported());
- when(mWifiService.getSupportedFeatures())
- .thenReturn(new Long(~WIFI_FEATURE_TRUST_ON_FIRST_USE));
+ when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_TRUST_ON_FIRST_USE)))
+ .thenReturn(false);
assertFalse(mWifiManager.isTrustOnFirstUseSupported());
}
@@ -3932,11 +3963,11 @@
*/
@Test
public void testIsStaConcurrencyForMultiInternetSupported() throws Exception {
- when(mWifiService.getSupportedFeatures())
- .thenReturn(new Long(WIFI_FEATURE_ADDITIONAL_STA_MULTI_INTERNET));
+ when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_ADDITIONAL_STA_MULTI_INTERNET)))
+ .thenReturn(true);
assertTrue(mWifiManager.isStaConcurrencyForMultiInternetSupported());
- when(mWifiService.getSupportedFeatures())
- .thenReturn(new Long(~WIFI_FEATURE_ADDITIONAL_STA_MULTI_INTERNET));
+ when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_ADDITIONAL_STA_MULTI_INTERNET)))
+ .thenReturn(false);
assertFalse(mWifiManager.isStaConcurrencyForMultiInternetSupported());
}
@@ -3966,11 +3997,11 @@
*/
@Test
public void testIsDualBandSimultaneousSupported() throws Exception {
- when(mWifiService.getSupportedFeatures())
- .thenReturn(new Long(WIFI_FEATURE_DUAL_BAND_SIMULTANEOUS));
+ when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_DUAL_BAND_SIMULTANEOUS)))
+ .thenReturn(true);
assertTrue(mWifiManager.isDualBandSimultaneousSupported());
- when(mWifiService.getSupportedFeatures())
- .thenReturn(new Long(~WIFI_FEATURE_DUAL_BAND_SIMULTANEOUS));
+ when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_DUAL_BAND_SIMULTANEOUS)))
+ .thenReturn(false);
assertFalse(mWifiManager.isDualBandSimultaneousSupported());
}
/*
@@ -3978,9 +4009,11 @@
*/
@Test
public void testIsTidToLinkMappingSupported() throws Exception {
- when(mWifiService.getSupportedFeatures()).thenReturn(WIFI_FEATURE_T2LM_NEGOTIATION);
+ when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_T2LM_NEGOTIATION)))
+ .thenReturn(true);
assertTrue(mWifiManager.isTidToLinkMappingNegotiationSupported());
- when(mWifiService.getSupportedFeatures()).thenReturn(~WIFI_FEATURE_T2LM_NEGOTIATION);
+ when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_T2LM_NEGOTIATION)))
+ .thenReturn(false);
assertFalse(mWifiManager.isTidToLinkMappingNegotiationSupported());
}
@@ -4158,11 +4191,11 @@
*/
@Test
public void testIsWepSupported() throws Exception {
- when(mWifiService.getSupportedFeatures())
- .thenReturn(new Long(WIFI_FEATURE_WEP));
+ when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_WEP)))
+ .thenReturn(true);
assertTrue(mWifiManager.isWepSupported());
- when(mWifiService.getSupportedFeatures())
- .thenReturn(new Long(~WIFI_FEATURE_WEP));
+ when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_WEP)))
+ .thenReturn(false);
assertFalse(mWifiManager.isWepSupported());
}
@@ -4171,11 +4204,11 @@
*/
@Test
public void testIsWpaPersonalSupported() throws Exception {
- when(mWifiService.getSupportedFeatures())
- .thenReturn(new Long(WIFI_FEATURE_WPA_PERSONAL));
+ when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_WPA_PERSONAL)))
+ .thenReturn(true);
assertTrue(mWifiManager.isWpaPersonalSupported());
- when(mWifiService.getSupportedFeatures())
- .thenReturn(new Long(~WIFI_FEATURE_WPA_PERSONAL));
+ when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_WPA_PERSONAL)))
+ .thenReturn(false);
assertFalse(mWifiManager.isWpaPersonalSupported());
}
@@ -4334,11 +4367,11 @@
*/
@Test
public void testIsD2dSupportedWhenInfraStaDisabled() throws Exception {
- when(mWifiService.getSupportedFeatures())
- .thenReturn(new Long(WIFI_FEATURE_D2D_WHEN_INFRA_STA_DISABLED));
+ when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_D2D_WHEN_INFRA_STA_DISABLED)))
+ .thenReturn(true);
assertTrue(mWifiManager.isD2dSupportedWhenInfraStaDisabled());
- when(mWifiService.getSupportedFeatures())
- .thenReturn(new Long(~WIFI_FEATURE_D2D_WHEN_INFRA_STA_DISABLED));
+ when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_D2D_WHEN_INFRA_STA_DISABLED)))
+ .thenReturn(false);
assertFalse(mWifiManager.isD2dSupportedWhenInfraStaDisabled());
}
@@ -4390,4 +4423,150 @@
mWifiManager.isPreferredNetworkOffloadSupported();
verify(mWifiService).isPnoSupported();
}
+
+ @Test
+ public void testSetAutojoinDisallowedSecurityTypesToWifiServiceImpl() throws Exception {
+ assumeTrue(SdkLevel.isAtLeastT());
+ int[] restrictions = {
+ WifiInfo.SECURITY_TYPE_OPEN,
+ WifiInfo.SECURITY_TYPE_WEP,
+ WifiInfo.SECURITY_TYPE_OWE };
+ int restrictionBitmap = (0x1 << WifiInfo.SECURITY_TYPE_OPEN)
+ | (0x1 << WifiInfo.SECURITY_TYPE_WEP)
+ | (0x1 << WifiInfo.SECURITY_TYPE_OWE);
+ ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
+ mWifiManager.setAutojoinDisallowedSecurityTypes(restrictions);
+ verify(mWifiService).setAutojoinDisallowedSecurityTypes(eq(restrictionBitmap),
+ bundleCaptor.capture());
+ assertEquals(mContext.getAttributionSource(),
+ bundleCaptor.getValue().getParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE));
+
+ // Null argument
+ assertThrows(NullPointerException.class,
+ () -> mWifiManager.setAutojoinDisallowedSecurityTypes(null));
+ }
+
+ @Test
+ public void testGetAutojoinDisallowedSecurityTypesToWifiServiceImpl() throws Exception {
+ assumeTrue(SdkLevel.isAtLeastT());
+ final int[] restrictionToSet = {
+ WifiInfo.SECURITY_TYPE_OPEN,
+ WifiInfo.SECURITY_TYPE_WEP,
+ WifiInfo.SECURITY_TYPE_OWE };
+
+ final int restrictionBitmap = (0x1 << WifiInfo.SECURITY_TYPE_OPEN)
+ | (0x1 << WifiInfo.SECURITY_TYPE_WEP)
+ | (0x1 << WifiInfo.SECURITY_TYPE_OWE);
+
+ SynchronousExecutor executor = mock(SynchronousExecutor.class);
+ Consumer<int[]> mockResultsCallback = mock(Consumer.class);
+
+ // null executor
+ assertThrows(NullPointerException.class,
+ () -> mWifiManager.getAutojoinDisallowedSecurityTypes(null, mockResultsCallback));
+ // null resultsCallback
+ assertThrows(NullPointerException.class,
+ () -> mWifiManager.getAutojoinDisallowedSecurityTypes(executor, null));
+
+ ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
+ ArgumentCaptor<IIntegerListener.Stub> cbCaptor = ArgumentCaptor.forClass(
+ IIntegerListener.Stub.class);
+
+ ArgumentCaptor<int[]> resultCaptor = ArgumentCaptor.forClass(int[].class);
+
+ mWifiManager.getAutojoinDisallowedSecurityTypes(new SynchronousExecutor(),
+ mockResultsCallback);
+ verify(mWifiService).getAutojoinDisallowedSecurityTypes(cbCaptor.capture(),
+ bundleCaptor.capture());
+ assertEquals(mContext.getAttributionSource(),
+ bundleCaptor.getValue().getParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE));
+
+ cbCaptor.getValue().onResult(restrictionBitmap);
+
+ verify(mockResultsCallback).accept(resultCaptor.capture());
+ assertArrayEquals(restrictionToSet, resultCaptor.getValue());
+ }
+
+ @Test
+ public void testStartLocalOnlyHotspotWithConfiguration() throws Exception {
+ // setChannels supported from S.
+ assumeTrue(SdkLevel.isAtLeastS());
+ SparseIntArray testChannel = new SparseIntArray(1);
+ testChannel.put(SoftApConfiguration.BAND_5GHZ, 0);
+ SoftApConfiguration customConfig = new SoftApConfiguration.Builder()
+ .setChannels(testChannel)
+ .build();
+ TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
+ mWifiManager.startLocalOnlyHotspotWithConfiguration(customConfig, mExecutor, callback);
+ SoftApConfiguration userConfig =
+ new SoftApConfiguration.Builder(customConfig)
+ .setUserConfiguration(true).build();
+ verify(mWifiService).startLocalOnlyHotspot(any(ILocalOnlyHotspotCallback.class),
+ anyString(), nullable(String.class), eq(userConfig), any(), eq(false));
+ assertThrows(NullPointerException.class,
+ () -> mWifiManager.startLocalOnlyHotspotWithConfiguration(
+ null, mExecutor, callback));
+ assertThrows(NullPointerException.class,
+ () -> mWifiManager.startLocalOnlyHotspotWithConfiguration(
+ customConfig, null, callback));
+ assertThrows(NullPointerException.class,
+ () -> mWifiManager.startLocalOnlyHotspotWithConfiguration(
+ customConfig, mExecutor, null));
+ }
+
+ /**
+ * Verify an IllegalArgumentException is thrown if listener is not provided.
+ */
+ @Test(expected = NullPointerException.class)
+ public void testAddWifiStateChangedListenerWithNullListener() throws Exception {
+ mWifiManager.addWifiStateChangedListener(mExecutor, null);
+ }
+
+ /**
+ * Verify an IllegalArgumentException is thrown if executor is not provided.
+ */
+ @Test(expected = NullPointerException.class)
+ public void testAddWifiStateChangedListenerWithNullExecutor() throws Exception {
+ mWifiManager.addWifiStateChangedListener(null, mWifiStateChangedListener);
+ }
+
+ /**
+ * Verify client provided listener is being called to the right listener.
+ */
+ @Test
+ public void testAddWifiStateChangedListenerAndReceiveEvent() throws Exception {
+ ArgumentCaptor<IWifiStateChangedListener.Stub> listenerCaptor =
+ ArgumentCaptor.forClass(IWifiStateChangedListener.Stub.class);
+ mWifiManager.addWifiStateChangedListener(new SynchronousExecutor(),
+ mWifiStateChangedListener);
+ verify(mWifiService).addWifiStateChangedListener(listenerCaptor.capture());
+ listenerCaptor.getValue().onWifiStateChanged();
+ verify(mRunnable).run();
+ }
+
+ /**
+ * Verify client removeWifiStateChangedListener.
+ */
+ @Test
+ public void testRemoveUnknownWifiStateChangedListener() throws Exception {
+ mWifiManager.removeWifiStateChangedListener(mWifiStateChangedListener);
+ verify(mWifiService, never()).removeWifiStateChangedListener(any());
+ }
+
+ /**
+ * Verify client removeWifiStateChangedListener with null listener will cause an exception.
+ */
+ @Test(expected = NullPointerException.class)
+ public void testRemoveWifiStateChangedListenerWithNullListener() throws Exception {
+ mWifiManager.removeWifiStateChangedListener(null);
+ }
+
+ @Test
+ public void testDisallowCurrentSuggestedNetwork() throws RemoteException {
+ assertThrows(NullPointerException.class,
+ () -> mWifiManager.disallowCurrentSuggestedNetwork(null));
+ BlockingOption option = new BlockingOption.Builder(100).build();
+ mWifiManager.disallowCurrentSuggestedNetwork(option);
+ verify(mWifiService).disallowCurrentSuggestedNetwork(eq(option), eq(TEST_PACKAGE_NAME));
+ }
}
diff --git a/framework/tests/src/android/net/wifi/WifiUsabilityStatsEntryTest.java b/framework/tests/src/android/net/wifi/WifiUsabilityStatsEntryTest.java
index 972c310..a70dc44 100644
--- a/framework/tests/src/android/net/wifi/WifiUsabilityStatsEntryTest.java
+++ b/framework/tests/src/android/net/wifi/WifiUsabilityStatsEntryTest.java
@@ -23,8 +23,11 @@
import static org.mockito.Mockito.validateMockitoUsage;
import android.net.wifi.WifiUsabilityStatsEntry.ContentionTimeStats;
+import android.net.wifi.WifiUsabilityStatsEntry.PacketStats;
+import android.net.wifi.WifiUsabilityStatsEntry.PeerInfo;
import android.net.wifi.WifiUsabilityStatsEntry.RadioStats;
import android.net.wifi.WifiUsabilityStatsEntry.RateStats;
+import android.net.wifi.WifiUsabilityStatsEntry.ScanResultWithSameFreq;
import android.os.Parcel;
import android.util.SparseArray;
@@ -80,37 +83,48 @@
contentionTimeStats[1] = new ContentionTimeStats(5, 6, 7, 8);
contentionTimeStats[2] = new ContentionTimeStats(9, 10, 11, 12);
contentionTimeStats[3] = new ContentionTimeStats(13, 14, 15, 16);
+ PacketStats[] packetStats = new PacketStats[4];
+ packetStats[0] = new PacketStats(1, 2, 3, 4);
+ packetStats[1] = new PacketStats(5, 6, 7, 8);
+ packetStats[2] = new PacketStats(9, 10, 11, 12);
+ packetStats[3] = new PacketStats(13, 14, 15, 16);
RateStats[] rateStats = new RateStats[2];
rateStats[0] = new RateStats(1, 3, 4, 7, 9, 11, 13, 15, 17);
rateStats[1] = new RateStats(2, 2, 3, 8, 10, 12, 14, 16, 18);
RadioStats[] radioStats = new RadioStats[2];
radioStats[0] = new RadioStats(0, 10, 11, 12, 13, 14, 15, 16, 17, 18);
- radioStats[1] = new RadioStats(1, 20, 21, 22, 23, 24, 25, 26, 27, 28);
+ radioStats[1] = new RadioStats(1, 20, 21, 22, 23, 24, 25, 26, 27, 28, new int[] {1, 2, 3});
+ PeerInfo[] peerInfo = new PeerInfo[1];
+ peerInfo[0] = new PeerInfo(1, 50, rateStats);
+ ScanResultWithSameFreq[] scanResultsWithSameFreq2G = new ScanResultWithSameFreq[1];
+ scanResultsWithSameFreq2G[0] = new ScanResultWithSameFreq(100, -50, 2412);
+ ScanResultWithSameFreq[] scanResultsWithSameFreq5G = new ScanResultWithSameFreq[1];
+ scanResultsWithSameFreq5G[0] = new ScanResultWithSameFreq(100, -50, 5500);
SparseArray<WifiUsabilityStatsEntry.LinkStats> linkStats = new SparseArray<>();
linkStats.put(0, new WifiUsabilityStatsEntry.LinkStats(0,
- WifiUsabilityStatsEntry.LINK_STATE_UNKNOWN, 0, -50, 300, 200, 188, 2, 2,
- 100,
- 300, 100, 100, 200,
- contentionTimeStats, rateStats));
+ WifiUsabilityStatsEntry.LINK_STATE_UNKNOWN, 0, -50, 2412, -50, 0, 0, 0,
+ 300, 200, 188, 2, 2, 100, 300, 100, 100, 200,
+ contentionTimeStats, rateStats, packetStats, peerInfo, scanResultsWithSameFreq2G));
linkStats.put(1, new WifiUsabilityStatsEntry.LinkStats(1,
- WifiUsabilityStatsEntry.LINK_STATE_UNKNOWN, 0, -40, 860, 600, 388, 2, 2,
- 200,
- 400, 100, 150, 300,
- contentionTimeStats, rateStats));
+ WifiUsabilityStatsEntry.LINK_STATE_UNKNOWN, 0, -40, 5500, -40, 1, 0, 0,
+ 860, 600, 388, 2, 2, 200, 400, 100, 150, 300,
+ contentionTimeStats, rateStats, packetStats, peerInfo, scanResultsWithSameFreq5G));
WifiUsabilityStatsEntry usabilityStatsEntry = new WifiUsabilityStatsEntry(
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
32, contentionTimeStats, rateStats, radioStats, 100, true,
- true, true, 23, 24, 25, true, linkStats);
+ true, true, 23, 24, 25, true, linkStats, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
+ false, 36, false, 37, 38, 39, 40, 41);
assertEquals(32, usabilityStatsEntry.getTimeSliceDutyCycleInPercent());
WifiUsabilityStatsEntry usabilityStatsEntryWithInvalidDutyCycleValue =
new WifiUsabilityStatsEntry(
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
21, 22, -1, contentionTimeStats, rateStats, radioStats, 101, true, true,
- true, 23, 24, 25, true, linkStats);
+ true, 23, 24, 25, true, linkStats, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
+ true, 36, true, 37, 38, 39, 40, 41);
try {
usabilityStatsEntryWithInvalidDutyCycleValue.getTimeSliceDutyCycleInPercent();
fail();
@@ -136,27 +150,39 @@
contentionTimeStats[1] = new ContentionTimeStats(5, 6, 7, 8);
contentionTimeStats[2] = new ContentionTimeStats(9, 10, 11, 12);
contentionTimeStats[3] = new ContentionTimeStats(13, 14, 15, 16);
+ PacketStats[] packetStats = new PacketStats[4];
+ packetStats[0] = new PacketStats(1, 2, 3, 4);
+ packetStats[1] = new PacketStats(5, 6, 7, 8);
+ packetStats[2] = new PacketStats(9, 10, 11, 12);
+ packetStats[3] = new PacketStats(13, 14, 15, 16);
RateStats[] rateStats = new RateStats[2];
rateStats[0] = new RateStats(1, 3, 4, 7, 9, 11, 13, 15, 17);
rateStats[1] = new RateStats(2, 2, 3, 8, 10, 12, 14, 16, 18);
RadioStats[] radioStats = new RadioStats[2];
radioStats[0] = new RadioStats(0, 10, 11, 12, 13, 14, 15, 16, 17, 18);
- radioStats[1] = new RadioStats(1, 20, 21, 22, 23, 24, 25, 26, 27, 28);
+ radioStats[1] = new RadioStats(1, 20, 21, 22, 23, 24, 25, 26, 27, 28, new int[] {1, 2, 3});
+ PeerInfo[] peerInfo = new PeerInfo[1];
+ peerInfo[0] = new PeerInfo(1, 50, rateStats);
+ ScanResultWithSameFreq[] scanResultsWithSameFreq2G = new ScanResultWithSameFreq[1];
+ scanResultsWithSameFreq2G[0] = new ScanResultWithSameFreq(100, -50, 2412);
+ ScanResultWithSameFreq[] scanResultsWithSameFreq5G = new ScanResultWithSameFreq[1];
+ scanResultsWithSameFreq5G[0] = new ScanResultWithSameFreq(100, -50, 5500);
SparseArray<WifiUsabilityStatsEntry.LinkStats> linkStats = new SparseArray<>();
linkStats.put(0, new WifiUsabilityStatsEntry.LinkStats(3,
- WifiUsabilityStatsEntry.LINK_STATE_IN_USE, 0, -50, 300, 200, 188, 2, 2, 100,
- 300, 100, 100, 200,
- contentionTimeStats, rateStats));
+ WifiUsabilityStatsEntry.LINK_STATE_IN_USE, 0, -50, 2412, -50, 0, 0, 0, 300,
+ 200, 188, 2, 2, 100, 300, 100, 100, 200,
+ contentionTimeStats, rateStats, packetStats, peerInfo, scanResultsWithSameFreq2G));
linkStats.put(1, new WifiUsabilityStatsEntry.LinkStats(8,
- WifiUsabilityStatsEntry.LINK_STATE_IN_USE, 0, -40, 860, 600, 388, 2, 2, 200,
- 400, 100, 150, 300,
- contentionTimeStats, rateStats));
+ WifiUsabilityStatsEntry.LINK_STATE_IN_USE, 0, -40, 5500, -40, 1, 0, 0, 860,
+ 600, 388, 2, 2, 200, 400, 100, 150, 300,
+ contentionTimeStats, rateStats, packetStats, peerInfo, scanResultsWithSameFreq5G));
return new WifiUsabilityStatsEntry(
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
50, contentionTimeStats, rateStats, radioStats, 102, true,
- true, true, 23, 24, 25, true, linkStats
+ true, true, 23, 24, 25, true, linkStats, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
+ true, 36, false, 37, 38, 39, 40, 41
);
}
@@ -336,6 +362,13 @@
for (int link : links) {
assertEquals(expected.getRssi(link), actual.getRssi(link));
assertEquals(expected.getRadioId(link), actual.getRadioId(link));
+ assertEquals(expected.getFrequencyMhz(link), actual.getFrequencyMhz(link));
+ assertEquals(expected.getRssiMgmt(link), actual.getRssiMgmt(link));
+ assertEquals(expected.getChannelWidth(link), actual.getChannelWidth(link));
+ assertEquals(expected.getCenterFreqFirstSegment(link),
+ actual.getCenterFreqFirstSegment(link));
+ assertEquals(expected.getCenterFreqSecondSegment(link),
+ actual.getCenterFreqSecondSegment(link));
assertEquals(expected.getTxLinkSpeedMbps(link),
actual.getTxLinkSpeedMbps(link));
assertEquals(expected.getRxLinkSpeedMbps(link),
@@ -467,6 +500,118 @@
actual.getContentionTimeStats(link,
WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_VO)
.getContentionNumSamples());
+ assertEquals(
+ expected.getPacketStats(link,
+ WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_BE)
+ .getTxSuccess(),
+ actual.getPacketStats(link,
+ WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_BE)
+ .getTxSuccess());
+ assertEquals(
+ expected.getPacketStats(link,
+ WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_BE)
+ .getTxRetries(),
+ actual.getPacketStats(link,
+ WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_BE)
+ .getTxRetries());
+ assertEquals(
+ expected.getPacketStats(link,
+ WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_BE)
+ .getTxBad(),
+ actual.getPacketStats(link,
+ WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_BE)
+ .getTxBad());
+ assertEquals(
+ expected.getPacketStats(link,
+ WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_BE)
+ .getRxSuccess(),
+ actual.getPacketStats(link,
+ WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_BE)
+ .getRxSuccess());
+ assertEquals(
+ expected.getPacketStats(link,
+ WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_BK)
+ .getTxSuccess(),
+ actual.getPacketStats(link,
+ WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_BK)
+ .getTxSuccess());
+ assertEquals(
+ expected.getPacketStats(link,
+ WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_BK)
+ .getTxRetries(),
+ actual.getPacketStats(link,
+ WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_BK)
+ .getTxRetries());
+ assertEquals(
+ expected.getPacketStats(link,
+ WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_BK)
+ .getTxBad(),
+ actual.getPacketStats(link,
+ WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_BK)
+ .getTxBad());
+ assertEquals(
+ expected.getPacketStats(link,
+ WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_BK)
+ .getRxSuccess(),
+ actual.getPacketStats(link,
+ WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_BK)
+ .getRxSuccess());
+ assertEquals(
+ expected.getPacketStats(link,
+ WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_VI)
+ .getTxSuccess(),
+ actual.getPacketStats(link,
+ WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_VI)
+ .getTxSuccess());
+ assertEquals(
+ expected.getPacketStats(link,
+ WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_VI)
+ .getTxRetries(),
+ actual.getPacketStats(link,
+ WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_VI)
+ .getTxRetries());
+ assertEquals(
+ expected.getPacketStats(link,
+ WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_VI)
+ .getTxBad(),
+ actual.getPacketStats(link,
+ WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_VI)
+ .getTxBad());
+ assertEquals(
+ expected.getPacketStats(link,
+ WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_VI)
+ .getRxSuccess(),
+ actual.getPacketStats(link,
+ WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_VI)
+ .getRxSuccess());
+ assertEquals(
+ expected.getPacketStats(link,
+ WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_VO)
+ .getTxSuccess(),
+ actual.getPacketStats(link,
+ WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_VO)
+ .getTxSuccess());
+ assertEquals(
+ expected.getPacketStats(link,
+ WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_VO)
+ .getTxRetries(),
+ actual.getPacketStats(link,
+ WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_VO)
+ .getTxRetries());
+ assertEquals(
+ expected.getPacketStats(link,
+ WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_VO)
+ .getTxBad(),
+ actual.getPacketStats(link,
+ WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_VO)
+ .getTxBad());
+ assertEquals(
+ expected.getPacketStats(link,
+ WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_VO)
+ .getRxSuccess(),
+ actual.getPacketStats(link,
+ WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_VO)
+ .getRxSuccess());
for (int j = 0; j < expected.getRateStats(link).size(); j++) {
RateStats expectedStats = expected.getRateStats(link).get(j);
@@ -483,9 +628,35 @@
assertEquals(expectedStats.getMpduLost(), actualStats.getMpduLost());
assertEquals(expectedStats.getRetries(), actualStats.getRetries());
}
-
+ for (int j = 0; j < expected.getPeerInfo(link).size(); j++) {
+ PeerInfo expectedStats = expected.getPeerInfo(link).get(j);
+ PeerInfo actualStats = actual.getPeerInfo(link).get(j);
+ assertEquals(expectedStats.getStaCount(), actualStats.getStaCount());
+ assertEquals(expectedStats.getChanUtil(), actualStats.getChanUtil());
+ }
+ for (int j = 0; j < expected.getScanResultsWithSameFreq(link).length; j++) {
+ assertEquals(expected.getScanResultsWithSameFreq(link)[j]
+ .getScanResultTimestampMicros(),
+ actual.getScanResultsWithSameFreq(link)[j]
+ .getScanResultTimestampMicros());
+ assertEquals(expected.getScanResultsWithSameFreq(link)[j].getRssi(),
+ actual.getScanResultsWithSameFreq(link)[j].getRssi());
+ assertEquals(expected.getScanResultsWithSameFreq(link)[j].getFrequency(),
+ actual.getScanResultsWithSameFreq(link)[j].getFrequency());
+ }
}
}
+ assertEquals(expected.getWifiLinkCount(), actual.getWifiLinkCount());
+ assertEquals(expected.isNetworkCapabilitiesDownstreamSufficient(),
+ actual.isNetworkCapabilitiesDownstreamSufficient());
+ assertEquals(expected.isNetworkCapabilitiesUpstreamSufficient(),
+ actual.isNetworkCapabilitiesUpstreamSufficient());
+ assertEquals(expected.isThroughputPredictorDownstreamSufficient(),
+ actual.isThroughputPredictorDownstreamSufficient());
+ assertEquals(expected.isThroughputPredictorUpstreamSufficient(),
+ actual.isThroughputPredictorUpstreamSufficient());
+ assertEquals(expected.isBluetoothConnected(), actual.isBluetoothConnected());
+ assertEquals(expected.getStatusDataStall(), actual.getStatusDataStall());
}
/**
@@ -496,14 +667,14 @@
SparseArray<WifiUsabilityStatsEntry.LinkStats> linkStats = new SparseArray<>();
linkStats.put(0, new WifiUsabilityStatsEntry.LinkStats(0,
- WifiUsabilityStatsEntry.LINK_STATE_IN_USE, 0, -50, 300, 200, 188, 2, 2, 100,
- 300, 100, 100, 200,
- null, null));
+ WifiUsabilityStatsEntry.LINK_STATE_IN_USE, 0, -50, 2412, -50, 0, 0, 0, 300,
+ 200, 188, 2, 2, 100, 300, 100, 100, 200,
+ null, null, null, null, null));
WifiUsabilityStatsEntry usabilityStatsEntry = new WifiUsabilityStatsEntry(
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
- 32, null, null, null, 100, true,
- true, true, 23, 24, 25, true, linkStats);
+ 32, null, null, null, 100, true, true, true, 23, 24, 25, true, linkStats, 26, 27,
+ 28, 29, 30, 31, 32, 33, 34, 35, true, 36, true, 37, 38, 39, 40, 41);
assertThrows("linkId is invalid - " + MloLink.INVALID_MLO_LINK_ID,
NoSuchElementException.class,
diff --git a/framework/tests/src/android/net/wifi/p2p/WifiP2pConfigTest.java b/framework/tests/src/android/net/wifi/p2p/WifiP2pConfigTest.java
index 15eba6f..b11daab 100644
--- a/framework/tests/src/android/net/wifi/p2p/WifiP2pConfigTest.java
+++ b/framework/tests/src/android/net/wifi/p2p/WifiP2pConfigTest.java
@@ -18,15 +18,20 @@
import static android.net.wifi.p2p.WifiP2pConfig.GROUP_CLIENT_IP_PROVISIONING_MODE_IPV4_DHCP;
import static android.net.wifi.p2p.WifiP2pConfig.GROUP_CLIENT_IP_PROVISIONING_MODE_IPV6_LINK_LOCAL;
+import static android.net.wifi.p2p.WifiP2pConfig.P2P_VERSION_2;
+import static android.net.wifi.p2p.WifiP2pConfig.PCC_MODE_CONNECTION_TYPE_LEGACY_OR_R2;
+import static android.net.wifi.p2p.WifiP2pConfig.PCC_MODE_CONNECTION_TYPE_R2_ONLY;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.junit.Assume.assumeTrue;
import android.net.MacAddress;
import android.net.wifi.OuiKeyedDataUtil;
+import android.net.wifi.util.Environment;
import android.os.Parcel;
import androidx.test.filters.SmallTest;
@@ -42,6 +47,8 @@
public class WifiP2pConfigTest {
private static final String DEVICE_ADDRESS = "aa:bb:cc:dd:ee:ff";
+ private static final String TEST_NETWORK_NAME = "DIRECT-xy-Android";
+ private static final String TEST_PASSPHRASE = "password";
/**
* Check network name setter
*/
@@ -108,12 +115,18 @@
@Test
public void testBuilderInvalidPassphrase() throws Exception {
WifiP2pConfig.Builder b = new WifiP2pConfig.Builder();
-
// sunny case
try {
- b.setPassphrase("abcd1234");
+ b.setPassphrase(TEST_PASSPHRASE);
} catch (IllegalArgumentException e) {
- fail("Unexpected IllegalArgumentException");
+ throw new AssertionError("the test failed", e);
+ }
+
+ // sunny case - password length of less than 128bytes
+ try {
+ b.setPassphrase("abed");
+ } catch (IllegalArgumentException e) {
+ throw new AssertionError("the test failed", e);
}
// null string.
@@ -122,11 +135,46 @@
fail("should throw IllegalArgumentException");
} catch (IllegalArgumentException e) {
// expected exception.
+ } catch (NullPointerException e) {
+ // expected exception.
+ }
+
+ // empty string.
+ try {
+ b.setPassphrase("");
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected exception.
+ }
+
+ // Password length of more than 128bytes .
+ try {
+ b.setPassphrase("j7YxZqK2gD5fT8rN9bW6hL0vQ3pO1mK4jU7iY9zX8cV5bN2hG1fS6dJ3kH0g"
+ + "L9wQ8rP7oM6nN5lK4mJ3iO2uY1tX0zW9vU8hG7fS6eD5cR4baa7YxZqK2gD5fT8rN9"
+ + "bW6hL0vQ2sweder");
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected exception.
+ }
+
+ WifiP2pConfig.Builder c = new WifiP2pConfig.Builder();
+
+ // sunny case
+ try {
+ c.setDeviceAddress(MacAddress.fromString(DEVICE_ADDRESS))
+ .setNetworkName(TEST_NETWORK_NAME)
+ .setPassphrase(TEST_PASSPHRASE)
+ .build();
+ } catch (IllegalArgumentException e) {
+ throw new AssertionError("the test failed", e);
}
// less than 8 characters.
try {
- b.setPassphrase("12abcde");
+ c.setDeviceAddress(MacAddress.fromString(DEVICE_ADDRESS))
+ .setNetworkName(TEST_NETWORK_NAME)
+ .setPassphrase("12abide")
+ .build();
fail("should throw IllegalArgumentException");
} catch (IllegalArgumentException e) {
// expected exception.
@@ -134,14 +182,86 @@
// more than 63 characters.
try {
- b.setPassphrase(
- "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890+/");
+ c.setDeviceAddress(MacAddress.fromString(DEVICE_ADDRESS))
+ .setNetworkName(TEST_NETWORK_NAME)
+ .setPassphrase("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQ"
+ + "RSTUVWXYZ1234567890+/")
+ .build();
fail("should throw IllegalArgumentException");
} catch (IllegalArgumentException e) {
// expected exception.
}
}
+ /**
+ * Check Pcc Mode passphrase setter
+ */
+ @Test
+ public void testPccModeBuilderSetterInvalidPassphrase() throws Exception {
+ assumeTrue(Environment.isSdkAtLeastB());
+
+ WifiP2pConfig.Builder c = new WifiP2pConfig.Builder();
+
+ // sunny case
+ try {
+ c.setDeviceAddress(MacAddress.fromString(DEVICE_ADDRESS))
+ .setNetworkName(TEST_NETWORK_NAME)
+ .setPassphrase(TEST_PASSPHRASE)
+ .setPccModeConnectionType(PCC_MODE_CONNECTION_TYPE_LEGACY_OR_R2)
+ .build();
+ } catch (IllegalArgumentException e) {
+ throw new AssertionError("the test failed", e);
+ }
+
+ // more than 63 characters in PCC Mode is not allowed.
+ try {
+ c.setDeviceAddress(MacAddress.fromString(DEVICE_ADDRESS))
+ .setNetworkName(TEST_NETWORK_NAME)
+ .setPassphrase("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQ"
+ + "RSTUVWXYZ1234567890+/")
+ .setPccModeConnectionType(PCC_MODE_CONNECTION_TYPE_LEGACY_OR_R2)
+ .build();
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected exception.
+ }
+
+ // less than 8 characters in PCC Mode is not allowed.
+ try {
+ c.setDeviceAddress(MacAddress.fromString(DEVICE_ADDRESS))
+ .setNetworkName(TEST_NETWORK_NAME)
+ .setPassphrase("12abcde")
+ .setPccModeConnectionType(PCC_MODE_CONNECTION_TYPE_LEGACY_OR_R2)
+ .build();
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected exception.
+ }
+
+ // less than 8 characters is allowed in R2 only mode.
+ try {
+ c.setDeviceAddress(MacAddress.fromString(DEVICE_ADDRESS))
+ .setNetworkName(TEST_NETWORK_NAME)
+ .setPassphrase("12")
+ .setPccModeConnectionType(PCC_MODE_CONNECTION_TYPE_R2_ONLY)
+ .build();
+ } catch (IllegalArgumentException e) {
+ throw new AssertionError("the test failed", e);
+ }
+
+ // more than 8 characters is allowed in R2 only mode.
+ try {
+ c.setDeviceAddress(MacAddress.fromString(DEVICE_ADDRESS))
+ .setNetworkName(TEST_NETWORK_NAME)
+ .setPassphrase("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQ"
+ + "RSTUVWXYZ1234567890+/")
+ .setPccModeConnectionType(PCC_MODE_CONNECTION_TYPE_R2_ONLY)
+ .build();
+ } catch (IllegalArgumentException e) {
+ throw new AssertionError("the test failed", e);
+ }
+ }
+
/** Verify that a default config can be built. */
@Test
public void testBuildDefaultConfig() {
@@ -300,4 +420,69 @@
config.invalidate();
assertEquals("", config.deviceAddress);
}
+
+ /** Verify that a config with the PCC Mode connection type field can be built. */
+ @Test
+ public void testBuildConfigWithPccModeConnectionType() throws Exception {
+ assumeTrue(Environment.isSdkAtLeastB());
+ WifiP2pConfig c = new WifiP2pConfig.Builder()
+ .setDeviceAddress(MacAddress.fromString(DEVICE_ADDRESS))
+ .setPccModeConnectionType(PCC_MODE_CONNECTION_TYPE_LEGACY_OR_R2)
+ .build();
+ assertEquals(c.deviceAddress, DEVICE_ADDRESS);
+ assertEquals(PCC_MODE_CONNECTION_TYPE_LEGACY_OR_R2, c.getPccModeConnectionType());
+ }
+
+ /** Verify that a config with the group owner version field can be built. */
+ @Test
+ public void testBuildConfigWithGroupOwnerVersion() throws Exception {
+ assumeTrue(Environment.isSdkAtLeastB());
+ WifiP2pConfig c = new WifiP2pConfig.Builder()
+ .setDeviceAddress(MacAddress.fromString(DEVICE_ADDRESS))
+ .build();
+ c.setGroupOwnerVersion(P2P_VERSION_2);
+ assertEquals(c.deviceAddress, DEVICE_ADDRESS);
+ assertEquals(PCC_MODE_CONNECTION_TYPE_LEGACY_OR_R2, c.getGroupOwnerVersion());
+ }
+
+ /** Verify that a config pairing bootstrapping configuration can be built. */
+ @Test
+ public void testBuildConfigWithPairingBootstrappingConfig() throws Exception {
+ assumeTrue(Environment.isSdkAtLeastB());
+ WifiP2pPairingBootstrappingConfig expectedPairingBootstrappingConfig =
+ new WifiP2pPairingBootstrappingConfig(WifiP2pPairingBootstrappingConfig
+ .PAIRING_BOOTSTRAPPING_METHOD_DISPLAY_PINCODE, "1234");
+ WifiP2pConfig c = new WifiP2pConfig.Builder()
+ .setDeviceAddress(MacAddress.fromString(DEVICE_ADDRESS))
+ .setPairingBootstrappingConfig(expectedPairingBootstrappingConfig)
+ .build();
+ assertEquals(c.deviceAddress, DEVICE_ADDRESS);
+ WifiP2pPairingBootstrappingConfig pairingBootstrappingConfig =
+ c.getPairingBootstrappingConfig();
+ assertNotNull(pairingBootstrappingConfig);
+ assertEquals(expectedPairingBootstrappingConfig, pairingBootstrappingConfig);
+ }
+
+ /**
+ * Verify that a config with the request to authorize a connection request from a peer device
+ * can be built.
+ */
+ @Test
+ public void testBuildConfigWithAuthorizeConnectionFromPeer() throws Exception {
+ assumeTrue(Environment.isSdkAtLeastB());
+ WifiP2pPairingBootstrappingConfig expectedPairingBootstrappingConfig =
+ new WifiP2pPairingBootstrappingConfig(WifiP2pPairingBootstrappingConfig
+ .PAIRING_BOOTSTRAPPING_METHOD_OUT_OF_BAND, "1234");
+ WifiP2pConfig c = new WifiP2pConfig.Builder()
+ .setDeviceAddress(MacAddress.fromString(DEVICE_ADDRESS))
+ .setPairingBootstrappingConfig(expectedPairingBootstrappingConfig)
+ .setGroupOperatingFrequency(2437)
+ .setAuthorizeConnectionFromPeer(true)
+ .build();
+ WifiP2pPairingBootstrappingConfig pairingBootstrappingConfig =
+ c.getPairingBootstrappingConfig();
+ assertNotNull(pairingBootstrappingConfig);
+ assertEquals(expectedPairingBootstrappingConfig, pairingBootstrappingConfig);
+ assertTrue(c.isAuthorizeConnectionFromPeer());
+ }
}
diff --git a/framework/tests/src/android/net/wifi/p2p/WifiP2pDeviceTest.java b/framework/tests/src/android/net/wifi/p2p/WifiP2pDeviceTest.java
index 611792d..72ee957 100644
--- a/framework/tests/src/android/net/wifi/p2p/WifiP2pDeviceTest.java
+++ b/framework/tests/src/android/net/wifi/p2p/WifiP2pDeviceTest.java
@@ -23,6 +23,7 @@
import android.net.MacAddress;
import android.net.wifi.OuiKeyedDataUtil;
import android.net.wifi.ScanResult;
+import android.net.wifi.util.Environment;
import android.os.Parcel;
import androidx.test.filters.SmallTest;
@@ -161,6 +162,10 @@
if (SdkLevel.isAtLeastV()) {
device.setVendorData(OuiKeyedDataUtil.createTestOuiKeyedDataList(5));
}
+ if (Environment.isSdkAtLeastB()) {
+ device.setPairingBootStrappingMethods(WifiP2pPairingBootstrappingConfig
+ .PAIRING_BOOTSTRAPPING_METHOD_OPPORTUNISTIC);
+ }
Parcel parcel = Parcel.obtain();
device.writeToParcel(parcel, 0);
@@ -178,6 +183,9 @@
if (SdkLevel.isAtLeastV()) {
assertEquals(device.getVendorData(), unparceledDevice.getVendorData());
}
+ if (Environment.isSdkAtLeastB()) {
+ assertTrue(device.isOpportunisticBootstrappingMethodSupported());
+ }
}
/**
@@ -207,4 +215,25 @@
device.setIpAddress(ipAddress);
assertEquals("192.168.49.1", device.getIpAddress().getHostAddress());
}
+
+ /**
+ * Test the setter/getter for pairing bootstrapping methods.
+ */
+ @Test
+ public void testSetPairingBootStrappingMethods() {
+ assumeTrue(Environment.isSdkAtLeastB());
+ WifiP2pDevice device = new WifiP2pDevice();
+ device.setPairingBootStrappingMethods(WifiP2pPairingBootstrappingConfig
+ .PAIRING_BOOTSTRAPPING_METHOD_OPPORTUNISTIC
+ | WifiP2pPairingBootstrappingConfig.PAIRING_BOOTSTRAPPING_METHOD_DISPLAY_PINCODE
+ | WifiP2pPairingBootstrappingConfig.PAIRING_BOOTSTRAPPING_METHOD_DISPLAY_PASSPHRASE
+ | WifiP2pPairingBootstrappingConfig.PAIRING_BOOTSTRAPPING_METHOD_KEYPAD_PINCODE
+ | WifiP2pPairingBootstrappingConfig
+ .PAIRING_BOOTSTRAPPING_METHOD_KEYPAD_PASSPHRASE);
+ assertTrue(device.isOpportunisticBootstrappingMethodSupported());
+ assertTrue(device.isPinCodeDisplayBootstrappingMethodSupported());
+ assertTrue(device.isPassphraseDisplayBootstrappingMethodSupported());
+ assertTrue(device.isPinCodeKeypadBootstrappingMethodSupported());
+ assertTrue(device.isPassphraseKeypadBootstrappingMethodSupported());
+ }
}
diff --git a/framework/tests/src/android/net/wifi/p2p/WifiP2pDirInfoTest.java b/framework/tests/src/android/net/wifi/p2p/WifiP2pDirInfoTest.java
new file mode 100644
index 0000000..f032fbe
--- /dev/null
+++ b/framework/tests/src/android/net/wifi/p2p/WifiP2pDirInfoTest.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.p2p;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assume.assumeTrue;
+
+import android.net.MacAddress;
+import android.net.wifi.util.Environment;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+/**
+ * Unit tests for {@link WifiP2pDirInfo}
+ */
+@SmallTest
+public final class WifiP2pDirInfoTest {
+ private static final String TEST_MAC_ADDRESS_STRING = "00:11:22:33:44:55";
+ private static final byte[] TEST_NONCE = {10, 20, 30, 40, 50, 60, 70, 80};
+ private static final byte[] TEST_DIR_TAG = {11, 22, 33, 44, 55, 66, 77, 88};
+ @Test
+ public void testWifiP2pDirInfo() {
+ assumeTrue(Environment.isSdkAtLeastB());
+ WifiP2pDirInfo dirInfo = new WifiP2pDirInfo(
+ MacAddress.fromString(TEST_MAC_ADDRESS_STRING), TEST_NONCE, TEST_DIR_TAG);
+ assertNotNull(dirInfo);
+ assertEquals(MacAddress.fromString(TEST_MAC_ADDRESS_STRING), dirInfo.getMacAddress());
+ assertArrayEquals(TEST_NONCE, dirInfo.getNonce());
+ assertArrayEquals(TEST_DIR_TAG, dirInfo.getDirTag());
+ }
+}
diff --git a/framework/tests/src/android/net/wifi/p2p/WifiP2pGroupTest.java b/framework/tests/src/android/net/wifi/p2p/WifiP2pGroupTest.java
index e84a76b..4cb9785 100644
--- a/framework/tests/src/android/net/wifi/p2p/WifiP2pGroupTest.java
+++ b/framework/tests/src/android/net/wifi/p2p/WifiP2pGroupTest.java
@@ -20,16 +20,19 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
import android.net.InetAddresses;
import android.net.MacAddress;
import android.net.wifi.OuiKeyedData;
import android.net.wifi.OuiKeyedDataUtil;
+import android.net.wifi.util.Environment;
import android.os.Parcel;
import androidx.test.filters.SmallTest;
import com.android.modules.utils.build.SdkLevel;
+import com.android.wifi.flags.Flags;
import org.junit.Test;
@@ -50,6 +53,8 @@
private static final int FREQUENCY = 5300;
private static final String CLIENT_1_DEV_ADDRESS = "aa:bb:cc:dd:ee:01";
private static final String CLIENT_2_DEV_ADDRESS = "aa:bb:cc:dd:ee:02";
+ private static final byte[] GROUP_OWNER_INTERFACE_ADDRESS =
+ { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 };
private static final WifiP2pDevice CLIENT_1 = new WifiP2pDevice(CLIENT_1_DEV_ADDRESS);
private static final WifiP2pDevice CLIENT_2 = new WifiP2pDevice(CLIENT_2_DEV_ADDRESS);
private static final MacAddress CLIENT_1_INTERFACE_MAC_ADDRESS =
@@ -83,6 +88,9 @@
if (SdkLevel.isAtLeastV()) {
group.setVendorData(VENDOR_DATA);
}
+ if (Environment.isSdkAtLeastB() && Flags.wifiDirectR2()) {
+ group.setSecurityType(WifiP2pGroup.SECURITY_TYPE_WPA3_COMPATIBILITY);
+ }
assertEquals(INTERFACE, group.getInterface());
assertEquals(NETWORK_ID, group.getNetworkId());
@@ -94,6 +102,10 @@
if (SdkLevel.isAtLeastV()) {
assertTrue(VENDOR_DATA.equals(group.getVendorData()));
}
+ if (Environment.isSdkAtLeastB() && Flags.wifiDirectR2()) {
+ assertEquals(WifiP2pGroup.SECURITY_TYPE_WPA3_COMPATIBILITY,
+ group.getSecurityType());
+ }
assertFalse(group.isClientListEmpty());
assertTrue(group.contains(CLIENT_1));
@@ -135,4 +147,16 @@
assertEquals(group.toString(), fromParcel.toString());
}
+
+ /** Verify {@link WifiP2pGroup#getGroupOwnerBssid()} */
+ @Test
+ public void testGetGroupOwnerBssid() throws Exception {
+ assumeTrue(Environment.isSdkAtLeastB());
+ WifiP2pGroup group = new WifiP2pGroup();
+ group.setIsGroupOwner(true);
+ group.interfaceAddress = GROUP_OWNER_INTERFACE_ADDRESS;
+ group.setSecurityType(WifiP2pGroup.SECURITY_TYPE_WPA3_SAE);
+ assertEquals(MacAddress.fromBytes(GROUP_OWNER_INTERFACE_ADDRESS),
+ group.getGroupOwnerBssid());
+ }
}
diff --git a/framework/tests/src/android/net/wifi/p2p/WifiP2pManagerTest.java b/framework/tests/src/android/net/wifi/p2p/WifiP2pManagerTest.java
index 21c42d8..f46456e 100644
--- a/framework/tests/src/android/net/wifi/p2p/WifiP2pManagerTest.java
+++ b/framework/tests/src/android/net/wifi/p2p/WifiP2pManagerTest.java
@@ -35,6 +35,7 @@
import android.content.Context;
import android.net.wifi.ScanResult;
import android.net.wifi.SynchronousExecutor;
+import android.net.wifi.util.Environment;
import android.os.Bundle;
import android.os.test.TestLooper;
import android.view.Display;
@@ -281,4 +282,32 @@
mDut.unregisterWifiP2pListener(listener);
verify(mP2pServiceMock).unregisterWifiP2pListener(any(IWifiP2pListener.Stub.class));
}
+
+ /**
+ * Test {@link WifiP2pManager#isWiFiDirectR2Supported()} works as
+ * expected.
+ */
+ @Test
+ public void testIsWiFiDirectR2Supported() throws Exception {
+ assumeTrue(Environment.isSdkAtLeastB());
+ when(mP2pServiceMock.getSupportedFeatures()).thenReturn(0L);
+ assertFalse(mDut.isWiFiDirectR2Supported());
+ when(mP2pServiceMock.getSupportedFeatures()).thenReturn(
+ WifiP2pManager.FEATURE_WIFI_DIRECT_R2);
+ assertTrue(mDut.isWiFiDirectR2Supported());
+ }
+
+ /**
+ * Test {@link WifiP2pManager#isPccModeSupported()} works as
+ * expected.
+ */
+ @Test
+ public void testIsPccModeSupported() throws Exception {
+ assumeTrue(Environment.isSdkAtLeastB());
+ when(mP2pServiceMock.getSupportedFeatures()).thenReturn(0L);
+ assertFalse(mDut.isPccModeSupported());
+ when(mP2pServiceMock.getSupportedFeatures()).thenReturn(
+ WifiP2pManager.FEATURE_PCC_MODE_ALLOW_LEGACY_AND_R2_CONNECTION);
+ assertTrue(mDut.isPccModeSupported());
+ }
}
diff --git a/framework/tests/src/android/net/wifi/p2p/WifiP2pUsdBasedLocalServiceAdvertisementConfigTest.java b/framework/tests/src/android/net/wifi/p2p/WifiP2pUsdBasedLocalServiceAdvertisementConfigTest.java
new file mode 100644
index 0000000..6a465f3
--- /dev/null
+++ b/framework/tests/src/android/net/wifi/p2p/WifiP2pUsdBasedLocalServiceAdvertisementConfigTest.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.p2p;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assume.assumeTrue;
+
+import android.net.wifi.util.Environment;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+/**
+ * Unit tests for {@link WifiP2pUsdBasedLocalServiceAdvertisementConfigTest}
+ */
+@SmallTest
+public final class WifiP2pUsdBasedLocalServiceAdvertisementConfigTest {
+ private static final int TEST_USD_DISCOVERY_CHANNEL_FREQUENCY_MHZ = 2412;
+ @Test
+ public void testWifiP2pUsdBasedLocalServiceAdvertisementConfig() {
+ assumeTrue(Environment.isSdkAtLeastB());
+ WifiP2pUsdBasedLocalServiceAdvertisementConfig localServiceAdvertisementConfig =
+ new WifiP2pUsdBasedLocalServiceAdvertisementConfig.Builder()
+ .setFrequencyMhz(TEST_USD_DISCOVERY_CHANNEL_FREQUENCY_MHZ).build();
+ assertNotNull(localServiceAdvertisementConfig);
+ assertEquals(TEST_USD_DISCOVERY_CHANNEL_FREQUENCY_MHZ,
+ localServiceAdvertisementConfig.getFrequencyMhz());
+ }
+}
diff --git a/framework/tests/src/android/net/wifi/p2p/WifiP2pUsdBasedServiceDiscoveryConfigTest.java b/framework/tests/src/android/net/wifi/p2p/WifiP2pUsdBasedServiceDiscoveryConfigTest.java
new file mode 100644
index 0000000..2f82851
--- /dev/null
+++ b/framework/tests/src/android/net/wifi/p2p/WifiP2pUsdBasedServiceDiscoveryConfigTest.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.p2p;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assume.assumeTrue;
+
+import android.net.wifi.ScanResult;
+import android.net.wifi.util.Environment;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+/**
+ * Unit tests for {@link WifiP2pUsdBasedServiceDiscoveryConfig}
+ */
+@SmallTest
+public final class WifiP2pUsdBasedServiceDiscoveryConfigTest {
+ private static final int[] TEST_USD_DISCOVERY_CHANNEL_FREQUENCIES_MHZ = {2412, 2437, 2462};
+ @Test
+ public void testWifiP2pUsdBasedServiceDiscoveryConfig() {
+ assumeTrue(Environment.isSdkAtLeastB());
+ WifiP2pUsdBasedServiceDiscoveryConfig serviceDiscoveryConfig =
+ new WifiP2pUsdBasedServiceDiscoveryConfig.Builder()
+ .setFrequenciesMhz(TEST_USD_DISCOVERY_CHANNEL_FREQUENCIES_MHZ).build();
+ assertNotNull(serviceDiscoveryConfig);
+ assertArrayEquals(TEST_USD_DISCOVERY_CHANNEL_FREQUENCIES_MHZ,
+ serviceDiscoveryConfig.getFrequenciesMhz());
+ assertEquals(ScanResult.UNSPECIFIED, serviceDiscoveryConfig.getBand());
+ }
+}
diff --git a/framework/tests/src/android/net/wifi/p2p/nsd/WifiP2pDnsSdServiceRequestTest.java b/framework/tests/src/android/net/wifi/p2p/nsd/WifiP2pDnsSdServiceRequestTest.java
index 7d46a5f..b2feaba 100644
--- a/framework/tests/src/android/net/wifi/p2p/nsd/WifiP2pDnsSdServiceRequestTest.java
+++ b/framework/tests/src/android/net/wifi/p2p/nsd/WifiP2pDnsSdServiceRequestTest.java
@@ -46,7 +46,7 @@
// failure case due to null service type
try {
- request = WifiP2pDnsSdServiceRequest.newInstance(null);
+ request = WifiP2pDnsSdServiceRequest.newInstance((String) null);
fail("should throw IllegalArgumentException");
} catch (IllegalArgumentException ex) {
// expected exception.
diff --git a/framework/tests/src/android/net/wifi/p2p/nsd/WifiP2pUpnpServiceRequestTest.java b/framework/tests/src/android/net/wifi/p2p/nsd/WifiP2pUpnpServiceRequestTest.java
index 79930dc..60d906e 100644
--- a/framework/tests/src/android/net/wifi/p2p/nsd/WifiP2pUpnpServiceRequestTest.java
+++ b/framework/tests/src/android/net/wifi/p2p/nsd/WifiP2pUpnpServiceRequestTest.java
@@ -40,7 +40,7 @@
// failure case due to null target string
try {
- request = WifiP2pUpnpServiceRequest.newInstance(null);
+ request = WifiP2pUpnpServiceRequest.newInstance((String) null);
fail("should throw IllegalArgumentException");
} catch (IllegalArgumentException ex) {
// expected exception.
diff --git a/framework/tests/src/android/net/wifi/p2p/nsd/WifiP2pUsdBasedServiceInfoTest.java b/framework/tests/src/android/net/wifi/p2p/nsd/WifiP2pUsdBasedServiceInfoTest.java
new file mode 100644
index 0000000..1bf4518
--- /dev/null
+++ b/framework/tests/src/android/net/wifi/p2p/nsd/WifiP2pUsdBasedServiceInfoTest.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.p2p.nsd;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assume.assumeTrue;
+
+import android.net.wifi.util.Environment;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+/**
+ * Unit tests for creating {@link WifiP2pServiceInfo} with
+ * {@link WifiP2pUsdBasedServiceConfig}.
+ */
+@SmallTest
+public final class WifiP2pUsdBasedServiceInfoTest {
+ private static final String TEST_USD_SERVICE_NAME = "test_service_name";
+ private static final int TEST_USD_PROTOCOL_TYPE = 4;
+ private static final byte[] TEST_USD_SERVICE_SPECIFIC_INFO = {10, 20, 30, 40, 50, 60};
+ @Test
+ public void testWifiP2pUsdBasedServiceInfo() {
+ assumeTrue(Environment.isSdkAtLeastB());
+ WifiP2pUsdBasedServiceConfig expectedUsdConfig = new WifiP2pUsdBasedServiceConfig.Builder(
+ TEST_USD_SERVICE_NAME)
+ .setServiceProtocolType(TEST_USD_PROTOCOL_TYPE)
+ .setServiceSpecificInfo(TEST_USD_SERVICE_SPECIFIC_INFO).build();
+ WifiP2pServiceInfo serviceInfo = new WifiP2pServiceInfo(expectedUsdConfig);
+ assertNotNull(serviceInfo);
+ WifiP2pUsdBasedServiceConfig usdConfig =
+ serviceInfo.getWifiP2pUsdBasedServiceConfig();
+ assertNotNull(usdConfig);
+ assertEquals(TEST_USD_SERVICE_NAME, usdConfig.getServiceName());
+ assertEquals(TEST_USD_PROTOCOL_TYPE, usdConfig.getServiceProtocolType());
+ assertArrayEquals(TEST_USD_SERVICE_SPECIFIC_INFO, usdConfig.getServiceSpecificInfo());
+ }
+}
diff --git a/framework/tests/src/android/net/wifi/p2p/nsd/WifiP2pUsdBasedServiceRequestTest.java b/framework/tests/src/android/net/wifi/p2p/nsd/WifiP2pUsdBasedServiceRequestTest.java
new file mode 100644
index 0000000..a53df44
--- /dev/null
+++ b/framework/tests/src/android/net/wifi/p2p/nsd/WifiP2pUsdBasedServiceRequestTest.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.p2p.nsd;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assume.assumeTrue;
+
+import android.net.wifi.util.Environment;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+/**
+ * Unit tests for creating {@link WifiP2pServiceRequest} with
+ * {@link WifiP2pUsdBasedServiceConfig}.
+ */
+@SmallTest
+public final class WifiP2pUsdBasedServiceRequestTest {
+ private static final String TEST_USD_SERVICE_NAME = "test_service_name";
+ private static final int TEST_USD_PROTOCOL_TYPE = 4;
+ private static final byte[] TEST_USD_SERVICE_SPECIFIC_INFO = {10, 20, 30, 40, 50, 60};
+ @Test
+ public void testWifiP2pUsdBasedServiceRequest() {
+ assumeTrue(Environment.isSdkAtLeastB());
+ WifiP2pUsdBasedServiceConfig expectedUsdConfig = new WifiP2pUsdBasedServiceConfig.Builder(
+ TEST_USD_SERVICE_NAME)
+ .setServiceProtocolType(TEST_USD_PROTOCOL_TYPE)
+ .setServiceSpecificInfo(TEST_USD_SERVICE_SPECIFIC_INFO).build();
+ WifiP2pServiceRequest serviceRequest = new WifiP2pServiceRequest(expectedUsdConfig);
+ assertNotNull(serviceRequest);
+ WifiP2pUsdBasedServiceConfig usdConfig =
+ serviceRequest.getWifiP2pUsdBasedServiceConfig();
+ assertNotNull(usdConfig);
+ assertEquals(TEST_USD_SERVICE_NAME, usdConfig.getServiceName());
+ assertEquals(TEST_USD_PROTOCOL_TYPE, usdConfig.getServiceProtocolType());
+ assertArrayEquals(TEST_USD_SERVICE_SPECIFIC_INFO, usdConfig.getServiceSpecificInfo());
+ }
+}
diff --git a/jni/Android.bp b/jni/Android.bp
new file mode 100644
index 0000000..d67c6aa
--- /dev/null
+++ b/jni/Android.bp
@@ -0,0 +1,17 @@
+cc_library_shared {
+ name: "libservice-wifi-jni",
+ min_sdk_version: "30",
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+ srcs: [
+ "com_android_server_ServiceManagerWrapper.cpp",
+ ],
+ shared_libs: [
+ "libbinder_ndk",
+ ],
+ apex_available: [
+ "com.android.wifi",
+ ],
+}
diff --git a/jni/com_android_server_ServiceManagerWrapper.cpp b/jni/com_android_server_ServiceManagerWrapper.cpp
new file mode 100644
index 0000000..b13346b
--- /dev/null
+++ b/jni/com_android_server_ServiceManagerWrapper.cpp
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android/binder_auto_utils.h>
+#include <android/binder_ibinder_jni.h>
+#include <android/binder_manager.h>
+#include <jni.h>
+
+namespace android {
+
+// nativeWaitForService
+extern "C" JNIEXPORT jobject JNICALL
+ Java_com_android_server_wifi_mainline_1supplicant_ServiceManagerWrapper_nativeWaitForService__Ljava_lang_String_2(
+ JNIEnv* env, jobject /* clazz */, jstring serviceNameJni) {
+ // AServiceManager_isDeclared and AServiceManager_waitForService were added in Android 31.
+ // Because this method will only be called on 35+, we can suppress the availability warning.
+ #pragma clang diagnostic push
+ #pragma clang diagnostic ignored "-Wunguarded-availability"
+ const char* serviceName = env->GetStringUTFChars(serviceNameJni, nullptr);
+ return AIBinder_toJavaBinder(env, AServiceManager_waitForService(serviceName));
+ #pragma clang diagnostic pop
+}
+
+}; // namespace android
diff --git a/service/Android.bp b/service/Android.bp
index c111ede..797fc73 100644
--- a/service/Android.bp
+++ b/service/Android.bp
@@ -66,6 +66,7 @@
"framework-location.stubs.module_lib",
"framework-statsd.stubs.module_lib",
"framework-tethering.stubs.module_lib",
+ "framework-uwb.stubs.module_lib",
"unsupportedappusage",
"app-compat-annotations",
"auto_value_annotations",
@@ -77,9 +78,9 @@
static_libs: [
// Types-only package shared across the HALs
- "android.hardware.wifi.common-V1-java",
+ "android.hardware.wifi.common-V2-java",
// AIDL vendor hal implementation
- "android.hardware.wifi-V2-java",
+ "android.hardware.wifi-V3-java",
// HIDL vendor hal implementation
"android.hardware.wifi-V1.0-java",
"android.hardware.wifi-V1.1-java",
@@ -89,7 +90,7 @@
"android.hardware.wifi-V1.5-java",
"android.hardware.wifi-V1.6-java",
// AIDL hostapd implementation
- "android.hardware.wifi.hostapd-V2-java",
+ "android.hardware.wifi.hostapd-V3-java",
// HIDL hostapd implementation
"android.hardware.wifi.hostapd-V1.0-java",
"android.hardware.wifi.hostapd-V1.1-java",
@@ -104,6 +105,7 @@
"android.hardware.wifi.supplicant-V1.3-java",
"android.hardware.wifi.supplicant-V1.4-java",
"android.hidl.manager-V1.2-java",
+ "android.system.wifi.mainline_supplicant-java",
"bouncycastle-unbundled",
"ksoap2",
// Note: libprotobuf-java-lite uses a few core platform APIs which
@@ -122,6 +124,7 @@
"wifi-lite-protos",
"wifi-nano-protos",
"android.net.wifi.flags-aconfig-java",
+ "android.security.flags-aconfig-java-export",
"net-utils-service-wifi",
],
apex_available: ["com.android.wifi"],
diff --git a/service/ServiceWifiResources/res/layout/wifi_p2p_dialog2_display_pin.xml b/service/ServiceWifiResources/res/layout/wifi_p2p_dialog2_display_pin.xml
new file mode 100644
index 0000000..020f987
--- /dev/null
+++ b/service/ServiceWifiResources/res/layout/wifi_p2p_dialog2_display_pin.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2024 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ style="@style/wifi_p2p_dialog2_display_pin_section">
+ <TextView
+ android:text="@string/wifi_p2p_dialog2_display_pin_label"
+ style="@style/wifi_p2p_dialog2_display_pin_label"/>
+
+ <TextView android:id="@+id/wifi_p2p_dialog2_display_pin"
+ style="@style/wifi_p2p_dialog2_display_pin" />
+</LinearLayout>
diff --git a/service/ServiceWifiResources/res/layout/wifi_p2p_dialog2_enter_pin.xml b/service/ServiceWifiResources/res/layout/wifi_p2p_dialog2_enter_pin.xml
new file mode 100644
index 0000000..32da7b7
--- /dev/null
+++ b/service/ServiceWifiResources/res/layout/wifi_p2p_dialog2_enter_pin.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2024 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ style="@style/wifi_p2p_dialog2_enter_pin_section">
+ <TextView
+ android:text="@string/wifi_p2p_dialog2_enter_pin_label"
+ style="@style/wifi_p2p_dialog2_enter_pin_label"/>
+
+ <EditText android:id="@+id/wifi_p2p_dialog2_enter_pin"
+ style="@style/wifi_p2p_dialog2_enter_pin" />
+</LinearLayout>
diff --git a/service/ServiceWifiResources/res/values-af/strings.xml b/service/ServiceWifiResources/res/values-af/strings.xml
index 3473553..0d2f519 100644
--- a/service/ServiceWifiResources/res/values-af/strings.xml
+++ b/service/ServiceWifiResources/res/values-af/strings.xml
@@ -48,8 +48,8 @@
<string name="wifi_watchdog_network_disabled" msgid="5769226742956006362">"Kon nie aan Wi-Fikoppel nie"</string>
<string name="wifi_watchdog_network_disabled_detailed" msgid="1725243835135539125">" het \'n swak internetverbinding."</string>
<string name="wifi_connect_alert_title" msgid="2368200646665663612">"Laat verbinding toe?"</string>
- <string name="wifi_connect_alert_message" msgid="7226456300982080746">"Program %1$s wil aan Wi-Fi-netwerk %2$s koppel"</string>
- <string name="wifi_connect_default_application" msgid="8917703737222707062">"\'n Program"</string>
+ <string name="wifi_connect_alert_message" msgid="7226456300982080746">"App %1$s wil aan wi-fi-netwerk %2$s koppel"</string>
+ <string name="wifi_connect_default_application" msgid="8917703737222707062">"\'n App"</string>
<string name="accept" msgid="8346431649376483879">"Aanvaar"</string>
<string name="decline" msgid="4172251727603762084">"Weier"</string>
<string name="ok" msgid="847575529546290102">"OK"</string>
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"Aan:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"Voer die vereiste PIN in:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"PIN:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"Toestelverbinding"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"Toestelverbinding"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"Uitnodiging gestuur na <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"Voer hierdie PIN op <xliff:g id="DEVICE_NAME">%1$s</xliff:g> in om te koppel."</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"OK"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"Toestelverbinding"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"Toestelverbinding"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"Toestelverbinding"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> wil aan jou toestel koppel."</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"Voer die PIN in wat op <xliff:g id="DEVICE_NAME">%1$s</xliff:g> wys om te koppel."</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> wil met die volgende PIN aan jou toestel koppel."</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{{device} wil aan jou toestel koppel. Aanvaar oor {countdown} sekonde.}other{{device} wil aan jou toestel koppel. Aanvaar oor {countdown} sekondes.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{Voer die PIN wat op {device} wys binne {countdown} sekonde in om te koppel.}other{Voer die PIN wat op {device} wys binne {countdown} sekondes in om te koppel.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{{device} wil met die volgende PIN aan jou toestel koppel. Aanvaar oor {countdown} sekonde.}other{{device} wil met die volgende PIN aan jou toestel koppel. Aanvaar oor {countdown} sekondes.}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"Koppel"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"Kanselleer"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"PIN"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"PIN"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"Jou toestel sal tydelik van wi-fi af ontkoppel word terwyl dit aan <xliff:g id="DEVICE_NAME">%1$s</xliff:g> gekoppel is"</string>
<string name="dlg_ok" msgid="254496739491689405">"OK"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"Kan nie aan <xliff:g id="SSID">%1$s</xliff:g> koppel nie"</string>
diff --git a/service/ServiceWifiResources/res/values-am/strings.xml b/service/ServiceWifiResources/res/values-am/strings.xml
index 4adbe8c..8913079 100644
--- a/service/ServiceWifiResources/res/values-am/strings.xml
+++ b/service/ServiceWifiResources/res/values-am/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"ለ፦"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"የሚፈለገውን ፒን ተይብ፦"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"ፒን፦"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"የመሣሪያ ግንኙነት"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"የመሣሪያ ግንኙነት"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"ግብዣ ለ<xliff:g id="DEVICE_NAME">%1$s</xliff:g> ተልኳል።"</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"ለማገናኘት ይህን ፒን <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ላይ ያስገቡ።"</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"እሺ"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"የመሣሪያ ግንኙነት"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"የመሣሪያ ግንኙነት"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"የመሣሪያ ግንኙነት"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> ከመሣሪያዎ ጋር መገናኘት ይፈልጋል።"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"ለማገናኘት <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ላይ የሚታየውን ፒን ያስገቡ።"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> በሚከተለው ፒን ከመሣሪያዎ ጋር መገናኘት ይፈልጋል።"</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{{device} ከመሣሪያዎ ጋር መገናኘት ይፈልጋል። በ{countdown} ሰከንድ ውስጥ ይቀበሉ።}one{{device} ከመሣሪያዎ ጋር መገናኘት ይፈልጋል። በ{countdown} ሰከንድ ውስጥ ይቀበሉ።}other{{device} ከመሣሪያዎ ጋር መገናኘት ይፈልጋል። በ{countdown} ሰከንዶች ውስጥ ይቀበሉ።}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{ለማገናኘት {device} ላይ የሚታየውን ፒን በ{countdown} ሰከንድ ውስጥ ያስገቡ።}one{ለማገናኘት {device} ላይ የሚታየውን ፒን በ{countdown} ሰከንድ ውስጥ ያስገቡ።}other{ለማገናኘት {device} ላይ የሚታየውን ፒን በ{countdown} ሰከንዶች ውስጥ ያስገቡ።}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{{device} በሚከተለው ፒን ከመሣሪያዎ ጋር መገናኘት ይፈልጋል። በ{countdown} ሰከንድ ውስጥ ይቀበሉ።}one{{device} በሚከተለው ፒን ከመሣሪያዎ ጋር መገናኘት ይፈልጋል። በ{countdown} ሰከንድ ውስጥ ይቀበሉ።}other{{device} በሚከተለው ፒን ከመሣሪያዎ ጋር መገናኘት ይፈልጋል። በ{countdown} ሰከንዶች ውስጥ ይቀበሉ።}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"አገናኝ"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"ይቅር"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"ፒን"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"ፒን"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"መሣሪያዎ ከ<xliff:g id="DEVICE_NAME">%1$s</xliff:g> ጋር በሚገናኝበት ጊዜ ለጊዜው ከWi-Fi ጋር ግንኙነቱ ይቋረጣል"</string>
<string name="dlg_ok" msgid="254496739491689405">"እሺ"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"ከ<xliff:g id="SSID">%1$s</xliff:g> ጋር መገናኘት አልተቻለም"</string>
diff --git a/service/ServiceWifiResources/res/values-ar/strings.xml b/service/ServiceWifiResources/res/values-ar/strings.xml
index 619d945..8d3ffa6 100644
--- a/service/ServiceWifiResources/res/values-ar/strings.xml
+++ b/service/ServiceWifiResources/res/values-ar/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"إلى:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"اكتب رمز PIN المطلوب:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"رقم التعريف الشخصي:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"اتصال الجهاز"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"اتصال الجهاز"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"تم إرسال الدعوة إلى جهاز \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\"."</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"أدخِل رقم التعريف الشخصي هذا على جهاز \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\" لتوصيله بجهازك."</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"حسنًا"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"اتصال الجهاز"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"اتصال الجهاز"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"اتصال الجهاز"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"يريد جهاز \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\" الاتصال بجهازك."</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"أدخِل رقم التعريف الشخصي المعروض على جهاز \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\" لتوصيله بجهازك."</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"يريد جهاز \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\" الاتصال بجهازك باستخدام رقم التعريف الشخصي الآتي."</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{يريد جهاز \"{device}\" الاتصال بجهازك. يمكنك القبول خلال ثانية واحدة ({countdown}).}zero{يريد جهاز \"{device}\" الاتصال بجهازك. يمكنك القبول خلال {countdown} ثانية.}two{يريد جهاز \"{device}\" الاتصال بجهازك. يمكنك القبول خلال ثانيتين ({countdown}).}few{يريد جهاز \"{device}\" الاتصال بجهازك. يمكنك القبول خلال {countdown} ثوانٍ.}many{يريد جهاز \"{device}\" الاتصال بجهازك. يمكنك القبول خلال {countdown} ثانية.}other{يريد جهاز \"{device}\" الاتصال بجهازك. يمكنك القبول خلال {countdown} ثانية.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{أدخِل رقم التعريف الشخصي المعروض على جهاز \"{device}\" خلال ثانية واحدة ({countdown}) لتوصيله بجهازك.}zero{أدخِل رقم التعريف الشخصي المعروض على جهاز \"{device}\" خلال {countdown} ثانية لتوصيله بجهازك.}two{أدخِل رقم التعريف الشخصي المعروض على جهاز \"{device}\" خلال ثانيتين ({countdown}) لتوصيله بجهازك.}few{أدخِل رقم التعريف الشخصي المعروض على جهاز \"{device}\" خلال {countdown} ثوانٍ لتوصيله بجهازك.}many{أدخِل رقم التعريف الشخصي المعروض على جهاز \"{device}\" خلال {countdown} ثانية لتوصيله بجهازك.}other{أدخِل رقم التعريف الشخصي المعروض على جهاز \"{device}\" خلال {countdown} ثانية لتوصيله بجهازك.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{يريد \"{device}\" الاتصال بجهازك باستخدام رقم التعريف الشخصي الآتي. يمكنك القبول خلال ثانية واحدة ({countdown}).}zero{يريد جهاز \"{device}\" الاتصال بجهازك باستخدام رقم التعريف الشخصي الآتي. يمكنك القبول خلال {countdown} ثانية.}two{يريد جهاز \"{device}\" الاتصال بجهازك باستخدام رقم التعريف الشخصي الآتي. يمكنك القبول خلال ثانيتين ({countdown}).}few{يريد جهاز \"{device}\" الاتصال بجهازك باستخدام رقم التعريف الشخصي الآتي. يمكنك القبول خلال {countdown} ثوانٍ.}many{يريد جهاز \"{device}\" الاتصال بجهازك باستخدام رقم التعريف الشخصي الآتي. يمكنك القبول خلال {countdown} ثانية.}other{يريد جهاز \"{device}\" الاتصال بجهازك باستخدام رقم التعريف الشخصي الآتي. يمكنك القبول خلال {countdown} ثانية.}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"اتصال"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"إلغاء"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"رقم التعريف الشخصي"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"رقم التعريف الشخصي"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"سيتم قطع اتصال الجهاز بشبكة Wi-Fi مؤقتًا أثناء اتصاله بـ <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="dlg_ok" msgid="254496739491689405">"حسنًا"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"يتعذّر الاتصال بـ <xliff:g id="SSID">%1$s</xliff:g>."</string>
diff --git a/service/ServiceWifiResources/res/values-as/strings.xml b/service/ServiceWifiResources/res/values-as/strings.xml
index 4b2f966..d1a79b9 100644
--- a/service/ServiceWifiResources/res/values-as/strings.xml
+++ b/service/ServiceWifiResources/res/values-as/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"প্ৰতি:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"প্ৰয়োজনীয় পিন নম্বৰটো লিখক:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"পিন:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"ডিভাইচৰ সংযোগ"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"ডিভাইচৰ সংযোগ"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>লৈ আমন্ত্ৰণ পঠিওৱা হৈছে।"</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"সংযোগ কৰিবলৈ <xliff:g id="DEVICE_NAME">%1$s</xliff:g>ত এই পিনটো দিয়ক।"</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"ঠিক আছে"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"ডিভাইচৰ সংযোগ"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"ডিভাইচৰ সংযোগ"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"ডিভাইচৰ সংযোগ"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>এ আপোনাৰ ডিভাইচৰ সৈতে সংযোগ কৰিব বিচাৰিছে।"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"সংযোগ কৰিবলৈ <xliff:g id="DEVICE_NAME">%1$s</xliff:g>ত দেখুওৱা পিনটো দিয়ক।"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>এ তলত দিয়া পিনটোৰ জৰিয়তে আপোনাৰ ডিভাইচৰ সৈতে সংযোগ কৰিব বিচাৰিছে।"</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{{device}এ আপোনাৰ ডিভাইচৰ সৈতে সংযোগ কৰিব বিচাৰিছে। {countdown} ছেকেণ্ডত গ্ৰহণ কৰক।}one{{device}এ আপোনাৰ ডিভাইচৰ সৈতে সংযোগ কৰিব বিচাৰিছে। {countdown} ছেকেণ্ডত গ্ৰহণ কৰক।}other{{device}এ আপোনাৰ ডিভাইচৰ সৈতে সংযোগ কৰিব বিচাৰিছে। {countdown} ছেকেণ্ডত গ্ৰহণ কৰক।}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{সংযোগ কৰিবলৈ {countdown} ছেকেণ্ডৰ ভিতৰত {device}ত দেখুওৱা পিনটো দিয়ক।}one{সংযোগ কৰিবলৈ {countdown} ছেকেণ্ডৰ ভিতৰত {device}ত দেখুওৱা পিনটো দিয়ক।}other{সংযোগ কৰিবলৈ {countdown} ছেকেণ্ডৰ ভিতৰত {device}ত দেখুওৱা পিনটো দিয়ক।}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{{device}এ তলত দিয়া পিনটোৰ জৰিয়তে আপোনাৰ ডিভাইচৰ সৈতে সংযোগ কৰিব বিচাৰিছে। {countdown} ছেকেণ্ডত গ্ৰহণ কৰক।}one{{device}এ তলত দিয়া পিনটোৰ জৰিয়তে আপোনাৰ ডিভাইচৰ সৈতে সংযোগ কৰিব বিচাৰিছে। {countdown} ছেকেণ্ডত গ্ৰহণ কৰক।}other{{device}এ তলত দিয়া পিনটোৰ জৰিয়তে আপোনাৰ ডিভাইচৰ সৈতে সংযোগ কৰিব বিচাৰিছে। {countdown} ছেকেণ্ডত গ্ৰহণ কৰক।}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"সংযোগ কৰক"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"বাতিল কৰক"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"পিন"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"পিন"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"আপোনাৰ ডিভাইচটো <xliff:g id="DEVICE_NAME">%1$s</xliff:g>ৰ লগত সংযুক্ত হৈ থকাৰ অৱস্থাত অস্থায়ীভাৱে ৱাই-ফাইৰ পৰা সংযোগ বিচ্ছিন্ন হ’ব"</string>
<string name="dlg_ok" msgid="254496739491689405">"ঠিক আছে"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"<xliff:g id="SSID">%1$s</xliff:g>ৰ সৈতে সংযোগ কৰিব নোৱাৰি"</string>
diff --git a/service/ServiceWifiResources/res/values-az/strings.xml b/service/ServiceWifiResources/res/values-az/strings.xml
index b39b971..c74b17a 100644
--- a/service/ServiceWifiResources/res/values-az/strings.xml
+++ b/service/ServiceWifiResources/res/values-az/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"Kimə:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"Tələb olunan PİN kodu daxil edin:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"PİN:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"Cihaz bağlantısı"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"Cihaz bağlantısı"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"Dəvət <xliff:g id="DEVICE_NAME">%1$s</xliff:g> cihazına göndərildi."</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"Qoşulmaq üçün bu PIN-i <xliff:g id="DEVICE_NAME">%1$s</xliff:g> cihazına daxil edin."</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"OK"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"Cihaz bağlantısı"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"Cihaz bağlantısı"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"Cihaz bağlantısı"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> cihazınıza qoşulmaq istəyir."</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"Qoşulmaq üçün <xliff:g id="DEVICE_NAME">%1$s</xliff:g> cihazında göstərilən PIN-i daxil edin."</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> aşağıdakı PIN ilə cihazınıza qoşulmaq istəyir."</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{{device} cihazınıza qoşulmaq istəyir. {countdown} saniyə ərzində qəbul edin.}other{{device} cihazınıza qoşulmaq istəyir. {countdown} saniyə ərzində qəbul edin.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{Qoşulmaq üçün {countdown} saniyə ərzində {device} cihazında göstərilən PIN-i daxil edin.}other{Qoşulmaq üçün {countdown} saniyə ərzində {device} cihazında göstərilən PIN-i daxil edin.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{{device} aşağıdakı PIN ilə cihazınıza qoşulmaq istəyir. {countdown} saniyə ərzində qəbul edin.}other{{device} aşağıdakı PIN ilə cihazınıza qoşulmaq istəyir. {countdown} saniyə ərzində qəbul edin.}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"Qoşulun"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"Ləğv edin"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"PIN"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"PIN"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> cihazına qoşulanda cihaz Wi-Fi-dan müvəqqəti ayrılacaq"</string>
<string name="dlg_ok" msgid="254496739491689405">"OK"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"<xliff:g id="SSID">%1$s</xliff:g> şəbəkəsinə qoşulmaq mümkün deyil"</string>
diff --git a/service/ServiceWifiResources/res/values-b+sr+Latn/strings.xml b/service/ServiceWifiResources/res/values-b+sr+Latn/strings.xml
index 267e4bd..7c18235 100644
--- a/service/ServiceWifiResources/res/values-b+sr+Latn/strings.xml
+++ b/service/ServiceWifiResources/res/values-b+sr+Latn/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"Kome:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"Unesite potrebni PIN:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"PIN:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"Veza uređaja"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"Veza uređaja"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"Poslat je poziv za: <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"Da biste se povezali, unesite ovaj PIN na uređaju <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"Potvrdi"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"Veza uređaja"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"Veza uređaja"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"Veza uređaja"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> želi da se poveže sa uređajem."</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"Da biste se povezali, unesite PIN prikazan na uređaju <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> želi da se poveže sa vašim uređajem pomoću sledećeg PIN-a."</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{{device} želi da se poveže sa vašim uređajem. Prihvatite za {countdown} sekundu.}one{{device} želi da se poveže sa vašim uređajem. Prihvatite za {countdown} sekundu.}few{{device} želi da se poveže sa vašim uređajem. Prihvatite za {countdown} sekunde.}other{{device} želi da se poveže sa vašim uređajem. Prihvatite za {countdown} sekundi.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{Da biste se povezali, unesite PIN prikazan na uređaju {device} u roku od {countdown} sekunde.}one{Da biste se povezali, unesite PIN prikazan na uređaju {device} u roku od {countdown} sekunde.}few{Da biste se povezali, unesite PIN prikazan na uređaju {device} u roku od {countdown} sekunde.}other{Da biste se povezali, unesite PIN prikazan na uređaju {device} u roku od {countdown} sekundi.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{{device} želi da se poveže sa vašim uređajem pomoću sledećeg PIN-a. Prihvatite za {countdown} sekundu.}one{{device} želi da se poveže sa vašim uređajem pomoću sledećeg PIN-a. Prihvatite za {countdown} sekundu.}few{{device} želi da se poveže sa vašim uređajem pomoću sledećeg PIN-a. Prihvatite za {countdown} sekunde.}other{{device} želi da se poveže sa vašim uređajem pomoću sledećeg PIN-a. Prihvatite za {countdown} sekundi.}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"Poveži"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"Otkaži"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"PIN"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"PIN"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"Uređaj će privremeno prekinuti vezu sa WiFi mrežom dok je povezan sa uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="dlg_ok" msgid="254496739491689405">"Potvrdi"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"Povezivanje na mrežu <xliff:g id="SSID">%1$s</xliff:g> nije uspelo"</string>
diff --git a/service/ServiceWifiResources/res/values-be/strings.xml b/service/ServiceWifiResources/res/values-be/strings.xml
index ae333d9..a99e0bc 100644
--- a/service/ServiceWifiResources/res/values-be/strings.xml
+++ b/service/ServiceWifiResources/res/values-be/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"Каму:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"Увядзіце патрэбны PIN-код:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"PIN-код"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"Падключэнне да прылады"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"Падключэнне да прылады"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"Запрашэнне адпраўлена на прыладу <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"Каб падключыцца, увядзіце гэты PIN-код на прыладзе <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"ОК"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"Падключэнне да прылады"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"Падключэнне да прылады"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"Падключэнне да прылады"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"Прылада <xliff:g id="DEVICE_NAME">%1$s</xliff:g> запытвае падключэнне да вашай прылады."</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"Каб падключыцца, увядзіце PIN-код, паказаны на прыладзе <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"Прылада <xliff:g id="DEVICE_NAME">%1$s</xliff:g> запытвае падключэнне да вашай прылады з наступным PIN-кодам."</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{Прылада {device} запытвае падключэнне да вашай прылады. Прыміце на працягу {countdown} секунды.}one{Прылада {device} запытвае падключэнне да вашай прылады. Прыміце на працягу {countdown} секунды.}few{Прылада {device} запытвае падключэнне да вашай прылады. Прыміце на працягу {countdown} секунд.}many{Прылада {device} запытвае падключэнне да вашай прылады. Прыміце на працягу {countdown} секунд.}other{Прылада {device} запытвае падключэнне да вашай прылады. Прыміце на працягу {countdown} секунды.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{Каб падключыцца, увядзіце PIN-код, паказаны на прыладзе {device}, на працягу {countdown} секунды.}one{Каб падключыцца, увядзіце PIN-код, паказаны на прыладзе {device}, на працягу {countdown} секунды.}few{Каб падключыцца, увядзіце PIN-код, паказаны на прыладзе {device}, на працягу {countdown} секунд.}many{Каб падключыцца, увядзіце PIN-код, паказаны на прыладзе {device}, на працягу {countdown} секунд.}other{Каб падключыцца, увядзіце PIN-код, паказаны на прыладзе {device}, на працягу {countdown} секунды.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{Прылада {device} запытвае падключэнне да вашай прылады з наступным PIN-кодам. Прыміце на працягу {countdown} секунды.}one{Прылада {device} запытвае падключэнне да вашай прылады з наступным PIN-кодам. Прыміце на працягу {countdown} секунды.}few{Прылада {device} запытвае падключэнне да вашай прылады з наступным PIN-кодам. Прыміце на працягу {countdown} секунд.}many{Прылада {device} запытвае падключэнне да вашай прылады з наступным PIN-кодам. Прыміце на працягу {countdown} секунд.}other{Прылада {device} запытвае падключэнне да вашай прылады з наступным PIN-кодам. Прыміце на працягу {countdown} секунды.}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"Падключыцца"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"Скасаваць"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"PIN-код"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"PIN-код"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"Прылада будзе часова заставацца адключанай ад сеткі Wi-Fi, пакуль падключана да прылады \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\""</string>
<string name="dlg_ok" msgid="254496739491689405">"ОК"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"Не ўдалося падключыцца да сеткі \"<xliff:g id="SSID">%1$s</xliff:g>\""</string>
diff --git a/service/ServiceWifiResources/res/values-bg/strings.xml b/service/ServiceWifiResources/res/values-bg/strings.xml
index eb2f5f4..cd25722 100644
--- a/service/ServiceWifiResources/res/values-bg/strings.xml
+++ b/service/ServiceWifiResources/res/values-bg/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"До:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"Въведете задължителния ПИН:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"ПИН:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"Връзка на устройството"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"Връзка на устройството"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"Поканата бе изпратена до <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"Въведете този ПИН код на <xliff:g id="DEVICE_NAME">%1$s</xliff:g>, за да се свържете."</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"OK"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"Връзка на устройството"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"Връзка на устройството"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"Връзка на устройството"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> иска да се свърже с устройството ви."</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"Въведете ПИН кода, показан на <xliff:g id="DEVICE_NAME">%1$s</xliff:g>, за да се свържете."</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> иска да се свърже с устройството ви чрез следния ПИН код."</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{{device} иска да се свърже с устройството ви. Имате {countdown} секунда, за да приемете.}other{{device} иска да се свърже с устройството ви. Имате {countdown} секунди, за да приемете.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{Въведете ПИН кода, показан на {device}, в рамките на {countdown} секунда, за да се свържете.}other{Въведете ПИН кода, показан на {device}, в рамките на {countdown} секунди, за да се свържете.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{{device} иска да се свърже с устройството ви чрез следния ПИН код. Имате {countdown} секунда, за да приемете.}other{{device} иска да се свърже с устройството ви чрез следния ПИН код. Имате {countdown} секунди, за да приемете.}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"Свързване"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"Отказ"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"ПИН"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"ПИН"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"Връзката с Wi-Fi на устройството ви временно ще бъде прекратена, докато то е свързано с(ъс) <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="dlg_ok" msgid="254496739491689405">"OK"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"Не може да се установи връзка с(ъс) <xliff:g id="SSID">%1$s</xliff:g>"</string>
diff --git a/service/ServiceWifiResources/res/values-bn/strings.xml b/service/ServiceWifiResources/res/values-bn/strings.xml
index f981dc2..a00451e 100644
--- a/service/ServiceWifiResources/res/values-bn/strings.xml
+++ b/service/ServiceWifiResources/res/values-bn/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"প্রাপক:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"প্রয়োজনীয় পিনটি লিখুন:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"পিন:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"ডিভাইস কানেকশন"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"ডিভাইস কানেকশন"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> ডিভাইসকে আমন্ত্রণ পাঠানো হয়েছে।"</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"কানেক্ট করতে <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ডিভাইসে পিন লিখুন।"</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"ঠিক আছে"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"ডিভাইস কানেকশন"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"ডিভাইস কানেকশন"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"ডিভাইস কানেকশন"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> আপনার ডিভাইসের সাথে কানেক্ট করতে চাইছে।"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"কানেক্ট করতে <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ডিভাইসে দেখানো পিন লিখুন।"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> নিচে দেওয়া পিন ব্যবহার করে আপনার ডিভাইসের সাথে কানেক্ট করতে চাইছে।"</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{{device} আপনার ডিভাইসের সাথে কানেক্ট করতে চাইছে। {countdown} সেকেন্ডের মধ্যে সম্মতি দিন।}one{{device} আপনার ডিভাইসের সাথে কানেক্ট করতে চাইছে। {countdown} সেকেন্ডের মধ্যে সম্মতি দিন।}other{{device} আপনার ডিভাইসের সাথে কানেক্ট করতে চাইছে। {countdown} সেকেন্ডের মধ্যে সম্মতি দিন।}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{কানেক্ট করতে {countdown} সেকেন্ডের মধ্যে {device} ডিভাইসে দেখানো পিন লিখুন।}one{কানেক্ট করতে {countdown} সেকেন্ডের মধ্যে {device} ডিভাইসে দেখানো পিন লিখুন।}other{কানেক্ট করতে {countdown} সেকেন্ডের মধ্যে {device} ডিভাইসে দেখানো পিন লিখুন।}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{{device} নিচে দেওয়া পিন ব্যবহার করে আপনার ডিভাইসের সাথে কানেক্ট করতে চাইছে। {countdown} সেকেন্ডের মধ্যে সম্মতি দিন।}one{{device} নিচে দেওয়া পিন ব্যবহার করে আপনার ডিভাইসের সাথে কানেক্ট করতে চাইছে। {countdown} সেকেন্ডের মধ্যে সম্মতি দিন।}other{{device} নিচে দেওয়া পিন ব্যবহার করে আপনার ডিভাইসের সাথে কানেক্ট করতে চাইছে। {countdown} সেকেন্ডের মধ্যে সম্মতি দিন।}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"কানেক্ট করুন"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"বাতিল করুন"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"পিন"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"পিন"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>-এ কানেক্ট থাকা অবস্থায় আপনার ডিভাইস সাময়িকভাবে ওয়াই-ফাই থেকে ডিসকানেক্ট হয়ে যাবে"</string>
<string name="dlg_ok" msgid="254496739491689405">"ঠিক আছে"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"<xliff:g id="SSID">%1$s</xliff:g>-এর সাথে কানেক্ট করা যাচ্ছে না"</string>
diff --git a/service/ServiceWifiResources/res/values-bs/strings.xml b/service/ServiceWifiResources/res/values-bs/strings.xml
index ca0ea80..79cddaa 100644
--- a/service/ServiceWifiResources/res/values-bs/strings.xml
+++ b/service/ServiceWifiResources/res/values-bs/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"Prima:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"Unesite potrebni PIN:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"PIN:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"Veza uređaja"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"Veza uređaja"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"Pozivnica je poslana na uređaj <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"Da se povežete, unesite ovaj PIN na uređaju <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"Uredu"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"Veza uređaja"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"Veza uređaja"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"Veza uređaja"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"Uređaj <xliff:g id="DEVICE_NAME">%1$s</xliff:g> se želi povezati s vašim uređajem."</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"Da se povežete, unesite PIN prikazan na uređaju <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"Uređaj <xliff:g id="DEVICE_NAME">%1$s</xliff:g> se želi povezati s vašim uređajem sa sljedećim PIN-om."</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{Uređaj {device} se želi povezati s vašim uređajem. Prihvatite za {countdown} sekundu.}one{Uređaj {device} se želi povezati s vašim uređajem. Prihvatite za {countdown} sekundu.}few{Uređaj {device} se želi povezati s vašim uređajem. Prihvatite za {countdown} sekunde.}other{Uređaj {device} se želi povezati s vašim uređajem. Prihvatite za {countdown} sekundi.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{Da se povežete, unesite PIN prikazan na uređaju {device} u roku od {countdown} sekunde.}one{Da se povežete, unesite PIN prikazan na uređaju {device} u roku od {countdown} sekunde.}few{Da se povežete, unesite PIN prikazan na uređaju {device} u roku od {countdown} sekunde.}other{Da se povežete, unesite PIN prikazan na uređaju {device} u roku od {countdown} sekundi.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{Uređaj {device} se želi povezati s vašim uređajem sa sljedećim PIN-om. Prihvatite za {countdown} sekundu.}one{Uređaj {device} se želi povezati s vašim uređajem sa sljedećim PIN-om. Prihvatite za {countdown} sekundu.}few{Uređaj {device} se želi povezati s vašim uređajem sa sljedećim PIN-om. Prihvatite za {countdown} sekunde.}other{Uređaj {device} se želi povezati s vašim uređajem sa sljedećim PIN-om. Prihvatite za {countdown} sekundi.}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"Poveži se"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"Otkaži"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"PIN"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"PIN"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"Povezanost uređaja s WiFi mrežom će se privremeno prekinuti dok je povezan s uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="dlg_ok" msgid="254496739491689405">"Uredu"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"Nije se moguće povezati s mrežom <xliff:g id="SSID">%1$s</xliff:g>"</string>
diff --git a/service/ServiceWifiResources/res/values-ca/strings.xml b/service/ServiceWifiResources/res/values-ca/strings.xml
index 9748360..b3c39a3 100644
--- a/service/ServiceWifiResources/res/values-ca/strings.xml
+++ b/service/ServiceWifiResources/res/values-ca/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"Per a:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"Introdueix el PIN sol·licitat:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"PIN:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"Connexió de dispositius"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"Connexió de dispositius"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"S\'ha enviat una invitació a <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"Introdueix aquest PIN a <xliff:g id="DEVICE_NAME">%1$s</xliff:g> per connectar-te."</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"D\'acord"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"Connexió de dispositius"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"Connexió de dispositius"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"Connexió de dispositius"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> vol connectar-se al teu dispositiu."</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"Introdueix el PIN que es mostra a <xliff:g id="DEVICE_NAME">%1$s</xliff:g> per connectar-te."</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> vol connectar-se al teu dispositiu amb el PIN següent."</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{{device} vol connectar-se al teu dispositiu. Accepta-ho d\'aquí a {countdown} segon.}many{{device} vol connectar-se al teu dispositiu. Accepta-ho d\'aquí a {countdown} de segons.}other{{device} vol connectar-se al teu dispositiu. Accepta-ho d\'aquí a {countdown} segons.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{Introdueix el PIN que es mostra a {device} en un termini d’{countdown} segon per connectar-te.}many{Introdueix el PIN que es mostra a {device} en un termini de {countdown} de segons per connectar-te.}other{Introdueix el PIN que es mostra a {device} en un termini de {countdown} segons per connectar-te.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{{device} vol connectar-se al teu dispositiu amb el PIN següent. Accepta-ho d\'aquí a {countdown} segon.}many{{device} vol connectar-se al teu dispositiu amb el PIN següent. Accepta-ho d\'aquí a {countdown} de segons.}other{{device} vol connectar-se al teu dispositiu amb el PIN següent. Accepta-ho d\'aquí a {countdown} segons.}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"Connecta"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"Cancel·la"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"PIN"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"PIN"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"El dispositiu es desconnectarà temporalment de la Wi‑Fi mentre estigui connectat a <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="dlg_ok" msgid="254496739491689405">"D\'acord"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"No es pot connectar a <xliff:g id="SSID">%1$s</xliff:g>"</string>
diff --git a/service/ServiceWifiResources/res/values-cs/strings.xml b/service/ServiceWifiResources/res/values-cs/strings.xml
index e26e53c..bcaa30d 100644
--- a/service/ServiceWifiResources/res/values-cs/strings.xml
+++ b/service/ServiceWifiResources/res/values-cs/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"Komu:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"Zadejte požadovaný kód PIN:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"PIN:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"Připojení zařízení"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"Připojení zařízení"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"Do zařízení <xliff:g id="DEVICE_NAME">%1$s</xliff:g> se odeslala pozvánka."</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"K připojení zadejte na zařízení <xliff:g id="DEVICE_NAME">%1$s</xliff:g> tento PIN."</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"OK"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"Připojení zařízení"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"Připojení zařízení"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"Připojení zařízení"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"Zařízení <xliff:g id="DEVICE_NAME">%1$s</xliff:g> se chce připojit k vašemu zařízení."</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"Pokud se chcete připojit, zadejte PIN zobrazený na zařízení <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"Zařízení <xliff:g id="DEVICE_NAME">%1$s</xliff:g> se chce připojit k vašemu zařízení s následujícím kódem PIN."</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{Zařízení {device} se chce připojit k vašemu zařízení. Na přijetí máte {countdown} sekundu.}few{Zařízení {device} se chce připojit k vašemu zařízení. Na přijetí máte {countdown} sekundy.}many{Zařízení {device} se chce připojit k vašemu zařízení. Na přijetí máte {countdown} sekundy.}other{Zařízení {device} se chce připojit k vašemu zařízení. Na přijetí máte {countdown} sekund.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{K připojení zadejte do {countdown} sekundy PIN zobrazený na zařízení {device}.}few{K připojení zadejte do {countdown} sekund PIN zobrazený na zařízení {device}.}many{K připojení zadejte do {countdown} sekundy PIN zobrazený na zařízení {device}.}other{K připojení zadejte do {countdown} sekund PIN zobrazený na zařízení {device}.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{Zařízení {device} se chce připojit k vašemu zařízení s následujícím kódem PIN. Na přijetí máte {countdown} sekundu.}few{Zařízení {device} se chce připojit k vašemu zařízení s následujícím kódem PIN. Na přijetí máte {countdown} sekundy.}many{Zařízení {device} se chce připojit k vašemu zařízení s následujícím kódem PIN. Na přijetí máte {countdown} sekundy.}other{Zařízení {device} se chce připojit k vašemu zařízení s následujícím kódem PIN. Na přijetí máte {countdown} sekund.}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"Připojit"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"Zrušit"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"PIN"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"PIN"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"Zatímco bude zařízení připojeno k zařízení <xliff:g id="DEVICE_NAME">%1$s</xliff:g>, dočasně se odpojí od Wi-Fi"</string>
<string name="dlg_ok" msgid="254496739491689405">"OK"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"K síti <xliff:g id="SSID">%1$s</xliff:g> se nelze připojit"</string>
diff --git a/service/ServiceWifiResources/res/values-da/strings.xml b/service/ServiceWifiResources/res/values-da/strings.xml
index 6a27388..aba3b75 100644
--- a/service/ServiceWifiResources/res/values-da/strings.xml
+++ b/service/ServiceWifiResources/res/values-da/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"Til:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"Skriv den påkrævede pinkode:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"Pinkode:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"Enhedsforbindelse"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"Enhedsforbindelse"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"Der er sendt en invitation til <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"Angiv denne pinkode på <xliff:g id="DEVICE_NAME">%1$s</xliff:g> for at oprette tilknytning."</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"OK"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"Enhedsforbindelse"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"Enhedsforbindelse"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"Enhedsforbindelse"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> vil gerne oprette tilknytning til din enhed."</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"Angiv den pinkode, der vises på <xliff:g id="DEVICE_NAME">%1$s</xliff:g>, for at oprette tilknytning."</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> vil gerne oprette tilknytning til din enhed med følgende pinkode."</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{{device} vil gerne oprette tilknytning til din enhed. Acceptér inden for {countdown} sekund.}one{{device} vil gerne oprette tilknytning til din enhed. Acceptér inden for {countdown} sekund.}other{{device} vil gerne oprette tilknytning til din enhed. Acceptér inden for {countdown} sekunder.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{Angiv den pinkode, der vises på {device}, inden for {countdown} sekund for at oprette tilknytning.}one{Angiv den pinkode, der vises på {device}, inden for {countdown} sekund for at oprette tilknytning.}other{Angiv den pinkode, der vises på {device}, inden for {countdown} sekunder for at oprette tilknytning.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{{device} vil gerne oprette tilknytning til din enhed med følgende pinkode. Acceptér inden for {countdown} sekund.}one{{device} vil gerne oprette tilknytning til din enhed med følgende pinkode. Acceptér inden for {countdown} sekund.}other{{device} vil gerne oprette tilknytning til din enhed med følgende pinkode. Acceptér inden for {countdown} sekunder.}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"Opret tilknytning"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"Annuller"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"Pinkode"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"Pinkode"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"Enhedens Wi-Fi-forbindelse afbrydes midlertidigt, når den er tilknyttet <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="dlg_ok" msgid="254496739491689405">"OK"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"Der kan ikke oprettes forbindelse til <xliff:g id="SSID">%1$s</xliff:g>"</string>
diff --git a/service/ServiceWifiResources/res/values-de/strings.xml b/service/ServiceWifiResources/res/values-de/strings.xml
index 4032ff1..3db2c40 100644
--- a/service/ServiceWifiResources/res/values-de/strings.xml
+++ b/service/ServiceWifiResources/res/values-de/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"An:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"Gib die PIN ein:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"PIN:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"Geräteverbindung"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"Geräteverbindung"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"Einladung an das Gerät „<xliff:g id="DEVICE_NAME">%1$s</xliff:g>“ gesendet."</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"Gib diese PIN auf dem Gerät „<xliff:g id="DEVICE_NAME">%1$s</xliff:g>“ ein, um eine Verbindung herzustellen."</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"Ok"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"Geräteverbindung"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"Geräteverbindung"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"Geräteverbindung"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"Das Gerät „<xliff:g id="DEVICE_NAME">%1$s</xliff:g>“ möchte eine Verbindung mit deinem Gerät herstellen."</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"Gib die auf dem Gerät „<xliff:g id="DEVICE_NAME">%1$s</xliff:g>“ angezeigte PIN ein, um eine Verbindung herzustellen."</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"Das Gerät „<xliff:g id="DEVICE_NAME">%1$s</xliff:g>“ möchte sich mit der folgenden PIN mit deinem Gerät verbinden."</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{Das Gerät „{device}“ möchte eine Verbindung mit deinem Gerät herstellen. In {countdown} Sekunde akzeptieren.}other{Das Gerät „{device}“ möchte eine Verbindung mit deinem Gerät herstellen. In {countdown} Sekunden akzeptieren.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{Gib die auf dem Gerät „{device}“ angezeigte PIN innerhalb von {countdown} Sekunde ein, um eine Verbindung herzustellen.}other{Gib die auf dem Gerät „{device}“ angezeigte PIN innerhalb von {countdown} Sekunden ein, um eine Verbindung herzustellen.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{Das Gerät „{device}“ möchte sich mit der folgenden PIN mit deinem Gerät verbinden. In {countdown} Sekunde akzeptieren.}other{Das Gerät „{device}“ möchte sich mit der folgenden PIN mit deinem Gerät verbinden. In {countdown} Sekunden akzeptieren.}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"Verbinden"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"Abbrechen"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"PIN"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"PIN"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"Dein Gerät wird vorübergehend vom WLAN getrennt, während es mit „<xliff:g id="DEVICE_NAME">%1$s</xliff:g>“ verbunden ist"</string>
<string name="dlg_ok" msgid="254496739491689405">"Ok"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"Verbindung zu <xliff:g id="SSID">%1$s</xliff:g> nicht möglich"</string>
diff --git a/service/ServiceWifiResources/res/values-el/strings.xml b/service/ServiceWifiResources/res/values-el/strings.xml
index 1e3a8e0..e3cbfc2 100644
--- a/service/ServiceWifiResources/res/values-el/strings.xml
+++ b/service/ServiceWifiResources/res/values-el/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"Προς:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"Πληκτρολογήστε τον απαιτούμενο κωδικό PIN:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"PIN:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"Σύνδεση συσκευής"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"Σύνδεση συσκευής"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"Η πρόσκληση εστάλη στη συσκευή <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"Εισαγάγετε αυτό το PIN στη συσκευή <xliff:g id="DEVICE_NAME">%1$s</xliff:g> για σύνδεση."</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"ΟΚ"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"Σύνδεση συσκευής"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"Σύνδεση συσκευής"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"Σύνδεση συσκευής"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"Η συσκευή <xliff:g id="DEVICE_NAME">%1$s</xliff:g> θέλει να συνδεθεί στη συσκευή σας."</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"Εισαγάγετε το PIN που εμφανίζεται στη συσκευή <xliff:g id="DEVICE_NAME">%1$s</xliff:g> για σύνδεση."</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"Η συσκευή <xliff:g id="DEVICE_NAME">%1$s</xliff:g> θέλει να συνδεθεί στη συσκευή σας με τον ακόλουθο κωδικό PIN."</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{Η συσκευή {device} θέλει να συνδεθεί στη συσκευή σας. Αποδοχή σε {countdown} δευτερόλεπτο.}other{Η συσκευή {device} θέλει να συνδεθεί στη συσκευή σας. Αποδοχή σε {countdown} δευτερόλεπτα.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{Εισαγάγετε το PIN που εμφανίζεται στη συσκευή {device} εντός {countdown} δευτερολέπτου για σύνδεση.}other{Εισαγάγετε το PIN που εμφανίζεται στη συσκευή {device} εντός {countdown} δευτερολέπτων για σύνδεση.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{Η συσκευή {device} θέλει να συνδεθεί στη συσκευή σας με τον ακόλουθο κωδικό PIN. Αποδοχή σε {countdown} δευτερόλεπτο.}other{Η συσκευή {device} θέλει να συνδεθεί στη συσκευή σας με τον ακόλουθο κωδικό PIN. Αποδοχή σε {countdown} δευτερόλεπτα.}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"Σύνδεση"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"Ακύρωση"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"PIN"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"PIN"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"Η συσκευή σας θα αποσυνδεθεί προσωρινά από το δίκτυο Wi-Fi ενώ είναι συνδεδεμένη στη συσκευή <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="dlg_ok" msgid="254496739491689405">"ΟΚ"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"Δεν είναι δυνατή η σύνδεση με <xliff:g id="SSID">%1$s</xliff:g>"</string>
diff --git a/service/ServiceWifiResources/res/values-en-rAU/strings.xml b/service/ServiceWifiResources/res/values-en-rAU/strings.xml
index 03afd3a..377f775 100644
--- a/service/ServiceWifiResources/res/values-en-rAU/strings.xml
+++ b/service/ServiceWifiResources/res/values-en-rAU/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"To:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"Type the required PIN:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"PIN:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"Device connection"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"Device connection"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"Invitation sent to <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"Enter this PIN on <xliff:g id="DEVICE_NAME">%1$s</xliff:g> to connect."</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"OK"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"Device connection"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"Device connection"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"Device connection"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> wants to connect to your device."</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"Enter the PIN shown on <xliff:g id="DEVICE_NAME">%1$s</xliff:g> to connect."</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> wants to connect to your device with the following PIN."</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{{device} wants to connect to your device. Accept in {countdown} second.}other{{device} wants to connect to your device. Accept in {countdown} seconds.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{Enter the PIN shown on {device} within {countdown} second to connect.}other{Enter the PIN shown on {device} within {countdown} seconds to connect.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{{device} wants to connect to your device with the following PIN. Accept in {countdown} second.}other{{device} wants to connect to your device with the following PIN. Accept in {countdown} seconds.}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"Connect"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"Cancel"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"PIN"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"PIN"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"Your device will temporarily disconnect from Wi-Fi while it\'s connected to <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="dlg_ok" msgid="254496739491689405">"OK"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"Can\'t connect to <xliff:g id="SSID">%1$s</xliff:g>"</string>
diff --git a/service/ServiceWifiResources/res/values-en-rCA/strings.xml b/service/ServiceWifiResources/res/values-en-rCA/strings.xml
index d15645c..c2b91ef 100644
--- a/service/ServiceWifiResources/res/values-en-rCA/strings.xml
+++ b/service/ServiceWifiResources/res/values-en-rCA/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"To:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"Type the required PIN:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"PIN:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"Device connection"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"Device connection"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"Invitation sent to <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"Enter this PIN on <xliff:g id="DEVICE_NAME">%1$s</xliff:g> to connect."</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"OK"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"Device connection"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"Device connection"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"Device connection"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> wants to connect to your device."</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"Enter the PIN shown on <xliff:g id="DEVICE_NAME">%1$s</xliff:g> to connect."</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> wants to connect to your device with the following PIN."</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{{device} wants to connect to your device. Accept in {countdown} second.}other{{device} wants to connect to your device. Accept in {countdown} seconds.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{Enter the PIN shown on {device} within {countdown} second to connect.}other{Enter the PIN shown on {device} within {countdown} seconds to connect.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{{device} wants to connect to your device with the following PIN. Accept in {countdown} second.}other{{device} wants to connect to your device with the following PIN. Accept in {countdown} seconds.}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"Connect"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"Cancel"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"PIN"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"PIN"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"Your device will temporarily disconnect from Wi-Fi while it\'s connected to <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="dlg_ok" msgid="254496739491689405">"OK"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"Can\'t connect to <xliff:g id="SSID">%1$s</xliff:g>"</string>
diff --git a/service/ServiceWifiResources/res/values-en-rGB/strings.xml b/service/ServiceWifiResources/res/values-en-rGB/strings.xml
index 03afd3a..377f775 100644
--- a/service/ServiceWifiResources/res/values-en-rGB/strings.xml
+++ b/service/ServiceWifiResources/res/values-en-rGB/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"To:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"Type the required PIN:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"PIN:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"Device connection"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"Device connection"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"Invitation sent to <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"Enter this PIN on <xliff:g id="DEVICE_NAME">%1$s</xliff:g> to connect."</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"OK"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"Device connection"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"Device connection"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"Device connection"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> wants to connect to your device."</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"Enter the PIN shown on <xliff:g id="DEVICE_NAME">%1$s</xliff:g> to connect."</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> wants to connect to your device with the following PIN."</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{{device} wants to connect to your device. Accept in {countdown} second.}other{{device} wants to connect to your device. Accept in {countdown} seconds.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{Enter the PIN shown on {device} within {countdown} second to connect.}other{Enter the PIN shown on {device} within {countdown} seconds to connect.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{{device} wants to connect to your device with the following PIN. Accept in {countdown} second.}other{{device} wants to connect to your device with the following PIN. Accept in {countdown} seconds.}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"Connect"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"Cancel"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"PIN"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"PIN"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"Your device will temporarily disconnect from Wi-Fi while it\'s connected to <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="dlg_ok" msgid="254496739491689405">"OK"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"Can\'t connect to <xliff:g id="SSID">%1$s</xliff:g>"</string>
diff --git a/service/ServiceWifiResources/res/values-en-rIN/strings.xml b/service/ServiceWifiResources/res/values-en-rIN/strings.xml
index 03afd3a..377f775 100644
--- a/service/ServiceWifiResources/res/values-en-rIN/strings.xml
+++ b/service/ServiceWifiResources/res/values-en-rIN/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"To:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"Type the required PIN:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"PIN:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"Device connection"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"Device connection"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"Invitation sent to <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"Enter this PIN on <xliff:g id="DEVICE_NAME">%1$s</xliff:g> to connect."</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"OK"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"Device connection"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"Device connection"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"Device connection"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> wants to connect to your device."</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"Enter the PIN shown on <xliff:g id="DEVICE_NAME">%1$s</xliff:g> to connect."</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> wants to connect to your device with the following PIN."</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{{device} wants to connect to your device. Accept in {countdown} second.}other{{device} wants to connect to your device. Accept in {countdown} seconds.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{Enter the PIN shown on {device} within {countdown} second to connect.}other{Enter the PIN shown on {device} within {countdown} seconds to connect.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{{device} wants to connect to your device with the following PIN. Accept in {countdown} second.}other{{device} wants to connect to your device with the following PIN. Accept in {countdown} seconds.}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"Connect"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"Cancel"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"PIN"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"PIN"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"Your device will temporarily disconnect from Wi-Fi while it\'s connected to <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="dlg_ok" msgid="254496739491689405">"OK"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"Can\'t connect to <xliff:g id="SSID">%1$s</xliff:g>"</string>
diff --git a/service/ServiceWifiResources/res/values-es-rUS/strings.xml b/service/ServiceWifiResources/res/values-es-rUS/strings.xml
index 72f5b3e..77d1c5f 100644
--- a/service/ServiceWifiResources/res/values-es-rUS/strings.xml
+++ b/service/ServiceWifiResources/res/values-es-rUS/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"Para:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"Escribe el PIN solicitado:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"PIN:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"Conexión del dispositivo"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"Conexión del dispositivo"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"Invitación enviada a <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"Ingresa este PIN en <xliff:g id="DEVICE_NAME">%1$s</xliff:g> para conectarte."</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"Aceptar"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"Conexión del dispositivo"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"Conexión del dispositivo"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"Conexión del dispositivo"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> quiere conectarse a tu dispositivo."</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"Ingresa el PIN que se muestra en <xliff:g id="DEVICE_NAME">%1$s</xliff:g> para conectarte."</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> quiere conectarse a tu dispositivo con el siguiente PIN."</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{{device} quiere conectarse a tu dispositivo. Aceptar en {countdown} segundo.}many{{device} quiere conectarse a tu dispositivo. Aceptar en {countdown} de segundos.}other{{device} quiere conectarse a tu dispositivo. Aceptar en {countdown} segundos.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{Ingresa el PIN que se muestra en {device} en un plazo de {countdown} segundo para conectarte.}many{Ingresa el PIN que se muestra en {device} en un plazo de {countdown} de segundos para conectarte.}other{Ingresa el PIN que se muestra en {device} en un plazo de {countdown} segundos para conectarte.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{{device} quiere conectarse a tu dispositivo con el siguiente PIN. Aceptar en {countdown} segundo.}many{{device} quiere conectarse a tu dispositivo con el siguiente PIN. Aceptar en {countdown} de segundos.}other{{device} quiere conectarse a tu dispositivo con el siguiente PIN. Aceptar en {countdown} segundos.}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"Conectar"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"Cancelar"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"PIN"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"PIN"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"Se desconectará temporalmente el dispositivo de la red Wi-Fi mientras esté conectado a <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="dlg_ok" msgid="254496739491689405">"Aceptar"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"No se puede establecer conexión con <xliff:g id="SSID">%1$s</xliff:g>"</string>
diff --git a/service/ServiceWifiResources/res/values-es/strings.xml b/service/ServiceWifiResources/res/values-es/strings.xml
index 33f0d5e..debb704 100644
--- a/service/ServiceWifiResources/res/values-es/strings.xml
+++ b/service/ServiceWifiResources/res/values-es/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"Para:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"Escribe el PIN solicitado:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"PIN:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"Conexión del dispositivo"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"Conexión del dispositivo"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"Invitación enviada a <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"Introduce este PIN en <xliff:g id="DEVICE_NAME">%1$s</xliff:g> para conectarte."</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"Aceptar"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"Conexión del dispositivo"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"Conexión del dispositivo"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"Conexión del dispositivo"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> quiere conectarse a tu dispositivo."</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"Introduce el PIN que se muestra en <xliff:g id="DEVICE_NAME">%1$s</xliff:g> para conectarte."</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> quiere conectarse a tu dispositivo con el siguiente PIN."</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{{device} quiere conectarse a tu dispositivo. Acepta en {countdown} segundo.}many{{device} quiere conectarse a tu dispositivo. Acepta en {countdown} segundos.}other{{device} quiere conectarse a tu dispositivo. Acepta en {countdown} segundos.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{Introduce el PIN que se muestra en {device} en un plazo de {countdown} segundo para conectarte.}many{Introduce el PIN que se muestra en {device} en un plazo de {countdown} segundos para conectarte.}other{Introduce el PIN que se muestra en {device} en un plazo de {countdown} segundos para conectarte.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{{device} quiere conectarse a tu dispositivo con el siguiente PIN. Acepta en {countdown} segundo.}many{{device} quiere conectarse a tu dispositivo con el siguiente PIN. Acepta en {countdown} segundos.}other{{device} quiere conectarse a tu dispositivo con el siguiente PIN. Acepta en {countdown} segundos.}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"Conectar"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"Cancelar"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"PIN"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"PIN"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"Tu dispositivo se desconectará temporalmente de la red Wi-Fi mientras esté conectado a <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="dlg_ok" msgid="254496739491689405">"Aceptar"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"No se puede conectar a <xliff:g id="SSID">%1$s</xliff:g>"</string>
diff --git a/service/ServiceWifiResources/res/values-et/strings.xml b/service/ServiceWifiResources/res/values-et/strings.xml
index 444af98..c31121d 100644
--- a/service/ServiceWifiResources/res/values-et/strings.xml
+++ b/service/ServiceWifiResources/res/values-et/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"Saaja:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"Sisestage nõutav PIN-kood:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"PIN-kood:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"Seadme ühendus"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"Seadme ühendus"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"Kutse saadeti seadmele <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"Ühenduse loomiseks sisestage see PIN-kood seadmesse<xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"OK"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"Seadme ühendus"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"Seadme ühendus"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"Seadme ühendus"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> soovib teie seadmega ühendust luua."</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"Ühenduse loomiseks sisestage seadmes <xliff:g id="DEVICE_NAME">%1$s</xliff:g> kuvatav kood."</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> soovib teie seadmega ühendust luua, kasutades järgmist PIN-koodi."</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{{device} soovib teie seadmega ühendust luua. Võtke vastu {countdown} sekundi jooksul.}other{{device} soovib teie seadmega ühendust luua. Võtke vastu {countdown} sekundi jooksul.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{Ühenduse loomiseks sisestage seadmes {device} kuvatav PIN-kood {countdown} sekundi jooksul.}other{Ühenduse loomiseks sisestage seadmes {device} kuvatav PIN-kood {countdown} sekundi jooksul.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{{device} soovib teie seadmega ühendust luua, kasutades järgmist PIN-koodi. Võtke vastu {countdown} sekundi jooksul.}other{{device} soovib teie seadmega ühendust luua, kasutades järgmist PIN-koodi. Võtke vastu {countdown} sekundi jooksul.}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"Ühenda"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"Tühista"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"PIN-kood"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"PIN-kood"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"Seadmega <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ühenduse loomisel katkestatakse ajutiselt teie seadme ühendus WiFi-võrguga."</string>
<string name="dlg_ok" msgid="254496739491689405">"OK"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"Võrguga <xliff:g id="SSID">%1$s</xliff:g> ei õnnestu ühendada"</string>
diff --git a/service/ServiceWifiResources/res/values-eu/strings.xml b/service/ServiceWifiResources/res/values-eu/strings.xml
index 42cf712..68c97c3 100644
--- a/service/ServiceWifiResources/res/values-eu/strings.xml
+++ b/service/ServiceWifiResources/res/values-eu/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"Hartzaileak:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"Idatzi beharrezko PINa:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"PINa:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"Gailuen konexioa"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"Gailuen konexioa"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"Gonbidapena bidali da <xliff:g id="DEVICE_NAME">%1$s</xliff:g> gailura."</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"Konektatzeko, idatzi PIN hau <xliff:g id="DEVICE_NAME">%1$s</xliff:g> gailuan."</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"Ados"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"Gailuen konexioa"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"Gailuen konexioa"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"Gailuen konexioa"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> gailuak zure gailura konektatu nahi du."</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"Konektatzeko, idatzi <xliff:g id="DEVICE_NAME">%1$s</xliff:g> gailuan agertzen den PINa."</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> gailuak zure gailura konektatu nahi du PIN honekin."</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{{device} gailuak zure gailura konektatu nahi du. {countdown} segundo duzu onartzeko.}other{{device} gailuak zure gailura konektatu nahi du. {countdown} segundo dituzu onartzeko.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{Konektatzeko, idatzi {device} gailuan agertzen den PINa {countdown} segundo igaro aurretik.}other{Konektatzeko, idatzi {device} gailuan agertzen den PINa {countdown} segundo igaro aurretik.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{{device} gailuak zure gailura konektatu nahi du PIN honekin. {countdown} segundo duzu onartzeko.}other{{device} gailuak zure gailura konektatu nahi du PIN honekin. {countdown} segundo dituzu onartzeko.}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"Konektatu"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"Utzi"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"PINa"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"PINa"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"Gailua wifi-saretik deskonektatuko da aldi batez <xliff:g id="DEVICE_NAME">%1$s</xliff:g> gailura konektatuta dagoen bitartean"</string>
<string name="dlg_ok" msgid="254496739491689405">"Ados"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"Ezin da konektatu <xliff:g id="SSID">%1$s</xliff:g> sarera"</string>
diff --git a/service/ServiceWifiResources/res/values-fa/strings.xml b/service/ServiceWifiResources/res/values-fa/strings.xml
index c11fd98..a1c7881 100644
--- a/service/ServiceWifiResources/res/values-fa/strings.xml
+++ b/service/ServiceWifiResources/res/values-fa/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"به:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"پین لازم را تایپ کنید:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"پین:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"اتصال دستگاه"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"اتصال دستگاه"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"دعوت به <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ارسال شد."</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"برای متصل شدن، این پین را در <xliff:g id="DEVICE_NAME">%1$s</xliff:g> وارد کنید."</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"تأیید"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"اتصال دستگاه"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"اتصال دستگاه"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"اتصال دستگاه"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> میخواهد به دستگاهتان متصل شود."</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"برای متصل شدن، پین نمایش دادهشده روی <xliff:g id="DEVICE_NAME">%1$s</xliff:g> را وارد کنید."</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> میخواهد با پین زیر به دستگاهتان متصل شود."</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{{device} میخواهد به دستگاهتان متصل شود. تا {countdown} ثانیه دیگر برای پذیرفتن فرصت دارید.}one{{device} میخواهد به دستگاهتان متصل شود. تا {countdown} ثانیه دیگر برای پذیرفتن فرصت دارید.}other{{device} میخواهد به دستگاهتان متصل شود. تا {countdown} ثانیه دیگر برای پذیرفتن فرصت دارید.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{برای متصل شدن، پین نمایش دادهشده روی {device} را تا {countdown} ثانیه دیگر وارد کنید.}one{برای متصل شدن، پین نمایش دادهشده روی {device} را تا {countdown} ثانیه دیگر وارد کنید.}other{برای متصل شدن، پین نمایش دادهشده روی {device} را تا {countdown} ثانیه دیگر وارد کنید.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{{device} میخواهد با پین زیر به دستگاهتان متصل شود. تا {countdown} ثانیه دیگر برای پذیرفتن فرصت دارید.}one{{device} میخواهد با پین زیر به دستگاهتان متصل شود. تا {countdown} ثانیه دیگر برای پذیرفتن فرصت دارید.}other{{device} میخواهد با پین زیر به دستگاهتان متصل شود. تا {countdown} ثانیه دیگر برای پذیرفتن فرصت دارید.}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"متصل شدن"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"لغو کردن"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"پین"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"پین"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"وقتی دستگاهتان به <xliff:g id="DEVICE_NAME">%1$s</xliff:g> متصل است، اتصال آن به Wi-Fi موقتاً قطع میشود"</string>
<string name="dlg_ok" msgid="254496739491689405">"تأیید"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"اتصال به <xliff:g id="SSID">%1$s</xliff:g> امکانپذیر نیست"</string>
diff --git a/service/ServiceWifiResources/res/values-fi/strings.xml b/service/ServiceWifiResources/res/values-fi/strings.xml
index dcda428..4fe2726 100644
--- a/service/ServiceWifiResources/res/values-fi/strings.xml
+++ b/service/ServiceWifiResources/res/values-fi/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"Kohde:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"Kirjoita pyydetty PIN-koodi:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"PIN-koodi:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"Laitteen yhteys"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"Laitteen yhteys"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"Kutsu lähetetty seuraavalle henkilölle: <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"Lisää tämä PIN-koodi laitteeseen (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>), jotta voit yhdistää sen."</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"OK"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"Laitteen yhteys"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"Laitteen yhteys"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"Laitteen yhteys"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> haluaa yhdistää laitteeseen."</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"Yhdistä lisäämällä PIN-koodi, joka näkyy laitteessa <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> haluaa yhdistää laitteeseen seuraavalla PIN-koodilla."</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{{device} haluaa yhdistää laitteeseen. Hyväksy {countdown} sekunnissa.}other{{device} haluaa yhdistää laitteeseen. Hyväksy {countdown} sekunnissa.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{Yhdistä laitteeseen lisäämällä laitteessa ({device}) näkyvä PIN-koodi {countdown} sekunnin kuluessa.}other{Yhdistä laitteeseen ({device}) lisäämällä PIN-koodi {countdown} sekunnin kuluessa.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{{device} haluaa yhdistää laitteeseen seuraavalla PIN-koodilla. Hyväksy {countdown} sekunnissa.}other{{device} haluaa yhdistää laitteeseen seuraavalla PIN-koodilla. Hyväksy {countdown} sekunnissa.}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"Yhdistä"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"Peru"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"PIN"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"PIN"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"Laitteen Wi-Fi-yhteys katkeaa tilapäisesti, kun siihen on yhdistetty <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="dlg_ok" msgid="254496739491689405">"OK"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"Verkkoon <xliff:g id="SSID">%1$s</xliff:g> ei saada yhteyttä"</string>
diff --git a/service/ServiceWifiResources/res/values-fr-feminine/strings.xml b/service/ServiceWifiResources/res/values-fr-feminine/strings.xml
new file mode 100644
index 0000000..bc890db
--- /dev/null
+++ b/service/ServiceWifiResources/res/values-fr-feminine/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wifi_eap_error_message_code_32763_carrier_overrides">
+ <item msgid="591026649262091217">"<xliff:g id="CARRIER_ID_PREFIX">:::1839:::</xliff:g> <xliff:g id="SSID">%1$s</xliff:g> : vous êtes déjà connectée à Verizon Wi-Fi Access. (Erreur 32763)"</item>
+ </string-array>
+</resources>
diff --git a/service/ServiceWifiResources/res/values-fr-masculine/strings.xml b/service/ServiceWifiResources/res/values-fr-masculine/strings.xml
new file mode 100644
index 0000000..9ed7470
--- /dev/null
+++ b/service/ServiceWifiResources/res/values-fr-masculine/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wifi_eap_error_message_code_32763_carrier_overrides">
+ <item msgid="591026649262091217">"<xliff:g id="CARRIER_ID_PREFIX">:::1839:::</xliff:g> <xliff:g id="SSID">%1$s</xliff:g> : vous êtes déjà connecté à Verizon Wi-Fi Access. (Erreur 32763)"</item>
+ </string-array>
+</resources>
diff --git a/service/ServiceWifiResources/res/values-fr-neuter/strings.xml b/service/ServiceWifiResources/res/values-fr-neuter/strings.xml
new file mode 100644
index 0000000..025a654
--- /dev/null
+++ b/service/ServiceWifiResources/res/values-fr-neuter/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wifi_eap_error_message_code_32763_carrier_overrides">
+ <item msgid="591026649262091217">"<xliff:g id="CARRIER_ID_PREFIX">:::1839:::</xliff:g> <xliff:g id="SSID">%1$s</xliff:g> : vous êtes déjà connecté·e à Verizon Wi-Fi Access. (Erreur 32763)"</item>
+ </string-array>
+</resources>
diff --git a/service/ServiceWifiResources/res/values-fr-rCA/strings.xml b/service/ServiceWifiResources/res/values-fr-rCA/strings.xml
index 30c082a..7ecfb0f 100644
--- a/service/ServiceWifiResources/res/values-fr-rCA/strings.xml
+++ b/service/ServiceWifiResources/res/values-fr-rCA/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"À :"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"Saisissez le NIP requis :"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"NIP :"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"Connexion à l\'appareil"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"Connexion à l\'appareil"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"Invitation envoyée à <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"Entrez ce code sur <xliff:g id="DEVICE_NAME">%1$s</xliff:g> pour vous connecter."</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"OK"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"Connexion à l\'appareil"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"Connexion à l\'appareil"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"Connexion à l\'appareil"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> souhaite se connecter à votre appareil."</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"Entrez le NIP affiché sur <xliff:g id="DEVICE_NAME">%1$s</xliff:g> pour vous connecter."</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> souhaite se connecter à votre appareil avec le NIP suivant."</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{{device} souhaite se connecter à votre appareil. Acceptez dans {countdown} seconde.}one{{device} souhaite se connecter à votre appareil. Acceptez dans {countdown} seconde.}many{{device} souhaite se connecter à votre appareil. Acceptez dans {countdown} de secondes.}other{{device} souhaite se connecter à votre appareil. Acceptez dans {countdown} secondes.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{Entrez le NIP affiché sur {device} dans un délai de {countdown} seconde pour vous connecter.}one{Entrez le NIP affiché sur {device} dans un délai de {countdown} seconde pour vous connecter.}many{Entrez le NIP affiché sur {device} dans un délai de {countdown} de secondes pour vous connecter.}other{Entrez le NIP affiché sur {device} dans un délai de {countdown} secondes pour vous connecter.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{{device} souhaite se connecter à votre appareil avec le NIP suivant. Acceptez dans {countdown} seconde.}one{{device} souhaite se connecter à votre appareil avec le NIP suivant. Acceptez dans {countdown} seconde.}many{{device} souhaite se connecter à votre appareil avec le NIP suivant. Acceptez dans {countdown} de secondes.}other{{device} souhaite se connecter à votre appareil avec le NIP suivant. Acceptez dans {countdown} secondes.}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"Se connecter"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"Annuler"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"NIP"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"NIP"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"Votre appareil sera déconnecté temporairement de la connexion Wi-Fi lorsqu\'il sera connecté à <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="dlg_ok" msgid="254496739491689405">"OK"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"Impossible de se connecter à <xliff:g id="SSID">%1$s</xliff:g>"</string>
diff --git a/service/ServiceWifiResources/res/values-fr/strings.xml b/service/ServiceWifiResources/res/values-fr/strings.xml
index cbc4374..17cdb90 100644
--- a/service/ServiceWifiResources/res/values-fr/strings.xml
+++ b/service/ServiceWifiResources/res/values-fr/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"À :"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"Saisissez le code PIN requis :"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"Code :"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"Connexion de l\'appareil"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"Connexion de l\'appareil"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"Invitation envoyée à <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"Saisissez ce code sur <xliff:g id="DEVICE_NAME">%1$s</xliff:g> pour vous connecter."</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"OK"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"Connexion de l\'appareil"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"Connexion de l\'appareil"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"Connexion de l\'appareil"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> souhaite se connecter à votre appareil."</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"Saisissez le code qui s\'affiche sur <xliff:g id="DEVICE_NAME">%1$s</xliff:g> pour vous connecter."</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> souhaite se connecter à votre appareil avec le code suivant."</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{{device} souhaite se connecter à votre appareil. {countdown} seconde restante pour accepter.}one{{device} souhaite se connecter à votre appareil. {countdown} seconde restante pour accepter.}many{{device} souhaite se connecter à votre appareil. {countdown} de secondes restantes pour accepter.}other{{device} souhaite se connecter à votre appareil. {countdown} secondes restantes pour accepter.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{Il vous reste {countdown} seconde pour saisir le code qui s\'affiche sur {device} et vous connecter.}one{Il vous reste {countdown} seconde pour saisir le code qui s\'affiche sur {device} et vous connecter.}many{Il vous reste {countdown} de secondes pour saisir le code qui s\'affiche sur {device} et vous connecter.}other{Il vous reste {countdown} secondes pour saisir le code qui s\'affiche sur {device} et vous connecter.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{{device} souhaite se connecter à votre appareil avec le code suivant. {countdown} seconde restante pour accepter.}one{{device} souhaite se connecter à votre appareil avec le code suivant. {countdown} seconde restante pour accepter.}many{{device} souhaite se connecter à votre appareil avec le code suivant. {countdown} de secondes restantes pour accepter.}other{{device} souhaite se connecter à votre appareil avec le code suivant. {countdown} secondes restantes pour accepter.}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"Connecter"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"Annuler"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"Code"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"Code"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"Tant que votre appareil sera connecté à <xliff:g id="DEVICE_NAME">%1$s</xliff:g>, il sera temporairement déconnecté du Wi-Fi"</string>
<string name="dlg_ok" msgid="254496739491689405">"OK"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"Impossible de se connecter à <xliff:g id="SSID">%1$s</xliff:g>"</string>
diff --git a/service/ServiceWifiResources/res/values-gl/strings.xml b/service/ServiceWifiResources/res/values-gl/strings.xml
index 5123f9a..41aa779 100644
--- a/service/ServiceWifiResources/res/values-gl/strings.xml
+++ b/service/ServiceWifiResources/res/values-gl/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"Para:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"Escribe o PIN obrigatorio:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"PIN:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"Conexión entre dispositivos"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"Conexión entre dispositivos"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"Invitación enviada a <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"Para establecer a conexión, mete este PIN en <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"Aceptar"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"Conexión entre dispositivos"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"Conexión entre dispositivos"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"Conexión entre dispositivos"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> quere conectarse ao teu dispositivo."</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"Para establecer a conexión, mete o PIN que aparece en <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> quere conectarse ao teu dispositivo co seguinte PIN."</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{{device} quere conectarse ao teu dispositivo. Acepta en {countdown} segundo.}other{{device} quere conectarse ao teu dispositivo. Acepta en {countdown} segundos.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{Para establecer a conexión, mete o PIN que aparece en {device} nun prazo de {countdown} segundo.}other{Para establecer a conexión, mete o PIN que aparece en {device} nun prazo de {countdown} segundos.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{{device} quere conectarse ao teu dispositivo co seguinte PIN. Acepta en {countdown} segundo.}other{{device} quere conectarse ao teu dispositivo co seguinte PIN. Acepta en {countdown} segundos.}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"Conectar"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"Cancelar"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"PIN"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"PIN"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"O dispositivo desconectarase temporalmente da wifi mentres estea conectado a <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="dlg_ok" msgid="254496739491689405">"Aceptar"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"Non se puido establecer conexión co <xliff:g id="SSID">%1$s</xliff:g>"</string>
diff --git a/service/ServiceWifiResources/res/values-gu/strings.xml b/service/ServiceWifiResources/res/values-gu/strings.xml
index 3ef9523..90e0c4d 100644
--- a/service/ServiceWifiResources/res/values-gu/strings.xml
+++ b/service/ServiceWifiResources/res/values-gu/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"પ્રતિ:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"આવશ્યક પિન લખો:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"પિન:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"ડિવાઇસ કનેક્શન"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"ડિવાઇસ કનેક્શન"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>ને આમંત્રણ મોકલ્યું."</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"કનેક્ટ કરવા માટે <xliff:g id="DEVICE_NAME">%1$s</xliff:g> પર આ પિન દાખલ કરો."</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"ઓકે"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"ડિવાઇસ કનેક્શન"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"ડિવાઇસ કનેક્શન"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"ડિવાઇસ કનેક્શન"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> તમારા ડિવાઇસ સાથે કનેક્ટ થવા માગે છે."</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"કનેક્ટ કરવા માટે <xliff:g id="DEVICE_NAME">%1$s</xliff:g> પર બતાવવામાં આવેલો પિન દાખલ કરો."</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"નીચે જણાવેલા પિન સાથે <xliff:g id="DEVICE_NAME">%1$s</xliff:g> તમારા ડિવાઇસ સાથે કનેક્ટ થવા માગે છે."</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{{device} તમારા ડિવાઇસ સાથે કનેક્ટ થવા માગે છે. {countdown} સેકન્ડમાં સ્વીકારો.}one{{device} તમારા ડિવાઇસ સાથે કનેક્ટ થવા માગે છે. {countdown} સેકન્ડમાં સ્વીકારો.}other{{device} તમારા ડિવાઇસ સાથે કનેક્ટ થવા માગે છે. {countdown} સેકન્ડમાં સ્વીકારો.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{કનેક્ટ કરવા માટે {device} પર બતાવવામાં આવેલો પિન {countdown} સેકન્ડમાં દાખલ કરો.}one{કનેક્ટ કરવા માટે {device} પર બતાવવામાં આવેલો પિન {countdown} સેકન્ડમાં દાખલ કરો.}other{કનેક્ટ કરવા માટે {device} પર બતાવવામાં આવેલો પિન {countdown} સેકન્ડમાં દાખલ કરો.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{નીચે જણાવેલા પિન સાથે {device} તમારા ડિવાઇસ સાથે કનેક્ટ થવા માગે છે. {countdown} સેકન્ડમાં સ્વીકારો.}one{નીચે જણાવેલા પિન સાથે {device} તમારા ડિવાઇસ સાથે કનેક્ટ થવા માગે છે. {countdown} સેકન્ડમાં સ્વીકારો.}other{નીચે જણાવેલા પિન સાથે {device} તમારા ડિવાઇસ સાથે કનેક્ટ થવા માગે છે. {countdown} સેકન્ડમાં સ્વીકારો.}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"કનેક્ટ કરો"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"રદ કરો"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"પિન"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"પિન"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"જ્યારે તમારું ડિવાઇસ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> સાથે કનેક્ટેડ હોય, ત્યારે તેને વાઇ-ફાઇથી હંગામી રીતે ડિસ્કનેક્ટ કરવામાં આવશે"</string>
<string name="dlg_ok" msgid="254496739491689405">"ઓકે"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"<xliff:g id="SSID">%1$s</xliff:g> સાથે કનેક્ટ કરી શકાતું નથી"</string>
diff --git a/service/ServiceWifiResources/res/values-hi/strings.xml b/service/ServiceWifiResources/res/values-hi/strings.xml
index 0b6ba44..732d4dd 100644
--- a/service/ServiceWifiResources/res/values-hi/strings.xml
+++ b/service/ServiceWifiResources/res/values-hi/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"प्रति:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"आवश्यक पिन लिखें:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"पिन:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"डिवाइस कनेक्शन"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"डिवाइस कनेक्शन"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> पर न्योता भेजा गया."</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"कनेक्ट करने के लिए, <xliff:g id="DEVICE_NAME">%1$s</xliff:g> पर यह पिन डालें."</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"ठीक है"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"डिवाइस कनेक्शन"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"डिवाइस कनेक्शन"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"डिवाइस कनेक्शन"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"आपको अपने डिवाइस से <xliff:g id="DEVICE_NAME">%1$s</xliff:g> को कनेक्ट करने का अनुरोध मिला है."</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"कनेक्ट करने के लिए, <xliff:g id="DEVICE_NAME">%1$s</xliff:g> पर दिखाया गया पिन डालें."</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"आपको इस पिन की मदद से <xliff:g id="DEVICE_NAME">%1$s</xliff:g> को अपने डिवाइस से कनेक्ट करने का अनुरोध मिला है."</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{आपको अपने डिवाइस से {device} को कनेक्ट करने का अनुरोध मिला है. इस अनुरोध को {countdown} सेकंड में स्वीकार करें.}one{आपको अपने डिवाइस से {device} को कनेक्ट करने का अनुरोध मिला है. इसे {countdown} सेकंड में स्वीकार करें.}other{आपको अपने डिवाइस से {device} को कनेक्ट करने का अनुरोध मिला है. इसे {countdown} सेकंड में स्वीकार करें.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{कनेक्ट करने के लिए, {device} पर दिखाए गए पिन को {countdown} सेकंड के अंदर डालें.}one{कनेक्ट करने के लिए, {device} पर दिखाए गए पिन को {countdown} सेकंड के अंदर डालें.}other{कनेक्ट करने के लिए, {device} पर दिखाए गए पिन को {countdown} सेकंड के अंदर डालें.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{आपको इस पिन की मदद से {device} को अपने डिवाइस से कनेक्ट करने का अनुरोध मिला है. इस अनुरोध को {countdown} सेकंड में स्वीकार करें.}one{आपको इस पिन की मदद से {device} को अपने डिवाइस से कनेक्ट करने का अनुरोध मिला है. इस अनुरोध को {countdown} सेकंड में स्वीकार करें.}other{आपको इस पिन की मदद से {device} को अपने डिवाइस से कनेक्ट करने का अनुरोध मिला है. इस अनुरोध को {countdown} सेकंड में स्वीकार करें.}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"कनेक्ट करें"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"रद्द करें"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"पिन"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"पिन"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> से कनेक्ट रहने के दौरान आपका डिवाइस, वाई-फ़ाई से अस्थायी रूप से डिसकनेक्ट हो जाएगा"</string>
<string name="dlg_ok" msgid="254496739491689405">"ठीक है"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"<xliff:g id="SSID">%1$s</xliff:g> से कनेक्ट नहीं किया जा सकता"</string>
diff --git a/service/ServiceWifiResources/res/values-hr/strings.xml b/service/ServiceWifiResources/res/values-hr/strings.xml
index dd3bfba..bf88b90 100644
--- a/service/ServiceWifiResources/res/values-hr/strings.xml
+++ b/service/ServiceWifiResources/res/values-hr/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"Prima:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"Upišite potreban PIN:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"PIN:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"Veza uređaja"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"Veza uređaja"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"Pozivnica je poslana na uređaj <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"Unesite ovaj PIN na uređaju <xliff:g id="DEVICE_NAME">%1$s</xliff:g> da biste se povezali."</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"U redu"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"Veza uređaja"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"Veza uređaja"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"Veza uređaja"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"Uređaj <xliff:g id="DEVICE_NAME">%1$s</xliff:g> želi se povezati s vašim uređajem."</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"Unesite PIN prikazan na uređaju <xliff:g id="DEVICE_NAME">%1$s</xliff:g> da biste se povezali."</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"Uređaj <xliff:g id="DEVICE_NAME">%1$s</xliff:g> želi se povezati s vašim uređajem pomoću sljedećeg PIN-a."</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{Uređaj {device} želi se povezati s vašim uređajem. Prihvatite za {countdown} sekundu.}one{Uređaj {device} želi se povezati s vašim uređajem. Prihvatite za {countdown} sekundu.}few{Uređaj {device} želi se povezati s vašim uređajem. Prihvatite za {countdown} sekunde.}other{Uređaj {device} želi se povezati s vašim uređajem. Prihvatite za {countdown} sekundi.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{Unesite PIN prikazan na uređaju {device} u roku od {countdown} sekunde da biste se povezali.}one{Unesite PIN prikazan na uređaju {device} u roku od {countdown} sekunde da biste se povezali.}few{Unesite PIN prikazan na uređaju {device} u roku od {countdown} sekunde da biste se povezali.}other{Unesite PIN prikazan na uređaju {device} u roku od {countdown} sekundi da biste se povezali.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{Uređaj {device} želi se povezati s vašim uređajem pomoću sljedećeg PIN-a. Prihvatite za {countdown} sekundu.}one{Uređaj {device} želi se povezati s vašim uređajem pomoću sljedećeg PIN-a. Prihvatite za {countdown} sekundu.}few{Uređaj {device} želi se povezati s vašim uređajem pomoću sljedećeg PIN-a. Prihvatite za {countdown} sekunde.}other{Uređaj {device} želi se povezati s vašim uređajem pomoću sljedećeg PIN-a. Prihvatite za {countdown} sekundi.}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"Poveži"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"Odustani"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"PIN"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"PIN"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"Vaš će uređaj privremeno prekinuti vezu s Wi-Fijem dok je povezan s uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="dlg_ok" msgid="254496739491689405">"U redu"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"Povezivanje s mrežom <xliff:g id="SSID">%1$s</xliff:g> nije uspjelo"</string>
diff --git a/service/ServiceWifiResources/res/values-hu/strings.xml b/service/ServiceWifiResources/res/values-hu/strings.xml
index bd7e938..e12768b 100644
--- a/service/ServiceWifiResources/res/values-hu/strings.xml
+++ b/service/ServiceWifiResources/res/values-hu/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"Címzett:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"Adja meg a szükséges PIN kódot:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"PIN-kód:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"Eszközkapcsolat"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"Eszközkapcsolat"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"Meghívó elküldve a következő eszköznek: <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"A csatlakozáshoz adja meg ezt a PIN-kódot a(z) <xliff:g id="DEVICE_NAME">%1$s</xliff:g> eszközön."</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"OK"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"Eszközkapcsolat"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"Eszközkapcsolat"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"Eszközkapcsolat"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"A(z) <xliff:g id="DEVICE_NAME">%1$s</xliff:g> csatlakozni szeretne az Ön eszközéhez."</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"A csatlakozáshoz adja meg a(z) <xliff:g id="DEVICE_NAME">%1$s</xliff:g> eszközön megjelenő PIN-kódot."</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"A(z) <xliff:g id="DEVICE_NAME">%1$s</xliff:g> a következő PIN-kóddal szeretne csatlakozni az Ön eszközéhez."</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{A(z) {device} csatlakozni szeretne az Ön eszközéhez. {countdown} másodperc maradt az elfogadásra.}other{A(z) {device} csatlakozni szeretne az Ön eszközéhez. {countdown} másodperc maradt az elfogadásra.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{A csatlakozáshoz {countdown} másodpercen belül adja meg a(z) {device} eszközön megjelenő PIN-kódot.}other{A csatlakozáshoz {countdown} másodpercen belül adja meg a(z) {device} eszközön megjelenő PIN-kódot.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{A(z) {device} a következő PIN-kóddal szeretne csatlakozni az Ön eszközéhez. {countdown} másodperc maradt az elfogadásra.}other{A(z) {device} a következő PIN-kóddal szeretne csatlakozni az Ön eszközéhez. {countdown} másodperc maradt az elfogadásra.}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"Csatlakozás"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"Mégse"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"PIN-kód"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"PIN-kód"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"Az eszköze ideiglenesen bontja a Wi-Fi-kapcsolatot arra az időre, amíg a(z) <xliff:g id="DEVICE_NAME">%1$s</xliff:g> eszközhöz csatlakozik"</string>
<string name="dlg_ok" msgid="254496739491689405">"OK"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"Nem lehet csatlakozni a következőhöz: <xliff:g id="SSID">%1$s</xliff:g>"</string>
diff --git a/service/ServiceWifiResources/res/values-hy/strings.xml b/service/ServiceWifiResources/res/values-hy/strings.xml
index 84738c1..70400c5 100644
--- a/service/ServiceWifiResources/res/values-hy/strings.xml
+++ b/service/ServiceWifiResources/res/values-hy/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"Ում`"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"Մուտքագրեք պահանջվող PIN-ը:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"PIN-ը՝"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"Սարքի միացում"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"Սարքի միացում"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"Հրավերն ուղարկվել է <xliff:g id="DEVICE_NAME">%1$s</xliff:g> սարքին։"</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"Միանալու համար մուտքագրեք այս PIN կոդը <xliff:g id="DEVICE_NAME">%1$s</xliff:g> սարքում։"</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"Եղավ"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"Սարքի միացում"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"Սարքի միացում"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"Սարքի միացում"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> սարքն ուզում է միանալ ձեր սարքին։"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"Միանալու համար մուտքագրեք <xliff:g id="DEVICE_NAME">%1$s</xliff:g> սարքում ցուցադրվող PIN կոդը։"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> սարքն ուզում է միանալ ձեր սարքին հետևյալ PIN կոդով։"</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{{device} սարքն ուզում է միանալ ձեր սարքին։ Մնաց {countdown} վայրկյան։}one{{device} սարքն ուզում է միանալ ձեր սարքին։ Մնաց {countdown} վայրկյան։}other{{device} սարքն ուզում է միանալ ձեր սարքին։ Մնաց {countdown} վայրկյան։}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{Միանալու համար {countdown} վայրկյանի ընթացքում մուտքագրեք {device} սարքում ցուցադրվող PIN կոդը։}one{Միանալու համար {countdown} վայրկյանի ընթացքում մուտքագրեք {device} սարքում ցուցադրվող PIN կոդը։}other{Միանալու համար {countdown} վայրկյանի ընթացքում մուտքագրեք {device} սարքում ցուցադրվող PIN կոդը։}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{{device} սարքն ուզում է միանալ ձեր սարքին հետևյալ PIN կոդով։ Մնաց {countdown} վայրկյան։}one{{device} սարքն ուզում է միանալ ձեր սարքին հետևյալ PIN կոդով։ Մնաց {countdown} վայրկյան։}other{{device} սարքն ուզում է միանալ ձեր սարքին հետևյալ PIN կոդով։ Մնաց {countdown} վայրկյան։}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"Միանալ"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"Չեղարկել"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"PIN կոդ"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"PIN կոդ"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"Ձեր սարքը ժամանակավորապես կանջատվի Wi-Fi-ից, քանի դեռ միացված է <xliff:g id="DEVICE_NAME">%1$s</xliff:g>-ին"</string>
<string name="dlg_ok" msgid="254496739491689405">"Եղավ"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"Չհաջողվեց միանալ <xliff:g id="SSID">%1$s</xliff:g> սարքին"</string>
diff --git a/service/ServiceWifiResources/res/values-in/strings.xml b/service/ServiceWifiResources/res/values-in/strings.xml
index 5e81803..ccab0c8 100644
--- a/service/ServiceWifiResources/res/values-in/strings.xml
+++ b/service/ServiceWifiResources/res/values-in/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"Kepada:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"Ketik PIN yang diminta:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"PIN:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"Koneksi perangkat"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"Koneksi perangkat"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"Undangan dikirim ke <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"Masukkan PIN ini di <xliff:g id="DEVICE_NAME">%1$s</xliff:g> untuk menghubungkan."</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"Oke"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"Koneksi perangkat"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"Koneksi perangkat"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"Koneksi perangkat"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> ingin terhubung ke perangkat Anda."</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"Masukkan PIN yang ditampilkan di <xliff:g id="DEVICE_NAME">%1$s</xliff:g> untuk menghubungkan."</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> ingin terhubung ke perangkat Anda dengan PIN berikut."</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{{device} ingin terhubung ke perangkat Anda. Terima dalam {countdown} detik.}other{{device} ingin terhubung ke perangkat Anda. Terima dalam {countdown} detik.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{Masukkan PIN yang ditampilkan di {device} dalam {countdown} detik untuk menghubungkan.}other{Masukkan PIN yang ditampilkan di {device} dalam {countdown} detik untuk menghubungkan.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{{device} ingin terhubung ke perangkat Anda dengan PIN berikut. Terima dalam {countdown} detik.}other{{device} ingin terhubung ke perangkat Anda dengan PIN berikut. Terima dalam {countdown} detik.}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"Hubungkan"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"Batal"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"PIN"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"PIN"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"Koneksi perangkat akan terputus sementara dari Wi-Fi saat terhubung ke <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="dlg_ok" msgid="254496739491689405">"Oke"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"Tidak dapat terhubung ke <xliff:g id="SSID">%1$s</xliff:g>"</string>
diff --git a/service/ServiceWifiResources/res/values-is/strings.xml b/service/ServiceWifiResources/res/values-is/strings.xml
index ebb850a..47b4188 100644
--- a/service/ServiceWifiResources/res/values-is/strings.xml
+++ b/service/ServiceWifiResources/res/values-is/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"Til:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"Sláðu inn PIN-númerið sem er krafist:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"PIN-númer:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"Tenging tækis"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"Tenging tækis"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"Boð var sent í <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"Sláðu þetta PIN-númer inn í <xliff:g id="DEVICE_NAME">%1$s</xliff:g> til að tengjast."</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"Í lagi"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"Tenging tækis"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"Tenging tækis"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"Tenging tækis"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> vill tengjast tækinu þínu."</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"Sláðu inn PIN-númerið sem birtist í <xliff:g id="DEVICE_NAME">%1$s</xliff:g> til að tengjast."</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> vill tengjast tækinu þínu með eftirfarandi PIN-númeri."</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{{device} vill tengjast tækinu þínu. Samþykktu áður en {countdown} sekúnda er liðin.}one{{device} vill tengjast tækinu þínu. Samþykktu áður en {countdown} sekúnda er liðin.}other{{device} vill tengjast tækinu þínu. Samþykktu áður en {countdown} sekúndur eru liðnar.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{Sláðu inn PIN-númerið sem birtist í {device} innan {countdown} sekúndu til að tengjast.}one{Sláðu inn PIN-númerið sem birtist í {device} innan {countdown} sekúndu til að tengjast.}other{Sláðu inn PIN-númerið sem birtist í {device} innan {countdown} sekúndna til að tengjast.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{{device} vill tengjast tækinu þínu með eftirfarandi PIN-númeri. Samþykktu áður en {countdown} sekúnda er liðin.}one{{device} vill tengjast tækinu þínu með eftirfarandi PIN-númeri. Samþykktu áður en {countdown} sekúnda er liðin.}other{{device} vill tengjast tækinu þínu með eftirfarandi PIN-númeri. Samþykktu áður en {countdown} sekúndur eru liðnar.}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"Tengja"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"Hætta við"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"PIN-númer"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"PIN-númer"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"Tækið þitt mun tímabundið aftengjast Wi-Fi á meðan það er tengt við <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="dlg_ok" msgid="254496739491689405">"Í lagi"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"Ekki hægt að tengjast <xliff:g id="SSID">%1$s</xliff:g>"</string>
diff --git a/service/ServiceWifiResources/res/values-it/strings.xml b/service/ServiceWifiResources/res/values-it/strings.xml
index 1d6ef13..3c9a6ac 100644
--- a/service/ServiceWifiResources/res/values-it/strings.xml
+++ b/service/ServiceWifiResources/res/values-it/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"A:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"Inserisci il PIN richiesto:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"PIN:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"Connessione dispositivo"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"Connessione dispositivo"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"Invito inviato a <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"Inserisci questo PIN su <xliff:g id="DEVICE_NAME">%1$s</xliff:g> per connetterti."</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"Ok"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"Connessione dispositivo"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"Connessione dispositivo"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"Connessione dispositivo"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> vuole connettersi al tuo dispositivo."</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"Inserisci il PIN mostrato su <xliff:g id="DEVICE_NAME">%1$s</xliff:g> per connetterti."</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> vuole connettersi al tuo dispositivo con il seguente PIN."</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{{device} vuole connettersi al tuo dispositivo. Accetta entro {countdown} secondo.}many{{device} vuole connettersi al tuo dispositivo. Accetta entro {countdown} di secondi.}other{{device} vuole connettersi al tuo dispositivo. Accetta entro {countdown} secondi.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{Inserisci il PIN mostrato su {device} entro {countdown} secondo per connetterti.}many{Inserisci il PIN mostrato su {device} entro {countdown} di secondi per connetterti.}other{Inserisci il PIN mostrato su {device} entro {countdown} secondi per connetterti.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{{device} vuole connettersi al tuo dispositivo con il seguente PIN. Accetta entro {countdown} secondo.}many{{device} vuole connettersi al tuo dispositivo con il seguente PIN. Accetta entro {countdown} secondi.}other{{device} vuole connettersi al tuo dispositivo con il seguente PIN. Accetta entro {countdown} secondi.}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"Connetti"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"Annulla"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"PIN"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"PIN"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"Il dispositivo verrà scollegato temporaneamente dalla rete Wi-Fi mentre è connesso a <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="dlg_ok" msgid="254496739491689405">"Ok"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"Impossibile connettersi alla rete <xliff:g id="SSID">%1$s</xliff:g>"</string>
diff --git a/service/ServiceWifiResources/res/values-iw/strings.xml b/service/ServiceWifiResources/res/values-iw/strings.xml
index df298ff..03edc4d 100644
--- a/service/ServiceWifiResources/res/values-iw/strings.xml
+++ b/service/ServiceWifiResources/res/values-iw/strings.xml
@@ -21,7 +21,7 @@
<string name="wifi_available_title_connecting" msgid="7233590022728579868">"התחברות לרשת Wi-Fi"</string>
<string name="wifi_available_title_connected" msgid="6329493859989844201">"בוצע חיבור לרשת Wi-Fi"</string>
<string name="wifi_available_title_failed_to_connect" msgid="4840833680513368639">"לא ניתן היה להתחבר לרשת Wi-Fi"</string>
- <string name="wifi_available_content_failed_to_connect" msgid="4330035988269701861">"יש להקיש כדי לראות את כל הרשתות"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="4330035988269701861">"יש ללחוץ כדי לראות את כל הרשתות"</string>
<string name="wifi_available_action_connect" msgid="5636634933476946222">"התחברות"</string>
<string name="wifi_available_action_all_networks" msgid="8491109932336522211">"כל הרשתות"</string>
<string name="notification_channel_network_status" msgid="1631786866932924838">"סטטוס הרשת"</string>
@@ -60,10 +60,28 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"אל:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"יש להקליד את קוד האימות הנדרש:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"קוד אימות:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"חיבור בין המכשירים"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"חיבור בין המכשירים"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"נשלחה הזמנה אל <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"כדי להתחבר, צריך להזין את קוד האימות הזה במכשיר <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"אישור"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"חיבור בין המכשירים"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"חיבור בין המכשירים"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"חיבור בין המכשירים"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"המכשיר <xliff:g id="DEVICE_NAME">%1$s</xliff:g> מבקש להתחבר למכשיר שלך."</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"כדי להתחבר, צריך להזין את קוד האימות שמוצג במכשיר <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"המכשיר <xliff:g id="DEVICE_NAME">%1$s</xliff:g> מבקש להתחבר למכשיר שלך באמצעות קוד האימות הבא."</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{מכשיר {device} מבקש להתחבר למכשיר שלך. ניתן לאשר תוך שנייה ({countdown}).}one{מכשיר {device} מבקש להתחבר למכשיר שלך. ניתן לאשר תוך {countdown} שניות.}two{מכשיר {device} מבקש להתחבר למכשיר שלך. ניתן לאשר תוך {countdown} שניות.}other{מכשיר {device} מבקש להתחבר למכשיר שלך. ניתן לאשר תוך {countdown} שניות.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{כדי להתחבר, צריך להזין את קוד האימות שמוצג במכשיר {device} תוך שנייה ({countdown}).}one{כדי להתחבר, צריך להזין את קוד האימות שמוצג במכשיר {device} תוך {countdown} שניות.}two{כדי להתחבר, צריך להזין את קוד האימות שמוצג במכשיר {device} תוך {countdown} שניות.}other{כדי להתחבר, צריך להזין את קוד האימות שמוצג במכשיר {device} תוך {countdown} שניות.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{המכשיר {device} מבקש להתחבר למכשיר שלך באמצעות קוד האימות הבא. ניתן לאשר תוך שנייה ({countdown}).}one{המכשיר {device} מבקש להתחבר למכשיר שלך באמצעות קוד האימות הבא. ניתן לאשר תוך {countdown} שניות.}two{המכשיר {device} מבקש להתחבר למכשיר שלך באמצעות קוד האימות הבא. ניתן לאשר תוך {countdown} שניות.}other{המכשיר {device} מבקש להתחבר למכשיר שלך באמצעות קוד האימות הבא. ניתן לאשר תוך {countdown} שניות.}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"חיבור"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"ביטול"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"קוד אימות"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"קוד אימות"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"המכשיר יתנתק מרשת ה-Wi-Fi באופן זמני כשהוא מחובר אל <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="dlg_ok" msgid="254496739491689405">"אישור"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"לא ניתן להתחבר אל <xliff:g id="SSID">%1$s</xliff:g>"</string>
- <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="4834133226521813352">"יש להקיש כדי לשנות את הגדרות הפרטיות ולנסות שוב"</string>
+ <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="4834133226521813352">"יש ללחוץ כדי לשנות את הגדרות הפרטיות ולנסות שוב"</string>
<string name="wifi_disable_mac_randomization_dialog_title" msgid="2054540994993681606">"לשנות את הגדרות הפרטיות?"</string>
<string name="wifi_disable_mac_randomization_dialog_message" msgid="8874064864332248988">"כדי לבצע חיבור, עליך לאפשר ל-<xliff:g id="SSID">%1$s</xliff:g> להשתמש בכתובת ה-MAC של המכשיר, שהיא מזהה ייחודי. הגדרת הפרטיות לרשת הזו משתמשת כרגע במזהה רנדומלי. \n\nשינוי זה עשוי לאפשר למכשירים בקרבת מקום לעקוב אחר מיקום המכשיר שלך."</string>
<string name="wifi_disable_mac_randomization_dialog_confirm_text" msgid="6954419863076751626">"שינוי ההגדרות"</string>
@@ -117,7 +135,7 @@
<item msgid="2705387186478280792">"<xliff:g id="CARRIER_ID_PREFIX">:::1839:::</xliff:g><xliff:g id="SSID">%1$s</xliff:g> : יש בעיה בהתחברות ל-Wi-Fi של Verizon. (קוד שגיאה = לא ידוע)"</item>
</string-array>
<string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="4896534374569504484">"נקודת האינטרנט (hotspot) נכבתה"</string>
- <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="7975476698140267728">"אין מכשירים מחוברים. יש להקיש כדי לשנות."</string>
+ <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="7975476698140267728">"אין מכשירים מחוברים. יש ללחוץ כדי לשנות."</string>
<string name="wifi_sim_required_title" msgid="2262227800991155459">"Wi-Fi מנותק"</string>
<string name="wifi_sim_required_message" msgid="284812212346125745">"יש להכניס SIM של <xliff:g id="CARRIER_NAME">%2$s</xliff:g> כדי להתחבר אל <xliff:g id="SSID">%1$s</xliff:g>"</string>
<string name="wifi_interface_priority_title" msgid="5117627874976875544">"האפליקציה <xliff:g id="APP">%1$s</xliff:g> מבקשת להשתמש במשאב רשת"</string>
@@ -141,7 +159,7 @@
<string name="wifi_ca_cert_dialog_message_signature_name_text" msgid="8455163626514894233">"טביעת אצבע SHA-256:\n<xliff:g id="VALUE">%1$s</xliff:g>\n\n"</string>
<string name="wifi_ca_cert_dialog_message_contact_text" msgid="5799083318641183815">"איש קשר:\n<xliff:g id="VALUE">%1$s</xliff:g>\n\n"</string>
<string name="wifi_ca_cert_notification_title" msgid="537569884930429796">"צריך לאמת את הרשת"</string>
- <string name="wifi_ca_cert_notification_message" msgid="6413248690626616961">"צריך לעיין בפרטי הרשת <xliff:g id="SSID">%1$s</xliff:g> לפני שמתחברים אליה. מקישים כדי להמשיך."</string>
+ <string name="wifi_ca_cert_notification_message" msgid="6413248690626616961">"צריך לעיין בפרטי הרשת <xliff:g id="SSID">%1$s</xliff:g> לפני שמתחברים אליה. לוחצים כדי להמשיך."</string>
<string name="wifi_ca_cert_failed_to_install_ca_cert" msgid="4864192219789736195">"הניסיון להתקנת האישור נכשל."</string>
<string name="wifi_tofu_invalid_cert_chain_title" msgid="332710627417595752">"לא ניתן להתחבר אל <xliff:g id="VALUE">%1$s</xliff:g>"</string>
<string name="wifi_tofu_invalid_cert_chain_message" msgid="7047987920029432392">"שרשרת האישורים של השרת לא חוקית."</string>
@@ -152,7 +170,7 @@
<string name="wifi_ca_cert_dialog_preT_message_hint" msgid="5682518783200852031">"חסר אישור לרשת <xliff:g id="SSID">%1$s</xliff:g>."</string>
<string name="wifi_ca_cert_dialog_preT_message_link" msgid="6325483132538546884">"הוראות להוספת אישורים"</string>
<string name="wifi_ca_cert_notification_preT_title" msgid="7255129934648316663">"לא ניתן לאמת את הרשת הזו"</string>
- <string name="wifi_ca_cert_notification_preT_message" msgid="4565553176090475724">"חסר אישור לרשת <xliff:g id="SSID">%1$s</xliff:g>. יש להקיש כדי ללמוד איך להוסיף אישורים."</string>
+ <string name="wifi_ca_cert_notification_preT_message" msgid="4565553176090475724">"חסר אישור לרשת <xliff:g id="SSID">%1$s</xliff:g>. יש ללחוץ כדי ללמוד איך להוסיף אישורים."</string>
<string name="wifi_ca_cert_notification_preT_continue_text" msgid="1525418430746943670">"יש להתחבר בכל זאת"</string>
<string name="wifi_ca_cert_notification_preT_abort_text" msgid="8307996031461071854">"אין להתחבר"</string>
<string name="wifi_enable_request_dialog_title" msgid="3577459145316177148">"לאפשר לאפליקציה <xliff:g id="APP_NAME">%1$s</xliff:g> להפעיל את ה-Wi‑Fi?"</string>
diff --git a/service/ServiceWifiResources/res/values-ja/strings.xml b/service/ServiceWifiResources/res/values-ja/strings.xml
index 6c31f68..10b78e3 100644
--- a/service/ServiceWifiResources/res/values-ja/strings.xml
+++ b/service/ServiceWifiResources/res/values-ja/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"受信側:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"必要なPINを入力してください:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"PIN:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"デバイスの接続"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"デバイスの接続"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> に招待状を送信しました。"</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"接続するには、この PIN を <xliff:g id="DEVICE_NAME">%1$s</xliff:g> に入力してください。"</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"OK"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"デバイスの接続"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"デバイスの接続"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"デバイスの接続"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> がデバイスへの接続をリクエストしています。"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"接続するには、<xliff:g id="DEVICE_NAME">%1$s</xliff:g> に表示されている PIN を入力してください。"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> が次の PIN を使用してデバイスへの接続をリクエストしています。"</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{{device} がデバイスへの接続をリクエストしています。{countdown} 秒以内に承諾してください。}other{{device} がデバイスへの接続をリクエストしています。{countdown} 秒以内に承諾してください。}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{接続するには、{device} に表示されている PIN を {countdown} 秒以内に入力してください。}other{接続するには、{device} に表示されている PIN を {countdown} 秒以内に入力してください。}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{{device} が次の PIN を使用してデバイスへの接続をリクエストしています。{countdown} 秒以内に承諾してください。}other{{device} が次の PIN を使用してデバイスへの接続をリクエストしています。{countdown} 秒以内に承諾してください。}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"接続"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"キャンセル"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"PIN"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"PIN"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"デバイスが <xliff:g id="DEVICE_NAME">%1$s</xliff:g> に接続されている間は一時的に Wi-Fi 接続が解除されます"</string>
<string name="dlg_ok" msgid="254496739491689405">"OK"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"<xliff:g id="SSID">%1$s</xliff:g> に接続できません"</string>
diff --git a/service/ServiceWifiResources/res/values-ka/strings.xml b/service/ServiceWifiResources/res/values-ka/strings.xml
index 0ae523b..8cc59fd 100644
--- a/service/ServiceWifiResources/res/values-ka/strings.xml
+++ b/service/ServiceWifiResources/res/values-ka/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"მიმღები:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"შეიყვანეთ საჭირო PIN:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"პინ-კოდი:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"მოწყობილობის დაკავშირება"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"მოწყობილობის დაკავშირება"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>-ს გაეგზავნა მოსაწვევი."</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"დასაკავშირებლად შეიყვანეთ PIN-კოდი <xliff:g id="DEVICE_NAME">%1$s</xliff:g>-ზე."</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"კარგი"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"მოწყობილობის დაკავშირება"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"მოწყობილობის დაკავშირება"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"მოწყობილობის დაკავშირება"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>-ს სურს თქვენს მოწყობილობასთან დაკავშირება."</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"დასაკავშირებლად შეიყვანეთ <xliff:g id="DEVICE_NAME">%1$s</xliff:g>-ზე ნაჩვენები PIN-კოდი."</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>-ს სურს თქვენს მოწყობილობასთან დაკავშირება შემდეგი PIN-კოდით."</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{{device}-ს სურს თქვენს მოწყობილობასთან დაკავშირება. {countdown} წამში დათანხმება.}other{{device}-ს სურს თქვენს მოწყობილობასთან დაკავშირება. {countdown} წამში დათანხმება.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{დასაკავშირებლად შეიყვანეთ {device}-ზე {countdown} წამში ნაჩვენები PIN-კოდი.}other{დასაკავშირებლად შეიყვანეთ {device}-ზე {countdown} წამში ნაჩვენები PIN-კოდი.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{{device}-ს სურს თქვენს მოწყობილობასთან დაკავშირება შემდეგი PIN-კოდით. {countdown} წამში დათანხმება.}other{{device}-ს სურს თქვენს მოწყობილობასთან დაკავშირება შემდეგი PIN-კოდით. {countdown} წამში დათანხმება.}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"დაკავშირება"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"გაუქმება"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"PIN-კოდი"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"PIN-კოდი"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"თქვენი მოწყობილობა დროებით გაითიშება Wi-Fi-დან, სანამ ის <xliff:g id="DEVICE_NAME">%1$s</xliff:g>-თან იქნება დაკავშირებული"</string>
<string name="dlg_ok" msgid="254496739491689405">"OK"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"<xliff:g id="SSID">%1$s</xliff:g>-თან დაკავშირება ვერ ხერხდება"</string>
diff --git a/service/ServiceWifiResources/res/values-kk/strings.xml b/service/ServiceWifiResources/res/values-kk/strings.xml
index 33fcbeb..53c2950 100644
--- a/service/ServiceWifiResources/res/values-kk/strings.xml
+++ b/service/ServiceWifiResources/res/values-kk/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"Кімге:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"Өтінілген PIN кодты теру:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"PIN:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"Құрылғыны қосу"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"Құрылғыны қосу"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> құрылғысына шақыру жіберілді."</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"Қосылу үшін осы PIN кодын <xliff:g id="DEVICE_NAME">%1$s</xliff:g> құрылғысына енгізіңіз."</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"Жарайды"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"Құрылғыны қосу"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"Құрылғыны қосу"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"Құрылғыны қосу"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> сіздің құрылғыңызға қосылғысы келеді."</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"Қосылу үшін <xliff:g id="DEVICE_NAME">%1$s</xliff:g> құрылғысында көрсетілген PIN кодын енгізіңіз."</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> келесі PIN коды арқылы сіздің құрылғыңызға қосылғысы келеді."</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{{device} сіздің құрылғыңызға қосылғысы келеді. Қабылдауға {countdown} секунд қалды.}other{{device} сіздің құрылғыңызға қосылғысы келеді. Қабылдауға {countdown} секунд қалды.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{Қосылу үшін {countdown} секунд ішінде {device} құрылғысында көрсетілген PIN кодын енгізіңіз.}other{Қосылу үшін {countdown} секунд ішінде {device} құрылғысында көрсетілген PIN кодын енгізіңіз.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{{device} келесі PIN коды арқылы сіздің құрылғыңызға қосылғысы келеді. Қабылдауға {countdown} секунд қалды.}other{{device} келесі PIN коды арқылы сіздің құрылғыңызға қосылғысы келеді. Қабылдауға {countdown} секунд қалды.}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"Қосылу"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"Бас тарту"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"PIN коды"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"PIN коды"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> құрылғысына қосулы тұрғанда, құрылғыңыз Wi-Fi желісінен уақытша ажырайды."</string>
<string name="dlg_ok" msgid="254496739491689405">"Жарайды"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"<xliff:g id="SSID">%1$s</xliff:g> құрылғысына қосылмайды."</string>
diff --git a/service/ServiceWifiResources/res/values-km/strings.xml b/service/ServiceWifiResources/res/values-km/strings.xml
index 6a63936..9a33bbd 100644
--- a/service/ServiceWifiResources/res/values-km/strings.xml
+++ b/service/ServiceWifiResources/res/values-km/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"ទៅ៖"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"បញ្ចូលកូដ PIN ដែលទាមទារ៖"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"កូដ PIN ៖"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"ការតភ្ជាប់ឧបករណ៍"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"ការតភ្ជាប់ឧបករណ៍"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"បានផ្ញើការអញ្ជើញទៅ <xliff:g id="DEVICE_NAME">%1$s</xliff:g>។"</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"បញ្ចូលកូដ PIN នេះនៅលើ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ដើម្បីភ្ជាប់។"</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"យល់ព្រម"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"ការតភ្ជាប់ឧបករណ៍"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"ការតភ្ជាប់ឧបករណ៍"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"ការតភ្ជាប់ឧបករណ៍"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> ចង់ភ្ជាប់ទៅឧបករណ៍របស់អ្នក។"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"បញ្ចូលកូដ PIN ដែលបង្ហាញនៅលើ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ដើម្បីភ្ជាប់។"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> ចង់ភ្ជាប់ទៅឧបករណ៍របស់អ្នកដោយប្រើកូដ PIN ខាងក្រោម។"</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{{device} ចង់ភ្ជាប់ទៅឧបករណ៍របស់អ្នក។ ទទួលយកក្នុងរយៈពេល {countdown} វិនាទី។}other{{device} ចង់ភ្ជាប់ទៅឧបករណ៍របស់អ្នក។ ទទួលយកក្នុងរយៈពេល {countdown} វិនាទី។}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{បញ្ចូលកូដ PIN ដែលបង្ហាញនៅលើ {device} ក្នុងរយៈពេល{countdown} វិនាទី ដើម្បីភ្ជាប់។}other{បញ្ចូលកូដ PIN ដែលបង្ហាញនៅលើ {device} ក្នុងរយៈពេល{countdown} វិនាទី ដើម្បីភ្ជាប់។}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{{device} ចង់ភ្ជាប់ទៅឧបករណ៍របស់អ្នកដោយប្រើកូដ PIN ខាងក្រោម។ ទទួលយកក្នុងរយៈពេល {countdown} វិនាទី។}other{{device} ចង់ភ្ជាប់ទៅឧបករណ៍របស់អ្នកដោយប្រើកូដ PIN ខាងក្រោម។ ទទួលយកក្នុងរយៈពេល {countdown} វិនាទី។}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"ភ្ជាប់"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"បោះបង់"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"កូដ PIN"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"កូដ PIN"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"ឧបករណ៍របស់អ្នកនឹងផ្ដាច់ពី Wi-Fi ជាបណ្ដោះអាសន្ន នៅពេលឧបករណ៍នេះភ្ជាប់ជាមួយ <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="dlg_ok" msgid="254496739491689405">"យល់ព្រម"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"មិនអាចភ្ជាប់ជាមួយ <xliff:g id="SSID">%1$s</xliff:g> បានទេ"</string>
diff --git a/service/ServiceWifiResources/res/values-kn/strings.xml b/service/ServiceWifiResources/res/values-kn/strings.xml
index 5bc762e..5ced65b 100644
--- a/service/ServiceWifiResources/res/values-kn/strings.xml
+++ b/service/ServiceWifiResources/res/values-kn/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"ಗೆ:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"ಅಗತ್ಯವಿರುವ ಪಿನ್ ಟೈಪ್ ಮಾಡಿ:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"ಪಿನ್:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"ಸಾಧನದ ಕನೆಕ್ಷನ್"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"ಸಾಧನದ ಕನೆಕ್ಷನ್"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> ಗೆ ಆಹ್ವಾನವನ್ನು ಕಳುಹಿಸಲಾಗಿದೆ."</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"ಸಂಪರ್ಕಿಸಲು <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ನಲ್ಲಿ ಈ ಪಿನ್ ಅನ್ನು ನಮೂದಿಸಿ."</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"ಸರಿ"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"ಸಾಧನದ ಕನೆಕ್ಷನ್"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"ಸಾಧನದ ಕನೆಕ್ಷನ್"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"ಸಾಧನದ ಕನೆಕ್ಷನ್"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> ನಿಮ್ಮ ಸಾಧನಕ್ಕೆ ಕನೆಕ್ಟ್ ಆಗಲು ಬಯಸುತ್ತದೆ."</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"ಕನೆಕ್ಟ್ ಮಾಡಲು <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ಸಾಧನದಲ್ಲಿ ನಿರ್ಮಿಸಲಾದ ಪಿನ್ ಅನ್ನು ನಮೂದಿಸಿ."</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"ಈ ಕೆಳಗಿನ ಪಿನ್ನೊಂದಿಗೆ ನಿಮ್ಮ ಸಾಧನಕ್ಕೆ ಕನೆಕ್ಟ್ ಆಗಲು <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ಬಯಸುತ್ತದೆ."</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{{device} ನಿಮ್ಮ ಸಾಧನಕ್ಕೆ ಕನೆಕ್ಟ್ ಆಗಲು ಬಯಸುತ್ತದೆ. {countdown} ಸೆಕೆಂಡ್ನಲ್ಲಿ ಸ್ವೀಕರಿಸಿ.}one{{device} ನಿಮ್ಮ ಸಾಧನಕ್ಕೆ ಕನೆಕ್ಟ್ ಆಗಲು ಬಯಸುತ್ತದೆ. {countdown} ಸೆಕೆಂಡ್ಗಳಲ್ಲಿ ಸ್ವೀಕರಿಸಿ.}other{{device} ನಿಮ್ಮ ಸಾಧನಕ್ಕೆ ಕನೆಕ್ಟ್ ಆಗಲು ಬಯಸುತ್ತದೆ. {countdown} ಸೆಕೆಂಡ್ಗಳಲ್ಲಿ ಸ್ವೀಕರಿಸಿ.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{ಕನೆಕ್ಟ್ ಮಾಡಲು {countdown} ಸೆಕೆಂಡ್ನಲ್ಲಿ {device} ನಲ್ಲಿ ತೋರಿಸಿರುವ ಪಿನ್ ಅನ್ನು ನಮೂದಿಸಿ.}one{ಕನೆಕ್ಟ್ ಮಾಡಲು {countdown} ಸೆಕೆಂಡ್ಗಳಲ್ಲಿ {device} ನಲ್ಲಿ ತೋರಿಸಿರುವ ಪಿನ್ ಅನ್ನು ನಮೂದಿಸಿ.}other{ಕನೆಕ್ಟ್ ಮಾಡಲು {countdown} ಸೆಕೆಂಡ್ಗಳಲ್ಲಿ {device} ನಲ್ಲಿ ತೋರಿಸಿರುವ ಪಿನ್ ಅನ್ನು ನಮೂದಿಸಿ.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{ಈ ಕೆಳಗಿನ ಪಿನ್ನೊಂದಿಗೆ ನಿಮ್ಮ ಸಾಧನಕ್ಕೆ ಕನೆಕ್ಟ್ ಆಗಲು {device} ಬಯಸುತ್ತದೆ. {countdown} ಸೆಕೆಂಡ್ನಲ್ಲಿ ಸ್ವೀಕರಿಸಿ.}one{ಈ ಕೆಳಗಿನ ಪಿನ್ನೊಂದಿಗೆ ನಿಮ್ಮ ಸಾಧನಕ್ಕೆ ಕನೆಕ್ಟ್ ಆಗಲು {device} ಬಯಸುತ್ತದೆ. {countdown} ಸೆಕೆಂಡ್ಗಳಲ್ಲಿ ಸ್ವೀಕರಿಸಿ.}other{ಈ ಕೆಳಗಿನ ಪಿನ್ನೊಂದಿಗೆ ನಿಮ್ಮ ಸಾಧನಕ್ಕೆ ಕನೆಕ್ಟ್ ಆಗಲು {device} ಬಯಸುತ್ತದೆ. {countdown} ಸೆಕೆಂಡ್ಗಳಲ್ಲಿ ಸ್ವೀಕರಿಸಿ.}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"ಕನೆಕ್ಟ್ ಮಾಡಿ"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"ರದ್ದುಮಾಡಿ"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"ಪಿನ್"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"ಪಿನ್"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"ನಿಮ್ಮ ಸಾಧನವು <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ಗೆ ಕನೆಕ್ಟ್ ಆಗಿರುವಾಗ, ವೈ-ಫೈನಿಂದ ಅದು ತಾತ್ಕಾಲಿಕವಾಗಿ ಡಿಸ್ಕನೆಕ್ಟ್ ಆಗುತ್ತದೆ"</string>
<string name="dlg_ok" msgid="254496739491689405">"ಸರಿ"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"<xliff:g id="SSID">%1$s</xliff:g> ಗೆ ಕನೆಕ್ಟ್ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
diff --git a/service/ServiceWifiResources/res/values-ko/strings.xml b/service/ServiceWifiResources/res/values-ko/strings.xml
index e77fb11..9dc1307 100644
--- a/service/ServiceWifiResources/res/values-ko/strings.xml
+++ b/service/ServiceWifiResources/res/values-ko/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"수신:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"필수 PIN 입력:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"PIN:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"기기 연결"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"기기 연결"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>에 초대를 보냈습니다."</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"연결하려면 <xliff:g id="DEVICE_NAME">%1$s</xliff:g>에 이 PIN을 입력하세요."</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"확인"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"기기 연결"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"기기 연결"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"기기 연결"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>에서 내 기기에 연결하려고 합니다."</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"연결하려면 <xliff:g id="DEVICE_NAME">%1$s</xliff:g>에 표시된 PIN을 입력하세요."</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>에서 다음 PIN을 사용하여 내 기기에 연결하려고 합니다."</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{{device}에서 내 기기에 연결하려고 합니다. {countdown}초 이내에 수락하세요.}other{{device}에서 내 기기에 연결하려고 합니다. {countdown}초 이내에 수락하세요.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{연결하려면 {countdown}초 이내에 {device}에 표시된 PIN을 입력하세요.}other{연결하려면 {countdown}초 이내에 {device}에 표시된 PIN을 입력하세요.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{{device}에서 다음 PIN을 사용하여 내 기기에 연결하려고 합니다. {countdown}초 이내에 수락하세요.}other{{device}에서 다음 PIN을 사용하여 내 기기에 연결하려고 합니다. {countdown}초 이내에 수락하세요.}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"연결"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"취소"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"PIN"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"PIN"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>에 연결되어 있는 동안 기기의 Wi-Fi 연결이 일시적으로 해제됩니다"</string>
<string name="dlg_ok" msgid="254496739491689405">"확인"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"<xliff:g id="SSID">%1$s</xliff:g>에 연결할 수 없습니다."</string>
diff --git a/service/ServiceWifiResources/res/values-ky/strings.xml b/service/ServiceWifiResources/res/values-ky/strings.xml
index e8c22b7..59b886c 100644
--- a/service/ServiceWifiResources/res/values-ky/strings.xml
+++ b/service/ServiceWifiResources/res/values-ky/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"Алуучу:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"Талап кылынган PIN\'ди териңиз:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"PIN:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"Түзмөктү туташтыруу"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"Түзмөктү туташтыруу"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"Чакыруу <xliff:g id="DEVICE_NAME">%1$s</xliff:g> түзмөгүнө жөнөтүлдү."</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"Туташтыруу үчүн ушул PIN кодду <xliff:g id="DEVICE_NAME">%1$s</xliff:g> түзмөгүнө киргизиңиз."</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"Жарайт"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"Түзмөктү туташтыруу"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"Түзмөктү туташтыруу"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"Түзмөктү туташтыруу"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> түзмөгүңүзгө туташканы жатат."</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"Туташтыруу үчүн <xliff:g id="DEVICE_NAME">%1$s</xliff:g> түзмөгүндө көрсөтүлгөн PIN кодду киргизиңиз."</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> түзмөгүңүзгө төмөнкү PIN код менен туташканы жатат."</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{{device} түзмөгүңүзгө туташканы жатат. {countdown} секундда кабыл алыңыз.}other{{device} түзмөгүңүзгө туташканы жатат. {countdown} секундда кабыл алыңыз.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{Туташтыруу үчүн {device} түзмөгүндө көрсөтүлгөн PIN кодду {countdown} секунддун ичинде киргизиңиз.}other{Туташтыруу үчүн {device} түзмөгүндө көрсөтүлгөн PIN кодду {countdown} секунддун ичинде киргизиңиз.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{{device} түзмөгүңүзгө төмөнкү PIN код менен туташканы жатат. {countdown} секундда кабыл алыңыз.}other{{device} түзмөгүңүзгө төмөнкү PIN код менен туташканы жатат. {countdown} секундда кабыл алыңыз.}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"Туташтыруу"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"Жокко чыгаруу"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"PIN код"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"PIN код"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"Түзмөгүңүз <xliff:g id="DEVICE_NAME">%1$s</xliff:g> түзмөгүнө туташып турганда убактылуу Wi-Fi\'дан ажыратылат"</string>
<string name="dlg_ok" msgid="254496739491689405">"Жарайт"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"<xliff:g id="SSID">%1$s</xliff:g> менен туташпай жатат"</string>
diff --git a/service/ServiceWifiResources/res/values-lo/strings.xml b/service/ServiceWifiResources/res/values-lo/strings.xml
index 4d99e10..3bcd489 100644
--- a/service/ServiceWifiResources/res/values-lo/strings.xml
+++ b/service/ServiceWifiResources/res/values-lo/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"ຈາກ:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"ພິມລະຫັດ PIN:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"PIN:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"ການເຊື່ອມຕໍ່ອຸປະກອນ"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"ການເຊື່ອມຕໍ່ອຸປະກອນ"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"ສົ່ງຄຳເຊີນໄປຫາ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ແລ້ວ."</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"ໃສ່ PIN ນີ້ຢູ່ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ເພື່ອເຊື່ອມຕໍ່."</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"ຕົກລົງ"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"ການເຊື່ອມຕໍ່ອຸປະກອນ"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"ການເຊື່ອມຕໍ່ອຸປະກອນ"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"ການເຊື່ອມຕໍ່ອຸປະກອນ"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> ຕ້ອງການເຊື່ອມຕໍ່ກັບອຸປະກອນຂອງທ່ານ."</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"ໃສ່ PIN ທີ່ສະແດງຢູ່ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ເພື່ອເຊື່ອມຕໍ່."</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> ຕ້ອງການເຊື່ອມຕໍ່ກັບອຸປະກອນຂອງທ່ານດ້ວຍ PIN ຕໍ່ໄປນີ້."</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{{device} ຕ້ອງການເຊື່ອມຕໍ່ກັບອຸປະກອນຂອງທ່ານ. ຕອບຮັບພາຍໃນ {countdown} ວິນາທີ.}other{{device} ຕ້ອງການເຊື່ອມຕໍ່ກັບອຸປະກອນຂອງທ່ານ. ຕອບຮັບພາຍໃນ {countdown} ວິນາທີ.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{ໃສ່ PIN ທີ່ສະແດງຢູ່ {device} ພາຍໃນ {countdown} ວິນາທີເພື່ອເຊື່ອມຕໍ່.}other{ໃສ່ PIN ທີ່ສະແດງຢູ່ {device} ພາຍໃນ {countdown} ວິນາທີເພື່ອເຊື່ອມຕໍ່.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{{device} ຕ້ອງການເຊື່ອມຕໍ່ກັບອຸປະກອນຂອງທ່ານດ້ວຍ PIN ຕໍ່ໄປນີ້. ຕອບຮັບພາຍໃນ {countdown} ວິນາທີ.}other{{device} ຕ້ອງການເຊື່ອມຕໍ່ກັບອຸປະກອນຂອງທ່ານດ້ວຍ PIN ຕໍ່ໄປນີ້. ຕອບຮັບພາຍໃນ {countdown} ວິນາທີ.}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"ເຊື່ອມຕໍ່"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"ຍົກເລີກ"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"PIN"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"PIN"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"ອຸປະກອນຂອງທ່ານຈະຕັດການເຊື່ອມຕໍ່ຈາກ Wi-Fi ເປັນການຊົ່ວຄາວໃນລະຫວ່າງທີ່ມັນເຊື່ອມຕໍ່ຫາ <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="dlg_ok" msgid="254496739491689405">"ຕົກລົງ"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"ບໍ່ສາມາດເຊື່ອມຕໍ່ຫາ <xliff:g id="SSID">%1$s</xliff:g> ໄດ້"</string>
diff --git a/service/ServiceWifiResources/res/values-lt/strings.xml b/service/ServiceWifiResources/res/values-lt/strings.xml
index e496179..5efb010 100644
--- a/service/ServiceWifiResources/res/values-lt/strings.xml
+++ b/service/ServiceWifiResources/res/values-lt/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"Skirta:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"Įveskite reikiamą PIN kodą:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"PIN kodas:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"Įrenginio ryšys"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"Įrenginio ryšys"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"Kvietimas išsiųstas į <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"Įveskite šį PIN kodą <xliff:g id="DEVICE_NAME">%1$s</xliff:g>, kad prisijungtumėte."</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"Gerai"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"Įrenginio ryšys"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"Įrenginio ryšys"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"Įrenginio ryšys"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> nori prisijungti prie jūsų įrenginio."</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"Įveskite <xliff:g id="DEVICE_NAME">%1$s</xliff:g> rodomą PIN kodą, kad prisijungtumėte."</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> nori prisijungti prie jūsų įrenginio naudojant toliau nurodytą PIN kodą."</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{{device} nori prisijungti prie jūsų įrenginio. Priimkite per {countdown} sekundę.}one{{device} nori prisijungti prie jūsų įrenginio. Priimkite per {countdown} sekundę.}few{{device} nori prisijungti prie jūsų įrenginio. Priimkite per {countdown} sekundes.}many{{device} nori prisijungti prie jūsų įrenginio. Priimkite per {countdown} sekundės.}other{{device} nori prisijungti prie jūsų įrenginio. Priimkite per {countdown} sekundžių.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{Įveskite {device} rodomą PIN kodą per {countdown} sekundę, kad prisijungtumėte.}one{Įveskite {device} rodomą PIN kodą per {countdown} sekundę, kad prisijungtumėte.}few{Įveskite {device} rodomą PIN kodą per {countdown} sekundes, kad prisijungtumėte.}many{Įveskite {device} rodomą PIN kodą per {countdown} sekundės, kad prisijungtumėte.}other{Įveskite {device} rodomą PIN kodą per {countdown} sekundžių, kad prisijungtumėte.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{{device} nori prisijungti prie jūsų įrenginio naudojant toliau nurodytą PIN kodą. Priimkite per {countdown} sekundę.}one{{device} nori prisijungti prie jūsų įrenginio naudojant toliau nurodytą PIN kodą. Priimkite per {countdown} sekundę.}few{{device} nori prisijungti prie jūsų įrenginio naudojant toliau nurodytą PIN kodą. Priimkite per {countdown} sekundes.}many{{device} nori prisijungti prie jūsų įrenginio naudojant toliau nurodytą PIN kodą. Priimkite per {countdown} sekundės.}other{{device} nori prisijungti prie jūsų įrenginio naudojant toliau nurodytą PIN kodą. Priimkite per {countdown} sekundžių.}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"Prisijungti"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"Atšaukti"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"PIN kodas"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"PIN kodas"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"Įrenginys bus laikinai atjungtas nuo „Wi-Fi“, kol bus prijungtas prie „<xliff:g id="DEVICE_NAME">%1$s</xliff:g>“"</string>
<string name="dlg_ok" msgid="254496739491689405">"Gerai"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"Nepavyksta prisijungti prie „<xliff:g id="SSID">%1$s</xliff:g>“"</string>
diff --git a/service/ServiceWifiResources/res/values-lv/strings.xml b/service/ServiceWifiResources/res/values-lv/strings.xml
index 6523fd3..360569f 100644
--- a/service/ServiceWifiResources/res/values-lv/strings.xml
+++ b/service/ServiceWifiResources/res/values-lv/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"Kam:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"Ierakstiet pieprasīto PIN:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"PIN:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"Ierīču saistīšana"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"Ierīču saistīšana"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"Uzaicinājums nosūtīts ierīcei <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"Lai izveidotu savienojumu, ievadiet šo PIN kodu ierīcē <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"Labi"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"Ierīču saistīšana"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"Ierīču saistīšana"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"Ierīču saistīšana"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> vēlas izveidot savienojumu ar jūsu ierīci."</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"Lai izveidotu savienojumu, ievadiet PIN kodu, kas redzams ierīcē <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> vēlas izveidot savienojumu ar jūsu ierīci, izmantojot tālāk norādīto PIN kodu."</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{{device} vēlas izveidot savienojumu ar jūsu ierīci. Atlikusi {countdown} sekunde, lai pieņemtu.}zero{{device} vēlas izveidot savienojumu ar jūsu ierīci. Atlikušas {countdown} sekundes, lai pieņemtu.}one{{device} vēlas izveidot savienojumu ar jūsu ierīci. Atlikusi {countdown} sekunde, lai pieņemtu.}other{{device} vēlas izveidot savienojumu ar jūsu ierīci. Atlikušas {countdown} sekundes, lai pieņemtu.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{Lai izveidotu savienojumu, {countdown} sekundes laikā ievadiet ierīcē {device} parādīto PIN kodu.}zero{Lai izveidotu savienojumu, {countdown} sekunžu laikā ievadiet ierīcē {device} parādīto PIN kodu.}one{Lai izveidotu savienojumu, {countdown} sekundes laikā ievadiet ierīcē {device} parādīto PIN kodu.}other{Lai izveidotu savienojumu, {countdown} sekunžu laikā ievadiet ierīcē {device} parādīto PIN kodu.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{{device} vēlas izveidot savienojumu ar jūsu ierīci, izmantojot tālāk norādīto PIN kodu. Atlikusi {countdown} sekunde, lai pieņemtu.}zero{{device} vēlas izveidot savienojumu ar jūsu ierīci, izmantojot tālāk norādīto PIN kodu. Atlikušas {countdown} sekundes, lai pieņemtu.}one{{device} vēlas izveidot savienojumu ar jūsu ierīci, izmantojot tālāk norādīto PIN kodu. Atlikusi {countdown} sekunde, lai pieņemtu.}other{{device} vēlas izveidot savienojumu ar jūsu ierīci, izmantojot tālāk norādīto PIN kodu. Atlikušas {countdown} sekundes, lai pieņemtu.}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"Izveidot savienojumu"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"Atcelt"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"PIN kods"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"PIN kods"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"Jūsu ierīce tiks īslaicīgi atvienota no Wi-Fi tīkla, kamēr ir izveidots savienojums ar ierīci <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
<string name="dlg_ok" msgid="254496739491689405">"Labi"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"Nevar izveidot savienojumu ar: <xliff:g id="SSID">%1$s</xliff:g>"</string>
diff --git a/service/ServiceWifiResources/res/values-mk/strings.xml b/service/ServiceWifiResources/res/values-mk/strings.xml
index f8db829..98a8689 100644
--- a/service/ServiceWifiResources/res/values-mk/strings.xml
+++ b/service/ServiceWifiResources/res/values-mk/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"До:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"Внеси го бараниот PIN:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"PIN:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"Врска со уред"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"Врска со уред"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"Испратена е покана до <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"Внесете го PIN-кодов на <xliff:g id="DEVICE_NAME">%1$s</xliff:g> за да се поврзете."</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"Во ред"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"Врска со уред"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"Врска со уред"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"Врска со уред"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> сака да се поврзе со вашиот уред."</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"Внесете го PIN-кодот прикажан на <xliff:g id="DEVICE_NAME">%1$s</xliff:g> за да се поврзете."</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> сака да се поврзе со вашиот уред со следниов PIN-код."</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{{device} сака да се поврзе со вашиот уред. Прифатете за {countdown} секунда.}one{{device} сака да се поврзе со вашиот уред. Прифатете за {countdown} секунда.}other{{device} сака да се поврзе со вашиот уред. Прифатете за {countdown} секунди.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{Внесете го PIN-кодот на {device} во рок од {countdown} секунда за да се поврзете.}one{Внесете го PIN-кодот на {device} во рок од {countdown} секунда за да се поврзете.}other{Внесете го PIN-кодот на {device} во рок од {countdown} секунди за да се поврзете.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{{device} сака да се поврзе со вашиот уред со следниов PIN-код. Прифатете за {countdown} секунда.}one{{device} сака да се поврзе со вашиот уред со следниов PIN-код. Прифатете за {countdown} секунда.}other{{device} сака да се поврзе со вашиот уред со следниов PIN-код. Прифатете за {countdown} секунди.}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"Поврзи"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"Откажи"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"PIN"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"PIN"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"Ќе се прекине врската на вашиот уред со Wi-Fi привремено додека е поврзан со <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="dlg_ok" msgid="254496739491689405">"Во ред"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"Не може да се поврзе на „<xliff:g id="SSID">%1$s</xliff:g>“"</string>
diff --git a/service/ServiceWifiResources/res/values-ml/strings.xml b/service/ServiceWifiResources/res/values-ml/strings.xml
index 18f1ada..1455f32 100644
--- a/service/ServiceWifiResources/res/values-ml/strings.xml
+++ b/service/ServiceWifiResources/res/values-ml/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"ടു:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"ആവശ്യമായ പിൻ ടൈപ്പുചെയ്യുക:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"പിൻ:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"ഉപകരണ കണക്ഷൻ"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"ഉപകരണ കണക്ഷൻ"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> എന്നതിലേക്ക് ക്ഷണം അയച്ചു."</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"കണക്റ്റ് ചെയ്യാൻ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> എന്നതിൽ ഈ പിൻ നൽകുക."</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"ശരി"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"ഉപകരണ കണക്ഷൻ"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"ഉപകരണ കണക്ഷൻ"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"ഉപകരണ കണക്ഷൻ"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> നിങ്ങളുടെ ഉപകരണത്തിലേക്ക് കണക്റ്റ് ചെയ്യാൻ ആഗ്രഹിക്കുന്നു."</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"കണക്റ്റ് ചെയ്യാൻ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> എന്നതിൽ കാണിക്കുന്ന പിൻ നൽകുക."</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> ഇനിപ്പറയുന്ന പിൻ ഉപയോഗിച്ച് നിങ്ങളുടെ ഉപകരണത്തിലേക്ക് കണക്റ്റ് ചെയ്യാൻ ആഗ്രഹിക്കുന്നു."</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{{device} നിങ്ങളുടെ ഉപകരണത്തിലേക്ക് കണക്റ്റ് ചെയ്യാൻ ആഗ്രഹിക്കുന്നു. {countdown} സെക്കൻഡിൽ അംഗീകരിക്കുക.}other{{device} നിങ്ങളുടെ ഉപകരണത്തിലേക്ക് കണക്റ്റ് ചെയ്യാൻ ആഗ്രഹിക്കുന്നു. {countdown} സെക്കൻഡിൽ അംഗീകരിക്കുക.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{കണക്റ്റ് ചെയ്യാൻ {countdown} സെക്കൻഡിനുള്ളിൽ {device} എന്നതിൽ കാണിക്കുന്ന പിൻ നൽകുക.}other{കണക്റ്റ് ചെയ്യാൻ {countdown} സെക്കൻഡിനുള്ളിൽ {device} എന്നതിൽ കാണിക്കുന്ന പിൻ നൽകുക.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{{device} ഇനിപ്പറയുന്ന പിൻ ഉപയോഗിച്ച് നിങ്ങളുടെ ഉപകരണത്തിലേക്ക് കണക്റ്റ് ചെയ്യാൻ ആഗ്രഹിക്കുന്നു. {countdown} സെക്കൻഡിൽ അംഗീകരിക്കുക.}other{{device} ഇനിപ്പറയുന്ന പിൻ ഉപയോഗിച്ച് നിങ്ങളുടെ ഉപകരണത്തിലേക്ക് കണക്റ്റ് ചെയ്യാൻ ആഗ്രഹിക്കുന്നു. {countdown} സെക്കൻഡിൽ അംഗീകരിക്കുക.}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"കണക്റ്റ് ചെയ്യുക"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"റദ്ദാക്കുക"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"പിൻ"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"പിൻ"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"നിങ്ങളുടെ ഉപകരണം <xliff:g id="DEVICE_NAME">%1$s</xliff:g> എന്നതുമായി കണക്റ്റ് ചെയ്തിരിക്കുമ്പോൾ, അത് വൈഫൈയിൽ നിന്ന് താൽക്കാലികമായി വിച്ഛേദിക്കും"</string>
<string name="dlg_ok" msgid="254496739491689405">"ശരി"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"<xliff:g id="SSID">%1$s</xliff:g>-ലേക്ക് കണക്റ്റ് ചെയ്യാനാവുന്നില്ല"</string>
diff --git a/service/ServiceWifiResources/res/values-mn/strings.xml b/service/ServiceWifiResources/res/values-mn/strings.xml
index 293e732..d036fa8 100644
--- a/service/ServiceWifiResources/res/values-mn/strings.xml
+++ b/service/ServiceWifiResources/res/values-mn/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"Хэнд:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"Шаардлагатай ПИН-г бичнэ үү:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"ПИН:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"Төхөөрөмжийн холболт"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"Төхөөрөмжийн холболт"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> руу урилга илгээсэн."</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"Холбогдохын тулд энэ ПИН-г <xliff:g id="DEVICE_NAME">%1$s</xliff:g> дээр оруулна уу."</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"OK"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"Төхөөрөмжийн холболт"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"Төхөөрөмжийн холболт"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"Төхөөрөмжийн холболт"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> таны төхөөрөмжид холбогдохыг хүсэж байна."</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"Холбогдохын тулд <xliff:g id="DEVICE_NAME">%1$s</xliff:g> дээр харуулсан ПИН-г оруулна уу."</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> дараах ПИН-ээр таны төхөөрөмжтэй холбогдохыг хүсэж байна."</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{{device} таны төхөөрөмжид холбогдохыг хүсэж байна. {countdown} секундийн дотор зөвшөөрнө үү.}other{{device} таны төхөөрөмжид холбогдохыг хүсэж байна. {countdown} секундийн дотор зөвшөөрнө үү.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{Холбогдохын тулд {countdown} секундийн дотор {device} дээр харуулсан ПИН-г оруулна уу.}other{Холбогдохын тулд {countdown} секундийн дотор {device} дээр харуулсан ПИН-г оруулна уу.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{{device} дараах ПИН-ээр таны төхөөрөмжтэй холбогдохыг хүсэж байна. {countdown} секундийн дотор зөвшөөрнө үү.}other{{device} дараах ПИН-ээр таны төхөөрөмжтэй холбогдохыг хүсэж байна. {countdown} секундийн дотор зөвшөөрнө үү.}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"Холбогдох"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"Цуцлах"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"ПИН"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"ПИН"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"Таны төхөөрөмж <xliff:g id="DEVICE_NAME">%1$s</xliff:g>-д холбогдсон үедээ Wi-Fi-с түр сална"</string>
<string name="dlg_ok" msgid="254496739491689405">"OK"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"<xliff:g id="SSID">%1$s</xliff:g>-д холбогдож чадсангүй"</string>
diff --git a/service/ServiceWifiResources/res/values-mr/strings.xml b/service/ServiceWifiResources/res/values-mr/strings.xml
index 5cdd82f..ec418c2 100644
--- a/service/ServiceWifiResources/res/values-mr/strings.xml
+++ b/service/ServiceWifiResources/res/values-mr/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"प्रति:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"आवश्यक पिन टाइप करा:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"पिन:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"डिव्हाइस कनेक्शन"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"डिव्हाइस कनेक्शन"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> यांना आमंत्रण पाठवले आहे."</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"कनेक्ट करण्यासाठी <xliff:g id="DEVICE_NAME">%1$s</xliff:g> वर हा पिन एंटर करा."</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"ओके"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"डिव्हाइस कनेक्शन"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"डिव्हाइस कनेक्शन"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"डिव्हाइस कनेक्शन"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> ला तुमच्या डिव्हाइसशी कनेक्ट करायचे आहे."</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"कनेक्ट करण्यासाठी <xliff:g id="DEVICE_NAME">%1$s</xliff:g> वर दाखवलेला पिन एंटर करा."</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> ला पुढील पिन वापरून तुमच्या डिव्हाइसशी कनेक्ट करायचे आहे."</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{{device} ला तुमच्या डिव्हाइसशी कनेक्ट करायचे आहे. {countdown} सेकंदामध्ये स्वीकारा.}other{{device} ला तुमच्या डिव्हाइसशी कनेक्ट करायचे आहे. {countdown} सेकंदांमध्ये स्वीकारा.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{कनेक्ट करण्यासाठी, {countdown} सेकंदाच्या आत {device} वर दाखवलेला पिन एंटर करा.}other{कनेक्ट करण्यासाठी, {countdown} सेकंदांच्या आत {device} वर दाखवलेला पिन एंटर करा.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{{device} ला पुढील पिन वापरून तुमच्या डिव्हाइसशी कनेक्ट करायचे आहे. {countdown} सेकंदामध्ये स्वीकारा.}other{{device} ला पुढील पिन वापरून तुमच्या डिव्हाइसशी कनेक्ट करायचे आहे. {countdown} सेकंदांमध्ये स्वीकारा.}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"कनेक्ट करा"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"रद्द करा"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"पिन"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"पिन"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"तुमचे डिव्हाइस <xliff:g id="DEVICE_NAME">%1$s</xliff:g> शी कनेक्ट केलेले असताना वाय-फायवरून तात्पुरते डिस्कनेक्ट होईल"</string>
<string name="dlg_ok" msgid="254496739491689405">"ठीक"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"<xliff:g id="SSID">%1$s</xliff:g> शी कनेक्ट करता आले नाही"</string>
diff --git a/service/ServiceWifiResources/res/values-ms/strings.xml b/service/ServiceWifiResources/res/values-ms/strings.xml
index 66e5b8b..c4e459d 100644
--- a/service/ServiceWifiResources/res/values-ms/strings.xml
+++ b/service/ServiceWifiResources/res/values-ms/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"Kepada:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"Taipkan PIN yang diperlukan:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"PIN:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"Sambungan peranti"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"Sambungan peranti"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"Undangan dihantar kepada <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"Masukkan PIN ini pada <xliff:g id="DEVICE_NAME">%1$s</xliff:g> untuk membuat sambungan."</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"OK"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"Sambungan peranti"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"Sambungan peranti"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"Sambungan peranti"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> mahu menyambung kepada peranti anda."</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"Masukkan PIN yang dipaparkan pada <xliff:g id="DEVICE_NAME">%1$s</xliff:g> untuk menyambung."</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> mahu menyambung kepada peranti anda dengan PIN yang berikut."</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{{device} mahu menyambung kepada peranti anda. Terima dalam masa {countdown} saat.}other{{device} mahu menyambung kepada peranti anda. Terima dalam masa {countdown} saat.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{Masukkan PIN yang dipaparkan pada {device} dalam masa {countdown} saat untuk membuat sambungan.}other{Masukkan PIN yang dipaparkan pada {device} dalam masa {countdown} saat untuk membuat sambungan.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{{device} mahu menyambung kepada peranti anda dengan PIN yang berikut. Terima dalam masa {countdown} saat.}other{{device} mahu menyambung kepada peranti anda dengan PIN yang berikut. Terima dalam masa {countdown} saat.}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"Sambung"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"Batal"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"PIN"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"PIN"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"Peranti anda akan diputuskan sambungan daripada Wi-Fi untuk sementara waktu semasa peranti ini disambungkan kepada <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="dlg_ok" msgid="254496739491689405">"OK"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"Tidak dapat menyambung ke <xliff:g id="SSID">%1$s</xliff:g>"</string>
diff --git a/service/ServiceWifiResources/res/values-my/strings.xml b/service/ServiceWifiResources/res/values-my/strings.xml
index ea57a2a..5ae53cd 100644
--- a/service/ServiceWifiResources/res/values-my/strings.xml
+++ b/service/ServiceWifiResources/res/values-my/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"သို့:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"လိုအပ်သော ပင် နံပါတ် ရိုက်ရန်:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"ပင် နံပါတ်:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"စက်ပစ္စည်းချိတ်ဆက်မှု"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"စက်ပစ္စည်းချိတ်ဆက်မှု"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"ဖိတ်ကြားချက်ကို <xliff:g id="DEVICE_NAME">%1$s</xliff:g> သို့ ပို့လိုက်သည်။"</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"ချိတ်ဆက်ရန်အတွက် <xliff:g id="DEVICE_NAME">%1$s</xliff:g> တွင် ဤပင်နံပါတ်ကို ထည့်ပါ။"</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"OK"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"စက်ပစ္စည်းချိတ်ဆက်မှု"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"စက်ပစ္စည်းချိတ်ဆက်မှု"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"စက်ပစ္စည်းချိတ်ဆက်မှု"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> က သင့်စက်ကို ချိတ်ဆက်လိုသည်။"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"ချိတ်ဆက်ရန်အတွက် <xliff:g id="DEVICE_NAME">%1$s</xliff:g> တွင် ပြထားသော ပင်နံပါတ်ကို ထည့်ပါ။"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> က အောက်ပါပင်နံပါတ်သုံး၍ သင့်စက်ကို ချိတ်ဆက်လိုသည်။"</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{{device} က သင့်စက်ကို ချိတ်ဆက်လိုသည်။ {countdown} စက္ကန့်အတွင်း လက်ခံပါ။}other{{device} က သင့်စက်ကို ချိတ်ဆက်လိုသည်။ {countdown} စက္ကန့်အတွင်း လက်ခံပါ။}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{ချိတ်ဆက်ရန်အတွက် {device} တွင် ပြထားသော ပင်နံပါတ်ကို {countdown} အတွင်း ထည့်ပါ။}other{ချိတ်ဆက်ရန်အတွက် {device} တွင် ပြထားသော ပင်နံပါတ်ကို {countdown} အတွင်း ထည့်ပါ။}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{{device} က အောက်ပါပင်နံပါတ်သုံး၍ သင့်စက်ကို ချိတ်ဆက်လိုသည်။ {countdown} စက္ကန့်အတွင်း လက်ခံပါ။}other{{device} က အောက်ပါပင်နံပါတ်သုံး၍ သင့်စက်ကို ချိတ်ဆက်လိုသည်။ {countdown} စက္ကန့်အတွင်း လက်ခံပါ။}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"ချိတ်ဆက်ရန်"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"မလုပ်တော့"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"ပင်နံပါတ်"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"ပင်နံပါတ်"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"သင့်စက်သည် <xliff:g id="DEVICE_NAME">%1$s</xliff:g> သို့ ချိတ်ဆက်ထားစဉ် Wi-Fi နှင့် ချိတ်ဆက်မှုကို ယာယီဖြုတ်ထားမည်"</string>
<string name="dlg_ok" msgid="254496739491689405">"OK"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"<xliff:g id="SSID">%1$s</xliff:g> နှင့် ချိတ်ဆက်၍မရပါ။"</string>
diff --git a/service/ServiceWifiResources/res/values-nb/strings.xml b/service/ServiceWifiResources/res/values-nb/strings.xml
index f97c308..888e701 100644
--- a/service/ServiceWifiResources/res/values-nb/strings.xml
+++ b/service/ServiceWifiResources/res/values-nb/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"Til:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"Skriv inn påkrevd PIN-kode:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"PIN:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"Enhetstilkobling"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"Enhetstilkobling"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"Invitasjonen er sendt til <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"Skriv inn denne PIN-koden på <xliff:g id="DEVICE_NAME">%1$s</xliff:g> for å koble til."</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"OK"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"Enhetstilkobling"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"Enhetstilkobling"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"Enhetstilkobling"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> vil koble til enheten din."</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"Skriv inn PIN-koden som vises på <xliff:g id="DEVICE_NAME">%1$s</xliff:g>, for å koble til."</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> vil koble til enheten din med den følgende PIN-koden."</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{{device} vil koble til enheten din. Godta om {countdown} sekund.}other{{device} vil koble til enheten din. Godta om {countdown} sekunder.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{Skriv inn PIN-koden som vises på {device}, innen {countdown} sekund for å koble til.}other{Skriv inn PIN-koden som vises på {device}, innen {countdown} sekunder for å koble til.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{{device} vil koble til enheten din med den følgende PIN-koden. Godta om {countdown} sekund.}other{{device} vil koble til enheten din med den følgende PIN-koden. Godta om {countdown} sekunder.}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"Koble til"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"Avbryt"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"PIN-kode"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"PIN-kode"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"Enheten din blir midlertidig koblet fra wifi mens den er koblet til <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="dlg_ok" msgid="254496739491689405">"OK"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"Kan ikke koble til <xliff:g id="SSID">%1$s</xliff:g>"</string>
diff --git a/service/ServiceWifiResources/res/values-ne/strings.xml b/service/ServiceWifiResources/res/values-ne/strings.xml
index aa5ac4b..daeffdf 100644
--- a/service/ServiceWifiResources/res/values-ne/strings.xml
+++ b/service/ServiceWifiResources/res/values-ne/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"प्रापक:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"आवश्यक PIN टाइप गर्नुहोस्:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"PIN:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"डिभाइसको कनेक्सन"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"डिभाइसको कनेक्सन"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> मा निम्तो पठाइएको छ।"</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"कनेक्ट गर्नका निम्ति यो PIN <xliff:g id="DEVICE_NAME">%1$s</xliff:g> मा हाल्नुहोस्।"</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"ठिक छ"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"डिभाइसको कनेक्सन"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"डिभाइसको कनेक्सन"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"डिभाइसको कनेक्सन"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> तपाईंको डिभाइसमा कनेक्ट गर्न चाहन्छ।"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"कनेक्ट गर्नका निम्ति <xliff:g id="DEVICE_NAME">%1$s</xliff:g> मा देखाइएको PIN हाल्नुहोस्।"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> निम्न PIN प्रयोग गरी तपाईंको डिभाइसमा कनेक्ट गर्न चाहन्छ।"</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{{device} तपाईंको डिभाइसमा कनेक्ट गर्न चाहन्छ। {countdown} सेकेन्डपछि स्वीकार गर्नुहोस्।}other{{device} तपाईंको डिभाइसमा कनेक्ट गर्न चाहन्छ। {countdown} सेकेन्डपछि स्वीकार गर्नुहोस्।}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{कनेक्ट गर्नका निम्ति {countdown} सेकेन्डभित्र {device} मा देखाइएको PIN हाल्नुहोस्।}other{कनेक्ट गर्नका निम्ति {countdown} सेकेन्डभित्र {device} मा देखाइएको PIN हाल्नुहोस्।}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{{device} निम्न PIN प्रयोग गरी तपाईंको डिभाइसमा कनेक्ट गर्न चाहन्छ। {countdown} सेकेन्डपछि स्वीकार गर्नुहोस्।}other{{device} निम्न PIN प्रयोग गरी तपाईंको डिभाइसमा कनेक्ट गर्न चाहन्छ। {countdown} सेकेन्डपछि स्वीकार गर्नुहोस्।}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"कनेक्ट गर्नुहोस्"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"रद्द गर्नुहोस्"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"PIN"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"PIN"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"तपाईंको डिभाइस <xliff:g id="DEVICE_NAME">%1$s</xliff:g> मा कनेक्ट गरिएको बेलामा यो केही बेर Wi-Fi बाट डिस्कनेक्ट हुने छ"</string>
<string name="dlg_ok" msgid="254496739491689405">"ठिक छ"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"<xliff:g id="SSID">%1$s</xliff:g> मा जडान गर्न सकिएन"</string>
diff --git a/service/ServiceWifiResources/res/values-night/styles.xml b/service/ServiceWifiResources/res/values-night/styles.xml
index 9279ee3..a970495 100644
--- a/service/ServiceWifiResources/res/values-night/styles.xml
+++ b/service/ServiceWifiResources/res/values-night/styles.xml
@@ -23,4 +23,18 @@
<item name="android:inputType">number</item>
<item name="android:textColor">@android:color/primary_text_dark</item>
</style>
+
+ <style name="wifi_p2p_dialog2" parent="@android:style/Theme.DeviceDefault.Dialog.Alert" />
+ <style name="wifi_p2p_dialog2_pin_label">
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:textColor">@android:color/secondary_text_dark</item>
+ <item name="android:textSize">14sp</item>
+ </style>
+ <style name="wifi_p2p_dialog2_pin">
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:textSize">18sp</item>
+ <item name="android:textColor">@android:color/primary_text_dark</item>
+ </style>
</resources>
diff --git a/service/ServiceWifiResources/res/values-nl/strings.xml b/service/ServiceWifiResources/res/values-nl/strings.xml
index 4c6e2d7..3531394 100644
--- a/service/ServiceWifiResources/res/values-nl/strings.xml
+++ b/service/ServiceWifiResources/res/values-nl/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"Naar:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"Voer de gewenste pincode in:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"Pincode"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"Apparaatverbinding"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"Apparaatverbinding"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"Uitnodiging verstuurd naar <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"Voer deze pincode in op <xliff:g id="DEVICE_NAME">%1$s</xliff:g> om verbinding te maken."</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"OK"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"Apparaatverbinding"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"Apparaatverbinding"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"Apparaatverbinding"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> wil verbinding maken met je apparaat."</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"Voer de pincode in die op <xliff:g id="DEVICE_NAME">%1$s</xliff:g> wordt getoond om verbinding te maken."</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> wil verbinding maken met je apparaat met de volgende pincode."</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{{device} wil verbinding maken met je apparaat. Accepteren over {countdown} seconde.}other{{device} wil verbinding maken met je apparaat. Accepteren over {countdown} seconden.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{Voer binnen {countdown} seconde de pincode in die op {device} wordt getoond om verbinding te maken.}other{Voer binnen {countdown} seconden de pincode in die op {device} wordt getoond om verbinding te maken.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{{device} wil verbinding maken met je apparaat met de volgende pincode. Accepteren over {countdown} seconde.}other{{device} wil verbinding maken met je apparaat met de volgende pincode. Accepteren over {countdown} seconden.}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"Verbinden"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"Annuleren"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"Pincode"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"Pincode"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"Je apparaat verbreekt tijdelijk de verbinding met wifi terwijl het verbonden is met <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="dlg_ok" msgid="254496739491689405">"OK"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"Kan niet verbinden met <xliff:g id="SSID">%1$s</xliff:g>"</string>
diff --git a/service/ServiceWifiResources/res/values-or/strings.xml b/service/ServiceWifiResources/res/values-or/strings.xml
index 6abb1e6..0860d79 100644
--- a/service/ServiceWifiResources/res/values-or/strings.xml
+++ b/service/ServiceWifiResources/res/values-or/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"ପ୍ରାପ୍ତେଷୁ:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"ଆବଶ୍ୟକ PIN ଟାଇପ୍ କରନ୍ତୁ:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"PIN:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"ଡିଭାଇସ କନେକ୍ସନ"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"ଡିଭାଇସ କନେକ୍ସନ"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>କୁ ଆମନ୍ତ୍ରଣ ପଠାଯାଇଛି।"</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"କନେକ୍ଟ କରିବାକୁ <xliff:g id="DEVICE_NAME">%1$s</xliff:g>ରେ ଏହି PIN ଲେଖନ୍ତୁ।"</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"ଠିକ ଅଛି"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"ଡିଭାଇସ କନେକ୍ସନ"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"ଡିଭାଇସ କନେକ୍ସନ"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"ଡିଭାଇସ କନେକ୍ସନ"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> ଆପଣଙ୍କ ଡିଭାଇସ ସହ କନେକ୍ଟ କରିବାକୁ ଚାହୁଁଛି।"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"କନେକ୍ଟ କରିବାକୁ <xliff:g id="DEVICE_NAME">%1$s</xliff:g>ରେ ଦେଖାଯାଉଥିବା PIN ଲେଖନ୍ତୁ।"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> ନିମ୍ନୋକ୍ତ PIN ମାଧ୍ୟମରେ ଆପଣଙ୍କ ଡିଭାଇସ ସହ କନେକ୍ଟ କରିବାକୁ ଚାହୁଁଛି।"</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{{device} ଆପଣଙ୍କ ଡିଭାଇସ ସହ କନେକ୍ଟ କରିବାକୁ ଚାହୁଁଛି। {countdown} ସେକେଣ୍ଡରେ ଗ୍ରହଣ କରନ୍ତୁ।}other{{device} ଆପଣଙ୍କ ଡିଭାଇସ ସହ କନେକ୍ଟ କରିବାକୁ ଚାହୁଁଛି। {countdown} ସେକେଣ୍ଡରେ ଗ୍ରହଣ କରନ୍ତୁ।}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{କନେକ୍ଟ କରିବାକୁ {countdown} ସେକେଣ୍ଡ ମଧ୍ୟରେ {device}ରେ ଦେଖାଯାଉଥିବା PIN ଲେଖନ୍ତୁ।}other{କନେକ୍ଟ କରିବାକୁ {countdown} ସେକେଣ୍ଡ ମଧ୍ୟରେ {device}ରେ ଦେଖାଯାଉଥିବା PIN ଲେଖନ୍ତୁ।}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{{device} ନିମ୍ନୋକ୍ତ PIN ମାଧ୍ୟମରେ ଆପଣଙ୍କ ଡିଭାଇସ ସହ କନେକ୍ଟ କରିବାକୁ ଚାହୁଁଛି। {countdown} ସେକେଣ୍ଡରେ ଗ୍ରହଣ କରନ୍ତୁ।}other{{device} ନିମ୍ନୋକ୍ତ PIN ମାଧ୍ୟମରେ ଆପଣଙ୍କ ଡିଭାଇସ ସହ କନେକ୍ଟ କରିବାକୁ ଚାହୁଁଛି। {countdown} ସେକେଣ୍ଡରେ ଗ୍ରହଣ କରନ୍ତୁ।}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"କନେକ୍ଟ କରନ୍ତୁ"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"ବାତିଲ କରନ୍ତୁ"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"PIN"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"PIN"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"ଆପଣଙ୍କ ଡିଭାଇସ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ସହ କନେକ୍ଟ ଥିବା ସମୟରେ ଏହା ଅସ୍ଥାୟୀ ଭାବେ ୱାଇ-ଫାଇରୁ ଡିସକନେକ୍ଟ ହୋଇଯିବ"</string>
<string name="dlg_ok" msgid="254496739491689405">"ଠିକ ଅଛି"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"<xliff:g id="SSID">%1$s</xliff:g> ସହିତ ସଂଯୋଗ କରାଯାଇପାରିବ ନାହିଁ"</string>
diff --git a/service/ServiceWifiResources/res/values-pa/strings.xml b/service/ServiceWifiResources/res/values-pa/strings.xml
index 2589be4..4c64a52 100644
--- a/service/ServiceWifiResources/res/values-pa/strings.xml
+++ b/service/ServiceWifiResources/res/values-pa/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"ਵੱਲ:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"ਲੋੜੀਂਦਾ ਪਿੰਨ ਟਾਈਪ ਕਰੋ:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"ਪਿੰਨ:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"ਡੀਵਾਈਸ ਕਨੈਕਸ਼ਨ"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"ਡੀਵਾਈਸ ਕਨੈਕਸ਼ਨ"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> ਨੂੰ ਸੱਦਾ ਭੇਜਿਆ ਗਿਆ।"</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"ਕਨੈਕਟ ਕਰਨ ਲਈ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> \'ਤੇ ਇਹ ਪਿੰਨ ਦਾਖਲ ਕਰੋ।"</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"ਠੀਕ ਹੈ"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"ਡੀਵਾਈਸ ਕਨੈਕਸ਼ਨ"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"ਡੀਵਾਈਸ ਕਨੈਕਸ਼ਨ"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"ਡੀਵਾਈਸ ਕਨੈਕਸ਼ਨ"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਨਾਲ ਕਨੈਕਟ ਕਰਨਾ ਚਾਹੁੰਦਾ ਹੈ।"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"ਕਨੈਕਟ ਕਰਨ ਲਈ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> \'ਤੇ ਦਿਖਾਇਆ ਗਿਆ ਪਿੰਨ ਦਾਖਲ ਕਰੋ।"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> ਅੱਗੇ ਦਿੱਤੇ ਪਿੰਨ ਨਾਲ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਨਾਲ ਕਨੈਕਟ ਕਰਨਾ ਚਾਹੁੰਦਾ ਹੈ।"</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{{device} ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਨਾਲ ਕਨੈਕਟ ਕਰਨਾ ਚਾਹੁੰਦਾ ਹੈ। {countdown} ਸਕਿੰਟ ਵਿੱਚ ਸਵੀਕਾਰ ਕਰੋ।}one{{device} ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਨਾਲ ਕਨੈਕਟ ਕਰਨਾ ਚਾਹੁੰਦਾ ਹੈ। {countdown} ਸਕਿੰਟ ਵਿੱਚ ਸਵੀਕਾਰ ਕਰੋ।}other{{device} ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਨਾਲ ਕਨੈਕਟ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹਨ। {countdown} ਸਕਿੰਟਾਂ ਵਿੱਚ ਸਵੀਕਾਰ ਕਰੋ।}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{ਕਨੈਕਟ ਕਰਨ ਲਈ {countdown} ਸਕਿੰਟ ਵਿੱਚ {device} \'ਤੇ ਦਿਖਾਇਆ ਗਿਆ ਪਿੰਨ ਦਾਖਲ ਕਰੋ।}one{ਕਨੈਕਟ ਕਰਨ ਲਈ {countdown} ਸਕਿੰਟ ਵਿੱਚ {device} \'ਤੇ ਦਿਖਾਇਆ ਗਿਆ ਪਿੰਨ ਦਾਖਲ ਕਰੋ।}other{ਕਨੈਕਟ ਕਰਨ ਲਈ {countdown} ਸਕਿੰਟਾਂ ਵਿੱਚ {device} \'ਤੇ ਦਿਖਾਇਆ ਗਿਆ ਪਿੰਨ ਦਾਖਲ ਕਰੋ।}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{{device} ਅੱਗੇ ਦਿੱਤੇ ਪਿੰਨ ਨਾਲ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਨਾਲ ਕਨੈਕਟ ਕਰਨਾ ਚਾਹੁੰਦਾ ਹੈ। {countdown} ਸਕਿੰਟ ਵਿੱਚ ਸਵੀਕਾਰ ਕਰੋ।}one{{device} ਅੱਗੇ ਦਿੱਤੇ ਪਿੰਨ ਨਾਲ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਨਾਲ ਕਨੈਕਟ ਕਰਨਾ ਚਾਹੁੰਦਾ ਹੈ। {countdown} ਸਕਿੰਟ ਵਿੱਚ ਸਵੀਕਾਰ ਕਰੋ।}other{{device} ਅੱਗੇ ਦਿੱਤੇ ਪਿੰਨ ਨਾਲ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਨਾਲ ਕਨੈਕਟ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹਨ। {countdown} ਸਕਿੰਟਾਂ ਵਿੱਚ ਸਵੀਕਾਰ ਕਰੋ।}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"ਕਨੈਕਟ ਕਰੋ"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"ਰੱਦ ਕਰੋ"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"ਪਿੰਨ"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"ਪਿੰਨ"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> ਨਾਲ ਕਨੈਕਟ ਹੋਣ \'ਤੇ, ਤੁਹਾਡਾ ਡੀਵਾਈਸ ਕੁਝ ਸਮੇਂ ਲਈ ਵਾਈ-ਫਾਈ ਤੋਂ ਡਿਸਕਨੈਕਟ ਹੋ ਜਾਵੇਗਾ"</string>
<string name="dlg_ok" msgid="254496739491689405">"ਠੀਕ ਹੈ"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"<xliff:g id="SSID">%1$s</xliff:g> ਨਾਲ ਕਨੈਕਟ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ"</string>
diff --git a/service/ServiceWifiResources/res/values-pl/strings.xml b/service/ServiceWifiResources/res/values-pl/strings.xml
index e3afb51..85c9402 100644
--- a/service/ServiceWifiResources/res/values-pl/strings.xml
+++ b/service/ServiceWifiResources/res/values-pl/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"Do:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"Wpisz wymagany kod PIN:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"Kod PIN:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"Połączenie urządzenia"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"Połączenie urządzenia"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"Zaproszenie zostało wysłane na urządzenie <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"Aby się połączyć, wpisz ten kod PIN na urządzeniu <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"OK"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"Połączenie urządzenia"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"Połączenie urządzenia"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"Połączenie urządzenia"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> chce połączyć się z Twoim urządzeniem."</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"Aby się połączyć, wpisz kod PIN widoczny na urządzeniu <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> chce połączyć się z Twoim urządzeniem za pomocą tego kodu PIN."</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{{device} chce połączyć się z Twoim urządzeniem. Zaakceptuj w ciągu {countdown} sekundy.}few{{device} chce połączyć się z Twoim urządzeniem. Zaakceptuj w ciągu {countdown} sekund.}many{{device} chce połączyć się z Twoim urządzeniem. Zaakceptuj w ciągu {countdown} sekund.}other{{device} chce połączyć się z Twoim urządzeniem. Zaakceptuj w ciągu {countdown} sekundy.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{Aby się połączyć, w ciągu {countdown} sekundy wpisz kod PIN widoczny na urządzeniu {device}.}few{Aby się połączyć, w ciągu {countdown} sekund wpisz kod PIN widoczny na urządzeniu {device}.}many{Aby się połączyć, w ciągu {countdown} sekund wpisz kod PIN widoczny na urządzeniu {device}.}other{Aby się połączyć, w ciągu {countdown} sekundy wpisz kod PIN widoczny na urządzeniu {device}.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{{device} chce połączyć się z Twoim urządzeniem za pomocą tego kodu PIN. Zaakceptuj w ciągu {countdown} sekundy.}few{{device} chce połączyć się z Twoim urządzeniem za pomocą tego kodu PIN. Zaakceptuj w ciągu {countdown} sekund.}many{{device} chce połączyć się z Twoim urządzeniem za pomocą tego kodu PIN. Zaakceptuj w ciągu {countdown} sekund.}other{{device} chce połączyć się z Twoim urządzeniem za pomocą tego kodu PIN. Zaakceptuj w ciągu {countdown} sekundy.}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"Połącz"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"Anuluj"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"Kod PIN"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"Kod PIN"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"Gdy urządzenie zostanie podłączone do urządzenia <xliff:g id="DEVICE_NAME">%1$s</xliff:g>, tymczasowo rozłączy się z Wi-Fi"</string>
<string name="dlg_ok" msgid="254496739491689405">"OK"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"Nie można połączyć się z siecią <xliff:g id="SSID">%1$s</xliff:g>"</string>
diff --git a/service/ServiceWifiResources/res/values-pt-rBR/strings.xml b/service/ServiceWifiResources/res/values-pt-rBR/strings.xml
index 2f2060c..f545a10 100644
--- a/service/ServiceWifiResources/res/values-pt-rBR/strings.xml
+++ b/service/ServiceWifiResources/res/values-pt-rBR/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"Para:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"Digite o PIN obrigatório:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"PIN:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"Conexão do dispositivo"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"Conexão do dispositivo"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"Convite enviado para o <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"Digite este PIN no <xliff:g id="DEVICE_NAME">%1$s</xliff:g> para se conectar."</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"OK"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"Conexão do dispositivo"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"Conexão do dispositivo"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"Conexão do dispositivo"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"O <xliff:g id="DEVICE_NAME">%1$s</xliff:g> quer se conectar ao seu dispositivo."</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"Digite o PIN mostrado no <xliff:g id="DEVICE_NAME">%1$s</xliff:g> para se conectar."</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"O <xliff:g id="DEVICE_NAME">%1$s</xliff:g> quer se conectar ao seu dispositivo com o seguinte PIN."</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{O {device} quer se conectar ao seu dispositivo. Aceite em {countdown} segundo.}one{O {device} quer se conectar ao seu dispositivo. Aceite em {countdown} segundo.}many{O {device} quer se conectar ao seu dispositivo. Aceite em {countdown} de segundos.}other{O {device} quer se conectar ao seu dispositivo. Aceite em {countdown} segundos.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{Digite o PIN mostrado no {device} em até {countdown} segundo para se conectar.}one{Digite o PIN mostrado no {device} em até {countdown} segundo para se conectar.}many{Digite o PIN mostrado no {device} em até {countdown} de segundos para se conectar.}other{Digite o PIN mostrado no {device} em até {countdown} segundos para se conectar.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{O {device} quer se conectar ao seu dispositivo com o seguinte PIN. Aceite em {countdown} segundo.}one{O {device} quer se conectar ao seu dispositivo com o seguinte PIN. Aceite em {countdown} segundo.}many{O {device} quer se conectar ao seu dispositivo com o seguinte PIN. Aceite em {countdown} de segundos.}other{O {device} quer se conectar ao seu dispositivo com o seguinte PIN. Aceite em {countdown} segundos.}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"Conectar"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"Cancelar"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"PIN"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"PIN"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"O dispositivo vai desconectar o Wi-Fi temporariamente enquanto estiver conectado ao <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="dlg_ok" msgid="254496739491689405">"OK"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"Não foi possível se conectar à rede <xliff:g id="SSID">%1$s</xliff:g>"</string>
diff --git a/service/ServiceWifiResources/res/values-pt-rPT/strings.xml b/service/ServiceWifiResources/res/values-pt-rPT/strings.xml
index 6b56d85..086254b 100644
--- a/service/ServiceWifiResources/res/values-pt-rPT/strings.xml
+++ b/service/ServiceWifiResources/res/values-pt-rPT/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"Para:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"Introduza o PIN solicitado:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"PIN:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"Ligação do dispositivo"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"Ligação do dispositivo"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"Convite enviado para o dispositivo <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"Introduza este PIN no dispositivo <xliff:g id="DEVICE_NAME">%1$s</xliff:g> para estabelecer ligação."</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"OK"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"Ligação do dispositivo"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"Ligação do dispositivo"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"Ligação do dispositivo"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"O dispositivo <xliff:g id="DEVICE_NAME">%1$s</xliff:g> quer estabelecer ligação ao seu dispositivo."</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"Introduza o PIN apresentado no dispositivo <xliff:g id="DEVICE_NAME">%1$s</xliff:g> para estabelecer ligação."</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"O dispositivo <xliff:g id="DEVICE_NAME">%1$s</xliff:g> quer estabelecer ligação ao seu dispositivo com o seguinte PIN."</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{O dispositivo {device} quer estabelecer ligação ao seu dispositivo. Aceite dentro de {countdown} segundo.}many{O dispositivo {device} quer estabelecer ligação ao seu dispositivo. Aceite dentro de {countdown} segundos.}other{O dispositivo {device} quer estabelecer ligação ao seu dispositivo. Aceite dentro de {countdown} segundos.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{Introduza o PIN apresentado no dispositivo {device} no prazo de {countdown} segundo para estabelecer ligação.}many{Introduza o PIN apresentado no dispositivo {device} no prazo de {countdown} segundos para estabelecer ligação.}other{Introduza o PIN apresentado no dispositivo {device} no prazo de {countdown} segundos para estabelecer ligação.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{O dispositivo {device} quer estabelecer ligação ao seu dispositivo com o seguinte PIN. Aceite dentro de {countdown} segundo.}many{O dispositivo {device} quer estabelecer ligação ao seu dispositivo com o seguinte PIN. Aceite dentro de {countdown} segundos.}other{O dispositivo {device} quer estabelecer ligação ao seu dispositivo com o seguinte PIN. Aceite dentro de {countdown} segundos.}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"Ligar"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"Cancelar"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"PIN"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"PIN"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"O seu dispositivo vai desligar-se temporariamente da rede Wi-Fi enquanto está ligado ao dispositivo <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
<string name="dlg_ok" msgid="254496739491689405">"OK"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"Não é possível ligar a <xliff:g id="SSID">%1$s</xliff:g>."</string>
diff --git a/service/ServiceWifiResources/res/values-pt/strings.xml b/service/ServiceWifiResources/res/values-pt/strings.xml
index 2f2060c..f545a10 100644
--- a/service/ServiceWifiResources/res/values-pt/strings.xml
+++ b/service/ServiceWifiResources/res/values-pt/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"Para:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"Digite o PIN obrigatório:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"PIN:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"Conexão do dispositivo"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"Conexão do dispositivo"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"Convite enviado para o <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"Digite este PIN no <xliff:g id="DEVICE_NAME">%1$s</xliff:g> para se conectar."</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"OK"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"Conexão do dispositivo"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"Conexão do dispositivo"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"Conexão do dispositivo"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"O <xliff:g id="DEVICE_NAME">%1$s</xliff:g> quer se conectar ao seu dispositivo."</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"Digite o PIN mostrado no <xliff:g id="DEVICE_NAME">%1$s</xliff:g> para se conectar."</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"O <xliff:g id="DEVICE_NAME">%1$s</xliff:g> quer se conectar ao seu dispositivo com o seguinte PIN."</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{O {device} quer se conectar ao seu dispositivo. Aceite em {countdown} segundo.}one{O {device} quer se conectar ao seu dispositivo. Aceite em {countdown} segundo.}many{O {device} quer se conectar ao seu dispositivo. Aceite em {countdown} de segundos.}other{O {device} quer se conectar ao seu dispositivo. Aceite em {countdown} segundos.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{Digite o PIN mostrado no {device} em até {countdown} segundo para se conectar.}one{Digite o PIN mostrado no {device} em até {countdown} segundo para se conectar.}many{Digite o PIN mostrado no {device} em até {countdown} de segundos para se conectar.}other{Digite o PIN mostrado no {device} em até {countdown} segundos para se conectar.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{O {device} quer se conectar ao seu dispositivo com o seguinte PIN. Aceite em {countdown} segundo.}one{O {device} quer se conectar ao seu dispositivo com o seguinte PIN. Aceite em {countdown} segundo.}many{O {device} quer se conectar ao seu dispositivo com o seguinte PIN. Aceite em {countdown} de segundos.}other{O {device} quer se conectar ao seu dispositivo com o seguinte PIN. Aceite em {countdown} segundos.}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"Conectar"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"Cancelar"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"PIN"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"PIN"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"O dispositivo vai desconectar o Wi-Fi temporariamente enquanto estiver conectado ao <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="dlg_ok" msgid="254496739491689405">"OK"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"Não foi possível se conectar à rede <xliff:g id="SSID">%1$s</xliff:g>"</string>
diff --git a/service/ServiceWifiResources/res/values-ro/strings.xml b/service/ServiceWifiResources/res/values-ro/strings.xml
index 40271f5..80291ea 100644
--- a/service/ServiceWifiResources/res/values-ro/strings.xml
+++ b/service/ServiceWifiResources/res/values-ro/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"Către:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"Introdu codul PIN necesar:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"Cod PIN:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"Conexiunea dispozitivului"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"Conexiunea dispozitivului"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"Invitația a fost trimisă la <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"Introdu acest PIN pe <xliff:g id="DEVICE_NAME">%1$s</xliff:g> pentru a te conecta."</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"OK"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"Conexiunea dispozitivului"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"Conexiunea dispozitivului"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"Conexiunea dispozitivului"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> solicită conectarea la dispozitivul tău."</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"Introdu PIN-ul afișat pe <xliff:g id="DEVICE_NAME">%1$s</xliff:g> pentru a te conecta."</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> solicită conectarea la dispozitivul tău cu următorul PIN."</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{{device} solicită conectarea la dispozitivul tău. Acceptă în {countdown} secundă.}few{{device} solicită conectarea la dispozitivul tău. Acceptă în {countdown} secunde.}other{{device} solicită conectarea la dispozitivul tău. Acceptă în {countdown} de secunde.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{Introdu PIN-ul afișat pe {device} în {countdown} secundă pentru a te conecta.}few{Introdu PIN-ul afișat pe {device} în {countdown} secunde pentru a te conecta.}other{Introdu PIN-ul afișat pe {device} în {countdown} de secunde pentru a te conecta.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{{device} solicită conectarea la dispozitivul tău cu următorul PIN. Acceptă în {countdown} secundă.}few{{device} solicită conectarea la dispozitivul tău cu următorul PIN. Acceptă în {countdown} secunde.}other{{device} solicită conectarea la dispozitivul tău cu următorul PIN. Acceptă în {countdown} de secunde.}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"Conectează"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"Anulează"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"PIN"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"PIN"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"Dispozitivul se va deconecta temporar de la Wi-Fi cât timp este conectat la <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="dlg_ok" msgid="254496739491689405">"OK"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"Nu se poate conecta la <xliff:g id="SSID">%1$s</xliff:g>"</string>
diff --git a/service/ServiceWifiResources/res/values-ru/strings.xml b/service/ServiceWifiResources/res/values-ru/strings.xml
index a47cd0e..e83fadb 100644
--- a/service/ServiceWifiResources/res/values-ru/strings.xml
+++ b/service/ServiceWifiResources/res/values-ru/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"Кому:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"Введите PIN-код:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"PIN-код:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"Подключение к устройству"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"Подключение к устройству"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"Приглашение отправлено пользователю устройства \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\"."</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"Чтобы подключиться, введите этот PIN-код на устройстве \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\"."</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"ОК"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"Подключение к устройству"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"Подключение к устройству"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"Подключение к устройству"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"К вашему устройству хочет подключиться пользователь устройства \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\"."</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"Чтобы подключиться, введите PIN-код, указанный на устройстве \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\"."</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"К вашему устройству хочет подключиться пользователь устройства \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\". Для этого потребуется указанный далее PIN-код."</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{К вашему устройству хочет подключиться пользователь устройства \"{device}\". У вас есть {countdown} секунда, чтобы дать согласие.}one{К вашему устройству хочет подключиться пользователь устройства \"{device}\". У вас есть {countdown} секунда, чтобы дать согласие.}few{К вашему устройству хочет подключиться пользователь устройства \"{device}\". У вас есть {countdown} секунды, чтобы дать согласие.}many{К вашему устройству хочет подключиться пользователь устройства \"{device}\". У вас есть {countdown} секунд, чтобы дать согласие.}other{К вашему устройству хочет подключиться пользователь устройства \"{device}\". У вас есть {countdown} секунды, чтобы дать согласие.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{Чтобы подключиться, в течение {countdown} секунды введите PIN-код, указанный на устройстве \"{device}\".}one{Чтобы подключиться, в течение {countdown} секунды введите PIN-код, указанный на устройстве \"{device}\".}few{Чтобы подключиться, в течение {countdown} секунд введите PIN-код, указанный на устройстве \"{device}\".}many{Чтобы подключиться, в течение {countdown} секунд введите PIN-код, указанный на устройстве \"{device}\".}other{Чтобы подключиться, в течение {countdown} секунды введите PIN-код, указанный на устройстве \"{device}\".}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{К вашему устройству хочет подключиться пользователь устройства \"{device}\". Для этого нужен указанный далее PIN-код. У вас есть {countdown} секунда, чтобы дать согласие.}one{К вашему устройству хочет подключиться пользователь устройства \"{device}\". Для этого нужен указанный далее PIN-код. У вас есть {countdown} секунда, чтобы дать согласие.}few{К вашему устройству хочет подключиться пользователь устройства \"{device}\". Для этого нужен указанный далее PIN-код. У вас есть {countdown} секунды, чтобы дать согласие.}many{К вашему устройству хочет подключиться пользователь устройства \"{device}\". Для этого нужен указанный далее PIN-код. У вас есть {countdown} секунд, чтобы дать согласие.}other{К вашему устройству хочет подключиться пользователь устройства \"{device}\". Для этого нужен указанный далее PIN-код. У вас есть {countdown} секунды, чтобы дать согласие.}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"Подключиться"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"Отмена"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"PIN-код"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"PIN-код"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"На время подключения к устройству <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ваше устройство отключится от сети Wi-Fi."</string>
<string name="dlg_ok" msgid="254496739491689405">"ОК"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"Не удалось подключиться к устройству \"<xliff:g id="SSID">%1$s</xliff:g>\""</string>
diff --git a/service/ServiceWifiResources/res/values-si/strings.xml b/service/ServiceWifiResources/res/values-si/strings.xml
index d9c7cb4..4e3c1cd 100644
--- a/service/ServiceWifiResources/res/values-si/strings.xml
+++ b/service/ServiceWifiResources/res/values-si/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"වෙත:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"අවශ්ය PIN එක ටයිප් කරන්න:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"PIN:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"උපාංග සම්බන්ධතාව"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"උපාංග සම්බන්ධතාව"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> වෙත ආරාධනය යැවුවා."</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"සම්බන්ධ වීමට <xliff:g id="DEVICE_NAME">%1$s</xliff:g> මත මෙම PIN ඇතුළු කරන්න."</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"හරි"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"උපාංග සම්බන්ධතාව"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"උපාංග සම්බන්ධතාව"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"උපාංග සම්බන්ධතාව"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> හට ඔබේ උපාංගයට සම්බන්ධ වීමට අවශ්යයි."</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"සම්බන්ධ වීමට <xliff:g id="DEVICE_NAME">%1$s</xliff:g> හි පෙන්වා ඇති PIN ඇතුළු කරන්න."</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> හට පහත PIN අංකය සමග ඔබේ උපාංගයට සම්බන්ධ වීමට අවශ්යයි."</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{{device} හට ඔබේ උපාංගයට සම්බන්ධ වීමට අවශ්යයි. තත්පර {countdown}කින් පිළිගන්න.}one{{device} හට ඔබේ උපාංගයට සම්බන්ධ වීමට අවශ්යයි. තත්පර {countdown}කින් පිළිගන්න.}other{{device} හට ඔබේ උපාංගයට සම්බන්ධ වීමට අවශ්යයි. තත්පර {countdown}කින් පිළිගන්න.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{සම්බන්ධ වීමට තත්පර {countdown}ක් ඇතුළත {device} හි පෙන්වා ඇති PIN ඇතුළු කරන්න.}one{සම්බන්ධ වීමට තත්පර {countdown}ක් ඇතුළත {device} හි පෙන්වා ඇති PIN ඇතුළු කරන්න.}other{සම්බන්ධ වීමට තත්පර {countdown}ක් ඇතුළත {device} හි පෙන්වා ඇති PIN ඇතුළු කරන්න.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{{device} හට පහත PIN අංකය සමග ඔබේ උපාංගයට සම්බන්ධ වීමට අවශ්යයි. තත්පර {countdown}කින් පිළිගන්න.}one{{device} හට පහත PIN අංකය සමග ඔබේ උපාංගයට සම්බන්ධ වීමට අවශ්යයි. තත්පර {countdown}කින් පිළිගන්න.}other{{device} හට පහත PIN අංකය සමග ඔබේ උපාංගයට සම්බන්ධ වීමට අවශ්යයි. තත්පර {countdown}කින් පිළිගන්න.}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"සම්බන්ධ කරන්න"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"අවලංගු කරන්න"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"PIN"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"PIN"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> වෙත සම්බන්ධ වී ඇති අතරේ ඔබේ උපාංගය Wi-Fi වෙතින් තාවකාලිකව විසන්ධි වනු ඇත"</string>
<string name="dlg_ok" msgid="254496739491689405">"හරි"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"<xliff:g id="SSID">%1$s</xliff:g> වෙත සම්බන්ධ විය නොහැකිය"</string>
diff --git a/service/ServiceWifiResources/res/values-sk/strings.xml b/service/ServiceWifiResources/res/values-sk/strings.xml
index 397dc9f..84521b6 100644
--- a/service/ServiceWifiResources/res/values-sk/strings.xml
+++ b/service/ServiceWifiResources/res/values-sk/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"Komu:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"Zadajte požadovaný kód PIN:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"PIN:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"Pripojenie zariadenia"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"Pripojenie zariadenia"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"Pozvánka bola odoslaná do zariadenia <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"Ak sa chcete pripojiť, zadajte tento kód PIN v zariadení <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"OK"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"Pripojenie zariadenia"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"Pripojenie zariadenia"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"Pripojenie zariadenia"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> sa chce pripojiť k vášmu zariadeniu."</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"Zadajte kód PIN zobrazený v zariadení <xliff:g id="DEVICE_NAME">%1$s</xliff:g> a pripojte sa."</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> sa chce pripojiť k vášmu zariadeniu pomocou nasledujúceho kódu PIN."</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{{device} sa chce pripojiť k vášmu zariadeniu. Prijmite o {countdown} sekundu.}few{{device} sa chce pripojiť k vášmu zariadeniu. Prijmite o {countdown} sekundy.}many{{device} sa chce pripojiť k vášmu zariadeniu. Prijmite o {countdown} sekundy.}other{{device} sa chce pripojiť k vášmu zariadeniu. Prijmite o {countdown} sekúnd.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{Ak sa chcete pripojiť, do {countdown} sekundy zadajte kód PIN zobrazený v zariadení {device}.}few{Ak sa chcete pripojiť, do {countdown} sekúnd zadajte kód PIN zobrazený v zariadení {device}.}many{Ak sa chcete pripojiť, do {countdown} sekundy zadajte kód PIN zobrazený v zariadení {device}.}other{Ak sa chcete pripojiť, do {countdown} sekúnd zadajte kód PIN zobrazený v zariadení {device}.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{{device} sa chce pripojiť k vášmu zariadeniu pomocou nasledujúceho kódu PIN. Prijmite o {countdown} sekundu.}few{{device} sa chce pripojiť k vášmu zariadeniu pomocou nasledujúceho kódu PIN. Prijmite o {countdown} sekundy.}many{{device} sa chce pripojiť k vášmu zariadeniu pomocou nasledujúceho kódu PIN. Prijmite o {countdown} sekundy.}other{{device} sa chce pripojiť k vášmu zariadeniu pomocou nasledujúceho kódu PIN. Prijmite o {countdown} sekúnd.}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"Pripojiť"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"Zrušiť"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"PIN"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"PIN"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"Počas pripojenia k zariadeniu <xliff:g id="DEVICE_NAME">%1$s</xliff:g> sa vaše zariadenie dočasne odpojí od siete Wi‑Fi"</string>
<string name="dlg_ok" msgid="254496739491689405">"OK"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"K sieti <xliff:g id="SSID">%1$s</xliff:g> sa nedá pripojiť"</string>
diff --git a/service/ServiceWifiResources/res/values-sl/strings.xml b/service/ServiceWifiResources/res/values-sl/strings.xml
index e05b77d..8cdff48 100644
--- a/service/ServiceWifiResources/res/values-sl/strings.xml
+++ b/service/ServiceWifiResources/res/values-sl/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"Za:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"Vnesite zahtevano kodo PIN:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"PIN:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"Povezava naprave"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"Povezava naprave"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"Povabilo je bilo poslano v napravo <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"Vnesite to kodo PIN v napravi <xliff:g id="DEVICE_NAME">%1$s</xliff:g>, če želite vzpostaviti povezavo."</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"V redu"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"Povezava naprave"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"Povezava naprave"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"Povezava naprave"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> se želi povezati z vašo napravo."</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"Vnesite kodo PIN, prikazano v napravi <xliff:g id="DEVICE_NAME">%1$s</xliff:g>, če želite vzpostaviti povezavo."</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> se želi povezati z vašo napravo s to kodo PIN."</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{{device} se želi povezati z vašo napravo. Sprejmite v roku {countdown} sekunde.}one{{device} se želi povezati z vašo napravo. Sprejmite v roku {countdown} sekunde.}two{{device} se želi povezati z vašo napravo. Sprejmite v roku {countdown} sekund.}few{{device} se želi povezati z vašo napravo. Sprejmite v roku {countdown} sekund.}other{{device} se želi povezati z vašo napravo. Sprejmite v roku {countdown} sekund.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{V roku {countdown} sekunde vnesite kodo PIN, prikazano v napravi {device}, če želite vzpostaviti povezavo.}one{V roku {countdown} sekunde vnesite kodo PIN, prikazano v napravi {device}, če želite vzpostaviti povezavo.}two{V roku {countdown} sekund vnesite kodo PIN, prikazano v napravi {device}, če želite vzpostaviti povezavo.}few{V roku {countdown} sekund vnesite kodo PIN, prikazano v napravi {device}, če želite vzpostaviti povezavo.}other{V roku {countdown} sekund vnesite kodo PIN, prikazano v napravi {device}, če želite vzpostaviti povezavo.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{{device} se želi povezati z vašo napravo s to kodo PIN. Sprejmite v roku {countdown} sekunde.}one{{device} se želi povezati z vašo napravo s to kodo PIN. Sprejmite v roku {countdown} sekunde.}two{{device} se želi povezati z vašo napravo s to kodo PIN. Sprejmite v roku {countdown} sekund.}few{{device} se želi povezati z vašo napravo s to kodo PIN. Sprejmite v roku {countdown} sekund.}other{{device} se želi povezati z vašo napravo s to kodo PIN. Sprejmite v roku {countdown} sekund.}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"Poveži"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"Prekliči"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"PIN"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"PIN"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"Naprava bo začasno prekinila povezavo z omrežjem Wi-Fi, medtem ko je povezana z napravo <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="dlg_ok" msgid="254496739491689405">"V redu"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"Povezava z omrežjem <xliff:g id="SSID">%1$s</xliff:g> ni mogoča"</string>
diff --git a/service/ServiceWifiResources/res/values-sq/strings.xml b/service/ServiceWifiResources/res/values-sq/strings.xml
index a71a892..18b379e 100644
--- a/service/ServiceWifiResources/res/values-sq/strings.xml
+++ b/service/ServiceWifiResources/res/values-sq/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"Për:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"Shkruaj PIN-in e kërkuar:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"PIN-i:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"Lidhja e pajisjes"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"Lidhja e pajisjes"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"Ftesa u dërgua te <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"Fut këtë kod PIN në <xliff:g id="DEVICE_NAME">%1$s</xliff:g> për ta lidhur."</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"Në rregull"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"Lidhja e pajisjes"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"Lidhja e pajisjes"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"Lidhja e pajisjes"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> dëshiron të lidhet me pajisjen tënde."</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"Fut kodin PIN që shfaqet në <xliff:g id="DEVICE_NAME">%1$s</xliff:g> për ta lidhur."</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> dëshiron të lidhet me pajisjen tënde me kodin e mëposhtëm PIN."</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{{device} dëshiron të lidhet me pajisjen tënde. Prano pas {countdown} sekonde.}other{{device} dëshiron të lidhet me pajisjen tënde. Prano pas {countdown} sekondash.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{Fut kodin PIN që shfaqet në {device} brenda {countdown} sekonde për ta lidhur.}other{Fut kodin PIN që shfaqet në {device} brenda {countdown} sekondash për ta lidhur.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{{device} dëshiron të lidhet me pajisjen tënde me kodin e mëposhtëm PIN. Prano pas {countdown} sekonde.}other{{device} dëshiron të lidhet me pajisjen tënde me kodin e mëposhtëm PIN. Prano pas {countdown} sekondash.}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"Lidh"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"Anulo"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"Kodi PIN"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"Kodi PIN"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"Pajisja jote do të shkëputet përkohësisht nga Wi-Fi ndërkohë që është e lidhur me <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="dlg_ok" msgid="254496739491689405">"Në rregull"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"Nuk mund të lidhet me <xliff:g id="SSID">%1$s</xliff:g>"</string>
diff --git a/service/ServiceWifiResources/res/values-sr/strings.xml b/service/ServiceWifiResources/res/values-sr/strings.xml
index 2f5a6ef..bc40eec 100644
--- a/service/ServiceWifiResources/res/values-sr/strings.xml
+++ b/service/ServiceWifiResources/res/values-sr/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"Коме:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"Унесите потребни PIN:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"PIN:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"Веза уређаја"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"Веза уређаја"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"Послат је позив за: <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"Да бисте се повезали, унесите овај PIN на уређају <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"Потврди"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"Веза уређаја"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"Веза уређаја"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"Веза уређаја"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> жели да се повеже са уређајем."</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"Да бисте се повезали, унесите PIN приказан на уређају <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> жели да се повеже са вашим уређајем помоћу следећег PIN-а."</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{{device} жели да се повеже са вашим уређајем. Прихватите за {countdown} секунду.}one{{device} жели да се повеже са вашим уређајем. Прихватите за {countdown} секунду.}few{{device} жели да се повеже са вашим уређајем. Прихватите за {countdown} секунде.}other{{device} жели да се повеже са вашим уређајем. Прихватите за {countdown} секунди.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{Да бисте се повезали, унесите PIN приказан на уређају {device} у року од {countdown} секунде.}one{Да бисте се повезали, унесите PIN приказан на уређају {device} у року од {countdown} секунде.}few{Да бисте се повезали, унесите PIN приказан на уређају {device} у року од {countdown} секунде.}other{Да бисте се повезали, унесите PIN приказан на уређају {device} у року од {countdown} секунди.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{{device} жели да се повеже са вашим уређајем помоћу следећег PIN-а. Прихватите за {countdown} секунду.}one{{device} жели да се повеже са вашим уређајем помоћу следећег PIN-а. Прихватите за {countdown} секунду.}few{{device} жели да се повеже са вашим уређајем помоћу следећег PIN-а. Прихватите за {countdown} секунде.}other{{device} жели да се повеже са вашим уређајем помоћу следећег PIN-а. Прихватите за {countdown} секунди.}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"Повежи"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"Откажи"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"PIN"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"PIN"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"Уређај ће привремено прекинути везу са WiFi мрежом док је повезан са уређајем <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="dlg_ok" msgid="254496739491689405">"Потврди"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"Повезивање на мрежу <xliff:g id="SSID">%1$s</xliff:g> није успело"</string>
diff --git a/service/ServiceWifiResources/res/values-sv/strings.xml b/service/ServiceWifiResources/res/values-sv/strings.xml
index d02a82d..d67dacd 100644
--- a/service/ServiceWifiResources/res/values-sv/strings.xml
+++ b/service/ServiceWifiResources/res/values-sv/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"Till:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"Ange den obligatoriska PIN-koden:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"PIN-kod:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"Enhetsanslutning"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"Enhetsanslutning"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"Inbjudan har skickats till <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"Ange den här pinkoden på <xliff:g id="DEVICE_NAME">%1$s</xliff:g> för att ansluta."</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"OK"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"Enhetsanslutning"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"Enhetsanslutning"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"Enhetsanslutning"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> vill ansluta till din enhet."</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"Ange pinkoden som visas på <xliff:g id="DEVICE_NAME">%1$s</xliff:g> för att ansluta."</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> vill ansluta till din enhet med följande pinkod."</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{{device} vill ansluta till din enhet. Godkänn inom {countdown} sekund.}other{{device} vill ansluta till din enhet. Godkänn inom {countdown} sekunder.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{Ange pinkoden som visas på {device} inom {countdown} sekund för att ansluta.}other{Ange pinkoden som visas på {device} inom {countdown} sekunder för att ansluta.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{{device} vill ansluta till din enhet med följande pinkod. Godkänn inom {countdown} sekund.}other{{device} vill ansluta till din enhet med följande pinkod. Godkänn inom {countdown} sekunder.}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"Anslut"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"Avbryt"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"Pinkod"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"Pinkod"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"Enheten kopplas tillfälligt från wifi när den är ansluten till <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="dlg_ok" msgid="254496739491689405">"OK"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"Det gick inte att ansluta till <xliff:g id="SSID">%1$s</xliff:g>"</string>
diff --git a/service/ServiceWifiResources/res/values-sw/strings.xml b/service/ServiceWifiResources/res/values-sw/strings.xml
index b63f476..b30efb1 100644
--- a/service/ServiceWifiResources/res/values-sw/strings.xml
+++ b/service/ServiceWifiResources/res/values-sw/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"Kwa:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"Charaza PIN inayohitajika:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"PIN:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"Muunganisho wa vifaa"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"Muunganisho wa vifaa"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"Mwaliko umetumwa kwenye <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"Weka PIN hii kwenye <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ili uunganishe."</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"Sawa"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"Muunganisho wa vifaa"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"Muunganisho wa vifaa"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"Muunganisho wa vifaa"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> inataka kuunganisha kwenye kifaa chako."</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"Weka PIN inayoonyeshwa kwenye <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ili uunganishe."</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> inataka kuunganisha kwenye kifaa chako kwa kutumia PIN ifuatayo."</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{{device} inataka kuunganisha kwenye kifaa chako. Kubali baada ya sekunde {countdown}.}other{{device} inataka kuunganisha kwenye kifaa chako. Kubali baada ya sekunde {countdown}.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{Weka PIN inayoonyeshwa kwenye {device} ndani ya sekunde {countdown} ili uunganishe.}other{Weka PIN inayoonyeshwa kwenye {device} ndani ya sekunde {countdown} ili uunganishe.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{{device} inataka kuunganisha kwenye kifaa chako kwa kutumia PIN ifuatayo. Kubali baada ya sekunde {countdown}.}other{{device} inataka kuunganisha kwenye kifaa chako kwa kutumia PIN ifuatayo. Kubali baada ya sekunde {countdown}.}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"Unganisha"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"Acha"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"PIN"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"PIN"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"Kifaa chako kitatenganishwa na Wi-Fi kwa muda wakati kimeunganishwa kwenye <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="dlg_ok" msgid="254496739491689405">"Sawa"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"Imeshindwa kuunganisha kwenye <xliff:g id="SSID">%1$s</xliff:g>"</string>
diff --git a/service/ServiceWifiResources/res/values-ta/strings.xml b/service/ServiceWifiResources/res/values-ta/strings.xml
index 005dfe5..ac64422 100644
--- a/service/ServiceWifiResources/res/values-ta/strings.xml
+++ b/service/ServiceWifiResources/res/values-ta/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"பெறுநர்:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"பின்வரும் அவசியமான பின்னை உள்ளிடவும்:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"பின்:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"சாதன இணைப்பு"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"சாதன இணைப்பு"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> சாதனத்திற்கு அழைப்பு அனுப்பப்பட்டது."</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"இணைப்பதற்கு இந்தப் பின்னை <xliff:g id="DEVICE_NAME">%1$s</xliff:g> சாதனத்தில் டைப் செய்யவும்."</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"சரி"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"சாதன இணைப்பு"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"சாதன இணைப்பு"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"சாதன இணைப்பு"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"உங்கள் சாதனத்துடன் இணைக்கும்படி <xliff:g id="DEVICE_NAME">%1$s</xliff:g> கேட்கிறது."</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"இணைப்பதற்கு <xliff:g id="DEVICE_NAME">%1$s</xliff:g> சாதனத்தில் கட்டப்படும் பின்னை டைப் செய்யவும்."</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"காட்டப்படும் பின்னைக் கொண்டு உங்கள் சாதனத்துடன் இணைக்கும்படி <xliff:g id="DEVICE_NAME">%1$s</xliff:g> கேட்கிறது."</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{உங்கள் சாதனத்துடன் இணைக்கும்படி {device} கேட்கிறது. {countdown} வினாடியில் ஏற்கவும்.}other{உங்கள் சாதனத்துடன் இணைக்கும்படி {device} கேட்கிறது. {countdown} வினாடிகளில் ஏற்கவும்.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{இணைப்பதற்கு {device} சாதனத்தில் காட்டப்படும் பின்னை {countdown} வினாடிக்குள் டைப் செய்யவும்.}other{இணைப்பதற்கு {device} சாதனத்தில் காட்டப்படும் பின்னை {countdown} வினாடிகளுக்குள் டைப் செய்யவும்.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{காட்டப்படும் பின்னைக் கொண்டு உங்கள் சாதனத்துடன் இணைக்கும்படி {device} கேட்கிறது. {countdown} வினாடியில் ஏற்கவும்.}other{காட்டப்படும் பின்னைக் கொண்டு உங்கள் சாதனத்துடன் இணைக்கும்படி {device} கேட்கிறது. {countdown} வினாடிகளில் ஏற்கவும்.}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"இணை"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"ரத்துசெய்"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"பின்"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"பின்"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> உடன் இணைக்கப்பட்டிருக்கும்போது உங்கள் சாதனம் வைஃபை இணைப்பில் இருந்து தற்காலிகமாகத் துண்டிக்கப்படும்"</string>
<string name="dlg_ok" msgid="254496739491689405">"சரி"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"<xliff:g id="SSID">%1$s</xliff:g> உடன் இணைக்க முடியவில்லை"</string>
diff --git a/service/ServiceWifiResources/res/values-te/strings.xml b/service/ServiceWifiResources/res/values-te/strings.xml
index ec40546..baa4146 100644
--- a/service/ServiceWifiResources/res/values-te/strings.xml
+++ b/service/ServiceWifiResources/res/values-te/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"వీరికి:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"అవసరమైన పిన్ను టైప్ చేయండి:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"పిన్:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"పరికర కనెక్షన్"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"పరికర కనెక్షన్"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>కు ఆహ్వానం పంపబడింది."</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"కనెక్ట్ చేయడానికి ఈ PINను <xliff:g id="DEVICE_NAME">%1$s</xliff:g>లో ఎంటర్ చేయండి."</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"సరే"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"పరికర కనెక్షన్"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"పరికర కనెక్షన్"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"పరికర కనెక్షన్"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> మీ పరికరానికి కనెక్ట్ చేయాలనుకుంటున్నారు."</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"కనెక్ట్ చేయడానికి <xliff:g id="DEVICE_NAME">%1$s</xliff:g>లో కనిపించే PINను ఎంటర్ చేయండి."</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>, కింద ఉన్న PINను ఉపయోగించి మీ పరికరానికి కనెక్ట్ చేయాలనుకుంటున్నారు."</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{{device} మీ పరికరానికి కనెక్ట్ చేయాలనుకుంటున్నారు. {countdown} సెకనులో ఆమోదించండి.}other{{device} మీ పరికరానికి కనెక్ట్ చేయాలనుకుంటున్నారు. {countdown} సెకన్లలో ఆమోదించండి.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{కనెక్ట్ చేయడానికి {countdown}లో {device}లో కనిపించే PINను ఎంటర్ చేయండి.}other{కనెక్ట్ చేయడానికి {countdown}లో {device}లో కనిపించే PINను ఎంటర్ చేయండి.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{{device}, కింద ఉన్న PINను ఉపయోగించి మీ పరికరంతో కనెక్ట్ చేయాలనుకుంటున్నారు. {countdown} సెకనులో ఆమోదించండి.}other{{device}, కింద ఉన్న PINను ఉపయోగించి మీ పరికరంతో కనెక్ట్ చేయాలనుకుంటున్నారు. {countdown} సెకన్లలో ఆమోదించండి.}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"కనెక్ట్ చేయండి"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"రద్దు చేయండి"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"PIN"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"PIN"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"మీ పరికరం <xliff:g id="DEVICE_NAME">%1$s</xliff:g>కి కనెక్ట్ అయి ఉన్నప్పుడు తాత్కాలికంగా Wi-Fi నుండి డిస్కనెక్ట్ అవుతుంది"</string>
<string name="dlg_ok" msgid="254496739491689405">"సరే"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"<xliff:g id="SSID">%1$s</xliff:g>కు కనెక్ట్ చేయడం సాధ్యపడదు"</string>
diff --git a/service/ServiceWifiResources/res/values-th/strings.xml b/service/ServiceWifiResources/res/values-th/strings.xml
index 0958cc3..69965b0 100644
--- a/service/ServiceWifiResources/res/values-th/strings.xml
+++ b/service/ServiceWifiResources/res/values-th/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"ถึง:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"พิมพ์ PIN ที่ต้องการ:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"PIN:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"การเชื่อมต่อของอุปกรณ์"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"การเชื่อมต่อของอุปกรณ์"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"ส่งข้อความเชิญถึง <xliff:g id="DEVICE_NAME">%1$s</xliff:g> แล้ว"</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"ป้อน PIN นี้ลงใน <xliff:g id="DEVICE_NAME">%1$s</xliff:g> เพื่อเชื่อมต่อ"</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"ตกลง"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"การเชื่อมต่อของอุปกรณ์"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"การเชื่อมต่อของอุปกรณ์"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"การเชื่อมต่อของอุปกรณ์"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> ต้องการเชื่อมต่อกับอุปกรณ์ของคุณ"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"ป้อน PIN ที่แสดงบน <xliff:g id="DEVICE_NAME">%1$s</xliff:g> เพื่อเชื่อมต่อ"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> ต้องการเชื่อมต่อกับอุปกรณ์ของคุณด้วย PIN ต่อไปนี้"</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{{device} ต้องการเชื่อมต่อกับอุปกรณ์ของคุณ ตอบรับภายใน {countdown} วินาที}other{{device} ต้องการเชื่อมต่อกับอุปกรณ์ของคุณ ตอบรับภายใน {countdown} วินาที}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{ป้อน PIN ที่แสดงบน {device} ภายใน {countdown} วินาทีเพื่อเชื่อมต่อ}other{ป้อน PIN ที่แสดงบน {device} ภายใน {countdown} วินาทีเพื่อเชื่อมต่อ}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{{device} ต้องการเชื่อมต่อกับอุปกรณ์ของคุณด้วย PIN ต่อไปนี้ ตอบรับภายใน {countdown} วินาที}other{{device} ต้องการเชื่อมต่อกับอุปกรณ์ของคุณด้วย PIN ต่อไปนี้ ตอบรับภายใน {countdown} วินาที}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"เชื่อมต่อ"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"ยกเลิก"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"PIN"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"PIN"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"อุปกรณ์ของคุณจะยกเลิกการเชื่อมต่อ Wi-Fi ชั่วคราวระหว่างที่เชื่อมต่อกับ <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="dlg_ok" msgid="254496739491689405">"ตกลง"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"เชื่อมต่อกับ <xliff:g id="SSID">%1$s</xliff:g> ไม่ได้"</string>
diff --git a/service/ServiceWifiResources/res/values-tl/strings.xml b/service/ServiceWifiResources/res/values-tl/strings.xml
index 7b16618..cff9e64 100644
--- a/service/ServiceWifiResources/res/values-tl/strings.xml
+++ b/service/ServiceWifiResources/res/values-tl/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"Kay:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"I-type ang kinakailangang PIN:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"PIN:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"Koneksyon ng device"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"Koneksyon ng device"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"Naipadala ang imbitasyon kay <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"Ilagay ang PIN na ito sa <xliff:g id="DEVICE_NAME">%1$s</xliff:g> para kumonekta."</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"OK"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"Koneksyon ng device"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"Koneksyon ng device"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"Koneksyon ng device"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"Gustong kumonekta ng <xliff:g id="DEVICE_NAME">%1$s</xliff:g> sa iyong device."</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"Ilagay ang ipinapakitang PIN sa <xliff:g id="DEVICE_NAME">%1$s</xliff:g> para kumonekta."</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"Gustong kumonekta ng <xliff:g id="DEVICE_NAME">%1$s</xliff:g> sa iyong device gamit ang sumusunod na PIN."</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{Gustong kumonekta ng {device} sa iyong device. Tanggapin sa loob ng {countdown} segundo.}one{Gustong kumonekta ng {device} sa iyong device. Tanggapin sa loob ng {countdown} segundo.}other{Gustong kumonekta ng {device} sa iyong device. Tanggapin sa loob ng {countdown} na segundo.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{Ilagay ang PIN na ipinapakita sa {device} sa loob ng {countdown} segundo para kumonekta.}one{Ilagay ang PIN na ipinapakita sa {device} sa loob ng {countdown} segundo para kumonekta.}other{Ilagay ang PIN na ipinapakita sa {device} sa loob ng {countdown} na segundo para kumonekta.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{Gustong kumonekta ng {device} sa iyong device gamit ang sumusunod na PIN. Tanggapin sa loob ng {countdown} segundo.}one{Gustong kumonekta ng {device} sa iyong device gamit ang sumusunod na PIN. Tanggapin sa loob ng {countdown} segundo.}other{Gustong kumonekta ng {device} sa iyong device gamit ang sumusunod na PIN. Tanggapin sa loob ng {countdown} na segundo.}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"Kumonekta"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"Kanselahin"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"PIN"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"PIN"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"Pansamantalang madidiskonekta sa Wi-Fi ang iyong device habang nakakonekta ito sa <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="dlg_ok" msgid="254496739491689405">"OK"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"Hindi makakonekta sa <xliff:g id="SSID">%1$s</xliff:g>"</string>
diff --git a/service/ServiceWifiResources/res/values-tr/strings.xml b/service/ServiceWifiResources/res/values-tr/strings.xml
index efc4d1b..917f23c 100644
--- a/service/ServiceWifiResources/res/values-tr/strings.xml
+++ b/service/ServiceWifiResources/res/values-tr/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"Alıcı:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"Gerekli PIN\'i yazın:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"PIN:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"Cihaz bağlantısı"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"Cihaz bağlantısı"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"Davetin <xliff:g id="DEVICE_NAME">%1$s</xliff:g> cihazına gönderildi."</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"Bağlanmak için bu PIN\'i <xliff:g id="DEVICE_NAME">%1$s</xliff:g> cihazına girin."</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"Tamam"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"Cihaz bağlantısı"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"Cihaz bağlantısı"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"Cihaz bağlantısı"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>, cihazınıza bağlanmak istiyor."</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"Bağlanmak için <xliff:g id="DEVICE_NAME">%1$s</xliff:g> cihazında gösterilen PIN\'i girin."</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>, aşağıdaki PIN\'i kullanarak cihazınıza bağlanmak istiyor."</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{{device}, cihazınıza bağlanmak istiyor. {countdown} saniye içinde kabul edin.}other{{device}, cihazınıza bağlanmak istiyor. {countdown} saniye içinde kabul edin.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{Bağlanmak için {device} cihazında gösterilen PIN\'i {countdown} saniye içinde girin.}other{Bağlanmak için {device} cihazında gösterilen PIN\'i {countdown} saniye içinde girin.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{{device}, aşağıdaki PIN\'i kullanarak cihazınıza bağlanmak istiyor. {countdown} saniye içinde kabul edin.}other{{device}, aşağıdaki PIN\'i kullanarak cihazınıza bağlanmak istiyor. {countdown} saniye içinde kabul edin.}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"Bağlan"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"İptal"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"PIN"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"PIN"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"Cihazınız <xliff:g id="DEVICE_NAME">%1$s</xliff:g> adlı cihaza bağlıyken kablosuz bağlantısı geçici olarak kesilecek"</string>
<string name="dlg_ok" msgid="254496739491689405">"Tamam"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"<xliff:g id="SSID">%1$s</xliff:g> ağına bağlanılamıyor"</string>
diff --git a/service/ServiceWifiResources/res/values-uk/strings.xml b/service/ServiceWifiResources/res/values-uk/strings.xml
index 456be30..e73df0a 100644
--- a/service/ServiceWifiResources/res/values-uk/strings.xml
+++ b/service/ServiceWifiResources/res/values-uk/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"Кому:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"Введіть потрібний PIN-код:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"PIN-код:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"Підключення пристрою"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"Підключення пристрою"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"Запрошення надіслано на пристрій \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\"."</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"Щоб підключитися, введіть цей PIN-код на пристрої \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\"."</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"OK"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"Підключення пристрою"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"Підключення пристрою"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"Підключення пристрою"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"Пристрій \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\" хоче підключитися до вашого пристрою."</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"Щоб підключитися, введіть PIN-код, який відображається на екрані пристрою \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\"."</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"Пристрій \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\" хоче підключитися до вашого пристрою за допомогою вказаного нижче PIN-коду."</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{Пристрій \"{device}\" хоче підключитися до вашого пристрою. У вас є {countdown} секунда, щоб прийняти запит.}one{Пристрій \"{device}\" хоче підключитися до вашого пристрою. У вас є {countdown} секунда, щоб прийняти запит.}few{Пристрій \"{device}\" хоче підключитися до вашого пристрою. У вас є {countdown} секунди, щоб прийняти запит.}many{Пристрій \"{device}\" хоче підключитися до вашого пристрою. У вас є {countdown} секунд, щоб прийняти запит.}other{Пристрій \"{device}\" хоче підключитися до вашого пристрою. У вас є {countdown} секунди, щоб прийняти запит.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{Щоб підключитися, протягом {countdown} секунди введіть PIN-код, який відображається на екрані пристрою \"{device}\".}one{Щоб підключитися, протягом {countdown} секунди введіть PIN-код, який відображається на екрані пристрою \"{device}\".}few{Щоб підключитися, протягом {countdown} секунд введіть PIN-код, який відображається на екрані пристрою \"{device}\".}many{Щоб підключитися, протягом {countdown} секунд введіть PIN-код, який відображається на екрані пристрою \"{device}\".}other{Щоб підключитися, протягом {countdown} секунди введіть PIN-код, який відображається на екрані пристрою \"{device}\".}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{Пристрій \"{device}\" хоче підключитися до вашого пристрою за допомогою вказаного нижче PIN-коду. У вас є {countdown} секунда, щоб прийняти запит.}one{Пристрій \"{device}\" хоче підключитися до вашого пристрою за допомогою вказаного нижче PIN-коду. У вас є {countdown} секунда, щоб прийняти запит.}few{Пристрій \"{device}\" хоче підключитися до вашого пристрою за допомогою вказаного нижче PIN-коду. У вас є {countdown} секунди, щоб прийняти запит.}many{Пристрій \"{device}\" хоче підключитися до вашого пристрою за допомогою вказаного нижче PIN-коду. У вас є {countdown} секунд, щоб прийняти запит.}other{Пристрій \"{device}\" хоче підключитися до вашого пристрою за допомогою вказаного нижче PIN-коду. У вас є {countdown} секунди, щоб прийняти запит.}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"Підключити"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"Скасувати"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"PIN-код"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"PIN-код"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"На час підключення до пристрою \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\" ваш пристрій буде від’єднано від мережі Wi-Fi"</string>
<string name="dlg_ok" msgid="254496739491689405">"OK"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"Не вдалося підключитися до мережі \"<xliff:g id="SSID">%1$s</xliff:g>\""</string>
diff --git a/service/ServiceWifiResources/res/values-ur/strings.xml b/service/ServiceWifiResources/res/values-ur/strings.xml
index d96adba..25f2a7a 100644
--- a/service/ServiceWifiResources/res/values-ur/strings.xml
+++ b/service/ServiceWifiResources/res/values-ur/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"بنام:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"مطلوبہ PIN ٹائپ کریں:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"PIN:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"آلے کا کنکشن"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"آلے کا کنکشن"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> کو دعوت نامہ بھیج دیا گیا ہے۔"</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"منسلک ہونے کے لیے <xliff:g id="DEVICE_NAME">%1$s</xliff:g> پر یہ PIN درج کریں۔"</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"ٹھیک ہے"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"آلے کا کنکشن"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"آلے کا کنکشن"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"آلے کا کنکشن"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> آپ کے آلے سے منسلک ہونا چاہتا ہے۔"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"منسلک ہونے کے لیے <xliff:g id="DEVICE_NAME">%1$s</xliff:g> پر دکھایا گیا PIN درج کریں۔"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> درج ذیل PIN کی مدد سے آپ کے آلے سے منسلک ہونا چاہتا ہے۔"</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{{device} آپ کے آلے سے منسلک ہونا چاہتا ہے۔ {countdown} سیکنڈ میں قبول کریں۔}other{{device} آپ کے آلے سے منسلک ہونا چاہتا ہے۔ {countdown} سیکنڈ میں قبول کریں۔}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{منسلک ہونے کے لیے {countdown} سیکنڈ کے اندر {device} پر دکھایا گیا PIN درج کریں۔}other{منسلک ہونے کے لیے {countdown} سیکنڈ کے اندر {device} پر دکھایا گیا PIN درج کریں۔}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{{device} درج ذیل PIN کی مدد سے آپ کے آلے سے منسلک ہونا چاہتا ہے۔ {countdown} سیکنڈ میں قبول کریں۔}other{{device} درج ذیل PIN کی مدد سے آپ کے آلے سے منسلک ہونا چاہتا ہے۔ {countdown} سیکنڈ میں قبول کریں۔}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"منسلک کریں"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"منسوخ کریں"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"PIN"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"PIN"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"آپ کا آلہ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> سے منسلک ہونے پر، عارضی طور پر Wi-Fi سے غیر منسلک ہو جائے گا"</string>
<string name="dlg_ok" msgid="254496739491689405">"ٹھیک ہے"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"<xliff:g id="SSID">%1$s</xliff:g> سے منسلک نہیں کر سکتے"</string>
diff --git a/service/ServiceWifiResources/res/values-uz/strings.xml b/service/ServiceWifiResources/res/values-uz/strings.xml
index ebd27bd..0d705fb 100644
--- a/service/ServiceWifiResources/res/values-uz/strings.xml
+++ b/service/ServiceWifiResources/res/values-uz/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"Kimga:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"So‘ralgan PIN kodni kiriting:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"PIN kod:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"Qurilma aloqasi"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"Qurilma aloqasi"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"Taklifnoma yuborildi: <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"Ulash uchun <xliff:g id="DEVICE_NAME">%1$s</xliff:g> qurilmasida bu PIN kodni kiriting."</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"OK"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"Qurilma aloqasi"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"Qurilma aloqasi"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"Qurilma aloqasi"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> sizning qurilmangizga ulanmoqchi."</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"Ulash uchun <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ekranidagi PIN kodni kiriting."</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> sizning qurilmangizga mazkur PIN kod orqali ulanmoqchi."</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{{device} sizning qurilmangizga ulanmoqchi. {countdown} soniya ichida qabul qiling.}other{{device} sizning qurilmangizga ulanmoqchi. {countdown} soniya ichida qabul qiling.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{Ulash uchun {device} ekranidagi PIN kodni {countdown} soniya ichida kiriting.}other{Ulash uchun {device} ekranidagi PIN kodni {countdown} soniya ichida kiriting.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{{device} sizning qurilmangizga mazkur PIN kod orqali ulanmoqchi. {countdown} soniya ichida qabul qiling.}other{{device} sizning qurilmangizga mazkur PIN kod orqali ulanmoqchi. {countdown} soniya ichida qabul qiling.}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"Ulash"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"Bekor qilish"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"PIN kod"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"PIN kod"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"Qurilmangiz <xliff:g id="DEVICE_NAME">%1$s</xliff:g> qurilmasiga ulangani uchun u vaqtincha Wi-Fi tarmoqdan uzildi."</string>
<string name="dlg_ok" msgid="254496739491689405">"OK"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"<xliff:g id="SSID">%1$s</xliff:g> bilan aloqa oʻrnatilmadi"</string>
diff --git a/service/ServiceWifiResources/res/values-vi/strings.xml b/service/ServiceWifiResources/res/values-vi/strings.xml
index bd2e416..511890b 100644
--- a/service/ServiceWifiResources/res/values-vi/strings.xml
+++ b/service/ServiceWifiResources/res/values-vi/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"Người nhận:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"Nhập PIN bắt buộc:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"Mã PIN:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"Kết nối thiết bị"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"Kết nối thiết bị"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"Lời mời đã được gửi tới <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"Nhập mã PIN này trên <xliff:g id="DEVICE_NAME">%1$s</xliff:g> để kết nối."</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"OK"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"Kết nối thiết bị"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"Kết nối thiết bị"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"Kết nối thiết bị"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> muốn kết nối với thiết bị của bạn."</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"Nhập mã PIN hiển thị trên <xliff:g id="DEVICE_NAME">%1$s</xliff:g> để kết nối."</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> muốn kết nối với thiết bị của bạn bằng mã PIN sau đây."</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{{device} muốn kết nối với thiết bị của bạn. Chấp nhận sau {countdown} giây.}other{{device} muốn kết nối với thiết bị của bạn. Chấp nhận sau {countdown} giây.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{Nhập mã PIN hiển thị trên {device} trong vòng {countdown} giây để kết nối.}other{Nhập mã PIN hiển thị trên {device} trong vòng {countdown} giây để kết nối.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{{device} muốn kết nối với thiết bị của bạn bằng mã PIN sau đây. Chấp nhận sau {countdown} giây.}other{{device} muốn kết nối với thiết bị của bạn bằng mã PIN sau đây. Chấp nhận sau {countdown} giây.}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"Kết nối"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"Huỷ"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"Mã PIN"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"Mã PIN"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"Thiết bị của bạn sẽ tạm thời ngắt kết nối với Wi-Fi trong khi kết nối với <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="dlg_ok" msgid="254496739491689405">"OK"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"Không thể kết nối với <xliff:g id="SSID">%1$s</xliff:g>"</string>
diff --git a/service/ServiceWifiResources/res/values-zh-rCN/strings.xml b/service/ServiceWifiResources/res/values-zh-rCN/strings.xml
index 5a0871e..397a5cd 100644
--- a/service/ServiceWifiResources/res/values-zh-rCN/strings.xml
+++ b/service/ServiceWifiResources/res/values-zh-rCN/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"收件人:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"输入所需的PIN码:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"PIN 码:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"设备连接"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"设备连接"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"已向“<xliff:g id="DEVICE_NAME">%1$s</xliff:g>”发送邀请。"</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"请在“<xliff:g id="DEVICE_NAME">%1$s</xliff:g>”上输入此 PIN 码以建立连接。"</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"确定"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"设备连接"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"设备连接"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"设备连接"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"“<xliff:g id="DEVICE_NAME">%1$s</xliff:g>”想要连接到您的设备。"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"请输入“<xliff:g id="DEVICE_NAME">%1$s</xliff:g>”上显示的 PIN 码以建立连接。"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"“<xliff:g id="DEVICE_NAME">%1$s</xliff:g>”想要使用以下 PIN 码连接到您的设备。"</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{“{device}”想要连接到您的设备。{countdown} 秒后接受。}other{“{device}”想要连接到您的设备。{countdown} 秒后接受。}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{请在 {countdown} 秒内输入“{device}”上显示的 PIN 码以建立连接。}other{请在 {countdown} 秒内输入“{device}”上显示的 PIN 码以建立连接。}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{“{device}”想要使用以下 PIN 码连接到您的设备。{countdown} 秒后接受。}other{“{device}”想要使用以下 PIN 码连接到您的设备。{countdown} 秒后接受。}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"连接"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"取消"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"PIN 码"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"PIN 码"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"当设备连接到<xliff:g id="DEVICE_NAME">%1$s</xliff:g>时,它会暂时断开 WLAN 连接"</string>
<string name="dlg_ok" msgid="254496739491689405">"确定"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"无法连接到“<xliff:g id="SSID">%1$s</xliff:g>”"</string>
diff --git a/service/ServiceWifiResources/res/values-zh-rHK/strings.xml b/service/ServiceWifiResources/res/values-zh-rHK/strings.xml
index 6353117..743108a 100644
--- a/service/ServiceWifiResources/res/values-zh-rHK/strings.xml
+++ b/service/ServiceWifiResources/res/values-zh-rHK/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"收件者:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"請輸入必要的 PIN 碼:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"PIN 碼:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"裝置連線"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"裝置連線"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"已傳送邀請至「<xliff:g id="DEVICE_NAME">%1$s</xliff:g>」。"</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"在「<xliff:g id="DEVICE_NAME">%1$s</xliff:g>」上輸入此 PIN 即可連線。"</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"確定"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"裝置連線"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"裝置連線"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"裝置連線"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"「<xliff:g id="DEVICE_NAME">%1$s</xliff:g>」想連結你的裝置。"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"輸入「<xliff:g id="DEVICE_NAME">%1$s</xliff:g>」上顯示的 PIN 即可建立連結。"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"「<xliff:g id="DEVICE_NAME">%1$s</xliff:g>」想透過以下 PIN 連結你的裝置。"</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{「{device}」想連結你的裝置。請於 {countdown} 秒內接受。}other{「{device}」想連結你的裝置。請於 {countdown} 秒內接受。}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{於 {countdown} 秒內輸入「{device}」上顯示的 PIN,即可建立連結。}other{於 {countdown} 秒內輸入「{device}」上顯示的 PIN,即可建立連結。}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{「{device}」想透過以下 PIN 連結你的裝置。請於 {countdown} 秒內接受。}other{「{device}」想透過以下 PIN 連結你的裝置。請於 {countdown} 秒內接受。}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"連線"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"取消"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"PIN"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"PIN"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"裝置與「<xliff:g id="DEVICE_NAME">%1$s</xliff:g>」連線期間將暫時中斷 Wi-Fi 連線"</string>
<string name="dlg_ok" msgid="254496739491689405">"確定"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"無法連接「<xliff:g id="SSID">%1$s</xliff:g>」"</string>
diff --git a/service/ServiceWifiResources/res/values-zh-rTW/strings.xml b/service/ServiceWifiResources/res/values-zh-rTW/strings.xml
index 6aed027..ca5f2df 100644
--- a/service/ServiceWifiResources/res/values-zh-rTW/strings.xml
+++ b/service/ServiceWifiResources/res/values-zh-rTW/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"收件者:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"請輸入必要的 PIN:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"PIN 碼:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"裝置連線"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"裝置連線"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"已傳送邀請至「<xliff:g id="DEVICE_NAME">%1$s</xliff:g>」。"</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"在「<xliff:g id="DEVICE_NAME">%1$s</xliff:g>」上輸入這個 PIN 碼即可連線。"</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"確定"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"裝置連線"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"裝置連線"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"裝置連線"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"「<xliff:g id="DEVICE_NAME">%1$s</xliff:g>」想連結你的裝置。"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"輸入「<xliff:g id="DEVICE_NAME">%1$s</xliff:g>」上顯示的 PIN 碼即可建立連結。"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"「<xliff:g id="DEVICE_NAME">%1$s</xliff:g>」想透過下列 PIN 碼連結你的裝置。"</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{「{device}」想連結你的裝置,請在 {countdown} 秒內接受。}other{「{device}」想連結你的裝置,請在 {countdown} 秒內接受。}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{在 {countdown} 秒內輸入「{device}」顯示的 PIN 碼,即可建立連結。}other{在 {countdown} 秒內輸入「{device}」顯示的 PIN 碼,即可建立連結。}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{「{device}」想透過下列 PIN 碼連結你的裝置,請在 {countdown} 秒內接受。}other{「{device}」想透過下列 PIN 碼連結你的裝置,請在 {countdown} 秒內接受。}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"連線"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"取消"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"PIN 碼"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"PIN 碼"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"裝置與「<xliff:g id="DEVICE_NAME">%1$s</xliff:g>」連線期間將暫時中斷 Wi-Fi 連線"</string>
<string name="dlg_ok" msgid="254496739491689405">"確定"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"無法連線至「<xliff:g id="SSID">%1$s</xliff:g>」"</string>
diff --git a/service/ServiceWifiResources/res/values-zu/strings.xml b/service/ServiceWifiResources/res/values-zu/strings.xml
index 5820703..14a732d 100644
--- a/service/ServiceWifiResources/res/values-zu/strings.xml
+++ b/service/ServiceWifiResources/res/values-zu/strings.xml
@@ -60,6 +60,24 @@
<string name="wifi_p2p_to_message" msgid="3809923305696994787">"Ku:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5200220251738047620">"Faka i-PIN edingekayo:"</string>
<string name="wifi_p2p_show_pin_message" msgid="1000091690967930798">"PIN:"</string>
+ <string name="wifi_p2p_dialog2_sent_title" msgid="2336103322429678328">"Uxhumo lwedivayisi"</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin" msgid="511248898541903515">"Uxhumo lwedivayisi"</string>
+ <string name="wifi_p2p_dialog2_sent_message" msgid="2544736217133674163">"Isimemo sithunyelwe ku-<xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin" msgid="5017076731258834940">"Faka le Phinikhodi ku-<xliff:g id="DEVICE_NAME">%1$s</xliff:g> ukuze uxhumeke."</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button" msgid="6464227471745156497">"KULUNGILE"</string>
+ <string name="wifi_p2p_dialog2_received_title" msgid="6897349204607457747">"Uxhumo lwedivayisi"</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin" msgid="6431543271224139601">"Uxhumo lwedivayisi"</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin" msgid="5017007825248741433">"Uxhumo lwedivayisi"</string>
+ <string name="wifi_p2p_dialog2_received_message" msgid="4376275522073306499">"I-<xliff:g id="DEVICE_NAME">%1$s</xliff:g> ifuna ukuxhumana nedivayisi yakho."</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin" msgid="6070908860523284394">"Faka Iphinikhodi eboniswe ku-<xliff:g id="DEVICE_NAME">%1$s</xliff:g> ukuze uxhumeke."</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin" msgid="5906560549535982131">"I-<xliff:g id="DEVICE_NAME">%1$s</xliff:g> ifuna ukuxhumana nedivayisi yakho Ngephinikhodi elandelayo."</string>
+ <string name="wifi_p2p_dialog2_received_message_countdown" msgid="557930403509771814">"{countdown,plural, =1{I-{device} ifuna ukuxhumana nedivayisi yakho. Yamukela kumzuzwana ongu-{countdown}.}one{I-{device} ifuna ukuxhumana nedivayisi yakho. Yamukela emizuzwaneni engu-{countdown}.}other{I-{device} ifuna ukuxhumana nedivayisi yakho. Yamukela emizuzwaneni engu-{countdown}.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown" msgid="3723666737782219820">"{countdown,plural, =1{Faka Iphinikhodi eboniswe ku-{device} kumzuzwana ongu-{countdown} ukuze uxhumeke.}one{Faka Iphinikhodi eboniswe ku-{device} emizuzwaneni engu-{countdown} ukuze uxhumeke.}other{Faka Iphinikhodi eboniswe ku-{device} emizuzwaneni engu-{countdown} ukuze uxhumeke.}}"</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown" msgid="1248395771858360837">"{countdown,plural, =1{I-{device} ifuna ukuxhumana nedivayisi yakho Ngephinikhodi elandelayo. Yamukela kumzuzwana ongu-{countdown}.}one{I-{device} ifuna ukuxhumana nedivayisi yakho Ngephinikhodi elandelayo. Yamukela emizuzwaneni engu-{countdown}.}other{I-{device} ifuna ukuxhumana nedivayisi yakho Ngephinikhodi elandelayo. Yamukela emizuzwaneni engu-{countdown}.}}"</string>
+ <string name="wifi_p2p_dialog2_received_positive_button" msgid="6358592617824573781">"Xhuma"</string>
+ <string name="wifi_p2p_dialog2_received_negative_button" msgid="4762549789911681138">"Khansela"</string>
+ <string name="wifi_p2p_dialog2_enter_pin_label" msgid="7410100924400114335">"Iphinikhodi"</string>
+ <string name="wifi_p2p_dialog2_display_pin_label" msgid="3929561425167093538">"Iphinikhodi"</string>
<string name="wifi_p2p_frequency_conflict_message" msgid="8535404941723941766">"Idivayisi yakho izonqamuka okwesikhashana ku-Wi-Fi ngenkathi uxhume ku-<xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="dlg_ok" msgid="254496739491689405">"KULUNGILE"</string>
<string name="wifi_cannot_connect_with_randomized_mac_title" msgid="2344570489693915253">"Ayikwazi ukuxhumeka ku-<xliff:g id="SSID">%1$s</xliff:g>"</string>
diff --git a/service/ServiceWifiResources/res/values/config.xml b/service/ServiceWifiResources/res/values/config.xml
index aaaa4ab..5390b48 100644
--- a/service/ServiceWifiResources/res/values/config.xml
+++ b/service/ServiceWifiResources/res/values/config.xml
@@ -1060,6 +1060,8 @@
<!-- Indicate the time in milliseconds to wait before auto-cancelling a P2P invitation received
dialog that the user has not responded to. A value of 0 indicates no timeout. -->
<integer translatable="false" name="config_p2pInvitationReceivedDialogTimeoutMs">0</integer>
+ <!-- Whether to show the timeout in the P2P invitation received dialog -->
+ <bool translatable="false" name="config_p2pInvitationReceivedDialogShowRemainingTime">true</bool>
<!-- Indicates whether or not to play a notification sound upon displaying a P2P invitation
received dialog that the user has not responded to. If the device is in vibrate mode, then
the device will vibrate instead of playing a sound. -->
@@ -1112,6 +1114,14 @@
<item>com.company2.example.test.name2</item>
-->
</string-array>
+ <!-- list of package names that the framework will allow to use SoftAp/Aware concurrency. If
+ this list is empty, then all packages are allowed -->
+ <string-array translatable="false" name="config_wifiSoftApAwareConcurrencyAllowlist">
+ <!-- Below is a sample configuration for this list:
+ <item>com.company1.example.test.name1</item>
+ <item>com.company2.example.test.name2</item>
+ -->
+ </string-array>
<!-- boolean indicating whether the Easy Connect (DPP) AKM is supported -->
<bool translatable="false" name ="config_wifiDppAkmSupported">false</bool>
<!-- Indicates the number of octets to mask for each BSSID in the SecurityLog output.
@@ -1344,7 +1354,19 @@
-->
</integer-array>
- <!-- Wi-Fi chip supports single link MLO SoftAp instances in the bridged mode -->
+
+ <!-- integer indicating the maximum number of MLDs supported for multi-link operation (MLO)
+ SoftAp. Each multi-link device (AP MLD) can be operated with multiple links or single link.
+ It is required to configure it at least 1 for multiple links MLO SoftAp. Default value 0 is
+ treated as device does NOT support multiple links MLO SoftAp and the maximum
+ number of MLDs is decided by configuration, config_wifiSoftApSingleLinkMloInBridgedModeSupported.
+ (i.e. 2 when config_wifiSoftApSingleLinkMloInBridgedModeSupported is true and 1 when
+ config_wifiSoftApSingleLinkMloInBridgedModeSupported is false.)
+ -->
+ <integer translatable="false" name="config_wifiSoftApMaxNumberMLDSupported">0</integer>
+
+ <!-- (Deprecated) Wi-Fi chip supports single link MLO SoftAp instances in the bridged mode.
+ The value will be used only when config_wifiSoftApMaxNumberMLDSupported isn't configured -->
<bool translatable="false" name="config_wifiSoftApSingleLinkMloInBridgedModeSupported">false</bool>
<!-- Boolean indicating whether Target Wake Time (TWT) feature is supported or not. This flag
@@ -1364,7 +1386,11 @@
feature are included in the array by default.
-->
<integer-array translatable="false" name="config_wifiDelayedSelectionCarrierIds">
- <item>2032</item>
+
+ <!-- Below is a sample configuration for this list:
+ <item>1234</item>
+ <item>5678</item>
+ -->
</integer-array>
<!-- Delay time in milliseconds for delayed carrier network selection.
@@ -1374,8 +1400,19 @@
<!-- Boolean indicating whether the device supports Wi-Fi Alliance WPA3 Specification
version 3.3 Section 14 - RSN Overriding.
- Enabling this config allows framework to parse the RSNO IE and RSNO2 IE.
- Only enable this flag if Supplicant and driver/firmware supports RSN Overriding. otherwise
- the connection may fail or downgrade to WPA2 -->
+ Enabling this config allows framework to parse the RSNO IE and RSNO2 IE on devices running
+ Supplicant AIDL interface version lower than 4. Only enable this flag if Supplicant and
+ driver/firmware supports RSN Overriding. otherwise the connection may fail or downgrade to
+ WPA2.
+ If the device is running the AIDL interface version 4 or later, this config item has
+ no effect. The feature will be enabled/disabled based on the chip capability for RSN
+ Overriding advertised via Supplicant AIDL wpa driver capability interface -->
<bool translatable="false" name ="config_wifiRsnOverridingEnabled">false</bool>
+
+ <!-- Boolean indicating whether to trigger bugreport for WiFi subsystem restart issue -->
+ <bool translatable="false" name ="config_wifi_subsystem_restart_bugreport_enabled">true</bool>
+
+ <!-- Boolean indicating whether to use the common nl80211 implementation of the WiFi Hal. This
+ will be used instead of the AIDL or HIDL implementation if enabled. -->
+ <bool translatable="false" name="config_wifiNl80211HalEnabled">false</bool>
</resources>
diff --git a/service/ServiceWifiResources/res/values/overlayable.xml b/service/ServiceWifiResources/res/values/overlayable.xml
index d499e36..5d0cf84 100644
--- a/service/ServiceWifiResources/res/values/overlayable.xml
+++ b/service/ServiceWifiResources/res/values/overlayable.xml
@@ -297,6 +297,7 @@
<item type="bool" name="config_wifiDialogCanceledOnTouchOutside" />
<item type="bool" name="config_showConfirmationDialogForThirdPartyAppsEnablingWifi" />
<item type="integer" name="config_p2pInvitationReceivedDialogTimeoutMs"/>
+ <item type="bool" name="config_p2pInvitationReceivedDialogShowRemainingTime" />
<item type="bool" name="config_p2pInvitationReceivedDialogNotificationSound"/>
<item type="integer" name="config_wifiP2pJoinRequestAuthorizingTimeoutMs" />
<item type="bool" name="config_wifiForcedSoftApRestartWhenCountryCodeChanged" />
@@ -307,6 +308,7 @@
<item type="bool" name="config_wifiUserApprovalNotRequireForDisconnectedP2p" />
<item type="integer" name="config_disconnectedP2pIfaceLowPriorityTimeoutMs" />
<item type="array" name="config_wifiP2pAwareConcurrencyAllowlist" />
+ <item type="array" name="config_wifiSoftApAwareConcurrencyAllowlist" />
<item type="bool" name="config_wifiNetworkCentricQosPolicyFeatureEnabled" />
<item type="bool" name="config_wifiApplicationCentricQosPolicyFeatureEnabled" />
<item type="string" name="config_wifiDriverWorldModeCountryCode" />
@@ -344,6 +346,7 @@
<item type="integer" name="config_wifi80211azMaxTimeBetweenNtbMeasurementsMicros"/>
<item type="bool" name="config_wifiD2dAllowedControlSupportedWhenInfraStaDisabled" />
<item type="array" name="config_wifiTwtBlockedOuiList" />
+ <item type="integer" name="config_wifiSoftApMaxNumberMLDSupported"/>
<item type="bool" name="config_wifiSoftApSingleLinkMloInBridgedModeSupported" />
<item type="bool" name="config_wifiTwtSupported" />
<item type="bool" name="config_wifiNetworkSelectionSetTargetBssid" />
@@ -351,6 +354,8 @@
<item type="array" name="config_wifiDelayedSelectionCarrierIds" />
<item type="integer" name="config_wifiDelayedCarrierSelectionTimeMs" />
<item type="bool" name="config_wifiRsnOverridingEnabled" />
+ <item type="bool" name="config_wifi_subsystem_restart_bugreport_enabled" />
+ <item type="bool" name="config_wifiNl80211HalEnabled" />
<!-- Params from config.xml that can be overlayed -->
@@ -387,13 +392,19 @@
<item type="string" name="accept" />
<item type="string" name="decline" />
<item type="string" name="ok" />
- <item type="string" name="wifi_p2p_invitation_sent_title" />
- <item type="string" name="wifi_p2p_invitation_to_connect_title" />
- <item type="string" name="wifi_p2p_invitation_seconds_remaining" />
- <item type="string" name="wifi_p2p_from_message" />
- <item type="string" name="wifi_p2p_to_message" />
- <item type="string" name="wifi_p2p_enter_pin_message" />
- <item type="string" name="wifi_p2p_show_pin_message" />
+ <item type="string" name="wifi_p2p_dialog2_sent_title" />
+ <item type="string" name="wifi_p2p_dialog2_sent_title_display_pin" />
+ <item type="string" name="wifi_p2p_dialog2_sent_message" />
+ <item type="string" name="wifi_p2p_dialog2_sent_message_display_pin" />
+ <item type="string" name="wifi_p2p_dialog2_sent_positive_button" />
+ <item type="string" name="wifi_p2p_dialog2_received_title" />
+ <item type="string" name="wifi_p2p_dialog2_received_message" />
+ <item type="string" name="wifi_p2p_dialog2_received_message_enter_pin" />
+ <item type="string" name="wifi_p2p_dialog2_received_message_display_pin" />
+ <item type="string" name="wifi_p2p_dialog2_received_positive_button" />
+ <item type="string" name="wifi_p2p_dialog2_received_negative_button" />
+ <item type="string" name="wifi_p2p_dialog2_enter_pin_label" />
+ <item type="string" name="wifi_p2p_dialog2_display_pin_label" />
<item type="string" name="wifi_p2p_frequency_conflict_message" />
<item type="string" name="dlg_ok" />
<item type="string" name="wifi_cannot_connect_with_randomized_mac_title" />
@@ -502,6 +513,17 @@
<item type="style" name="wifi_p2p_dialog_row_content" />
<item type="style" name="wifi_p2p_dialog_enter_pin_message" />
<item type="style" name="wifi_p2p_dialog_pin_input" />
+
+ <item type="style" name="wifi_p2p_dialog2" />
+ <item type="style" name="wifi_p2p_dialog2_pin_section" />
+ <item type="style" name="wifi_p2p_dialog2_pin_label" />
+ <item type="style" name="wifi_p2p_dialog2_pin" />
+ <item type="style" name="wifi_p2p_dialog2_enter_pin_section" />
+ <item type="style" name="wifi_p2p_dialog2_enter_pin_label" />
+ <item type="style" name="wifi_p2p_dialog2_enter_pin" />
+ <item type="style" name="wifi_p2p_dialog2_display_pin_section" />
+ <item type="style" name="wifi_p2p_dialog2_display_pin_label" />
+ <item type="style" name="wifi_p2p_dialog2_display_pin" />
<!-- Params from styles.xml that can be overlayed -->
<!-- Params from drawable/ that can be overlayed -->
diff --git a/service/ServiceWifiResources/res/values/strings.xml b/service/ServiceWifiResources/res/values/strings.xml
index 26624b0..3660d75 100644
--- a/service/ServiceWifiResources/res/values/strings.xml
+++ b/service/ServiceWifiResources/res/values/strings.xml
@@ -100,6 +100,7 @@
<string name="wifi_p2p_invitation_sent_title">Invitation sent</string>
<string name="wifi_p2p_invitation_to_connect_title">Invitation to connect</string>
+ <!-- Start of strings for legacy P2P Dialog -->
<!-- The message of the P2P Invitation Received dialog indicating the seconds left to accept before auto rejection [CHAR_LIMIT=NONE] [ICU SYNTAX] -->
<string name="wifi_p2p_invitation_seconds_remaining">
{0, plural,
@@ -111,6 +112,47 @@
<string name="wifi_p2p_to_message">To: </string>
<string name="wifi_p2p_enter_pin_message">Type the required PIN: </string>
<string name="wifi_p2p_show_pin_message">PIN: </string>
+ <!-- End of strings for legacy P2P Dialog -->
+
+ <!-- Start of strings for P2P Dialog 2 -->
+ <string name="wifi_p2p_dialog2_sent_title">Device connection</string>
+ <string name="wifi_p2p_dialog2_sent_title_display_pin">Device connection</string>
+ <string name="wifi_p2p_dialog2_sent_message">Invitation sent to <xliff:g id="device_name">%1$s</xliff:g>.</string>
+ <string name="wifi_p2p_dialog2_sent_message_display_pin">Enter this PIN on <xliff:g id="device_name">%1$s</xliff:g> to connect.</string>
+ <string name="wifi_p2p_dialog2_sent_positive_button">OK</string>
+
+ <string name="wifi_p2p_dialog2_received_title">Device connection</string>
+ <string name="wifi_p2p_dialog2_received_title_enter_pin">Device connection</string>
+ <string name="wifi_p2p_dialog2_received_title_display_pin">Device connection</string>
+ <string name="wifi_p2p_dialog2_received_message"><xliff:g id="device_name">%1$s</xliff:g> wants to connect to your device.</string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin">Enter the PIN shown on <xliff:g id="device_name">%1$s</xliff:g> to connect.</string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin"><xliff:g id="device_name">%1$s</xliff:g> wants to connect to your device with the following PIN.</string>
+
+ <string name="wifi_p2p_dialog2_received_message_countdown">
+ {countdown, plural,
+ =1 {{device} wants to connect to your device. Accept in {countdown} second.}
+ other {{device} wants to connect to your device. Accept in {countdown} seconds.}
+ }
+ </string>
+ <string name="wifi_p2p_dialog2_received_message_enter_pin_countdown">
+ {countdown, plural,
+ =1 {Enter the PIN shown on {device} within {countdown} second to connect.}
+ other {Enter the PIN shown on {device} within {countdown} seconds to connect.}
+ }
+ </string>
+ <string name="wifi_p2p_dialog2_received_message_display_pin_countdown">
+ {countdown, plural,
+ =1 {{device} wants to connect to your device with the following PIN. Accept in {countdown} second.}
+ other {{device} wants to connect to your device with the following PIN. Accept in {countdown} seconds.}
+ }
+ </string>
+
+ <string name="wifi_p2p_dialog2_received_positive_button">Connect</string>
+ <string name="wifi_p2p_dialog2_received_negative_button">Cancel</string>
+
+ <string name="wifi_p2p_dialog2_enter_pin_label">PIN</string>
+ <string name="wifi_p2p_dialog2_display_pin_label">PIN</string>
+ <!-- End of strings for P2P Dialog 2 -->
<string name="wifi_p2p_frequency_conflict_message">Your device will temporarily disconnect from Wi-Fi while it\'s connected to <xliff:g id="device_name">%1$s</xliff:g></string>
<!-- Dialog ok button-->
diff --git a/service/ServiceWifiResources/res/values/styles.xml b/service/ServiceWifiResources/res/values/styles.xml
index 714d10f..e86aee8 100644
--- a/service/ServiceWifiResources/res/values/styles.xml
+++ b/service/ServiceWifiResources/res/values/styles.xml
@@ -63,4 +63,38 @@
<item name="android:inputType">number</item>
<item name="android:textColor">@android:color/primary_text_light</item>
</style>
+
+ <style name="wifi_p2p_dialog2" parent="@android:style/Theme.DeviceDefault.Light.Dialog.Alert" />
+
+ <style name="wifi_p2p_dialog2_pin_section">
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:orientation">vertical</item>
+ <item name="android:paddingLeft">24dp</item>
+ <item name="android:paddingRight">24dp</item>
+ </style>
+ <style name="wifi_p2p_dialog2_pin_label" >
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:textColor">@android:color/secondary_text_light</item>
+ <item name="android:textSize">14sp</item>
+ </style>
+ <style name="wifi_p2p_dialog2_pin">
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:textColor">@android:color/primary_text_light</item>
+ <item name="android:textSize">18sp</item>
+ </style>
+
+ <style name="wifi_p2p_dialog2_enter_pin_section" parent="@style/wifi_p2p_dialog2_pin_section" />
+ <style name="wifi_p2p_dialog2_enter_pin_label" parent="@style/wifi_p2p_dialog2_pin_label" />
+ <style name="wifi_p2p_dialog2_enter_pin" parent="@style/wifi_p2p_dialog2_pin">
+ <item name="android:singleLine">true</item>
+ <item name="android:maxLength">8</item>
+ <item name="android:inputType">number</item>
+ </style>
+
+ <style name="wifi_p2p_dialog2_display_pin_section" parent="@style/wifi_p2p_dialog2_pin_section" />
+ <style name="wifi_p2p_dialog2_display_pin_label" parent="@style/wifi_p2p_dialog2_pin_label" />
+ <style name="wifi_p2p_dialog2_display_pin" parent="@style/wifi_p2p_dialog2_pin" />
</resources>
diff --git a/service/java/com/android/server/wifi/ActiveModeWarden.java b/service/java/com/android/server/wifi/ActiveModeWarden.java
index 6b6b5c0..a2877c0 100644
--- a/service/java/com/android/server/wifi/ActiveModeWarden.java
+++ b/service/java/com/android/server/wifi/ActiveModeWarden.java
@@ -47,6 +47,7 @@
import android.net.wifi.ISubsystemRestartCallback;
import android.net.wifi.IWifiConnectedNetworkScorer;
import android.net.wifi.IWifiNetworkStateChangedListener;
+import android.net.wifi.IWifiStateChangedListener;
import android.net.wifi.SoftApCapability;
import android.net.wifi.SoftApConfiguration;
import android.net.wifi.SoftApState;
@@ -98,6 +99,7 @@
import java.io.PrintWriter;
import java.util.ArrayDeque;
import java.util.ArrayList;
+import java.util.BitSet;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@@ -105,7 +107,6 @@
import java.util.Set;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -153,6 +154,8 @@
new RemoteCallbackList<>();
private final RemoteCallbackList<IWifiNetworkStateChangedListener>
mWifiNetworkStateChangedListeners = new RemoteCallbackList<>();
+ private final RemoteCallbackList<IWifiStateChangedListener> mWifiStateChangedListeners =
+ new RemoteCallbackList<>();
private boolean mIsMultiplePrimaryBugreportTaken = false;
private boolean mIsShuttingdown = false;
@@ -171,7 +174,6 @@
private WorkSource mLastPrimaryClientModeManagerRequestorWs = null;
@Nullable
private WorkSource mLastScanOnlyClientModeManagerRequestorWs = null;
- private AtomicLong mSupportedFeatureSet = new AtomicLong(0);
private AtomicInteger mBandsSupported = new AtomicInteger(0);
// Mutex lock between service Api binder thread and Wifi main thread
private final Object mServiceApiLock = new Object();
@@ -179,6 +181,8 @@
private Network mCurrentNetwork;
@GuardedBy("mServiceApiLock")
private WifiInfo mCurrentConnectionInfo = new WifiInfo();
+ @GuardedBy("mServiceApiLock")
+ private BitSet mSupportedFeatureSet = new BitSet();
@GuardedBy("mServiceApiLock")
private final ArraySet<WorkSource> mRequestWs = new ArraySet<>();
@@ -211,7 +215,10 @@
if (mVerboseLoggingEnabled) {
Log.d(TAG, "setting wifi state to: " + newState);
}
- mWifiState.set(newState);
+ if (mWifiState.get() != newState) {
+ mWifiState.set(newState);
+ notifyRemoteWifiStateChangedListeners();
+ }
break;
default:
Log.d(TAG, "attempted to set an invalid state: " + newState);
@@ -268,6 +275,32 @@
}
/**
+ * See {@link WifiManager#addWifiStateChangedListener(Executor, WifiStateChangedListener)}
+ */
+ public void addWifiStateChangedListener(@NonNull IWifiStateChangedListener listener) {
+ mWifiStateChangedListeners.register(listener);
+ }
+
+ /**
+ * See {@link WifiManager#removeWifiStateChangedListener(WifiStateChangedListener)}
+ */
+ public void removeWifiStateChangedListener(@NonNull IWifiStateChangedListener listener) {
+ mWifiStateChangedListeners.unregister(listener);
+ }
+
+ private void notifyRemoteWifiStateChangedListeners() {
+ final int itemCount = mWifiStateChangedListeners.beginBroadcast();
+ for (int i = 0; i < itemCount; i++) {
+ try {
+ mWifiStateChangedListeners.getBroadcastItem(i).onWifiStateChanged();
+ } catch (RemoteException e) {
+ Log.e(TAG, "onWifiStateChanged: remote exception -- " + e);
+ }
+ }
+ mWifiStateChangedListeners.finishBroadcast();
+ }
+
+ /**
* Called from WifiServiceImpl to register a callback for notifications from SoftApManager
*/
public void registerSoftApCallback(@NonNull WifiServiceImpl.SoftApCallbackInternal callback) {
@@ -680,14 +713,14 @@
/** Begin listening to broadcasts and start the internal state machine. */
public void start() {
- mContext.registerReceiver(new BroadcastReceiver() {
+ mContext.registerReceiverForAllUsers(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// Location mode has been toggled... trigger with the scan change
// update to make sure we are in the correct mode
scanAlwaysModeChanged();
}
- }, new IntentFilter(LocationManager.MODE_CHANGED_ACTION));
+ }, new IntentFilter(LocationManager.MODE_CHANGED_ACTION), null, mHandler);
mContext.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@@ -1371,7 +1404,9 @@
Log.d(TAG, "Switching all client mode managers");
for (ConcreteClientModeManager clientModeManager : mClientModeManagers) {
if (clientModeManager.getRole() != ROLE_CLIENT_PRIMARY
- && clientModeManager.getRole() != ROLE_CLIENT_SCAN_ONLY) {
+ && clientModeManager.getRole() != ROLE_CLIENT_SCAN_ONLY
+ && clientModeManager.getTargetRole() != ROLE_CLIENT_PRIMARY
+ && clientModeManager.getTargetRole() != ROLE_CLIENT_SCAN_ONLY) {
continue;
}
if (!switchPrimaryOrScanOnlyClientModeManagerRole(clientModeManager)) {
@@ -2699,6 +2734,28 @@
// onStopped will move the state machine to "DisabledState".
break;
}
+ case CMD_RECOVERY_RESTART_WIFI_CONTINUE: {
+ log("received CMD_RECOVERY_RESTART_WIFI_CONTINUE when already in "
+ + "mEnabledState");
+ // This could happen when SoftAp is turned on before recovery is complete.
+ // Simply make sure the primary CMM is on in this case.
+ if (shouldEnableSta() && !hasPrimaryOrScanOnlyModeManager()) {
+ startPrimaryOrScanOnlyClientModeManager(
+ // Assumes user toggled it on from settings before.
+ mFacade.getSettingsWorkSource(mContext));
+ }
+ int numCallbacks = mRestartCallbacks.beginBroadcast();
+ for (int i = 0; i < numCallbacks; i++) {
+ try {
+ mRestartCallbacks.getBroadcastItem(i).onSubsystemRestarted();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failure calling onSubsystemRestarted" + e);
+ }
+ }
+ mRestartCallbacks.finishBroadcast();
+ mWifiInjector.getSelfRecovery().onRecoveryCompleted();
+ break;
+ }
default:
return NOT_HANDLED;
}
@@ -2734,86 +2791,85 @@
/**
* Set the current supported Wifi feature set, called from primary client mode manager.
- * @param supportedFeatureSet supported Wifi feature set
+ * @param wifiNativeFeatureSet feature set retrieved from WifiNative
* @param isStaApConcurrencySupported true if Sta+Ap concurrency supported
* @param isStaStaConcurrencySupported true if Sta+Sta concurrency supported
*/
- private void setSupportedFeatureSet(long supportedFeatureSet,
+ private void setSupportedFeatureSet(BitSet wifiNativeFeatureSet,
boolean isStaApConcurrencySupported,
boolean isStaStaConcurrencySupported) {
- long concurrencyFeatureSet = 0L;
+ BitSet featureSet = (BitSet) wifiNativeFeatureSet.clone();
+
+ // Concurrency features
if (isStaApConcurrencySupported) {
- concurrencyFeatureSet |= WifiManager.WIFI_FEATURE_AP_STA;
+ featureSet.set(WifiManager.WIFI_FEATURE_AP_STA);
}
if (isStaStaConcurrencySupported) {
if (mResourceCache.getBoolean(
R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled)) {
- concurrencyFeatureSet |= WifiManager.WIFI_FEATURE_ADDITIONAL_STA_LOCAL_ONLY;
+ featureSet.set(WifiManager.WIFI_FEATURE_ADDITIONAL_STA_LOCAL_ONLY);
}
if (mResourceCache.getBoolean(
R.bool.config_wifiMultiStaNetworkSwitchingMakeBeforeBreakEnabled)) {
- concurrencyFeatureSet |= WifiManager.WIFI_FEATURE_ADDITIONAL_STA_MBB;
+ featureSet.set(WifiManager.WIFI_FEATURE_ADDITIONAL_STA_MBB);
}
if (mResourceCache.getBoolean(
R.bool.config_wifiMultiStaRestrictedConcurrencyEnabled)) {
- concurrencyFeatureSet |= WifiManager.WIFI_FEATURE_ADDITIONAL_STA_RESTRICTED;
+ featureSet.set(WifiManager.WIFI_FEATURE_ADDITIONAL_STA_RESTRICTED);
}
if (mResourceCache.getBoolean(
R.bool.config_wifiMultiStaMultiInternetConcurrencyEnabled)) {
- concurrencyFeatureSet |= WifiManager.WIFI_FEATURE_ADDITIONAL_STA_MULTI_INTERNET;
+ featureSet.set(WifiManager.WIFI_FEATURE_ADDITIONAL_STA_MULTI_INTERNET);
}
}
- long additionalFeatureSet = 0L;
- long excludedFeatureSet = 0L;
- // Mask the feature set against system properties.
- if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_RTT)) {
- // flags filled in by vendor HAL, remove if overlay disables it.
- excludedFeatureSet |=
- (WifiManager.WIFI_FEATURE_D2D_RTT | WifiManager.WIFI_FEATURE_D2AP_RTT);
- }
- if (!mResourceCache.getBoolean(
- R.bool.config_wifi_p2p_mac_randomization_supported)) {
- // flags filled in by vendor HAL, remove if overlay disables it.
- excludedFeatureSet |= WifiManager.WIFI_FEATURE_P2P_RAND_MAC;
- }
-
+ // Additional features
if (mResourceCache.getBoolean(
R.bool.config_wifi_connected_mac_randomization_supported)) {
// no corresponding flags in vendor HAL, set if overlay enables it.
- additionalFeatureSet |= WifiManager.WIFI_FEATURE_CONNECTED_RAND_MAC;
+ featureSet.set(WifiManager.WIFI_FEATURE_CONNECTED_RAND_MAC);
}
if (ApConfigUtil.isApMacRandomizationSupported(mContext)) {
// no corresponding flags in vendor HAL, set if overlay enables it.
- additionalFeatureSet |= WifiManager.WIFI_FEATURE_AP_RAND_MAC;
+ featureSet.set(WifiManager.WIFI_FEATURE_AP_RAND_MAC);
}
-
if (ApConfigUtil.isBridgedModeSupported(mContext, mWifiNative)) {
// The bridged mode requires the kernel network modules support.
// It doesn't relate the vendor HAL, set if overlay enables it.
- additionalFeatureSet |= WifiManager.WIFI_FEATURE_BRIDGED_AP;
+ featureSet.set(WifiManager.WIFI_FEATURE_BRIDGED_AP);
}
if (ApConfigUtil.isStaWithBridgedModeSupported(mContext, mWifiNative)) {
// The bridged mode requires the kernel network modules support.
// It doesn't relate the vendor HAL, set if overlay enables it.
- additionalFeatureSet |= WifiManager.WIFI_FEATURE_STA_BRIDGED_AP;
+ featureSet.set(WifiManager.WIFI_FEATURE_STA_BRIDGED_AP);
}
if (mWifiGlobals.isWepSupported()) {
- additionalFeatureSet |= WifiManager.WIFI_FEATURE_WEP;
+ featureSet.set(WifiManager.WIFI_FEATURE_WEP);
}
if (!mWifiGlobals.isWpaPersonalDeprecated()) {
// The WPA didn't be deprecated, set it.
- additionalFeatureSet |= WifiManager.WIFI_FEATURE_WPA_PERSONAL;
+ featureSet.set(WifiManager.WIFI_FEATURE_WPA_PERSONAL);
}
if (mWifiGlobals.isD2dSupportedWhenInfraStaDisabled()) {
- additionalFeatureSet |= WifiManager.WIFI_FEATURE_D2D_WHEN_INFRA_STA_DISABLED;
+ featureSet.set(WifiManager.WIFI_FEATURE_D2D_WHEN_INFRA_STA_DISABLED);
}
- mSupportedFeatureSet.set(
- (supportedFeatureSet | concurrencyFeatureSet | additionalFeatureSet)
- & ~excludedFeatureSet);
- if (mVerboseLoggingEnabled) {
- Log.d(TAG, "setSupportedFeatureSet 0x" + Long.toHexString(mSupportedFeatureSet.get()));
+
+ // Remove capabilities that are disabled by the system properties
+ if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_RTT)) {
+ featureSet.clear(WifiManager.WIFI_FEATURE_D2D_RTT);
+ featureSet.clear(WifiManager.WIFI_FEATURE_D2AP_RTT);
+ }
+ if (!mResourceCache.getBoolean(
+ R.bool.config_wifi_p2p_mac_randomization_supported)) {
+ featureSet.clear(WifiManager.WIFI_FEATURE_P2P_RAND_MAC);
+ }
+
+ synchronized (mServiceApiLock) {
+ mSupportedFeatureSet = featureSet;
+ if (mVerboseLoggingEnabled) {
+ Log.d(TAG, "setSupportedFeatureSet to " + mSupportedFeatureSet);
+ }
}
}
@@ -2821,8 +2877,10 @@
* Get the current supported Wifi feature set.
* @return supported Wifi feature set
*/
- public long getSupportedFeatureSet() {
- return mSupportedFeatureSet.get();
+ public @NonNull BitSet getSupportedFeatureSet() {
+ synchronized (mServiceApiLock) {
+ return mSupportedFeatureSet;
+ }
}
/**
@@ -2925,4 +2983,26 @@
mSettingsStore.updateSatelliteModeTracker();
mWifiController.sendMessage(WifiController.CMD_SATELLITE_MODE_CHANGED);
}
+
+ /**
+ * Returns the number of multiple link devices (MLD) which are being operated.
+ */
+ public int getCurrentMLDAp() {
+ if (!SdkLevel.isAtLeastT()) {
+ return 0;
+ }
+ int numberMLD = 0;
+ for (SoftApManager manager : mSoftApManagers) {
+ if (manager.isStarted() && manager.getSoftApModeConfiguration()
+ .getSoftApConfiguration().isIeee80211beEnabled()) {
+ if (manager.isBridgedMode() && !manager.isUsingMlo()) {
+ // Non MLO bridged mode, it occupies two MLD APs.
+ numberMLD += 2;
+ } else {
+ numberMLD++;
+ }
+ }
+ }
+ return numberMLD;
+ }
}
diff --git a/service/java/com/android/server/wifi/ClientMode.java b/service/java/com/android/server/wifi/ClientMode.java
index 7292de3..d5c7c82 100644
--- a/service/java/com/android/server/wifi/ClientMode.java
+++ b/service/java/com/android/server/wifi/ClientMode.java
@@ -22,6 +22,7 @@
import android.net.DhcpResultsParcelable;
import android.net.MacAddress;
import android.net.Network;
+import android.net.wifi.BlockingOption;
import android.net.wifi.IWifiConnectedNetworkScorer;
import android.net.wifi.WifiAnnotations;
import android.net.wifi.WifiConfiguration;
@@ -43,6 +44,7 @@
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.BitSet;
import java.util.List;
import java.util.Set;
@@ -136,7 +138,8 @@
DhcpResultsParcelable syncGetDhcpResultsParcelable();
/** Get the supported feature set synchronously */
- long getSupportedFeatures();
+ @NonNull
+ BitSet getSupportedFeatures();
boolean syncStartSubscriptionProvisioning(int callingUid, OsuProvider provider,
IProvisioningCallback callback);
@@ -368,4 +371,9 @@
* Notify changes in PowerManager#isDeviceIdleMode
*/
void onIdleModeChanged(boolean isIdle);
+
+ /**
+ * Block current connect network and add to blocklist
+ */
+ void blockNetwork(BlockingOption option);
}
diff --git a/service/java/com/android/server/wifi/ClientModeDefaults.java b/service/java/com/android/server/wifi/ClientModeDefaults.java
index f526f2d..6a9d1ae 100644
--- a/service/java/com/android/server/wifi/ClientModeDefaults.java
+++ b/service/java/com/android/server/wifi/ClientModeDefaults.java
@@ -21,6 +21,7 @@
import android.net.DhcpResultsParcelable;
import android.net.MacAddress;
import android.net.Network;
+import android.net.wifi.BlockingOption;
import android.net.wifi.IWifiConnectedNetworkScorer;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
@@ -284,4 +285,7 @@
@Override
default void onIdleModeChanged(boolean isIdle) { }
+
+ @Override
+ default void blockNetwork(BlockingOption option) { }
}
diff --git a/service/java/com/android/server/wifi/ClientModeImpl.java b/service/java/com/android/server/wifi/ClientModeImpl.java
index 8e97cae..ba671d0 100644
--- a/service/java/com/android/server/wifi/ClientModeImpl.java
+++ b/service/java/com/android/server/wifi/ClientModeImpl.java
@@ -33,6 +33,8 @@
import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_SCAN_ONLY;
import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_SECONDARY_LONG_LIVED;
import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_SECONDARY_TRANSIENT;
+import static com.android.server.wifi.WifiBlocklistMonitor.REASON_APP_DISALLOW;
+import static com.android.server.wifi.WifiConfigManager.LINK_CONFIGURATION_BSSID_MATCH_LENGTH;
import static com.android.server.wifi.WifiSettingsConfigStore.SECONDARY_WIFI_STA_FACTORY_MAC_ADDRESS;
import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_STA_FACTORY_MAC_ADDRESS;
import static com.android.server.wifi.proto.WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__ROLE__ROLE_CLIENT_LOCAL_ONLY;
@@ -85,6 +87,7 @@
import android.net.shared.ProvisioningConfiguration.ScanResultInfo;
import android.net.vcn.VcnManager;
import android.net.vcn.VcnNetworkPolicyResult;
+import android.net.wifi.BlockingOption;
import android.net.wifi.IWifiConnectedNetworkScorer;
import android.net.wifi.MloLink;
import android.net.wifi.ScanResult;
@@ -160,6 +163,7 @@
import com.android.server.wifi.proto.nano.WifiMetricsProto.StaEvent;
import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiIsUnusableEvent;
import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiUsabilityStats;
+import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiUsabilityStatsEntry;
import com.android.server.wifi.util.ActionListenerWrapper;
import com.android.server.wifi.util.InformationElementUtil;
import com.android.server.wifi.util.NativeUtil;
@@ -182,6 +186,7 @@
import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.BitSet;
import java.util.Collections;
import java.util.List;
import java.util.Map;
@@ -679,12 +684,6 @@
// connected before wrong password failure on this network reached this threshold.
public static final int THRESHOLD_TO_PERM_WRONG_PASSWORD = 3;
- // Maximum duration to continue to log Wifi usability stats after a data stall is triggered.
- @VisibleForTesting
- public static final long DURATION_TO_WAIT_ADD_STATS_AFTER_DATA_STALL_MS = 30 * 1000;
- private long mDataStallTriggerTimeMs = -1;
- private int mLastStatusDataStall = WifiIsUnusableEvent.TYPE_UNKNOWN;
-
@Nullable
private StateMachineObituary mObituary = null;
@@ -923,6 +922,7 @@
mRoamingState = new RoamingState(threshold);
mDisconnectedState = new DisconnectedState(threshold);
+ // Code indentation is used to show the hierarchical relationship between states.
addState(mConnectableState); {
addState(mConnectingOrConnectedState, mConnectableState); {
addState(mL2ConnectingState, mConnectingOrConnectedState);
@@ -1227,7 +1227,7 @@
if (config.networkId == mTargetNetworkId || config.networkId == mLastNetworkId) {
// Disconnect and let autojoin reselect a new network
mFrameworkDisconnectReasonOverride = WifiStatsLog.WIFI_DISCONNECT_REPORTED__FAILURE_CODE__DISCONNECT_NETWORK_REMOVED;
- sendMessage(CMD_DISCONNECT, StaEvent.DISCONNECT_NETWORK_REMOVED);
+ sendMessageAtFrontOfQueue(CMD_DISCONNECT, StaEvent.DISCONNECT_NETWORK_REMOVED);
// Log disconnection here, since the network config won't exist when the
// disconnection event is received.
String bssid = getConnectedBssidInternal();
@@ -1264,7 +1264,8 @@
+ " triggering disconnect");
mFrameworkDisconnectReasonOverride =
WifiStatsLog.WIFI_DISCONNECT_REPORTED__FAILURE_CODE__DISCONNECT_NETWORK_WIFI7_TOGGLED;
- sendMessage(CMD_DISCONNECT, StaEvent.DISCONNECT_NETWORK_WIFI7_TOGGLED);
+ sendMessageAtFrontOfQueue(CMD_DISCONNECT,
+ StaEvent.DISCONNECT_NETWORK_WIFI7_TOGGLED);
return;
}
@@ -1281,7 +1282,8 @@
if (!newConfig.trusted) {
Log.w(getTag(), "Network marked untrusted, triggering disconnect");
mFrameworkDisconnectReasonOverride = WifiStatsLog.WIFI_DISCONNECT_REPORTED__FAILURE_CODE__DISCONNECT_NETWORK_UNTRUSTED;
- sendMessage(CMD_DISCONNECT, StaEvent.DISCONNECT_NETWORK_UNTRUSTED);
+ sendMessageAtFrontOfQueue(CMD_DISCONNECT,
+ StaEvent.DISCONNECT_NETWORK_UNTRUSTED);
return;
}
}
@@ -1289,7 +1291,7 @@
if (isMetered) {
Log.w(getTag(), "Network marked metered, triggering disconnect");
mFrameworkDisconnectReasonOverride = WifiStatsLog.WIFI_DISCONNECT_REPORTED__FAILURE_CODE__DISCONNECT_NETWORK_METERED;
- sendMessage(CMD_DISCONNECT, StaEvent.DISCONNECT_NETWORK_METERED);
+ sendMessageAtFrontOfQueue(CMD_DISCONNECT, StaEvent.DISCONNECT_NETWORK_METERED);
return;
}
@@ -1305,7 +1307,8 @@
if (config.networkId == mTargetNetworkId || config.networkId == mLastNetworkId) {
// Disconnect and let autojoin reselect a new network
mFrameworkDisconnectReasonOverride = WifiStatsLog.WIFI_DISCONNECT_REPORTED__FAILURE_CODE__DISCONNECT_TEMP_DISABLED;
- sendMessage(CMD_DISCONNECT, StaEvent.DISCONNECT_NETWORK_TEMPORARY_DISABLED);
+ sendMessageAtFrontOfQueue(CMD_DISCONNECT,
+ StaEvent.DISCONNECT_NETWORK_TEMPORARY_DISABLED);
}
}
@@ -1320,7 +1323,8 @@
if (config.networkId == mTargetNetworkId || config.networkId == mLastNetworkId) {
// Disconnect and let autojoin reselect a new network
mFrameworkDisconnectReasonOverride = WifiStatsLog.WIFI_DISCONNECT_REPORTED__FAILURE_CODE__DISCONNECT_PERM_DISABLED;
- sendMessage(CMD_DISCONNECT, StaEvent.DISCONNECT_NETWORK_PERMANENT_DISABLED);
+ sendMessageAtFrontOfQueue(CMD_DISCONNECT,
+ StaEvent.DISCONNECT_NETWORK_PERMANENT_DISABLED);
}
}
}
@@ -1340,7 +1344,8 @@
&& configuration.carrierMerged == merged) {
Log.i(getTag(), "Carrier network offload disabled, triggering disconnect");
mFrameworkDisconnectReasonOverride = WifiStatsLog.WIFI_DISCONNECT_REPORTED__FAILURE_CODE__DISCONNECT_CARRIER_OFFLOAD_DISABLED;
- sendMessage(CMD_DISCONNECT, StaEvent.DISCONNECT_CARRIER_OFFLOAD_DISABLED);
+ sendMessageAtFrontOfQueue(CMD_DISCONNECT,
+ StaEvent.DISCONNECT_CARRIER_OFFLOAD_DISABLED);
}
mWifiConnectivityManager.clearCachedCandidates();
}
@@ -1646,14 +1651,14 @@
}
private boolean isLinkLayerStatsSupported() {
- return (getSupportedFeatures() & WIFI_FEATURE_LINK_LAYER_STATS) != 0;
+ return getSupportedFeatures().get(WIFI_FEATURE_LINK_LAYER_STATS);
}
/**
* @return true if this device supports WPA3_SAE
*/
private boolean isWpa3SaeSupported() {
- return (getSupportedFeatures() & WIFI_FEATURE_WPA3_SAE) != 0;
+ return getSupportedFeatures().get(WIFI_FEATURE_WPA3_SAE);
}
/**
@@ -1978,7 +1983,7 @@
/**
* Get the supported feature set synchronously
*/
- public long getSupportedFeatures() {
+ public @NonNull BitSet getSupportedFeatures() {
return mWifiNative.getSupportedFeatureSet(mInterfaceName);
}
@@ -2042,8 +2047,7 @@
* Check if a TDLS session can be established
*/
public boolean isTdlsOperationCurrentlyAvailable() {
- return (getSupportedFeatures() & WIFI_FEATURE_TDLS) != 0 && isConnected()
- && canEnableTdls();
+ return getSupportedFeatures().get(WIFI_FEATURE_TDLS) && isConnected() && canEnableTdls();
}
/**
@@ -2278,9 +2282,7 @@
sb.append(" ");
sb.append(Integer.toString(msg.arg2));
if (mWifiInfo.getSSID() != null) {
- if (mWifiInfo.getSSID() != null) {
- sb.append(" ").append(mWifiInfo.getSSID());
- }
+ sb.append(" ").append(mWifiInfo.getSSID());
}
if (mWifiInfo.getBSSID() != null) {
sb.append(" ").append(mWifiInfo.getBSSID());
@@ -2817,9 +2819,6 @@
* set Tx link speed only if it is valid
*/
if (newTxLinkSpeed > 0) {
- if (newTxLinkSpeed != mWifiInfo.getTxLinkSpeedMbps() && SdkLevel.isAtLeastV()) {
- updateNetworkCapabilities = true;
- }
mWifiInfo.setLinkSpeed(newTxLinkSpeed);
mWifiInfo.setTxLinkSpeedMbps(newTxLinkSpeed);
}
@@ -2827,9 +2826,6 @@
* set Rx link speed only if it is valid
*/
if (newRxLinkSpeed > 0) {
- if (newRxLinkSpeed != mWifiInfo.getRxLinkSpeedMbps() && SdkLevel.isAtLeastV()) {
- updateNetworkCapabilities = true;
- }
mWifiInfo.setRxLinkSpeedMbps(newRxLinkSpeed);
}
if (newFrequency > 0) {
@@ -4072,9 +4068,11 @@
WifiConfiguration.NetworkSelectionStatus.DISABLED_DHCP_FAILURE);
/* DHCP times out after about 30 seconds, we do a
- * disconnect thru supplicant, we will let autojoin retry connecting to the network
+ * disconnect through supplicant, we will let autojoin retry connecting to the network
*/
mFrameworkDisconnectReasonOverride = WifiStatsLog.WIFI_DISCONNECT_REPORTED__FAILURE_CODE__DISCONNECT_IP_PROVISIONING_FAILURE;
+ mWifiMetrics.logStaEvent(mInterfaceName, StaEvent.TYPE_FRAMEWORK_DISCONNECT,
+ StaEvent.DISCONNECT_IP_CONFIGURATION_LOST);
mWifiNative.disconnect(mInterfaceName);
updateCurrentConnectionInfo();
}
@@ -4096,7 +4094,7 @@
mFrameworkDisconnectReasonOverride = WifiStatsLog.WIFI_DISCONNECT_REPORTED__FAILURE_CODE__DISCONNECT_NUD_FAILURE_ORGANIC;
}
// Disconnect via supplicant, and let autojoin retry connecting to the network.
- mWifiNative.disconnect(mInterfaceName);
+ sendMessageAtFrontOfQueue(CMD_DISCONNECT, StaEvent.DISCONNECT_IP_REACHABILITY_LOST);
updateCurrentConnectionInfo();
}
@@ -4170,9 +4168,6 @@
mWifiMetrics.logStaEvent(mInterfaceName, StaEvent.TYPE_CMD_IP_REACHABILITY_LOST);
mWifiMetrics.logWifiIsUnusableEvent(mInterfaceName,
WifiIsUnusableEvent.TYPE_IP_REACHABILITY_LOST);
- mWifiMetrics.addToWifiUsabilityStatsList(mInterfaceName,
- WifiUsabilityStats.LABEL_BAD,
- WifiUsabilityStats.TYPE_IP_REACHABILITY_LOST, -1);
if (mWifiGlobals.getIpReachabilityDisconnectEnabled()) {
handleIpReachabilityLost(lossReason);
} else {
@@ -4766,10 +4761,9 @@
break;
}
if (mWifiP2pConnection.shouldTemporarilyDisconnectWifi()) {
- mWifiMetrics.logStaEvent(mInterfaceName, StaEvent.TYPE_FRAMEWORK_DISCONNECT,
- StaEvent.DISCONNECT_P2P_DISCONNECT_WIFI_REQUEST);
mFrameworkDisconnectReasonOverride = WifiStatsLog.WIFI_DISCONNECT_REPORTED__FAILURE_CODE__DISCONNECT_P2P_REQUESTED_DISCONNECT;
- mWifiNative.disconnect(mInterfaceName);
+ sendMessageAtFrontOfQueue(CMD_DISCONNECT,
+ StaEvent.DISCONNECT_P2P_DISCONNECT_WIFI_REQUEST);
} else {
mWifiNative.reconnect(mInterfaceName);
}
@@ -5023,7 +5017,8 @@
loge("Disconnecting from Passpoint network due to an issue with the "
+ "Terms and Conditions URL");
mFrameworkDisconnectReasonOverride = WifiStatsLog.WIFI_DISCONNECT_REPORTED__FAILURE_CODE__DISCONNECT_PASSPOINT_TAC;
- sendMessage(CMD_DISCONNECT, StaEvent.DISCONNECT_PASSPOINT_TAC);
+ sendMessageAtFrontOfQueue(CMD_DISCONNECT,
+ StaEvent.DISCONNECT_PASSPOINT_TAC);
}
break;
case WifiMonitor.HS20_REMEDIATION_EVENT:
@@ -5121,8 +5116,8 @@
case CMD_CONNECTING_WATCHDOG_TIMER:
case WifiMonitor.NETWORK_NOT_FOUND_EVENT:
case CMD_ROAM_WATCHDOG_TIMER: {
- // no-op: all messages must be handled in the base state in case it was missed
- // in one of the child states.
+ // no-op: all messages must be handled in the base state if they were not
+ // handled in one of the child states.
break;
}
case CMD_ACCEPT_EAP_SERVER_CERTIFICATE:
@@ -5330,7 +5325,7 @@
if (vcnNetworkPolicy.isTeardownRequested()) {
mFrameworkDisconnectReasonOverride =
WifiStatsLog.WIFI_DISCONNECT_REPORTED__FAILURE_CODE__DISCONNECT_VNC_REQUEST;
- sendMessage(CMD_DISCONNECT, StaEvent.DISCONNECT_VCN_REQUEST);
+ sendMessageAtFrontOfQueue(CMD_DISCONNECT, StaEvent.DISCONNECT_VCN_REQUEST);
}
final NetworkCapabilities vcnCapability = vcnNetworkPolicy.getNetworkCapabilities();
if (!vcnCapability.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED)) {
@@ -5779,7 +5774,8 @@
logw("Connected to unknown networkId " + mLastNetworkId
+ ", disconnecting...");
mFrameworkDisconnectReasonOverride = WifiStatsLog.WIFI_DISCONNECT_REPORTED__FAILURE_CODE__DISCONNECT_UNKNOWN_NETWORK;
- sendMessage(CMD_DISCONNECT, StaEvent.DISCONNECT_UNKNOWN_NETWORK);
+ sendMessageAtFrontOfQueue(CMD_DISCONNECT,
+ StaEvent.DISCONNECT_UNKNOWN_NETWORK);
break;
}
handleNetworkConnectionEventInfo(config, connectionInfo);
@@ -6042,7 +6038,8 @@
// disconnect the network.
if (disconnectRequired) {
mFrameworkDisconnectReasonOverride = WifiStatsLog.WIFI_DISCONNECT_REPORTED__FAILURE_CODE__DISCONNECT_NETWORK_UNTRUSTED;
- sendMessage(CMD_DISCONNECT, StaEvent.DISCONNECT_NETWORK_UNTRUSTED);
+ sendMessageAtFrontOfQueue(CMD_DISCONNECT,
+ StaEvent.DISCONNECT_NETWORK_UNTRUSTED);
}
break;
}
@@ -6398,9 +6395,8 @@
WifiConfiguration.NetworkSelectionStatus
.DISABLED_AUTHENTICATION_NO_CREDENTIALS);
}
- mWifiMetrics.logStaEvent(mInterfaceName, StaEvent.TYPE_FRAMEWORK_DISCONNECT,
- StaEvent.DISCONNECT_GENERIC);
- mWifiNative.disconnect(mInterfaceName);
+ sendMessageAtFrontOfQueue(CMD_DISCONNECT,
+ StaEvent.DISCONNECT_NO_CREDENTIALS);
}
break;
}
@@ -6449,7 +6445,8 @@
// In the TOFU flow, the user approval dialog is now displayed and the
// network remains disconnected and disabled until it is approved.
mFrameworkDisconnectReasonOverride = WifiStatsLog.WIFI_DISCONNECT_REPORTED__FAILURE_CODE__DISCONNECT_NETWORK_UNTRUSTED;
- sendMessage(CMD_DISCONNECT, StaEvent.DISCONNECT_NETWORK_UNTRUSTED);
+ sendMessageAtFrontOfQueue(CMD_DISCONNECT,
+ StaEvent.DISCONNECT_NETWORK_UNTRUSTED);
mLeafCertSent = true;
}
break;
@@ -6477,13 +6474,15 @@
if (config == null) {
logw("Connected to a network that's already been removed " + mLastNetworkId
+ ", disconnecting...");
- sendMessage(CMD_DISCONNECT, StaEvent.DISCONNECT_UNKNOWN_NETWORK);
+ sendMessageAtFrontOfQueue(CMD_DISCONNECT, StaEvent.DISCONNECT_UNKNOWN_NETWORK);
return;
}
mRssiPollToken++;
if (mEnableRssiPolling) {
sendMessage(CMD_RSSI_POLL, mRssiPollToken, 0);
+ mWifiMetrics.logAsynchronousEvent(mInterfaceName,
+ WifiUsabilityStatsEntry.CAPTURE_EVENT_TYPE_RSSI_POLLING_ENABLED);
} else {
updateLinkLayerStatsRssiAndScoreReport();
}
@@ -6593,12 +6592,9 @@
if (getConnectedWifiConfigurationInternal() == null || mNetworkAgent == null) {
// The current config may have been removed while we were connecting,
// trigger a disconnect to clear up state.
- reportConnectionAttemptEnd(
- WifiMetrics.ConnectionEvent.FAILURE_NETWORK_DISCONNECTION,
- WifiMetricsProto.ConnectionEvent.HLF_NONE,
- WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN, 0);
mFrameworkDisconnectReasonOverride = WifiStatsLog.WIFI_DISCONNECT_REPORTED__FAILURE_CODE__DISCONNECT_NETWORK_REMOVED;
- mWifiNative.disconnect(mInterfaceName);
+ sendMessageAtFrontOfQueue(CMD_DISCONNECT,
+ StaEvent.DISCONNECT_UNKNOWN_NETWORK);
} else {
handleSuccessfulIpConfiguration();
transitionTo(mL3ConnectedState);
@@ -6631,9 +6627,8 @@
WifiDiagnostics.REPORT_REASON_REACHABILITY_LOST);
mWifiMetrics.logWifiIsUnusableEvent(mInterfaceName,
WifiIsUnusableEvent.TYPE_IP_REACHABILITY_LOST);
- mWifiMetrics.addToWifiUsabilityStatsList(mInterfaceName,
- WifiUsabilityStats.LABEL_BAD,
- WifiUsabilityStats.TYPE_IP_REACHABILITY_LOST, -1);
+ mWifiMetrics.logAsynchronousEvent(mInterfaceName,
+ WifiUsabilityStatsEntry.CAPTURE_EVENT_TYPE_IP_REACHABILITY_LOST, -1);
if (mWifiGlobals.getIpReachabilityDisconnectEnabled()) {
handleIpReachabilityLost(-1);
} else {
@@ -6645,15 +6640,17 @@
if (!isFromCurrentIpClientCallbacks(message)) break;
mWifiDiagnostics.triggerBugReportDataCapture(
WifiDiagnostics.REPORT_REASON_REACHABILITY_FAILURE);
+ mWifiMetrics.logAsynchronousEvent(mInterfaceName,
+ WifiUsabilityStatsEntry.CAPTURE_EVENT_TYPE_IP_REACHABILITY_FAILURE,
+ ((ReachabilityLossInfoParcelable) message.obj).reason);
handleIpReachabilityFailure((ReachabilityLossInfoParcelable) message.obj);
break;
}
case WifiP2pServiceImpl.DISCONNECT_WIFI_REQUEST: {
if (mWifiP2pConnection.shouldTemporarilyDisconnectWifi()) {
- mWifiMetrics.logStaEvent(mInterfaceName, StaEvent.TYPE_FRAMEWORK_DISCONNECT,
- StaEvent.DISCONNECT_P2P_DISCONNECT_WIFI_REQUEST);
mFrameworkDisconnectReasonOverride = WifiStatsLog.WIFI_DISCONNECT_REPORTED__FAILURE_CODE__DISCONNECT_P2P_REQUESTED_DISCONNECT;
- mWifiNative.disconnect(mInterfaceName);
+ sendMessageAtFrontOfQueue(CMD_DISCONNECT,
+ StaEvent.DISCONNECT_P2P_DISCONNECT_WIFI_REQUEST);
}
break;
}
@@ -6707,7 +6704,7 @@
}
case CMD_ONESHOT_RSSI_POLL: {
if (!mEnableRssiPolling) {
- updateLinkLayerStatsRssiDataStallScoreReport();
+ updateLinkLayerStatsRssiDataStallScoreReport(true);
}
break;
}
@@ -6719,7 +6716,7 @@
break;
}
if (message.arg1 == mRssiPollToken) {
- updateLinkLayerStatsRssiDataStallScoreReport();
+ updateLinkLayerStatsRssiDataStallScoreReport(false);
mWifiScoreCard.noteSignalPoll(mWifiInfo);
// Update the polling interval as needed before sending the delayed message
// so that the next polling can happen after the updated interval
@@ -6751,10 +6748,14 @@
updateLinkLayerStatsRssiSpeedFrequencyCapabilities(txBytes, rxBytes);
sendMessageDelayed(obtainMessage(CMD_RSSI_POLL, mRssiPollToken, 0),
mWifiGlobals.getPollRssiIntervalMillis());
+ mWifiMetrics.logAsynchronousEvent(mInterfaceName,
+ WifiUsabilityStatsEntry.CAPTURE_EVENT_TYPE_RSSI_POLLING_ENABLED);
}
else {
mRssiMonitor.setShortPollRssiInterval();
removeMessages(CMD_RSSI_POLL);
+ mWifiMetrics.logAsynchronousEvent(mInterfaceName,
+ WifiUsabilityStatsEntry.CAPTURE_EVENT_TYPE_RSSI_POLLING_DISABLED);
}
break;
}
@@ -6914,8 +6915,10 @@
/**
* Fetches link stats, updates Wifi Data Stall, Score Card and Score Report.
+ *
+ * oneshot indicates that this update request came from CMD_ONESHOT_RSSI_POLL.
*/
- private WifiLinkLayerStats updateLinkLayerStatsRssiDataStallScoreReport() {
+ private WifiLinkLayerStats updateLinkLayerStatsRssiDataStallScoreReport(boolean oneshot) {
// Get Info and continue polling
long txBytes;
long rxBytes;
@@ -6928,12 +6931,19 @@
}
WifiLinkLayerStats stats = updateLinkLayerStatsRssiSpeedFrequencyCapabilities(txBytes,
rxBytes);
- mWifiMetrics.updateWifiUsabilityStatsEntries(mInterfaceName, mWifiInfo, stats);
// checkDataStallAndThroughputSufficiency() should be called before
// mWifiScoreReport.calculateAndReportScore() which needs the latest throughput
int statusDataStall = mWifiDataStall.checkDataStallAndThroughputSufficiency(
mInterfaceName, mLastConnectionCapabilities, mLastLinkLayerStats, stats,
mWifiInfo, txBytes, rxBytes);
+ // This function will update stats that are used for WifiUsabilityStatsEntry and
+ // logScorerPredictionResult, so it should be called before
+ // mWifiMetrics.updateWifiUsabilityStatsEntries and
+ // mWifiMetrics.logScorerPredictionResult
+ mWifiMetrics.updateWiFiEvaluationAndScorerStats(mWifiScoreReport.getLingering(),
+ mWifiInfo, mLastConnectionCapabilities);
+ mWifiMetrics.updateWifiUsabilityStatsEntries(mInterfaceName, mWifiInfo, stats, oneshot,
+ statusDataStall);
if (getClientRoleForMetrics(getConnectedWifiConfiguration())
== WIFI_CONNECTION_RESULT_REPORTED__ROLE__ROLE_CLIENT_PRIMARY) {
mWifiMetrics.logScorerPredictionResult(mWifiInjector.hasActiveModem(),
@@ -6941,29 +6951,9 @@
mWifiCarrierInfoManager.isMobileDataEnabled(),
mWifiGlobals.getPollRssiIntervalMillis(),
mWifiScoreReport.getAospScorerPredictionStatusForEvaluation(),
- mWifiScoreReport.getExternalScorerPredictionStatusForEvaluation(),
- mWifiScoreReport.getLingering(),
- mWifiInfo, mLastConnectionCapabilities);
+ mWifiScoreReport.getExternalScorerPredictionStatusForEvaluation());
mWifiScoreReport.clearScorerPredictionStatusForEvaluation();
}
-
- if (mDataStallTriggerTimeMs == -1
- && statusDataStall != WifiIsUnusableEvent.TYPE_UNKNOWN) {
- mDataStallTriggerTimeMs = mClock.getElapsedSinceBootMillis();
- mLastStatusDataStall = statusDataStall;
- }
- if (mDataStallTriggerTimeMs != -1) {
- long elapsedTime = mClock.getElapsedSinceBootMillis()
- - mDataStallTriggerTimeMs;
- if (elapsedTime >= DURATION_TO_WAIT_ADD_STATS_AFTER_DATA_STALL_MS) {
- mDataStallTriggerTimeMs = -1;
- mWifiMetrics.addToWifiUsabilityStatsList(mInterfaceName,
- WifiUsabilityStats.LABEL_BAD,
- convertToUsabilityStatsTriggerType(mLastStatusDataStall),
- -1);
- mLastStatusDataStall = WifiIsUnusableEvent.TYPE_UNKNOWN;
- }
- }
// Send the update score to network agent.
mWifiScoreReport.calculateAndReportScore();
@@ -7273,9 +7263,8 @@
mRoamFailCount++;
handleNetworkDisconnect(false,
WifiStatsLog.WIFI_DISCONNECT_REPORTED__FAILURE_CODE__ROAM_WATCHDOG_TIMER);
- mWifiMetrics.logStaEvent(mInterfaceName, StaEvent.TYPE_FRAMEWORK_DISCONNECT,
+ sendMessageAtFrontOfQueue(CMD_DISCONNECT,
StaEvent.DISCONNECT_ROAM_WATCHDOG_TIMER);
- mWifiNative.disconnect(mInterfaceName);
transitionTo(mDisconnectedState);
}
break;
@@ -7367,7 +7356,7 @@
@Override
public void enterImpl() {
if (mVerboseLoggingEnabled) {
- log("Enter ConnectedState mScreenOn=" + mScreenOn);
+ log("Enter ConnectedState mScreenOn=" + mScreenOn);
}
reportConnectionAttemptEnd(
@@ -7426,8 +7415,6 @@
switch (message.what) {
case CMD_UNWANTED_NETWORK: {
if (message.arg1 == NETWORK_STATUS_UNWANTED_DISCONNECT) {
- mWifiMetrics.logStaEvent(mInterfaceName, StaEvent.TYPE_FRAMEWORK_DISCONNECT,
- StaEvent.DISCONNECT_UNWANTED);
if (mClientModeManager.getRole() == ROLE_CLIENT_SECONDARY_TRANSIENT
&& mClientModeManager.getPreviousRole() == ROLE_CLIENT_PRIMARY) {
mWifiMetrics.incrementMakeBeforeBreakLingerCompletedCount(
@@ -7452,7 +7439,7 @@
DISABLED_UNWANTED_LOW_RSSI);
}
mFrameworkDisconnectReasonOverride = WifiStatsLog.WIFI_DISCONNECT_REPORTED__FAILURE_CODE__DISCONNECT_UNWANTED_BY_CONNECTIVITY;
- mWifiNative.disconnect(mInterfaceName);
+ sendMessageAtFrontOfQueue(CMD_DISCONNECT, StaEvent.DISCONNECT_UNWANTED);
} else if (message.arg1 == NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN
|| message.arg1 == NETWORK_STATUS_UNWANTED_VALIDATION_FAILED) {
Log.d(getTag(), (message.arg1 == NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN
@@ -8085,21 +8072,21 @@
* @return true if this device supports FILS-SHA256
*/
private boolean isFilsSha256Supported() {
- return (getSupportedFeatures() & WIFI_FEATURE_FILS_SHA256) != 0;
+ return getSupportedFeatures().get(WIFI_FEATURE_FILS_SHA256);
}
/**
* @return true if this device supports FILS-SHA384
*/
private boolean isFilsSha384Supported() {
- return (getSupportedFeatures() & WIFI_FEATURE_FILS_SHA384) != 0;
+ return getSupportedFeatures().get(WIFI_FEATURE_FILS_SHA384);
}
/**
* @return true if this device supports Trust On First Use
*/
private boolean isTrustOnFirstUseSupported() {
- return (getSupportedFeatures() & WIFI_FEATURE_TRUST_ON_FIRST_USE) != 0;
+ return getSupportedFeatures().get(WIFI_FEATURE_TRUST_ON_FIRST_USE);
}
/**
@@ -8913,4 +8900,38 @@
mWifiInjector.getActiveModeWarden().updateCurrentConnectionInfo();
}
}
+
+ @Override
+ public void blockNetwork(BlockingOption option) {
+ if (mLastNetworkId == WifiConfiguration.INVALID_NETWORK_ID) {
+ Log.e(TAG, "Calling blockNetwork when disconnected");
+ return;
+ }
+ WifiConfiguration configuration = mWifiConfigManager.getConfiguredNetwork(mLastNetworkId);
+ if (configuration == null) {
+ Log.e(TAG, "No available config for networkId: " + mLastNetworkId);
+ return;
+ }
+ if (mLastBssid == null) {
+ Log.e(TAG, "No available BSSID for networkId: " + mLastNetworkId);
+ return;
+ }
+ if (option.isBlockingBssidOnly()) {
+ mWifiBlocklistMonitor.blockBssidForDurationMs(mLastBssid,
+ mWifiConfigManager.getConfiguredNetwork(mLastNetworkId),
+ option.getBlockingTimeSeconds() * 1000L, REASON_APP_DISALLOW, 0);
+ } else {
+ ScanDetailCache scanDetailCache = mWifiConfigManager
+ .getScanDetailCacheForNetwork(mLastNetworkId);
+ for (String bssid : scanDetailCache.keySet()) {
+ if (bssid.regionMatches(true, 0, mLastBssid, 0,
+ LINK_CONFIGURATION_BSSID_MATCH_LENGTH)) {
+ mWifiBlocklistMonitor.blockBssidForDurationMs(bssid,
+ mWifiConfigManager.getConfiguredNetwork(mLastNetworkId),
+ option.getBlockingTimeSeconds() * 1000L, REASON_APP_DISALLOW, 0);
+ }
+ }
+ }
+ mWifiBlocklistMonitor.updateAndGetBssidBlocklistForSsids(Set.of(configuration.SSID));
+ }
}
diff --git a/service/java/com/android/server/wifi/ConcreteClientModeManager.java b/service/java/com/android/server/wifi/ConcreteClientModeManager.java
index 33c5f31..36a43a5 100644
--- a/service/java/com/android/server/wifi/ConcreteClientModeManager.java
+++ b/service/java/com/android/server/wifi/ConcreteClientModeManager.java
@@ -30,6 +30,7 @@
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
+import android.net.wifi.BlockingOption;
import android.net.wifi.IWifiConnectedNetworkScorer;
import android.net.wifi.WifiAnnotations;
import android.net.wifi.WifiConfiguration;
@@ -75,6 +76,7 @@
import java.io.PrintWriter;
import java.util.ArrayDeque;
import java.util.ArrayList;
+import java.util.BitSet;
import java.util.List;
import java.util.Set;
@@ -1479,7 +1481,7 @@
}
@Override
- public long getSupportedFeatures() {
+ public @NonNull BitSet getSupportedFeatures() {
return getClientMode().getSupportedFeatures();
}
@@ -1724,4 +1726,9 @@
public void onIdleModeChanged(boolean isIdle) {
getClientMode().onIdleModeChanged(isIdle);
}
+
+ @Override
+ public void blockNetwork(BlockingOption option) {
+ getClientMode().blockNetwork(option);
+ }
}
diff --git a/service/java/com/android/server/wifi/DefaultClientModeManager.java b/service/java/com/android/server/wifi/DefaultClientModeManager.java
index 450dd1e..b289640 100644
--- a/service/java/com/android/server/wifi/DefaultClientModeManager.java
+++ b/service/java/com/android/server/wifi/DefaultClientModeManager.java
@@ -16,11 +16,13 @@
package com.android.server.wifi;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.WorkSource;
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.util.BitSet;
/**
* This is used for creating a public {@link ClientModeManager} instance when wifi is off.
@@ -81,8 +83,8 @@
}
@Override
- public long getSupportedFeatures() {
- return 0L;
+ public @NonNull BitSet getSupportedFeatures() {
+ return new BitSet();
}
@Override
diff --git a/service/java/com/android/server/wifi/HalDeviceManager.java b/service/java/com/android/server/wifi/HalDeviceManager.java
index 8d0d9c4..a251af8 100644
--- a/service/java/com/android/server/wifi/HalDeviceManager.java
+++ b/service/java/com/android/server/wifi/HalDeviceManager.java
@@ -19,7 +19,7 @@
import static com.android.server.wifi.HalDeviceManagerUtil.jsonToStaticChipInfo;
import static com.android.server.wifi.HalDeviceManagerUtil.staticChipInfoToJson;
import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_STATIC_CHIP_INFO;
-import static com.android.server.wifi.util.GeneralUtil.bitsetToLong;
+import static com.android.server.wifi.util.GeneralUtil.longToBitset;
import android.annotation.IntDef;
import android.annotation.NonNull;
@@ -83,8 +83,9 @@
private final FeatureFlags mFeatureFlags;
private boolean mDbg = false;
- public static final long CHIP_CAPABILITY_ANY = 0L;
- private static final long CHIP_CAPABILITY_UNINITIALIZED = -1L;
+ public static final BitSet CHIP_CAPABILITY_ANY = new BitSet();
+ // TODO: Determine if CHIP_CAPABILITY_UNINITIALIZED can be replaced with an empty BitSet
+ private static final BitSet CHIP_CAPABILITY_UNINITIALIZED = longToBitset(-1L);
private static final int DBS_24G_5G_MASK =
WifiScanner.WIFI_BAND_24_GHZ | WifiScanner.WIFI_BAND_5_GHZ;
@@ -322,8 +323,9 @@
* @param concreteClientModeManager ConcreteClientModeManager requesting the interface.
* @return A newly created interface - or null if the interface could not be created.
*/
- public WifiStaIface createStaIface(
- long requiredChipCapabilities,
+ @VisibleForTesting
+ protected WifiStaIface createStaIface(
+ @NonNull BitSet requiredChipCapabilities,
@Nullable InterfaceDestroyedListener destroyedListener, @Nullable Handler handler,
@NonNull WorkSource requestorWs,
@NonNull ConcreteClientModeManager concreteClientModeManager) {
@@ -332,7 +334,8 @@
return null;
}
WifiStaIface staIface = (WifiStaIface) createIface(HDM_CREATE_IFACE_STA,
- requiredChipCapabilities, destroyedListener, handler, requestorWs, null);
+ requiredChipCapabilities, destroyedListener, handler, requestorWs, null,
+ false /* isUsingMultiLinkOperation */);
if (staIface != null) {
mClientModeManagers.put(getName(staIface), concreteClientModeManager);
}
@@ -367,7 +370,7 @@
* Create AP interface if possible (see createStaIface doc).
*/
public WifiApIface createApIface(
- long requiredChipCapabilities,
+ @NonNull BitSet requiredChipCapabilities,
@Nullable InterfaceDestroyedListener destroyedListener, @Nullable Handler handler,
@NonNull WorkSource requestorWs, boolean isBridged,
@NonNull SoftApManager softApManager, @NonNull List<OuiKeyedData> vendorData) {
@@ -377,7 +380,7 @@
}
WifiApIface apIface = (WifiApIface) createIface(isBridged ? HDM_CREATE_IFACE_AP_BRIDGE
: HDM_CREATE_IFACE_AP, requiredChipCapabilities, destroyedListener,
- handler, requestorWs, vendorData);
+ handler, requestorWs, vendorData, softApManager.isUsingMlo());
if (apIface != null) {
mSoftApManagers.put(getName(apIface), softApManager);
}
@@ -387,12 +390,14 @@
/**
* Create P2P interface if possible (see createStaIface doc).
*/
- public String createP2pIface(
- long requiredChipCapabilities,
+ @VisibleForTesting
+ protected String createP2pIface(
+ @NonNull BitSet requiredChipCapabilities,
@Nullable InterfaceDestroyedListener destroyedListener,
@Nullable Handler handler, @NonNull WorkSource requestorWs) {
WifiP2pIface iface = (WifiP2pIface) createIface(HDM_CREATE_IFACE_P2P,
- requiredChipCapabilities, destroyedListener, handler, requestorWs, null);
+ requiredChipCapabilities, destroyedListener, handler, requestorWs, null,
+ false /* isUsingMultiLinkOperation */);
if (iface == null) {
return null;
}
@@ -419,7 +424,8 @@
public WifiNanIface createNanIface(@Nullable InterfaceDestroyedListener destroyedListener,
@Nullable Handler handler, @NonNull WorkSource requestorWs) {
return (WifiNanIface) createIface(HDM_CREATE_IFACE_NAN, CHIP_CAPABILITY_ANY,
- destroyedListener, handler, requestorWs, null);
+ destroyedListener, handler, requestorWs, null,
+ false /* isUsingMultiLinkOperation */);
}
/**
@@ -818,8 +824,9 @@
* interface using rules based on the requestor app's context.
* @return true if the device supports the provided combo, false otherwise.
*/
- public boolean isItPossibleToCreateIface(@HdmIfaceTypeForCreation int createIfaceType,
- long requiredChipCapabilities, WorkSource requestorWs) {
+ @VisibleForTesting
+ protected boolean isItPossibleToCreateIface(@HdmIfaceTypeForCreation int createIfaceType,
+ BitSet requiredChipCapabilities, WorkSource requestorWs) {
if (VDBG) {
Log.d(TAG, "isItPossibleToCreateIface: createIfaceType=" + createIfaceType
+ ", requiredChipCapabilities=" + requiredChipCapabilities);
@@ -863,7 +870,7 @@
*/
private List<WifiIfaceInfo> getIfacesToDestroyForRequest(
@HdmIfaceTypeForCreation int createIfaceType, boolean queryForNewInterface,
- long requiredChipCapabilities, WorkSource requestorWs) {
+ BitSet requiredChipCapabilities, WorkSource requestorWs) {
if (VDBG) {
Log.d(TAG, "getIfacesToDestroyForRequest: ifaceType=" + createIfaceType
+ ", requiredChipCapabilities=" + requiredChipCapabilities
@@ -1066,7 +1073,7 @@
// Arrays of WifiIfaceInfo indexed by @HdmIfaceTypeForCreation, in order of creation as
// returned by WifiChip.getXxxIfaceNames.
public WifiIfaceInfo[][] ifaces = new WifiIfaceInfo[CREATE_TYPES_BY_PRIORITY.length][];
- public long chipCapabilities;
+ public BitSet chipCapabilities = new BitSet();
public List<WifiChip.WifiRadioCombination> radioCombinations = null;
// A data structure for the faster band combination lookup.
public Set<List<Integer>> bandCombinations = null;
@@ -1208,7 +1215,7 @@
return null;
}
- long chipCapabilities = getChipCapabilities(chip);
+ BitSet chipCapabilities = getChipCapabilities(chip);
List<String> ifaceNames = chip.getStaIfaceNames();
if (ifaceNames == null) {
@@ -1378,6 +1385,7 @@
}
} catch (JSONException e) {
Log.e(TAG, "Failed to load static chip info from store: " + e);
+ return new StaticChipInfo[0];
}
return staticChipInfos;
}
@@ -1390,7 +1398,6 @@
WifiChipInfo chipInfo = chipInfos[i];
staticChipInfos[i] = new StaticChipInfo(
chipInfo.chipId,
- chipInfo.chipCapabilities,
chipInfo.availableModes);
}
return staticChipInfos;
@@ -1616,8 +1623,9 @@
}
private WifiHal.WifiInterface createIface(@HdmIfaceTypeForCreation int createIfaceType,
- long requiredChipCapabilities, InterfaceDestroyedListener destroyedListener,
- Handler handler, WorkSource requestorWs, @Nullable List<OuiKeyedData> vendorData) {
+ BitSet requiredChipCapabilities, InterfaceDestroyedListener destroyedListener,
+ Handler handler, WorkSource requestorWs, @Nullable List<OuiKeyedData> vendorData,
+ boolean isUsingMultiLinkOperation) {
if (mDbg) {
Log.d(TAG, "createIface: createIfaceType=" + createIfaceType
+ ", requiredChipCapabilities=" + requiredChipCapabilities
@@ -1628,6 +1636,10 @@
+ "with NonNull destroyedListener but Null handler");
return null;
}
+ if (requiredChipCapabilities == null) {
+ Log.wtf(TAG, "createIface received null required chip capabilities");
+ return null;
+ }
synchronized (mLock) {
WifiChipInfo[] chipInfos = getAllChipInfo(false);
@@ -1649,23 +1661,33 @@
return createIfaceIfPossible(
chipInfos, createIfaceType, requiredChipCapabilities,
- destroyedListener, handler, requestorWs, vendorData);
+ destroyedListener, handler, requestorWs, vendorData,
+ isUsingMultiLinkOperation);
}
}
- private static boolean isChipCapabilitiesSupported(long currentChipCapabilities,
- long requiredChipCapabilities) {
- if (requiredChipCapabilities == CHIP_CAPABILITY_ANY) return true;
+ @VisibleForTesting
+ protected static boolean areChipCapabilitiesSupported(BitSet currentChipCapabilities,
+ BitSet requiredChipCapabilities) {
+ if (requiredChipCapabilities == null
+ || requiredChipCapabilities.equals(CHIP_CAPABILITY_ANY)) {
+ // No capabilities are required for this operation
+ return true;
+ }
+ if (currentChipCapabilities.equals(CHIP_CAPABILITY_UNINITIALIZED)) {
+ return true;
+ }
- if (CHIP_CAPABILITY_UNINITIALIZED == currentChipCapabilities) return true;
-
- return (currentChipCapabilities & requiredChipCapabilities)
- == requiredChipCapabilities;
+ // Check if the chip supports the required capabilities using
+ // (requiredChipCapabilities & currentChipCapabilities) == requiredChipCapabilities
+ BitSet tempRequiredCapabilities = (BitSet) requiredChipCapabilities.clone();
+ tempRequiredCapabilities.and(currentChipCapabilities);
+ return tempRequiredCapabilities.equals(requiredChipCapabilities);
}
private IfaceCreationData getBestIfaceCreationProposal(
WifiChipInfo[] chipInfos, @HdmIfaceTypeForCreation int createIfaceType,
- long requiredChipCapabilities, WorkSource requestorWs) {
+ BitSet requiredChipCapabilities, WorkSource requestorWs) {
int targetHalIfaceType = HAL_IFACE_MAP.get(createIfaceType);
if (VDBG) {
Log.d(TAG, "getBestIfaceCreationProposal: chipInfos=" + Arrays.deepToString(chipInfos)
@@ -1677,7 +1699,7 @@
synchronized (mLock) {
IfaceCreationData bestIfaceCreationProposal = null;
for (WifiChipInfo chipInfo : chipInfos) {
- if (!isChipCapabilitiesSupported(
+ if (!areChipCapabilitiesSupported(
chipInfo.chipCapabilities, requiredChipCapabilities)) {
continue;
}
@@ -1749,15 +1771,17 @@
private WifiHal.WifiInterface createIfaceIfPossible(
WifiChipInfo[] chipInfos, @HdmIfaceTypeForCreation int createIfaceType,
- long requiredChipCapabilities, InterfaceDestroyedListener destroyedListener,
- Handler handler, WorkSource requestorWs, @Nullable List<OuiKeyedData> vendorData) {
+ BitSet requiredChipCapabilities, InterfaceDestroyedListener destroyedListener,
+ Handler handler, WorkSource requestorWs, @Nullable List<OuiKeyedData> vendorData,
+ boolean isUsingMultiLinkOperation) {
int targetHalIfaceType = HAL_IFACE_MAP.get(createIfaceType);
if (VDBG) {
Log.d(TAG, "createIfaceIfPossible: chipInfos=" + Arrays.deepToString(chipInfos)
+ ", createIfaceType=" + createIfaceType
+ ", targetHalIfaceType=" + targetHalIfaceType
+ ", requiredChipCapabilities=" + requiredChipCapabilities
- + ", requestorWs=" + requestorWs);
+ + ", requestorWs=" + requestorWs
+ + ", isUsingMultiLinkOperation" + isUsingMultiLinkOperation);
}
if (vendorData != null && !vendorData.isEmpty()) {
Log.d(TAG, "Request includes vendor data. ifaceType=" + createIfaceType
@@ -1769,7 +1793,7 @@
if (bestIfaceCreationProposal != null) {
WifiHal.WifiInterface iface = executeChipReconfiguration(bestIfaceCreationProposal,
- createIfaceType, vendorData);
+ createIfaceType, vendorData, isUsingMultiLinkOperation);
if (iface == null) {
// If the chip reconfiguration failed, we'll need to clean up internal state.
Log.e(TAG, "Teardown Wifi internal state");
@@ -1876,6 +1900,51 @@
return false;
}
+ private boolean isRequestorAllowedToUseApNanConcurrency(WorkSource requestorWs) {
+ String[] allowlistArray = mContext.getResources().getStringArray(
+ R.array.config_wifiSoftApAwareConcurrencyAllowlist);
+ if (allowlistArray == null || allowlistArray.length == 0) {
+ // No allowlist defined, so allow.
+ return true;
+ }
+ List<String> allowlist = Arrays.asList(allowlistArray);
+ for (int i = 0; i < requestorWs.size(); i++) {
+ if (allowlist.contains(requestorWs.getPackageName(i))) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Remove AP from the combo if NAN requested (or NAN if AP is requested) if the current
+ * requestor is not allowed to use AP/NAN concurrency.
+ */
+ @NonNull
+ private int[] removeApNanConcurrencyIfNotAllowed(
+ @NonNull int[] chipCreateTypeCombo,
+ @HdmIfaceTypeForCreation int requestedCreateType,
+ WorkSource requestorWs) {
+ if (isRequestorAllowedToUseApNanConcurrency(requestorWs)) {
+ return chipCreateTypeCombo;
+ }
+
+ int[] newCombo = chipCreateTypeCombo.clone();
+ switch (requestedCreateType) {
+ case HDM_CREATE_IFACE_AP:
+ case HDM_CREATE_IFACE_AP_BRIDGE:
+ newCombo[HDM_CREATE_IFACE_NAN] = 0;
+ break;
+ case HDM_CREATE_IFACE_NAN:
+ newCombo[HDM_CREATE_IFACE_AP] = 0;
+ newCombo[HDM_CREATE_IFACE_AP_BRIDGE] = 0;
+ break;
+ default:
+ break;
+ }
+ return newCombo;
+ }
+
/**
* Checks whether the input chip-create-type-combo can support the requested create type:
* if not then returns null, if yes then returns information containing the list of interfaces
@@ -1923,6 +1992,10 @@
}
}
+ // Remove AP/NAN concurrency if the requestor isn't on the allowlist.
+ chipCreateTypeCombo = removeApNanConcurrencyIfNotAllowed(
+ chipCreateTypeCombo, requestedCreateType, requestorWs);
+
IfaceCreationData ifaceCreationData = new IfaceCreationData();
ifaceCreationData.chipInfo = chipInfo;
ifaceCreationData.chipModeId = chipModeId;
@@ -2414,7 +2487,8 @@
* Returns the newly created interface or a null on any error.
*/
private WifiHal.WifiInterface executeChipReconfiguration(IfaceCreationData ifaceCreationData,
- @HdmIfaceTypeForCreation int createIfaceType, @Nullable List<OuiKeyedData> vendorData) {
+ @HdmIfaceTypeForCreation int createIfaceType, @Nullable List<OuiKeyedData> vendorData,
+ boolean isUsingMultiLinkOperation) {
if (mDbg) {
Log.d(TAG, "executeChipReconfiguration: ifaceCreationData=" + ifaceCreationData
+ ", createIfaceType=" + createIfaceType);
@@ -2488,7 +2562,8 @@
iface = ifaceCreationData.chipInfo.chip.createStaIface();
break;
case HDM_CREATE_IFACE_AP_BRIDGE:
- iface = ifaceCreationData.chipInfo.chip.createBridgedApIface(vendorData);
+ iface = ifaceCreationData.chipInfo.chip.createBridgedApIface(vendorData,
+ isUsingMultiLinkOperation);
break;
case HDM_CREATE_IFACE_AP:
iface = ifaceCreationData.chipInfo.chip.createApIface(vendorData);
@@ -2858,18 +2933,18 @@
* @param wifiChip WifiChip to get the features for.
* @return Bitset of WifiManager.WIFI_FEATURE_* values.
*/
- private long getChipCapabilities(@NonNull WifiChip wifiChip) {
- if (wifiChip == null) return 0;
+ private BitSet getChipCapabilities(@NonNull WifiChip wifiChip) {
+ if (wifiChip == null) return new BitSet();
WifiChip.Response<BitSet> capsResp = wifiChip.getCapabilitiesBeforeIfacesExist();
if (capsResp.getStatusCode() == WifiHal.WIFI_STATUS_SUCCESS) {
- return bitsetToLong(capsResp.getValue());
+ return capsResp.getValue();
} else if (capsResp.getStatusCode() != WifiHal.WIFI_STATUS_ERROR_REMOTE_EXCEPTION) {
// Non-remote exception here is likely because HIDL HAL < v1.5
// does not support getting capabilities before creating an interface.
return CHIP_CAPABILITY_UNINITIALIZED;
} else { // remote exception
- return 0;
+ return new BitSet();
}
}
diff --git a/service/java/com/android/server/wifi/HalDeviceManagerUtil.java b/service/java/com/android/server/wifi/HalDeviceManagerUtil.java
index 5897307..09aa486 100644
--- a/service/java/com/android/server/wifi/HalDeviceManagerUtil.java
+++ b/service/java/com/android/server/wifi/HalDeviceManagerUtil.java
@@ -33,15 +33,12 @@
public class HalDeviceManagerUtil {
static class StaticChipInfo {
private int mChipId;
- private long mChipCapabilities;
private @NonNull ArrayList<WifiChip.ChipMode> mAvailableModes = new ArrayList<>();
StaticChipInfo(
int chipId,
- long chipCapabilities,
@NonNull ArrayList<WifiChip.ChipMode> availableModes) {
mChipId = chipId;
- mChipCapabilities = chipCapabilities;
if (availableModes != null) {
mAvailableModes = availableModes;
}
@@ -51,24 +48,18 @@
return mChipId;
}
- long getChipCapabilities() {
- return mChipCapabilities;
- }
-
ArrayList<WifiChip.ChipMode> getAvailableModes() {
return mAvailableModes;
}
}
private static final String KEY_CHIP_ID = "chipId";
- private static final String KEY_CHIP_CAPABILITIES = "chipCapabilities";
private static final String KEY_AVAILABLE_MODES = "availableModes";
static JSONObject staticChipInfoToJson(@NonNull StaticChipInfo staticChipInfo)
throws JSONException {
JSONObject jsonObject = new JSONObject();
jsonObject.put(KEY_CHIP_ID, staticChipInfo.getChipId());
- jsonObject.put(KEY_CHIP_CAPABILITIES, staticChipInfo.getChipCapabilities());
JSONArray availableModesJson = new JSONArray();
for (WifiChip.ChipMode mode : staticChipInfo.getAvailableModes()) {
availableModesJson.put(chipModeToJson(mode));
@@ -80,12 +71,11 @@
static StaticChipInfo jsonToStaticChipInfo(JSONObject jsonObject) throws JSONException {
ArrayList<WifiChip.ChipMode> availableModes = new ArrayList<>();
int chipId = jsonObject.getInt(KEY_CHIP_ID);
- long chipCapabilities = jsonObject.getLong(KEY_CHIP_CAPABILITIES);
JSONArray modesJson = jsonObject.getJSONArray(KEY_AVAILABLE_MODES);
for (int i = 0; i < modesJson.length(); i++) {
availableModes.add(jsonToChipMode(modesJson.getJSONObject(i)));
}
- return new StaticChipInfo(chipId, chipCapabilities, availableModes);
+ return new StaticChipInfo(chipId, availableModes);
}
private static final String KEY_ID = "id";
diff --git a/service/java/com/android/server/wifi/HostapdHal.java b/service/java/com/android/server/wifi/HostapdHal.java
index 7d7b2bf..149973c 100644
--- a/service/java/com/android/server/wifi/HostapdHal.java
+++ b/service/java/com/android/server/wifi/HostapdHal.java
@@ -28,6 +28,7 @@
import com.android.server.wifi.WifiNative.SoftApHalCallback;
import java.io.PrintWriter;
+import java.util.List;
import javax.annotation.concurrent.ThreadSafe;
@@ -160,13 +161,16 @@
* @return true on success, false otherwise.
*/
public boolean addAccessPoint(@NonNull String ifaceName, @NonNull SoftApConfiguration config,
- boolean isMetered, @NonNull Runnable onFailureListener) {
+ boolean isMetered, boolean isUsingMultiLinkOperation,
+ @NonNull List<String> instanceIdentities,
+ @NonNull Runnable onFailureListener) {
synchronized (mLock) {
String methodStr = "addAccessPoint";
if (mIHostapd == null) {
return handleNullIHostapd(methodStr);
}
- return mIHostapd.addAccessPoint(ifaceName, config, isMetered, onFailureListener);
+ return mIHostapd.addAccessPoint(ifaceName, config, isMetered, isUsingMultiLinkOperation,
+ instanceIdentities, onFailureListener);
}
}
diff --git a/service/java/com/android/server/wifi/HostapdHalAidlImp.java b/service/java/com/android/server/wifi/HostapdHalAidlImp.java
index c689998..32c6376 100644
--- a/service/java/com/android/server/wifi/HostapdHalAidlImp.java
+++ b/service/java/com/android/server/wifi/HostapdHalAidlImp.java
@@ -16,6 +16,7 @@
package com.android.server.wifi;
import android.annotation.NonNull;
+import android.annotation.SuppressLint;
import android.hardware.wifi.hostapd.ApInfo;
import android.hardware.wifi.hostapd.BandMask;
import android.hardware.wifi.hostapd.ChannelBandwidth;
@@ -32,6 +33,7 @@
import android.hardware.wifi.hostapd.IfaceParams;
import android.hardware.wifi.hostapd.NetworkParams;
import android.net.MacAddress;
+import android.net.wifi.DeauthenticationReasonCode;
import android.net.wifi.OuiKeyedData;
import android.net.wifi.ScanResult;
import android.net.wifi.SoftApConfiguration;
@@ -40,6 +42,7 @@
import android.net.wifi.WifiAnnotations;
import android.net.wifi.WifiContext;
import android.net.wifi.WifiManager;
+import android.net.wifi.util.Environment;
import android.net.wifi.util.WifiResourceCache;
import android.os.Handler;
import android.os.IBinder;
@@ -56,6 +59,7 @@
import com.android.server.wifi.util.ApConfigUtil;
import com.android.server.wifi.util.HalAidlUtil;
import com.android.server.wifi.util.NativeUtil;
+import com.android.wifi.flags.Flags;
import com.android.wifi.resources.R;
import java.io.PrintWriter;
@@ -232,7 +236,8 @@
*/
@Override
public boolean addAccessPoint(@NonNull String ifaceName, @NonNull SoftApConfiguration config,
- boolean isMetered, Runnable onFailureListener) {
+ boolean isMetered, boolean isUsingMultiLinkOperation, List<String> instanceIdentities,
+ Runnable onFailureListener) {
synchronized (mLock) {
final String methodStr = "addAccessPoint";
Log.d(TAG, methodStr + ": " + ifaceName);
@@ -240,7 +245,8 @@
return false;
}
try {
- IfaceParams ifaceParams = prepareIfaceParams(ifaceName, config);
+ IfaceParams ifaceParams = prepareIfaceParams(ifaceName, config,
+ isUsingMultiLinkOperation, instanceIdentities);
NetworkParams nwParams = prepareNetworkParams(isMetered, config);
if (ifaceParams == null || nwParams == null) {
Log.e(TAG, "addAccessPoint parameters could not be prepared.");
@@ -433,8 +439,12 @@
+ " isConnected: " + info.isConnected);
SoftApHalCallback callback = mSoftApHalCallbacks.get(info.ifaceName);
if (callback != null) {
+ int disconnectReasonCode = isServiceVersionAtLeast(3) && !info.isConnected
+ ? mapHalToFrameworkDeauthenticationReasonCode(info.disconnectReasonCode)
+ : DeauthenticationReasonCode.REASON_UNKNOWN;
callback.onConnectedClientsChanged(info.apIfaceInstance,
- MacAddress.fromBytes(info.clientAddress), info.isConnected);
+ MacAddress.fromBytes(info.clientAddress), info.isConnected,
+ disconnectReasonCode);
}
} catch (IllegalArgumentException iae) {
Log.e(TAG, " Invalid clientAddress, " + iae);
@@ -856,6 +866,176 @@
}
}
+ /**
+ * Convert from a HAL DeauthenticationReasonCode to its framework equivalent.
+ *
+ * @param deauthenticationReasonCode The deauthentication reason code defined in HAL.
+ * @return The corresponding {@link DeauthenticationReasonCode}.
+ */
+ @VisibleForTesting
+ @WifiAnnotations.SoftApDisconnectReason int mapHalToFrameworkDeauthenticationReasonCode(
+ int deauthenticationReasonCode) {
+ return switch (deauthenticationReasonCode) {
+ case android.hardware.wifi.common.DeauthenticationReasonCode.HOSTAPD_NO_REASON ->
+ DeauthenticationReasonCode.REASON_UNKNOWN;
+ case android.hardware.wifi.common.DeauthenticationReasonCode.UNSPECIFIED ->
+ DeauthenticationReasonCode.REASON_UNSPECIFIED;
+ case android.hardware.wifi.common.DeauthenticationReasonCode.PREV_AUTH_NOT_VALID ->
+ DeauthenticationReasonCode.REASON_PREV_AUTH_NOT_VALID;
+ case android.hardware.wifi.common.DeauthenticationReasonCode.DEAUTH_LEAVING ->
+ DeauthenticationReasonCode.REASON_DEAUTH_LEAVING;
+ case android.hardware.wifi.common
+ .DeauthenticationReasonCode.DISASSOC_DUE_TO_INACTIVITY ->
+ DeauthenticationReasonCode.REASON_DISASSOC_DUE_TO_INACTIVITY;
+ case android.hardware.wifi.common.DeauthenticationReasonCode.DISASSOC_AP_BUSY ->
+ DeauthenticationReasonCode.REASON_DISASSOC_AP_BUSY;
+ case android.hardware.wifi.common
+ .DeauthenticationReasonCode.CLASS2_FRAME_FROM_NONAUTH_STA ->
+ DeauthenticationReasonCode.REASON_CLASS2_FRAME_FROM_NONAUTH_STA;
+ case android.hardware.wifi.common
+ .DeauthenticationReasonCode.CLASS3_FRAME_FROM_NONASSOC_STA ->
+ DeauthenticationReasonCode.REASON_CLASS3_FRAME_FROM_NONASSOC_STA;
+ case android.hardware.wifi.common.DeauthenticationReasonCode.DISASSOC_STA_HAS_LEFT ->
+ DeauthenticationReasonCode.REASON_DISASSOC_STA_HAS_LEFT;
+ case android.hardware.wifi.common
+ .DeauthenticationReasonCode.STA_REQ_ASSOC_WITHOUT_AUTH ->
+ DeauthenticationReasonCode.REASON_STA_REQ_ASSOC_WITHOUT_AUTH;
+ case android.hardware.wifi.common
+ .DeauthenticationReasonCode.PWR_CAPABILITY_NOT_VALID ->
+ DeauthenticationReasonCode.REASON_PWR_CAPABILITY_NOT_VALID;
+ case android.hardware.wifi.common
+ .DeauthenticationReasonCode.SUPPORTED_CHANNEL_NOT_VALID ->
+ DeauthenticationReasonCode.REASON_SUPPORTED_CHANNEL_NOT_VALID;
+ case android.hardware.wifi.common.DeauthenticationReasonCode.BSS_TRANSITION_DISASSOC ->
+ DeauthenticationReasonCode.REASON_BSS_TRANSITION_DISASSOC;
+ case android.hardware.wifi.common.DeauthenticationReasonCode.INVALID_IE ->
+ DeauthenticationReasonCode.REASON_INVALID_IE;
+ case android.hardware.wifi.common.DeauthenticationReasonCode.MICHAEL_MIC_FAILURE ->
+ DeauthenticationReasonCode.REASON_MICHAEL_MIC_FAILURE;
+ case android.hardware.wifi.common
+ .DeauthenticationReasonCode.FOURWAY_HANDSHAKE_TIMEOUT ->
+ DeauthenticationReasonCode.REASON_FOURWAY_HANDSHAKE_TIMEOUT;
+ case android.hardware.wifi.common
+ .DeauthenticationReasonCode.GROUP_KEY_UPDATE_TIMEOUT ->
+ DeauthenticationReasonCode.REASON_GROUP_KEY_UPDATE_TIMEOUT;
+ case android.hardware.wifi.common.DeauthenticationReasonCode.IE_IN_4WAY_DIFFERS ->
+ DeauthenticationReasonCode.REASON_IE_IN_4WAY_DIFFERS;
+ case android.hardware.wifi.common.DeauthenticationReasonCode.GROUP_CIPHER_NOT_VALID ->
+ DeauthenticationReasonCode.REASON_GROUP_CIPHER_NOT_VALID;
+ case android.hardware.wifi.common
+ .DeauthenticationReasonCode.PAIRWISE_CIPHER_NOT_VALID ->
+ DeauthenticationReasonCode.REASON_PAIRWISE_CIPHER_NOT_VALID;
+ case android.hardware.wifi.common.DeauthenticationReasonCode.AKMP_NOT_VALID ->
+ DeauthenticationReasonCode.REASON_AKMP_NOT_VALID;
+ case android.hardware.wifi.common
+ .DeauthenticationReasonCode.UNSUPPORTED_RSN_IE_VERSION ->
+ DeauthenticationReasonCode.REASON_UNSUPPORTED_RSN_IE_VERSION;
+ case android.hardware.wifi.common.DeauthenticationReasonCode.INVALID_RSN_IE_CAPAB ->
+ DeauthenticationReasonCode.REASON_INVALID_RSN_IE_CAPAB;
+ case android.hardware.wifi.common.DeauthenticationReasonCode.IEEE_802_1X_AUTH_FAILED ->
+ DeauthenticationReasonCode.REASON_IEEE_802_1X_AUTH_FAILED;
+ case android.hardware.wifi.common.DeauthenticationReasonCode.CIPHER_SUITE_REJECTED ->
+ DeauthenticationReasonCode.REASON_CIPHER_SUITE_REJECTED;
+ case android.hardware.wifi.common
+ .DeauthenticationReasonCode.TDLS_TEARDOWN_UNREACHABLE ->
+ DeauthenticationReasonCode.REASON_TDLS_TEARDOWN_UNREACHABLE;
+ case android.hardware.wifi.common
+ .DeauthenticationReasonCode.TDLS_TEARDOWN_UNSPECIFIED ->
+ DeauthenticationReasonCode.REASON_TDLS_TEARDOWN_UNSPECIFIED;
+ case android.hardware.wifi.common.DeauthenticationReasonCode.SSP_REQUESTED_DISASSOC ->
+ DeauthenticationReasonCode.REASON_SSP_REQUESTED_DISASSOC;
+ case android.hardware.wifi.common
+ .DeauthenticationReasonCode.NO_SSP_ROAMING_AGREEMENT ->
+ DeauthenticationReasonCode.REASON_NO_SSP_ROAMING_AGREEMENT;
+ case android.hardware.wifi.common.DeauthenticationReasonCode.BAD_CIPHER_OR_AKM ->
+ DeauthenticationReasonCode.REASON_BAD_CIPHER_OR_AKM;
+ case android.hardware.wifi.common
+ .DeauthenticationReasonCode.NOT_AUTHORIZED_THIS_LOCATION ->
+ DeauthenticationReasonCode.REASON_NOT_AUTHORIZED_THIS_LOCATION;
+ case android.hardware.wifi.common
+ .DeauthenticationReasonCode.SERVICE_CHANGE_PRECLUDES_TS ->
+ DeauthenticationReasonCode.REASON_SERVICE_CHANGE_PRECLUDES_TS;
+ case android.hardware.wifi.common.DeauthenticationReasonCode.UNSPECIFIED_QOS_REASON ->
+ DeauthenticationReasonCode.REASON_UNSPECIFIED_QOS_REASON;
+ case android.hardware.wifi.common.DeauthenticationReasonCode.NOT_ENOUGH_BANDWIDTH ->
+ DeauthenticationReasonCode.REASON_NOT_ENOUGH_BANDWIDTH;
+ case android.hardware.wifi.common.DeauthenticationReasonCode.DISASSOC_LOW_ACK ->
+ DeauthenticationReasonCode.REASON_DISASSOC_LOW_ACK;
+ case android.hardware.wifi.common.DeauthenticationReasonCode.EXCEEDED_TXOP ->
+ DeauthenticationReasonCode.REASON_EXCEEDED_TXOP;
+ case android.hardware.wifi.common.DeauthenticationReasonCode.STA_LEAVING ->
+ DeauthenticationReasonCode.REASON_STA_LEAVING;
+ case android.hardware.wifi.common.DeauthenticationReasonCode.END_TS_BA_DLS ->
+ DeauthenticationReasonCode.REASON_END_TS_BA_DLS;
+ case android.hardware.wifi.common.DeauthenticationReasonCode.UNKNOWN_TS_BA ->
+ DeauthenticationReasonCode.REASON_UNKNOWN_TS_BA;
+ case android.hardware.wifi.common.DeauthenticationReasonCode.TIMEOUT ->
+ DeauthenticationReasonCode.REASON_TIMEOUT;
+ case android.hardware.wifi.common.DeauthenticationReasonCode.PEERKEY_MISMATCH ->
+ DeauthenticationReasonCode.REASON_PEERKEY_MISMATCH;
+ case android.hardware.wifi.common
+ .DeauthenticationReasonCode.AUTHORIZED_ACCESS_LIMIT_REACHED ->
+ DeauthenticationReasonCode.REASON_AUTHORIZED_ACCESS_LIMIT_REACHED;
+ case android.hardware.wifi.common
+ .DeauthenticationReasonCode.EXTERNAL_SERVICE_REQUIREMENTS ->
+ DeauthenticationReasonCode.REASON_EXTERNAL_SERVICE_REQUIREMENTS;
+ case android.hardware.wifi.common
+ .DeauthenticationReasonCode.INVALID_FT_ACTION_FRAME_COUNT ->
+ DeauthenticationReasonCode.REASON_INVALID_FT_ACTION_FRAME_COUNT;
+ case android.hardware.wifi.common.DeauthenticationReasonCode.INVALID_PMKID ->
+ DeauthenticationReasonCode.REASON_INVALID_PMKID;
+ case android.hardware.wifi.common.DeauthenticationReasonCode.INVALID_MDE ->
+ DeauthenticationReasonCode.REASON_INVALID_MDE;
+ case android.hardware.wifi.common.DeauthenticationReasonCode.INVALID_FTE ->
+ DeauthenticationReasonCode.REASON_INVALID_FTE;
+ case android.hardware.wifi.common.DeauthenticationReasonCode.MESH_PEERING_CANCELLED ->
+ DeauthenticationReasonCode.REASON_MESH_PEERING_CANCELLED;
+ case android.hardware.wifi.common.DeauthenticationReasonCode.MESH_MAX_PEERS ->
+ DeauthenticationReasonCode.REASON_MESH_MAX_PEERS;
+ case android.hardware.wifi.common
+ .DeauthenticationReasonCode.MESH_CONFIG_POLICY_VIOLATION ->
+ DeauthenticationReasonCode.REASON_MESH_CONFIG_POLICY_VIOLATION;
+ case android.hardware.wifi.common.DeauthenticationReasonCode.MESH_CLOSE_RCVD ->
+ DeauthenticationReasonCode.REASON_MESH_CLOSE_RCVD;
+ case android.hardware.wifi.common.DeauthenticationReasonCode.MESH_MAX_RETRIES ->
+ DeauthenticationReasonCode.REASON_MESH_MAX_RETRIES;
+ case android.hardware.wifi.common.DeauthenticationReasonCode.MESH_CONFIRM_TIMEOUT ->
+ DeauthenticationReasonCode.REASON_MESH_CONFIRM_TIMEOUT;
+ case android.hardware.wifi.common.DeauthenticationReasonCode.MESH_INVALID_GTK ->
+ DeauthenticationReasonCode.REASON_MESH_INVALID_GTK;
+ case android.hardware.wifi.common
+ .DeauthenticationReasonCode.MESH_INCONSISTENT_PARAMS ->
+ DeauthenticationReasonCode.REASON_MESH_INCONSISTENT_PARAMS;
+ case android.hardware.wifi.common
+ .DeauthenticationReasonCode.MESH_INVALID_SECURITY_CAP ->
+ DeauthenticationReasonCode.REASON_MESH_INVALID_SECURITY_CAP;
+ case android.hardware.wifi.common
+ .DeauthenticationReasonCode.MESH_PATH_ERROR_NO_PROXY_INFO ->
+ DeauthenticationReasonCode.REASON_MESH_PATH_ERROR_NO_PROXY_INFO;
+ case android.hardware.wifi.common
+ .DeauthenticationReasonCode.MESH_PATH_ERROR_NO_FORWARDING_INFO ->
+ DeauthenticationReasonCode.REASON_MESH_PATH_ERROR_NO_FORWARDING_INFO;
+ case android.hardware.wifi.common
+ .DeauthenticationReasonCode.MESH_PATH_ERROR_DEST_UNREACHABLE ->
+ DeauthenticationReasonCode.REASON_MESH_PATH_ERROR_DEST_UNREACHABLE;
+ case android.hardware.wifi.common
+ .DeauthenticationReasonCode.MAC_ADDRESS_ALREADY_EXISTS_IN_MBSS ->
+ DeauthenticationReasonCode.REASON_MAC_ADDRESS_ALREADY_EXISTS_IN_MBSS;
+ case android.hardware.wifi.common
+ .DeauthenticationReasonCode.MESH_CHANNEL_SWITCH_REGULATORY_REQ ->
+ DeauthenticationReasonCode.REASON_MESH_CHANNEL_SWITCH_REGULATORY_REQ;
+ case android.hardware.wifi.common
+ .DeauthenticationReasonCode.MESH_CHANNEL_SWITCH_UNSPECIFIED ->
+ DeauthenticationReasonCode.REASON_MESH_CHANNEL_SWITCH_UNSPECIFIED;
+ default -> {
+ Log.e(TAG, "Invalid DeauthenticationReasonCode: "
+ + deauthenticationReasonCode);
+ yield DeauthenticationReasonCode.REASON_UNKNOWN;
+ }
+ };
+ }
+
+ @SuppressLint("NewApi")
private NetworkParams prepareNetworkParams(boolean isMetered,
SoftApConfiguration config) {
NetworkParams nwParams = new NetworkParams();
@@ -885,6 +1065,9 @@
nwParams.encryptionType = getEncryptionType(config);
nwParams.passphrase = (config.getPassphrase() != null)
? config.getPassphrase() : "";
+ if (Flags.apIsolate() && isServiceVersionAtLeast(3) && Environment.isSdkAtLeastB()) {
+ nwParams.isClientIsolationEnabled = config.isClientIsolationEnabled();
+ }
if (nwParams.ssid == null || nwParams.passphrase == null) {
return null;
@@ -892,12 +1075,18 @@
return nwParams;
}
- private IfaceParams prepareIfaceParams(String ifaceName, SoftApConfiguration config)
+ private IfaceParams prepareIfaceParams(String ifaceName, SoftApConfiguration config,
+ boolean isUsingMultiLinkOperation, List<String> instanceIdentities)
throws IllegalArgumentException {
IfaceParams ifaceParams = new IfaceParams();
ifaceParams.name = ifaceName;
ifaceParams.hwModeParams = prepareHwModeParams(config);
ifaceParams.channelParams = prepareChannelParamsList(config);
+ ifaceParams.usesMlo = isUsingMultiLinkOperation;
+ if (instanceIdentities != null) {
+ ifaceParams.instanceIdentities =
+ instanceIdentities.toArray(new String[instanceIdentities.size()]);
+ }
if (ifaceParams.name == null || ifaceParams.hwModeParams == null
|| ifaceParams.channelParams == null) {
return null;
diff --git a/service/java/com/android/server/wifi/HostapdHalHidlImp.java b/service/java/com/android/server/wifi/HostapdHalHidlImp.java
index ce74efe..389624e 100644
--- a/service/java/com/android/server/wifi/HostapdHalHidlImp.java
+++ b/service/java/com/android/server/wifi/HostapdHalHidlImp.java
@@ -26,6 +26,7 @@
import android.hidl.manager.V1_0.IServiceManager;
import android.hidl.manager.V1_0.IServiceNotification;
import android.net.MacAddress;
+import android.net.wifi.DeauthenticationReasonCode;
import android.net.wifi.ScanResult;
import android.net.wifi.SoftApConfiguration;
import android.net.wifi.SoftApConfiguration.BandType;
@@ -437,7 +438,9 @@
*/
@Override
public boolean addAccessPoint(@NonNull String ifaceName, @NonNull SoftApConfiguration config,
- boolean isMetered, @NonNull Runnable onFailureListener) {
+ boolean isMetered, boolean isUsingMultiLinkOperation,
+ @NonNull List<String> instanceIdentities,
+ @NonNull Runnable onFailureListener) {
synchronized (mLock) {
final String methodStr = "addAccessPoint";
IHostapd.IfaceParams ifaceParamsV1_0 = prepareIfaceParamsV1_0(ifaceName, config);
@@ -1299,7 +1302,8 @@
SoftApHalCallback callback = mSoftApHalCallbacks.get(ifaceName);
if (callback != null) {
callback.onConnectedClientsChanged(apIfaceInstance,
- MacAddress.fromBytes(clientAddress), isConnected);
+ MacAddress.fromBytes(clientAddress), isConnected,
+ DeauthenticationReasonCode.REASON_UNKNOWN);
}
} catch (IllegalArgumentException iae) {
Log.e(TAG, " Invalid clientAddress, " + iae);
diff --git a/service/java/com/android/server/wifi/IHostapdHal.java b/service/java/com/android/server/wifi/IHostapdHal.java
index a93cff2..eafb495 100644
--- a/service/java/com/android/server/wifi/IHostapdHal.java
+++ b/service/java/com/android/server/wifi/IHostapdHal.java
@@ -23,6 +23,7 @@
import com.android.server.wifi.WifiNative.SoftApHalCallback;
import java.io.PrintWriter;
+import java.util.List;
/** Abstraction of HAL interface */
interface IHostapdHal {
@@ -53,11 +54,13 @@
* @param ifaceName Name of the interface.
* @param config Configuration to use for the AP.
* @param isMetered Indicates the network is metered or not. Ignored in AIDL imp.
+ * @param isUsingMultiLinkOperation Indicate the AP is using MLO or not.
* @param onFailureListener A runnable to be triggered on failure.
* @return true on success, false otherwise.
*/
boolean addAccessPoint(@NonNull String ifaceName,
@NonNull SoftApConfiguration config, boolean isMetered,
+ boolean isUsingMultiLinkOperation, @NonNull List<String> instanceIdentities,
Runnable onFailureListener);
/**
diff --git a/service/java/com/android/server/wifi/ISupplicantStaIfaceHal.java b/service/java/com/android/server/wifi/ISupplicantStaIfaceHal.java
index 96e703d..c860322 100644
--- a/service/java/com/android/server/wifi/ISupplicantStaIfaceHal.java
+++ b/service/java/com/android/server/wifi/ISupplicantStaIfaceHal.java
@@ -853,4 +853,11 @@
* @param ifaceName Name of the interface.
*/
default void disableMscs(String ifaceName) {}
+
+ /**
+ * Returns true if this device supports RSN Overriding, false otherwise.
+ */
+ default boolean isRsnOverridingSupported(@NonNull String ifaceName) {
+ return false;
+ }
}
diff --git a/service/java/com/android/server/wifi/MboOceController.java b/service/java/com/android/server/wifi/MboOceController.java
index 2b5e910..35b1965 100644
--- a/service/java/com/android/server/wifi/MboOceController.java
+++ b/service/java/com/android/server/wifi/MboOceController.java
@@ -25,6 +25,8 @@
import com.android.server.wifi.SupplicantStaIfaceHal.MboAssocDisallowedReasonCode;
+import java.util.BitSet;
+
/**
* MboOceController is responsible for controlling MBO and OCE operations.
*/
@@ -60,9 +62,9 @@
if (clientModeManager == null) {
return;
}
- long supportedFeatures = clientModeManager.getSupportedFeatures();
- mIsMboSupported = (supportedFeatures & WIFI_FEATURE_MBO) != 0;
- mIsOceSupported = (supportedFeatures & WIFI_FEATURE_OCE) != 0;
+ BitSet supportedFeatures = clientModeManager.getSupportedFeatures();
+ mIsMboSupported = supportedFeatures.get(WIFI_FEATURE_MBO);
+ mIsOceSupported = supportedFeatures.get(WIFI_FEATURE_OCE);
mEnabled = true;
if (mVerboseLoggingEnabled) {
Log.d(TAG, "Enable MBO-OCE MBO support: " + mIsMboSupported
diff --git a/service/java/com/android/server/wifi/RunnerHandler.java b/service/java/com/android/server/wifi/RunnerHandler.java
index 78b7b12..0329031 100644
--- a/service/java/com/android/server/wifi/RunnerHandler.java
+++ b/service/java/com/android/server/wifi/RunnerHandler.java
@@ -52,6 +52,7 @@
// TODO: b/246623192 Add Wifi metric for Runner state overruns.
private final LocalLog mLocalLog;
+ private boolean mVerboseLoggingEnabled = false;
/**
* The Runner handler Constructor
@@ -73,6 +74,11 @@
mIgnoredMethods.add("handleMessage");
}
+ /** Enable/disable verbose logging. */
+ public void enableVerboseLogging(boolean verboseEnabled) {
+ mVerboseLoggingEnabled = verboseEnabled;
+ }
+
private String getSignature(StackTraceElement[] elements, Runnable callback) {
StringBuilder sb = new StringBuilder();
for (StackTraceElement e : elements) {
@@ -114,7 +120,8 @@
public void dispatchMessage(@NonNull Message msg) {
final Bundle bundle = msg.getData();
final String signature = bundle.getString(KEY_SIGNATURE);
- if (signature != null) {
+ boolean traceEvent = mVerboseLoggingEnabled;
+ if (signature != null && traceEvent) {
Trace.traceBegin(Trace.TRACE_TAG_NETWORK, signature);
}
// The message sent to front of the queue has when=0, get from the bundle in that case.
@@ -122,10 +129,10 @@
final long start = SystemClock.uptimeMillis();
final long scheduleLatency = start - when;
super.dispatchMessage(msg);
- if (signature != null) {
+ final long runTime = SystemClock.uptimeMillis() - start;
+ if (signature != null && traceEvent) {
Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
}
- final long runTime = SystemClock.uptimeMillis() - start;
final String signatureToLog = signature != null ? signature : "unknown";
if (runTime > mRunningTimeThresholdInMilliseconds) {
mLocalLog.log(signatureToLog + " was running for " + runTime);
diff --git a/service/java/com/android/server/wifi/RunnerState.java b/service/java/com/android/server/wifi/RunnerState.java
index e6a8573..4ec5b62 100644
--- a/service/java/com/android/server/wifi/RunnerState.java
+++ b/service/java/com/android/server/wifi/RunnerState.java
@@ -20,6 +20,7 @@
import android.annotation.NonNull;
import android.os.Message;
+import android.os.SystemClock;
import android.os.Trace;
import android.util.LocalLog;
@@ -48,6 +49,7 @@
private final int mRunningTimeThresholdInMilliseconds;
// TODO: b/246623192 Add Wifi metric for Runner state overruns.
private final LocalLog mLocalLog;
+ private final WifiInjector mWifiInjector;
/**
* The Runner state Constructor
@@ -56,37 +58,55 @@
public RunnerState(int threshold, @NonNull LocalLog localLog) {
mRunningTimeThresholdInMilliseconds = threshold;
mLocalLog = localLog;
+ mWifiInjector = WifiInjector.getInstance();
+ }
+
+ private boolean isVerboseLoggingEnabled() {
+ return mWifiInjector.isVerboseLoggingEnabled();
}
@Override
public boolean processMessage(Message message) {
- long startTime = System.currentTimeMillis();
-
String signatureToLog = getMessageLogRec(message);
if (signatureToLog == null) {
signatureToLog = getMessageLogRec(message.what);
}
- Trace.traceBegin(Trace.TRACE_TAG_NETWORK, signatureToLog);
+ boolean traceEvent = isVerboseLoggingEnabled();
+ if (traceEvent) {
+ Trace.traceBegin(Trace.TRACE_TAG_NETWORK, signatureToLog);
+ }
+
+ long startTime = SystemClock.uptimeMillis();
+ // TODO(b/295398783): Support deferMessage and sendMessageAtFrontOfQueue where when is 0;
+ long scheduleLatency = message.getWhen() != 0 ? startTime - message.getWhen() : 0;
boolean ret = processMessageImpl(message);
- Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
- long runTime = System.currentTimeMillis() - startTime;
+ long runTime = SystemClock.uptimeMillis() - startTime;
+ if (traceEvent) {
+ Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
+ }
if (runTime > mRunningTimeThresholdInMilliseconds) {
mLocalLog.log(signatureToLog + " was running for " + runTime + " ms");
}
- if (runTime > METRICS_THRESHOLD_MILLIS) {
- WifiStatsLog.write(WIFI_THREAD_TASK_EXECUTED, (int) runTime, 0, signatureToLog);
+ if (runTime > METRICS_THRESHOLD_MILLIS || scheduleLatency > METRICS_THRESHOLD_MILLIS) {
+ WifiStatsLog.write(WIFI_THREAD_TASK_EXECUTED, (int) runTime, (int) scheduleLatency,
+ signatureToLog);
}
return ret;
}
@Override
public void enter() {
- long startTime = System.currentTimeMillis();
String signatureToLog = getMessageLogRec(STATE_ENTER_CMD);
- Trace.traceBegin(Trace.TRACE_TAG_NETWORK, signatureToLog);
+ boolean traceEvent = isVerboseLoggingEnabled();
+ if (traceEvent) {
+ Trace.traceBegin(Trace.TRACE_TAG_NETWORK, signatureToLog);
+ }
+ long startTime = SystemClock.uptimeMillis();
enterImpl();
- Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
- long runTime = System.currentTimeMillis() - startTime;
+ long runTime = SystemClock.uptimeMillis() - startTime;
+ if (traceEvent) {
+ Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
+ }
if (runTime > mRunningTimeThresholdInMilliseconds) {
mLocalLog.log(signatureToLog + " was running for " + runTime + " ms");
}
@@ -97,12 +117,18 @@
@Override
public void exit() {
- long startTime = System.currentTimeMillis();
String signatureToLog = getMessageLogRec(STATE_EXIT_CMD);
- Trace.traceBegin(Trace.TRACE_TAG_NETWORK, signatureToLog);
+ boolean traceEvent = isVerboseLoggingEnabled();
+ if (traceEvent) {
+ Trace.traceBegin(Trace.TRACE_TAG_NETWORK, signatureToLog);
+ }
+ long startTime = SystemClock.uptimeMillis();
exitImpl();
- Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
- long runTime = System.currentTimeMillis() - startTime;
+ long runTime = SystemClock.uptimeMillis() - startTime;
+ if (traceEvent) {
+ Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
+ }
+
if (runTime > mRunningTimeThresholdInMilliseconds) {
mLocalLog.log(signatureToLog + " was running for " + runTime + " ms");
}
diff --git a/service/java/com/android/server/wifi/ScanDetail.java b/service/java/com/android/server/wifi/ScanDetail.java
index 59eb16a..fa51486 100644
--- a/service/java/com/android/server/wifi/ScanDetail.java
+++ b/service/java/com/android/server/wifi/ScanDetail.java
@@ -62,6 +62,8 @@
boolean is80211McResponder = false;
boolean isTwtResponder = false;
boolean is11azNtbResponder = false;
+ boolean isSecureHeLtfSupported = false;
+ boolean isRangingFrameProtectionRequired = false;
if (networkDetail != null) {
hessid = networkDetail.getHESSID();
anqpDomainId = networkDetail.getAnqpDomainID();
@@ -77,6 +79,8 @@
is80211McResponder = networkDetail.is80211McResponderSupport();
isTwtResponder = networkDetail.isIndividualTwtSupported();
is11azNtbResponder = networkDetail.is80211azNtbResponder();
+ isSecureHeLtfSupported = networkDetail.isSecureHeLtfSupported();
+ isRangingFrameProtectionRequired = networkDetail.isRangingFrameProtectionRequired();
}
sBuilder.clear();
mScanResult = sBuilder
@@ -91,6 +95,8 @@
.setTsf(tsf)
.setIsTwtResponder(isTwtResponder)
.setIs80211azNtbRTTResponder(is11azNtbResponder)
+ .setSecureHeLtfSupported(isSecureHeLtfSupported)
+ .setRangingFrameProtectionRequired(isRangingFrameProtectionRequired)
.build();
mSeen = System.currentTimeMillis();
mScanResult.seen = mSeen;
diff --git a/service/java/com/android/server/wifi/ScanOnlyModeImpl.java b/service/java/com/android/server/wifi/ScanOnlyModeImpl.java
index 6449b6a..1946652 100644
--- a/service/java/com/android/server/wifi/ScanOnlyModeImpl.java
+++ b/service/java/com/android/server/wifi/ScanOnlyModeImpl.java
@@ -18,6 +18,8 @@
import android.annotation.NonNull;
+import java.util.BitSet;
+
/**
* Used to respond to calls to ClientMode interface when ClientModeImpl is not up
* i.e. in scan only mode.
@@ -40,7 +42,7 @@
}
@Override
- public long getSupportedFeatures() {
+ public @NonNull BitSet getSupportedFeatures() {
return mWifiNative.getSupportedFeatureSet(mIfaceName);
}
diff --git a/service/java/com/android/server/wifi/SoftApManager.java b/service/java/com/android/server/wifi/SoftApManager.java
index 5afaf78..1f8c280 100644
--- a/service/java/com/android/server/wifi/SoftApManager.java
+++ b/service/java/com/android/server/wifi/SoftApManager.java
@@ -66,8 +66,11 @@
import com.android.server.wifi.coex.CoexManager.CoexListener;
import com.android.server.wifi.util.ApConfigUtil;
import com.android.server.wifi.util.WaitingState;
+import com.android.wifi.flags.Flags;
import com.android.wifi.resources.R;
+import com.google.common.collect.ImmutableList;
+
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
@@ -217,6 +220,12 @@
private boolean mVerboseLoggingEnabled = false;
+ // Whether this device supports multiple link operation in a single MLD.
+ private boolean mIsMLDApSupportMLO = false;
+
+ // Whether this SoftApManager (i.e. this AP interface) is using multiple link operation.
+ private boolean mIsUsingMlo = false;
+
/**
* The specified configuration passed in during initialization or during a configuration update
* that doesn't require a restart.
@@ -250,7 +259,7 @@
private final SarManager mSarManager;
- private String mStartTimestamp;
+ private long mStartTimestampMs;
private long mDefaultShutdownTimeoutMillis;
@@ -339,10 +348,10 @@
@Override
public void onConnectedClientsChanged(String apIfaceInstance, MacAddress clientAddress,
- boolean isConnected) {
+ boolean isConnected, @WifiAnnotations.SoftApDisconnectReason int disconnectReason) {
if (clientAddress != null) {
WifiClient client = new WifiClient(clientAddress, apIfaceInstance != null
- ? apIfaceInstance : mApInterfaceName);
+ ? apIfaceInstance : mApInterfaceName, disconnectReason);
mStateMachine.sendMessage(SoftApStateMachine.CMD_ASSOCIATED_STATIONS_CHANGED,
isConnected ? 1 : 0, 0, client);
} else {
@@ -512,6 +521,9 @@
updateSafeChannelFrequencyList();
mId = id;
mRole = role;
+ // chip support it && overlay configuration is set.
+ mIsMLDApSupportMLO = mWifiNative.isMLDApSupportMLO();
+ mIsUsingMlo = useMultilinkMloSoftAp();
enableVerboseLogging(verboseLoggingEnabled);
mStateMachine.sendMessage(SoftApStateMachine.CMD_START, requestorWs);
}
@@ -534,13 +546,38 @@
mStateMachine.sendMessage(SoftApStateMachine.CMD_STOP);
}
+ public boolean isUsingMlo() {
+ return mIsUsingMlo;
+ }
+
+ private boolean useMultilinkMloSoftAp() {
+ if (!Flags.mloSap()) {
+ return false;
+ }
+ if (SdkLevel.isAtLeastT() && mCurrentSoftApConfiguration != null
+ && mCurrentSoftApConfiguration.isIeee80211beEnabled()
+ && isBridgedMode() && mIsMLDApSupportMLO) {
+
+ int currentExistingMLD =
+ mActiveModeWarden.getCurrentMLDAp();
+ if (ApConfigUtil.is11beAllowedForThisConfiguration(
+ null /* Wiphy capability can be ignored for MLO case*/,
+ mContext, mCurrentSoftApConfiguration, true /* isBridgedMode */,
+ currentExistingMLD,
+ true /* isMLDApSupportMLO */)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
private boolean isOweTransition() {
return (SdkLevel.isAtLeastT() && mCurrentSoftApConfiguration != null
&& mCurrentSoftApConfiguration.getSecurityType()
== SoftApConfiguration.SECURITY_TYPE_WPA3_OWE_TRANSITION);
}
- private boolean isBridgedMode() {
+ public boolean isBridgedMode() {
return (SdkLevel.isAtLeastS() && mCurrentSoftApConfiguration != null
&& (mCurrentSoftApConfiguration.getBands().length > 1));
}
@@ -663,6 +700,13 @@
}
/**
+ * Return true when current softap state is enabled.
+ */
+ public boolean isStarted() {
+ return mCurrentApState == WifiManager.WIFI_AP_STATE_ENABLED;
+ }
+
+ /**
* Dump info about this softap manager.
*/
@Override
@@ -684,7 +728,7 @@
pw.println("mBridgedModeOpportunisticsShutdownTimeoutEnabled: "
+ mBridgedModeOpportunisticsShutdownTimeoutEnabled);
pw.println("mCurrentSoftApInfoMap " + mCurrentSoftApInfoMap);
- pw.println("mStartTimestamp: " + mStartTimestamp);
+ pw.println("mStartTimestamp: " + FORMATTER.format(new Date(mStartTimestampMs)));
pw.println("mSafeChannelFrequencyList: " + mSafeChannelFrequencyList.stream()
.map(Object::toString)
.collect(Collectors.joining(",")));
@@ -844,7 +888,6 @@
} else {
Log.d(getTag(), "startSoftAp: band " + mCurrentSoftApConfiguration.getBand());
}
-
updateApState(WifiManager.WIFI_AP_STATE_ENABLING,
WifiManager.WIFI_AP_STATE_DISABLED, 0);
@@ -882,14 +925,14 @@
localConfigBuilder.build(),
mSpecifiedModeConfiguration.getTargetMode()
== WifiManager.IFACE_IP_MODE_TETHERED,
- mSoftApHalCallback);
+ mSoftApHalCallback, mIsUsingMlo);
if (startResult != START_RESULT_SUCCESS) {
Log.e(getTag(), "Soft AP start failed");
return startResult;
}
mWifiDiagnostics.startLogging(mApInterfaceName);
- mStartTimestamp = FORMATTER.format(new Date(System.currentTimeMillis()));
+ mStartTimestampMs = mWifiInjector.getClock().getWallClockMillis();
Log.d(getTag(), "Soft AP is started ");
return START_RESULT_SUCCESS;
@@ -1276,11 +1319,10 @@
== InterfaceConflictManager.ICM_SKIP_COMMAND_WAIT_FOR_USER) {
break;
}
-
mApInterfaceName = mWifiNative.setupInterfaceForSoftApMode(
mWifiNativeInterfaceCallback, mRequestorWs,
mCurrentSoftApConfiguration.getBand(), isBridgeRequired(),
- SoftApManager.this, getVendorData());
+ SoftApManager.this, getVendorData(), mIsUsingMlo);
if (TextUtils.isEmpty(mApInterfaceName)) {
Log.e(getTag(), "setup failure when creating ap interface.");
// Only check if it's possible to create single AP, since a DBS request
@@ -1293,13 +1335,17 @@
break;
}
- if (SdkLevel.isAtLeastT()
+ if (!mIsUsingMlo && SdkLevel.isAtLeastT()
&& mCurrentSoftApConfiguration.isIeee80211beEnabled()) {
DeviceWiphyCapabilities capabilities =
mWifiNative.getDeviceWiphyCapabilities(
mApInterfaceName, isBridgeRequired());
+ int currentExistingMLD =
+ mActiveModeWarden.getCurrentMLDAp();
if (!ApConfigUtil.is11beAllowedForThisConfiguration(capabilities,
- mContext, mCurrentSoftApConfiguration, isBridgedMode())) {
+ mContext, mCurrentSoftApConfiguration, isBridgedMode(),
+ currentExistingMLD,
+ mIsMLDApSupportMLO)) {
Log.d(getTag(), "11BE is not allowed,"
+ " removing from configuration");
mCurrentSoftApConfiguration = new SoftApConfiguration.Builder(
@@ -1488,7 +1534,7 @@
mApInterfaceName = mWifiNative.setupInterfaceForSoftApMode(
mWifiNativeInterfaceCallback, mRequestorWs,
mCurrentSoftApConfiguration.getBand(), isBridgeRequired(),
- SoftApManager.this, getVendorData());
+ SoftApManager.this, getVendorData(), mIsUsingMlo);
if (TextUtils.isEmpty(mApInterfaceName)) {
Log.e(getTag(), "setup failure when creating single AP iface");
handleStartSoftApFailure(START_RESULT_FAILURE_GENERAL);
@@ -1737,6 +1783,13 @@
+ currentInfoWithClientsChanged);
if (mSoftApCallback != null) {
+ if (Flags.softapDisconnectReason() && !isConnected) {
+ // Client successfully disconnected, should also notify callback
+ mSoftApCallback.onClientsDisconnected(
+ currentInfoWithClientsChanged,
+ ImmutableList.of(client));
+ }
+
mSoftApCallback.onConnectedClientsOrInfoChanged(mCurrentSoftApInfoMap,
mConnectedClientWithApInfoMap, isBridgeRequired());
} else {
@@ -1995,7 +2048,8 @@
WifiClient client = (WifiClient) message.obj;
Log.d(getTag(), "CMD_ASSOCIATED_STATIONS_CHANGED, Client: "
+ client.getMacAddress().toString() + " isConnected: "
- + isConnected);
+ + isConnected + " disconnectReason: "
+ + client.getDisconnectReason());
updateConnectedClients(client, isConnected);
break;
case CMD_AP_INFO_CHANGED:
@@ -2027,6 +2081,7 @@
updateApState(WifiManager.WIFI_AP_STATE_DISABLING,
WifiManager.WIFI_AP_STATE_ENABLING, 0);
}
+ writeSoftApStoppedEvent(STOP_EVENT_STOPPED);
quitNow();
break;
case CMD_START:
@@ -2350,6 +2405,8 @@
if (mCurrentSoftApConfiguration != null) {
securityType = mCurrentSoftApConfiguration.getSecurityType();
}
+ int durationSeconds =
+ (int) ((mWifiInjector.getClock().getWallClockMillis() - mStartTimestampMs) / 1000);
// TODO(b/245824786): Fill out the rest of the fields
mWifiMetrics.writeSoftApStoppedEvent(
stopEvent,
@@ -2360,7 +2417,7 @@
ApConfigUtil.isStaWithBridgedModeSupported(mContext, mWifiNative),
getCurrentStaFreqMhz(),
mDefaultShutdownTimeoutMillis > 0,
- -1,
+ durationSeconds,
securityType,
standard,
-1,
diff --git a/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackAidlImpl.java b/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackAidlImpl.java
index ae98ccb..0d2f958 100644
--- a/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackAidlImpl.java
+++ b/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackAidlImpl.java
@@ -56,6 +56,8 @@
import android.hardware.wifi.supplicant.StaIfaceReasonCode;
import android.hardware.wifi.supplicant.StaIfaceStatusCode;
import android.hardware.wifi.supplicant.SupplicantStateChangeData;
+import android.hardware.wifi.supplicant.UsdMessageInfo;
+import android.hardware.wifi.supplicant.UsdServiceDiscoveryInfo;
import android.hardware.wifi.supplicant.WpsConfigError;
import android.hardware.wifi.supplicant.WpsErrorIndication;
import android.net.MacAddress;
@@ -374,15 +376,13 @@
// was not successfully verified is indicated with a status code of 15. This
// typically happens when the entered password is wrong. So treat status code
// of 15 as incorrect password.
- // Some implementations also send status code of 1 for incorrect password. But
- // this is a generic status code and can't be treated as incorrect password all
- // the time. So treat status code of 1 as incorrect password only if the STA
- // was not connected to this network before. In this case, we will
- // send an authentication failure event up.
+ // Some implementations also send status code of 1 for incorrect password. For
+ // both status codes, broadcast authentication failure message with reason code
+ // set to wrong password. ClientModeImpl will notify user for wrong password
+ // error if the network had never been connected before.
if (statusCode == SupplicantStaIfaceHal.StaIfaceStatusCode.CHALLENGE_FAIL
- || (statusCode
- == SupplicantStaIfaceHal.StaIfaceStatusCode.UNSPECIFIED_FAILURE
- && !curConfiguration.getNetworkSelectionStatus().hasEverConnected())) {
+ || statusCode
+ == SupplicantStaIfaceHal.StaIfaceStatusCode.UNSPECIFIED_FAILURE) {
mStaIfaceHal.logCallback("SAE incorrect password");
isWrongPwd = true;
} else {
@@ -671,6 +671,33 @@
}
}
+ @Override
+ public void onUsdPublishStarted(int cmdId, int publishId) { }
+
+ @Override
+ public void onUsdSubscribeStarted(int cmdId, int subscribeId) { }
+
+ @Override
+ public void onUsdPublishConfigFailed(int cmdId) { }
+
+ @Override
+ public void onUsdSubscribeConfigFailed(int cmdId) { }
+
+ @Override
+ public void onUsdPublishTerminated(int publishId, int reasonCode) { }
+
+ @Override
+ public void onUsdSubscribeTerminated(int subscribeId, int reasonCode) { }
+
+ @Override
+ public void onUsdPublishReplied(UsdServiceDiscoveryInfo info) { }
+
+ @Override
+ public void onUsdServiceDiscovered(UsdServiceDiscoveryInfo info) { }
+
+ @Override
+ public void onUsdMessageReceived(UsdMessageInfo messageInfo) { }
+
private @MboOceConstants.BtmResponseStatus int halToFrameworkBtmResponseStatus(int status) {
switch (status) {
case BssTmStatusCode.ACCEPT:
diff --git a/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackHidlImpl.java b/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackHidlImpl.java
index facbb7b..7727a96 100644
--- a/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackHidlImpl.java
+++ b/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackHidlImpl.java
@@ -333,15 +333,13 @@
// was not successfully verified is indicated with a status code of 15. This
// typically happens when the entered password is wrong. So treat status code
// of 15 as incorrect password.
- // Some implementations also send status code of 1 for incorrect password. But
- // this is a generic status code and can't be treated as incorrect password all
- // the time. So treat status code of 1 as incorrect password only if the STA
- // was not connected to this network before. In this case, we will
- // send an authentication failure event up.
+ // Some implementations also send status code of 1 for incorrect password. For
+ // both status codes, broadcast authentication failure message with reason code
+ // set to wrong password. ClientModeImpl will notify user for wrong password
+ // error if the network had never been connected before.
if (statusCode == SupplicantStaIfaceHal.StaIfaceStatusCode.CHALLENGE_FAIL
- || (statusCode
- == SupplicantStaIfaceHal.StaIfaceStatusCode.UNSPECIFIED_FAILURE
- && !curConfiguration.getNetworkSelectionStatus().hasEverConnected())) {
+ || statusCode
+ == SupplicantStaIfaceHal.StaIfaceStatusCode.UNSPECIFIED_FAILURE) {
mStaIfaceHal.logCallback("SAE incorrect password");
isWrongPwd = true;
} else {
diff --git a/service/java/com/android/server/wifi/SupplicantStaIfaceHal.java b/service/java/com/android/server/wifi/SupplicantStaIfaceHal.java
index 7129609..72b47f1 100644
--- a/service/java/com/android/server/wifi/SupplicantStaIfaceHal.java
+++ b/service/java/com/android/server/wifi/SupplicantStaIfaceHal.java
@@ -1955,6 +1955,20 @@
}
/**
+ * Returns true if this device supports RSN Overriding, false otherwise.
+ */
+ public boolean isRsnOverridingSupported(@NonNull String ifaceName) {
+ synchronized (mLock) {
+ String methodStr = "isRsnOverridingSupported";
+ if (mStaIfaceHal == null) {
+ handleNullHal(methodStr);
+ return false;
+ }
+ return mStaIfaceHal.isRsnOverridingSupported(ifaceName);
+ }
+ }
+
+ /**
* Returns connection capabilities of the current network
*
* @param ifaceName Name of the interface.
diff --git a/service/java/com/android/server/wifi/SupplicantStaIfaceHalAidlImpl.java b/service/java/com/android/server/wifi/SupplicantStaIfaceHalAidlImpl.java
index b378188..e11368e 100644
--- a/service/java/com/android/server/wifi/SupplicantStaIfaceHalAidlImpl.java
+++ b/service/java/com/android/server/wifi/SupplicantStaIfaceHalAidlImpl.java
@@ -33,13 +33,10 @@
import static android.net.wifi.WifiManager.WIFI_FEATURE_WFD_R2;
import static android.net.wifi.WifiManager.WIFI_FEATURE_WPA3_SAE;
import static android.net.wifi.WifiManager.WIFI_FEATURE_WPA3_SUITE_B;
-import static android.os.Build.VERSION.SDK_INT;
-
-import static com.android.server.wifi.util.GeneralUtil.getCapabilityIndex;
import android.annotation.NonNull;
+import android.annotation.SuppressLint;
import android.content.Context;
-import android.hardware.wifi.WifiChannelWidthInMhz;
import android.hardware.wifi.supplicant.BtCoexistenceMode;
import android.hardware.wifi.supplicant.ConnectionCapabilities;
import android.hardware.wifi.supplicant.DebugLevel;
@@ -77,6 +74,7 @@
import android.hardware.wifi.supplicant.RxFilterType;
import android.hardware.wifi.supplicant.SignalPollResult;
import android.hardware.wifi.supplicant.SupplicantStatusCode;
+import android.hardware.wifi.supplicant.WifiChannelWidthInMhz;
import android.hardware.wifi.supplicant.WifiTechnology;
import android.hardware.wifi.supplicant.WpaDriverCapabilitiesMask;
import android.hardware.wifi.supplicant.WpsConfigMethods;
@@ -93,6 +91,7 @@
import android.net.wifi.WifiMigration;
import android.net.wifi.WifiSsid;
import android.net.wifi.flags.Flags;
+import android.net.wifi.util.Environment;
import android.os.Handler;
import android.os.IBinder;
import android.os.IBinder.DeathRecipient;
@@ -104,6 +103,7 @@
import android.util.Pair;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.modules.utils.HandlerExecutor;
import com.android.modules.utils.build.SdkLevel;
import com.android.server.wifi.mockwifi.MockWifiServiceUtil;
import com.android.server.wifi.util.HalAidlUtil;
@@ -120,6 +120,7 @@
import java.util.Objects;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
+import java.util.function.IntConsumer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -186,6 +187,8 @@
@VisibleForTesting
protected boolean mHasMigratedLegacyKeystoreAliases = false;
+ @VisibleForTesting
+ protected KeystoreMigrationStatusConsumer mKeystoreMigrationStatusConsumer;
private class SupplicantDeathRecipient implements DeathRecipient {
@Override
@@ -214,6 +217,26 @@
}
}
+ @VisibleForTesting
+ protected class KeystoreMigrationStatusConsumer implements IntConsumer {
+ @Override
+ public void accept(int statusCode) {
+ synchronized (mLock) {
+ if (statusCode == WifiMigration.KEYSTORE_MIGRATION_SUCCESS_MIGRATION_NOT_NEEDED
+ || statusCode
+ == WifiMigration.KEYSTORE_MIGRATION_SUCCESS_MIGRATION_COMPLETE) {
+ mHasMigratedLegacyKeystoreAliases = true;
+ } else {
+ mHasMigratedLegacyKeystoreAliases = false;
+ }
+ Log.i(TAG, "Keystore migration returned with success="
+ + mHasMigratedLegacyKeystoreAliases + ", statusCode=" + statusCode);
+ // Consumer is no longer needed, since the callback has been received
+ mKeystoreMigrationStatusConsumer = null;
+ }
+ }
+ }
+
public SupplicantStaIfaceHalAidlImpl(Context context, WifiMonitor monitor, Handler handler,
Clock clock, WifiMetrics wifiMetrics, WifiGlobals wifiGlobals,
@NonNull SsidTranslator ssidTranslator, WifiInjector wifiInjector) {
@@ -2593,16 +2616,15 @@
BitSet advancedCapabilities = new BitSet();
int keyMgmtCapabilities = getKeyMgmtCapabilities(ifaceName);
- advancedCapabilities.set(
- getCapabilityIndex(WIFI_FEATURE_PASSPOINT_TERMS_AND_CONDITIONS));
- advancedCapabilities.set(getCapabilityIndex(WIFI_FEATURE_DECORATED_IDENTITY));
+ advancedCapabilities.set(WIFI_FEATURE_PASSPOINT_TERMS_AND_CONDITIONS);
+ advancedCapabilities.set(WIFI_FEATURE_DECORATED_IDENTITY);
if (mVerboseLoggingEnabled) {
Log.v(TAG, methodStr + ": Passpoint T&C supported");
Log.v(TAG, methodStr + ": RFC 7542 decorated identity supported");
}
if ((keyMgmtCapabilities & KeyMgmtMask.SAE) != 0) {
- advancedCapabilities.set(getCapabilityIndex(WIFI_FEATURE_WPA3_SAE));
+ advancedCapabilities.set(WIFI_FEATURE_WPA3_SAE);
if (mVerboseLoggingEnabled) {
Log.v(TAG, methodStr + ": SAE supported");
@@ -2610,7 +2632,7 @@
}
if ((keyMgmtCapabilities & KeyMgmtMask.SUITE_B_192) != 0) {
- advancedCapabilities.set(getCapabilityIndex(WIFI_FEATURE_WPA3_SUITE_B));
+ advancedCapabilities.set(WIFI_FEATURE_WPA3_SUITE_B);
if (mVerboseLoggingEnabled) {
Log.v(TAG, methodStr + ": SUITE_B supported");
@@ -2618,7 +2640,7 @@
}
if ((keyMgmtCapabilities & KeyMgmtMask.OWE) != 0) {
- advancedCapabilities.set(getCapabilityIndex(WIFI_FEATURE_OWE));
+ advancedCapabilities.set(WIFI_FEATURE_OWE);
if (mVerboseLoggingEnabled) {
Log.v(TAG, methodStr + ": OWE supported");
@@ -2626,8 +2648,8 @@
}
if ((keyMgmtCapabilities & KeyMgmtMask.DPP) != 0) {
- advancedCapabilities.set(getCapabilityIndex(WIFI_FEATURE_DPP));
- advancedCapabilities.set(getCapabilityIndex(WIFI_FEATURE_DPP_ENROLLEE_RESPONDER));
+ advancedCapabilities.set(WIFI_FEATURE_DPP);
+ advancedCapabilities.set(WIFI_FEATURE_DPP_ENROLLEE_RESPONDER);
if (mVerboseLoggingEnabled) {
Log.v(TAG, methodStr + ": DPP supported");
@@ -2636,7 +2658,7 @@
}
if ((keyMgmtCapabilities & KeyMgmtMask.WAPI_PSK) != 0) {
- advancedCapabilities.set(getCapabilityIndex(WIFI_FEATURE_WAPI));
+ advancedCapabilities.set(WIFI_FEATURE_WAPI);
if (mVerboseLoggingEnabled) {
Log.v(TAG, methodStr + ": WAPI supported");
@@ -2644,7 +2666,7 @@
}
if ((keyMgmtCapabilities & KeyMgmtMask.FILS_SHA256) != 0) {
- advancedCapabilities.set(getCapabilityIndex(WIFI_FEATURE_FILS_SHA256));
+ advancedCapabilities.set(WIFI_FEATURE_FILS_SHA256);
if (mVerboseLoggingEnabled) {
Log.v(TAG, methodStr + ": FILS_SHA256 supported");
@@ -2652,7 +2674,7 @@
}
if ((keyMgmtCapabilities & KeyMgmtMask.FILS_SHA384) != 0) {
- advancedCapabilities.set(getCapabilityIndex(WIFI_FEATURE_FILS_SHA384));
+ advancedCapabilities.set(WIFI_FEATURE_FILS_SHA384);
if (mVerboseLoggingEnabled) {
Log.v(TAG, methodStr + ": FILS_SHA384 supported");
@@ -2696,14 +2718,14 @@
BitSet featureSet = new BitSet();
if ((drvCapabilitiesMask & WpaDriverCapabilitiesMask.SET_TLS_MINIMUM_VERSION) != 0) {
- featureSet.set(getCapabilityIndex(WIFI_FEATURE_SET_TLS_MINIMUM_VERSION));
+ featureSet.set(WIFI_FEATURE_SET_TLS_MINIMUM_VERSION);
if (mVerboseLoggingEnabled) {
Log.v(TAG, methodStr + ": EAP-TLS minimum version supported");
}
}
if ((drvCapabilitiesMask & WpaDriverCapabilitiesMask.TLS_V1_3) != 0) {
- featureSet.set(getCapabilityIndex(WIFI_FEATURE_TLS_V1_3));
+ featureSet.set(WIFI_FEATURE_TLS_V1_3);
if (mVerboseLoggingEnabled) {
Log.v(TAG, methodStr + ": EAP-TLS v1.3 supported");
}
@@ -2721,12 +2743,12 @@
BitSet featureSet = new BitSet();
if ((drvCapabilitiesMask & WpaDriverCapabilitiesMask.MBO) != 0) {
- featureSet.set(getCapabilityIndex(WIFI_FEATURE_MBO));
+ featureSet.set(WIFI_FEATURE_MBO);
if (mVerboseLoggingEnabled) {
Log.v(TAG, methodStr + ": MBO supported");
}
if ((drvCapabilitiesMask & WpaDriverCapabilitiesMask.OCE) != 0) {
- featureSet.set(getCapabilityIndex(WIFI_FEATURE_OCE));
+ featureSet.set(WIFI_FEATURE_OCE);
if (mVerboseLoggingEnabled) {
Log.v(TAG, methodStr + ": OCE supported");
}
@@ -2734,14 +2756,14 @@
}
if ((drvCapabilitiesMask & WpaDriverCapabilitiesMask.SAE_PK) != 0) {
- featureSet.set(getCapabilityIndex(WIFI_FEATURE_SAE_PK));
+ featureSet.set(WIFI_FEATURE_SAE_PK);
if (mVerboseLoggingEnabled) {
Log.v(TAG, methodStr + ": SAE-PK supported");
}
}
if ((drvCapabilitiesMask & WpaDriverCapabilitiesMask.WFD_R2) != 0) {
- featureSet.set(getCapabilityIndex(WIFI_FEATURE_WFD_R2));
+ featureSet.set(WIFI_FEATURE_WFD_R2);
if (mVerboseLoggingEnabled) {
Log.v(TAG, methodStr + ": WFD-R2 supported");
}
@@ -2749,7 +2771,7 @@
if ((drvCapabilitiesMask
& WpaDriverCapabilitiesMask.TRUST_ON_FIRST_USE) != 0) {
- featureSet.set(getCapabilityIndex(WIFI_FEATURE_TRUST_ON_FIRST_USE));
+ featureSet.set(WIFI_FEATURE_TRUST_ON_FIRST_USE);
if (mVerboseLoggingEnabled) {
Log.v(TAG, methodStr + ": Trust-On-First-Use supported");
}
@@ -2762,6 +2784,27 @@
}
/**
+ * Returns true if this device supports RSN Overriding, false otherwise. Need service version
+ * at least 4 or higher.
+ */
+ public boolean isRsnOverridingSupported(@NonNull String ifaceName) {
+ synchronized (mLock) {
+ final String methodStr = "isRsnOverridingSupported";
+ if (!isServiceVersionAtLeast(4)) {
+ return false;
+ }
+ int drvCapabilitiesMask = getWpaDriverCapabilities(ifaceName);
+ boolean rsnOverridingSupported =
+ (drvCapabilitiesMask & WpaDriverCapabilitiesMask.RSN_OVERRIDING) != 0;
+ if (mVerboseLoggingEnabled) {
+ Log.v(TAG, methodStr + ": RSN Overriding supported: "
+ + rsnOverridingSupported);
+ }
+ return rsnOverridingSupported;
+ }
+ }
+
+ /**
* Get the bitmask of supplicant/driver supported features in
* AIDL WpaDriverCapabilitiesMask format.
*/
@@ -4062,6 +4105,7 @@
}
}
+ @SuppressLint("NewApi") // Keystore migration API is guarded by an SDK check
private void registerNonStandardCertCallback() {
synchronized (mLock) {
final String methodStr = "registerNonStandardCertCallback";
@@ -4072,11 +4116,14 @@
return;
}
- // TODO: Use SdkLevel API when it exists, rather than the SDK_INT
- if (!mHasMigratedLegacyKeystoreAliases && SDK_INT >= 36
+ if (!mHasMigratedLegacyKeystoreAliases && Environment.isSdkAtLeastB()
&& Flags.legacyKeystoreToWifiBlobstoreMigrationReadOnly()) {
- WifiMigration.migrateLegacyKeystoreToWifiBlobstore();
- mHasMigratedLegacyKeystoreAliases = true;
+ if (mKeystoreMigrationStatusConsumer == null) {
+ // Create global callback temporarily for access in the unit tests
+ mKeystoreMigrationStatusConsumer = new KeystoreMigrationStatusConsumer();
+ }
+ WifiMigration.migrateLegacyKeystoreToWifiBlobstore(
+ new HandlerExecutor(mEventHandler), mKeystoreMigrationStatusConsumer);
}
try {
diff --git a/service/java/com/android/server/wifi/SupplicantStaIfaceHalHidlImpl.java b/service/java/com/android/server/wifi/SupplicantStaIfaceHalHidlImpl.java
index c98e23a..6b9838d 100644
--- a/service/java/com/android/server/wifi/SupplicantStaIfaceHalHidlImpl.java
+++ b/service/java/com/android/server/wifi/SupplicantStaIfaceHalHidlImpl.java
@@ -30,8 +30,6 @@
import static android.net.wifi.WifiManager.WIFI_FEATURE_WPA3_SAE;
import static android.net.wifi.WifiManager.WIFI_FEATURE_WPA3_SUITE_B;
-import static com.android.server.wifi.util.GeneralUtil.getCapabilityIndex;
-
import android.annotation.NonNull;
import android.content.Context;
import android.hardware.wifi.V1_0.WifiChannelWidthInMhz;
@@ -2974,7 +2972,7 @@
if ((keyMgmtCapabilities & android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork
.KeyMgmtMask.SAE) != 0) {
- advancedCapabilities.set(getCapabilityIndex(WIFI_FEATURE_WPA3_SAE));
+ advancedCapabilities.set(WIFI_FEATURE_WPA3_SAE);
if (mVerboseLoggingEnabled) {
Log.v(TAG, methodStr + ": SAE supported");
@@ -2983,7 +2981,7 @@
if ((keyMgmtCapabilities & android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork
.KeyMgmtMask.SUITE_B_192) != 0) {
- advancedCapabilities.set(getCapabilityIndex(WIFI_FEATURE_WPA3_SUITE_B));
+ advancedCapabilities.set(WIFI_FEATURE_WPA3_SUITE_B);
if (mVerboseLoggingEnabled) {
Log.v(TAG, methodStr + ": SUITE_B supported");
@@ -2992,7 +2990,7 @@
if ((keyMgmtCapabilities & android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork
.KeyMgmtMask.OWE) != 0) {
- advancedCapabilities.set(getCapabilityIndex(WIFI_FEATURE_OWE));
+ advancedCapabilities.set(WIFI_FEATURE_OWE);
if (mVerboseLoggingEnabled) {
Log.v(TAG, methodStr + ": OWE supported");
@@ -3001,13 +2999,13 @@
if ((keyMgmtCapabilities & android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork
.KeyMgmtMask.DPP) != 0) {
- advancedCapabilities.set(getCapabilityIndex(WIFI_FEATURE_DPP));
+ advancedCapabilities.set(WIFI_FEATURE_DPP);
if (mVerboseLoggingEnabled) {
Log.v(TAG, methodStr + ": DPP supported");
}
if (isV1_4()) {
- advancedCapabilities.set(getCapabilityIndex(WIFI_FEATURE_DPP_ENROLLEE_RESPONDER));
+ advancedCapabilities.set(WIFI_FEATURE_DPP_ENROLLEE_RESPONDER);
if (mVerboseLoggingEnabled) {
Log.v(TAG, methodStr + ": DPP ENROLLEE RESPONDER supported");
}
@@ -3015,9 +3013,8 @@
}
if (isV1_4()) {
- advancedCapabilities.set(
- getCapabilityIndex(WIFI_FEATURE_PASSPOINT_TERMS_AND_CONDITIONS));
- advancedCapabilities.set(getCapabilityIndex(WIFI_FEATURE_DECORATED_IDENTITY));
+ advancedCapabilities.set(WIFI_FEATURE_PASSPOINT_TERMS_AND_CONDITIONS);
+ advancedCapabilities.set(WIFI_FEATURE_DECORATED_IDENTITY);
if (mVerboseLoggingEnabled) {
Log.v(TAG, methodStr + ": Passpoint T&C supported");
Log.v(TAG, methodStr + ": RFC 7542 decorated identity supported");
@@ -3026,7 +3023,7 @@
if ((keyMgmtCapabilities & android.hardware.wifi.supplicant.V1_3.ISupplicantStaNetwork
.KeyMgmtMask.WAPI_PSK) != 0) {
- advancedCapabilities.set(getCapabilityIndex(WIFI_FEATURE_WAPI));
+ advancedCapabilities.set(WIFI_FEATURE_WAPI);
if (mVerboseLoggingEnabled) {
Log.v(TAG, methodStr + ": WAPI supported");
@@ -3035,7 +3032,7 @@
if ((keyMgmtCapabilities & android.hardware.wifi.supplicant.V1_3.ISupplicantStaNetwork
.KeyMgmtMask.FILS_SHA256) != 0) {
- advancedCapabilities.set(getCapabilityIndex(WIFI_FEATURE_FILS_SHA256));
+ advancedCapabilities.set(WIFI_FEATURE_FILS_SHA256);
if (mVerboseLoggingEnabled) {
Log.v(TAG, methodStr + ": FILS_SHA256 supported");
@@ -3043,7 +3040,7 @@
}
if ((keyMgmtCapabilities & android.hardware.wifi.supplicant.V1_3.ISupplicantStaNetwork
.KeyMgmtMask.FILS_SHA384) != 0) {
- advancedCapabilities.set(getCapabilityIndex(WIFI_FEATURE_FILS_SHA384));
+ advancedCapabilities.set(WIFI_FEATURE_FILS_SHA384);
if (mVerboseLoggingEnabled) {
Log.v(TAG, methodStr + ": FILS_SHA384 supported");
@@ -3214,13 +3211,13 @@
}
if ((drvCapabilitiesMask.value & WpaDriverCapabilitiesMask.MBO) != 0) {
- featureSet.set(getCapabilityIndex(WIFI_FEATURE_MBO));
+ featureSet.set(WIFI_FEATURE_MBO);
if (mVerboseLoggingEnabled) {
Log.v(TAG, methodStr + ": MBO supported");
}
if ((drvCapabilitiesMask.value
& WpaDriverCapabilitiesMask.OCE) != 0) {
- featureSet.set(getCapabilityIndex(WIFI_FEATURE_OCE));
+ featureSet.set(WIFI_FEATURE_OCE);
if (mVerboseLoggingEnabled) {
Log.v(TAG, methodStr + ": OCE supported");
}
@@ -3229,7 +3226,7 @@
if ((drvCapabilitiesMask.value
& android.hardware.wifi.supplicant.V1_4.WpaDriverCapabilitiesMask.SAE_PK) != 0) {
- featureSet.set(getCapabilityIndex(WIFI_FEATURE_SAE_PK));
+ featureSet.set(WIFI_FEATURE_SAE_PK);
if (mVerboseLoggingEnabled) {
Log.v(TAG, methodStr + ": SAE-PK supported");
}
@@ -3237,7 +3234,7 @@
if ((drvCapabilitiesMask.value
& android.hardware.wifi.supplicant.V1_4.WpaDriverCapabilitiesMask.WFD_R2) != 0) {
- featureSet.set(getCapabilityIndex(WIFI_FEATURE_WFD_R2));
+ featureSet.set(WIFI_FEATURE_WFD_R2);
if (mVerboseLoggingEnabled) {
Log.v(TAG, methodStr + ": WFD-R2 supported");
}
diff --git a/service/java/com/android/server/wifi/SupplicantStaNetworkHalAidlImpl.java b/service/java/com/android/server/wifi/SupplicantStaNetworkHalAidlImpl.java
index 3a0a810..4797584 100644
--- a/service/java/com/android/server/wifi/SupplicantStaNetworkHalAidlImpl.java
+++ b/service/java/com/android/server/wifi/SupplicantStaNetworkHalAidlImpl.java
@@ -19,8 +19,6 @@
import static android.net.wifi.WifiManager.WIFI_FEATURE_TLS_V1_3;
import static android.net.wifi.WifiManager.WIFI_FEATURE_WPA3_SUITE_B;
-import static com.android.server.wifi.util.GeneralUtil.getCapabilityIndex;
-
import android.annotation.NonNull;
import android.content.Context;
import android.hardware.wifi.supplicant.AuthAlgMask;
@@ -888,7 +886,7 @@
private int getOptimalMinimumTlsVersion(WifiEnterpriseConfig enterpriseConfig) {
int maxTlsVersionSupported = WifiEnterpriseConfig.TLS_V1_2;
- if (mWpaDriverFeatures.get(getCapabilityIndex(WIFI_FEATURE_TLS_V1_3))) {
+ if (mWpaDriverFeatures.get(WIFI_FEATURE_TLS_V1_3)) {
maxTlsVersionSupported = WifiEnterpriseConfig.TLS_V1_3;
}
@@ -1048,8 +1046,7 @@
mask |= GroupCipherMask.GTK_NOT_USED;
break;
case WifiConfiguration.GroupCipher.GCMP_256:
- if (!mAdvanceKeyMgmtFeatures.get(
- getCapabilityIndex(WIFI_FEATURE_WPA3_SUITE_B))) {
+ if (!mAdvanceKeyMgmtFeatures.get(WIFI_FEATURE_WPA3_SUITE_B)) {
Log.d(TAG, "Ignore unsupported GCMP_256 cipher.");
break;
}
@@ -1110,8 +1107,7 @@
mask |= PairwiseCipherMask.CCMP;
break;
case WifiConfiguration.PairwiseCipher.GCMP_256:
- if (!mAdvanceKeyMgmtFeatures.get(
- getCapabilityIndex(WIFI_FEATURE_WPA3_SUITE_B))) {
+ if (!mAdvanceKeyMgmtFeatures.get(WIFI_FEATURE_WPA3_SUITE_B)) {
Log.d(TAG, "Ignore unsupporting GCMP_256 cipher.");
break;
}
diff --git a/service/java/com/android/server/wifi/SupplicantStaNetworkHalHidlImpl.java b/service/java/com/android/server/wifi/SupplicantStaNetworkHalHidlImpl.java
index 896019f..4a96230 100644
--- a/service/java/com/android/server/wifi/SupplicantStaNetworkHalHidlImpl.java
+++ b/service/java/com/android/server/wifi/SupplicantStaNetworkHalHidlImpl.java
@@ -17,8 +17,6 @@
import static android.net.wifi.WifiManager.WIFI_FEATURE_WPA3_SUITE_B;
-import static com.android.server.wifi.util.GeneralUtil.getCapabilityIndex;
-
import android.content.Context;
import android.hardware.wifi.supplicant.V1_0.ISupplicantStaNetwork;
import android.hardware.wifi.supplicant.V1_0.ISupplicantStaNetworkCallback;
@@ -994,8 +992,7 @@
Log.d(TAG, "Ignore GCMP_256 cipher for the HAL older than 1.2.");
break;
}
- if (!mAdvanceKeyMgmtFeatures.get(
- getCapabilityIndex(WIFI_FEATURE_WPA3_SUITE_B))) {
+ if (!mAdvanceKeyMgmtFeatures.get(WIFI_FEATURE_WPA3_SUITE_B)) {
Log.d(TAG, "Ignore unsupporting GCMP_256 cipher.");
break;
}
@@ -1072,8 +1069,7 @@
Log.d(TAG, "Ignore GCMP_256 cipher for the HAL older than 1.2.");
break;
}
- if (!mAdvanceKeyMgmtFeatures.get(
- getCapabilityIndex(WIFI_FEATURE_WPA3_SUITE_B))) {
+ if (!mAdvanceKeyMgmtFeatures.get(WIFI_FEATURE_WPA3_SUITE_B)) {
Log.d(TAG, "Ignore unsupporting GCMP_256 cipher.");
break;
}
diff --git a/service/java/com/android/server/wifi/WepNetworkUsageController.java b/service/java/com/android/server/wifi/WepNetworkUsageController.java
new file mode 100644
index 0000000..27817ed
--- /dev/null
+++ b/service/java/com/android/server/wifi/WepNetworkUsageController.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wifi;
+
+import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_WEP_ALLOWED;
+
+import android.annotation.NonNull;
+import android.net.wifi.WifiInfo;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.util.LocalLog;
+import android.util.Log;
+
+import com.android.wifi.flags.FeatureFlags;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
+/**
+ * Class used to control WEP network usage.
+ * Start to access this class from android 16 and flag: wep_disabled_in_apm is true.
+ */
+public class WepNetworkUsageController {
+ private static final String TAG = "WepNetworkUsageController";
+
+ private final HandlerThread mHandlerThread;
+ private final WifiDeviceStateChangeManager mWifiDeviceStateChangeManager;
+ private final WifiSettingsConfigStore mWifiSettingsConfigStore;
+ private final WifiGlobals mWifiGlobals;
+ private final ActiveModeWarden mActiveModeWarden;
+ private final LocalLog mLocalLog;
+ private final FeatureFlags mFeatureFlags;
+
+ private boolean mVerboseLoggingEnabled;
+ private boolean mIsWepAllowedSettingEnabled;
+ private boolean mIsAdvancedProtectionModeEnabled;
+
+ public WepNetworkUsageController(
+ @NonNull HandlerThread handlerThread,
+ @NonNull WifiDeviceStateChangeManager wifiDeviceStateChangeManager,
+ @NonNull WifiSettingsConfigStore wifiSettingsConfigStore,
+ @NonNull WifiGlobals wifiGlobals,
+ @NonNull ActiveModeWarden activeModeWarden,
+ @NonNull FeatureFlags featureFlags) {
+ mHandlerThread = handlerThread;
+ mWifiDeviceStateChangeManager = wifiDeviceStateChangeManager;
+ mWifiSettingsConfigStore = wifiSettingsConfigStore;
+ mWifiGlobals = wifiGlobals;
+ mActiveModeWarden = activeModeWarden;
+ mFeatureFlags = featureFlags;
+ if (!mFeatureFlags.wepDisabledInApm()) {
+ Log.wtf(TAG, "WepNetworkUsageController should work only"
+ + " after feature flag is enabled");
+ }
+ mLocalLog = new LocalLog(32);
+ }
+
+ /** Handle the boot completed event. Start to monitor WEP network usage */
+ public void handleBootCompleted() {
+ mIsWepAllowedSettingEnabled = mWifiSettingsConfigStore.get(WIFI_WEP_ALLOWED);
+ mWifiSettingsConfigStore.registerChangeListener(WIFI_WEP_ALLOWED,
+ (key, value) -> {
+ mIsWepAllowedSettingEnabled = value;
+ handleWepAllowedChanged();
+ },
+ new Handler(mHandlerThread.getLooper()));
+ mWifiDeviceStateChangeManager.registerStateChangeCallback(
+ new WifiDeviceStateChangeManager.StateChangeCallback() {
+ @Override
+ public void onAdvancedProtectionModeStateChanged(boolean apmOn) {
+ mIsAdvancedProtectionModeEnabled = apmOn;
+ handleWepAllowedChanged();
+ }
+ });
+ }
+
+ /**
+ * Enable verbose logging for WifiConnectivityManager.
+ */
+ public void enableVerboseLogging(boolean verbose) {
+ mVerboseLoggingEnabled = verbose;
+ }
+
+ /**
+ * Handles WEP allowed changed either settings: WIFI_WEP_ALLOWED changed or APM changed.
+ */
+ private void handleWepAllowedChanged() {
+ final boolean isWepAllowed = mIsWepAllowedSettingEnabled
+ && !mIsAdvancedProtectionModeEnabled;
+ mLocalLog.log("handleWepAllowedChanged, mIsWepAllowedSettingEnabledByUser = "
+ + mIsWepAllowedSettingEnabled
+ + " and isAdvancedProtectionEnabled = " + mIsAdvancedProtectionModeEnabled);
+ if (isWepAllowed == mWifiGlobals.isWepAllowed()) {
+ return; // No changed.
+ }
+ mWifiGlobals.setWepAllowed(isWepAllowed);
+ if (!isWepAllowed) {
+ for (ClientModeManager clientModeManager
+ : mActiveModeWarden.getClientModeManagers()) {
+ if (!(clientModeManager instanceof ConcreteClientModeManager)) {
+ continue;
+ }
+ ConcreteClientModeManager cmm = (ConcreteClientModeManager) clientModeManager;
+ WifiInfo info = cmm.getConnectionInfo();
+ if (info != null
+ && info.getCurrentSecurityType() == WifiInfo.SECURITY_TYPE_WEP) {
+ clientModeManager.disconnect();
+ }
+ }
+ }
+ }
+
+ /**
+ * Dump output for debugging.
+ */
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ pw.println("Dump of WepNetworkUsageController:");
+ if (mVerboseLoggingEnabled) {
+ mLocalLog.dump(fd, pw, args);
+ }
+ pw.println("mIsAdvancedProtectionModeEnabled=" + mIsAdvancedProtectionModeEnabled);
+ pw.println("mIsWepAllowedSettingEnabled=" + mIsWepAllowedSettingEnabled);
+
+ }
+}
diff --git a/service/java/com/android/server/wifi/WifiBlocklistMonitor.java b/service/java/com/android/server/wifi/WifiBlocklistMonitor.java
index 179f7f3..4e3a0ce 100644
--- a/service/java/com/android/server/wifi/WifiBlocklistMonitor.java
+++ b/service/java/com/android/server/wifi/WifiBlocklistMonitor.java
@@ -89,8 +89,9 @@
public static final int REASON_NONLOCAL_DISCONNECT_CONNECTING = 12;
// Connection attempt aborted by the watchdog because the AP didn't respond.
public static final int REASON_FAILURE_NO_RESPONSE = 13;
+ public static final int REASON_APP_DISALLOW = 14;
// Constant being used to keep track of how many failure reasons there are.
- public static final int NUMBER_REASON_CODES = 14;
+ public static final int NUMBER_REASON_CODES = 15;
public static final int INVALID_REASON = -1;
@IntDef(prefix = { "REASON_" }, value = {
@@ -107,7 +108,8 @@
REASON_FRAMEWORK_DISCONNECT_FAST_RECONNECT,
REASON_FRAMEWORK_DISCONNECT_CONNECTED_SCORE,
REASON_NONLOCAL_DISCONNECT_CONNECTING,
- REASON_FAILURE_NO_RESPONSE
+ REASON_FAILURE_NO_RESPONSE,
+ REASON_APP_DISALLOW
})
@Retention(RetentionPolicy.SOURCE)
public @interface FailureReason {}
@@ -186,6 +188,8 @@
"REASON_NONLOCAL_DISCONNECT_CONNECTING", true, false));
result.put(REASON_FAILURE_NO_RESPONSE, new BssidDisableReason(
"REASON_FAILURE_NO_RESPONSE", true, true));
+ result.put(REASON_APP_DISALLOW, new BssidDisableReason(
+ "REASON_APP_DISALLOW", false, false));
return result;
}
diff --git a/service/java/com/android/server/wifi/WifiConfigManager.java b/service/java/com/android/server/wifi/WifiConfigManager.java
index 87d0a5b..b476fe0 100644
--- a/service/java/com/android/server/wifi/WifiConfigManager.java
+++ b/service/java/com/android/server/wifi/WifiConfigManager.java
@@ -17,12 +17,16 @@
package com.android.server.wifi;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_PSK;
+import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_SAE;
import static android.net.wifi.WifiManager.AddNetworkResult.STATUS_INVALID_CONFIGURATION;
import static android.net.wifi.WifiManager.AddNetworkResult.STATUS_INVALID_CONFIGURATION_ENTERPRISE;
import static android.net.wifi.WifiManager.AddNetworkResult.STATUS_NO_PERMISSION_MODIFY_CONFIG;
import static android.net.wifi.WifiManager.AddNetworkResult.STATUS_SUCCESS;
import static android.net.wifi.WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE;
+import static com.android.server.wifi.WifiConfigurationUtil.validatePassword;
+
import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -81,6 +85,7 @@
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.BitSet;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
@@ -224,7 +229,6 @@
* Link networks only if the bssid in scan results for the networks match in the first
* 16 ASCII chars in the bssid string. For example = "af:de:56;34:15:7"
*/
- @VisibleForTesting
public static final int LINK_CONFIGURATION_BSSID_MATCH_LENGTH = 16;
/**
* Log tag for this class.
@@ -1125,6 +1129,12 @@
if (internalConfig.isSecurityType(newType)) {
internalConfig.setSecurityParamsIsAddedByAutoUpgrade(newType,
externalConfig.getDefaultSecurityParams().isAddedByAutoUpgrade());
+ // Set to SAE-only in case we're updating a PSK/SAE config with an SAE-only
+ // passphrase.
+ if (oldType == SECURITY_TYPE_PSK && newType == SECURITY_TYPE_SAE
+ && !validatePassword(externalConfig.preSharedKey, false, false, false)) {
+ internalConfig.setSecurityParams(externalConfig.getSecurityParamsList());
+ }
} else if (externalConfig.isSecurityType(oldType)) {
internalConfig.setSecurityParams(newType);
internalConfig.addSecurityParams(oldType);
@@ -1439,7 +1449,7 @@
}
WifiConfiguration newInternalConfig = null;
- long supportedFeatures = mWifiInjector.getActiveModeWarden()
+ BitSet supportedFeatures = mWifiInjector.getActiveModeWarden()
.getPrimaryClientModeManager().getSupportedFeatures();
// First check if we already have a network with the provided network id or configKey.
@@ -1589,7 +1599,7 @@
// Validate an Enterprise network with Trust On First Use.
if (config.isEnterprise() && config.enterpriseConfig.isTrustOnFirstUseEnabled()) {
- if ((supportedFeatures & WIFI_FEATURE_TRUST_ON_FIRST_USE) == 0) {
+ if (!supportedFeatures.get(WIFI_FEATURE_TRUST_ON_FIRST_USE)) {
Log.e(TAG, "Trust On First Use could not be set "
+ "when Trust On First Use is not supported.");
return new Pair<>(
@@ -3554,7 +3564,7 @@
List<WifiConfiguration> configurations,
Map<String, String> macAddressMapping) {
- long supportedFeatures = mWifiInjector.getActiveModeWarden()
+ BitSet supportedFeatures = mWifiInjector.getActiveModeWarden()
.getPrimaryClientModeManager().getSupportedFeatures();
for (WifiConfiguration configuration : configurations) {
@@ -3593,7 +3603,7 @@
* @param configurations list of configurations retrieved from store.
*/
private void loadInternalDataFromUserStore(List<WifiConfiguration> configurations) {
- long supportedFeatures = mWifiInjector.getActiveModeWarden()
+ BitSet supportedFeatures = mWifiInjector.getActiveModeWarden()
.getPrimaryClientModeManager().getSupportedFeatures();
for (WifiConfiguration configuration : configurations) {
diff --git a/service/java/com/android/server/wifi/WifiConfigurationUtil.java b/service/java/com/android/server/wifi/WifiConfigurationUtil.java
index 501a071..b44d2af 100644
--- a/service/java/com/android/server/wifi/WifiConfigurationUtil.java
+++ b/service/java/com/android/server/wifi/WifiConfigurationUtil.java
@@ -515,7 +515,10 @@
return true;
}
- private static boolean validatePassword(String password, boolean isAdd, boolean isSae,
+ /**
+ * Checks that a password is formatted correctly.
+ */
+ public static boolean validatePassword(String password, boolean isAdd, boolean isSae,
boolean isWapi) {
if (isAdd) {
if (password == null) {
@@ -753,7 +756,7 @@
* update could contain only the fields that are being changed.
* @return true if the parameters are valid, false otherwise.
*/
- public static boolean validate(WifiConfiguration config, long supportedFeatureSet,
+ public static boolean validate(WifiConfiguration config, BitSet supportedFeatureSet,
boolean isAdd) {
if (!validateSsid(config.SSID, isAdd)) {
return false;
@@ -799,7 +802,7 @@
return false;
}
if (config.isSecurityType(WifiConfiguration.SECURITY_TYPE_DPP)
- && (supportedFeatureSet & WifiManager.WIFI_FEATURE_DPP_AKM) == 0) {
+ && !supportedFeatureSet.get(WifiManager.WIFI_FEATURE_DPP_AKM)) {
Log.e(TAG, "DPP AKM is not supported");
return false;
}
@@ -1182,14 +1185,14 @@
}
private static boolean isSecurityParamsSupported(SecurityParams params) {
- final long wifiFeatures = WifiInjector.getInstance()
+ final BitSet wifiFeatures = WifiInjector.getInstance()
.getActiveModeWarden().getPrimaryClientModeManager()
.getSupportedFeatures();
switch (params.getSecurityType()) {
case WifiConfiguration.SECURITY_TYPE_SAE:
- return 0 != (wifiFeatures & WifiManager.WIFI_FEATURE_WPA3_SAE);
+ return wifiFeatures.get(WifiManager.WIFI_FEATURE_WPA3_SAE);
case WifiConfiguration.SECURITY_TYPE_OWE:
- return 0 != (wifiFeatures & WifiManager.WIFI_FEATURE_OWE);
+ return wifiFeatures.get(WifiManager.WIFI_FEATURE_OWE);
}
return true;
}
diff --git a/service/java/com/android/server/wifi/WifiConnectivityHelper.java b/service/java/com/android/server/wifi/WifiConnectivityHelper.java
index e1c43ec..65d5306 100644
--- a/service/java/com/android/server/wifi/WifiConnectivityHelper.java
+++ b/service/java/com/android/server/wifi/WifiConnectivityHelper.java
@@ -25,6 +25,7 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.BitSet;
/**
* This class provides helper functions for Wifi connectivity related modules to
@@ -63,10 +64,10 @@
ClientModeManager primaryManager =
mWifiInjector.getActiveModeWarden().getPrimaryClientModeManager();
- long fwFeatureSet = primaryManager.getSupportedFeatures();
- Log.d(TAG, "Firmware supported feature set: " + Long.toHexString(fwFeatureSet));
+ BitSet fwFeatureSet = primaryManager.getSupportedFeatures();
+ Log.d(TAG, "Firmware supported feature set: " + fwFeatureSet);
- if ((fwFeatureSet & WIFI_FEATURE_CONTROL_ROAMING) == 0) {
+ if (!fwFeatureSet.get(WIFI_FEATURE_CONTROL_ROAMING)) {
Log.d(TAG, "Firmware roaming is not supported");
return true;
}
diff --git a/service/java/com/android/server/wifi/WifiConnectivityManager.java b/service/java/com/android/server/wifi/WifiConnectivityManager.java
index b7e12e0..da0ae94 100644
--- a/service/java/com/android/server/wifi/WifiConnectivityManager.java
+++ b/service/java/com/android/server/wifi/WifiConnectivityManager.java
@@ -69,7 +69,6 @@
import com.android.server.wifi.proto.WifiStatsLog;
import com.android.server.wifi.scanner.WifiScannerInternal;
import com.android.server.wifi.util.WifiPermissionsUtil;
-import com.android.wifi.flags.FeatureFlags;
import com.android.wifi.resources.R;
import java.io.FileDescriptor;
@@ -184,7 +183,6 @@
private final WifiChannelUtilization mWifiChannelUtilization;
private final PowerManager mPowerManager;
private final DeviceConfigFacade mDeviceConfigFacade;
- private final FeatureFlags mFeatureFlags;
private final ActiveModeWarden mActiveModeWarden;
private final FrameworkFacade mFrameworkFacade;
private final WifiPermissionsUtil mWifiPermissionsUtil;
@@ -203,6 +201,7 @@
private int mInitialScanState = INITIAL_SCAN_STATE_COMPLETE;
private boolean mAutoJoinEnabledExternal = true; // enabled by default
private boolean mAutoJoinEnabledExternalSetByDeviceAdmin = false;
+ private int mAutojoinDisallowedSecurityTypes = 0; // restrict none by default
private boolean mUntrustedConnectionAllowed = false;
private Set<Integer> mRestrictedConnectionAllowedUids = new ArraySet<>();
private boolean mOemPaidConnectionAllowed = false;
@@ -684,13 +683,11 @@
List<WifiCandidates.Candidate> candidates = mNetworkSelector.getCandidatesFromScan(
scanDetails, bssidBlocklist, cmmStates, mUntrustedConnectionAllowed,
mOemPaidConnectionAllowed, mOemPrivateConnectionAllowed,
- mRestrictedConnectionAllowedUids, skipSufficiencyCheck);
-
+ mRestrictedConnectionAllowedUids, skipSufficiencyCheck,
+ mAutojoinDisallowedSecurityTypes);
// Filter candidates before caching to avoid reconnecting on failure
- if (mFeatureFlags.delayedCarrierNetworkSelection()) {
- candidates = filterDelayedCarrierSelectionCandidates(candidates, listenerName,
- isFullScan);
- }
+ candidates = filterDelayedCarrierSelectionCandidates(candidates, listenerName,
+ isFullScan);
mLatestCandidates = candidates;
mLatestCandidatesTimestampMs = mClock.getElapsedSinceBootMillis();
@@ -1507,7 +1504,6 @@
mPasspointManager = passpointManager;
mMultiInternetManager = multiInternetManager;
mDeviceConfigFacade = deviceConfigFacade;
- mFeatureFlags = mDeviceConfigFacade.getFeatureFlags();
mActiveModeWarden = activeModeWarden;
mFrameworkFacade = frameworkFacade;
mWifiGlobals = wifiGlobals;
@@ -3669,6 +3665,22 @@
}
/**
+ * Set auto join restriction on select security types
+ */
+ public void setAutojoinDisallowedSecurityTypes(int restrictions) {
+ localLog("Set auto join restriction on select security types - restrictions: "
+ + restrictions);
+ mAutojoinDisallowedSecurityTypes = restrictions;
+ }
+
+ /**
+ * Return auto join restriction on select security types
+ */
+ public int getAutojoinDisallowedSecurityTypes() {
+ return mAutojoinDisallowedSecurityTypes;
+ }
+
+ /**
* Check if multi internet connection exists.
*
* @return true if multi internet connection exists.
diff --git a/service/java/com/android/server/wifi/WifiDataStall.java b/service/java/com/android/server/wifi/WifiDataStall.java
index 97131f0..45aa5f7 100644
--- a/service/java/com/android/server/wifi/WifiDataStall.java
+++ b/service/java/com/android/server/wifi/WifiDataStall.java
@@ -344,6 +344,22 @@
}
/**
+ * Get the number of tx bytes transmitted on current interface since the interface is created
+ * @return the number of tx bytes transmitted
+ */
+ public long getTxTransmittedBytes() {
+ return mLastTxBytes;
+ }
+
+ /**
+ * Get the number of rx bytes transmitted on current interface since the interface is created
+ * @return the number of tx bytes transmitted
+ */
+ public long getRxTransmittedBytes() {
+ return mLastRxBytes;
+ }
+
+ /**
* Update data stall detection, check throughput sufficiency and report wifi health stat
* with the latest link layer stats
* @param connectionCapabilities Connection capabilities.
diff --git a/service/java/com/android/server/wifi/WifiDeviceStateChangeManager.java b/service/java/com/android/server/wifi/WifiDeviceStateChangeManager.java
index 74df0a5..6efa28f 100644
--- a/service/java/com/android/server/wifi/WifiDeviceStateChangeManager.java
+++ b/service/java/com/android/server/wifi/WifiDeviceStateChangeManager.java
@@ -16,15 +16,22 @@
package com.android.server.wifi;
+import android.annotation.SuppressLint;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.net.wifi.util.Environment;
import android.os.Handler;
import android.os.PowerManager;
+import android.security.Flags;
+import android.security.advancedprotection.AdvancedProtectionManager;
import android.text.TextUtils;
import android.util.ArraySet;
+import com.android.modules.utils.HandlerExecutor;
+import com.android.wifi.flags.FeatureFlags;
+
import java.util.Set;
/** A centralized manager to handle all the device state changes */
@@ -33,6 +40,10 @@
private final Context mContext;
private final PowerManager mPowerManager;
+ private final WifiInjector mWifiInjector;
+ private AdvancedProtectionManager mAdvancedProtectionManager;
+ private FeatureFlags mFeatureFlags;
+
private final Set<StateChangeCallback> mChangeCallbackList = new ArraySet<>();
private boolean mIsWifiServiceStarted = false;
@@ -47,17 +58,28 @@
* @param screenOn true for ON, false otherwise
*/
default void onScreenStateChanged(boolean screenOn) {}
+
+ /**
+ * Called when the Advanced protection mode state changes
+ *
+ * @param apmOn true for ON, false otherwise
+ */
+ default void onAdvancedProtectionModeStateChanged(boolean apmOn) {}
}
/** Create the instance of WifiDeviceStateChangeManager. */
- public WifiDeviceStateChangeManager(Context context, Handler handler) {
+ public WifiDeviceStateChangeManager(Context context, Handler handler,
+ WifiInjector wifiInjector) {
mHandler = handler;
mContext = context;
+ mWifiInjector = wifiInjector;
mPowerManager = mContext.getSystemService(PowerManager.class);
}
/** Handle the boot completed event. Start to register the receiver and callback. */
+ @SuppressLint("NewApi")
public void handleBootCompleted() {
+ mFeatureFlags = mWifiInjector.getDeviceConfigFacade().getFeatureFlags();
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
@@ -76,6 +98,23 @@
},
filter);
handleScreenStateChanged(mPowerManager.isInteractive());
+ if (Environment.isSdkAtLeastB() && mFeatureFlags.wepDisabledInApm() && Flags.aapmApi()) {
+ mAdvancedProtectionManager =
+ mContext.getSystemService(AdvancedProtectionManager.class);
+ if (mAdvancedProtectionManager != null) {
+ mAdvancedProtectionManager.registerAdvancedProtectionCallback(
+ new HandlerExecutor(mHandler),
+ state -> {
+ handleAdvancedProtectionModeStateChanged(state);
+ });
+ handleAdvancedProtectionModeStateChanged(
+ mAdvancedProtectionManager.isAdvancedProtectionEnabled());
+ } else {
+ handleAdvancedProtectionModeStateChanged(false);
+ }
+ } else {
+ handleAdvancedProtectionModeStateChanged(false);
+ }
mIsWifiServiceStarted = true;
}
@@ -83,10 +122,17 @@
* Register a state change callback. When the state is changed, caller with receive the callback
* event
*/
+ @SuppressLint("NewApi")
public void registerStateChangeCallback(StateChangeCallback callback) {
mChangeCallbackList.add(callback);
if (!mIsWifiServiceStarted) return;
callback.onScreenStateChanged(mPowerManager.isInteractive());
+ if (Environment.isSdkAtLeastB() && mAdvancedProtectionManager != null) {
+ callback.onAdvancedProtectionModeStateChanged(
+ mAdvancedProtectionManager.isAdvancedProtectionEnabled());
+ } else {
+ callback.onAdvancedProtectionModeStateChanged(false);
+ }
}
/**
@@ -101,4 +147,10 @@
callback.onScreenStateChanged(screenOn);
}
}
+
+ private void handleAdvancedProtectionModeStateChanged(boolean apmOn) {
+ for (StateChangeCallback callback : mChangeCallbackList) {
+ callback.onAdvancedProtectionModeStateChanged(apmOn);
+ }
+ }
}
diff --git a/service/java/com/android/server/wifi/WifiDiagnostics.java b/service/java/com/android/server/wifi/WifiDiagnostics.java
index 4c48868..87fb91d 100644
--- a/service/java/com/android/server/wifi/WifiDiagnostics.java
+++ b/service/java/com/android/server/wifi/WifiDiagnostics.java
@@ -1053,6 +1053,13 @@
return;
}
+ if (bugDetail.equals("Subsystem Restart") && !mContext.getResources().getBoolean(
+ R.bool.config_wifi_subsystem_restart_bugreport_enabled)) {
+ Log.d(TAG, "config_wifi_subsystem_restart_bugreport_enabled is disabled, skip "
+ + bugTitle + "(" + bugDetail + ")");
+ return;
+ }
+
if (!shouldTakeBugreport(bugTitle, bugDetail)) {
return;
}
diff --git a/service/java/com/android/server/wifi/WifiDialogManager.java b/service/java/com/android/server/wifi/WifiDialogManager.java
index cc175b6..15485e9 100644
--- a/service/java/com/android/server/wifi/WifiDialogManager.java
+++ b/service/java/com/android/server/wifi/WifiDialogManager.java
@@ -232,31 +232,15 @@
@AnyThread
public void launchDialog() {
if (mInternalHandle != null) {
- mWifiThreadRunner.post(() -> mInternalHandle.launchDialog(0),
+ mWifiThreadRunner.post(() -> mInternalHandle.launchDialog(),
TAG + "#launchDialog");
} else if (mLegacyHandle != null) {
- mWifiThreadRunner.post(() -> mLegacyHandle.launchDialog(0),
+ mWifiThreadRunner.post(() -> mLegacyHandle.launchDialog(),
TAG + "#launchDialog");
}
}
/**
- * Launches the dialog with a timeout before it is auto-cancelled.
- * @param timeoutMs timeout in milliseconds before the dialog is auto-cancelled. A value <=0
- * indicates no timeout.
- */
- @AnyThread
- public void launchDialog(long timeoutMs) {
- if (mInternalHandle != null) {
- mWifiThreadRunner.post(() -> mInternalHandle.launchDialog(timeoutMs),
- TAG + "#launchDialogTimeout");
- } else if (mLegacyHandle != null) {
- mWifiThreadRunner.post(() -> mLegacyHandle.launchDialog(timeoutMs),
- TAG + "#launchDialogTimeout");
- }
- }
-
- /**
* Dismisses the dialog. Dialogs will automatically be dismissed once the user replies, but
* this method may be used to dismiss unanswered dialogs that are no longer needed.
*/
@@ -291,9 +275,9 @@
}
/**
- * @see {@link DialogHandle#launchDialog(long)}
+ * @see DialogHandle#launchDialog()
*/
- void launchDialog(long timeoutMs) {
+ void launchDialog() {
if (mIntent == null) {
Log.e(TAG, "Cannot launch dialog with null Intent!");
return;
@@ -303,7 +287,6 @@
return;
}
registerDialog();
- mIntent.putExtra(WifiManager.EXTRA_DIALOG_TIMEOUT_MS, timeoutMs);
mIntent.putExtra(WifiManager.EXTRA_DIALOG_ID, mDialogId);
boolean launched = false;
// Collapse the QuickSettings since we can't show WifiDialog dialogs over it.
@@ -474,10 +457,8 @@
final String mNeutralButtonText;
@Nullable final SimpleDialogCallback mCallback;
@Nullable final WifiThreadRunner mCallbackThreadRunner;
- private Runnable mTimeoutRunnable;
private AlertDialog mAlertDialog;
int mWindowType = WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
- long mTimeoutMs = 0;
LegacySimpleDialogHandle(
final String title,
@@ -525,18 +506,12 @@
mCallbackThreadRunner = callbackThreadRunner;
}
- void launchDialog(long timeoutMs) {
+ void launchDialog() {
if (mAlertDialog != null && mAlertDialog.isShowing()) {
// Dialog is already launched. Dismiss and create a new one.
mAlertDialog.setOnDismissListener(null);
mAlertDialog.dismiss();
}
- if (mTimeoutRunnable != null) {
- // Reset the timeout runnable if one has already been created.
- mWifiThreadRunner.removeCallbacks(mTimeoutRunnable);
- mTimeoutRunnable = null;
- }
- mTimeoutMs = timeoutMs;
mAlertDialog = mFrameworkFacade.makeAlertDialogBuilder(
new ContextThemeWrapper(mContext, R.style.wifi_dialog))
.setTitle(mTitle)
@@ -579,10 +554,6 @@
})
.setOnDismissListener((dialogDismiss) -> {
mWifiThreadRunner.post(() -> {
- if (mTimeoutRunnable != null) {
- mWifiThreadRunner.removeCallbacks(mTimeoutRunnable);
- mTimeoutRunnable = null;
- }
mAlertDialog = null;
mActiveLegacySimpleDialogs.remove(this);
}, mTitle + "#onDismiss");
@@ -609,11 +580,6 @@
if (messageView != null) {
messageView.setMovementMethod(LinkMovementMethod.getInstance());
}
- if (mTimeoutMs > 0) {
- mTimeoutRunnable = mAlertDialog::cancel;
- mWifiThreadRunner.postDelayed(mTimeoutRunnable, mTimeoutMs,
- TAG + "#cancelDialog");
- }
mActiveLegacySimpleDialogs.add(this);
}
@@ -632,7 +598,7 @@
void changeWindowType(int windowType) {
mWindowType = windowType;
if (mActiveLegacySimpleDialogs.contains(this)) {
- launchDialog(mTimeoutMs);
+ launchDialog();
}
}
}
@@ -657,7 +623,7 @@
void onNeutralButtonClicked();
/**
- * The dialog was cancelled (back button or home button or timeout).
+ * The dialog was cancelled (back button or home button).
*/
void onCancelled();
}
@@ -897,6 +863,7 @@
final @Nullable String deviceName,
final boolean isPinRequested,
@Nullable String displayPin,
+ int timeoutMs,
int displayId,
@Nullable P2pInvitationReceivedDialogCallback callback,
@Nullable WifiThreadRunner callbackThreadRunner) {
@@ -904,7 +871,8 @@
if (intent != null) {
intent.putExtra(WifiManager.EXTRA_P2P_DEVICE_NAME, deviceName)
.putExtra(WifiManager.EXTRA_P2P_PIN_REQUESTED, isPinRequested)
- .putExtra(WifiManager.EXTRA_P2P_DISPLAY_PIN, displayPin);
+ .putExtra(WifiManager.EXTRA_P2P_DISPLAY_PIN, displayPin)
+ .putExtra(WifiManager.EXTRA_DIALOG_TIMEOUT_MS, timeoutMs);
setIntent(intent);
}
setDisplayId(displayId);
@@ -952,13 +920,14 @@
* @param deviceName Name of the device sending the invitation.
* @param isPinRequested True if a PIN was requested and a PIN input UI should be shown.
* @param displayPin Display PIN, or {@code null} if no PIN should be displayed
+ * @param timeoutMs Timeout for the dialog in milliseconds. 0 indicates no timeout.
* @param displayId The ID of the Display on which to place the dialog
* (Display.DEFAULT_DISPLAY
* refers to the default display)
* @param callback Callback to receive the dialog response.
* @param callbackThreadRunner WifiThreadRunner to run the callback on.
* @return DialogHandle Handle for the dialog, or {@code null} if no dialog could
- * be created.
+ * be created.
*/
@AnyThread
@NonNull
@@ -966,6 +935,7 @@
@Nullable String deviceName,
boolean isPinRequested,
@Nullable String displayPin,
+ int timeoutMs,
int displayId,
@Nullable P2pInvitationReceivedDialogCallback callback,
@Nullable WifiThreadRunner callbackThreadRunner) {
@@ -974,6 +944,7 @@
deviceName,
isPinRequested,
displayPin,
+ timeoutMs,
displayId,
callback,
callbackThreadRunner)
diff --git a/service/java/com/android/server/wifi/WifiGlobals.java b/service/java/com/android/server/wifi/WifiGlobals.java
index 1b37c07..bc778da 100644
--- a/service/java/com/android/server/wifi/WifiGlobals.java
+++ b/service/java/com/android/server/wifi/WifiGlobals.java
@@ -653,6 +653,15 @@
.getInteger(R.integer.config_wifiDisableTemporaryMaximumDurationMs);
}
+ /**
+ * Returns whether device support Wi-Fi 7 multi-link device Soft Ap.
+ */
+ public boolean isMLDApSupported() {
+ int numberOfMLDSupported = mWifiResourceCache
+ .getInteger(R.integer.config_wifiSoftApMaxNumberMLDSupported);
+ return numberOfMLDSupported != 0;
+ }
+
/** Dump method for debugging */
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println("Dump of WifiGlobals");
diff --git a/service/java/com/android/server/wifi/WifiInjector.java b/service/java/com/android/server/wifi/WifiInjector.java
index ddb7a0f..8df39ac 100644
--- a/service/java/com/android/server/wifi/WifiInjector.java
+++ b/service/java/com/android/server/wifi/WifiInjector.java
@@ -270,6 +270,9 @@
private final TwtManager mTwtManager;
private final WifiVoipDetector mWifiVoipDetector;
private final boolean mHasActiveModem;
+ private final RunnerHandler mWifiHandler;
+ private boolean mVerboseLoggingEnabled;
+ @Nullable private final WepNetworkUsageController mWepNetworkUsageController;
public WifiInjector(WifiContext context) {
if (context == null) {
@@ -298,20 +301,21 @@
mWifiMonitor = new WifiMonitor();
mBatteryStats = context.getSystemService(BatteryStatsManager.class);
mWifiP2pMetrics = new WifiP2pMetrics(mClock, mContext);
- RunnerHandler wifiHandler = new RunnerHandler(wifiLooper, context.getResources().getInteger(
+ mWifiHandler = new RunnerHandler(wifiLooper, context.getResources().getInteger(
R.integer.config_wifiConfigurationWifiRunnerThresholdInMs),
mWifiHandlerLocalLog);
- mWifiDeviceStateChangeManager = new WifiDeviceStateChangeManager(context, wifiHandler);
+ mWifiDeviceStateChangeManager = new WifiDeviceStateChangeManager(context, mWifiHandler,
+ this);
+ mWifiGlobals = new WifiGlobals(mContext);
mWifiMetrics = new WifiMetrics(mContext, mFrameworkFacade, mClock, wifiLooper,
awareMetrics, rttMetrics, new WifiPowerMetrics(mBatteryStats), mWifiP2pMetrics,
- mDppMetrics, mWifiMonitor, mWifiDeviceStateChangeManager);
+ mDppMetrics, mWifiMonitor, mWifiDeviceStateChangeManager, mWifiGlobals);
mWifiDiagnosticsHandlerThread = new HandlerThread("WifiDiagnostics");
mWifiDiagnosticsHandlerThread.start();
mWifiNotificationManager = new WifiNotificationManager(mContext);
- mWifiGlobals = new WifiGlobals(mContext);
mScoringParams = new ScoringParams(mContext);
mWifiChannelUtilizationScan = new WifiChannelUtilization(mClock, mContext);
mSettingsMigrationDataHolder = new SettingsMigrationDataHolder(mContext);
@@ -325,35 +329,35 @@
mWifiBackupRestore = new WifiBackupRestore(mWifiPermissionsUtil);
mSoftApBackupRestore = new SoftApBackupRestore(mContext, mSettingsMigrationDataHolder);
mWifiStateTracker = new WifiStateTracker(mBatteryStats);
- mWifiThreadRunner = new WifiThreadRunner(wifiHandler);
+ mWifiThreadRunner = new WifiThreadRunner(mWifiHandler);
mWifiDialogManager = new WifiDialogManager(mContext, mWifiThreadRunner, mFrameworkFacade,
this);
- mSsidTranslator = new SsidTranslator(mContext, wifiHandler);
+ mSsidTranslator = new SsidTranslator(mContext, mWifiHandler);
mPasspointProvisionerHandlerThread =
new HandlerThread("PasspointProvisionerHandlerThread");
mPasspointProvisionerHandlerThread.start();
- mDeviceConfigFacade = new DeviceConfigFacade(mContext, wifiHandler, mWifiMetrics);
+ mDeviceConfigFacade = new DeviceConfigFacade(mContext, mWifiHandler, mWifiMetrics);
mFeatureFlags = mDeviceConfigFacade.getFeatureFlags();
mAdaptiveConnectivityEnabledSettingObserver =
- new AdaptiveConnectivityEnabledSettingObserver(wifiHandler, mWifiMetrics,
+ new AdaptiveConnectivityEnabledSettingObserver(mWifiHandler, mWifiMetrics,
mFrameworkFacade, mContext);
// Modules interacting with Native.
- mHalDeviceManager = new HalDeviceManager(mContext, mClock, this, wifiHandler);
+ mHalDeviceManager = new HalDeviceManager(mContext, mClock, this, mWifiHandler);
mInterfaceConflictManager = new InterfaceConflictManager(this, mContext, mFrameworkFacade,
mHalDeviceManager, mWifiThreadRunner, mWifiDialogManager, new LocalLog(
mContext.getSystemService(ActivityManager.class).isLowRamDevice() ? 128 : 256));
- mWifiVendorHal = new WifiVendorHal(mContext, mHalDeviceManager, wifiHandler, mWifiGlobals,
+ mWifiVendorHal = new WifiVendorHal(mContext, mHalDeviceManager, mWifiHandler, mWifiGlobals,
mSsidTranslator);
mSupplicantStaIfaceHal = new SupplicantStaIfaceHal(
- mContext, mWifiMonitor, mFrameworkFacade, wifiHandler, mClock, mWifiMetrics,
+ mContext, mWifiMonitor, mFrameworkFacade, mWifiHandler, mClock, mWifiMetrics,
mWifiGlobals, mSsidTranslator, this);
- mHostapdHal = new HostapdHal(mContext, wifiHandler);
+ mHostapdHal = new HostapdHal(mContext, mWifiHandler);
mWifiCondManager = (WifiNl80211Manager) mContext.getSystemService(
Context.WIFI_NL80211_SERVICE);
mWifiNative = new WifiNative(
mWifiVendorHal, mSupplicantStaIfaceHal, mHostapdHal, mWifiCondManager,
mWifiMonitor, mPropertyService, mWifiMetrics,
- wifiHandler, new Random(), mBuildProperties, this);
+ mWifiHandler, new Random(), mBuildProperties, this);
mWifiP2pMonitor = new WifiP2pMonitor();
mSupplicantP2pIfaceHal = new SupplicantP2pIfaceHal(mWifiP2pMonitor, mWifiGlobals, this);
mWifiP2pNative = new WifiP2pNative(mWifiCondManager, mWifiNative, mWifiMetrics,
@@ -363,7 +367,7 @@
if (SdkLevel.isAtLeastS()) {
mCoexManager = new CoexManager(mContext, mWifiNative, makeTelephonyManager(),
subscriptionManager, mContext.getSystemService(CarrierConfigManager.class),
- wifiHandler);
+ mWifiHandler);
} else {
mCoexManager = null;
}
@@ -391,7 +395,7 @@
wifiLooper);
mWifiCarrierInfoManager = new WifiCarrierInfoManager(makeTelephonyManager(),
subscriptionManager, this, mFrameworkFacade, mContext,
- mWifiConfigStore, wifiHandler, mWifiMetrics, mClock, mWifiPseudonymManager);
+ mWifiConfigStore, mWifiHandler, mWifiMetrics, mClock, mWifiPseudonymManager);
String l2KeySeed = Secure.getString(mContext.getContentResolver(), Secure.ANDROID_ID);
mWifiScoreCard = new WifiScoreCard(mClock, l2KeySeed, mDeviceConfigFacade,
mContext, mWifiGlobals);
@@ -439,8 +443,8 @@
new RandomizedMacStoreData(),
mLruConnectionTracker,
this,
- wifiHandler);
- mSettingsConfigStore = new WifiSettingsConfigStore(context, wifiHandler,
+ mWifiHandler);
+ mSettingsConfigStore = new WifiSettingsConfigStore(context, mWifiHandler,
mSettingsMigrationDataHolder, mWifiConfigManager, mWifiConfigStore);
mWifiSettingsBackupRestore = new WifiSettingsBackupRestore(mSettingsConfigStore);
mSettingsStore = new WifiSettingsStore(mContext, mSettingsConfigStore, mWifiThreadRunner,
@@ -472,12 +476,12 @@
mThroughputScorer = new ThroughputScorer(mContext, mScoringParams);
mWifiNetworkSelector.registerCandidateScorer(mThroughputScorer);
mWifiMetrics.setWifiNetworkSelector(mWifiNetworkSelector);
- mWifiNetworkSuggestionsManager = new WifiNetworkSuggestionsManager(mContext, wifiHandler,
+ mWifiNetworkSuggestionsManager = new WifiNetworkSuggestionsManager(mContext, mWifiHandler,
this, mWifiPermissionsUtil, mWifiConfigManager, mWifiConfigStore, mWifiMetrics,
mWifiCarrierInfoManager, mWifiKeyStore, mLruConnectionTracker,
mClock);
mPasspointManager = new PasspointManager(mContext, this,
- wifiHandler, mWifiNative, mWifiKeyStore, mClock, new PasspointObjectFactory(),
+ mWifiHandler, mWifiNative, mWifiKeyStore, mClock, new PasspointObjectFactory(),
mWifiConfigManager, mWifiConfigStore, mSettingsStore, mWifiMetrics,
mWifiCarrierInfoManager, mMacAddressUtil, mWifiPermissionsUtil);
mNominateHelper =
@@ -499,7 +503,7 @@
mDefaultClientModeManager = new DefaultClientModeManager();
mExternalScoreUpdateObserverProxy =
new ExternalScoreUpdateObserverProxy(mWifiThreadRunner);
- mDppManager = new DppManager(this, wifiHandler, mWifiNative,
+ mDppManager = new DppManager(this, mWifiHandler, mWifiNative,
mWifiConfigManager, mContext, mDppMetrics, mScanRequestProxy, mWifiPermissionsUtil);
mActiveModeWarden = new ActiveModeWarden(this, wifiLooper,
mWifiNative, mDefaultClientModeManager, mBatteryStats, mWifiDiagnostics,
@@ -507,10 +511,10 @@
mExternalScoreUpdateObserverProxy, mDppManager, mWifiGlobals);
mWifiMetrics.setActiveModeWarden(mActiveModeWarden);
mWifiHealthMonitor = new WifiHealthMonitor(mContext, this, mClock, mWifiConfigManager,
- mWifiScoreCard, wifiHandler, mWifiNative, l2KeySeed, mDeviceConfigFacade,
+ mWifiScoreCard, mWifiHandler, mWifiNative, l2KeySeed, mDeviceConfigFacade,
mActiveModeWarden);
mWifiDataStall = new WifiDataStall(mWifiMetrics, mContext,
- mDeviceConfigFacade, wifiChannelUtilizationConnected, mClock, wifiHandler,
+ mDeviceConfigFacade, wifiChannelUtilizationConnected, mClock, mWifiHandler,
mThroughputPredictor, mActiveModeWarden, mCmiMonitor, mWifiGlobals);
mWifiMetrics.setWifiDataStall(mWifiDataStall);
mWifiMetrics.setWifiHealthMonitor(mWifiHealthMonitor);
@@ -525,8 +529,8 @@
new ConnectToNetworkNotificationBuilder(mContext, mFrameworkFacade),
mMakeBeforeBreakManager, mWifiNotificationManager, mWifiPermissionsUtil);
mMultiInternetManager = new MultiInternetManager(mActiveModeWarden, mFrameworkFacade,
- mContext, mCmiMonitor, mSettingsStore, wifiHandler, mClock);
- mExternalPnoScanRequestManager = new ExternalPnoScanRequestManager(wifiHandler, mContext);
+ mContext, mCmiMonitor, mSettingsStore, mWifiHandler, mClock);
+ mExternalPnoScanRequestManager = new ExternalPnoScanRequestManager(mWifiHandler, mContext);
mCountryCode = new WifiCountryCode(mContext, mActiveModeWarden, mWifiP2pMetrics,
mCmiMonitor, mWifiNative, mSettingsConfigStore, mClock, mWifiPermissionsUtil,
mWifiCarrierInfoManager);
@@ -534,7 +538,7 @@
mContext, mScoringParams, mWifiConfigManager,
mWifiNetworkSuggestionsManager, mWifiNetworkSelector,
mWifiConnectivityHelper, mWifiLastResortWatchdog, mOpenNetworkNotifier,
- mWifiMetrics, wifiHandler,
+ mWifiMetrics, mWifiHandler,
mClock, mConnectivityLocalLog, mWifiScoreCard, mWifiBlocklistMonitor,
mWifiChannelUtilizationScan, mPasspointManager, mMultiInternetManager,
mDeviceConfigFacade, mActiveModeWarden, mFrameworkFacade, mWifiGlobals,
@@ -545,7 +549,7 @@
mWifiThreadRunner);
mConnectionFailureNotifier = new ConnectionFailureNotifier(
mContext, mFrameworkFacade, mWifiConfigManager,
- mWifiConnectivityManager, wifiHandler,
+ mWifiConnectivityManager, mWifiHandler,
mWifiNotificationManager, mConnectionFailureNotificationBuilder,
mWifiDialogManager);
mWifiNetworkFactory = new WifiNetworkFactory(
@@ -576,27 +580,28 @@
mWifiPermissionsUtil, mMultiInternetManager, mWifiConnectivityManager,
mConnectivityLocalLog);
mWifiScanAlwaysAvailableSettingsCompatibility =
- new WifiScanAlwaysAvailableSettingsCompatibility(mContext, wifiHandler,
+ new WifiScanAlwaysAvailableSettingsCompatibility(mContext, mWifiHandler,
mSettingsStore, mActiveModeWarden, mFrameworkFacade);
mWifiApConfigStore = new WifiApConfigStore(
- mContext, this, wifiHandler, mBackupManagerProxy,
+ mContext, this, mWifiHandler, mBackupManagerProxy,
mWifiConfigStore, mWifiConfigManager, mActiveModeWarden, mWifiMetrics);
WakeupNotificationFactory wakeupNotificationFactory =
new WakeupNotificationFactory(mContext, mFrameworkFacade);
WakeupOnboarding wakeupOnboarding = new WakeupOnboarding(mContext, mWifiConfigManager,
- wifiHandler, mFrameworkFacade, wakeupNotificationFactory, mWifiNotificationManager);
- mWakeupController = new WakeupController(mContext, wifiHandler,
+ mWifiHandler, mFrameworkFacade, wakeupNotificationFactory,
+ mWifiNotificationManager);
+ mWakeupController = new WakeupController(mContext, mWifiHandler,
new WakeupLock(mWifiConfigManager, mWifiMetrics.getWakeupMetrics(), mClock),
new WakeupEvaluator(mScoringParams), wakeupOnboarding, mWifiConfigManager,
mWifiConfigStore, mWifiNetworkSuggestionsManager, mWifiMetrics.getWakeupMetrics(),
this, mFrameworkFacade, mClock, mActiveModeWarden);
mLockManager = new WifiLockManager(mContext, mBatteryStats, mActiveModeWarden,
- mFrameworkFacade, wifiHandler, mClock, mWifiMetrics, mDeviceConfigFacade,
+ mFrameworkFacade, mWifiHandler, mClock, mWifiMetrics, mDeviceConfigFacade,
mWifiPermissionsUtil, mWifiDeviceStateChangeManager);
mSelfRecovery = new SelfRecovery(mContext, mActiveModeWarden, mClock, mWifiNative,
mWifiGlobals);
mWifiMulticastLockManager = new WifiMulticastLockManager(mActiveModeWarden, mBatteryStats,
- wifiLooper);
+ wifiLooper, mContext);
mApplicationQosPolicyRequestHandler = new ApplicationQosPolicyRequestHandler(
mActiveModeWarden, mWifiNative, mWifiHandlerThread, mDeviceConfigFacade, mContext);
@@ -607,7 +612,7 @@
mSimRequiredNotifier = new SimRequiredNotifier(mContext, mFrameworkFacade,
mWifiNotificationManager);
mWifiPulledAtomLogger = new WifiPulledAtomLogger(
- mContext.getSystemService(StatsManager.class), wifiHandler,
+ mContext.getSystemService(StatsManager.class), mWifiHandler,
mContext, this);
mAfcLocationUtil = new AfcLocationUtil();
mAfcClient = new AfcClient(BackgroundThread.getHandler());
@@ -621,16 +626,23 @@
mActiveModeWarden, new WifiRoamingConfigStore(mWifiConfigManager,
mWifiConfigStore));
- mTwtManager = new TwtManager(this, mCmiMonitor, mWifiNative, wifiHandler, mClock,
+ mTwtManager = new TwtManager(this, mCmiMonitor, mWifiNative, mWifiHandler, mClock,
WifiTwtSession.MAX_TWT_SESSIONS, 1);
mBackupRestoreController = new BackupRestoreController(mWifiSettingsBackupRestore, mClock);
if (mFeatureFlags.voipDetectionBugfix() && SdkLevel.isAtLeastV()) {
- mWifiVoipDetector = new WifiVoipDetector(mContext, wifiHandler, this,
+ mWifiVoipDetector = new WifiVoipDetector(mContext, mWifiHandler, this,
mWifiCarrierInfoManager);
} else {
mWifiVoipDetector = null;
}
mHasActiveModem = makeTelephonyManager().getActiveModemCount() > 0;
+ if (mFeatureFlags.wepDisabledInApm()) {
+ mWepNetworkUsageController = new WepNetworkUsageController(mWifiHandlerThread,
+ mWifiDeviceStateChangeManager, mSettingsConfigStore, mWifiGlobals,
+ mActiveModeWarden, mFeatureFlags);
+ } else {
+ mWepNetworkUsageController = null;
+ }
}
/**
@@ -653,6 +665,7 @@
*/
public void enableVerboseLogging(boolean verboseEnabled, boolean halVerboseEnabled) {
Log.i(TAG, "enableVerboseLogging " + verboseEnabled + " hal " + halVerboseEnabled);
+ mVerboseLoggingEnabled = verboseEnabled;
mWifiLastResortWatchdog.enableVerboseLogging(verboseEnabled);
mWifiBackupRestore.enableVerboseLogging(verboseEnabled);
mHalDeviceManager.enableVerboseLogging(verboseEnabled);
@@ -690,6 +703,7 @@
mExternalPnoScanRequestManager.enableVerboseLogging(verboseEnabled);
mMultiInternetWifiNetworkFactory.enableVerboseLogging(verboseEnabled);
mWifiRoamingModeManager.enableVerboseLogging(verboseEnabled);
+ mWifiHandler.enableVerboseLogging(verboseEnabled);
}
public UserManager getUserManager() {
@@ -1304,4 +1318,16 @@
public boolean hasActiveModem() {
return mHasActiveModem;
}
+
+ /**
+ * Check if verbose logging enabled
+ */
+ public boolean isVerboseLoggingEnabled() {
+ return mVerboseLoggingEnabled;
+ }
+
+ @Nullable
+ public WepNetworkUsageController getWepNetworkUsageController() {
+ return mWepNetworkUsageController;
+ }
}
diff --git a/service/java/com/android/server/wifi/WifiLinkLayerStats.java b/service/java/com/android/server/wifi/WifiLinkLayerStats.java
index 2db7c24..0276514 100644
--- a/service/java/com/android/server/wifi/WifiLinkLayerStats.java
+++ b/service/java/com/android/server/wifi/WifiLinkLayerStats.java
@@ -16,10 +16,13 @@
package com.android.server.wifi;
+import android.net.wifi.WifiManager;
import android.net.wifi.WifiUsabilityStatsEntry.LinkState;
+import android.net.wifi.WifiUsabilityStatsEntry.WifiChannelBandwidth;
import android.util.SparseArray;
import java.util.Arrays;
+import java.util.List;
/**
* A class representing link layer statistics collected over a Wifi Interface.
@@ -155,11 +158,29 @@
*/
public PeerInfo[] peerInfo;
+ public List<ScanResultWithSameFreq> scan_results_same_freq;
}
public LinkSpecificStats[] links;
/**
+ * Scan result who has the same frequency with WiFi Link
+ */
+ public static class ScanResultWithSameFreq {
+ /**
+ * timestamp in microseconds (since boot) when
+ * this result was last seen.
+ */
+ public long scan_result_timestamp_micros;
+ /** The detected signal level in dBm, also known as the RSSI */
+ public int rssi;
+ /** The center frequency of the primary 20 MHz frequency (in MHz) of the channel */
+ public int frequencyMhz;
+ /** BSSID of access point */
+ public String bssid;
+ }
+
+ /**
* The stats below which is already captured in WifiLinkLayerStats#LinkSpecificStats will be
* having an aggregated value. The aggregation logic is defined at
* wifiNative#setAggregatedLinkLayerStats().
@@ -303,6 +324,18 @@
*/
public int frequency;
/**
+ * Center frequency in MHz for first segment
+ */
+ public int frequencyFirstSegment;
+ /**
+ * Center frequency in MHz for second segment
+ */
+ public int frequencySecondSegment;
+ /**
+ * Channel Width as {@link WifiChannelBandwidth}
+ */
+ public @WifiChannelBandwidth int channelWidth;
+ /**
* Cumulative milliseconds radio is awake on this channel
*/
public int radioOnTimeMs;
@@ -454,6 +487,10 @@
* Channel stats list
*/
public final SparseArray<ChannelStats> channelStatsMap = new SparseArray<>();
+ /**
+ * Time for which the radio is in active tranmission per tx level
+ */
+ public int[] tx_time_in_ms_per_level;
}
/**
@@ -461,6 +498,8 @@
*/
public RadioStat[] radioStats;
+ public @WifiManager.MloMode int wifiMloMode;
+
@Override
public String toString() {
StringBuilder sbuf = new StringBuilder();
diff --git a/service/java/com/android/server/wifi/WifiLockManager.java b/service/java/com/android/server/wifi/WifiLockManager.java
index 8ba4759..80d4ee3 100644
--- a/service/java/com/android/server/wifi/WifiLockManager.java
+++ b/service/java/com/android/server/wifi/WifiLockManager.java
@@ -43,6 +43,7 @@
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.BitSet;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.concurrent.Executor;
@@ -849,13 +850,13 @@
return mLatencyModeSupport;
}
- long supportedFeatures =
+ BitSet supportedFeatures =
mActiveModeWarden.getPrimaryClientModeManager().getSupportedFeatures();
- if (supportedFeatures == 0L) {
+ if (supportedFeatures.isEmpty()) {
return LOW_LATENCY_SUPPORT_UNDEFINED;
}
- if ((supportedFeatures & WifiManager.WIFI_FEATURE_LOW_LATENCY) != 0) {
+ if (supportedFeatures.get(WifiManager.WIFI_FEATURE_LOW_LATENCY)) {
mLatencyModeSupport = LOW_LATENCY_SUPPORTED;
} else {
mLatencyModeSupport = LOW_LATENCY_NOT_SUPPORTED;
@@ -966,6 +967,7 @@
}
}
mWifiLowLatencyLockListeners.finishBroadcast();
+ mWifiMetrics.setLowLatencyState(mIsLowLatencyActivated);
}
private void notifyLowLatencyOwnershipChanged() {
diff --git a/service/java/com/android/server/wifi/WifiMetrics.java b/service/java/com/android/server/wifi/WifiMetrics.java
index 45c636e..1f9d54a 100644
--- a/service/java/com/android/server/wifi/WifiMetrics.java
+++ b/service/java/com/android/server/wifi/WifiMetrics.java
@@ -127,15 +127,19 @@
import com.android.server.wifi.proto.nano.WifiMetricsProto.LinkProbeStats.ExperimentProbeCounts;
import com.android.server.wifi.proto.nano.WifiMetricsProto.LinkProbeStats.LinkProbeFailureReasonCount;
import com.android.server.wifi.proto.nano.WifiMetricsProto.LinkSpeedCount;
+import com.android.server.wifi.proto.nano.WifiMetricsProto.LinkStats;
import com.android.server.wifi.proto.nano.WifiMetricsProto.MeteredNetworkStats;
import com.android.server.wifi.proto.nano.WifiMetricsProto.NetworkDisableReason;
import com.android.server.wifi.proto.nano.WifiMetricsProto.NetworkSelectionExperimentDecisions;
+import com.android.server.wifi.proto.nano.WifiMetricsProto.PacketStats;
import com.android.server.wifi.proto.nano.WifiMetricsProto.PasspointProfileTypeCount;
import com.android.server.wifi.proto.nano.WifiMetricsProto.PasspointProvisionStats;
import com.android.server.wifi.proto.nano.WifiMetricsProto.PasspointProvisionStats.ProvisionFailureCount;
+import com.android.server.wifi.proto.nano.WifiMetricsProto.PeerInfo;
import com.android.server.wifi.proto.nano.WifiMetricsProto.PnoScanMetrics;
import com.android.server.wifi.proto.nano.WifiMetricsProto.RadioStats;
import com.android.server.wifi.proto.nano.WifiMetricsProto.RateStats;
+import com.android.server.wifi.proto.nano.WifiMetricsProto.ScanResultWithSameFreq;
import com.android.server.wifi.proto.nano.WifiMetricsProto.SoftApConnectedClientsEvent;
import com.android.server.wifi.proto.nano.WifiMetricsProto.StaEvent;
import com.android.server.wifi.proto.nano.WifiMetricsProto.StaEvent.ConfigInfo;
@@ -152,8 +156,8 @@
import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiStatus;
import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiToWifiSwitchStats;
import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiToggleStats;
-import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiUsabilityStats;
-import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiUsabilityStatsEntry;
+import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiUsabilityStats; // This contains a time series of WifiUsabilityStatsEntry along with some metadata, such as the label of the time series or trigger type.
+import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiUsabilityStatsEntry; // This contains all the stats for a single point in time.
import com.android.server.wifi.rtt.RttMetrics;
import com.android.server.wifi.scanner.KnownBandsChannelHelper;
import com.android.server.wifi.util.InformationElementUtil;
@@ -239,12 +243,15 @@
// Minimum time wait before generating next WifiIsUnusableEvent from data stall
public static final int MIN_DATA_STALL_WAIT_MS = 120 * 1000; // 2 minutes
// Max number of WifiUsabilityStatsEntry elements to store in the ringbuffer.
- public static final int MAX_WIFI_USABILITY_STATS_ENTRIES_LIST_SIZE = 40;
- // Max number of WifiUsabilityStats elements to store for each type.
- public static final int MAX_WIFI_USABILITY_STATS_LIST_SIZE_PER_TYPE = 10;
+ public static final int MAX_WIFI_USABILITY_STATS_ENTRIES_RING_BUFFER_SIZE = 80;
+ // Max number of WifiUsabilityStats records to store for each type.
+ public static final int MAX_WIFI_USABILITY_STATS_RECORDS_PER_TYPE = 10;
// Max number of WifiUsabilityStats per labeled type to upload to server
- public static final int MAX_WIFI_USABILITY_STATS_PER_TYPE_TO_UPLOAD = 2;
+ public static final int MAX_WIFI_USABILITY_STATS_RECORDS_PER_TYPE_TO_UPLOAD = 2;
+ // One WifiGood WifiUsabilityStats record will be created each time we see this many
+ // WifiUsabilityStatsEntry time samples.
public static final int NUM_WIFI_USABILITY_STATS_ENTRIES_PER_WIFI_GOOD = 100;
+ // At most, one WifiGood WifiUsabilityStats record will be created during this time period.
public static final int MIN_WIFI_GOOD_USABILITY_STATS_PERIOD_MS = 1000 * 3600; // 1 hour
public static final int PASSPOINT_DEAUTH_IMMINENT_SCOPE_ESS = 0;
public static final int PASSPOINT_DEAUTH_IMMINENT_SCOPE_BSS = 1;
@@ -299,8 +306,8 @@
private SessionData mPreviousSession;
@VisibleForTesting
public SessionData mCurrentSession;
- private String mLastBssid;
- private int mLastFrequency = -1;
+ private Map<String, String> mLastBssidPerIfaceMap = new ArrayMap<>();
+ private Map<String, Integer> mLastFrequencyPerIfaceMap = new ArrayMap<>();
private int mSeqNumInsideFramework = 0;
private int mLastWifiUsabilityScore = -1;
private int mLastWifiUsabilityScoreNoReset = -1;
@@ -312,6 +319,7 @@
private int mProbeElapsedTimeSinceLastUpdateMs = -1;
private int mProbeMcsRateSinceLastUpdate = -1;
private long mScoreBreachLowTimeMillis = -1;
+ private int mAccumulatedLabelBadCount = 0;
public static final int MAX_STA_EVENTS = 768;
@VisibleForTesting static final int MAX_USER_ACTION_EVENTS = 200;
@@ -334,6 +342,13 @@
private int mScorerUid = Process.WIFI_UID;
@VisibleForTesting
int mUnusableEventType = WifiIsUnusableEvent.TYPE_UNKNOWN;
+ private int mWifiFrameworkState = 0;
+ private SpeedSufficient mSpeedSufficientNetworkCapabilities = new SpeedSufficient();
+ private SpeedSufficient mSpeedSufficientThroughputPredictor = new SpeedSufficient();
+ private int mLastUwbState = -1;
+ private boolean mIsLowLatencyActivated = false;
+ private int mVoipMode = -1;
+ private int mLastThreadDeviceRole = -1;
/**
* Wi-Fi usability state per interface as predicted by the network scorer.
@@ -479,11 +494,20 @@
private int mLinkProbeStaEventCount = 0;
@VisibleForTesting static final int MAX_LINK_PROBE_STA_EVENTS = MAX_STA_EVENTS / 4;
- private final LinkedList<WifiUsabilityStatsEntry> mWifiUsabilityStatsEntriesList =
+ // Each WifiUsabilityStatsEntry contains the stats for one instant in time. This LinkedList
+ // is used as a ring buffer and contains the history of the most recent
+ // MAX_WIFI_USABILITY_STATS_ENTRIES_RING_BUFFER_SIZE WifiUsabilityStatsEntry values.
+ @VisibleForTesting
+ public final LinkedList<WifiUsabilityStatsEntry> mWifiUsabilityStatsEntriesRingBuffer =
new LinkedList<>();
+ // One WifiUsabilityStats contains a single time series of WifiUsabilityStatsEntry along with
+ // some metadata. These LinkedList's below contain sets of time series that are labeled as
+ // either 'good' or 'bad'.
private final LinkedList<WifiUsabilityStats> mWifiUsabilityStatsListBad = new LinkedList<>();
private final LinkedList<WifiUsabilityStats> mWifiUsabilityStatsListGood = new LinkedList<>();
- private int mWifiUsabilityStatsCounter = 0;
+ // Counts the number of WifiUsabilityStatsEntry's that we have seen so that we only create a
+ // WifiUsabilityStats every NUM_WIFI_USABILITY_STATS_ENTRIES_PER_WIFI_GOOD time samples.
+ private int mWifiUsabilityStatsEntryCounter = 0;
private final Random mRand = new Random();
private final RemoteCallbackList<IOnWifiUsabilityStatsListener> mOnWifiUsabilityListeners;
@@ -513,6 +537,7 @@
private final WifiMonitor mWifiMonitor;
private ActiveModeWarden mActiveModeWarden;
+ private WifiGlobals mWifiGlobals;
private final Map<String, ActiveModeManager.ClientRole> mIfaceToRoleMap = new ArrayMap<>();
/** WifiConfigStore read duration histogram. */
@@ -1660,7 +1685,8 @@
WifiP2pMetrics wifiP2pMetrics,
DppMetrics dppMetrics,
WifiMonitor wifiMonitor,
- WifiDeviceStateChangeManager wifiDeviceStateChangeManager) {
+ WifiDeviceStateChangeManager wifiDeviceStateChangeManager,
+ WifiGlobals wifiGlobals) {
mContext = context;
mFacade = facade;
mClock = clock;
@@ -1695,6 +1721,7 @@
handleScreenStateChanged(screenOn);
}
});
+ mWifiGlobals = wifiGlobals;
}
/** Sets internal ScoringParams member */
@@ -4397,8 +4424,8 @@
public void logFirmwareAlert(String ifaceName, int errorCode) {
incrementAlertReasonCount(errorCode);
logWifiIsUnusableEvent(ifaceName, WifiIsUnusableEvent.TYPE_FIRMWARE_ALERT, errorCode);
- addToWifiUsabilityStatsList(ifaceName, WifiUsabilityStats.LABEL_BAD,
- WifiUsabilityStats.TYPE_FIRMWARE_ALERT, errorCode);
+ logAsynchronousEvent(ifaceName,
+ WifiUsabilityStatsEntry.CAPTURE_EVENT_TYPE_FIRMWARE_ALERT, errorCode);
}
public static final String PROTO_DUMP_ARG = "wifiMetricsProto";
@@ -4969,27 +4996,10 @@
}
pw.println("Hardware Version: " + SystemProperties.get("ro.boot.revision", ""));
- pw.println("mWifiUsabilityStatsEntriesList:");
- for (WifiUsabilityStatsEntry stats : mWifiUsabilityStatsEntriesList) {
+ pw.println("mWifiUsabilityStatsEntriesRingBuffer:");
+ for (WifiUsabilityStatsEntry stats : mWifiUsabilityStatsEntriesRingBuffer) {
printWifiUsabilityStatsEntry(pw, stats);
}
- pw.println("mWifiUsabilityStatsList:");
- for (WifiUsabilityStats stats : mWifiUsabilityStatsListGood) {
- pw.println("\nlabel=" + stats.label);
- pw.println("\ntrigger_type=" + stats.triggerType);
- pw.println("\ntime_stamp_ms=" + stats.timeStampMs);
- for (WifiUsabilityStatsEntry entry : stats.stats) {
- printWifiUsabilityStatsEntry(pw, entry);
- }
- }
- for (WifiUsabilityStats stats : mWifiUsabilityStatsListBad) {
- pw.println("\nlabel=" + stats.label);
- pw.println("\ntrigger_type=" + stats.triggerType);
- pw.println("\ntime_stamp_ms=" + stats.timeStampMs);
- for (WifiUsabilityStatsEntry entry : stats.stats) {
- printWifiUsabilityStatsEntry(pw, entry);
- }
- }
pw.println("mMobilityStatePnoStatsMap:");
for (int i = 0; i < mMobilityStatePnoStatsMap.size(); i++) {
@@ -5135,6 +5145,11 @@
line.append(",roam_scan_time_ms=" + radioStat.totalRoamScanTimeMs);
line.append(",pno_scan_time_ms=" + radioStat.totalPnoScanTimeMs);
line.append(",hotspot_2_scan_time_ms=" + radioStat.totalHotspot2ScanTimeMs);
+ if (radioStat.txTimeMsPerLevel != null && radioStat.txTimeMsPerLevel.length > 0) {
+ for (int i = 0; i < radioStat.txTimeMsPerLevel.length; ++i) {
+ line.append(",tx_time_ms_per_level=" + radioStat.txTimeMsPerLevel[i]);
+ }
+ }
}
}
line.append(",total_radio_on_time_ms=" + entry.totalRadioOnTimeMs);
@@ -5190,6 +5205,98 @@
line.append(",retries=" + rateStat.retries);
}
}
+ line.append(",wifi_link_count=" + entry.wifiLinkCount);
+ for (LinkStats linkStat : entry.linkStats) {
+ line.append(",Link Stats from link_id=" + linkStat.linkId);
+ line.append(",state=" + linkStat.state);
+ line.append(",radio_id=" + linkStat.radioId);
+ line.append(",frequency_mhz=" + linkStat.frequencyMhz);
+ line.append(",beacon_rx=" + linkStat.beaconRx);
+ line.append(",rssi_mgmt=" + linkStat.rssiMgmt);
+ line.append(",time_slice_duty_cycle_in_percent="
+ + linkStat.timeSliceDutyCycleInPercent);
+ line.append(",rssi=" + linkStat.rssi);
+ line.append(",channel_width=" + linkStat.channelWidth);
+ line.append(",center_freq_first_seg=" + linkStat.centerFreqFirstSeg);
+ line.append(",center_freq_second_seg=" + linkStat.centerFreqSecondSeg);
+ line.append(",on_time_in_ms=" + linkStat.onTimeInMs);
+ line.append(",cca_busy_time_in_ms=" + linkStat.ccaBusyTimeInMs);
+ if (linkStat.contentionTimeStats != null) {
+ for (ContentionTimeStats contentionTimeStat : linkStat.contentionTimeStats) {
+ line.append(",access_category=" + contentionTimeStat.accessCategory);
+ line.append(",contention_time_min_micros="
+ + contentionTimeStat.contentionTimeMinMicros);
+ line.append(",contention_time_max_micros="
+ + contentionTimeStat.contentionTimeMaxMicros);
+ line.append(",contention_time_avg_micros="
+ + contentionTimeStat.contentionTimeAvgMicros);
+ line.append(",contention_num_samples="
+ + contentionTimeStat.contentionNumSamples);
+ }
+ }
+ if (linkStat.packetStats != null) {
+ for (PacketStats packetStats : linkStat.packetStats) {
+ line.append(",access_category=" + packetStats.accessCategory);
+ line.append(",tx_success=" + packetStats.txSuccess);
+ line.append(",tx_retries=" + packetStats.txRetries);
+ line.append(",tx_bad=" + packetStats.txBad);
+ line.append(",rx_success=" + packetStats.rxSuccess);
+ }
+ }
+ if (linkStat.peerInfo != null) {
+ for (PeerInfo peerInfo : linkStat.peerInfo) {
+ line.append(",sta_count=" + peerInfo.staCount);
+ line.append(",chan_util=" + peerInfo.chanUtil);
+ if (peerInfo.rateStats != null) {
+ for (RateStats rateStat : peerInfo.rateStats) {
+ line.append(",preamble=" + rateStat.preamble);
+ line.append(",nss=" + rateStat.nss);
+ line.append(",bw=" + rateStat.bw);
+ line.append(",rate_mcs_idx=" + rateStat.rateMcsIdx);
+ line.append(",bit_rate_in_kbps=" + rateStat.bitRateInKbps);
+ line.append(",tx_mpdu=" + rateStat.txMpdu);
+ line.append(",rx_mpdu=" + rateStat.rxMpdu);
+ line.append(",mpdu_lost=" + rateStat.mpduLost);
+ line.append(",retries=" + rateStat.retries);
+ }
+ }
+ }
+ }
+ if (linkStat.scanResultWithSameFreq != null) {
+ for (ScanResultWithSameFreq scanResultWithSameFreq
+ : linkStat.scanResultWithSameFreq) {
+ line.append(",scan_result_timestamp_micros="
+ + scanResultWithSameFreq.scanResultTimestampMicros);
+ line.append(",rssi=" + scanResultWithSameFreq.rssi);
+ line.append(",frequencyMhz=" + scanResultWithSameFreq.frequencyMhz);
+ }
+ }
+ line.append(",tx_linkspeed=" + linkStat.txLinkspeed);
+ line.append(",rx_linkspeed=" + linkStat.rxLinkspeed);
+ }
+ line.append(",mlo_mode=" + entry.mloMode);
+ line.append(",tx_transmitted_bytes=" + entry.txTransmittedBytes);
+ line.append(",rx_transmitted_bytes=" + entry.rxTransmittedBytes);
+ line.append(",label_bad_event_count=" + entry.labelBadEventCount);
+ line.append(",wifi_framework_state=" + entry.wifiFrameworkState);
+ line.append(",is_network_capabilities_downstream_sufficient="
+ + entry.isNetworkCapabilitiesDownstreamSufficient);
+ line.append(",is_network_capabilities_upstream_sufficient="
+ + entry.isNetworkCapabilitiesUpstreamSufficient);
+ line.append(",is_throughput_predictor_downstream_sufficient="
+ + entry.isThroughputPredictorDownstreamSufficient);
+ line.append(",is_throughput_predictor_upstream_sufficient="
+ + entry.isThroughputPredictorUpstreamSufficient);
+ line.append(",is_bluetooth_connected=" + entry.isBluetoothConnected);
+ line.append(",uwb_adapter_state=" + entry.uwbAdapterState);
+ line.append(",is_low_latency_activated=" + entry.isLowLatencyActivated);
+ line.append(",max_supported_tx_linkspeed=" + entry.maxSupportedTxLinkspeed);
+ line.append(",max_supported_rx_linkspeed=" + entry.maxSupportedRxLinkspeed);
+ line.append(",voip_mode=" + entry.voipMode);
+ line.append(",thread_device_role=" + entry.threadDeviceRole);
+ line.append(",capture_event_type=" + entry.captureEventType);
+ line.append(",capture_event_type_subcode=" + entry.captureEventTypeSubcode);
+ line.append(",status_data_stall=" + entry.statusDataStall);
pw.println(line.toString());
}
@@ -5661,23 +5768,6 @@
}
mWifiLogProto.hardwareRevision = SystemProperties.get("ro.boot.revision", "");
- // Postprocessing on WifiUsabilityStats to upload an equal number of LABEL_GOOD and
- // LABEL_BAD WifiUsabilityStats
- final int numUsabilityStats = Math.min(
- Math.min(mWifiUsabilityStatsListBad.size(),
- mWifiUsabilityStatsListGood.size()),
- MAX_WIFI_USABILITY_STATS_PER_TYPE_TO_UPLOAD);
- LinkedList<WifiUsabilityStats> usabilityStatsGoodCopy =
- new LinkedList<>(mWifiUsabilityStatsListGood);
- LinkedList<WifiUsabilityStats> usabilityStatsBadCopy =
- new LinkedList<>(mWifiUsabilityStatsListBad);
- mWifiLogProto.wifiUsabilityStatsList = new WifiUsabilityStats[numUsabilityStats * 2];
- for (int i = 0; i < numUsabilityStats; i++) {
- mWifiLogProto.wifiUsabilityStatsList[2 * i] = usabilityStatsGoodCopy.remove(
- mRand.nextInt(usabilityStatsGoodCopy.size()));
- mWifiLogProto.wifiUsabilityStatsList[2 * i + 1] = usabilityStatsBadCopy.remove(
- mRand.nextInt(usabilityStatsBadCopy.size()));
- }
mWifiLogProto.mobilityStatePnoStatsList =
new DeviceMobilityStatePnoScanStats[mMobilityStatePnoStatsMap.size()];
for (int i = 0; i < mMobilityStatePnoStatsMap.size(); i++) {
@@ -6015,13 +6105,13 @@
mInstalledPasspointProfileTypeForR2.clear();
mWifiUsabilityStatsListGood.clear();
mWifiUsabilityStatsListBad.clear();
- mWifiUsabilityStatsEntriesList.clear();
+ mWifiUsabilityStatsEntriesRingBuffer.clear();
mMobilityStatePnoStatsMap.clear();
mWifiP2pMetrics.clear();
mDppMetrics.clear();
- mWifiUsabilityStatsCounter = 0;
- mLastBssid = null;
- mLastFrequency = -1;
+ mWifiUsabilityStatsEntryCounter = 0;
+ mLastBssidPerIfaceMap.clear();
+ mLastFrequencyPerIfaceMap.clear();
mSeqNumInsideFramework = 0;
mLastWifiUsabilityScore = -1;
mLastWifiUsabilityScoreNoReset = -1;
@@ -6033,6 +6123,7 @@
mProbeElapsedTimeSinceLastUpdateMs = -1;
mProbeMcsRateSinceLastUpdate = -1;
mScoreBreachLowTimeMillis = -1;
+ mAccumulatedLabelBadCount = 0;
mMeteredNetworkStatsBuilder.clear();
mWifiConfigStoreReadDurationHistogram.clear();
mWifiConfigStoreWriteDurationHistogram.clear();
@@ -6621,6 +6712,16 @@
return "DISCONNECT_VCN_REQUEST";
case StaEvent.DISCONNECT_UNKNOWN_NETWORK:
return "DISCONNECT_UNKNOWN_NETWORK";
+ case StaEvent.DISCONNECT_NETWORK_UNTRUSTED:
+ return "DISCONNECT_NETWORK_UNTRUSTED";
+ case StaEvent.DISCONNECT_NETWORK_WIFI7_TOGGLED:
+ return "DISCONNECT_NETWORK_WIFI7_TOGGLED";
+ case StaEvent.DISCONNECT_IP_CONFIGURATION_LOST:
+ return "DISCONNECT_IP_CONFIGURATION_LOST";
+ case StaEvent.DISCONNECT_IP_REACHABILITY_LOST:
+ return "DISCONNECT_IP_REACHABILITY_LOST";
+ case StaEvent.DISCONNECT_NO_CREDENTIALS:
+ return "DISCONNECT_NO_CREDENTIALS";
default:
return "DISCONNECT_UNKNOWN=" + frameworkDisconnectReason;
}
@@ -7048,14 +7149,35 @@
}
/**
+ * If isFullCapture is true, capture everything in ring buffer
+ *
+ * If isFullCapture is false, extract WifiUsabilityStatsEntries from ring buffer whose
+ * timestamps are within [triggerStartTimeMillis, triggerStopTimeMillis) and store them as
+ * upload candidates.
+ *
+ * @param triggerType data capture trigger type
+ * @param isFullCapture if we do full capture on ring buffer or not
+ * @param triggerStartTimeMillis data capture start timestamp, elapsed time since boot
+ * @param triggerStopTimeMillis data capture stop timestamp, elapsed time since boot
+ * @return error code, 0 is success
+ */
+ public int storeCapturedData(int triggerType, boolean isFullCapture,
+ long triggerStartTimeMillis, long triggerStopTimeMillis) {
+ // TODO: Implement how to extract WifiUsabilityStatsEntries from ring buffer whose
+ // timestamps are within [triggerStartTimeMillis, triggerStopTimeMillis]
+ Log.d(TAG, "storeCapturedData: triggerType=" + triggerType
+ + ", isFullCapture=" + isFullCapture);
+ return 0;
+ }
+
+ /**
* Extract data from |info| and |stats| to build a WifiUsabilityStatsEntry and then adds it
* into an internal ring buffer.
- * @param info
- * @param stats
- * @param ifaceName
+ *
+ * oneshot is used to indicate that this call came from CMD_ONESHOT_RSSI_POLL.
*/
public void updateWifiUsabilityStatsEntries(String ifaceName, WifiInfo info,
- WifiLinkLayerStats stats) {
+ WifiLinkLayerStats stats, boolean oneshot, int statusDataStall) {
// This is only collected for primary STA currently because RSSI polling is disabled for
// non-primary STAs.
synchronized (mLock) {
@@ -7072,9 +7194,213 @@
stats.rxmpdu_be = info.rxSuccess;
}
WifiUsabilityStatsEntry wifiUsabilityStatsEntry =
- mWifiUsabilityStatsEntriesList.size()
- < MAX_WIFI_USABILITY_STATS_ENTRIES_LIST_SIZE
- ? new WifiUsabilityStatsEntry() : mWifiUsabilityStatsEntriesList.remove();
+ mWifiUsabilityStatsEntriesRingBuffer.size()
+ < MAX_WIFI_USABILITY_STATS_ENTRIES_RING_BUFFER_SIZE
+ ? new WifiUsabilityStatsEntry() : mWifiUsabilityStatsEntriesRingBuffer.remove()
+ .clear();
+ if (isWiFiScorerNewStatsCollected()) {
+ SparseArray<MloLink> mloLinks = new SparseArray<>();
+ for (MloLink link: info.getAffiliatedMloLinks()) {
+ mloLinks.put(link.getLinkId(), link);
+ }
+ if (stats.links != null && stats.links.length > 0) {
+ int numLinks = stats.links.length;
+ wifiUsabilityStatsEntry.wifiLinkCount = numLinks;
+ wifiUsabilityStatsEntry.linkStats = new LinkStats[numLinks];
+ for (int i = 0; i < numLinks; ++i) {
+ LinkStats linkStats = new LinkStats();
+ WifiLinkLayerStats.LinkSpecificStats link = stats.links[i];
+ linkStats.linkId = link.link_id;
+ linkStats.state = link.state;
+ linkStats.radioId = link.radio_id;
+ linkStats.frequencyMhz = link.frequencyMhz;
+ linkStats.beaconRx = link.beacon_rx;
+ linkStats.rssiMgmt = link.rssi_mgmt;
+ linkStats.timeSliceDutyCycleInPercent = link.timeSliceDutyCycleInPercent;
+ linkStats.rssi = (mloLinks.size() > 0) ? mloLinks.get(link.link_id,
+ new MloLink()).getRssi() : info.getRssi();
+ linkStats.txLinkspeed = (mloLinks.size() > 0) ? mloLinks.get(link.link_id,
+ new MloLink()).getTxLinkSpeedMbps() : info.getTxLinkSpeedMbps();
+ linkStats.rxLinkspeed = (mloLinks.size() > 0) ? mloLinks.get(link.link_id,
+ new MloLink()).getRxLinkSpeedMbps() : info.getRxLinkSpeedMbps();
+ WifiLinkLayerStats.ChannelStats channlStatsEntryOnFreq =
+ stats.channelStatsMap.get(link.frequencyMhz);
+ if (channlStatsEntryOnFreq != null) {
+ linkStats.channelWidth = channlStatsEntryOnFreq.channelWidth;
+ linkStats.centerFreqFirstSeg =
+ channlStatsEntryOnFreq.frequencyFirstSegment;
+ linkStats.centerFreqSecondSeg =
+ channlStatsEntryOnFreq.frequencySecondSegment;
+ linkStats.onTimeInMs = channlStatsEntryOnFreq.radioOnTimeMs;
+ linkStats.ccaBusyTimeInMs = channlStatsEntryOnFreq.ccaBusyTimeMs;
+ }
+ linkStats.contentionTimeStats =
+ new ContentionTimeStats[NUM_WME_ACCESS_CATEGORIES];
+ linkStats.packetStats = new PacketStats[NUM_WME_ACCESS_CATEGORIES];
+ for (int ac = 0; ac < NUM_WME_ACCESS_CATEGORIES; ac++) {
+ ContentionTimeStats contentionTimeStats = new ContentionTimeStats();
+ PacketStats packetStats = new PacketStats();
+ switch (ac) {
+ case ContentionTimeStats.WME_ACCESS_CATEGORY_BE:
+ contentionTimeStats.accessCategory =
+ ContentionTimeStats.WME_ACCESS_CATEGORY_BE;
+ contentionTimeStats.contentionTimeMinMicros =
+ stats.contentionTimeMinBeInUsec;
+ contentionTimeStats.contentionTimeMaxMicros =
+ stats.contentionTimeMaxBeInUsec;
+ contentionTimeStats.contentionTimeAvgMicros =
+ stats.contentionTimeAvgBeInUsec;
+ contentionTimeStats.contentionNumSamples =
+ stats.contentionNumSamplesBe;
+ packetStats.accessCategory =
+ ContentionTimeStats.WME_ACCESS_CATEGORY_BE;
+ packetStats.txSuccess = link.txmpdu_be;
+ packetStats.txRetries = link.retries_be;
+ packetStats.txBad = link.lostmpdu_be;
+ packetStats.rxSuccess = link.rxmpdu_be;
+ break;
+ case ContentionTimeStats.WME_ACCESS_CATEGORY_BK:
+ contentionTimeStats.accessCategory =
+ ContentionTimeStats.WME_ACCESS_CATEGORY_BK;
+ contentionTimeStats.contentionTimeMinMicros =
+ stats.contentionTimeMinBkInUsec;
+ contentionTimeStats.contentionTimeMaxMicros =
+ stats.contentionTimeMaxBkInUsec;
+ contentionTimeStats.contentionTimeAvgMicros =
+ stats.contentionTimeAvgBkInUsec;
+ contentionTimeStats.contentionNumSamples =
+ stats.contentionNumSamplesBk;
+ packetStats.accessCategory =
+ ContentionTimeStats.WME_ACCESS_CATEGORY_BK;
+ packetStats.txSuccess = link.txmpdu_bk;
+ packetStats.txRetries = link.retries_bk;
+ packetStats.txBad = link.lostmpdu_bk;
+ packetStats.rxSuccess = link.rxmpdu_bk;
+ break;
+ case ContentionTimeStats.WME_ACCESS_CATEGORY_VI:
+ contentionTimeStats.accessCategory =
+ ContentionTimeStats.WME_ACCESS_CATEGORY_VI;
+ contentionTimeStats.contentionTimeMinMicros =
+ stats.contentionTimeMinViInUsec;
+ contentionTimeStats.contentionTimeMaxMicros =
+ stats.contentionTimeMaxViInUsec;
+ contentionTimeStats.contentionTimeAvgMicros =
+ stats.contentionTimeAvgViInUsec;
+ contentionTimeStats.contentionNumSamples =
+ stats.contentionNumSamplesVi;
+ packetStats.accessCategory =
+ ContentionTimeStats.WME_ACCESS_CATEGORY_VI;
+ packetStats.txSuccess = link.txmpdu_vi;
+ packetStats.txRetries = link.retries_vi;
+ packetStats.txBad = link.lostmpdu_vi;
+ packetStats.rxSuccess = link.rxmpdu_vi;
+ break;
+ case ContentionTimeStats.WME_ACCESS_CATEGORY_VO:
+ contentionTimeStats.accessCategory =
+ ContentionTimeStats.WME_ACCESS_CATEGORY_VO;
+ contentionTimeStats.contentionTimeMinMicros =
+ stats.contentionTimeMinVoInUsec;
+ contentionTimeStats.contentionTimeMaxMicros =
+ stats.contentionTimeMaxVoInUsec;
+ contentionTimeStats.contentionTimeAvgMicros =
+ stats.contentionTimeAvgVoInUsec;
+ contentionTimeStats.contentionNumSamples =
+ stats.contentionNumSamplesVo;
+ packetStats.accessCategory =
+ ContentionTimeStats.WME_ACCESS_CATEGORY_VO;
+ packetStats.txSuccess = link.txmpdu_vo;
+ packetStats.txRetries = link.retries_vo;
+ packetStats.txBad = link.lostmpdu_vo;
+ packetStats.rxSuccess = link.rxmpdu_vo;
+ break;
+ default:
+ Log.e(TAG, "Unknown WME Access Category: " + ac);
+ }
+ linkStats.contentionTimeStats[ac] = contentionTimeStats;
+ linkStats.packetStats[ac] = packetStats;
+ }
+ if (link.peerInfo != null && link.peerInfo.length > 0) {
+ int numPeers = link.peerInfo.length;
+ linkStats.peerInfo = new PeerInfo[numPeers];
+ for (int peerIndex = 0; peerIndex < numPeers; ++peerIndex) {
+ PeerInfo peerInfo = new PeerInfo();
+ WifiLinkLayerStats.PeerInfo curPeer = link.peerInfo[peerIndex];
+ peerInfo.staCount = curPeer.staCount;
+ peerInfo.chanUtil = curPeer.chanUtil;
+ if (curPeer.rateStats != null && curPeer.rateStats.length > 0) {
+ int numRates = curPeer.rateStats.length;
+ peerInfo.rateStats = new RateStats[numRates];
+ for (int rateIndex = 0; rateIndex < numRates; rateIndex++) {
+ RateStats rateStats = new RateStats();
+ WifiLinkLayerStats.RateStat curRate =
+ curPeer.rateStats[rateIndex];
+ rateStats.preamble = curRate.preamble;
+ rateStats.nss = curRate.nss;
+ rateStats.bw = curRate.bw;
+ rateStats.rateMcsIdx = curRate.rateMcsIdx;
+ rateStats.bitRateInKbps = curRate.bitRateInKbps;
+ rateStats.txMpdu = curRate.txMpdu;
+ rateStats.rxMpdu = curRate.rxMpdu;
+ rateStats.mpduLost = curRate.mpduLost;
+ rateStats.retries = curRate.retries;
+ peerInfo.rateStats[rateIndex] = rateStats;
+ }
+ }
+ linkStats.peerInfo[peerIndex] = peerInfo;
+ }
+ }
+ List<ScanResultWithSameFreq> scanResultsWithSameFreq = new ArrayList<>();
+ if (link.scan_results_same_freq != null
+ && link.scan_results_same_freq.size() > 0) {
+ for (int scanResultsIndex = 0; scanResultsIndex
+ < link.scan_results_same_freq.size(); ++scanResultsIndex) {
+ WifiLinkLayerStats.ScanResultWithSameFreq linkLayerScanResult =
+ link.scan_results_same_freq.get(scanResultsIndex);
+ if (linkLayerScanResult != null) {
+ String wifiLinkBssid = (mloLinks.size() > 0)
+ ? mloLinks.get(link.link_id, new MloLink())
+ .getApMacAddress().toString() : info.getBSSID();
+ if (!linkLayerScanResult.bssid.equals(wifiLinkBssid)) {
+ ScanResultWithSameFreq scanResultWithSameFreq =
+ new ScanResultWithSameFreq();
+ scanResultWithSameFreq.scanResultTimestampMicros =
+ linkLayerScanResult.scan_result_timestamp_micros;
+ scanResultWithSameFreq.rssi = linkLayerScanResult.rssi;
+ scanResultWithSameFreq.frequencyMhz =
+ linkLayerScanResult.frequencyMhz;
+ scanResultsWithSameFreq.add(scanResultWithSameFreq);
+ }
+ }
+ }
+ }
+ linkStats.scanResultWithSameFreq =
+ scanResultsWithSameFreq.toArray(new ScanResultWithSameFreq[0]);
+ wifiUsabilityStatsEntry.linkStats[i] = linkStats;
+ }
+ }
+ wifiUsabilityStatsEntry.mloMode = stats.wifiMloMode;
+ wifiUsabilityStatsEntry.labelBadEventCount = mAccumulatedLabelBadCount;
+ wifiUsabilityStatsEntry.wifiFrameworkState = mWifiFrameworkState;
+ wifiUsabilityStatsEntry.isNetworkCapabilitiesDownstreamSufficient =
+ mSpeedSufficientNetworkCapabilities.Downstream;
+ wifiUsabilityStatsEntry.isNetworkCapabilitiesUpstreamSufficient =
+ mSpeedSufficientNetworkCapabilities.Upstream;
+ wifiUsabilityStatsEntry.isThroughputPredictorDownstreamSufficient =
+ mSpeedSufficientThroughputPredictor.Downstream;
+ wifiUsabilityStatsEntry.isThroughputPredictorUpstreamSufficient =
+ mSpeedSufficientThroughputPredictor.Upstream;
+ wifiUsabilityStatsEntry.isBluetoothConnected =
+ mWifiGlobals.isBluetoothConnected();
+ wifiUsabilityStatsEntry.uwbAdapterState = getLastUwbState();
+ wifiUsabilityStatsEntry.isLowLatencyActivated = getLowLatencyState();
+ wifiUsabilityStatsEntry.maxSupportedTxLinkspeed =
+ info.getMaxSupportedTxLinkSpeedMbps();
+ wifiUsabilityStatsEntry.maxSupportedRxLinkspeed =
+ info.getMaxSupportedRxLinkSpeedMbps();
+ wifiUsabilityStatsEntry.voipMode = getVoipMode();
+ wifiUsabilityStatsEntry.threadDeviceRole = getLastThreadDeviceRole();
+ }
+
wifiUsabilityStatsEntry.timeStampMs = stats.timeStampInMs;
wifiUsabilityStatsEntry.totalTxSuccess = stats.txmpdu_be + stats.txmpdu_bk
+ stats.txmpdu_vi + stats.txmpdu_vo;
@@ -7102,6 +7428,19 @@
radioStats.totalRoamScanTimeMs = radio.on_time_roam_scan;
radioStats.totalPnoScanTimeMs = radio.on_time_pno_scan;
radioStats.totalHotspot2ScanTimeMs = radio.on_time_hs20_scan;
+ if (isWiFiScorerNewStatsCollected()) {
+ if (radio.tx_time_in_ms_per_level != null
+ && radio.tx_time_in_ms_per_level.length > 0) {
+ int txTimePerLevelLength = radio.tx_time_in_ms_per_level.length;
+ radioStats.txTimeMsPerLevel = new int[txTimePerLevelLength];
+ for (int txTimePerLevelIndex = 0;
+ txTimePerLevelIndex < txTimePerLevelLength;
+ ++txTimePerLevelIndex) {
+ radioStats.txTimeMsPerLevel[txTimePerLevelIndex] =
+ radio.tx_time_in_ms_per_level[txTimePerLevelIndex];
+ }
+ }
+ }
wifiUsabilityStatsEntry.radioStats[i] = radioStats;
}
}
@@ -7126,11 +7465,12 @@
mLastTotalBeaconRx = stats.beacon_rx;
wifiUsabilityStatsEntry.timeSliceDutyCycleInPercent = stats.timeSliceDutyCycleInPercent;
- boolean isSameBssidAndFreq = mLastBssid == null || mLastFrequency == -1
- || (mLastBssid.equals(info.getBSSID())
- && mLastFrequency == info.getFrequency());
- mLastBssid = info.getBSSID();
- mLastFrequency = info.getFrequency();
+ String lastBssid = mLastBssidPerIfaceMap.get(ifaceName);
+ int lastFrequency = mLastFrequencyPerIfaceMap.getOrDefault(ifaceName, -1);
+ boolean isSameBssidAndFreq = lastBssid == null || lastFrequency == -1
+ || (lastBssid.equals(info.getBSSID()) && lastFrequency == info.getFrequency());
+ mLastBssidPerIfaceMap.put(ifaceName, info.getBSSID());
+ mLastFrequencyPerIfaceMap.put(ifaceName, info.getFrequency());
wifiUsabilityStatsEntry.wifiScore = mLastScoreNoReset;
wifiUsabilityStatsEntry.wifiUsabilityScore = mLastWifiUsabilityScoreNoReset;
wifiUsabilityStatsEntry.seqNumToFramework = mSeqNumToFramework;
@@ -7220,13 +7560,20 @@
}
if (mWifiChannelUtilization != null) {
wifiUsabilityStatsEntry.channelUtilizationRatio =
- mWifiChannelUtilization.getUtilizationRatio(mLastFrequency);
+ mWifiChannelUtilization.getUtilizationRatio(lastFrequency);
}
if (mWifiDataStall != null) {
wifiUsabilityStatsEntry.isThroughputSufficient =
mWifiDataStall.isThroughputSufficient();
wifiUsabilityStatsEntry.isCellularDataAvailable =
mWifiDataStall.isCellularDataAvailable();
+ if (isWiFiScorerNewStatsCollected()) {
+ wifiUsabilityStatsEntry.txTransmittedBytes =
+ mWifiDataStall.getTxTransmittedBytes();
+ wifiUsabilityStatsEntry.rxTransmittedBytes =
+ mWifiDataStall.getRxTransmittedBytes();
+ wifiUsabilityStatsEntry.statusDataStall = statusDataStall;
+ }
}
if (mWifiSettingsStore != null) {
wifiUsabilityStatsEntry.isWifiScoringEnabled =
@@ -7256,21 +7603,16 @@
wifiUsabilityStatsEntry.rateStats[i] = rate;
}
}
+ wifiUsabilityStatsEntry.captureEventType = oneshot
+ ? WifiUsabilityStatsEntry.CAPTURE_EVENT_TYPE_ONESHOT_RSSI_POLL
+ : WifiUsabilityStatsEntry.CAPTURE_EVENT_TYPE_SYNCHRONOUS;
- mWifiUsabilityStatsEntriesList.add(wifiUsabilityStatsEntry);
- mWifiUsabilityStatsCounter++;
- if (mWifiUsabilityStatsCounter >= NUM_WIFI_USABILITY_STATS_ENTRIES_PER_WIFI_GOOD) {
- addToWifiUsabilityStatsList(ifaceName, WifiUsabilityStats.LABEL_GOOD,
- WifiUsabilityStats.TYPE_UNKNOWN, -1);
- }
+ mWifiUsabilityStatsEntriesRingBuffer.add(wifiUsabilityStatsEntry);
+ mWifiUsabilityStatsEntryCounter++;
if (mScoreBreachLowTimeMillis != -1) {
long elapsedTime = mClock.getElapsedSinceBootMillis() - mScoreBreachLowTimeMillis;
if (elapsedTime >= MIN_SCORE_BREACH_TO_GOOD_STATS_WAIT_TIME_MS) {
mScoreBreachLowTimeMillis = -1;
- if (elapsedTime <= VALIDITY_PERIOD_OF_SCORE_BREACH_LOW_MS) {
- addToWifiUsabilityStatsList(ifaceName, WifiUsabilityStats.LABEL_GOOD,
- WifiUsabilityStats.TYPE_UNKNOWN, -1);
- }
}
}
@@ -7365,6 +7707,60 @@
return contentionTimeStatsArray;
}
+ private android.net.wifi.WifiUsabilityStatsEntry.PacketStats[]
+ convertPacketStats(WifiLinkLayerStats.LinkSpecificStats stats) {
+ android.net.wifi.WifiUsabilityStatsEntry.PacketStats[] packetStatsArray =
+ new android.net.wifi.WifiUsabilityStatsEntry.PacketStats[
+ android.net.wifi.WifiUsabilityStatsEntry.NUM_WME_ACCESS_CATEGORIES];
+ for (int ac = 0; ac < android.net.wifi.WifiUsabilityStatsEntry.NUM_WME_ACCESS_CATEGORIES;
+ ac++) {
+ android.net.wifi.WifiUsabilityStatsEntry.PacketStats packetStats = null;
+ switch (ac) {
+ case android.net.wifi.WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_BE:
+ packetStats =
+ new android.net.wifi.WifiUsabilityStatsEntry.PacketStats(
+ stats.txmpdu_be,
+ stats.retries_be,
+ stats.lostmpdu_be,
+ stats.rxmpdu_be
+ );
+ break;
+ case android.net.wifi.WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_BK:
+ packetStats =
+ new android.net.wifi.WifiUsabilityStatsEntry.PacketStats(
+ stats.txmpdu_bk,
+ stats.retries_bk,
+ stats.lostmpdu_bk,
+ stats.rxmpdu_bk
+ );
+ break;
+ case android.net.wifi.WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_VO:
+ packetStats =
+ new android.net.wifi.WifiUsabilityStatsEntry.PacketStats(
+ stats.txmpdu_vo,
+ stats.retries_vo,
+ stats.lostmpdu_vo,
+ stats.rxmpdu_vo
+ );
+ break;
+ case android.net.wifi.WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_VI:
+ packetStats =
+ new android.net.wifi.WifiUsabilityStatsEntry.PacketStats(
+ stats.txmpdu_vi,
+ stats.retries_vi,
+ stats.lostmpdu_vi,
+ stats.rxmpdu_vi
+ );
+ break;
+ default:
+ Log.d(TAG, "Unknown WME Access Category: " + ac);
+ packetStats = null;
+ }
+ packetStatsArray[ac] = packetStats;
+ }
+ return packetStatsArray;
+ }
+
private android.net.wifi.WifiUsabilityStatsEntry.RateStats[] convertRateStats(
WifiLinkLayerStats.LinkSpecificStats stats) {
android.net.wifi.WifiUsabilityStatsEntry.RateStats[] rateStats = null;
@@ -7388,6 +7784,43 @@
return rateStats;
}
+ private android.net.wifi.WifiUsabilityStatsEntry.PeerInfo[] convertPeerInfo(
+ WifiLinkLayerStats.LinkSpecificStats stats) {
+ android.net.wifi.WifiUsabilityStatsEntry.PeerInfo[] peerInfos = null;
+ if (stats.peerInfo != null && stats.peerInfo.length > 0) {
+ int numPeers = stats.peerInfo.length;
+ peerInfos = new android.net.wifi.WifiUsabilityStatsEntry.PeerInfo[numPeers];
+ for (int i = 0; i < numPeers; i++) {
+ WifiLinkLayerStats.PeerInfo curPeer = stats.peerInfo[i];
+ android.net.wifi.WifiUsabilityStatsEntry.RateStats[] rateStats = null;
+ if (curPeer.rateStats != null && curPeer.rateStats.length > 0) {
+ int numRates = curPeer.rateStats.length;
+ rateStats = new android.net.wifi.WifiUsabilityStatsEntry.RateStats[numRates];
+ for (int rateIndex = 0; rateIndex < numRates; ++rateIndex) {
+ WifiLinkLayerStats.RateStat curRate = curPeer.rateStats[rateIndex];
+ rateStats[rateIndex] =
+ new android.net.wifi.WifiUsabilityStatsEntry.RateStats(
+ convertPreambleTypeEnumToUsabilityStatsType(
+ curRate.preamble),
+ convertSpatialStreamEnumToUsabilityStatsType(curRate.nss),
+ convertBandwidthEnumToUsabilityStatsType(curRate.bw),
+ curRate.rateMcsIdx,
+ curRate.bitRateInKbps,
+ curRate.txMpdu,
+ curRate.rxMpdu,
+ curRate.mpduLost,
+ curRate.retries);
+ }
+ }
+ android.net.wifi.WifiUsabilityStatsEntry.PeerInfo peerInfo =
+ new android.net.wifi.WifiUsabilityStatsEntry.PeerInfo(
+ curPeer.staCount, curPeer.chanUtil, rateStats);
+ peerInfos[i] = peerInfo;
+ }
+ }
+ return peerInfos;
+ }
+
private SparseArray<android.net.wifi.WifiUsabilityStatsEntry.LinkStats> convertLinkStats(
WifiLinkLayerStats stats, WifiInfo info) {
SparseArray<android.net.wifi.WifiUsabilityStatsEntry.LinkStats> linkStats =
@@ -7408,6 +7841,30 @@
mLastLinkMetrics.put(inStat.link_id, linkMetrics);
WifiLinkLayerStats.ChannelStats channelStatsMap = stats.channelStatsMap.get(
inStat.frequencyMhz);
+ List<android.net.wifi.WifiUsabilityStatsEntry.ScanResultWithSameFreq>
+ scanResultsWithSameFreq = new ArrayList<>();
+
+ if (inStat.scan_results_same_freq != null
+ && inStat.scan_results_same_freq.size() > 0) {
+ for (int scanResultsIndex = 0; scanResultsIndex
+ < inStat.scan_results_same_freq.size(); ++scanResultsIndex) {
+ WifiLinkLayerStats.ScanResultWithSameFreq linkLayerScanResult =
+ inStat.scan_results_same_freq.get(scanResultsIndex);
+ if (linkLayerScanResult != null) {
+ if (!linkLayerScanResult.bssid.equals(info.getBSSID())) {
+ android.net.wifi.WifiUsabilityStatsEntry.ScanResultWithSameFreq
+ scanResultWithSameFreq =
+ new android.net.wifi.WifiUsabilityStatsEntry
+ .ScanResultWithSameFreq(
+ linkLayerScanResult.scan_result_timestamp_micros,
+ linkLayerScanResult.rssi,
+ linkLayerScanResult.frequencyMhz
+ );
+ scanResultsWithSameFreq.add(scanResultWithSameFreq);
+ }
+ }
+ }
+ }
// Note: RSSI, Tx & Rx link speed are derived from signal poll stats which is updated in
// Mlolink or WifiInfo (non-MLO case).
android.net.wifi.WifiUsabilityStatsEntry.LinkStats outStat =
@@ -7415,6 +7872,10 @@
inStat.state, inStat.radio_id,
(mloLinks.size() > 0) ? mloLinks.get(inStat.link_id,
new MloLink()).getRssi() : info.getRssi(),
+ inStat.frequencyMhz, inStat.rssi_mgmt,
+ (channelStatsMap != null) ? channelStatsMap.channelWidth : 0,
+ (channelStatsMap != null) ? channelStatsMap.frequencyFirstSegment : 0,
+ (channelStatsMap != null) ? channelStatsMap.frequencySecondSegment : 0,
(mloLinks.size() > 0) ? mloLinks.get(inStat.link_id,
new MloLink()).getTxLinkSpeedMbps() : info.getTxLinkSpeedMbps(),
(mloLinks.size() > 0) ? mloLinks.get(inStat.link_id,
@@ -7430,14 +7891,23 @@
inStat.beacon_rx, inStat.timeSliceDutyCycleInPercent,
(channelStatsMap != null) ? channelStatsMap.ccaBusyTimeMs : 0 ,
(channelStatsMap != null) ? channelStatsMap.radioOnTimeMs : 0,
- convertContentionTimeStats(inStat),
- convertRateStats(inStat));
+ convertContentionTimeStats(inStat), convertRateStats(inStat),
+ convertPacketStats(inStat), convertPeerInfo(inStat),
+ scanResultsWithSameFreq.toArray(
+ new android.net.wifi.WifiUsabilityStatsEntry
+ .ScanResultWithSameFreq[0]));
linkStats.put(inStat.link_id, outStat);
}
return linkStats;
}
+ /**
+ * Converts from the WifiUsabilityStatsEntry proto used internally to the
+ * WifiUsabilityStatsEntry structure sent on the SDK API.
+ *
+ * These are two different types.
+ */
private android.net.wifi.WifiUsabilityStatsEntry createNewWifiUsabilityStatsEntryParcelable(
WifiUsabilityStatsEntry s, WifiLinkLayerStats stats, WifiInfo info) {
int probeStatus;
@@ -7479,7 +7949,14 @@
s.rxLinkSpeedMbps, s.timeSliceDutyCycleInPercent, contentionTimeStats, rateStats,
radioStats, s.channelUtilizationRatio, s.isThroughputSufficient,
s.isWifiScoringEnabled, s.isCellularDataAvailable, 0, 0, 0, false,
- convertLinkStats(stats, info)
+ convertLinkStats(stats, info), s.wifiLinkCount, s.mloMode,
+ s.txTransmittedBytes, s.rxTransmittedBytes, s.labelBadEventCount,
+ s.wifiFrameworkState, s.isNetworkCapabilitiesDownstreamSufficient,
+ s.isNetworkCapabilitiesUpstreamSufficient,
+ s.isThroughputPredictorDownstreamSufficient,
+ s.isThroughputPredictorUpstreamSufficient, s.isBluetoothConnected,
+ s.uwbAdapterState, s.isLowLatencyActivated, s.maxSupportedTxLinkspeed,
+ s.maxSupportedRxLinkspeed, s.voipMode, s.threadDeviceRole, s.statusDataStall
);
}
@@ -7611,6 +8088,14 @@
return;
}
for (int i = 0; i < stats.length; i++) {
+ int[] txTimeMsPerLevel = null;
+ if (stats[i].txTimeMsPerLevel != null && stats[i].txTimeMsPerLevel.length > 0) {
+ int txTimeMsPerLevelLength = stats[i].txTimeMsPerLevel.length;
+ txTimeMsPerLevel = new int[txTimeMsPerLevelLength];
+ for (int j = 0; j < txTimeMsPerLevelLength; ++j) {
+ txTimeMsPerLevel[j] = stats[i].txTimeMsPerLevel[j];
+ }
+ }
statsParcelable[i] =
new android.net.wifi.WifiUsabilityStatsEntry.RadioStats(
stats[i].radioId,
@@ -7622,7 +8107,8 @@
stats[i].totalBackgroundScanTimeMs,
stats[i].totalRoamScanTimeMs,
stats[i].totalPnoScanTimeMs,
- stats[i].totalHotspot2ScanTimeMs);
+ stats[i].totalHotspot2ScanTimeMs,
+ txTimeMsPerLevel);
}
}
@@ -7668,9 +8154,54 @@
out.staCount = s.staCount;
out.channelUtilization = s.channelUtilization;
out.radioStats = s.radioStats;
+ out.wifiLinkCount = s.wifiLinkCount;
+ out.linkStats = s.linkStats;
+ out.mloMode = s.mloMode;
+ out.txTransmittedBytes = s.txTransmittedBytes;
+ out.rxTransmittedBytes = s.rxTransmittedBytes;
+ out.labelBadEventCount = s.labelBadEventCount;
+ out.wifiFrameworkState = s.wifiFrameworkState;
+ out.isNetworkCapabilitiesDownstreamSufficient = s.isNetworkCapabilitiesDownstreamSufficient;
+ out.isNetworkCapabilitiesUpstreamSufficient = s.isNetworkCapabilitiesUpstreamSufficient;
+ out.isThroughputPredictorDownstreamSufficient = s.isThroughputPredictorDownstreamSufficient;
+ out.isThroughputPredictorUpstreamSufficient = s.isThroughputPredictorUpstreamSufficient;
+ out.isBluetoothConnected = s.isBluetoothConnected;
+ out.uwbAdapterState = s.uwbAdapterState;
+ out.isLowLatencyActivated = s.isLowLatencyActivated;
+ out.maxSupportedTxLinkspeed = s.maxSupportedTxLinkspeed;
+ out.maxSupportedRxLinkspeed = s.maxSupportedRxLinkspeed;
+ out.voipMode = s.voipMode;
+ out.threadDeviceRole = s.threadDeviceRole;
+ out.statusDataStall = s.statusDataStall;
return out;
}
+ /**
+ * Used to log an asynchronous event (such as WiFi disconnect) into the ring buffer.
+ */
+ public void logAsynchronousEvent(String ifaceName, int e, int c) {
+ if (!isPrimary(ifaceName)) {
+ return;
+ }
+ WifiUsabilityStatsEntry wifiUsabilityStatsEntry =
+ mWifiUsabilityStatsEntriesRingBuffer.size()
+ < MAX_WIFI_USABILITY_STATS_ENTRIES_RING_BUFFER_SIZE
+ ? new WifiUsabilityStatsEntry() : mWifiUsabilityStatsEntriesRingBuffer.remove()
+ .clear();
+ wifiUsabilityStatsEntry.timeStampMs = mClock.getElapsedSinceBootMillis();
+ wifiUsabilityStatsEntry.captureEventType = e;
+ wifiUsabilityStatsEntry.captureEventTypeSubcode = c;
+ mWifiUsabilityStatsEntriesRingBuffer.add(wifiUsabilityStatsEntry);
+ }
+ /**
+ * Used to log an asynchronous event (such as WiFi disconnect) into the ring buffer.
+ *
+ * Helper function when the subcode is not needed.
+ */
+ public void logAsynchronousEvent(String ifaceName, int e) {
+ logAsynchronousEvent(ifaceName, e, -1);
+ }
+
private WifiUsabilityStats createWifiUsabilityStatsWithLabel(int label, int triggerType,
int firmwareAlertCode) {
WifiUsabilityStats wifiUsabilityStats = new WifiUsabilityStats();
@@ -7679,16 +8210,18 @@
wifiUsabilityStats.firmwareAlertCode = firmwareAlertCode;
wifiUsabilityStats.timeStampMs = mClock.getElapsedSinceBootMillis();
wifiUsabilityStats.stats =
- new WifiUsabilityStatsEntry[mWifiUsabilityStatsEntriesList.size()];
- for (int i = 0; i < mWifiUsabilityStatsEntriesList.size(); i++) {
+ new WifiUsabilityStatsEntry[mWifiUsabilityStatsEntriesRingBuffer.size()];
+ for (int i = 0; i < mWifiUsabilityStatsEntriesRingBuffer.size(); i++) {
wifiUsabilityStats.stats[i] =
- createNewWifiUsabilityStatsEntry(mWifiUsabilityStatsEntriesList.get(i));
+ createNewWifiUsabilityStatsEntry(mWifiUsabilityStatsEntriesRingBuffer.get(i));
}
return wifiUsabilityStats;
}
/**
- * Label the current snapshot of WifiUsabilityStatsEntrys and save the labeled data in memory.
+ * Label the current snapshot of WifiUsabilityStatsEntriesRingBuffer and save the labeled data
+ * inside a WifiUsabilityStats ptoto.
+ *
* @param label WifiUsabilityStats.LABEL_GOOD or WifiUsabilityStats.LABEL_BAD
* @param triggerType what event triggers WifiUsabilityStats
* @param firmwareAlertCode the firmware alert code when the stats was triggered by a
@@ -7700,7 +8233,7 @@
if (!isPrimary(ifaceName)) {
return;
}
- if (mWifiUsabilityStatsEntriesList.isEmpty() || !mScreenOn) {
+ if (mWifiUsabilityStatsEntriesRingBuffer.isEmpty() || !mScreenOn) {
return;
}
if (label == WifiUsabilityStats.LABEL_GOOD) {
@@ -7710,9 +8243,9 @@
|| mWifiUsabilityStatsListGood.getLast().stats[mWifiUsabilityStatsListGood
.getLast().stats.length - 1].timeStampMs
+ MIN_WIFI_GOOD_USABILITY_STATS_PERIOD_MS
- < mWifiUsabilityStatsEntriesList.getLast().timeStampMs) {
+ < mWifiUsabilityStatsEntriesRingBuffer.getLast().timeStampMs) {
while (mWifiUsabilityStatsListGood.size()
- >= MAX_WIFI_USABILITY_STATS_LIST_SIZE_PER_TYPE) {
+ >= MAX_WIFI_USABILITY_STATS_RECORDS_PER_TYPE) {
mWifiUsabilityStatsListGood.remove(
mRand.nextInt(mWifiUsabilityStatsListGood.size()));
}
@@ -7728,9 +8261,9 @@
|| (mWifiUsabilityStatsListBad.getLast().stats[mWifiUsabilityStatsListBad
.getLast().stats.length - 1].timeStampMs
+ MIN_DATA_STALL_WAIT_MS
- < mWifiUsabilityStatsEntriesList.getLast().timeStampMs)) {
+ < mWifiUsabilityStatsEntriesRingBuffer.getLast().timeStampMs)) {
while (mWifiUsabilityStatsListBad.size()
- >= MAX_WIFI_USABILITY_STATS_LIST_SIZE_PER_TYPE) {
+ >= MAX_WIFI_USABILITY_STATS_RECORDS_PER_TYPE) {
mWifiUsabilityStatsListBad.remove(
mRand.nextInt(mWifiUsabilityStatsListBad.size()));
}
@@ -7738,9 +8271,10 @@
createWifiUsabilityStatsWithLabel(label, triggerType,
firmwareAlertCode));
}
+ mAccumulatedLabelBadCount++;
}
- mWifiUsabilityStatsCounter = 0;
- mWifiUsabilityStatsEntriesList.clear();
+ mWifiUsabilityStatsEntryCounter = 0;
+ mWifiUsabilityStatsEntriesRingBuffer.clear();
}
}
@@ -8996,6 +9530,18 @@
return speedSufficient;
}
+ public void updateWiFiEvaluationAndScorerStats(boolean lingering, WifiInfo wifiInfo,
+ ConnectionCapabilities connectionCapabilities) {
+ mWifiFrameworkState = getFrameworkStateForScorer(lingering);
+ Speeds speedsNetworkCapabilities = getNetworkCapabilitiesSpeeds();
+ mSpeedSufficientNetworkCapabilities =
+ calcSpeedSufficientNetworkCapabilities(speedsNetworkCapabilities);
+ WifiDataStall.Speeds speedsThroughputPredictor =
+ mWifiDataStall.getThrouhgputPredictorSpeeds(wifiInfo, connectionCapabilities);
+ mSpeedSufficientThroughputPredictor =
+ calcSpeedSufficientThroughputPredictor(speedsThroughputPredictor);
+ }
+
/**
* Log a ScorerPredictionResultReported atom.
*/
@@ -9004,10 +9550,7 @@
boolean isMobileDataEnabled,
int pollingIntervalMs,
int aospScorerPrediction,
- int externalScorerPrediction,
- boolean lingering,
- WifiInfo wifiInfo,
- ConnectionCapabilities connectionCapabilities
+ int externalScorerPrediction
) {
boolean isCellularDataAvailable = mWifiDataStall.isCellularDataAvailable();
boolean isThroughputSufficient = mWifiDataStall.isThroughputSufficient();
@@ -9016,14 +9559,6 @@
hasActiveSubInfo, isMobileDataEnabled, isCellularDataAvailable,
mAdaptiveConnectivityEnabled);
int scorerUnusableEvent = convertWifiUnusableTypeForScorer(mUnusableEventType);
- int wifiFrameworkState = getFrameworkStateForScorer(lingering);
- Speeds speedsNetworkCapabilities = getNetworkCapabilitiesSpeeds();
- SpeedSufficient speedSufficientNetworkCapabilities =
- calcSpeedSufficientNetworkCapabilities(speedsNetworkCapabilities);
- WifiDataStall.Speeds speedsThroughputPredictor = mWifiDataStall.getThrouhgputPredictorSpeeds(
- wifiInfo, connectionCapabilities);
- SpeedSufficient speedSufficientThroughputPredictor =
- calcSpeedSufficientThroughputPredictor(speedsThroughputPredictor);
WifiStatsLog.write_non_chained(SCORER_PREDICTION_RESULT_REPORTED,
Process.WIFI_UID,
@@ -9031,10 +9566,10 @@
aospScorerPrediction,
scorerUnusableEvent,
isThroughputSufficient, deviceState, pollingIntervalMs,
- wifiFrameworkState, speedSufficientNetworkCapabilities.Downstream,
- speedSufficientNetworkCapabilities.Upstream,
- speedSufficientThroughputPredictor.Downstream,
- speedSufficientThroughputPredictor.Upstream);
+ mWifiFrameworkState, mSpeedSufficientNetworkCapabilities.Downstream,
+ mSpeedSufficientNetworkCapabilities.Upstream,
+ mSpeedSufficientThroughputPredictor.Downstream,
+ mSpeedSufficientThroughputPredictor.Upstream);
if (mScorerUid != Process.WIFI_UID) {
WifiStatsLog.write_non_chained(SCORER_PREDICTION_RESULT_REPORTED,
mScorerUid,
@@ -9042,10 +9577,10 @@
externalScorerPrediction,
scorerUnusableEvent,
isThroughputSufficient, deviceState, pollingIntervalMs,
- wifiFrameworkState, speedSufficientNetworkCapabilities.Downstream,
- speedSufficientNetworkCapabilities.Upstream,
- speedSufficientThroughputPredictor.Downstream,
- speedSufficientThroughputPredictor.Upstream);
+ mWifiFrameworkState, mSpeedSufficientNetworkCapabilities.Downstream,
+ mSpeedSufficientNetworkCapabilities.Upstream,
+ mSpeedSufficientThroughputPredictor.Downstream,
+ mSpeedSufficientThroughputPredictor.Upstream);
}
// We'd better reset to TYPE_NONE if it is defined in the future.
@@ -9940,4 +10475,36 @@
WifiStatsLog.write(WifiStatsLog.SOFT_AP_STATE_CHANGED,
WifiStatsLog.SOFT_AP_STATE_CHANGED__HOTSPOT_ON__STATE_OFF);
}
+
+ public int getLastUwbState() {
+ return mLastUwbState;
+ }
+
+ public void setLastUwbState(int state) {
+ mLastUwbState = state;
+ }
+
+ public boolean getLowLatencyState() {
+ return mIsLowLatencyActivated;
+ }
+
+ public void setLowLatencyState(boolean state) {
+ mIsLowLatencyActivated = state;
+ }
+
+ public int getVoipMode() {
+ return mVoipMode;
+ }
+
+ public void setVoipMode(int mode) {
+ mVoipMode = mode;
+ }
+
+ public int getLastThreadDeviceRole() {
+ return mLastThreadDeviceRole;
+ }
+
+ public void setLastThreadDeviceRole(int deviceRole) {
+ mLastThreadDeviceRole = deviceRole;
+ }
}
diff --git a/service/java/com/android/server/wifi/WifiMulticastLockManager.java b/service/java/com/android/server/wifi/WifiMulticastLockManager.java
index 07de76a..fa40fd7 100644
--- a/service/java/com/android/server/wifi/WifiMulticastLockManager.java
+++ b/service/java/com/android/server/wifi/WifiMulticastLockManager.java
@@ -17,6 +17,8 @@
package com.android.server.wifi;
import android.annotation.Nullable;
+import android.app.ActivityManager;
+import android.content.Context;
import android.os.BatteryStatsManager;
import android.os.Binder;
import android.os.Handler;
@@ -30,7 +32,9 @@
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
/**
* WifiMulticastLockManager tracks holders of multicast locks and
@@ -38,10 +42,15 @@
*/
public class WifiMulticastLockManager {
private static final String TAG = "WifiMulticastLockManager";
+ private static final int IMPORTANCE_THRESHOLD =
+ ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED;
private final List<Multicaster> mMulticasters = new ArrayList<>();
+ private final Map<Integer, Integer> mNumLocksPerActiveOwner = new HashMap<>();
+ private final Map<Integer, Integer> mNumLocksPerInactiveOwner = new HashMap<>();
private int mMulticastEnabled = 0;
private int mMulticastDisabled = 0;
private final Handler mHandler;
+ private final Object mLock = new Object();
private boolean mVerboseLoggingEnabled = false;
private final BatteryStatsManager mBatteryStats;
private final ActiveModeWarden mActiveModeWarden;
@@ -58,13 +67,22 @@
public WifiMulticastLockManager(
ActiveModeWarden activeModeWarden,
BatteryStatsManager batteryStats,
- Looper looper) {
+ Looper looper,
+ Context context) {
mBatteryStats = batteryStats;
mActiveModeWarden = activeModeWarden;
mHandler = new Handler(looper);
mActiveModeWarden.registerPrimaryClientModeManagerChangedCallback(
new PrimaryClientModeManagerChangedCallback());
+
+ ActivityManager activityManager = context.getSystemService(ActivityManager.class);
+ activityManager.addOnUidImportanceListener(new ActivityManager.OnUidImportanceListener() {
+ @Override
+ public void onUidImportance(final int uid, final int importance) {
+ handleImportanceChanged(uid, importance);
+ }
+ }, IMPORTANCE_THRESHOLD);
}
private class Multicaster implements IBinder.DeathRecipient {
@@ -72,9 +90,9 @@
int mUid;
IBinder mBinder;
- Multicaster(String tag, IBinder binder) {
+ Multicaster(int uid, IBinder binder, String tag) {
mTag = tag;
- mUid = Binder.getCallingUid();
+ mUid = uid;
mBinder = binder;
try {
mBinder.linkToDeath(this, 0);
@@ -87,7 +105,7 @@
public void binderDied() {
mHandler.post(() -> {
Log.e(TAG, "Multicaster binderDied");
- synchronized (mMulticasters) {
+ synchronized (mLock) {
int i = mMulticasters.indexOf(this);
if (i != -1) {
removeMulticasterLocked(i, mUid, mTag);
@@ -108,16 +126,71 @@
return mTag;
}
+ public IBinder getBinder() {
+ return mBinder;
+ }
+
public String toString() {
return "Multicaster{" + mTag + " uid=" + mUid + "}";
}
}
+ private boolean uidIsLockOwner(int uid) {
+ return mNumLocksPerActiveOwner.containsKey(uid)
+ || mNumLocksPerInactiveOwner.containsKey(uid);
+ }
+
+ private void transitionUidToActive(int uid) {
+ if (mNumLocksPerInactiveOwner.containsKey(uid)) {
+ mNumLocksPerActiveOwner.put(uid, mNumLocksPerInactiveOwner.get(uid));
+ mNumLocksPerInactiveOwner.remove(uid);
+ }
+ }
+
+ private void transitionUidToInactive(int uid) {
+ if (mNumLocksPerActiveOwner.containsKey(uid)) {
+ mNumLocksPerInactiveOwner.put(uid, mNumLocksPerActiveOwner.get(uid));
+ mNumLocksPerActiveOwner.remove(uid);
+ }
+ }
+
+ private void handleImportanceChanged(int uid, int importance) {
+ mHandler.post(() -> {
+ synchronized (mLock) {
+ if (!uidIsLockOwner(uid)) {
+ return;
+ }
+
+ boolean uidIsNowActive = importance < IMPORTANCE_THRESHOLD;
+ boolean prevIsMulticastEnabled = isMulticastEnabled();
+ Log.i(TAG, "Handling importance changed for uid=" + uid
+ + ", isNowActive=" + uidIsNowActive + ", importance=" + importance);
+ if (uidIsNowActive) {
+ transitionUidToActive(uid);
+ } else {
+ transitionUidToInactive(uid);
+ }
+
+ boolean currentIsMulticastEnabled = isMulticastEnabled();
+ if (prevIsMulticastEnabled != currentIsMulticastEnabled) {
+ if (currentIsMulticastEnabled) {
+ // Filtering should be stopped if multicast is enabled
+ stopFilteringMulticastPackets();
+ } else {
+ startFilteringMulticastPackets();
+ }
+ }
+ }
+ });
+ }
+
protected void dump(PrintWriter pw) {
pw.println("mMulticastEnabled " + mMulticastEnabled);
pw.println("mMulticastDisabled " + mMulticastDisabled);
- pw.println("Multicast Locks held:");
- synchronized (mMulticasters) {
+ synchronized (mLock) {
+ pw.println("Active lock owners: " + mNumLocksPerActiveOwner);
+ pw.println("Inactive lock owners: " + mNumLocksPerInactiveOwner);
+ pw.println("Multicast Locks held:");
for (Multicaster l : mMulticasters) {
pw.print(" ");
pw.println(l);
@@ -129,11 +202,10 @@
mVerboseLoggingEnabled = verboseEnabled;
}
- /** Start filtering if no multicasters exist. */
- public void initializeFiltering() {
- synchronized (mMulticasters) {
- // if anybody had requested filters be off, leave off
- if (mMulticasters.size() == 0) {
+ /** Start filtering multicast packets if no locks are actively held */
+ public void startFilteringMulticastPackets() {
+ synchronized (mLock) {
+ if (!isMulticastEnabled()) {
mActiveModeWarden.getPrimaryClientModeManager()
.getMcastLockManagerFilterController()
.startFilteringMulticastPackets();
@@ -141,15 +213,29 @@
}
}
+ private void stopFilteringMulticastPackets() {
+ mActiveModeWarden.getPrimaryClientModeManager()
+ .getMcastLockManagerFilterController()
+ .stopFilteringMulticastPackets();
+ }
+
/**
* Acquire a multicast lock.
* @param binder a binder used to ensure caller is still alive
* @param tag string name of the caller.
*/
- public void acquireLock(IBinder binder, String tag) {
- synchronized (mMulticasters) {
+ public void acquireLock(int uid, IBinder binder, String tag) {
+ synchronized (mLock) {
mMulticastEnabled++;
- mMulticasters.add(new Multicaster(tag, binder));
+
+ // Assume that the application is active if it is requesting a lock
+ if (mNumLocksPerInactiveOwner.containsKey(uid)) {
+ transitionUidToActive(uid);
+ }
+ int numLocksHeldByUid = mNumLocksPerActiveOwner.getOrDefault(uid, 0);
+ mNumLocksPerActiveOwner.put(uid, numLocksHeldByUid + 1);
+ mMulticasters.add(new Multicaster(uid, binder, tag));
+
// Note that we could call stopFilteringMulticastPackets only when
// our new size == 1 (first call), but this function won't
// be called often and by making the stopPacket call each
@@ -159,7 +245,6 @@
.stopFilteringMulticastPackets();
}
- int uid = Binder.getCallingUid();
final long ident = Binder.clearCallingIdentity();
mBatteryStats.reportWifiMulticastEnabled(new WorkSource(uid));
WifiStatsLog.write_non_chained(
@@ -169,14 +254,14 @@
}
/** Releases a multicast lock */
- public void releaseLock(String tag) {
- int uid = Binder.getCallingUid();
- synchronized (mMulticasters) {
+ public void releaseLock(int uid, IBinder binder, String tag) {
+ synchronized (mLock) {
mMulticastDisabled++;
int size = mMulticasters.size();
for (int i = size - 1; i >= 0; i--) {
Multicaster m = mMulticasters.get(i);
- if ((m != null) && (m.getUid() == uid) && (m.getTag().equals(tag))) {
+ if ((m != null) && (m.getUid() == uid) && (m.getTag().equals(tag))
+ && (m.getBinder() == binder)) {
removeMulticasterLocked(i, uid, tag);
break;
}
@@ -184,13 +269,28 @@
}
}
+ private void decrementNumLocksForUid(int uid, Map<Integer, Integer> map) {
+ int numLocksHeldByUid = map.get(uid) - 1;
+ if (numLocksHeldByUid == 0) {
+ map.remove(uid);
+ } else {
+ map.put(uid, numLocksHeldByUid);
+ }
+ }
+
private void removeMulticasterLocked(int i, int uid, String tag) {
Multicaster removed = mMulticasters.remove(i);
-
if (removed != null) {
removed.unlinkDeathRecipient();
}
- if (mMulticasters.size() == 0) {
+
+ if (mNumLocksPerActiveOwner.containsKey(uid)) {
+ decrementNumLocksForUid(uid, mNumLocksPerActiveOwner);
+ } else if (mNumLocksPerInactiveOwner.containsKey(uid)) {
+ decrementNumLocksForUid(uid, mNumLocksPerInactiveOwner);
+ }
+
+ if (!isMulticastEnabled()) {
mActiveModeWarden.getPrimaryClientModeManager()
.getMcastLockManagerFilterController()
.startFilteringMulticastPackets();
@@ -206,8 +306,9 @@
/** Returns whether multicast should be allowed (filtering disabled). */
public boolean isMulticastEnabled() {
- synchronized (mMulticasters) {
- return mMulticasters.size() > 0;
+ synchronized (mLock) {
+ // Multicast is enabled if any active lock owners exist
+ return !mNumLocksPerActiveOwner.isEmpty();
}
}
diff --git a/service/java/com/android/server/wifi/WifiNative.java b/service/java/com/android/server/wifi/WifiNative.java
index aa1d339..26e1adc 100644
--- a/service/java/com/android/server/wifi/WifiNative.java
+++ b/service/java/com/android/server/wifi/WifiNative.java
@@ -27,7 +27,6 @@
import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_NATIVE_SUPPORTED_FEATURES;
import static com.android.server.wifi.p2p.WifiP2pNative.P2P_IFACE_NAME;
import static com.android.server.wifi.p2p.WifiP2pNative.P2P_INTERFACE_PROPERTY;
-import static com.android.server.wifi.util.GeneralUtil.bitsetToLong;
import static com.android.server.wifi.util.GeneralUtil.longToBitset;
import static com.android.wifi.flags.Flags.rsnOverriding;
@@ -40,6 +39,7 @@
import android.net.TrafficStats;
import android.net.apf.ApfCapabilities;
import android.net.wifi.CoexUnsafeChannel;
+import android.net.wifi.DeauthenticationReasonCode;
import android.net.wifi.MscsParams;
import android.net.wifi.OuiKeyedData;
import android.net.wifi.QosPolicyParams;
@@ -79,6 +79,7 @@
import com.android.internal.util.HexDump;
import com.android.modules.utils.build.SdkLevel;
import com.android.server.wifi.SupplicantStaIfaceHal.QosPolicyStatus;
+import com.android.server.wifi.WifiLinkLayerStats.ScanResultWithSameFreq;
import com.android.server.wifi.hal.WifiChip;
import com.android.server.wifi.hal.WifiHal;
import com.android.server.wifi.hal.WifiNanIface;
@@ -90,6 +91,7 @@
import com.android.server.wifi.util.NativeUtil;
import com.android.server.wifi.util.NetdWrapper;
import com.android.server.wifi.util.NetdWrapper.NetdEventObserver;
+import com.android.wifi.flags.Flags;
import com.android.wifi.resources.R;
import java.io.PrintWriter;
@@ -294,7 +296,8 @@
@Override
public void onConnectedClientsChanged(NativeWifiClient client, boolean isConnected) {
mSoftApHalCallback.onConnectedClientsChanged(mIfaceName,
- client.getMacAddress(), isConnected);
+ client.getMacAddress(), isConnected,
+ DeauthenticationReasonCode.REASON_UNKNOWN);
}
}
@@ -359,9 +362,11 @@
* @param clientAddress Macaddress of the client.
* @param isConnected Indication as to whether the client is connected (true), or
* disconnected (false).
+ * @param disconnectReason The reason for disconnection, if applicable. This
+ * parameter is only meaningful when {@code isConnected} is false.
*/
void onConnectedClientsChanged(String apIfaceInstance, MacAddress clientAddress,
- boolean isConnected);
+ boolean isConnected, @WifiAnnotations.SoftApDisconnectReason int disconnectReason);
}
/********************************************************
@@ -396,7 +401,7 @@
/** Network observer registered for this interface */
public NetworkObserverInternal networkObserver;
/** Interface feature set / capabilities */
- public long featureSet;
+ public BitSet featureSet = new BitSet();
public int bandsSupported;
public DeviceWiphyCapabilities phyCapabilities;
public WifiHal.WifiInterface iface;
@@ -420,6 +425,12 @@
case IFACE_TYPE_AP:
typeString = "AP";
break;
+ case IFACE_TYPE_P2P:
+ typeString = "P2P";
+ break;
+ case IFACE_TYPE_NAN:
+ typeString = "NAN";
+ break;
default:
typeString = "<UNKNOWN>";
break;
@@ -1316,8 +1327,12 @@
nanInterfaceDestroyedListener, handler, requestorWs);
if (nanIface != null) {
iface.iface = nanIface;
- return iface;
+ iface.name = nanIface.getName();
+ if (!TextUtils.isEmpty(iface.name)) {
+ return iface;
+ }
}
+ mIfaceMgr.removeIface(iface.id);
}
Log.e(TAG, "Failed to allocate new Nan iface");
stopHalAndWificondIfNecessary();
@@ -1562,8 +1577,6 @@
iface.featureSet = getSupportedFeatureSetInternal(iface.name);
updateSupportedBandForStaInternal(iface);
- mIsRsnOverridingSupported = mContext.getResources().getBoolean(
- R.bool.config_wifiRsnOverridingEnabled) && rsnOverriding();
mWifiVendorHal.enableStaChannelForPeerNetwork(mContext.getResources().getBoolean(
R.bool.config_wifiEnableStaIndoorChannelForPeerNetwork),
@@ -1574,6 +1587,18 @@
}
/**
+ * Return true when the device supports Wi-Fi 7 MLD AP and multiple links operation (MLO).
+ */
+ public boolean isMLDApSupportMLO() {
+ if (!Flags.mloSap()) {
+ return false;
+ }
+ BitSet cachedFeatureSet = getCompleteFeatureSetFromConfigStore();
+ return mWifiInjector.getWifiGlobals().isMLDApSupported()
+ && cachedFeatureSet.get(WifiManager.WIFI_FEATURE_SOFTAP_MLO);
+ }
+
+ /**
* Setup an interface for Soft AP mode operations.
*
* This method configures an interface in AP mode in all the native daemons
@@ -1590,7 +1615,8 @@
public String setupInterfaceForSoftApMode(
@NonNull InterfaceCallback interfaceCallback, @NonNull WorkSource requestorWs,
@SoftApConfiguration.BandType int band, boolean isBridged,
- @NonNull SoftApManager softApManager, @NonNull List<OuiKeyedData> vendorData) {
+ @NonNull SoftApManager softApManager, @NonNull List<OuiKeyedData> vendorData,
+ boolean isUsingMlo) {
synchronized (mLock) {
String bugTitle = "Wi-Fi BugReport (softAp interface failure)";
String errorMsg = "";
@@ -1628,7 +1654,7 @@
return null;
}
String ifaceInstanceName = iface.name;
- if (isBridged) {
+ if (isBridged && !isUsingMlo) {
List<String> instances = getBridgedApInstances(iface.name);
if (instances == null || instances.size() == 0) {
errorMsg = "Failed to get bridged AP instances" + iface.name;
@@ -1764,7 +1790,13 @@
iface.featureSet = getSupportedFeatureSetInternal(iface.name);
saveCompleteFeatureSetInConfigStoreIfNecessary(iface.featureSet);
updateSupportedBandForStaInternal(iface);
- mIsEnhancedOpenSupported = (iface.featureSet & WIFI_FEATURE_OWE) != 0;
+ mIsEnhancedOpenSupported = iface.featureSet.get(WIFI_FEATURE_OWE);
+ if (rsnOverriding()) {
+ mIsRsnOverridingSupported = isSupplicantAidlServiceVersionAtLeast(4)
+ ? mSupplicantStaIfaceHal.isRsnOverridingSupported(iface.name)
+ : mContext.getResources().getBoolean(
+ R.bool.config_wifiRsnOverridingEnabled);
+ }
Log.i(TAG, "Successfully switched to connectivity mode on iface=" + iface);
return true;
}
@@ -2368,7 +2400,7 @@
*/
public @SoftApManager.StartResult int startSoftAp(
@NonNull String ifaceName, SoftApConfiguration config, boolean isMetered,
- SoftApHalCallback callback) {
+ SoftApHalCallback callback, boolean isUsingMlo) {
if (mHostapdHal.isApInfoCallbackSupported()) {
if (!mHostapdHal.registerApCallback(ifaceName, callback)) {
Log.e(TAG, "Failed to register ap hal event callback");
@@ -2383,8 +2415,10 @@
return SoftApManager.START_RESULT_FAILURE_REGISTER_AP_CALLBACK_WIFICOND;
}
}
-
- if (!mHostapdHal.addAccessPoint(ifaceName, config, isMetered, callback::onFailure)) {
+ if (!mHostapdHal.addAccessPoint(ifaceName, config, isMetered,
+ isUsingMlo,
+ getBridgedApInstances(ifaceName),
+ callback::onFailure)) {
String errorMsg = "Failed to add softAp";
Log.e(TAG, errorMsg);
mWifiMetrics.incrementNumSetupSoftApInterfaceFailureDueToHostapd();
@@ -3764,6 +3798,30 @@
WifiLinkLayerStats stats = mWifiVendorHal.getWifiLinkLayerStats(ifaceName);
if (stats != null) {
stats.aggregateLinkLayerStats();
+ stats.wifiMloMode = getMloMode();
+ ScanData scanData = getCachedScanResults(ifaceName);
+ if (scanData != null && scanData.getResults() != null
+ && scanData.getResults().length > 0) {
+ for (int linkIndex = 0; linkIndex < stats.links.length; ++linkIndex) {
+ List<ScanResultWithSameFreq> ScanResultsSameFreq = new ArrayList<>();
+ for (int scanResultsIndex = 0; scanResultsIndex < scanData.getResults().length;
+ ++scanResultsIndex) {
+ if (scanData.getResults()[scanResultsIndex].frequency
+ != stats.links[linkIndex].frequencyMhz) {
+ continue;
+ }
+ ScanResultWithSameFreq ScanResultSameFreq = new ScanResultWithSameFreq();
+ ScanResultSameFreq.scan_result_timestamp_micros =
+ scanData.getResults()[scanResultsIndex].timestamp;
+ ScanResultSameFreq.rssi = scanData.getResults()[scanResultsIndex].level;
+ ScanResultSameFreq.frequencyMhz =
+ scanData.getResults()[scanResultsIndex].frequency;
+ ScanResultSameFreq.bssid = scanData.getResults()[scanResultsIndex].BSSID;
+ ScanResultsSameFreq.add(ScanResultSameFreq);
+ }
+ stats.links[linkIndex].scan_results_same_freq = ScanResultsSameFreq;
+ }
+ }
}
return stats;
}
@@ -3944,19 +4002,18 @@
* @param ifaceName Name of the interface.
* @return bitmask defined by WifiManager.WIFI_FEATURE_*
*/
- public long getSupportedFeatureSet(String ifaceName) {
+ public @NonNull BitSet getSupportedFeatureSet(String ifaceName) {
synchronized (mLock) {
- long featureSet = 0;
// First get the complete feature set stored in config store when supplicant was
// started
- featureSet = bitsetToLong(getCompleteFeatureSetFromConfigStore());
+ BitSet featureSet = getCompleteFeatureSetFromConfigStore();
// Include the feature set saved in interface class. This is to make sure that
// framework is returning the feature set for SoftAp only products and multi-chip
// products.
if (ifaceName != null) {
Iface iface = mIfaceMgr.getIface(ifaceName);
if (iface != null) {
- featureSet |= iface.featureSet;
+ featureSet.or(iface.featureSet);
}
}
return featureSet;
@@ -3985,16 +4042,15 @@
* @param ifaceName Name of the interface.
* @return bitmask defined by WifiManager.WIFI_FEATURE_*
*/
- private long getSupportedFeatureSetInternal(@NonNull String ifaceName) {
- BitSet featureBitset = mSupplicantStaIfaceHal.getAdvancedCapabilities(ifaceName);
- featureBitset.or(mSupplicantStaIfaceHal.getWpaDriverFeatureSet(ifaceName));
- featureBitset.or(mWifiVendorHal.getSupportedFeatureSet(ifaceName));
- long featureSet = bitsetToLong(featureBitset);
+ private BitSet getSupportedFeatureSetInternal(@NonNull String ifaceName) {
+ BitSet featureSet = mSupplicantStaIfaceHal.getAdvancedCapabilities(ifaceName);
+ featureSet.or(mSupplicantStaIfaceHal.getWpaDriverFeatureSet(ifaceName));
+ featureSet.or(mWifiVendorHal.getSupportedFeatureSet(ifaceName));
if (SdkLevel.isAtLeastT()) {
- if (((featureSet & WifiManager.WIFI_FEATURE_DPP) != 0)
+ if (featureSet.get(WifiManager.WIFI_FEATURE_DPP)
&& mContext.getResources().getBoolean(R.bool.config_wifiDppAkmSupported)) {
// Set if DPP is filled by supplicant and DPP AKM is enabled by overlay.
- featureSet |= WifiManager.WIFI_FEATURE_DPP_AKM;
+ featureSet.set(WifiManager.WIFI_FEATURE_DPP_AKM);
Log.v(TAG, ": DPP AKM supported");
}
}
@@ -5173,8 +5229,7 @@
* Save the complete list of features retrieved from WiFi HAL and Supplicant HAL in
* config store.
*/
- private void saveCompleteFeatureSetInConfigStoreIfNecessary(long featureSetLong) {
- BitSet featureSet = longToBitset(featureSetLong);
+ private void saveCompleteFeatureSetInConfigStoreIfNecessary(BitSet featureSet) {
BitSet cachedFeatureSet = getCompleteFeatureSetFromConfigStore();
if (!cachedFeatureSet.equals(featureSet)) {
mCachedFeatureSet = featureSet;
diff --git a/service/java/com/android/server/wifi/WifiNetworkSelector.java b/service/java/com/android/server/wifi/WifiNetworkSelector.java
index 7686e22..4f5a2b8 100644
--- a/service/java/com/android/server/wifi/WifiNetworkSelector.java
+++ b/service/java/com/android/server/wifi/WifiNetworkSelector.java
@@ -467,7 +467,8 @@
@SuppressLint("NewApi")
private List<ScanDetail> filterScanResults(List<ScanDetail> scanDetails,
- Set<String> bssidBlocklist, List<ClientModeManagerState> cmmStates) {
+ Set<String> bssidBlocklist, List<ClientModeManagerState> cmmStates,
+ int autojoinRestrictionSecurityTypes) {
List<ScanDetail> validScanDetails = new ArrayList<>();
StringBuffer noValidSsid = new StringBuffer();
StringBuffer blockedBssid = new StringBuffer();
@@ -475,6 +476,7 @@
StringBuffer mboAssociationDisallowedBssid = new StringBuffer();
StringBuffer adminRestrictedSsid = new StringBuffer();
StringJoiner deprecatedSecurityTypeSsid = new StringJoiner(" / ");
+ StringJoiner autojoinRestrictionSecurityTypesBssid = new StringJoiner(" / ");
List<String> currentBssids = cmmStates.stream()
.map(cmmState -> cmmState.wifiInfo.getBSSID())
.collect(Collectors.toList());
@@ -611,6 +613,22 @@
}
}
+ // Skip network with security type that is restricted to auto join
+ if (autojoinRestrictionSecurityTypes != 0/*restrict none*/) {
+ @WifiAnnotations.SecurityType int[] securityTypes = scanResult.getSecurityTypes();
+ boolean securityTypeRestricted = true;
+ for (int type : securityTypes) {
+ if (((0x1 << type) & autojoinRestrictionSecurityTypes) == 0) {
+ securityTypeRestricted = false;
+ break;
+ }
+ }
+ if (securityTypeRestricted) {
+ autojoinRestrictionSecurityTypesBssid.add(scanId);
+ continue;
+ }
+ }
+
validScanDetails.add(scanDetail);
}
mWifiMetrics.incrementNetworkSelectionFilteredBssidCount(numBssidFiltered);
@@ -663,6 +681,11 @@
+ deprecatedSecurityTypeSsid);
}
+ if (autojoinRestrictionSecurityTypesBssid.length() != 0) {
+ localLog("Networks filtered out due to auto join restriction on the security type: "
+ + autojoinRestrictionSecurityTypesBssid);
+ }
+
return validScanDetails;
}
@@ -685,7 +708,7 @@
mIsEnhancedOpenSupportedInitialized = true;
ClientModeManager primaryManager =
mWifiInjector.getActiveModeWarden().getPrimaryClientModeManager();
- mIsEnhancedOpenSupported = (primaryManager.getSupportedFeatures() & WIFI_FEATURE_OWE) != 0;
+ mIsEnhancedOpenSupported = primaryManager.getSupportedFeatures().get(WIFI_FEATURE_OWE);
return mIsEnhancedOpenSupported;
}
@@ -1075,7 +1098,8 @@
@NonNull List<ScanDetail> scanDetails, @NonNull Set<String> bssidBlocklist,
@NonNull List<ClientModeManagerState> cmmStates, boolean untrustedNetworkAllowed,
boolean oemPaidNetworkAllowed, boolean oemPrivateNetworkAllowed,
- Set<Integer> restrictedNetworkAllowedUids, boolean skipSufficiencyCheck) {
+ Set<Integer> restrictedNetworkAllowedUids, boolean skipSufficiencyCheck,
+ int autojoinRestrictionSecurityTypes) {
mFilteredNetworks.clear();
mConnectableNetworks.clear();
if (scanDetails.size() == 0) {
@@ -1092,7 +1116,8 @@
}
// Filter out unwanted networks.
- mFilteredNetworks = filterScanResults(scanDetails, bssidBlocklist, cmmStates);
+ mFilteredNetworks = filterScanResults(scanDetails, bssidBlocklist, cmmStates,
+ autojoinRestrictionSecurityTypes);
if (mFilteredNetworks.size() == 0) {
return null;
}
diff --git a/service/java/com/android/server/wifi/WifiNetworkSuggestionsManager.java b/service/java/com/android/server/wifi/WifiNetworkSuggestionsManager.java
index 9fa6113..ee4bb2f 100644
--- a/service/java/com/android/server/wifi/WifiNetworkSuggestionsManager.java
+++ b/service/java/com/android/server/wifi/WifiNetworkSuggestionsManager.java
@@ -74,6 +74,7 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
+import java.util.BitSet;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
@@ -1115,7 +1116,7 @@
return false;
}
- long supportedFeatures = mWifiInjector.getActiveModeWarden()
+ BitSet supportedFeatures = mWifiInjector.getActiveModeWarden()
.getPrimaryClientModeManager().getSupportedFeatures();
for (WifiNetworkSuggestion wns : networkSuggestions) {
diff --git a/service/java/com/android/server/wifi/WifiPulledAtomLogger.java b/service/java/com/android/server/wifi/WifiPulledAtomLogger.java
index 44bc126..36a54e6 100644
--- a/service/java/com/android/server/wifi/WifiPulledAtomLogger.java
+++ b/service/java/com/android/server/wifi/WifiPulledAtomLogger.java
@@ -26,6 +26,7 @@
import android.net.wifi.WifiSsid;
import android.os.Handler;
import android.os.Process;
+import android.text.TextUtils;
import android.util.Log;
import android.util.StatsEvent;
@@ -149,6 +150,10 @@
data.add(WifiStatsLog.buildStatsEvent(atomTag,
WifiStatsLog.WIFI_SETTING_INFO__SETTING_NAME__LOCATION_MODE,
mWifiInjector.getWifiPermissionsUtil().isLocationModeEnabled()));
+ data.add(WifiStatsLog.buildStatsEvent(atomTag,
+ WifiStatsLog.WIFI_SETTING_INFO__SETTING_NAME__EXTERNAL_SCORER_DRY_RUN,
+ !TextUtils.isEmpty(
+ mWifiInjector.getDeviceConfigFacade().getDryRunScorerPkgName())));
return StatsManager.PULL_SUCCESS;
}
diff --git a/service/java/com/android/server/wifi/WifiScoreReport.java b/service/java/com/android/server/wifi/WifiScoreReport.java
index c3c4a0f..a65fe8a 100644
--- a/service/java/com/android/server/wifi/WifiScoreReport.java
+++ b/service/java/com/android/server/wifi/WifiScoreReport.java
@@ -138,6 +138,8 @@
/**
* Callback from {@link ExternalScoreUpdateObserverProxy}
+ *
+ * Wifi Scorer calls these callbacks when it needs to send information to us.
*/
private class ScoreUpdateObserverProxy implements WifiManager.ScoreUpdateObserver {
@Override
@@ -255,7 +257,8 @@
}
// TODO(b/153075963): This should not be plumbed through WifiMetrics
- mWifiMetrics.updateWifiUsabilityStatsEntries(mInterfaceName, mWifiInfo, stats);
+ mWifiMetrics.updateWifiUsabilityStatsEntries(mInterfaceName, mWifiInfo, stats, false,
+ 0);
}
@Override
@@ -652,12 +655,13 @@
}
/**
- * Calculate wifi network score based on updated link layer stats and send the score to
- * the WifiNetworkAgent.
- *
- * If the score has changed from the previous value, update the WifiNetworkAgent.
+ * Calculate the new wifi network score based on updated link layer stats.
*
* Called periodically (POLL_RSSI_INTERVAL_MSECS) about every 3 seconds.
+ *
+ * Note: This function will only notify connectivity services of the updated route if we are NOT
+ * using a connected external WiFi scorer.
+ *
*/
public void calculateAndReportScore() {
if (mWifiInfo.getRssi() == mWifiInfo.INVALID_RSSI) {
@@ -1122,11 +1126,14 @@
|| netId != getCurrentNetId()
|| isLocalOnlyOrRestrictedConnection()
|| sessionId == INVALID_SESSION_ID) {
- Log.w(TAG, "Cannot start external scoring"
- + " netId=" + netId
- + " currentNetId=" + getCurrentNetId()
- + " currentNetCapabilities=" + getCurrentNetCapabilities()
- + " sessionId=" + sessionId);
+ StringBuilder sb = new StringBuilder();
+ sb.append("Cannot start external scoring netId=").append(netId)
+ .append(" currentNetId=").append(getCurrentNetId());
+ if (mVerboseLoggingEnabled) {
+ sb.append(" currentNetCapabilities=").append(getCurrentNetCapabilities());
+ }
+ sb.append(" sessionId=").append(sessionId);
+ Log.w(TAG, sb.toString());
return;
}
mCurrentWifiConfiguration = mWifiConfigManager.getConfiguredNetwork(
diff --git a/service/java/com/android/server/wifi/WifiServiceImpl.java b/service/java/com/android/server/wifi/WifiServiceImpl.java
index 4347040..385beb6 100644
--- a/service/java/com/android/server/wifi/WifiServiceImpl.java
+++ b/service/java/com/android/server/wifi/WifiServiceImpl.java
@@ -38,12 +38,12 @@
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_TRUST_ON_FIRST_USE;
import static android.net.wifi.WifiManager.WIFI_INTERFACE_TYPE_AP;
import static android.net.wifi.WifiManager.WIFI_INTERFACE_TYPE_AWARE;
import static android.net.wifi.WifiManager.WIFI_INTERFACE_TYPE_DIRECT;
import static android.net.wifi.WifiManager.WIFI_INTERFACE_TYPE_STA;
import static android.net.wifi.WifiManager.WIFI_STATE_ENABLED;
+import static android.net.wifi.WifiManager.WifiStateChangedListener;
import static android.os.Process.WIFI_UID;
import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_LOCAL_ONLY;
@@ -101,7 +101,9 @@
import android.net.TetheringManager;
import android.net.Uri;
import android.net.ip.IpClientUtil;
-import android.net.wifi.BaseWifiService;
+import android.net.thread.ThreadNetworkController;
+import android.net.thread.ThreadNetworkManager;
+import android.net.wifi.BlockingOption;
import android.net.wifi.CoexUnsafeChannel;
import android.net.wifi.IActionListener;
import android.net.wifi.IBooleanListener;
@@ -134,8 +136,10 @@
import android.net.wifi.IWifiBandsListener;
import android.net.wifi.IWifiConnectedNetworkScorer;
import android.net.wifi.IWifiLowLatencyLockListener;
+import android.net.wifi.IWifiManager;
import android.net.wifi.IWifiNetworkSelectionConfigListener;
import android.net.wifi.IWifiNetworkStateChangedListener;
+import android.net.wifi.IWifiStateChangedListener;
import android.net.wifi.IWifiVerboseLoggingStatusChangedListener;
import android.net.wifi.MscsParams;
import android.net.wifi.QosPolicyParams;
@@ -169,6 +173,7 @@
import android.net.wifi.twt.TwtRequest;
import android.net.wifi.twt.TwtSession;
import android.net.wifi.twt.TwtSessionCallback;
+import android.net.wifi.util.Environment;
import android.net.wifi.util.ScanResultUtil;
import android.net.wifi.util.WifiResourceCache;
import android.os.AsyncTask;
@@ -201,6 +206,7 @@
import android.util.Pair;
import android.util.SparseArray;
import android.util.SparseIntArray;
+import android.uwb.UwbManager;
import androidx.annotation.RequiresApi;
@@ -223,6 +229,7 @@
import com.android.server.wifi.util.LastCallerInfoManager;
import com.android.server.wifi.util.RssiUtil;
import com.android.server.wifi.util.WifiPermissionsUtil;
+import com.android.wifi.flags.FeatureFlags;
import com.android.wifi.resources.R;
import org.json.JSONArray;
@@ -245,6 +252,7 @@
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.BitSet;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@@ -264,7 +272,7 @@
* WifiService handles remote WiFi operation requests by implementing
* the IWifiManager interface.
*/
-public class WifiServiceImpl extends BaseWifiService {
+public class WifiServiceImpl extends IWifiManager.Stub {
private static final String TAG = "WifiService";
private static final boolean VDBG = false;
@@ -329,6 +337,9 @@
private final DefaultClientModeManager mDefaultClientModeManager;
+ private final WepNetworkUsageController mWepNetworkUsageController;
+
+ private final FeatureFlags mFeatureFlags;
@VisibleForTesting
public final CountryCodeTracker mCountryCodeTracker;
private final MultiInternetManager mMultiInternetManager;
@@ -428,6 +439,14 @@
Map<String, List<WifiClient>> clients, boolean isBridged) {}
/**
+ * see:
+ * {@code WifiManager.SoftApCallback#onClientsDisconnected(SoftApInfo,
+ * List<WifiClient>)}
+ */
+ void onClientsDisconnected(@NonNull SoftApInfo info,
+ @NonNull List<WifiClient> clients) {}
+
+ /**
* see: {@code WifiManager.SoftApCallback#onCapabilityChanged(SoftApCapability)}
*/
void onCapabilityChanged(@NonNull SoftApCapability softApCapability) {}
@@ -515,6 +534,28 @@
}
callbacks.finishBroadcast();
}
+
+ /**
+ * Notify register that clients have disconnected from a soft AP instance.
+ *
+ * @param info The {@link SoftApInfo} of the AP.
+ * @param clients The clients that have disconnected from the AP instance specified by
+ * {@code info}.
+ */
+ public void notifyRegisterOnClientsDisconnected(
+ RemoteCallbackList<ISoftApCallback> callbacks, SoftApInfo info,
+ List<WifiClient> clients) {
+ int itemCount = callbacks.beginBroadcast();
+ for (int i = 0; i < itemCount; i++) {
+ try {
+ callbacks.getBroadcastItem(i).onClientsDisconnected(new SoftApInfo(info),
+ clients);
+ } catch (RemoteException e) {
+ Log.e(TAG, "onClientsDisconnected: remote exception -- " + e);
+ }
+ }
+ callbacks.finishBroadcast();
+ }
}
public WifiServiceImpl(WifiContext context, WifiInjector wifiInjector) {
@@ -579,10 +620,12 @@
mWifiTetheringDisallowed = false;
mMultiInternetManager = mWifiInjector.getMultiInternetManager();
mDeviceConfigFacade = mWifiInjector.getDeviceConfigFacade();
+ mFeatureFlags = mDeviceConfigFacade.getFeatureFlags();
mApplicationQosPolicyRequestHandler = mWifiInjector.getApplicationQosPolicyRequestHandler();
mWifiPulledAtomLogger = mWifiInjector.getWifiPulledAtomLogger();
mAfcManager = mWifiInjector.getAfcManager();
mTwtManager = mWifiInjector.getTwtManager();
+ mWepNetworkUsageController = mWifiInjector.getWepNetworkUsageController();
}
/**
@@ -608,17 +651,20 @@
mWifiInjector.getWifiScanAlwaysAvailableSettingsCompatibility().initialize();
mWifiInjector.getWifiNotificationManager().createNotificationChannels();
- // Align the value between config stroe (i.e.WifiConfigStore.xml) and WifiGlobals.
- mSettingsConfigStore.registerChangeListener(WIFI_WEP_ALLOWED,
- (key, value) -> {
- if (mWifiGlobals.isWepAllowed() != value) {
- // It should only happen when settings is restored from cloud.
- handleWepAllowedChanged(value);
- Log.i(TAG, "(Cloud Restoration) Wep allowed is changed to " + value);
- }
- },
- new Handler(mWifiHandlerThread.getLooper()));
- mWifiGlobals.setWepAllowed(mSettingsConfigStore.get(WIFI_WEP_ALLOWED));
+ // Old design, flag is disabled.
+ if (!mFeatureFlags.wepDisabledInApm()) {
+ mWifiGlobals.setWepAllowed(mSettingsConfigStore.get(WIFI_WEP_ALLOWED));
+ // Align the value between config store (i.e.WifiConfigStore.xml) and WifiGlobals.
+ mSettingsConfigStore.registerChangeListener(WIFI_WEP_ALLOWED,
+ (key, value) -> {
+ if (mWifiGlobals.isWepAllowed() != value) {
+ handleWepAllowedChanged(value);
+ Log.i(TAG, "Wep allowed is changed to "
+ + value);
+ }
+ },
+ new Handler(mWifiHandlerThread.getLooper()));
+ }
mContext.registerReceiver(
new BroadcastReceiver() {
@Override
@@ -872,9 +918,13 @@
}
updateVerboseLoggingEnabled();
mWifiInjector.getWifiDeviceStateChangeManager().handleBootCompleted();
+ if (mFeatureFlags.wepDisabledInApm()
+ && mWepNetworkUsageController != null) {
+ mWepNetworkUsageController.handleBootCompleted();
+ }
setPulledAtomCallbacks();
mTwtManager.registerWifiNativeTwtEvents();
- mContext.registerReceiver(
+ mContext.registerReceiverForAllUsers(
new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@@ -888,6 +938,33 @@
null,
new Handler(mWifiHandlerThread.getLooper()));
updateLocationMode();
+
+ if (SdkLevel.isAtLeastT()) {
+ UwbManager uwbManager =
+ mContext.getSystemService(UwbManager.class);
+ if (uwbManager != null) {
+ uwbManager.registerAdapterStateCallback(new HandlerExecutor(new Handler(
+ mWifiHandlerThread.getLooper())), new UwbAdapterStateListener());
+ }
+ }
+
+ if (SdkLevel.isAtLeastV()) {
+ ThreadNetworkManager threadManager =
+ mContext.getSystemService(ThreadNetworkManager.class);
+ if (threadManager != null) {
+ List<ThreadNetworkController> threadNetworkControllers =
+ threadManager.getAllThreadNetworkControllers();
+ if (threadNetworkControllers.size() > 0) {
+ ThreadNetworkController threadNetworkController =
+ threadNetworkControllers.get(0);
+ if (threadNetworkController != null) {
+ threadNetworkController.registerStateCallback(
+ new HandlerExecutor(new Handler(mWifiHandlerThread.getLooper())),
+ new ThreadStateListener());
+ }
+ }
+ }
+ }
}, TAG + "#handleBootCompleted");
}
@@ -1313,9 +1390,10 @@
*/
@Override
public synchronized boolean setWifiEnabled(String packageName, boolean enable) {
- if (!isValidCallingUser() || enforceChangePermission(packageName) != MODE_ALLOWED) {
+ if (enforceChangePermission(packageName) != MODE_ALLOWED) {
return false;
}
+ enforceValidCallingUser();
int callingUid = Binder.getCallingUid();
int callingPid = Binder.getCallingPid();
boolean isPrivileged = isPrivileged(callingPid, callingUid);
@@ -1613,6 +1691,36 @@
}
/**
+ * See {@link WifiManager#addWifiStateChangedListener(Executor, WifiStateChangedListener)}
+ */
+ public void addWifiStateChangedListener(@NonNull IWifiStateChangedListener listener) {
+ enforceAccessPermission();
+ if (listener == null) {
+ throw new IllegalArgumentException("listener must not be null");
+ }
+ if (mVerboseLoggingEnabled) {
+ mLog.info("addWifiStateChangedListener uid=%").c(Binder.getCallingUid()).flush();
+ }
+ mWifiThreadRunner.post(() -> mActiveModeWarden.addWifiStateChangedListener(listener),
+ TAG + "#addWifiStateChangedListener");
+ }
+
+ /**
+ * See {@link WifiManager#removeWifiStateChangedListener(WifiStateChangedListener)}
+ */
+ public void removeWifiStateChangedListener(@NonNull IWifiStateChangedListener listener) {
+ enforceAccessPermission();
+ if (listener == null) {
+ throw new IllegalArgumentException("listener must not be null");
+ }
+ if (mVerboseLoggingEnabled) {
+ mLog.info("removeWifiStateChangedListener uid=%").c(Binder.getCallingUid()).flush();
+ }
+ mWifiThreadRunner.post(() -> mActiveModeWarden.removeWifiStateChangedListener(listener),
+ TAG + "#removeWifiStateChangedListener");
+ }
+
+ /**
* see {@link WifiManager#getWifiApState()}
* @return One of {@link WifiManager#WIFI_AP_STATE_DISABLED},
* {@link WifiManager#WIFI_AP_STATE_DISABLING},
@@ -1690,6 +1798,7 @@
/**
* See {@link WifiManager#registerCoexCallback(WifiManager.CoexCallback)}
*/
+ @Override
@RequiresApi(Build.VERSION_CODES.S)
public void registerCoexCallback(@NonNull ICoexCallback callback) {
if (!SdkLevel.isAtLeastS()) {
@@ -1728,6 +1837,7 @@
/**
* See {@link WifiManager#unregisterCoexCallback(WifiManager.CoexCallback)}
*/
+ @Override
@RequiresApi(Build.VERSION_CODES.S)
public void unregisterCoexCallback(@NonNull ICoexCallback callback) {
if (!SdkLevel.isAtLeastS()) {
@@ -2060,7 +2170,7 @@
continue;
}
List<Integer> freqsForBand = ApConfigUtil.getAvailableChannelFreqsForBand(
- band, mWifiNative, mResourceCache, true);
+ band, mWifiNative, null, true);
if (freqsForBand != null) {
freqs.addAll(freqsForBand);
int[] channel = new int[freqsForBand.size()];
@@ -2118,6 +2228,31 @@
}
}
+ @RequiresApi(Build.VERSION_CODES.TIRAMISU)
+ class UwbAdapterStateListener implements UwbManager.AdapterStateCallback {
+ @Override
+ public void onStateChanged(int state, int reason) {
+ if (mVerboseLoggingEnabled) {
+ Log.d(TAG, "UwbManager.AdapterState=" + state);
+ }
+ mWifiMetrics.setLastUwbState(state);
+ }
+ }
+
+ @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
+ class ThreadStateListener implements ThreadNetworkController.StateCallback {
+ @Override
+ public void onDeviceRoleChanged(int mDeviceRole) {
+ if (mVerboseLoggingEnabled) {
+ Log.d(TAG, "ThreadNetworkController.DeviceRole=" + mDeviceRole);
+ }
+ mWifiMetrics.setLastThreadDeviceRole(mDeviceRole);
+ }
+
+ @Override
+ public void onPartitionIdChanged(long mPartitionId) {}
+ }
+
/**
* SoftAp callback
*/
@@ -2222,6 +2357,10 @@
// Default country code
mSoftApCapability = updateSoftApCapabilityWithAvailableChannelList(
mSoftApCapability, mCountryCode.getCountryCode(), null);
+ if (mWifiNative.isMLDApSupportMLO()) {
+ mSoftApCapability.setSupportedFeatures(
+ true, SoftApCapability.SOFTAP_FEATURE_MLO);
+ }
}
return mSoftApCapability;
}
@@ -2342,6 +2481,19 @@
notifyRegisterOnBlockedClientConnecting(mRegisteredSoftApCallbacks, client,
blockedReason);
}
+
+ /**
+ * Called when clients disconnect from a soft AP instance.
+ *
+ * @param info The {@link SoftApInfo} of the AP.
+ * @param clients The clients that have disconnected from the AP instance specified by
+ * {@code info}.
+ */
+ @Override
+ public void onClientsDisconnected(@NonNull SoftApInfo info,
+ @NonNull List<WifiClient> clients) {
+ notifyRegisterOnClientsDisconnected(mRegisteredSoftApCallbacks, info, clients);
+ }
}
private final class TetheredSoftApTracker extends BaseSoftApTracker {
@@ -2792,7 +2944,8 @@
*/
@Override
public int startLocalOnlyHotspot(ILocalOnlyHotspotCallback callback, String packageName,
- String featureId, SoftApConfiguration customConfig, Bundle extras) {
+ String featureId, SoftApConfiguration customConfig, Bundle extras,
+ boolean isCalledFromSystemApi) {
// first check if the caller has permission to start a local only hotspot
// need to check for WIFI_STATE_CHANGE and location permission
final int uid = Binder.getCallingUid();
@@ -2802,7 +2955,9 @@
mLog.info("start lohs uid=% pid=%").c(uid).c(pid).flush();
// Permission requirements are different with/without custom config.
- if (customConfig == null) {
+ // From B, the custom config may from public API, check isCalledFromSystemApi
+ if (customConfig == null
+ || (Environment.isSdkAtLeastB() && !isCalledFromSystemApi)) {
if (enforceChangePermission(packageName) != MODE_ALLOWED) {
return LocalOnlyHotspotCallback.ERROR_GENERIC;
}
@@ -3218,18 +3373,18 @@
}
/**
- * Returns true if we should log the call to getSupportedFeatures.
+ * Returns true if we should log the call to isFeatureSupported.
*
- * Because of the way getSupportedFeatures is used in WifiManager, there are
+ * Because of the way isFeatureSupported is used in WifiManager, there are
* often clusters of several back-to-back calls; avoid repeated logging if
* the feature set has not changed and the time interval is short.
*/
- private boolean needToLogSupportedFeatures(long features) {
+ private boolean needToLogSupportedFeatures(BitSet features) {
if (mVerboseLoggingEnabled) {
long now = mClock.getElapsedSinceBootMillis();
synchronized (this) {
if (now > mLastLoggedSupportedFeaturesTimestamp + A_FEW_MILLISECONDS
- || features != mLastLoggedSupportedFeatures) {
+ || !features.equals(mLastLoggedSupportedFeatures)) {
mLastLoggedSupportedFeaturesTimestamp = now;
mLastLoggedSupportedFeatures = features;
return true;
@@ -3239,23 +3394,20 @@
return false;
}
private static final int A_FEW_MILLISECONDS = 250;
- private long mLastLoggedSupportedFeatures = -1;
+ private BitSet mLastLoggedSupportedFeatures = new BitSet();
private long mLastLoggedSupportedFeaturesTimestamp = 0;
- /**
- * see {@link android.net.wifi.WifiManager#getSupportedFeatures}
- */
@Override
- public long getSupportedFeatures() {
+ public boolean isFeatureSupported(int feature) {
enforceAccessPermission();
- long features = getSupportedFeaturesInternal();
- if (needToLogSupportedFeatures(features)) {
- mLog.info("getSupportedFeatures uid=% returns %")
+ BitSet supportedFeatures = getSupportedFeaturesInternal();
+ if (needToLogSupportedFeatures(supportedFeatures)) {
+ mLog.info("isFeatureSupported uid=% returns %")
.c(Binder.getCallingUid())
- .c(Long.toHexString(features))
+ .c(supportedFeatures.toString())
.flush();
}
- return features;
+ return supportedFeatures.get(feature);
}
@Override
@@ -3270,7 +3422,7 @@
.c(Binder.getCallingUid())
.flush();
}
- if ((getSupportedFeatures() & WifiManager.WIFI_FEATURE_LINK_LAYER_STATS) == 0) {
+ if (!isFeatureSupported(WifiManager.WIFI_FEATURE_LINK_LAYER_STATS)) {
try {
listener.onWifiActivityEnergyInfo(null);
} catch (RemoteException e) {
@@ -3448,6 +3600,7 @@
/**
* See {@link WifiManager#getPrivilegedConnectedNetwork()}
*/
+ @Override
public WifiConfiguration getPrivilegedConnectedNetwork(String packageName, String featureId,
Bundle extras) {
enforceReadCredentialPermission();
@@ -5615,7 +5768,7 @@
mContext, Settings.Global.STAY_ON_WHILE_PLUGGED_IN, 0));
pw.println("mInIdleMode " + mInIdleMode);
pw.println("mScanPending " + mScanPending);
- pw.println("SupportedFeatures:" + Long.toHexString(getSupportedFeaturesInternal()));
+ pw.println("SupportedFeatures: " + getSupportedFeaturesInternal());
pw.println("SettingsStore:");
mSettingsStore.dump(fd, pw, args);
mActiveModeWarden.dump(fd, pw, args);
@@ -5688,6 +5841,11 @@
}
pw.println();
mResourceCache.dump(pw);
+ if (mFeatureFlags.wepDisabledInApm()
+ && mWepNetworkUsageController != null) {
+ pw.println();
+ mWepNetworkUsageController.dump(fd, pw, args);
+ }
}
}, TAG + "#dump");
}
@@ -5755,21 +5913,23 @@
public void initializeMulticastFiltering() {
enforceMulticastChangePermission();
mLog.info("initializeMulticastFiltering uid=%").c(Binder.getCallingUid()).flush();
- mWifiMulticastLockManager.initializeFiltering();
+ mWifiMulticastLockManager.startFilteringMulticastPackets();
}
@Override
public void acquireMulticastLock(IBinder binder, String tag) {
enforceMulticastChangePermission();
- mLog.info("acquireMulticastLock uid=% tag=%").c(Binder.getCallingUid()).c(tag).flush();
- mWifiMulticastLockManager.acquireLock(binder, tag);
+ int uid = Binder.getCallingUid();
+ mLog.info("acquireMulticastLock uid=% tag=%").c(uid).c(tag).flush();
+ mWifiMulticastLockManager.acquireLock(uid, binder, tag);
}
@Override
- public void releaseMulticastLock(String tag) {
+ public void releaseMulticastLock(IBinder binder, String tag) {
enforceMulticastChangePermission();
- mLog.info("releaseMulticastLock uid=% tag=%").c(Binder.getCallingUid()).c(tag).flush();
- mWifiMulticastLockManager.releaseLock(tag);
+ int uid = Binder.getCallingUid();
+ mLog.info("releaseMulticastLock uid=% tag=%").c(uid).c(tag).flush();
+ mWifiMulticastLockManager.releaseLock(uid, binder, tag);
}
@Override
@@ -5868,6 +6028,10 @@
if (SdkLevel.isAtLeastV() && mWifiInjector.getWifiVoipDetector() != null) {
mWifiInjector.getWifiVoipDetector().enableVerboseLogging(mVerboseLoggingEnabled);
}
+ if (mFeatureFlags.wepDisabledInApm()
+ && mWepNetworkUsageController != null) {
+ mWepNetworkUsageController.enableVerboseLogging(mVerboseLoggingEnabled);
+ }
}
@Override
@@ -6246,7 +6410,7 @@
TAG + "#unregisterTrafficStateCallback");
}
- private long getSupportedFeaturesInternal() {
+ private BitSet getSupportedFeaturesInternal() {
return mActiveModeWarden.getSupportedFeatureSet();
}
@@ -7042,6 +7206,7 @@
/**
* See {@link WifiManager#registerScanResultsCallback(WifiManager.ScanResultsCallback)}
*/
+ @Override
public void registerScanResultsCallback(@NonNull IScanResultsCallback callback) {
if (callback == null) {
throw new IllegalArgumentException("callback must not be null");
@@ -7569,6 +7734,29 @@
return mSettingsStore.handleWifiScoringEnabled(enabled);
}
+ /**
+ * See {@link android.net.wifi.WifiManager#storeCapturedData(Executor, IntConsumer, int,
+ * booloan, long, long)}.
+ */
+ @Override
+ public void storeCapturedData(int triggerType, boolean isFullCapture,
+ long triggerStartTimeMillis, long triggerStopTimeMillis,
+ @NonNull IIntegerListener listener) {
+ if (listener == null) {
+ throw new IllegalArgumentException("listener should not be null");
+ }
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE, "WifiService");
+ mWifiThreadRunner.post(() -> {
+ try {
+ listener.onResult(mWifiMetrics.storeCapturedData(triggerType, isFullCapture,
+ triggerStartTimeMillis, triggerStopTimeMillis));
+ } catch (RemoteException e) {
+ Log.e(TAG, e.getMessage(), e);
+ }
+ }, TAG + "#storeCapturedData");
+ }
+
@VisibleForTesting
static boolean isValidBandForGetUsableChannels(@WifiScanner.WifiBand int band) {
switch (band) {
@@ -7741,21 +7929,20 @@
*/
@Override
public boolean isPnoSupported() {
+ boolean featureSetSupportsPno = isFeatureSupported(WifiManager.WIFI_FEATURE_PNO);
return mWifiGlobals.isSwPnoEnabled()
- || (mWifiGlobals.isBackgroundScanSupported()
- && (getSupportedFeatures() & WifiManager.WIFI_FEATURE_PNO) != 0);
+ || (mWifiGlobals.isBackgroundScanSupported() && featureSetSupportsPno);
}
private boolean isAggressiveRoamingModeSupported() {
- return (getSupportedFeatures() & WifiManager.WIFI_FEATURE_AGGRESSIVE_ROAMING_MODE_SUPPORT)
- != 0;
+ return isFeatureSupported(WifiManager.WIFI_FEATURE_AGGRESSIVE_ROAMING_MODE_SUPPORT);
}
/**
* @return true if this device supports Trust On First Use
*/
private boolean isTrustOnFirstUseSupported() {
- return (getSupportedFeatures() & WIFI_FEATURE_TRUST_ON_FIRST_USE) != 0;
+ return isFeatureSupported(WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE);
}
/**
@@ -8319,6 +8506,7 @@
* See {@link WifiManager#removeWifiLowLatencyLockListener(
* WifiManager.WifiLowLatencyLockListener)}
*/
+ @Override
public void removeWifiLowLatencyLockListener(IWifiLowLatencyLockListener listener) {
if (listener == null) {
throw new IllegalArgumentException();
@@ -8348,6 +8536,7 @@
* See {@link WifiManager#getMaxMloAssociationLinkCount(Executor, Consumer)}
*/
@RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Override
public void getMaxMloAssociationLinkCount(@NonNull IIntegerListener listener, Bundle extras) {
// SDK check.
if (!SdkLevel.isAtLeastU()) {
@@ -8379,6 +8568,7 @@
/**
* See {@link WifiManager#getMaxMloStrLinkCount(Executor, Consumer)}
*/
+ @Override
@RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
public void getMaxMloStrLinkCount(@NonNull IIntegerListener listener, Bundle extras) {
// SDK check.
@@ -8411,6 +8601,7 @@
/**
* See {@link WifiManager#getSupportedSimultaneousBandCombinations(Executor, Consumer)}.
*/
+ @Override
public void getSupportedSimultaneousBandCombinations(@NonNull IWifiBandsListener listener,
Bundle extras) {
// SDK check.
@@ -8488,12 +8679,12 @@
+ " is not allowed to set wifi web allowed by user");
}
mLog.info("setWepAllowed=% uid=%").c(isAllowed).c(callingUid).flush();
- mWifiThreadRunner.post(() -> {
- mSettingsConfigStore.put(WIFI_WEP_ALLOWED, isAllowed);
- handleWepAllowedChanged(isAllowed);
- }, TAG + "#setWepAllowed");
+ mSettingsConfigStore.put(WIFI_WEP_ALLOWED, isAllowed);
}
+ /**
+ * @deprecated Use mWepNetworkUsageController.handleWepAllowedChanged() instead.
+ */
private void handleWepAllowedChanged(boolean isAllowed) {
mWifiGlobals.setWepAllowed(isAllowed);
if (!isAllowed) {
@@ -8861,4 +9052,147 @@
}
}, TAG + "#queryD2dAllowedWhenInfraStaDisabled");
}
+
+ /**
+ * See {@link WifiManager#setAutojoinDisallowedSecurityTypes(int)}
+ * @param restrictions The autojoin restriction security types to be set.
+ * @throws SecurityException if the caller does not have permission.
+ * @throws IllegalArgumentException if the arguments are null or invalid
+ */
+ @Override
+ @RequiresApi(Build.VERSION_CODES.TIRAMISU)
+ public void setAutojoinDisallowedSecurityTypes(int restrictions, @NonNull Bundle extras) {
+ // SDK check.
+ if (!SdkLevel.isAtLeastT()) {
+ throw new UnsupportedOperationException("SDK level too old");
+ }
+ // Check null argument
+ if (extras == null) {
+ throw new IllegalArgumentException("extras cannot be null");
+ }
+ // Check invalid argument
+ if ((restrictions & (0x1 << WifiInfo.SECURITY_TYPE_OPEN)) == 0
+ && (restrictions & (0x1 << WifiInfo.SECURITY_TYPE_OWE)) != 0) {
+ throw new IllegalArgumentException("Restricting OWE but not OPEN is not allowed");
+ }
+ if ((restrictions & (0x1 << WifiInfo.SECURITY_TYPE_PSK)) == 0
+ && (restrictions & (0x1 << WifiInfo.SECURITY_TYPE_SAE)) != 0) {
+ throw new IllegalArgumentException("Restricting SAE but not PSK is not allowed");
+ }
+ if ((restrictions & (0x1 << WifiInfo.SECURITY_TYPE_EAP)) == 0
+ && (restrictions & (0x1 << WifiInfo.SECURITY_TYPE_EAP_WPA3_ENTERPRISE)) != 0) {
+ throw new IllegalArgumentException(
+ "Restricting EAP_WPA3_ENTERPRISE but not EAP is not allowed");
+ }
+ // Permission check.
+ int uid = Binder.getCallingUid();
+ if (!mWifiPermissionsUtil.checkManageWifiNetworkSelectionPermission(uid)
+ && !mWifiPermissionsUtil.checkNetworkSettingsPermission(uid)) {
+ throw new SecurityException(
+ "Uid=" + uid + " is not allowed to set AutoJoinRestrictionSecurityTypes");
+ }
+ if (mVerboseLoggingEnabled) {
+ mLog.info("setAutojoinDisallowedSecurityTypes uid=% Package Name=% restrictions=%")
+ .c(uid).c(getPackageName(extras)).c(restrictions).flush();
+ }
+ mWifiThreadRunner.post(() -> {
+ mWifiConnectivityManager.setAutojoinDisallowedSecurityTypes(restrictions);
+ }, TAG + "#setAutojoinDisallowedSecurityTypes");
+ }
+
+ /**
+ * See {@link WifiManager#getAutojoinDisallowedSecurityTypes(Executor, Consumer)}
+ */
+ @Override
+ @RequiresApi(Build.VERSION_CODES.TIRAMISU)
+ public void getAutojoinDisallowedSecurityTypes(@NonNull IIntegerListener listener,
+ @NonNull Bundle extras) {
+ // SDK check.
+ if (!SdkLevel.isAtLeastT()) {
+ throw new UnsupportedOperationException("SDK level too old");
+ }
+ // Argument check
+ if (listener == null) {
+ throw new IllegalArgumentException("listener cannot be null");
+ }
+ if (extras == null) {
+ throw new IllegalArgumentException("extras cannot be null");
+ }
+ // Permission check.
+ int uid = Binder.getCallingUid();
+ if (!mWifiPermissionsUtil.checkManageWifiNetworkSelectionPermission(uid)
+ && !mWifiPermissionsUtil.checkNetworkSettingsPermission(uid)) {
+ throw new SecurityException(
+ "Uid=" + uid + " is not allowed to get AutoJoinRestrictionSecurityTypes");
+ }
+ if (mVerboseLoggingEnabled) {
+ mLog.info("getAutojoinDisallowedSecurityTypes: Uid=% Package Name=%").c(
+ Binder.getCallingUid()).c(getPackageName(extras)).flush();
+ }
+
+ mWifiThreadRunner.post(() -> {
+ try {
+ listener.onResult(mWifiConnectivityManager.getAutojoinDisallowedSecurityTypes());
+ } catch (RemoteException e) {
+ Log.e(TAG, e.getMessage(), e);
+ }
+ }, TAG + "#getAutojoinDisallowedSecurityTypes");
+ }
+
+ @Override
+ public void disallowCurrentSuggestedNetwork(@NonNull BlockingOption option,
+ @NonNull String packageName) {
+ Objects.requireNonNull(option, "blockingOption cannot be null");
+ int callingUid = Binder.getCallingUid();
+ mWifiPermissionsUtil.checkPackage(callingUid, packageName);
+ if (enforceChangePermission(packageName) != MODE_ALLOWED) {
+ throw new SecurityException("Caller does not hold CHANGE_WIFI_STATE permission");
+ }
+ if (mVerboseLoggingEnabled) {
+ mLog.info("disallowCurrentSuggestedNetwork: Uid=% Package Name=%").c(
+ callingUid).c(option.toString()).flush();
+ }
+ if (mActiveModeWarden.getWifiState() != WIFI_STATE_ENABLED) {
+ return;
+ }
+ WifiInfo info = mActiveModeWarden.getConnectionInfo();
+ if (!packageName.equals(info.getRequestingPackageName())) {
+ return;
+ }
+ mWifiThreadRunner.post(
+ () -> mActiveModeWarden.getPrimaryClientModeManager().blockNetwork(option),
+ "disallowCurrentSuggestedNetwork");
+ }
+ /**
+ * See {@link WifiManager#isUsdSubscriberSupported()}
+ */
+ @Override
+ public boolean isUsdSubscriberSupported() {
+ if (!Environment.isSdkAtLeastB()) {
+ throw new UnsupportedOperationException("SDK level too old");
+ }
+ int uid = getMockableCallingUid();
+ if (!mWifiPermissionsUtil.checkManageWifiNetworkSelectionPermission(uid)) {
+ throw new SecurityException("App not allowed to use USD (uid = " + uid + ")");
+ }
+ // USDSubscriber is not supported.
+ return false;
+ }
+
+ /**
+ * See {@link WifiManager#isUsdPublisherSupported()}
+ */
+ @Override
+ public boolean isUsdPublisherSupported() {
+ if (!Environment.isSdkAtLeastB()) {
+ throw new UnsupportedOperationException("SDK level too old");
+ }
+ int uid = getMockableCallingUid();
+ if (!mWifiPermissionsUtil.checkManageWifiNetworkSelectionPermission(uid)) {
+ throw new SecurityException("App not allowed to use USD (uid = " + uid + ")");
+ }
+ // USDPublisher is not supported.
+ return false;
+ }
+
}
diff --git a/service/java/com/android/server/wifi/WifiSettingsConfigStore.java b/service/java/com/android/server/wifi/WifiSettingsConfigStore.java
index a5ba58d..1aab172 100644
--- a/service/java/com/android/server/wifi/WifiSettingsConfigStore.java
+++ b/service/java/com/android/server/wifi/WifiSettingsConfigStore.java
@@ -136,6 +136,12 @@
new Key<>("wifi_default_country_code", WifiCountryCode.getOemDefaultCountryCode());
/**
+ * Store the supported P2P features.
+ */
+ public static final Key<Long> WIFI_P2P_SUPPORTED_FEATURES =
+ new Key<>("wifi_p2p_supported_features", 0L);
+
+ /**
* Store the supported features retrieved from WiFi HAL and Supplicant HAL. Note that this
* value is deprecated and is replaced by {@link #WIFI_NATIVE_EXTENDED_SUPPORTED_FEATURES}
*/
diff --git a/service/java/com/android/server/wifi/WifiShellCommand.java b/service/java/com/android/server/wifi/WifiShellCommand.java
index 1439406..fe23f18 100644
--- a/service/java/com/android/server/wifi/WifiShellCommand.java
+++ b/service/java/com/android/server/wifi/WifiShellCommand.java
@@ -25,13 +25,13 @@
import static android.net.wifi.WifiManager.ACTION_REMOVE_SUGGESTION_DISCONNECT;
import static android.net.wifi.WifiManager.ACTION_REMOVE_SUGGESTION_LINGER;
import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.REQUEST_REGISTERED;
+import static android.net.wifi.WifiManager.ROAMING_MODE_AGGRESSIVE;
+import static android.net.wifi.WifiManager.ROAMING_MODE_NONE;
+import static android.net.wifi.WifiManager.ROAMING_MODE_NORMAL;
import static android.net.wifi.WifiManager.VERBOSE_LOGGING_LEVEL_DISABLED;
import static android.net.wifi.WifiManager.VERBOSE_LOGGING_LEVEL_WIFI_AWARE_ENABLED_ONLY;
import static android.net.wifi.WifiManager.WIFI_STATE_DISABLED;
import static android.net.wifi.WifiManager.WIFI_STATE_ENABLED;
-import static android.net.wifi.WifiManager.ROAMING_MODE_NONE;
-import static android.net.wifi.WifiManager.ROAMING_MODE_NORMAL;
-import static android.net.wifi.WifiManager.ROAMING_MODE_AGGRESSIVE;
import static com.android.server.wifi.HalDeviceManager.HDM_CREATE_IFACE_AP;
import static com.android.server.wifi.HalDeviceManager.HDM_CREATE_IFACE_AP_BRIDGE;
@@ -275,6 +275,11 @@
@Override
public void onBlockedClientConnecting(WifiClient client, int reason) {
}
+
+ @Override
+ public void onClientsDisconnected(SoftApInfo info, List<WifiClient> clients) {
+ mPrintWriter.println("onClientsDisconnected, info: " + info + ", clients: " + clients);
+ }
}
/**
@@ -903,7 +908,7 @@
mWifiService.registerLocalOnlyHotspotSoftApCallback(softApCallback, extras);
if (REQUEST_REGISTERED != mWifiService.startLocalOnlyHotspot(
lohsCallback, SHELL_PACKAGE_NAME, null /* featureId */,
- config, extras)) {
+ config, extras, false)) {
pw.println("Lohs failed to start. Please check config parameters");
}
// Wait for lohs to start and complete callback
@@ -1002,14 +1007,10 @@
if (ApConfigUtil.isWpa3SaeSupported(mContext)) {
pw.println("wifi_softap_wpa3_sae_supported");
}
- if ((mWifiService.getSupportedFeatures()
- & WifiManager.WIFI_FEATURE_BRIDGED_AP)
- == WifiManager.WIFI_FEATURE_BRIDGED_AP) {
+ if (mWifiService.isFeatureSupported(WifiManager.WIFI_FEATURE_BRIDGED_AP)) {
pw.println("wifi_softap_bridged_ap_supported");
}
- if ((mWifiService.getSupportedFeatures()
- & WifiManager.WIFI_FEATURE_STA_BRIDGED_AP)
- == WifiManager.WIFI_FEATURE_STA_BRIDGED_AP) {
+ if (mWifiService.isFeatureSupported(WifiManager.WIFI_FEATURE_STA_BRIDGED_AP)) {
pw.println("wifi_softap_bridged_ap_with_sta_supported");
}
return 0;
@@ -1509,7 +1510,7 @@
String neutralButtonText = null;
String dialogOption = getNextOption();
boolean simpleTimeoutSpecified = false;
- long simpleTimeoutMs = 0;
+ long simpleTimeoutMs = 15 * 1000;
boolean useLegacy = false;
while (dialogOption != null) {
switch (dialogOption) {
@@ -1595,53 +1596,47 @@
wifiEnableRequestCallback,
mWifiThreadRunner);
}
- if (simpleTimeoutSpecified) {
- simpleDialogHandle.launchDialog(simpleTimeoutMs);
- pw.println("Launched dialog with " + simpleTimeoutMs + " millisecond"
- + " timeout. Waiting for user response...");
- pw.flush();
- String dialogResponse = simpleQueue.take();
- if (dialogResponse == null) {
- pw.println("No response received.");
- } else {
- pw.println(dialogResponse);
- }
+ simpleDialogHandle.launchDialog();
+ pw.println("Launched dialog. Waiting up to " + simpleTimeoutMs + " ms for"
+ + " user response before dismissing...");
+ String simpleDialogResponse = simpleQueue.poll(simpleTimeoutMs,
+ TimeUnit.MILLISECONDS);
+ if (simpleDialogResponse == null) {
+ pw.println("No response received. Dismissing dialog.");
+ simpleDialogHandle.dismissDialog();
} else {
- simpleDialogHandle.launchDialog();
- pw.println("Launched dialog. Waiting up to 15 seconds for user response"
- + " before dismissing...");
- pw.flush();
- String dialogResponse = simpleQueue.poll(15, TimeUnit.SECONDS);
- if (dialogResponse == null) {
- pw.println("No response received. Dismissing dialog.");
- simpleDialogHandle.dismissDialog();
- } else {
- pw.println(dialogResponse);
- }
+ pw.println(simpleDialogResponse);
}
return 0;
case "launch-dialog-p2p-invitation-sent": {
int displayId = Display.DEFAULT_DISPLAY;
String deviceName = getNextArgRequired();
- String displayPin = getNextArgRequired();
String cmdOption = getNextOption();
- if (cmdOption != null && cmdOption.equals("-i")) {
- String displayIdStr = getNextArgRequired();
- try {
- displayId = Integer.parseInt(displayIdStr);
- } catch (NumberFormatException e) {
- pw.println("Invalid <display-id> argument to "
- + "'launch-dialog-p2p-invitation-sent' "
- + "- must be an integer: "
- + displayIdStr);
- return -1;
+ String displayPin = null;
+ while (cmdOption != null) {
+ if (cmdOption.equals("-d")) {
+ displayPin = getNextArgRequired();
+ } else if (cmdOption.equals("-i")) {
+ String displayIdStr = getNextArgRequired();
+ try {
+ displayId = Integer.parseInt(displayIdStr);
+ } catch (NumberFormatException e) {
+ pw.println("Invalid <display-id> argument to "
+ + "'launch-dialog-p2p-invitation-sent' "
+ + "- must be an integer: "
+ + displayIdStr);
+ return -1;
+ }
+ DisplayManager dm = mContext.getSystemService(DisplayManager.class);
+ Display[] displays = dm.getDisplays();
+ for (Display display : displays) {
+ pw.println("Display: id=" + display.getDisplayId() + ", info="
+ + display.getDeviceProductInfo());
+ }
+ } else {
+ pw.println("Ignoring unknown option " + cmdOption);
}
- DisplayManager dm = mContext.getSystemService(DisplayManager.class);
- Display[] displays = dm.getDisplays();
- for (Display display : displays) {
- pw.println("Display: id=" + display.getDisplayId() + ", info="
- + display.getDeviceProductInfo());
- }
+ cmdOption = getNextOption();
}
mWifiDialogManager.createP2pInvitationSentDialog(deviceName, displayPin,
displayId).launchDialog();
@@ -1655,7 +1650,7 @@
String pinOption = getNextOption();
int displayId = Display.DEFAULT_DISPLAY;
boolean p2pInvRecTimeoutSpecified = false;
- long p2pInvRecTimeout = 0;
+ int p2pInvRecTimeout = 0;
while (pinOption != null) {
if (pinOption.equals("-p")) {
isPinRequested = true;
@@ -1705,11 +1700,12 @@
deviceName,
isPinRequested,
displayPin,
+ p2pInvRecTimeout,
displayId,
callback,
mWifiThreadRunner);
+ p2pInvitationReceivedDialogHandle.launchDialog();
if (p2pInvRecTimeoutSpecified) {
- p2pInvitationReceivedDialogHandle.launchDialog(p2pInvRecTimeout);
pw.println("Launched dialog with " + p2pInvRecTimeout + " millisecond"
+ " timeout. Waiting for user response...");
pw.flush();
@@ -1720,7 +1716,6 @@
pw.println(dialogResponse);
}
} else {
- p2pInvitationReceivedDialogHandle.launchDialog();
pw.println("Launched dialog. Waiting up to 15 seconds for user response"
+ " before dismissing...");
pw.flush();
@@ -3055,7 +3050,8 @@
pw.println(" -x - Neutral Button Text");
pw.println(" -c - Optional timeout in milliseconds");
pw.println(" -s - Use the legacy dialog implementation on the system process");
- pw.println(" launch-dialog-p2p-invitation-sent <device_name> <pin> [-i <display_id>]");
+ pw.println(" launch-dialog-p2p-invitation-sent <device_name> [-d <pin>]"
+ + " [-i <display_id>]");
pw.println(" Launches a P2P Invitation Sent dialog.");
pw.println(" <device_name> - Name of the device the invitation was sent to");
pw.println(" <pin> - PIN for the invited device to input");
diff --git a/service/java/com/android/server/wifi/WifiVendorHal.java b/service/java/com/android/server/wifi/WifiVendorHal.java
index 9d2f1d5..13b659f 100644
--- a/service/java/com/android/server/wifi/WifiVendorHal.java
+++ b/service/java/com/android/server/wifi/WifiVendorHal.java
@@ -18,7 +18,6 @@
import static com.android.server.wifi.HalDeviceManager.HDM_CREATE_IFACE_AP;
import static com.android.server.wifi.HalDeviceManager.HDM_CREATE_IFACE_AP_BRIDGE;
import static com.android.server.wifi.HalDeviceManager.HDM_CREATE_IFACE_STA;
-import static com.android.server.wifi.util.GeneralUtil.getCapabilityIndex;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -380,10 +379,10 @@
}
}
- private long getNecessaryCapabilitiesForSoftApMode(@SoftApConfiguration.BandType int band) {
- long caps = HalDeviceManager.CHIP_CAPABILITY_ANY;
+ private BitSet getNecessaryCapabilitiesForSoftApMode(@SoftApConfiguration.BandType int band) {
+ BitSet caps = new BitSet();
if ((band & SoftApConfiguration.BAND_60GHZ) != 0) {
- caps |= WifiManager.WIFI_FEATURE_INFRA_60G;
+ caps.set(WifiManager.WIFI_FEATURE_INFRA_60G);
}
return caps;
}
@@ -795,7 +794,7 @@
final PackageManager pm = sContext.getPackageManager();
for (Pair pair: sSystemFeatureCapabilityTranslation) {
if (pm.hasSystemFeature((String) pair.second)) {
- featureSet.set(getCapabilityIndex((long) pair.first));
+ featureSet.set((int) pair.first);
}
}
enter("System feature set: %").c(featureSet.toString()).flush();
@@ -898,28 +897,27 @@
featureSet.or(iface.getCapabilities());
if (mHalDeviceManager.is24g5gDbsSupported(iface)
|| mHalDeviceManager.is5g6gDbsSupported(iface)) {
- featureSet.set(
- getCapabilityIndex(WifiManager.WIFI_FEATURE_DUAL_BAND_SIMULTANEOUS));
+ featureSet.set(WifiManager.WIFI_FEATURE_DUAL_BAND_SIMULTANEOUS);
}
}
}
if (mWifiGlobals.isWpa3SaeH2eSupported()) {
- featureSet.set(getCapabilityIndex(WifiManager.WIFI_FEATURE_SAE_H2E));
+ featureSet.set(WifiManager.WIFI_FEATURE_SAE_H2E);
}
Set<Integer> supportedIfaceTypes = mHalDeviceManager.getSupportedIfaceTypes();
if (supportedIfaceTypes.contains(WifiChip.IFACE_TYPE_STA)) {
- featureSet.set(getCapabilityIndex(WifiManager.WIFI_FEATURE_INFRA));
+ featureSet.set(WifiManager.WIFI_FEATURE_INFRA);
}
if (supportedIfaceTypes.contains(WifiChip.IFACE_TYPE_AP)) {
- featureSet.set(getCapabilityIndex(WifiManager.WIFI_FEATURE_MOBILE_HOTSPOT));
+ featureSet.set(WifiManager.WIFI_FEATURE_MOBILE_HOTSPOT);
}
if (supportedIfaceTypes.contains(WifiChip.IFACE_TYPE_P2P)) {
- featureSet.set(getCapabilityIndex(WifiManager.WIFI_FEATURE_P2P));
+ featureSet.set(WifiManager.WIFI_FEATURE_P2P);
}
if (supportedIfaceTypes.contains(WifiChip.IFACE_TYPE_NAN)) {
- featureSet.set(getCapabilityIndex(WifiManager.WIFI_FEATURE_AWARE));
+ featureSet.set(WifiManager.WIFI_FEATURE_AWARE);
}
return featureSet;
diff --git a/service/java/com/android/server/wifi/WifiVoipDetector.java b/service/java/com/android/server/wifi/WifiVoipDetector.java
index 5754bc3..e8c274b 100644
--- a/service/java/com/android/server/wifi/WifiVoipDetector.java
+++ b/service/java/com/android/server/wifi/WifiVoipDetector.java
@@ -181,6 +181,7 @@
log = "Failed to set Voip Mode to " + newMode + " (maybe not supported?)";
} else {
mCurrentMode = newMode;
+ mWifiInjector.getWifiMetrics().setVoipMode(mCurrentMode);
}
mLocalLog.log(log);
if (mVerboseLoggingEnabled) {
diff --git a/service/java/com/android/server/wifi/aware/Capabilities.java b/service/java/com/android/server/wifi/aware/Capabilities.java
index b47eca2..59c78aa 100644
--- a/service/java/com/android/server/wifi/aware/Capabilities.java
+++ b/service/java/com/android/server/wifi/aware/Capabilities.java
@@ -50,6 +50,9 @@
public boolean isSuspensionSupported;
public boolean is6gSupported;
public boolean isHeSupported;
+ public boolean isPeriodicRangingSupported;
+ public int maxSupportedRangingPktBandWidth;
+ public int maxSupportedRxChains;
/**
* Converts the internal capabilities to a parcelable & potentially app-facing
@@ -75,6 +78,10 @@
bundle.putBoolean(Characteristics.KEY_SUPPORT_NAN_PAIRING, isNanPairingSupported);
bundle.putBoolean(Characteristics.KEY_SUPPORT_SUSPENSION,
deviceConfigFacade.isAwareSuspensionEnabled() && isSuspensionSupported);
+ bundle.putBoolean(Characteristics.KEY_SUPPORT_PERIODIC_RANGING, isPeriodicRangingSupported);
+ bundle.putInt(Characteristics.KEY_MAX_SUPPORTED_RANGING_PKT_BANDWIDTH,
+ maxSupportedRangingPktBandWidth);
+ bundle.putInt(Characteristics.KEY_MAX_SUPPORTED_RX_CHAINS, maxSupportedRxChains);
return new Characteristics(bundle);
}
@@ -97,6 +104,9 @@
j.put("isSetClusterIdSupported", isSetClusterIdSupported);
j.put("isNanPairingSupported", isNanPairingSupported);
j.put("isSuspensionSupported", isSuspensionSupported);
+ j.put("isPeriodicRangingSupported", isPeriodicRangingSupported);
+ j.put("maxSupportedRangingPktBandWidth", maxSupportedRangingPktBandWidth);
+ j.put("maxSupportedRxChains", maxSupportedRxChains);
return j;
}
@@ -142,6 +152,12 @@
+ is6gSupported
+ ", isHeSupported="
+ isHeSupported
+ + ", isPeriodicRangingSupported="
+ + isPeriodicRangingSupported
+ + ", maxSupportedRangingPktBandWidth="
+ + maxSupportedRangingPktBandWidth
+ + ",maxSupportedRxChains="
+ + maxSupportedRxChains
+ "]";
}
}
diff --git a/service/java/com/android/server/wifi/aware/WifiAwareDiscoverySessionState.java b/service/java/com/android/server/wifi/aware/WifiAwareDiscoverySessionState.java
index e5fdeed..503e56a 100644
--- a/service/java/com/android/server/wifi/aware/WifiAwareDiscoverySessionState.java
+++ b/service/java/com/android/server/wifi/aware/WifiAwareDiscoverySessionState.java
@@ -29,9 +29,11 @@
import android.net.wifi.WifiScanner;
import android.net.wifi.aware.AwarePairingConfig;
import android.net.wifi.aware.IWifiAwareDiscoverySessionCallback;
+import android.net.wifi.aware.PeerHandle;
import android.net.wifi.aware.PublishConfig;
import android.net.wifi.aware.SubscribeConfig;
import android.net.wifi.aware.WifiAwareManager;
+import android.net.wifi.rtt.RangingResult;
import android.net.wifi.util.HexEncoding;
import android.os.RemoteException;
import android.os.SystemClock;
@@ -42,6 +44,7 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -75,10 +78,12 @@
PeerInfo(int instanceId, byte[] mac) {
mInstanceId = instanceId;
mMac = mac;
+ mPeerHandle = new PeerHandle(instanceId);
}
int mInstanceId;
byte[] mMac;
+ PeerHandle mPeerHandle;
@Override
public String toString() {
@@ -688,6 +693,29 @@
}
/**
+ * Callback from HAL when ranging results are available
+ */
+ public void onRangingResultsReceived(List<RangingResult> rangingResults) {
+ List<RangingResult> validResults = new ArrayList<>();
+ try {
+ for (RangingResult rangingResult : rangingResults) {
+ PeerHandle peerHandle =
+ getPeerHandleFromPeerMac(rangingResult.getMacAddress().toByteArray());
+ if (peerHandle == null) {
+ Log.e(TAG, "Could not find Peer Handle for the ranging result");
+ continue;
+ }
+ RangingResult result = new RangingResult.Builder(
+ rangingResult).setPeerHandle(peerHandle).build();
+ validResults.add(result);
+ }
+ mCallback.onRangingResultsReceived(validResults);
+ } catch (RemoteException e) {
+ Log.w(TAG, "onRangingResultsReceived: RemoteException (FYI): " + e);
+ }
+ }
+
+ /**
* Event that receive the bootstrapping request finished
*/
public void onBootStrappingConfirmReceived(int peerId, boolean accept, int method) {
@@ -720,6 +748,19 @@
}
/**
+ * Get the peerHandle assigned by the framework from the peer mac.
+ */
+ public PeerHandle getPeerHandleFromPeerMac(byte[] peerMac) {
+ for (int i = 0; i < mPeerInfoByRequestorInstanceId.size(); ++i) {
+ PeerInfo peerInfo = mPeerInfoByRequestorInstanceId.valueAt(i);
+ if (Arrays.equals(peerMac, peerInfo.mMac)) {
+ return peerInfo.mPeerHandle;
+ }
+ }
+ return null;
+ }
+
+ /**
* Dump the internal state of the class.
*/
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
diff --git a/service/java/com/android/server/wifi/aware/WifiAwareNativeCallback.java b/service/java/com/android/server/wifi/aware/WifiAwareNativeCallback.java
index d6f02bc..2f4b082 100644
--- a/service/java/com/android/server/wifi/aware/WifiAwareNativeCallback.java
+++ b/service/java/com/android/server/wifi/aware/WifiAwareNativeCallback.java
@@ -21,6 +21,7 @@
import android.net.wifi.aware.AwarePairingConfig;
import android.net.wifi.aware.IdentityChangedListener;
import android.net.wifi.aware.WifiAwareChannelInfo;
+import android.net.wifi.rtt.RangingResult;
import android.util.Log;
import android.util.SparseArray;
import android.util.SparseIntArray;
@@ -161,6 +162,11 @@
}
@Override
+ public void notifyRangingResults(ArrayList<RangingResult> rangingResults, byte sessionId) {
+ mWifiAwareStateManager.onRangingResults(rangingResults, sessionId);
+ }
+
+ @Override
public void notifyEnableResponse(short id, int status) {
if (status == NanStatusCode.SUCCESS
|| status == NanStatusCode.ALREADY_ENABLED) {
diff --git a/service/java/com/android/server/wifi/aware/WifiAwareServiceImpl.java b/service/java/com/android/server/wifi/aware/WifiAwareServiceImpl.java
index 468b8b8..a44d90a 100644
--- a/service/java/com/android/server/wifi/aware/WifiAwareServiceImpl.java
+++ b/service/java/com/android/server/wifi/aware/WifiAwareServiceImpl.java
@@ -43,7 +43,6 @@
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
-import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
@@ -89,7 +88,7 @@
private WifiAwareNativeApi mWifiAwareNativeApi;
private WifiAwareNativeCallback mWifiAwareNativeCallback;
private WifiAwareShellCommand mShellCommand;
- private Handler mHandler;
+ private RunnerHandler mHandler;
private final Object mLock = new Object();
private final SparseArray<IBinder.DeathRecipient> mDeathRecipientsByClientId =
@@ -160,6 +159,7 @@
mWifiAwareNativeManager.enableVerboseLogging(mVerboseLoggingEnabled,
mVerboseLoggingEnabled);
mWifiAwareNativeApi.enableVerboseLogging(mVerboseLoggingEnabled, vDbg);
+ mHandler.enableVerboseLogging(mVerboseLoggingEnabled);
}
/**
diff --git a/service/java/com/android/server/wifi/aware/WifiAwareStateManager.java b/service/java/com/android/server/wifi/aware/WifiAwareStateManager.java
index 3df13e8..1904747 100644
--- a/service/java/com/android/server/wifi/aware/WifiAwareStateManager.java
+++ b/service/java/com/android/server/wifi/aware/WifiAwareStateManager.java
@@ -89,6 +89,7 @@
import android.net.wifi.aware.WifiAwareDataPathSecurityConfig;
import android.net.wifi.aware.WifiAwareManager;
import android.net.wifi.aware.WifiAwareNetworkSpecifier;
+import android.net.wifi.rtt.RangingResult;
import android.net.wifi.util.HexEncoding;
import android.os.Bundle;
import android.os.Handler;
@@ -281,6 +282,7 @@
private static final int NOTIFICATION_TYPE_ON_BOOTSTRAPPING_REQUEST = 316;
private static final int NOTIFICATION_TYPE_ON_BOOTSTRAPPING_CONFIRM = 317;
private static final int NOTIFICATION_TYPE_ON_SUSPENSION_MODE_CHANGED = 318;
+ private static final int NOTIFICATION_TYPE_RANGING_RESULTS = 319;
private static final SparseArray<String> sSmToString = MessageUtils.findMessageNames(
new Class[]{WifiAwareStateManager.class},
@@ -717,41 +719,39 @@
}
if (action.equals(Intent.ACTION_SCREEN_ON)
|| action.equals(Intent.ACTION_SCREEN_OFF)) {
- reconfigure();
+ mHandler.post(() -> reconfigure());
}
if (action.equals(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED)) {
- reconfigure();
+ mHandler.post(() -> reconfigure());
}
}
},
- intentFilter,
- null,
- mHandler);
+ intentFilter);
intentFilter = new IntentFilter();
intentFilter.addAction(LocationManager.MODE_CHANGED_ACTION);
- mContext.registerReceiver(
+ mContext.registerReceiverForAllUsers(
new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (mVerboseLoggingEnabled) {
Log.v(TAG, "onReceive: MODE_CHANGED_ACTION: intent=" + intent);
}
- if (mWifiPermissionsUtil.isLocationModeEnabled()) {
- enableUsage();
- } else {
- if (SdkLevel.isAtLeastT()) {
- handleLocationModeDisabled();
+ mHandler.post(() -> {
+ if (mWifiPermissionsUtil.isLocationModeEnabled()) {
+ enableUsage();
} else {
- disableUsage(false);
+ if (SdkLevel.isAtLeastT()) {
+ handleLocationModeDisabled();
+ } else {
+ disableUsage(false);
+ }
}
- }
+ });
}
},
- intentFilter,
- null,
- mHandler);
+ intentFilter, null, null);
intentFilter = new IntentFilter();
intentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
@@ -767,18 +767,18 @@
WifiManager.EXTRA_WIFI_STATE,
WifiManager.WIFI_STATE_UNKNOWN)
== WifiManager.WIFI_STATE_ENABLED;
- if (isEnabled) {
- enableUsage();
- } else {
- if (!isD2dAllowedWhenStaDisabled()) {
- disableUsage(false);
+ mHandler.post(() -> {
+ if (isEnabled) {
+ enableUsage();
+ } else {
+ if (!isD2dAllowedWhenStaDisabled()) {
+ disableUsage(false);
+ }
}
- }
+ });
}
},
- intentFilter,
- null,
- mHandler);
+ intentFilter);
mSettingsConfigStore.registerChangeListener(D2D_ALLOWED_WHEN_INFRA_STA_DISABLED,
(key, value) -> {
// Check setting & wifi enabled status only when feature is supported.
@@ -1721,6 +1721,18 @@
}
/**
+ * Place a callback request on the state machine queue: update vendor
+ * capabilities of the Aware stack.
+ */
+ public void onRangingResults(List<RangingResult> rangingResults, int sessionId) {
+ Message msg = mSm.obtainMessage(MESSAGE_TYPE_NOTIFICATION);
+ msg.arg1 = NOTIFICATION_TYPE_RANGING_RESULTS;
+ msg.obj = rangingResults;
+ msg.getData().putInt(MESSAGE_BUNDLE_KEY_SESSION_ID, sessionId);
+ mSm.sendMessage(msg);
+ }
+
+ /**
* Places a callback request on the state machine queue: data-path interface creation command
* completed.
*/
@@ -2822,6 +2834,11 @@
onSuspensionModeChangedLocal(isSuspended);
break;
}
+ case NOTIFICATION_TYPE_RANGING_RESULTS: {
+ int sessionId = msg.getData().getInt(MESSAGE_BUNDLE_KEY_SESSION_ID);
+ onRangingResultsReceivedLocal((List<RangingResult>) msg.obj, sessionId);
+ break;
+ }
default:
Log.wtf(TAG, "processNotification: this isn't a NOTIFICATION -- msg=" + msg);
}
@@ -5175,6 +5192,21 @@
mAwareMetrics.recordEnableAware();
}
+ private void onRangingResultsReceivedLocal(List<RangingResult> rangingResults,
+ int pubSubId) {
+ if (mVdbg) {
+ Log.v(TAG,
+ "onRangingResultsReceivedNotification: pubSubId=" + pubSubId);
+ }
+ Pair<WifiAwareClientState, WifiAwareDiscoverySessionState> data =
+ getClientSessionForPubSubId(pubSubId);
+ if (data == null) {
+ Log.e(TAG, "onRangingResultsReceivedLocal: no session found for pubSubId=" + pubSubId);
+ return;
+ }
+ data.second.onRangingResultsReceived(rangingResults);
+ }
+
private void onClusterChangeLocal(int clusterEventType, byte[] clusterId) {
mClusterId = clusterId;
mClusterEventType = clusterEventType;
diff --git a/service/java/com/android/server/wifi/coex/CoexUtils.java b/service/java/com/android/server/wifi/coex/CoexUtils.java
index 786fe78..35d988b 100644
--- a/service/java/com/android/server/wifi/coex/CoexUtils.java
+++ b/service/java/com/android/server/wifi/coex/CoexUtils.java
@@ -650,8 +650,9 @@
public CoexCellChannel(@Annotation.NetworkType int rat, int band,
int downlinkFreqKhz, int downlinkBandwidthKhz,
int uplinkFreqKhz, int uplinkBandwidthKhz, int subId) {
- if (band < 1 || band > 261) {
- Log.wtf(TAG, "Band is " + band + " but should be a value from 1 to 261");
+ if ((band < 1 || band > 261) && band != PhysicalChannelConfig.BAND_UNKNOWN) {
+ Log.wtf(TAG, "Band is " + band + " but should be a value from 1 to 261"
+ + " or PhysicalChannelConfig.BAND_UNKNOWN");
}
if (downlinkFreqKhz < 0 && downlinkFreqKhz != PhysicalChannelConfig.FREQUENCY_UNKNOWN) {
Log.wtf(TAG, "Downlink frequency is " + downlinkFreqKhz + " but should be >= 0"
diff --git a/service/java/com/android/server/wifi/hal/IWifiChip.java b/service/java/com/android/server/wifi/hal/IWifiChip.java
index 7c8235c..b421124 100644
--- a/service/java/com/android/server/wifi/hal/IWifiChip.java
+++ b/service/java/com/android/server/wifi/hal/IWifiChip.java
@@ -58,10 +58,14 @@
*
* @param vendorData List of {@link OuiKeyedData} containing vendor-provided
* configuration data. Empty list indicates no vendor data.
+ * @param isUsingMultiLinkOperation whether the bridged AP is using multi-links
+ * operation soft ap.
+ *
* @return {@link WifiApIface} object, or null if a failure occurred.
*/
@Nullable
- WifiApIface createBridgedApIface(@NonNull List<OuiKeyedData> vendorData);
+ WifiApIface createBridgedApIface(@NonNull List<OuiKeyedData> vendorData,
+ boolean isUsingMultiLinkOperation);
/**
* Create a NAN interface on the chip.
diff --git a/service/java/com/android/server/wifi/hal/WifiChip.java b/service/java/com/android/server/wifi/hal/WifiChip.java
index 557573f..45c6de2 100644
--- a/service/java/com/android/server/wifi/hal/WifiChip.java
+++ b/service/java/com/android/server/wifi/hal/WifiChip.java
@@ -556,16 +556,17 @@
}
/**
- * See comments for {@link IWifiChip#createBridgedApIface(List)}
+ * See comments for {@link IWifiChip#createBridgedApIface(List, boolean)}
*/
@Nullable
- public WifiApIface createBridgedApIface(@NonNull List<OuiKeyedData> vendorData) {
+ public WifiApIface createBridgedApIface(@NonNull List<OuiKeyedData> vendorData,
+ boolean isUsingMultiLinkOperation) {
if (vendorData == null) {
Log.e(TAG, "createBridgedApIface received null vendorData");
return null;
}
return validateAndCall("createBridgedApIface", null,
- () -> mWifiChip.createBridgedApIface(vendorData));
+ () -> mWifiChip.createBridgedApIface(vendorData, isUsingMultiLinkOperation));
}
/**
diff --git a/service/java/com/android/server/wifi/hal/WifiChipAidlImpl.java b/service/java/com/android/server/wifi/hal/WifiChipAidlImpl.java
index 6ce53df..d63d1e1 100644
--- a/service/java/com/android/server/wifi/hal/WifiChipAidlImpl.java
+++ b/service/java/com/android/server/wifi/hal/WifiChipAidlImpl.java
@@ -23,8 +23,6 @@
import static android.hardware.wifi.WifiChannelWidthInMhz.WIDTH_80P80;
import static android.net.wifi.CoexUnsafeChannel.POWER_CAP_NONE;
-import static com.android.server.wifi.util.GeneralUtil.getCapabilityIndex;
-
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
@@ -32,6 +30,7 @@
import android.hardware.wifi.AvailableAfcChannelInfo;
import android.hardware.wifi.AvailableAfcFrequencyInfo;
import android.hardware.wifi.IWifiApIface;
+import android.hardware.wifi.IWifiChip.ApIfaceParams;
import android.hardware.wifi.IWifiChip.ChannelCategoryMask;
import android.hardware.wifi.IWifiChip.CoexRestriction;
import android.hardware.wifi.IWifiChip.FeatureSetMask;
@@ -134,7 +133,11 @@
try {
if (!checkIfaceAndLogFailure(methodStr)) return null;
IWifiApIface iface;
- if (WifiHalAidlImpl.isServiceVersionAtLeast(2) && !vendorData.isEmpty()) {
+ if (WifiHalAidlImpl.isServiceVersionAtLeast(3)) {
+ iface = mWifiChip.createApOrBridgedApIfaceWithParams(prepareApIfaceParams(
+ IfaceConcurrencyType.AP, vendorData,
+ false /* usesMlo */));
+ } else if (WifiHalAidlImpl.isServiceVersionAtLeast(2) && !vendorData.isEmpty()) {
android.hardware.wifi.common.OuiKeyedData[] halVendorData =
HalAidlUtil.frameworkToHalOuiKeyedDataList(vendorData);
iface = mWifiChip.createApOrBridgedApIface(
@@ -152,18 +155,34 @@
}
}
+ private ApIfaceParams prepareApIfaceParams(int ifaceType,
+ @NonNull List<OuiKeyedData> vendorData, boolean usesMlo)
+ throws IllegalArgumentException {
+ ApIfaceParams ifaceParams = new ApIfaceParams();
+ ifaceParams.ifaceType = ifaceType;
+ ifaceParams.vendorData =
+ HalAidlUtil.frameworkToHalOuiKeyedDataList(vendorData);
+ ifaceParams.usesMlo = usesMlo;
+ return ifaceParams;
+ }
+
/**
* See comments for {@link IWifiChip#createBridgedApIface(List)}
*/
@Override
@Nullable
- public WifiApIface createBridgedApIface(@NonNull List<OuiKeyedData> vendorData) {
+ public WifiApIface createBridgedApIface(@NonNull List<OuiKeyedData> vendorData,
+ boolean isUsingMultiLinkOperation) {
final String methodStr = "createBridgedApIface";
synchronized (mLock) {
try {
if (!checkIfaceAndLogFailure(methodStr)) return null;
IWifiApIface iface;
- if (WifiHalAidlImpl.isServiceVersionAtLeast(2) && !vendorData.isEmpty()) {
+ if (WifiHalAidlImpl.isServiceVersionAtLeast(3)) {
+ iface = mWifiChip.createApOrBridgedApIfaceWithParams(prepareApIfaceParams(
+ IfaceConcurrencyType.AP_BRIDGED, vendorData,
+ isUsingMultiLinkOperation));
+ } else if (WifiHalAidlImpl.isServiceVersionAtLeast(2) && !vendorData.isEmpty()) {
android.hardware.wifi.common.OuiKeyedData[] halVendorData =
HalAidlUtil.frameworkToHalOuiKeyedDataList(vendorData);
iface = mWifiChip.createApOrBridgedApIface(
@@ -1596,25 +1615,28 @@
protected static BitSet halToFrameworkChipFeatureSet(long halFeatureSet) {
BitSet features = new BitSet();
if (bitmapContains(halFeatureSet, FeatureSetMask.SET_TX_POWER_LIMIT)) {
- features.set(getCapabilityIndex(WifiManager.WIFI_FEATURE_TX_POWER_LIMIT));
+ features.set(WifiManager.WIFI_FEATURE_TX_POWER_LIMIT);
}
if (bitmapContains(halFeatureSet, FeatureSetMask.D2D_RTT)) {
- features.set(getCapabilityIndex(WifiManager.WIFI_FEATURE_D2D_RTT));
+ features.set(WifiManager.WIFI_FEATURE_D2D_RTT);
}
if (bitmapContains(halFeatureSet, FeatureSetMask.D2AP_RTT)) {
- features.set(getCapabilityIndex(WifiManager.WIFI_FEATURE_D2AP_RTT));
+ features.set(WifiManager.WIFI_FEATURE_D2AP_RTT);
}
if (bitmapContains(halFeatureSet, FeatureSetMask.SET_LATENCY_MODE)) {
- features.set(getCapabilityIndex(WifiManager.WIFI_FEATURE_LOW_LATENCY));
+ features.set(WifiManager.WIFI_FEATURE_LOW_LATENCY);
}
if (bitmapContains(halFeatureSet, FeatureSetMask.P2P_RAND_MAC)) {
- features.set(getCapabilityIndex(WifiManager.WIFI_FEATURE_P2P_RAND_MAC));
+ features.set(WifiManager.WIFI_FEATURE_P2P_RAND_MAC);
}
if (bitmapContains(halFeatureSet, FeatureSetMask.WIGIG)) {
- features.set(getCapabilityIndex(WifiManager.WIFI_FEATURE_INFRA_60G));
+ features.set(WifiManager.WIFI_FEATURE_INFRA_60G);
}
if (bitmapContains(halFeatureSet, FeatureSetMask.T2LM_NEGOTIATION)) {
- features.set(getCapabilityIndex(WifiManager.WIFI_FEATURE_T2LM_NEGOTIATION));
+ features.set(WifiManager.WIFI_FEATURE_T2LM_NEGOTIATION);
+ }
+ if (bitmapContains(halFeatureSet, FeatureSetMask.MLO_SAP)) {
+ features.set(WifiManager.WIFI_FEATURE_SOFTAP_MLO);
}
return features;
}
diff --git a/service/java/com/android/server/wifi/hal/WifiChipHidlImpl.java b/service/java/com/android/server/wifi/hal/WifiChipHidlImpl.java
index 505b654..f7a9779 100644
--- a/service/java/com/android/server/wifi/hal/WifiChipHidlImpl.java
+++ b/service/java/com/android/server/wifi/hal/WifiChipHidlImpl.java
@@ -23,8 +23,6 @@
import static android.hardware.wifi.V1_6.WifiChannelWidthInMhz.WIDTH_80P80;
import static android.net.wifi.CoexUnsafeChannel.POWER_CAP_NONE;
-import static com.android.server.wifi.util.GeneralUtil.getCapabilityIndex;
-
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
@@ -122,7 +120,8 @@
*/
@Override
@Nullable
- public WifiApIface createBridgedApIface(@NonNull List<OuiKeyedData> vendorData) {
+ public WifiApIface createBridgedApIface(@NonNull List<OuiKeyedData> vendorData,
+ boolean isUsingMultiLinkOperation) {
String methodStr = "createBridgedApIface";
return validateAndCall(methodStr, null,
() -> createBridgedApIfaceInternal(methodStr));
@@ -1750,7 +1749,7 @@
}
}
- private static final long[][] sChipFeatureCapabilityTranslation = {
+ private static final int[][] sChipFeatureCapabilityTranslation = {
{WifiManager.WIFI_FEATURE_TX_POWER_LIMIT,
android.hardware.wifi.V1_1.IWifiChip.ChipCapabilityMask.SET_TX_POWER_LIMIT
},
@@ -1766,7 +1765,7 @@
* Translation table used by getSupportedFeatureSet for translating IWifiChip caps for
* additional capabilities introduced in V1.5
*/
- private static final long[][] sChipFeatureCapabilityTranslation15 = {
+ private static final int[][] sChipFeatureCapabilityTranslation15 = {
{WifiManager.WIFI_FEATURE_INFRA_60G,
android.hardware.wifi.V1_5.IWifiChip.ChipCapabilityMask.WIGIG
}
@@ -1776,7 +1775,7 @@
* Translation table used by getSupportedFeatureSet for translating IWifiChip caps for
* additional capabilities introduced in V1.3
*/
- private static final long[][] sChipFeatureCapabilityTranslation13 = {
+ private static final int[][] sChipFeatureCapabilityTranslation13 = {
{WifiManager.WIFI_FEATURE_LOW_LATENCY,
android.hardware.wifi.V1_3.IWifiChip.ChipCapabilityMask.SET_LATENCY_MODE
},
@@ -1797,7 +1796,7 @@
BitSet features = new BitSet();
for (int i = 0; i < sChipFeatureCapabilityTranslation.length; i++) {
if ((capabilities & sChipFeatureCapabilityTranslation[i][1]) != 0) {
- features.set(getCapabilityIndex(sChipFeatureCapabilityTranslation[i][0]));
+ features.set(sChipFeatureCapabilityTranslation[i][0]);
}
}
return features;
@@ -1817,7 +1816,7 @@
// Next collect features for V1_5 version
for (int i = 0; i < sChipFeatureCapabilityTranslation15.length; i++) {
if ((capabilities & sChipFeatureCapabilityTranslation15[i][1]) != 0) {
- features.set(getCapabilityIndex(sChipFeatureCapabilityTranslation15[i][0]));
+ features.set(sChipFeatureCapabilityTranslation15[i][0]);
}
}
return features;
@@ -1837,7 +1836,7 @@
// Next collect features for V1_3 version
for (int i = 0; i < sChipFeatureCapabilityTranslation13.length; i++) {
if ((capabilities & sChipFeatureCapabilityTranslation13[i][1]) != 0) {
- features.set(getCapabilityIndex(sChipFeatureCapabilityTranslation13[i][0]));
+ features.set(sChipFeatureCapabilityTranslation13[i][0]);
}
}
return features;
diff --git a/service/java/com/android/server/wifi/hal/WifiNanIface.java b/service/java/com/android/server/wifi/hal/WifiNanIface.java
index 9fcf9e2..8a2a8f8 100644
--- a/service/java/com/android/server/wifi/hal/WifiNanIface.java
+++ b/service/java/com/android/server/wifi/hal/WifiNanIface.java
@@ -26,6 +26,7 @@
import android.net.wifi.aware.SubscribeConfig;
import android.net.wifi.aware.WifiAwareChannelInfo;
import android.net.wifi.aware.WifiAwareDataPathSecurityConfig;
+import android.net.wifi.rtt.RangingResult;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
@@ -857,5 +858,13 @@
* the suspension mode
*/
void eventSuspensionModeChanged(boolean isSuspended);
+
+ /**
+ * Invoked when ranging results are available.
+ * @param rangingResults Rtt results data.
+ * @param sessionId ID of an active publish or subscribe discovery session.
+ */
+ void notifyRangingResults(ArrayList<RangingResult> rangingResults, byte sessionId);
+
}
}
diff --git a/service/java/com/android/server/wifi/hal/WifiNanIfaceAidlImpl.java b/service/java/com/android/server/wifi/hal/WifiNanIfaceAidlImpl.java
index ecefe9b..4b329f2 100644
--- a/service/java/com/android/server/wifi/hal/WifiNanIfaceAidlImpl.java
+++ b/service/java/com/android/server/wifi/hal/WifiNanIfaceAidlImpl.java
@@ -55,6 +55,7 @@
import android.hardware.wifi.NanSubscribeRequest;
import android.hardware.wifi.NanTransmitFollowupRequest;
import android.hardware.wifi.NanTxType;
+import android.hardware.wifi.WifiChannelInfo;
import android.net.MacAddress;
import android.net.wifi.aware.AwarePairingConfig;
import android.net.wifi.aware.ConfigRequest;
@@ -866,6 +867,7 @@
req.baseConfigs.enableSessionSuspendability = SdkLevel.isAtLeastU()
&& publishConfig.isSuspendable();
+ req.rangingResultsRequired = publishConfig.mEnablePeriodicRangingResults;
req.publishType = publishConfig.mPublishType;
req.txType = NanTxType.BROADCAST;
req.pairingConfig = createAidlPairingConfig(publishConfig.getPairingConfig());
@@ -953,6 +955,21 @@
HalAidlUtil.frameworkToHalOuiKeyedDataList(subscribeConfig.getVendorData());
}
+ if (subscribeConfig.mPeriodicRangingEnabled) {
+ req.baseConfigs.configRangingIndications |=
+ NanRangingIndication.CONTINUOUS_INDICATION_MASK;
+ req.baseConfigs.rangingIntervalMs = subscribeConfig.mPeriodicRangingInterval;
+ req.baseConfigs.rttBurstSize = subscribeConfig.mRttBurstSize;
+ req.baseConfigs.preamble = WifiRttControllerAidlImpl
+ .frameworkToHalResponderPreamble(subscribeConfig.mPreamble);
+ req.baseConfigs.channelInfo = new WifiChannelInfo();
+ req.baseConfigs.channelInfo.width = WifiRttControllerAidlImpl
+ .frameworkToHalChannelWidth(subscribeConfig.mChannelWidth);
+ req.baseConfigs.channelInfo.centerFreq = subscribeConfig.mFrequencyMhz;
+ req.baseConfigs.channelInfo.centerFreq0 = subscribeConfig.mCenterFrequency0Mhz;
+ req.baseConfigs.channelInfo.centerFreq1 = subscribeConfig.mCenterFrequency1Mhz;
+ }
+
return req;
}
diff --git a/service/java/com/android/server/wifi/hal/WifiNanIfaceCallbackAidlImpl.java b/service/java/com/android/server/wifi/hal/WifiNanIfaceCallbackAidlImpl.java
index f3c410b..125d9a3 100644
--- a/service/java/com/android/server/wifi/hal/WifiNanIfaceCallbackAidlImpl.java
+++ b/service/java/com/android/server/wifi/hal/WifiNanIfaceCallbackAidlImpl.java
@@ -47,14 +47,19 @@
import android.hardware.wifi.NanStatusCode;
import android.hardware.wifi.NanSuspensionModeChangeInd;
import android.hardware.wifi.NpkSecurityAssociation;
+import android.hardware.wifi.RttResult;
+import android.hardware.wifi.RttType;
import android.net.MacAddress;
import android.net.wifi.OuiKeyedData;
import android.net.wifi.aware.AwarePairingConfig;
import android.net.wifi.aware.Characteristics;
import android.net.wifi.aware.WifiAwareChannelInfo;
+import android.net.wifi.rtt.RangingResult;
+import android.net.wifi.rtt.ResponderLocation;
import android.net.wifi.util.HexEncoding;
import android.util.Log;
+import com.android.modules.utils.build.SdkLevel;
import com.android.server.wifi.aware.Capabilities;
import com.android.server.wifi.aware.PairingConfigManager.PairingSecurityAssociationInfo;
import com.android.server.wifi.hal.WifiNanIface.NanClusterEventType;
@@ -74,6 +79,11 @@
private boolean mVerboseLoggingEnabled;
private final WifiNanIfaceAidlImpl mWifiNanIface;
+ private static final int SUPPORTED_RX_CHAINS_1 = 1;
+ private static final int SUPPORTED_RX_CHAINS_2 = 2;
+ private static final int SUPPORTED_RX_CHAINS_3 = 3;
+ private static final int SUPPORTED_RX_CHAINS_4 = 4;
+
public WifiNanIfaceCallbackAidlImpl(WifiNanIfaceAidlImpl wifiNanIface) {
mWifiNanIface = wifiNanIface;
@@ -312,6 +322,18 @@
}
@Override
+ public void notifyRangingResults(RttResult[] results, byte sessionId) {
+ if (!checkFrameworkCallback()) return;
+ if (mVerboseLoggingEnabled) {
+ int numResults = results != null ? results.length : -1;
+ Log.v(TAG, "notifyRangingResults: number of ranging results: " + numResults
+ + ", session_id=" + sessionId);
+ }
+ ArrayList<RangingResult> rangingResults = convertToFrameworkRangingResults(results);
+ mWifiNanIface.getFrameworkCallback().notifyRangingResults(rangingResults, sessionId);
+ }
+
+ @Override
public void notifyTerminateDataPathResponse(char id, NanStatus status) {
if (!checkFrameworkCallback()) return;
if (mVerboseLoggingEnabled) {
@@ -736,6 +758,11 @@
frameworkCapabilities.isSuspensionSupported = capabilities.supportsSuspension;
frameworkCapabilities.is6gSupported = capabilities.supports6g;
frameworkCapabilities.isHeSupported = capabilities.supportsHe;
+ frameworkCapabilities.isPeriodicRangingSupported = capabilities.supportsPeriodicRanging;
+ frameworkCapabilities.maxSupportedRangingPktBandWidth = WifiRttControllerAidlImpl
+ .halToFrameworkChannelBandwidth(capabilities.maxSupportedBandwidth);
+ frameworkCapabilities.maxSupportedRxChains =
+ toFrameworkChainsSupported(capabilities.maxNumRxChainsSupported);
return frameworkCapabilities;
}
@@ -771,6 +798,21 @@
return publicCipherSuites;
}
+ private static int toFrameworkChainsSupported(int supportedRxChains) {
+ switch(supportedRxChains) {
+ case SUPPORTED_RX_CHAINS_1:
+ return Characteristics.SUPPORTED_RX_CHAINS_1;
+ case SUPPORTED_RX_CHAINS_2:
+ return Characteristics.SUPPORTED_RX_CHAINS_2;
+ case SUPPORTED_RX_CHAINS_3:
+ return Characteristics.SUPPORTED_RX_CHAINS_3;
+ case SUPPORTED_RX_CHAINS_4:
+ return Characteristics.SUPPORTED_RX_CHAINS_4;
+ default:
+ return Characteristics.SUPPORTED_RX_CHAINS_UNSPECIFIED;
+ }
+ }
+
private static String statusString(NanStatus status) {
if (status == null) {
return "status=null";
@@ -808,4 +850,49 @@
}
return true;
}
+
+ private ArrayList<RangingResult> convertToFrameworkRangingResults(RttResult[] halResults) {
+ ArrayList<RangingResult> rangingResults = new ArrayList();
+ for (RttResult rttResult : halResults) {
+ if (rttResult == null) continue;
+ byte[] lci = rttResult.lci.data;
+ byte[] lcr = rttResult.lcr.data;
+ ResponderLocation responderLocation;
+ try {
+ responderLocation = new ResponderLocation(lci, lcr);
+ if (!responderLocation.isValid()) {
+ responderLocation = null;
+ }
+ } catch (Exception e) {
+ responderLocation = null;
+ Log.e(TAG, "ResponderLocation: lci/lcr parser failed exception -- " + e);
+ }
+ if (rttResult.successNumber <= 1 && rttResult.distanceSdInMm != 0) {
+ if (mVerboseLoggingEnabled) {
+ Log.w(TAG, "postProcessResults: non-zero distance stdev with 0||1 num "
+ + "samples!? result=" + rttResult);
+ }
+ rttResult.distanceSdInMm = 0;
+ }
+ RangingResult.Builder resultBuilder = new RangingResult.Builder()
+ .setStatus(WifiRttControllerAidlImpl.halToFrameworkRttStatus(rttResult.status))
+ .setMacAddress(MacAddress.fromBytes(rttResult.addr))
+ .setDistanceMm(rttResult.distanceInMm)
+ .setDistanceStdDevMm(rttResult.distanceSdInMm)
+ .setRssi(rttResult.rssi / -2)
+ .setNumAttemptedMeasurements(rttResult.numberPerBurstPeer)
+ .setNumSuccessfulMeasurements(rttResult.successNumber)
+ .setUnverifiedResponderLocation(responderLocation)
+ .setRangingTimestampMillis(
+ rttResult.timeStampInUs / WifiRttController.CONVERSION_US_TO_MS)
+ .set80211mcMeasurement(rttResult.type == RttType.TWO_SIDED_11MC);
+ if (SdkLevel.isAtLeastV() && WifiHalAidlImpl.isServiceVersionAtLeast(2)
+ && rttResult.vendorData != null) {
+ resultBuilder.setVendorData(
+ HalAidlUtil.halToFrameworkOuiKeyedDataList(rttResult.vendorData));
+ }
+ rangingResults.add(resultBuilder.build());
+ }
+ return rangingResults;
+ }
}
diff --git a/service/java/com/android/server/wifi/hal/WifiRttController.java b/service/java/com/android/server/wifi/hal/WifiRttController.java
index 9061a01..5accbdd 100644
--- a/service/java/com/android/server/wifi/hal/WifiRttController.java
+++ b/service/java/com/android/server/wifi/hal/WifiRttController.java
@@ -116,6 +116,12 @@
public boolean ntbInitiatorSupported;
// Whether IEEE 802.11az Non-Trigger-based (non-TB) responder mode is supported.
public boolean ntbResponderSupported;
+ // Whether secure HE-LTF (Long Training Field) is supported
+ public boolean secureHeLtfSupported;
+ // Whether ranging frame protection is supported
+ public boolean rangingFrameProtectionSupported;
+ // Maximum supported secure HE-LTF protocol version
+ public int maxSupportedSecureHeLtfProtocolVersion;
public Capabilities() {
}
@@ -166,6 +172,10 @@
azBwSupported = rttHalCapabilities.azBwSupport;
ntbInitiatorSupported = rttHalCapabilities.ntbInitiatorSupported;
ntbResponderSupported = rttHalCapabilities.ntbResponderSupported;
+ secureHeLtfSupported = rttHalCapabilities.secureHeLtfSupported;
+ rangingFrameProtectionSupported = rttHalCapabilities.rangingFrameProtectionSupported;
+ maxSupportedSecureHeLtfProtocolVersion =
+ rttHalCapabilities.maxSupportedSecureHeLtfProtocolVersion;
}
}
diff --git a/service/java/com/android/server/wifi/hal/WifiRttControllerAidlImpl.java b/service/java/com/android/server/wifi/hal/WifiRttControllerAidlImpl.java
index ba32e3f..51346df 100644
--- a/service/java/com/android/server/wifi/hal/WifiRttControllerAidlImpl.java
+++ b/service/java/com/android/server/wifi/hal/WifiRttControllerAidlImpl.java
@@ -312,7 +312,10 @@
return rangingResults;
}
- private static @WifiAnnotations.ChannelWidth int halToFrameworkChannelBandwidth(
+ /**
+ * AIDL Hal to framework mapping for Channel width
+ */
+ public static @WifiAnnotations.ChannelWidth int halToFrameworkChannelBandwidth(
@RttBw int packetBw) {
switch (packetBw) {
case RttBw.BW_20MHZ:
@@ -330,7 +333,10 @@
}
}
- private static @WifiRttController.FrameworkRttStatus int halToFrameworkRttStatus(
+ /**
+ * AIDL Hal to framework mapping for RTT status
+ */
+ public static @WifiRttController.FrameworkRttStatus int halToFrameworkRttStatus(
int halStatus) {
switch (halStatus) {
case RttStatus.SUCCESS:
@@ -575,7 +581,10 @@
}
}
- private static int frameworkToHalChannelWidth(int responderChannelWidth)
+ /**
+ * Framework to AIDL Hal mapping for Channel Width
+ */
+ public static int frameworkToHalChannelWidth(int responderChannelWidth)
throws IllegalArgumentException {
switch (responderChannelWidth) {
case ResponderConfig.CHANNEL_WIDTH_20MHZ:
@@ -616,7 +625,10 @@
}
}
- private static int frameworkToHalResponderPreamble(int responderPreamble)
+ /**
+ * Framework to AIDL Hal mapping for Preamble
+ */
+ public static int frameworkToHalResponderPreamble(int responderPreamble)
throws IllegalArgumentException {
switch (responderPreamble) {
case ResponderConfig.PREAMBLE_LEGACY:
@@ -627,6 +639,8 @@
return RttPreamble.VHT;
case ResponderConfig.PREAMBLE_HE:
return RttPreamble.HE;
+ case ResponderConfig.PREAMBLE_EHT:
+ return RttPreamble.EHT;
default:
throw new IllegalArgumentException(
"frameworkToHalResponderPreamble: bad " + responderPreamble);
diff --git a/service/java/com/android/server/wifi/hal/WifiStaIfaceAidlImpl.java b/service/java/com/android/server/wifi/hal/WifiStaIfaceAidlImpl.java
index ee64cfe..583c637 100644
--- a/service/java/com/android/server/wifi/hal/WifiStaIfaceAidlImpl.java
+++ b/service/java/com/android/server/wifi/hal/WifiStaIfaceAidlImpl.java
@@ -17,7 +17,6 @@
package com.android.server.wifi.hal;
import static com.android.server.wifi.hal.WifiHalAidlImpl.isServiceVersionAtLeast;
-import static com.android.server.wifi.util.GeneralUtil.getCapabilityIndex;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -394,7 +393,8 @@
final String methodStr = "getCachedScanData";
synchronized (mLock) {
try {
- if (!checkIfaceAndLogFailure(methodStr)) return null;
+ if (!isServiceVersionAtLeast(2)
+ || !checkIfaceAndLogFailure(methodStr)) return null;
CachedScanData scanData = mWifiStaIface.getCachedScanData();
return halToFrameworkCachedScanData(scanData);
} catch (RemoteException e) {
@@ -1271,56 +1271,55 @@
BitSet features = new BitSet();
if (hasCapability(halFeatureSet,
android.hardware.wifi.IWifiStaIface.FeatureSetMask.HOTSPOT)) {
- features.set(getCapabilityIndex(WifiManager.WIFI_FEATURE_PASSPOINT));
+ features.set(WifiManager.WIFI_FEATURE_PASSPOINT);
}
if (hasCapability(halFeatureSet,
android.hardware.wifi.IWifiStaIface.FeatureSetMask.BACKGROUND_SCAN)) {
- features.set(getCapabilityIndex(WifiManager.WIFI_FEATURE_SCANNER));
+ features.set(WifiManager.WIFI_FEATURE_SCANNER);
}
if (hasCapability(halFeatureSet,
android.hardware.wifi.IWifiStaIface.FeatureSetMask.PNO)) {
- features.set(getCapabilityIndex(WifiManager.WIFI_FEATURE_PNO));
+ features.set(WifiManager.WIFI_FEATURE_PNO);
}
if (hasCapability(halFeatureSet,
android.hardware.wifi.IWifiStaIface.FeatureSetMask.TDLS)) {
- features.set(getCapabilityIndex(WifiManager.WIFI_FEATURE_TDLS));
+ features.set(WifiManager.WIFI_FEATURE_TDLS);
}
if (hasCapability(halFeatureSet,
android.hardware.wifi.IWifiStaIface.FeatureSetMask.TDLS_OFFCHANNEL)) {
- features.set(getCapabilityIndex(WifiManager.WIFI_FEATURE_TDLS_OFFCHANNEL));
+ features.set(WifiManager.WIFI_FEATURE_TDLS_OFFCHANNEL);
}
if (hasCapability(halFeatureSet,
android.hardware.wifi.IWifiStaIface.FeatureSetMask.LINK_LAYER_STATS)) {
- features.set(getCapabilityIndex(WifiManager.WIFI_FEATURE_LINK_LAYER_STATS));
+ features.set(WifiManager.WIFI_FEATURE_LINK_LAYER_STATS);
}
if (hasCapability(halFeatureSet,
android.hardware.wifi.IWifiStaIface.FeatureSetMask.RSSI_MONITOR)) {
- features.set(getCapabilityIndex(WifiManager.WIFI_FEATURE_RSSI_MONITOR));
+ features.set(WifiManager.WIFI_FEATURE_RSSI_MONITOR);
}
if (hasCapability(halFeatureSet,
android.hardware.wifi.IWifiStaIface.FeatureSetMask.KEEP_ALIVE)) {
- features.set(getCapabilityIndex(WifiManager.WIFI_FEATURE_MKEEP_ALIVE));
+ features.set(WifiManager.WIFI_FEATURE_MKEEP_ALIVE);
}
if (hasCapability(halFeatureSet,
android.hardware.wifi.IWifiStaIface.FeatureSetMask.ND_OFFLOAD)) {
- features.set(getCapabilityIndex(WifiManager.WIFI_FEATURE_CONFIG_NDO));
+ features.set(WifiManager.WIFI_FEATURE_CONFIG_NDO);
}
if (hasCapability(halFeatureSet,
android.hardware.wifi.IWifiStaIface.FeatureSetMask.CONTROL_ROAMING)) {
- features.set(getCapabilityIndex(WifiManager.WIFI_FEATURE_CONTROL_ROAMING));
+ features.set(WifiManager.WIFI_FEATURE_CONTROL_ROAMING);
}
if (hasCapability(halFeatureSet,
android.hardware.wifi.IWifiStaIface.FeatureSetMask.PROBE_IE_ALLOWLIST)) {
- features.set(getCapabilityIndex(WifiManager.WIFI_FEATURE_IE_WHITELIST));
+ features.set(WifiManager.WIFI_FEATURE_IE_WHITELIST);
}
if (hasCapability(halFeatureSet,
android.hardware.wifi.IWifiStaIface.FeatureSetMask.SCAN_RAND)) {
- features.set(getCapabilityIndex(WifiManager.WIFI_FEATURE_SCAN_RAND));
+ features.set(WifiManager.WIFI_FEATURE_SCAN_RAND);
}
if (hasCapability(halFeatureSet,
android.hardware.wifi.IWifiStaIface.FeatureSetMask.ROAMING_MODE_CONTROL)) {
- features.set(
- getCapabilityIndex(WifiManager.WIFI_FEATURE_AGGRESSIVE_ROAMING_MODE_SUPPORT));
+ features.set(WifiManager.WIFI_FEATURE_AGGRESSIVE_ROAMING_MODE_SUPPORT);
}
return features;
}
@@ -1479,11 +1478,21 @@
radio.on_time_roam_scan = aidlRadioStats.onTimeInMsForRoamScan;
radio.on_time_pno_scan = aidlRadioStats.onTimeInMsForPnoScan;
radio.on_time_hs20_scan = aidlRadioStats.onTimeInMsForHs20Scan;
+ if (aidlRadioStats.txTimeInMsPerLevel != null
+ && aidlRadioStats.txTimeInMsPerLevel.length > 0) {
+ radio.tx_time_in_ms_per_level = new int[aidlRadioStats.txTimeInMsPerLevel.length];
+ for (int i = 0; i < aidlRadioStats.txTimeInMsPerLevel.length; ++i) {
+ radio.tx_time_in_ms_per_level[i] = aidlRadioStats.txTimeInMsPerLevel[i];
+ }
+ }
/* Copy list of channel stats */
for (WifiChannelStats channelStats : aidlRadioStats.channelStats) {
WifiLinkLayerStats.ChannelStats channelStatsEntry =
new WifiLinkLayerStats.ChannelStats();
channelStatsEntry.frequency = channelStats.channel.centerFreq;
+ channelStatsEntry.frequencyFirstSegment = channelStats.channel.centerFreq0;
+ channelStatsEntry.frequencySecondSegment = channelStats.channel.centerFreq1;
+ channelStatsEntry.channelWidth = channelStats.channel.width;
channelStatsEntry.radioOnTimeMs = channelStats.onTimeInMs;
channelStatsEntry.ccaBusyTimeMs = channelStats.ccaBusyTimeInMs;
radio.channelStatsMap.put(channelStats.channel.centerFreq, channelStatsEntry);
diff --git a/service/java/com/android/server/wifi/hal/WifiStaIfaceHidlImpl.java b/service/java/com/android/server/wifi/hal/WifiStaIfaceHidlImpl.java
index bdcecde..a5deeae 100644
--- a/service/java/com/android/server/wifi/hal/WifiStaIfaceHidlImpl.java
+++ b/service/java/com/android/server/wifi/hal/WifiStaIfaceHidlImpl.java
@@ -18,8 +18,6 @@
import static android.net.wifi.WifiUsabilityStatsEntry.LINK_STATE_UNKNOWN;
-import static com.android.server.wifi.util.GeneralUtil.getCapabilityIndex;
-
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
@@ -896,52 +894,52 @@
BitSet features = new BitSet();
if (hasCapability(caps,
android.hardware.wifi.V1_0.IWifiStaIface.StaIfaceCapabilityMask.HOTSPOT)) {
- features.set(getCapabilityIndex(WifiManager.WIFI_FEATURE_PASSPOINT));
+ features.set(WifiManager.WIFI_FEATURE_PASSPOINT);
}
if (hasCapability(caps,
android.hardware.wifi.V1_0.IWifiStaIface.StaIfaceCapabilityMask.BACKGROUND_SCAN)) {
- features.set(getCapabilityIndex(WifiManager.WIFI_FEATURE_SCANNER));
+ features.set(WifiManager.WIFI_FEATURE_SCANNER);
}
if (hasCapability(caps,
android.hardware.wifi.V1_0.IWifiStaIface.StaIfaceCapabilityMask.PNO)) {
- features.set(getCapabilityIndex(WifiManager.WIFI_FEATURE_PNO));
+ features.set(WifiManager.WIFI_FEATURE_PNO);
}
if (hasCapability(caps,
android.hardware.wifi.V1_0.IWifiStaIface.StaIfaceCapabilityMask.TDLS)) {
- features.set(getCapabilityIndex(WifiManager.WIFI_FEATURE_TDLS));
+ features.set(WifiManager.WIFI_FEATURE_TDLS);
}
if (hasCapability(caps,
android.hardware.wifi.V1_0.IWifiStaIface.StaIfaceCapabilityMask.TDLS_OFFCHANNEL)) {
- features.set(getCapabilityIndex(WifiManager.WIFI_FEATURE_TDLS_OFFCHANNEL));
+ features.set(WifiManager.WIFI_FEATURE_TDLS_OFFCHANNEL);
}
if (hasCapability(caps,
android.hardware.wifi.V1_0.IWifiStaIface.StaIfaceCapabilityMask.LINK_LAYER_STATS)) {
- features.set(getCapabilityIndex(WifiManager.WIFI_FEATURE_LINK_LAYER_STATS));
+ features.set(WifiManager.WIFI_FEATURE_LINK_LAYER_STATS);
}
if (hasCapability(caps,
android.hardware.wifi.V1_0.IWifiStaIface.StaIfaceCapabilityMask.RSSI_MONITOR)) {
- features.set(getCapabilityIndex(WifiManager.WIFI_FEATURE_RSSI_MONITOR));
+ features.set(WifiManager.WIFI_FEATURE_RSSI_MONITOR);
}
if (hasCapability(caps,
android.hardware.wifi.V1_0.IWifiStaIface.StaIfaceCapabilityMask.KEEP_ALIVE)) {
- features.set(getCapabilityIndex(WifiManager.WIFI_FEATURE_MKEEP_ALIVE));
+ features.set(WifiManager.WIFI_FEATURE_MKEEP_ALIVE);
}
if (hasCapability(caps,
android.hardware.wifi.V1_0.IWifiStaIface.StaIfaceCapabilityMask.ND_OFFLOAD)) {
- features.set(getCapabilityIndex(WifiManager.WIFI_FEATURE_CONFIG_NDO));
+ features.set(WifiManager.WIFI_FEATURE_CONFIG_NDO);
}
if (hasCapability(caps,
android.hardware.wifi.V1_0.IWifiStaIface.StaIfaceCapabilityMask.CONTROL_ROAMING)) {
- features.set(getCapabilityIndex(WifiManager.WIFI_FEATURE_CONTROL_ROAMING));
+ features.set(WifiManager.WIFI_FEATURE_CONTROL_ROAMING);
}
if (hasCapability(caps,
android.hardware.wifi.V1_0.IWifiStaIface.StaIfaceCapabilityMask
.PROBE_IE_WHITELIST)) {
- features.set(getCapabilityIndex(WifiManager.WIFI_FEATURE_IE_WHITELIST));
+ features.set(WifiManager.WIFI_FEATURE_IE_WHITELIST);
}
if (hasCapability(caps,
android.hardware.wifi.V1_0.IWifiStaIface.StaIfaceCapabilityMask.SCAN_RAND)) {
- features.set(getCapabilityIndex(WifiManager.WIFI_FEATURE_SCAN_RAND));
+ features.set(WifiManager.WIFI_FEATURE_SCAN_RAND);
}
return features;
}
diff --git a/service/java/com/android/server/wifi/hotspot2/NetworkDetail.java b/service/java/com/android/server/wifi/hotspot2/NetworkDetail.java
index e2facfe..3bcd659 100644
--- a/service/java/com/android/server/wifi/hotspot2/NetworkDetail.java
+++ b/service/java/com/android/server/wifi/hotspot2/NetworkDetail.java
@@ -17,9 +17,11 @@
import java.nio.charset.CharsetDecoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
public class NetworkDetail {
@@ -170,6 +172,8 @@
private int mMloLinkId = MloLink.INVALID_MLO_LINK_ID;
private List<MloLink> mAffiliatedMloLinks = Collections.emptyList();
private byte[] mDisabledSubchannelBitmap;
+ private final boolean mIsSecureHeLtfSupported;
+ private final boolean mIsRangingFrameProtectionRequired;
public NetworkDetail(String bssid, ScanResult.InformationElement[] infoElements,
List<String> anqpLines, int freq) {
@@ -226,6 +230,8 @@
InformationElementUtil.SupportedRates extendedSupportedRates =
new InformationElementUtil.SupportedRates();
+ InformationElementUtil.Rsnxe rsnxe = new InformationElementUtil.Rsnxe();
+
RuntimeException exception = null;
ArrayList<Integer> iesFound = new ArrayList<Integer>();
@@ -299,6 +305,9 @@
break;
}
break;
+ case ScanResult.InformationElement.EID_RSN_EXTENSION:
+ rsnxe.from(ie);
+ break;
default:
break;
}
@@ -378,6 +387,8 @@
int channelWidth = ScanResult.UNSPECIFIED;
int centerFreq0 = mPrimaryFreq;
int centerFreq1 = 0;
+ mIsSecureHeLtfSupported = rsnxe.isSecureHeLtfSupported();
+ mIsRangingFrameProtectionRequired = rsnxe.isRangingFrameProtectionRequired();
// Check if EHT Operation Info is present in EHT operation IE.
if (ehtOperation.isEhtOperationInfoPresent()) {
@@ -567,6 +578,8 @@
mApType6GHz = base.mApType6GHz;
mIs11azNtbResponder = base.mIs11azNtbResponder;
mIs11azTbResponder = base.mIs11azTbResponder;
+ mIsSecureHeLtfSupported = base.mIsSecureHeLtfSupported;
+ mIsRangingFrameProtectionRequired = base.mIsRangingFrameProtectionRequired;
}
public NetworkDetail complete(Map<Constants.ANQPElementType, ANQPElement> anqpElements) {
@@ -715,36 +728,90 @@
}
@Override
- public boolean equals(Object thatObject) {
- if (this == thatObject) {
- return true;
- }
- if (thatObject == null || getClass() != thatObject.getClass()) {
- return false;
- }
-
- NetworkDetail that = (NetworkDetail)thatObject;
-
- return getSSID().equals(that.getSSID()) && getBSSID() == that.getBSSID();
- }
-
- @Override
- public int hashCode() {
- return ((mSSID.hashCode() * 31) + (int)(mBSSID >>> 32)) * 31 + (int)mBSSID;
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof NetworkDetail that)) return false;
+ return mHESSID == that.mHESSID && mBSSID == that.mBSSID
+ && mIsHiddenSsid == that.mIsHiddenSsid
+ && mStationCount == that.mStationCount
+ && mChannelUtilization == that.mChannelUtilization && mCapacity == that.mCapacity
+ && mChannelWidth == that.mChannelWidth && mPrimaryFreq == that.mPrimaryFreq
+ && mCenterfreq0 == that.mCenterfreq0 && mCenterfreq1 == that.mCenterfreq1
+ && mWifiMode == that.mWifiMode && mMaxRate == that.mMaxRate
+ && mMaxNumberSpatialStreams == that.mMaxNumberSpatialStreams
+ && mInternet == that.mInternet && mAnqpDomainID == that.mAnqpDomainID
+ && mAnqpOICount == that.mAnqpOICount && mDtimInterval == that.mDtimInterval
+ && mMboAssociationDisallowedReasonCode == that.mMboAssociationDisallowedReasonCode
+ && mMboSupported == that.mMboSupported
+ && mMboCellularDataAware == that.mMboCellularDataAware
+ && mOceSupported == that.mOceSupported && mTwtRequired == that.mTwtRequired
+ && mIndividualTwtSupported == that.mIndividualTwtSupported
+ && mBroadcastTwtSupported == that.mBroadcastTwtSupported
+ && mRestrictedTwtSupported == that.mRestrictedTwtSupported
+ && mEpcsPriorityAccessSupported == that.mEpcsPriorityAccessSupported
+ && mFilsCapable == that.mFilsCapable
+ && mIs11azNtbResponder == that.mIs11azNtbResponder
+ && mIs11azTbResponder == that.mIs11azTbResponder && mMloLinkId == that.mMloLinkId
+ && mIsSecureHeLtfSupported == that.mIsSecureHeLtfSupported
+ && mIsRangingFrameProtectionRequired == that.mIsRangingFrameProtectionRequired
+ && Objects.equals(mSSID, that.mSSID) && mAnt == that.mAnt
+ && mHSRelease == that.mHSRelease && Arrays.equals(mRoamingConsortiums,
+ that.mRoamingConsortiums) && Objects.equals(mCountryCode, that.mCountryCode)
+ && Objects.equals(mExtendedCapabilities, that.mExtendedCapabilities)
+ && Objects.equals(mANQPElements, that.mANQPElements)
+ && mApType6GHz == that.mApType6GHz && Objects.equals(mMldMacAddress,
+ that.mMldMacAddress) && Objects.equals(mAffiliatedMloLinks,
+ that.mAffiliatedMloLinks) && Arrays.equals(mDisabledSubchannelBitmap,
+ that.mDisabledSubchannelBitmap);
}
@Override
public String toString() {
- return "NetworkInfo{SSID='" + mSSID
- + "', HESSID=" + Utils.macToString(mHESSID)
- + ", BSSID=" + Utils.macToString(mBSSID)
- + ", StationCount=" + mStationCount
- + ", ChannelUtilization=" + mChannelUtilization
- + ", Capacity=" + mCapacity
- + ", Ant=" + mAnt + ", Internet=" + mInternet + ", HSRelease="
- + mHSRelease + ", AnqpDomainID" + mAnqpDomainID + ", AnqpOICount" + mAnqpOICount
- + ", RoamingConsortiums=" + Utils.roamingConsortiumsToString(mRoamingConsortiums)
- + "}";
+ return "NetworkDetail{" + "mSSID='" + mSSID + '\'' + ", mHESSID='" + Utils.macToString(
+ mHESSID) + '\'' + ", mBSSID='" + Utils.macToString(mBSSID) + '\''
+ + ", mIsHiddenSsid=" + mIsHiddenSsid + ", mStationCount=" + mStationCount
+ + ", mChannelUtilization=" + mChannelUtilization + ", mCapacity=" + mCapacity
+ + ", mChannelWidth=" + mChannelWidth + ", mPrimaryFreq=" + mPrimaryFreq
+ + ", mCenterfreq0=" + mCenterfreq0 + ", mCenterfreq1=" + mCenterfreq1
+ + ", mWifiMode=" + mWifiMode + ", mMaxRate=" + mMaxRate
+ + ", mMaxNumberSpatialStreams=" + mMaxNumberSpatialStreams + ", mAnt=" + mAnt
+ + ", mInternet=" + mInternet + ", mHSRelease=" + mHSRelease + ", mAnqpDomainID="
+ + mAnqpDomainID + ", mAnqpOICount=" + mAnqpOICount + ", mRoamingConsortiums="
+ + Utils.roamingConsortiumsToString(mRoamingConsortiums) + ", mDtimInterval="
+ + mDtimInterval + ", mCountryCode='" + mCountryCode + '\''
+ + ", mExtendedCapabilities=" + mExtendedCapabilities + ", mANQPElements="
+ + mANQPElements + ", mMboAssociationDisallowedReasonCode="
+ + mMboAssociationDisallowedReasonCode + ", mMboSupported=" + mMboSupported
+ + ", mMboCellularDataAware=" + mMboCellularDataAware + ", mOceSupported="
+ + mOceSupported + ", mTwtRequired=" + mTwtRequired + ", mIndividualTwtSupported="
+ + mIndividualTwtSupported + ", mBroadcastTwtSupported=" + mBroadcastTwtSupported
+ + ", mRestrictedTwtSupported=" + mRestrictedTwtSupported
+ + ", mEpcsPriorityAccessSupported=" + mEpcsPriorityAccessSupported
+ + ", mFilsCapable=" + mFilsCapable + ", mApType6GHz=" + mApType6GHz
+ + ", mIs11azNtbResponder=" + mIs11azNtbResponder + ", mIs11azTbResponder="
+ + mIs11azTbResponder + ", mMldMacAddress=" + mMldMacAddress + ", mMloLinkId="
+ + mMloLinkId + ", mAffiliatedMloLinks=" + mAffiliatedMloLinks
+ + ", mDisabledSubchannelBitmap=" + Arrays.toString(mDisabledSubchannelBitmap)
+ + ", mIsSecureHeLtfSupported=" + mIsSecureHeLtfSupported
+ + ", mIsRangingFrameProtectionRequired=" + mIsRangingFrameProtectionRequired + '}';
+ }
+
+ @Override
+ public int hashCode() {
+ int result = Objects.hash(mSSID, mHESSID, mBSSID, mIsHiddenSsid, mStationCount,
+ mChannelUtilization, mCapacity, mChannelWidth, mPrimaryFreq, mCenterfreq0,
+ mCenterfreq1,
+ mWifiMode, mMaxRate, mMaxNumberSpatialStreams, mAnt, mInternet, mHSRelease,
+ mAnqpDomainID, mAnqpOICount, mDtimInterval, mCountryCode, mExtendedCapabilities,
+ mANQPElements, mMboAssociationDisallowedReasonCode, mMboSupported,
+ mMboCellularDataAware, mOceSupported, mTwtRequired, mIndividualTwtSupported,
+ mBroadcastTwtSupported, mRestrictedTwtSupported, mEpcsPriorityAccessSupported,
+ mFilsCapable, mApType6GHz, mIs11azNtbResponder, mIs11azTbResponder, mMldMacAddress,
+ mMloLinkId, mAffiliatedMloLinks, mIsSecureHeLtfSupported,
+ mIsRangingFrameProtectionRequired);
+ result = 31 * result + Arrays.hashCode(mRoamingConsortiums);
+ result = 31 * result + Arrays.hashCode(mDisabledSubchannelBitmap);
+ return result;
}
public String toKeyString() {
@@ -856,4 +923,14 @@
public InformationElementUtil.ApType6GHz getApType6GHz() {
return mApType6GHz;
}
+
+ /** Return whether secure HE-LTF is supported or not. */
+ public boolean isSecureHeLtfSupported() {
+ return mIsSecureHeLtfSupported;
+ }
+
+ /** Return whether ranging frame protection is required or not */
+ public boolean isRangingFrameProtectionRequired() {
+ return mIsRangingFrameProtectionRequired;
+ }
}
diff --git a/service/java/com/android/server/wifi/mainline_supplicant/MainlineSupplicant.java b/service/java/com/android/server/wifi/mainline_supplicant/MainlineSupplicant.java
new file mode 100644
index 0000000..e347122
--- /dev/null
+++ b/service/java/com/android/server/wifi/mainline_supplicant/MainlineSupplicant.java
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wifi.mainline_supplicant;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.net.wifi.util.Environment;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.ServiceSpecificException;
+import android.system.wifi.mainline_supplicant.IMainlineSupplicant;
+import android.util.Log;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Allows us to bring up, tear down, and make calls into the mainline supplicant process.
+ * <p>
+ * The mainline supplicant is a separate wpa_supplicant binary stored in the Wifi mainline module,
+ * which provides specific functionalities such as USD.
+ */
+public class MainlineSupplicant {
+ private static final String TAG = "MainlineSupplicant";
+ private static final String MAINLINE_SUPPLICANT_SERVICE_NAME = "wifi_mainline_supplicant";
+ private static final long WAIT_FOR_DEATH_TIMEOUT_MS = 50L;
+
+ private IMainlineSupplicant mIMainlineSupplicant;
+ private final Object mLock = new Object();
+ private SupplicantDeathRecipient mDeathRecipient;
+ private CountDownLatch mWaitForDeathLatch;
+
+ public MainlineSupplicant() {
+ mDeathRecipient = new SupplicantDeathRecipient();
+ }
+
+ @VisibleForTesting
+ protected IMainlineSupplicant getNewServiceBinderMockable() {
+ return IMainlineSupplicant.Stub.asInterface(
+ ServiceManagerWrapper.waitForService(MAINLINE_SUPPLICANT_SERVICE_NAME));
+ }
+
+ private @Nullable IBinder getCurrentServiceBinder() {
+ synchronized (mLock) {
+ if (mIMainlineSupplicant == null) {
+ return null;
+ }
+ return mIMainlineSupplicant.asBinder();
+ }
+ }
+
+ private class SupplicantDeathRecipient implements IBinder.DeathRecipient {
+ @Override
+ public void binderDied() {
+ }
+
+ @Override
+ public void binderDied(@NonNull IBinder who) {
+ synchronized (mLock) {
+ IBinder currentBinder = getCurrentServiceBinder();
+ Log.i(TAG, "Death notification received. who=" + who
+ + ", currentBinder=" + currentBinder);
+ if (currentBinder == null || currentBinder != who) {
+ Log.i(TAG, "Ignoring stale death notification");
+ return;
+ }
+ if (mWaitForDeathLatch != null) {
+ // Latch indicates that this event was triggered by stopService
+ mWaitForDeathLatch.countDown();
+ }
+ mIMainlineSupplicant = null;
+ Log.i(TAG, "Service death was handled successfully");
+ }
+ }
+ }
+
+ /**
+ * Start the mainline supplicant process.
+ *
+ * @return true if the process was started, false otherwise.
+ */
+ public boolean startService() {
+ synchronized (mLock) {
+ if (!Environment.isSdkAtLeastB()) {
+ Log.e(TAG, "Service is not available before Android B");
+ return false;
+ }
+ if (mIMainlineSupplicant != null) {
+ Log.i(TAG, "Service has already been started");
+ return true;
+ }
+
+ mIMainlineSupplicant = getNewServiceBinderMockable();
+ if (mIMainlineSupplicant == null) {
+ Log.e(TAG, "Unable to retrieve binder from the ServiceManager");
+ return false;
+ }
+
+ try {
+ mWaitForDeathLatch = null;
+ mIMainlineSupplicant.asBinder().linkToDeath(mDeathRecipient, /* flags= */ 0);
+ } catch (RemoteException e) {
+ handleRemoteException(e, "startService");
+ return false;
+ }
+
+ Log.i(TAG, "Service was started successfully");
+ return true;
+ }
+ }
+
+ /**
+ * Check whether this instance is active.
+ */
+ @VisibleForTesting
+ protected boolean isActive() {
+ synchronized (mLock) {
+ return mIMainlineSupplicant != null;
+ }
+ }
+
+ /**
+ * Stop the mainline supplicant process.
+ */
+ public void stopService() {
+ synchronized (mLock) {
+ if (mIMainlineSupplicant == null) {
+ Log.i(TAG, "Service has already been stopped");
+ return;
+ }
+ try {
+ Log.i(TAG, "Attempting to stop the service");
+ mWaitForDeathLatch = new CountDownLatch(1);
+ mIMainlineSupplicant.terminate();
+ } catch (RemoteException e) {
+ handleRemoteException(e, "stopService");
+ return;
+ }
+ }
+
+ // Wait for latch to confirm the service death
+ try {
+ if (mWaitForDeathLatch.await(WAIT_FOR_DEATH_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
+ Log.i(TAG, "Service death confirmation was received");
+ } else {
+ Log.e(TAG, "Timed out waiting for confirmation of service death");
+ }
+ } catch (InterruptedException e) {
+ Log.e(TAG, "Failed to wait for service death");
+ }
+ }
+
+ private void handleServiceSpecificException(ServiceSpecificException e, String methodName) {
+ Log.e(TAG, methodName + " encountered ServiceSpecificException " + e);
+ }
+
+ private void handleRemoteException(RemoteException e, String methodName) {
+ synchronized (mLock) {
+ Log.e(TAG, methodName + " encountered RemoteException " + e);
+ mIMainlineSupplicant = null;
+ }
+ }
+}
diff --git a/service/java/com/android/server/wifi/mainline_supplicant/ServiceManagerWrapper.java b/service/java/com/android/server/wifi/mainline_supplicant/ServiceManagerWrapper.java
new file mode 100644
index 0000000..828d694
--- /dev/null
+++ b/service/java/com/android/server/wifi/mainline_supplicant/ServiceManagerWrapper.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wifi.mainline_supplicant;
+
+import android.annotation.Nullable;
+import android.os.IBinder;
+
+import com.android.modules.utils.build.SdkLevel;
+
+/**
+ * Wrapper around ServiceManager APIs that are not directly available to the mainline module.
+ */
+public final class ServiceManagerWrapper {
+ static {
+ System.loadLibrary("service-wifi-jni");
+ }
+
+ /**
+ * Returns the specified service from the service manager.
+ *
+ * If the service is not running, service manager will attempt to start it, and this function
+ * will wait for it to be ready.
+ *
+ * @return {@code null} only if there are permission problems or fatal errors
+ */
+ public static @Nullable IBinder waitForService(String serviceName) {
+ // Underlying implementation requires SDK 31+
+ if (!SdkLevel.isAtLeastS()) {
+ return null;
+ }
+ return nativeWaitForService(serviceName);
+ }
+
+ private static native IBinder nativeWaitForService(String serviceName);
+}
diff --git a/service/java/com/android/server/wifi/p2p/ISupplicantP2pIfaceHal.java b/service/java/com/android/server/wifi/p2p/ISupplicantP2pIfaceHal.java
index 72f669b..ef2d9fd 100644
--- a/service/java/com/android/server/wifi/p2p/ISupplicantP2pIfaceHal.java
+++ b/service/java/com/android/server/wifi/p2p/ISupplicantP2pIfaceHal.java
@@ -300,6 +300,7 @@
* @return true, if operation was successful.
*/
boolean groupAdd(String networkName, String passphrase,
+ @WifiP2pConfig.PccModeConnectionType int connectionType,
boolean isPersistent, int freq, String peerAddress, boolean join);
/**
diff --git a/service/java/com/android/server/wifi/p2p/SupplicantP2pIfaceCallbackAidlImpl.java b/service/java/com/android/server/wifi/p2p/SupplicantP2pIfaceCallbackAidlImpl.java
index e3eabad..3bc093e 100644
--- a/service/java/com/android/server/wifi/p2p/SupplicantP2pIfaceCallbackAidlImpl.java
+++ b/service/java/com/android/server/wifi/p2p/SupplicantP2pIfaceCallbackAidlImpl.java
@@ -17,10 +17,12 @@
package com.android.server.wifi.p2p;
import static com.android.net.module.util.Inet4AddressUtils.intToInet4AddressHTL;
+import static com.android.wifi.flags.Flags.wifiDirectR2;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.hardware.wifi.supplicant.ISupplicantP2pIfaceCallback;
+import android.hardware.wifi.supplicant.KeyMgmtMask;
import android.hardware.wifi.supplicant.P2pClientEapolIpAddressInfo;
import android.hardware.wifi.supplicant.P2pDeviceFoundEventParams;
import android.hardware.wifi.supplicant.P2pGoNegotiationReqEventParams;
@@ -31,6 +33,7 @@
import android.hardware.wifi.supplicant.P2pProvDiscStatusCode;
import android.hardware.wifi.supplicant.P2pProvisionDiscoveryCompletedEventParams;
import android.hardware.wifi.supplicant.P2pStatusCode;
+import android.hardware.wifi.supplicant.P2pUsdBasedServiceDiscoveryResultParams;
import android.hardware.wifi.supplicant.WpsConfigMethods;
import android.hardware.wifi.supplicant.WpsDevPasswordId;
import android.net.MacAddress;
@@ -43,6 +46,7 @@
import android.net.wifi.p2p.WifiP2pProvDiscEvent;
import android.net.wifi.p2p.WifiP2pWfdInfo;
import android.net.wifi.p2p.nsd.WifiP2pServiceResponse;
+import android.net.wifi.util.Environment;
import android.text.TextUtils;
import android.util.Log;
@@ -271,7 +275,7 @@
boolean isPersistent) {
onGroupStarted(groupIfName, isGroupOwner, ssid, frequency, psk, passphrase, goDeviceAddress,
isPersistent, /* goInterfaceAddress */ null, /*p2pClientIpInfo */ null,
- /* vendorData */ null);
+ /* vendorData */ null, 0);
}
/**
@@ -282,10 +286,14 @@
@Override
public void onGroupStartedWithParams(P2pGroupStartedEventParams groupStartedEventParams) {
List<OuiKeyedData> vendorData = null;
+ int keyMgmtMask = 0;
if (mServiceVersion >= 3 && groupStartedEventParams.vendorData != null) {
vendorData = HalAidlUtil.halToFrameworkOuiKeyedDataList(
groupStartedEventParams.vendorData);
}
+ if (mServiceVersion >= 4) {
+ keyMgmtMask = groupStartedEventParams.keyMgmtMask;
+ }
onGroupStarted(groupStartedEventParams.groupInterfaceName,
groupStartedEventParams.isGroupOwner, groupStartedEventParams.ssid,
groupStartedEventParams.frequencyMHz, groupStartedEventParams.psk,
@@ -293,14 +301,16 @@
groupStartedEventParams.isPersistent, groupStartedEventParams.goInterfaceAddress,
groupStartedEventParams.isP2pClientEapolIpAddressInfoPresent
? groupStartedEventParams.p2pClientIpInfo : null,
- vendorData);
+ vendorData,
+ keyMgmtMask);
}
private void onGroupStarted(String groupIfName, boolean isGroupOwner, byte[] ssid,
int frequency, byte[] psk, String passphrase, byte[] goDeviceAddress,
boolean isPersistent, byte[] goInterfaceAddress,
P2pClientEapolIpAddressInfo p2pClientIpInfo,
- @Nullable List<OuiKeyedData> vendorData) {
+ @Nullable List<OuiKeyedData> vendorData,
+ int keyMgmtMask) {
if (groupIfName == null) {
Log.e(TAG, "Missing group interface name.");
return;
@@ -361,9 +371,29 @@
group.setVendorData(vendorData);
}
+ if (Environment.isSdkAtLeastB()
+ && wifiDirectR2()) {
+ group.setSecurityType(convertHalKeyMgmtMaskToP2pGroupSecurityType(keyMgmtMask));
+ }
+
mMonitor.broadcastP2pGroupStarted(mInterface, group);
}
+ private @WifiP2pGroup.SecurityType int convertHalKeyMgmtMaskToP2pGroupSecurityType(
+ int keyMgmtMask) {
+ if (keyMgmtMask == KeyMgmtMask.WPA_PSK) {
+ return WifiP2pGroup.SECURITY_TYPE_WPA2_PSK;
+ } else if (keyMgmtMask == KeyMgmtMask.SAE) {
+ return WifiP2pGroup.SECURITY_TYPE_WPA3_SAE;
+ } else if ((keyMgmtMask & (KeyMgmtMask.SAE | KeyMgmtMask.WPA_PSK))
+ == (KeyMgmtMask.SAE | KeyMgmtMask.WPA_PSK)) {
+ return WifiP2pGroup.SECURITY_TYPE_WPA3_COMPATIBILITY;
+ } else {
+ Log.e(TAG, "Unknown Key management mask: " + keyMgmtMask);
+ return WifiP2pGroup.SECURITY_TYPE_UNKNOWN;
+ }
+ }
+
/**
* Used to indicate the removal of a P2P group.
*
@@ -627,6 +657,41 @@
mMonitor.broadcastP2pServiceDiscoveryResponse(mInterface, response);
}
+ /**
+ * Used to indicate the reception of a USD based service discovery response.
+ *
+ * @param params Parameters associated with the USD based service discovery result.
+ */
+ @Override
+ public void onUsdBasedServiceDiscoveryResult(P2pUsdBasedServiceDiscoveryResultParams params) {
+ logd("Usd based service discovery result received on " + mInterface);
+ // TODO implementation
+ }
+
+ /**
+ * Used to indicate the termination of USD based service discovery.
+ *
+ * @param sessionId Identifier to identify the instance of a service discovery.
+ * @param reasonCode The reason for termination of service discovery.
+ */
+ @Override
+ public void onUsdBasedServiceDiscoveryTerminated(int sessionId, int reasonCode) {
+ logd("Usd based service discovery terminated on " + mInterface);
+ // TODO implementation
+ }
+
+ /**
+ * Used to indicate the termination of USD based service Advertisement
+ *
+ * @param sessionId Identifier to identify the instance of a service advertisement.
+ * @param reasonCode The reason for termination of service advertisement.
+ */
+ @Override
+ public void onUsdBasedServiceAdvertisementTerminated(int sessionId, int reasonCode) {
+ logd("Usd based service advertisement terminated on " + mInterface);
+ // TODO implementation
+ }
+
private WifiP2pDevice createStaEventDevice(byte[] interfaceAddress, byte[] p2pDeviceAddress,
InetAddress ipAddress) {
WifiP2pDevice device = new WifiP2pDevice();
diff --git a/service/java/com/android/server/wifi/p2p/SupplicantP2pIfaceHal.java b/service/java/com/android/server/wifi/p2p/SupplicantP2pIfaceHal.java
index b621e76..149a0ec 100644
--- a/service/java/com/android/server/wifi/p2p/SupplicantP2pIfaceHal.java
+++ b/service/java/com/android/server/wifi/p2p/SupplicantP2pIfaceHal.java
@@ -568,13 +568,14 @@
* @return true, if operation was successful.
*/
public boolean groupAdd(String networkName, String passphrase,
+ @WifiP2pConfig.PccModeConnectionType int connectionType,
boolean isPersistent, int freq, String peerAddress, boolean join) {
synchronized (mLock) {
String methodStr = "groupAdd";
if (mP2pIfaceHal == null) {
return handleNullHal(methodStr);
}
- return mP2pIfaceHal.groupAdd(networkName, passphrase,
+ return mP2pIfaceHal.groupAdd(networkName, passphrase, connectionType,
isPersistent, freq, peerAddress, join);
}
}
diff --git a/service/java/com/android/server/wifi/p2p/SupplicantP2pIfaceHalAidlImpl.java b/service/java/com/android/server/wifi/p2p/SupplicantP2pIfaceHalAidlImpl.java
index a8956b4..565893e 100644
--- a/service/java/com/android/server/wifi/p2p/SupplicantP2pIfaceHalAidlImpl.java
+++ b/service/java/com/android/server/wifi/p2p/SupplicantP2pIfaceHalAidlImpl.java
@@ -16,6 +16,9 @@
package com.android.server.wifi.p2p;
+import static android.net.wifi.p2p.WifiP2pManager.FEATURE_PCC_MODE_ALLOW_LEGACY_AND_R2_CONNECTION;
+import static android.net.wifi.p2p.WifiP2pManager.FEATURE_WIFI_DIRECT_R2;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.hardware.wifi.supplicant.DebugLevel;
@@ -26,7 +29,9 @@
import android.hardware.wifi.supplicant.ISupplicantP2pNetwork;
import android.hardware.wifi.supplicant.IfaceInfo;
import android.hardware.wifi.supplicant.IfaceType;
+import android.hardware.wifi.supplicant.KeyMgmtMask;
import android.hardware.wifi.supplicant.MiracastMode;
+import android.hardware.wifi.supplicant.P2pAddGroupConfigurationParams;
import android.hardware.wifi.supplicant.P2pConnectInfo;
import android.hardware.wifi.supplicant.P2pDiscoveryInfo;
import android.hardware.wifi.supplicant.P2pExtListenInfo;
@@ -1221,6 +1226,7 @@
* @return true, if operation was successful.
*/
public boolean groupAdd(String networkName, String passphrase,
+ @WifiP2pConfig.PccModeConnectionType int connectionType,
boolean isPersistent, int freq, String peerAddress, boolean join) {
synchronized (mLock) {
String methodStr = "groupAdd";
@@ -1245,6 +1251,11 @@
return false;
}
+ if (getCachedServiceVersion() >= 4) {
+ return addGroupWithConfigurationParams(
+ ssid, passphrase, connectionType, isPersistent, freq, macAddress, join);
+ }
+
try {
mISupplicantP2pIface.addGroupWithConfig(
ssid, passphrase, isPersistent, freq, macAddress, join);
@@ -1258,6 +1269,46 @@
}
}
+ private boolean addGroupWithConfigurationParams(byte[] ssid, String passphrase,
+ @WifiP2pConfig.PccModeConnectionType int connectionType,
+ boolean isPersistent, int freq, byte[] macAddress, boolean join) {
+ String methodStr = "addGroupWithConfigurationParams";
+
+ // Expect that these parameters are already validated.
+ P2pAddGroupConfigurationParams groupConfigurationParams =
+ new P2pAddGroupConfigurationParams();
+ groupConfigurationParams.ssid = ssid;
+ groupConfigurationParams.passphrase = passphrase;
+ groupConfigurationParams.isPersistent = isPersistent;
+ groupConfigurationParams.frequencyMHzOrBand = freq;
+ groupConfigurationParams.goInterfaceAddress = macAddress;
+ groupConfigurationParams.joinExistingGroup = join;
+ groupConfigurationParams.keyMgmtMask = p2pConfigConnectionTypeToSupplicantKeyMgmtMask(
+ connectionType);
+ try {
+ mISupplicantP2pIface.addGroupWithConfigurationParams(groupConfigurationParams);
+ return true;
+ } catch (RemoteException e) {
+ handleRemoteException(e, methodStr);
+ } catch (ServiceSpecificException e) {
+ handleServiceSpecificException(e, methodStr);
+ }
+ return false;
+ }
+
+ private static int p2pConfigConnectionTypeToSupplicantKeyMgmtMask(
+ @WifiP2pConfig.PccModeConnectionType int connectionType) {
+ int keyMgmtMask = 0;
+ if (WifiP2pConfig.PCC_MODE_CONNECTION_TYPE_R2_ONLY == connectionType) {
+ keyMgmtMask = KeyMgmtMask.SAE;
+ } else if (WifiP2pConfig.PCC_MODE_CONNECTION_TYPE_LEGACY_OR_R2 == connectionType) {
+ keyMgmtMask = KeyMgmtMask.WPA_PSK | KeyMgmtMask.SAE;
+ } else {
+ keyMgmtMask = KeyMgmtMask.WPA_PSK;
+ }
+ return keyMgmtMask;
+ }
+
/**
* Terminate a P2P group. If a new virtual network interface was used for
* the group, it must also be removed. The network interface name of the
@@ -2602,14 +2653,34 @@
* @return bitmask defined by WifiP2pManager.FEATURE_*
*/
public long getSupportedFeatures() {
- // First AIDL version supports these three features.
- long result = WifiP2pManager.FEATURE_SET_VENDOR_ELEMENTS
- | WifiP2pManager.FEATURE_FLEXIBLE_DISCOVERY
- | WifiP2pManager.FEATURE_GROUP_CLIENT_REMOVAL;
- if (getCachedServiceVersion() >= 2) {
- result |= WifiP2pManager.FEATURE_GROUP_OWNER_IPV6_LINK_LOCAL_ADDRESS_PROVIDED;
+ synchronized (mLock) {
+ String methodStr = "getSupportedFeatures";
+ long features = 0;
+ if (!checkP2pIfaceAndLogFailure(methodStr)) {
+ return 0;
+ }
+ if (getCachedServiceVersion() < 4) {
+ return 0;
+ }
+
+ try {
+ long p2pHalfeatures = mISupplicantP2pIface.getFeatureSet();
+ if ((p2pHalfeatures & mISupplicantP2pIface.P2P_FEATURE_V2) != 0) {
+ features |= FEATURE_WIFI_DIRECT_R2;
+ Log.i(TAG, "WIFI_DIRECT_R2 supported ");
+ }
+ if ((p2pHalfeatures & mISupplicantP2pIface.P2P_FEATURE_PCC_MODE_WPA3_COMPATIBILITY)
+ != 0) {
+ features |= FEATURE_PCC_MODE_ALLOW_LEGACY_AND_R2_CONNECTION;
+ Log.i(TAG, "PCC_MODE_ALLOW_LEGACY_AND_R2_CONNECTION supported ");
+ }
+ } catch (RemoteException e) {
+ handleRemoteException(e, methodStr);
+ } catch (ServiceSpecificException e) {
+ handleServiceSpecificException(e, methodStr);
+ }
+ return features;
}
- return result;
}
/**
diff --git a/service/java/com/android/server/wifi/p2p/SupplicantP2pIfaceHalHidlImpl.java b/service/java/com/android/server/wifi/p2p/SupplicantP2pIfaceHalHidlImpl.java
index 7f28476..2644bfb 100644
--- a/service/java/com/android/server/wifi/p2p/SupplicantP2pIfaceHalHidlImpl.java
+++ b/service/java/com/android/server/wifi/p2p/SupplicantP2pIfaceHalHidlImpl.java
@@ -1370,6 +1370,7 @@
* @return true, if operation was successful.
*/
public boolean groupAdd(String networkName, String passphrase,
+ @WifiP2pConfig.PccModeConnectionType int connectionType,
boolean isPersistent, int freq, String peerAddress, boolean join) {
synchronized (mLock) {
android.hardware.wifi.supplicant.V1_2.ISupplicantP2pIface ifaceV12 =
diff --git a/service/java/com/android/server/wifi/p2p/WifiP2pNative.java b/service/java/com/android/server/wifi/p2p/WifiP2pNative.java
index 3be642d..f6f7392 100644
--- a/service/java/com/android/server/wifi/p2p/WifiP2pNative.java
+++ b/service/java/com/android/server/wifi/p2p/WifiP2pNative.java
@@ -17,9 +17,11 @@
package com.android.server.wifi.p2p;
import static com.android.server.wifi.HalDeviceManager.HDM_CREATE_IFACE_P2P;
+import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_P2P_SUPPORTED_FEATURES;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SuppressLint;
import android.net.wifi.CoexUnsafeChannel;
import android.net.wifi.ScanResult;
import android.net.wifi.nl80211.WifiNl80211Manager;
@@ -30,6 +32,7 @@
import android.net.wifi.p2p.WifiP2pGroupList;
import android.net.wifi.p2p.WifiP2pManager;
import android.net.wifi.p2p.nsd.WifiP2pServiceInfo;
+import android.net.wifi.util.Environment;
import android.os.Handler;
import android.os.WorkSource;
import android.text.TextUtils;
@@ -41,8 +44,10 @@
import com.android.server.wifi.WifiInjector;
import com.android.server.wifi.WifiMetrics;
import com.android.server.wifi.WifiNative;
+import com.android.server.wifi.WifiSettingsConfigStore;
import com.android.server.wifi.WifiVendorHal;
import com.android.wifi.flags.FeatureFlags;
+import com.android.wifi.flags.Flags;
import java.util.HashSet;
import java.util.List;
@@ -68,6 +73,8 @@
private WifiNative.Iface mP2pIface;
private String mP2pIfaceName;
private InterfaceDestroyedListenerInternal mInterfaceDestroyedListener;
+ private int mServiceVersion = -1;
+ private long mCachedFeatureSet = 0;
/**
* Death handler for the supplicant daemon.
@@ -270,6 +277,11 @@
mWifiMetrics.incrementNumSetupP2pInterfaceFailureDueToSupplicant();
return null;
}
+ long featureSet = mSupplicantP2pIfaceHal.getSupportedFeatures();
+ mWifiInjector.getSettingsConfigStore()
+ .put(WIFI_P2P_SUPPORTED_FEATURES, featureSet);
+ mCachedFeatureSet = featureSet | getDriverIndependentFeatures();
+ Log.i(TAG, "P2P Supported features: " + mCachedFeatureSet);
Log.i(TAG, "P2P interface setup completed");
return mP2pIfaceName;
} else {
@@ -329,7 +341,34 @@
* @return bitmask defined by WifiP2pManager.FEATURE_*
*/
public long getSupportedFeatures() {
- return mSupplicantP2pIfaceHal.getSupportedFeatures();
+ if (mCachedFeatureSet == 0) {
+ mCachedFeatureSet = getDriverIndependentFeatures()
+ | mWifiInjector.getSettingsConfigStore().get(
+ WifiSettingsConfigStore.WIFI_P2P_SUPPORTED_FEATURES);
+ }
+ return mCachedFeatureSet;
+ }
+
+ private long getDriverIndependentFeatures() {
+ long features = 0;
+ // First AIDL version supports these three features.
+ if (getCachedServiceVersion() >= 1) {
+ features = WifiP2pManager.FEATURE_SET_VENDOR_ELEMENTS
+ | WifiP2pManager.FEATURE_FLEXIBLE_DISCOVERY
+ | WifiP2pManager.FEATURE_GROUP_CLIENT_REMOVAL;
+ if (mServiceVersion >= 2) {
+ features |= WifiP2pManager.FEATURE_GROUP_OWNER_IPV6_LINK_LOCAL_ADDRESS_PROVIDED;
+ }
+ }
+ return features;
+ }
+
+ private int getCachedServiceVersion() {
+ if (mServiceVersion == -1) {
+ mServiceVersion = mWifiInjector.getSettingsConfigStore().get(
+ WifiSettingsConfigStore.SUPPLICANT_HAL_AIDL_SERVICE_VERSION);
+ }
+ return mServiceVersion;
}
/**
@@ -684,8 +723,13 @@
*
* @return true, if operation was successful.
*/
+ @SuppressLint("NewApi")
public boolean p2pGroupAdd(WifiP2pConfig config, boolean join) {
int freq = 0;
+ int connectionType = Environment.isSdkAtLeastB() && Flags.wifiDirectR2()
+ ? config.getPccModeConnectionType()
+ : WifiP2pConfig.PCC_MODE_DEFAULT_CONNECTION_TYPE_LEGACY_ONLY;
+
switch (config.groupOwnerBand) {
case WifiP2pConfig.GROUP_OWNER_BAND_2GHZ:
freq = 2;
@@ -693,18 +737,70 @@
case WifiP2pConfig.GROUP_OWNER_BAND_5GHZ:
freq = 5;
break;
+ case WifiP2pConfig.GROUP_OWNER_BAND_6GHZ:
+ freq = 6;
+ break;
// treat it as frequency.
default:
freq = config.groupOwnerBand;
}
+ if (Environment.isSdkAtLeastB() && Flags.wifiDirectR2()) {
+ /* Check if the device supports Wi-Fi Direct R2 */
+ if ((WifiP2pConfig.GROUP_OWNER_BAND_6GHZ == config.groupOwnerBand
+ || WifiP2pConfig.PCC_MODE_CONNECTION_TYPE_R2_ONLY == connectionType)
+ && !isWiFiDirectR2Supported()) {
+ Log.e(TAG, "Failed to add the group - Wi-Fi Direct R2 not supported");
+ return false;
+ }
+
+ /* Check if the device supports Wi-Fi Direct R1/R2 Compatibility Mode */
+ if (WifiP2pConfig.PCC_MODE_CONNECTION_TYPE_LEGACY_OR_R2 == connectionType
+ && !isPccModeAllowLegacyAndR2ConnectionSupported()) {
+ Log.e(TAG, "Failed to add the group - R1/R2 compatibility not supported");
+ return false;
+ }
+
+ /* Check if this is a valid configuration for 6GHz band */
+ if (WifiP2pConfig.GROUP_OWNER_BAND_6GHZ == config.groupOwnerBand
+ && WifiP2pConfig.PCC_MODE_CONNECTION_TYPE_R2_ONLY != connectionType) {
+ Log.e(TAG, "Failed to add the group in 6GHz band - ConnectionType: "
+ + connectionType);
+ return false;
+ }
+
+ /* Check if we can upgrade LEGACY to R2 */
+ if (WifiP2pConfig.PCC_MODE_CONNECTION_TYPE_LEGACY_ONLY == connectionType
+ && isPccModeAllowLegacyAndR2ConnectionSupported()) {
+ Log.e(TAG, "Upgrade Legacy connection to R1/R2 compatibility");
+ connectionType = WifiP2pConfig.PCC_MODE_CONNECTION_TYPE_LEGACY_OR_R2;
+ }
+ }
+
+
abortWifiRunningScanIfNeeded(join);
return mSupplicantP2pIfaceHal.groupAdd(
config.networkName,
config.passphrase,
+ connectionType,
(config.netId == WifiP2pGroup.NETWORK_ID_PERSISTENT),
freq, config.deviceAddress, join);
}
+ /**
+ * @return true if this device supports Wi-Fi Direct R2
+ */
+ private boolean isWiFiDirectR2Supported() {
+ return (mCachedFeatureSet & WifiP2pManager.FEATURE_WIFI_DIRECT_R2) != 0;
+ }
+
+ /**
+ * @return true if this device supports R1/R2 Compatibility Mode.
+ */
+ private boolean isPccModeAllowLegacyAndR2ConnectionSupported() {
+ return (mCachedFeatureSet
+ & WifiP2pManager.FEATURE_PCC_MODE_ALLOW_LEGACY_AND_R2_CONNECTION) != 0;
+ }
+
private void abortWifiRunningScanIfNeeded(boolean isJoin) {
if (!isJoin) return;
diff --git a/service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java b/service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java
index 6fb46f4..19456d6 100644
--- a/service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java
+++ b/service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java
@@ -18,6 +18,7 @@
import static android.net.wifi.p2p.WifiP2pConfig.GROUP_CLIENT_IP_PROVISIONING_MODE_IPV4_DHCP;
import static android.net.wifi.p2p.WifiP2pConfig.GROUP_CLIENT_IP_PROVISIONING_MODE_IPV6_LINK_LOCAL;
+import static android.net.wifi.p2p.WifiP2pConfig.P2P_VERSION_2;
import static com.android.net.module.util.Inet4AddressUtils.inet4AddressToIntHTL;
import static com.android.net.module.util.Inet4AddressUtils.netmaskToPrefixLength;
@@ -83,6 +84,7 @@
import android.net.wifi.p2p.nsd.WifiP2pServiceInfo;
import android.net.wifi.p2p.nsd.WifiP2pServiceRequest;
import android.net.wifi.p2p.nsd.WifiP2pServiceResponse;
+import android.net.wifi.util.Environment;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
@@ -146,6 +148,7 @@
import com.android.server.wifi.util.WifiPermissionsUtil;
import com.android.server.wifi.util.WifiPermissionsWrapper;
import com.android.wifi.flags.FeatureFlags;
+import com.android.wifi.flags.Flags;
import com.android.wifi.resources.R;
import java.io.FileDescriptor;
@@ -433,6 +436,8 @@
// client(application) P2P group info list, key = package name
private final Map<String, WifiP2pGroupInfo> mOwnershipMap = new HashMap<>();
+ private WifiP2pGroup mGroup;
+ private final WifiP2pInfo mWifiP2pInfo = new WifiP2pInfo();
// Max number of P2P groups supported
private static final int MAX_NUM_GROUP = 1;
@@ -600,9 +605,11 @@
private static class WifiP2pGroupInfo {
public WifiP2pGroup p2pGroup;
public WifiP2pInfo p2pInfo;
- WifiP2pGroupInfo(WifiP2pGroup group, WifiP2pInfo info) {
+ public IIpClient ipClient;
+ WifiP2pGroupInfo(WifiP2pGroup group, WifiP2pInfo info, IIpClient client) {
p2pGroup = group;
p2pInfo = info;
+ ipClient = client;
}
}
@@ -657,6 +664,8 @@
case WifiP2pManager.REMOVE_EXTERNAL_APPROVER:
case WifiP2pManager.SET_CONNECTION_REQUEST_RESULT:
case WifiP2pManager.SET_VENDOR_ELEMENTS:
+ case WifiP2pManager.GET_DIR_INFO:
+ case WifiP2pManager.VALIDATE_DIR_INFO:
mP2pStateMachine.sendMessage(Message.obtain(msg));
break;
default:
@@ -815,6 +824,7 @@
}
private void stopIpClient() {
+ // TODO: Modify logic for Dual P2P in next CL
// Invalidate all previous start requests
mIpClientStartIndex++;
if (mIpClient != null) {
@@ -886,6 +896,8 @@
return;
}
mIpClient = ipClient;
+ mOwnershipMap.put(
+ mConnectionPkgName, new WifiP2pGroupInfo(mGroup, mWifiP2pInfo, mIpClient));
ProvisioningConfiguration config = null;
switch (mGroupClientIpProvisioningMode) {
@@ -1116,6 +1128,16 @@
|| mOwnershipMap.containsKey(SHARED_PKG_NAME);
}
+ private String getGroupOwnerPackageName(WifiP2pGroup group) {
+ for (Map.Entry<String, WifiP2pGroupInfo> entry : mOwnershipMap.entrySet()) {
+ if (entry.getValue().p2pGroup.getInterface().equals(group.getInterface())) {
+ return entry.getKey();
+ }
+ }
+ Log.wtf(TAG, "group missing from ownership map " + group.getInterface());
+ return SHARED_PKG_NAME;
+ }
+
/** This is used to provide information to drivers to optimize performance depending
* on the current mode of operation.
* 0 - disabled
@@ -1399,13 +1421,16 @@
pw.println("mClientInfoList " + mClientInfoList.size());
pw.println("mActiveClients " + mActiveClients);
pw.println("mPeerAuthorizingTimestamp" + mPeerAuthorizingTimestamp);
- pw.println("isDualP2pSupported" + isDualP2pSupported());
+ pw.println("isOwnershipSupported " + mFeatureFlags.p2pOwnership());
+ pw.println("isDualP2pSupported " + isDualP2pSupported());
pw.println();
- final IIpClient ipClient = mIpClient;
- if (ipClient != null) {
- pw.println("mIpClient:");
- IpClientUtil.dumpIpClient(ipClient, fd, pw, args);
+ for (WifiP2pGroupInfo info : mOwnershipMap.values()) {
+ IIpClient ipClient = info.ipClient;
+ if (ipClient != null) {
+ pw.println("mIpClient:");
+ IpClientUtil.dumpIpClient(ipClient, fd, pw, args);
+ }
}
}
@@ -1445,6 +1470,8 @@
private final InactiveState mInactiveState = new InactiveState(mThreshold, mThreadLocalLog);
// Idle is when p2p is enabled and there's no ongoing connection attempt
private final IdleState mIdleState = new IdleState(mThreshold, mThreadLocalLog);
+ private final L3ConnectingState mL3ConnectingState =
+ new L3ConnectingState(mThreshold, mThreadLocalLog);
private final GroupCreatingState mGroupCreatingState =
new GroupCreatingState(mThreshold, mThreadLocalLog);
private final UserAuthorizingInviteRequestState mUserAuthorizingInviteRequestState =
@@ -1514,8 +1541,6 @@
sendP2pPersistentGroupsChangedBroadcast();
}
});
- private final WifiP2pInfo mWifiP2pInfo = new WifiP2pInfo();
- private WifiP2pGroup mGroup;
// Is wifi on or off.
private boolean mIsWifiEnabled = false;
@@ -1546,6 +1571,7 @@
addState(mGroupNegotiationState, mGroupCreatingState);
addState(mFrequencyConflictState, mGroupCreatingState);
addState(mP2pRejectWaitState, mGroupCreatingState);
+ addState(mL3ConnectingState, mGroupCreatingState);
addState(mGroupCreatedState, mP2pEnabledState);
addState(mUserAuthorizingJoinState, mGroupCreatedState);
addState(mOngoingGroupRemovalState, mGroupCreatedState);
@@ -1596,7 +1622,7 @@
mSettingsConfigStore.registerChangeListener(D2D_ALLOWED_WHEN_INFRA_STA_DISABLED,
new D2DAllowWhenInfraStaDisabledValueListener(), this.getHandler());
// Register for location mode on/off broadcasts
- mContext.registerReceiver(new BroadcastReceiver() {
+ mContext.registerReceiverForAllUsers(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
/* if location mode is off, ongoing discovery should be stopped.
@@ -1610,7 +1636,7 @@
sendMessage(WifiP2pManager.STOP_DISCOVERY);
}
}
- }, new IntentFilter(LocationManager.MODE_CHANGED_ACTION));
+ }, new IntentFilter(LocationManager.MODE_CHANGED_ACTION), null, getHandler());
// Register for tethering state
if (!SdkLevel.isAtLeastS()) {
mContext.registerReceiver(new BroadcastReceiver() {
@@ -1666,22 +1692,19 @@
}
private RemoteCallbackList<IWifiP2pListener> generateCallbackList(WifiP2pGroup group) {
+ // TODO: Modify logic for Dual P2P in next CL
if (!mFeatureFlags.p2pOwnership() || mOwnershipMap.containsKey(SHARED_PKG_NAME)) {
return mWifiP2pListeners;
}
- for (Map.Entry<String, WifiP2pGroupInfo> entry : mOwnershipMap.entrySet()) {
- if (entry.getValue().p2pGroup.getInterface().equals(group.getInterface())) {
- IWifiP2pListener p2pListener = mP2pListenerMap.get(entry.getKey());
- RemoteCallbackList<IWifiP2pListener> listener = new RemoteCallbackList<>();
- if (p2pListener != null) {
- listener.register(p2pListener);
- logd("WifiP2pListener callback generated for " + entry.getKey());
- }
- return listener;
- }
+ String pkgName = getGroupOwnerPackageName(group);
+ IWifiP2pListener p2pListener = mP2pListenerMap.get(pkgName);
+ RemoteCallbackList<IWifiP2pListener> listener = new RemoteCallbackList<>();
+ if (p2pListener != null) {
+ listener.register(p2pListener);
+ logd("WifiP2pListener callback generated for " + pkgName);
}
- return mWifiP2pListeners;
+ return listener;
}
@Override
@@ -1896,6 +1919,10 @@
return "WifiP2pManager.SET_VENDOR_ELEMENTS";
case P2P_REJECTION_RESUME_AFTER_DELAY:
return "P2P_REJECTION_RESUME_AFTER_DELAY";
+ case WifiP2pManager.GET_DIR_INFO:
+ return "WifiP2pManager.GET_DIR_INFO";
+ case WifiP2pManager.VALIDATE_DIR_INFO:
+ return "WifiP2pManager.VALIDATE_DIR_INFO";
case RunnerState.STATE_ENTER_CMD:
return "Enter";
case RunnerState.STATE_EXIT_CMD:
@@ -3392,7 +3419,22 @@
WifiP2pManager.BUSY);
break;
}
- if (mVerboseLoggingEnabled) logd(getName() + " discover services");
+ int serviceDiscoveryType = message.arg1;
+ logd(getName() + " discover services - Type: " + serviceDiscoveryType);
+ if (serviceDiscoveryType
+ == WifiP2pManager.WIFI_P2P_USD_BASED_SERVICE_DISCOVERY) {
+ if (Environment.isSdkAtLeastB() && Flags.wifiDirectR2()
+ && isFeatureSupported(
+ WifiP2pManager.FEATURE_WIFI_DIRECT_R2)) {
+ // TODO implementation
+ replyToMessage(message, WifiP2pManager.DISCOVER_SERVICES_FAILED,
+ WifiP2pManager.ERROR);
+ } else {
+ replyToMessage(message, WifiP2pManager.DISCOVER_SERVICES_FAILED,
+ WifiP2pManager.ERROR);
+ }
+ break;
+ }
if (!updateSupplicantServiceRequest()) {
replyToMessage(message, WifiP2pManager.DISCOVER_SERVICES_FAILED,
WifiP2pManager.NO_SERVICE_REQUESTS);
@@ -3455,9 +3497,7 @@
break;
}
if (mVerboseLoggingEnabled) logd(getName() + " add service");
- WifiP2pServiceInfo servInfo =
- extras.getParcelable(WifiP2pManager.EXTRA_PARAM_KEY_SERVICE_INFO);
- if (addLocalService(message.replyTo, servInfo)) {
+ if (addLocalService(message)) {
replyToMessage(message, WifiP2pManager.ADD_LOCAL_SERVICE_SUCCEEDED);
} else {
replyToMessage(message, WifiP2pManager.ADD_LOCAL_SERVICE_FAILED);
@@ -3477,8 +3517,7 @@
break;
case WifiP2pManager.ADD_SERVICE_REQUEST:
if (mVerboseLoggingEnabled) logd(getName() + " add service request");
- if (!addServiceRequest(message.replyTo,
- (WifiP2pServiceRequest) message.obj)) {
+ if (!addServiceRequest(message)) {
replyToMessage(message, WifiP2pManager.ADD_SERVICE_REQUEST_FAILED);
break;
}
@@ -3529,7 +3568,7 @@
case SET_MIRACAST_MODE:
mWifiNative.setMiracastMode(message.arg1);
break;
- case WifiP2pManager.START_LISTEN:
+ case WifiP2pManager.START_LISTEN: {
String packageName = getCallingPkgName(message.sendingUid, message.replyTo);
if (packageName == null) {
replyToMessage(message, WifiP2pManager.START_LISTEN_FAILED);
@@ -3546,10 +3585,10 @@
.getBundle(WifiP2pManager.EXTRA_PARAM_KEY_BUNDLE);
WifiP2pExtListenParams extListenParams = SdkLevel.isAtLeastV()
&& (listenType == WifiP2pManager.WIFI_P2P_EXT_LISTEN_WITH_PARAMS)
- ? extras.getParcelable(
- WifiP2pManager.EXTRA_PARAM_KEY_EXT_LISTEN_PARAMS,
- WifiP2pExtListenParams.class)
- : null;
+ ? extras.getParcelable(
+ WifiP2pManager.EXTRA_PARAM_KEY_EXT_LISTEN_PARAMS,
+ WifiP2pExtListenParams.class)
+ : null;
boolean hasPermission;
if (isPlatformOrTargetSdkLessThanT(packageName, uid)) {
hasPermission = mWifiPermissionsUtil.checkCanAccessWifiDirect(
@@ -3580,6 +3619,7 @@
replyToMessage(message, WifiP2pManager.START_LISTEN_FAILED);
}
break;
+ }
case WifiP2pManager.STOP_LISTEN:
mLastCallerInfoManager.put(WifiManager.API_P2P_STOP_LISTENING,
Process.myTid(), message.sendingUid, 0,
@@ -3640,6 +3680,37 @@
}
updateP2pChannels();
break;
+ case WifiP2pManager.GET_DIR_INFO: {
+ String packageName = getCallingPkgName(message.sendingUid, message.replyTo);
+ if (packageName == null) {
+ replyToMessage(message, WifiP2pManager.GET_DIR_INFO_FAILED);
+ break;
+ }
+ if (!Environment.isSdkAtLeastB()
+ || !checkNearbyDevicesPermission(message, "GET_DIR_INFO")) {
+ replyToMessage(message, WifiP2pManager.GET_DIR_INFO_FAILED);
+ break;
+ }
+ // TODO implementation
+ replyToMessage(message, WifiP2pManager.RESPONSE_GET_DIR_INFO, null);
+ break;
+ }
+ case WifiP2pManager.VALIDATE_DIR_INFO: {
+ String packageName = getCallingPkgName(message.sendingUid, message.replyTo);
+ if (packageName == null) {
+ replyToMessage(message, WifiP2pManager.VALIDATE_DIR_INFO_FAILED);
+ break;
+ }
+ if (!Environment.isSdkAtLeastB()
+ || !checkNearbyDevicesPermission(message,
+ "VALIDATE_DIR_INFO")) {
+ replyToMessage(message, WifiP2pManager.VALIDATE_DIR_INFO_FAILED);
+ break;
+ }
+ // TODO implementation
+ replyToMessage(message, WifiP2pManager.RESPONSE_VALIDATE_DIR_INFO, 0);
+ break;
+ }
default:
return NOT_HANDLED;
}
@@ -4410,8 +4481,7 @@
: WifiManager.API_P2P_CREATE_GROUP_P2P_CONFIG,
Process.myTid(), uid, 0, packageName, true);
boolean ret = false;
- if (config != null) {
- if (isConfigValidAsGroup(config)) {
+ if (config != null && isConfigValidAsGroup(config)) {
mConnectionPkgName = packageName;
if (mVerboseLoggingEnabled) {
logd("FAST_CONNECTION GO band freq: "
@@ -4421,7 +4491,9 @@
P2pConnectionEvent.CONNECTION_FAST,
config, GroupEvent.GROUP_OWNER, uid, attributionTag);
ret = mWifiNative.p2pGroupAdd(config, false);
- }
+ } else if (isConfigForGroupOwnerV2(config)) {
+ logd("Requested to create Group Owner - V2");
+ // TODO implementation
} else if (netId == WifiP2pGroup.NETWORK_ID_PERSISTENT) {
// check if the go persistent group is present.
netId = mGroups.getNetworkId(mThisDevice.deviceAddress);
@@ -5292,14 +5364,9 @@
Log.wtf(TAG, "group size= " + mOwnershipMap.size()
+ " exceeds max number of p2p group supported");
}
- mOwnershipMap.put(
- mConnectionPkgName, new WifiP2pGroupInfo(mGroup, null));
+ mOwnershipMap.put(mConnectionPkgName,
+ new WifiP2pGroupInfo(mGroup, mWifiP2pInfo, mIpClient));
mWifiNative.setP2pGroupIdle(mGroup.getInterface(), GROUP_IDLE_TIME_S);
- Log.d(TAG, "start Ip client with provisioning mode: "
- + mSavedPeerConfig.getGroupClientIpProvisioningMode());
- startIpClient(mGroup.getInterface(), getHandler(),
- mSavedPeerConfig.getGroupClientIpProvisioningMode(),
- mGroup.p2pClientEapolIpInfo);
WifiP2pDevice groupOwner = mGroup.getOwner();
if (!EMPTY_DEVICE_ADDRESS.equals(groupOwner.deviceAddress)) {
WifiP2pDevice peer = mPeers.get(groupOwner.deviceAddress);
@@ -5320,6 +5387,16 @@
// essential.
logw("Unknown group owner " + groupOwner);
}
+ // TODO: enable state transition when GroupCreatedState merged to IdleState
+ /* if (mFeatureFlags.p2pOwnership()) {
+ smTransition(this, mL3ConnectingState);
+ break;
+ }*/
+ Log.d(TAG, "start Ip client with provisioning mode: "
+ + mSavedPeerConfig.getGroupClientIpProvisioningMode());
+ startIpClient(mGroup.getInterface(), getHandler(),
+ mSavedPeerConfig.getGroupClientIpProvisioningMode(),
+ mGroup.p2pClientEapolIpInfo);
smTransition(this, mGroupCreatedState);
break;
case TETHER_INTERFACE_STATE_CHANGED:
@@ -5336,11 +5413,8 @@
Log.wtf(TAG, "group size= " + mOwnershipMap.size()
+ " exceeds max number of p2p group supported");
}
- WifiP2pGroupInfo groupInfo = mOwnershipMap.putIfAbsent(mConnectionPkgName,
- new WifiP2pGroupInfo(mGroup, null));
- if (groupInfo != null) {
- groupInfo.p2pGroup = mGroup;
- }
+ mOwnershipMap.put(mConnectionPkgName,
+ new WifiP2pGroupInfo(mGroup, mWifiP2pInfo, mIpClient));
smTransition(this, mGroupCreatedState);
break;
case WifiP2pMonitor.P2P_GO_NEGOTIATION_FAILURE_EVENT:
@@ -5494,6 +5568,149 @@
}
}
+ class L3ConnectingState extends RunnerState {
+
+ /**
+ * The Runner state Constructor
+ *
+ * @param threshold the running time threshold in milliseconds
+ */
+ L3ConnectingState(int threshold, @NonNull LocalLog localLog) {
+ super(threshold, localLog);
+ }
+
+ @Override
+ public void enterImpl() {
+ logSmStateName(this.getName(),
+ getCurrentState() != null ? getCurrentState().getName() : "");
+ Log.d(TAG, "start Ip client with provisioning mode: "
+ + mSavedPeerConfig.getGroupClientIpProvisioningMode());
+ startIpClient(mGroup.getInterface(), getHandler(),
+ mSavedPeerConfig.getGroupClientIpProvisioningMode(),
+ mGroup.p2pClientEapolIpInfo);
+ }
+
+ @Override
+ public boolean processMessageImpl(Message message) {
+ logSmMessage(getName(), message);
+ switch (message.what) {
+ case IPC_PRE_DHCP_ACTION:
+ mWifiNative.setP2pPowerSave(mGroup.getInterface(), false);
+ try {
+ mIpClient.completedPreDhcpAction();
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+ break;
+ case IPC_POST_DHCP_ACTION:
+ mWifiNative.setP2pPowerSave(mGroup.getInterface(), true);
+ break;
+ case IPC_DHCP_RESULTS:
+ mDhcpResultsParcelable = (DhcpResultsParcelable) message.obj;
+ if (mDhcpResultsParcelable == null) {
+ break;
+ }
+
+ if (mVerboseLoggingEnabled) {
+ logd("mDhcpResultsParcelable: " + mDhcpResultsParcelable);
+ }
+ if (mDhcpResultsParcelable.serverAddress != null) {
+ setWifiP2pInfoOnGroupFormation(mDhcpResultsParcelable.serverAddress);
+ } else {
+ // In case of static IP (IP address received via EAPOL-Key exchange),
+ // the DHCP server address is null. So look for the gateway address.
+ InetAddress addr =
+ mDhcpResultsParcelable.baseConfiguration.getGateway();
+ if (addr != null) {
+ setWifiP2pInfoOnGroupFormation(addr.getHostAddress());
+ }
+ }
+ try {
+ final String ifname = mGroup.getInterface();
+ if (mDhcpResultsParcelable != null) {
+ mNetdWrapper.addInterfaceToLocalNetwork(
+ ifname,
+ mDhcpResultsParcelable.baseConfiguration.getRoutes(ifname));
+ }
+ } catch (Exception e) {
+ loge("Failed to add iface to local network " + e);
+ }
+ onGroupCreated(new WifiP2pInfo(mWifiP2pInfo),
+ eraseOwnDeviceAddress(mGroup),
+ generateCallbackList(mGroup));
+ sendP2pConnectionChangedBroadcast();
+ break;
+ case IPC_PROVISIONING_SUCCESS:
+ if (mSavedPeerConfig.getGroupClientIpProvisioningMode()
+ != GROUP_CLIENT_IP_PROVISIONING_MODE_IPV6_LINK_LOCAL) {
+ smTransition(this, mIdleState);
+ break;
+ }
+
+ LinkProperties linkProperties = (LinkProperties) message.obj;
+ if (mVerboseLoggingEnabled) {
+ logd("IP provisioning result " + linkProperties);
+ }
+ try {
+ mNetdWrapper.addInterfaceToLocalNetwork(
+ mGroup.getInterface(),
+ linkProperties.getRoutes());
+ } catch (Exception e) {
+ loge("Failed to add iface to local network " + e);
+ mWifiNative.p2pGroupRemove(mGroup.getInterface());
+ }
+
+ byte[] goInterfaceMacAddress = mGroup.interfaceAddress;
+ if (goInterfaceMacAddress == null) {
+ setWifiP2pInfoOnGroupFormationWithInetAddress(null);
+ onGroupCreated(new WifiP2pInfo(mWifiP2pInfo),
+ eraseOwnDeviceAddress(mGroup),
+ generateCallbackList(mGroup));
+ sendP2pConnectionChangedBroadcast();
+ smTransition(this, mIdleState);
+ break;
+ }
+
+ byte[] goIpv6Address = MacAddress.fromBytes(goInterfaceMacAddress)
+ .getLinkLocalIpv6FromEui48Mac().getAddress();
+ try {
+ InetAddress goIp = Inet6Address.getByAddress(null, goIpv6Address,
+ NetworkInterface.getByName(mGroup.getInterface()));
+ setWifiP2pInfoOnGroupFormationWithInetAddress(goIp);
+ onGroupCreated(new WifiP2pInfo(mWifiP2pInfo),
+ eraseOwnDeviceAddress(mGroup),
+ generateCallbackList(mGroup));
+ sendP2pConnectionChangedBroadcast();
+ } catch (UnknownHostException | SocketException e) {
+ loge("Unable to retrieve link-local IPv6 address of group owner "
+ + e);
+ mWifiNative.p2pGroupRemove(mGroup.getInterface());
+ }
+ smTransition(this, mIdleState);
+ break;
+ case IPC_PROVISIONING_FAILURE:
+ loge("IP provisioning failed");
+ mWifiNative.p2pGroupRemove(mGroup.getInterface());
+ smTransition(this, mIdleState);
+ break;
+ default:
+ return NOT_HANDLED;
+ }
+ return HANDLED;
+ }
+
+ public void exitImpl() {
+
+ }
+
+ @Override
+ public String getMessageLogRec(int what) {
+ return P2pStateMachine.class.getSimpleName() + "."
+ + this.getClass().getSimpleName()
+ + "." + getWhatToString(what);
+ }
+ }
+
class FrequencyConflictState extends RunnerState {
private WifiDialogManager.DialogHandle mFrequencyConflictDialog;
private AlertDialog mFrequencyConflictDialogPreT;
@@ -5917,6 +6134,7 @@
&& message.sendingUid != Process.SYSTEM_UID) {
replyToMessage(message, WifiP2pManager.REMOVE_GROUP_FAILED,
WifiP2pManager.BUSY);
+ logd("Remove group requested by non-group owner " + packageName);
break;
}
mLastCallerInfoManager.put(WifiManager.API_P2P_REMOVE_GROUP,
@@ -5954,15 +6172,8 @@
Log.e(TAG, "Illegal arguments");
break;
}
- String pkgName = SHARED_PKG_NAME;
WifiP2pGroup group = (WifiP2pGroup) message.obj;
- for (Map.Entry<String, WifiP2pGroupInfo> entry : mOwnershipMap.entrySet()) {
- if (entry.getValue().p2pGroup.getInterface().equals(
- group.getInterface())) {
- pkgName = entry.getKey();
- break;
- }
- }
+ String pkgName = getGroupOwnerPackageName(group);
handleGroupRemoved(pkgName);
if (mFeatureFlags.p2pOwnership()) {
smTransition(this, mIdleState);
@@ -6499,11 +6710,60 @@
broadcastOptions.setRequireNoneOfPermissions(excludedPermissionsList.toArray(
new String[0]));
}
+ context.sendBroadcast(intent, null, broadcastOptions.toBundle());
+ }
+ }
+
+ private void sendMultipleP2pConnectionChangedBroadcast(Intent intent,
+ @Nullable String[] excludedPermissions, Set<String> pkgNames) {
+ Context context = mContext.createContextAsUser(UserHandle.ALL, 0);
+ boolean isLocationModeEnabled = mWifiPermissionsUtil.isLocationModeEnabled();
+ String[] permissions = isLocationModeEnabled ? RECEIVER_PERMISSIONS_FOR_BROADCAST
+ : RECEIVER_PERMISSIONS_FOR_BROADCAST_LOCATION_OFF;
+ if (SdkLevel.isAtLeastU()) {
+ BroadcastOptions broadcastOptions = mWifiInjector.makeBroadcastOptions();
+ broadcastOptions.setRequireAllOfPermissions(permissions);
+ broadcastOptions.setRequireNoneOfPermissions(excludedPermissions);
+ if (pkgNames.size() > 0) {
+ for (String pkg : pkgNames) {
+ intent.setPackage(pkg);
+ context.sendBroadcast(intent, null, broadcastOptions.toBundle());
+ }
+ } else {
+ context.sendBroadcast(intent, null, broadcastOptions.toBundle());
+ }
+ } else {
+ if (pkgNames.size() > 0) {
+ for (String pkg : pkgNames) {
+ intent.setPackage(pkg);
+ context.sendBroadcastWithMultiplePermissions(intent, permissions);
+ }
+ } else {
+ context.sendBroadcastWithMultiplePermissions(intent, permissions);
+ }
+ }
+ if (SdkLevel.isAtLeastT()) {
+ // on Android T or later, also send broadcasts to apps that have NEARBY_WIFI_DEVICES
+ String[] requiredPermissions = new String[]{
+ android.Manifest.permission.NEARBY_WIFI_DEVICES,
+ android.Manifest.permission.ACCESS_WIFI_STATE
+ };
+ BroadcastOptions broadcastOptions = mWifiInjector.makeBroadcastOptions();
+ broadcastOptions.setRequireAllOfPermissions(requiredPermissions);
+ ArrayList<String> excludedPermissionsList = new ArrayList<>();
+ if (isLocationModeEnabled) {
+ excludedPermissionsList.add(android.Manifest.permission.ACCESS_FINE_LOCATION);
+ }
+ if (excludedPermissions != null) {
+ Collections.addAll(excludedPermissionsList, excludedPermissions);
+ }
+ if (excludedPermissionsList.size() > 0) {
+ broadcastOptions.setRequireNoneOfPermissions(excludedPermissionsList.toArray(
+ new String[0]));
+ }
// remove package name from intent for ownership
- if (mFeatureFlags.p2pOwnership()
- && intent.getAction().equals(
- WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION)) {
- intent = getP2pConnectionChangedIntent(true);
+ if (mFeatureFlags.p2pOwnership()) {
+ intent = getP2pConnectionChangedIntent();
}
context.sendBroadcast(intent, null, broadcastOptions.toBundle());
}
@@ -6529,35 +6789,80 @@
sendBroadcastWithExcludedPermissions(intent, null);
}
- private Intent getP2pConnectionChangedIntent(boolean tethering) {
+ private Intent getP2pConnectionChangedIntent() {
Intent intent = new Intent(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
intent.putExtra(WifiP2pManager.EXTRA_WIFI_P2P_INFO, new WifiP2pInfo(mWifiP2pInfo));
intent.putExtra(WifiP2pManager.EXTRA_NETWORK_INFO, makeNetworkInfo());
intent.putExtra(WifiP2pManager.EXTRA_WIFI_P2P_GROUP, eraseOwnDeviceAddress(mGroup));
- if (tethering || !mFeatureFlags.p2pOwnership()) return intent;
- if (!mOwnershipMap.containsKey(SHARED_PKG_NAME)) {
- for (String pkg : mOwnershipMap.keySet()) {
- intent.setPackage(pkg);
- logd("sending p2p connection changed broadcast to only " + pkg);
+ return intent;
+ }
+
+ private Set<String> getGroupOwnershipPackageList() {
+ Set<String> pkgNames = new HashSet<>();
+
+ if (mOwnershipMap.isEmpty()) {
+ logd("No ownership mapping available");
+ return pkgNames;
+ }
+
+ boolean hasSharedPkg = mOwnershipMap.containsKey(SHARED_PKG_NAME);
+
+ if (mOwnershipMap.size() == 1) {
+ if (hasSharedPkg) {
+ logd("Sending P2P connection changed broadcast to everyone");
+ return pkgNames;
+ }
+ String pkg = mOwnershipMap.keySet().iterator().next();
+ pkgNames.add(pkg);
+ logd("Sending P2P connection changed broadcast to only " + pkg);
+ return pkgNames;
+ }
+
+ if (hasSharedPkg) {
+ for (ClientInfo client : mClientInfoList.values()) {
+ if (!mOwnershipMap.containsKey(client.mPackageName)) {
+ pkgNames.add(client.mPackageName);
+ }
+ }
+ } else {
+ if (mGroup == null) {
+ loge("P2P current group information is not available");
+ return pkgNames;
+ }
+ for (Map.Entry<String, WifiP2pGroupInfo> entry : mOwnershipMap.entrySet()) {
+ if (entry.getValue().p2pGroup.getInterface().equals(mGroup.getInterface())) {
+ pkgNames.add(entry.getKey());
+ }
}
}
- return intent;
+
+ return pkgNames;
}
private void sendP2pConnectionChangedBroadcast() {
if (mVerboseLoggingEnabled) logd("sending p2p connection changed broadcast");
- Intent intent = getP2pConnectionChangedIntent(false);
+ Intent intent = getP2pConnectionChangedIntent();
+ Set<String> pkgNames = getGroupOwnershipPackageList();
if (SdkLevel.isAtLeastU()) {
// First send direct foreground broadcast to Tethering package and system service
// with same android.permission.MAINLINE_NETWORK_STACK
sendBroadcastWithMainlineNetworkStackPermissionPostU();
// Then send the same broadcast to remaining apps without
// android.permission.MAINLINE_NETWORK_STACK
- sendBroadcastWithExcludedPermissions(intent,
- RECEIVER_PERMISSIONS_MAINLINE_NETWORK_STACK);
+ if (mFeatureFlags.p2pOwnership()) {
+ sendMultipleP2pConnectionChangedBroadcast(intent,
+ RECEIVER_PERMISSIONS_MAINLINE_NETWORK_STACK, pkgNames);
+ } else {
+ sendBroadcastWithExcludedPermissions(intent,
+ RECEIVER_PERMISSIONS_MAINLINE_NETWORK_STACK);
+ }
} else {
- sendBroadcastWithExcludedPermissions(intent, null);
+ if (mFeatureFlags.p2pOwnership()) {
+ sendMultipleP2pConnectionChangedBroadcast(intent, null, pkgNames);
+ } else {
+ sendBroadcastWithExcludedPermissions(intent, null);
+ }
}
if (mWifiChannel != null) {
mWifiChannel.sendMessage(WifiP2pServiceImpl.P2P_CONNECTION_CHANGED,
@@ -6654,7 +6959,7 @@
if (TextUtils.isEmpty(tetheringServicePackage)) return false;
Log.i(TAG, "sending p2p tether request broadcast to " + tetheringServicePackage
+ " with permission " + Arrays.toString(permissions));
- Intent intent = getP2pConnectionChangedIntent(true);
+ Intent intent = getP2pConnectionChangedIntent();
if (setAdditionalFlags) {
intent.addFlags(flags);
}
@@ -6666,7 +6971,7 @@
private void sendBroadcastWithMainlineNetworkStackPermissionPostU() {
String[] receiverPermissions = RECEIVER_PERMISSIONS_MAINLINE_NETWORK_STACK;
- Intent intent = getP2pConnectionChangedIntent(true);
+ Intent intent = getP2pConnectionChangedIntent();
// Adding the flag to allow recipient to run at foreground priority with a shorter
// timeout interval.
intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
@@ -6812,6 +7117,7 @@
deviceName,
false /* isPinRequested */,
pin,
+ 0,
displayId,
new WifiDialogManager.P2pInvitationReceivedDialogCallback() {
@Override
@@ -6978,11 +7284,12 @@
deviceName,
isPinRequested,
displayPin,
+ mContext.getResources().getInteger(
+ R.integer.config_p2pInvitationReceivedDialogTimeoutMs),
displayId,
callback,
new WifiThreadRunner(getHandler()));
- mInvitationDialogHandle.launchDialog(mContext.getResources().getInteger(
- R.integer.config_p2pInvitationReceivedDialogTimeoutMs));
+ mInvitationDialogHandle.launchDialog();
}
private void notifyInvitationReceived(
@@ -7081,6 +7388,23 @@
&& !TextUtils.isEmpty(config.passphrase);
}
+ /**
+ * Check the config for group owner version 2.
+ *
+ * @param config config to be checked for P2P group owner version.
+ * @return true if it is version 2, false otherwise.
+ */
+ @SuppressLint("NewApi")
+ private boolean isConfigForGroupOwnerV2(WifiP2pConfig config) {
+ if (config != null && Environment.isSdkAtLeastB()
+ && isFeatureSupported(WifiP2pManager.FEATURE_WIFI_DIRECT_R2)
+ && Flags.wifiDirectR2()
+ && config.getGroupOwnerVersion() == P2P_VERSION_2) {
+ return true;
+ }
+ return false;
+ }
+
private WifiP2pDevice fetchCurrentDeviceDetails(WifiP2pConfig config) {
if (config == null) return null;
// Fetch & update group capability from supplicant on the device
@@ -7444,11 +7768,8 @@
mWifiP2pInfo.groupFormed = true;
mWifiP2pInfo.isGroupOwner = mGroup.isGroupOwner();
mWifiP2pInfo.groupOwnerAddress = serverAddress;
- WifiP2pGroupInfo groupInfo = mOwnershipMap.putIfAbsent(
- mConnectionPkgName, new WifiP2pGroupInfo(null, mWifiP2pInfo));
- if (groupInfo != null) {
- groupInfo.p2pInfo = mWifiP2pInfo;
- }
+ mOwnershipMap.put(
+ mConnectionPkgName, new WifiP2pGroupInfo(mGroup, mWifiP2pInfo, mIpClient));
}
private void resetWifiP2pInfo() {
@@ -7744,6 +8065,7 @@
}
private void handleGroupRemoved(String packageName) {
+ // TODO: Modify logic for Dual P2P in next CL
if (mGroup.isGroupOwner()) {
// {@link com.android.server.connectivity.Tethering} listens to
// {@link WifiP2pManager#WIFI_P2P_CONNECTION_CHANGED_ACTION}
@@ -7891,11 +8213,25 @@
mServiceDiscReqId = null;
}
- private boolean addServiceRequest(Messenger m, WifiP2pServiceRequest req) {
+ @SuppressLint("NewApi")
+ private boolean addServiceRequest(@NonNull Message message) {
+ Messenger m = message.replyTo;
+ WifiP2pServiceRequest req = (WifiP2pServiceRequest) message.obj;
if (m == null || req == null) {
Log.e(TAG, "Illegal argument(s)");
return false;
}
+ if (Environment.isSdkAtLeastB() && Flags.wifiDirectR2()
+ && isFeatureSupported(WifiP2pManager.FEATURE_WIFI_DIRECT_R2)) {
+ if (req.getWifiP2pUsdBasedServiceConfig() != null) {
+ if (mVerboseLoggingEnabled) {
+ logd(getName() + " USD service config: "
+ + req.getWifiP2pUsdBasedServiceConfig().toString());
+ }
+ // TODO implementation
+ return false;
+ }
+ }
// TODO: We could track individual service adds separately and avoid
// having to do update all service requests on every new request
clearClientDeadChannels();
@@ -7970,11 +8306,22 @@
updateSupplicantServiceRequest();
}
- private boolean addLocalService(Messenger m, WifiP2pServiceInfo servInfo) {
+ private boolean addLocalService(@NonNull Message message) {
+ Messenger m = message.replyTo;
+ Bundle extras = message.getData()
+ .getBundle(WifiP2pManager.EXTRA_PARAM_KEY_BUNDLE);
+ WifiP2pServiceInfo servInfo =
+ extras.getParcelable(WifiP2pManager.EXTRA_PARAM_KEY_SERVICE_INFO);
if (m == null || servInfo == null) {
Log.e(TAG, "Illegal arguments");
return false;
}
+ int addLocalServiceType = message.arg1;
+ if (addLocalServiceType
+ == WifiP2pManager.WIFI_P2P_USD_BASED_ADD_LOCAL_SERVICE) {
+ // TODO implementation
+ return false;
+ }
clearClientDeadChannels();
diff --git a/service/java/com/android/server/wifi/rtt/RttServiceImpl.java b/service/java/com/android/server/wifi/rtt/RttServiceImpl.java
index 85e5e65..930368e 100644
--- a/service/java/com/android/server/wifi/rtt/RttServiceImpl.java
+++ b/service/java/com/android/server/wifi/rtt/RttServiceImpl.java
@@ -21,7 +21,10 @@
import static android.net.wifi.rtt.WifiRttManager.CHARACTERISTICS_KEY_BOOLEAN_LCR;
import static android.net.wifi.rtt.WifiRttManager.CHARACTERISTICS_KEY_BOOLEAN_NTB_INITIATOR;
import static android.net.wifi.rtt.WifiRttManager.CHARACTERISTICS_KEY_BOOLEAN_ONE_SIDED_RTT;
+import static android.net.wifi.rtt.WifiRttManager.CHARACTERISTICS_KEY_BOOLEAN_RANGING_FRAME_PROTECTION_SUPPORTED;
+import static android.net.wifi.rtt.WifiRttManager.CHARACTERISTICS_KEY_BOOLEAN_SECURE_HE_LTF_SUPPORTED;
import static android.net.wifi.rtt.WifiRttManager.CHARACTERISTICS_KEY_BOOLEAN_STA_RESPONDER;
+import static android.net.wifi.rtt.WifiRttManager.CHARACTERISTICS_KEY_INT_MAX_SUPPORTED_SECURE_HE_LTF_PROTO_VERSION;
import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_VERBOSE_LOGGING_ENABLED;
@@ -240,6 +243,9 @@
j.put("mcVersion", mCapabilities.mcVersion);
j.put("ntbInitiatorSupported", mCapabilities.ntbInitiatorSupported);
j.put("ntbResponderSupported", mCapabilities.ntbResponderSupported);
+ j.put("secureHeLtfSupported", mCapabilities.secureHeLtfSupported);
+ j.put("rangingFrameProtectionSupported",
+ mCapabilities.rangingFrameProtectionSupported);
} catch (JSONException e) {
Log.e(TAG, "onCommand: get_capabilities e=" + e);
}
@@ -346,7 +352,7 @@
intentFilter = new IntentFilter();
intentFilter.addAction(LocationManager.MODE_CHANGED_ACTION);
- mContext.registerReceiver(new BroadcastReceiver() {
+ mContext.registerReceiverForAllUsers(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (mVerboseLoggingEnabled) {
@@ -358,7 +364,7 @@
disable();
}
}
- }, intentFilter);
+ }, intentFilter, null, mRttServiceSynchronized.mHandler);
mHalDeviceManager.initialize();
mHalDeviceManager.registerStatusListener(() -> {
@@ -483,6 +489,12 @@
capabilities.responderSupported);
characteristics.putBoolean(CHARACTERISTICS_KEY_BOOLEAN_NTB_INITIATOR,
capabilities.ntbInitiatorSupported);
+ characteristics.putBoolean(CHARACTERISTICS_KEY_BOOLEAN_SECURE_HE_LTF_SUPPORTED,
+ capabilities.secureHeLtfSupported);
+ characteristics.putBoolean(CHARACTERISTICS_KEY_BOOLEAN_RANGING_FRAME_PROTECTION_SUPPORTED,
+ capabilities.rangingFrameProtectionSupported);
+ characteristics.putInt(CHARACTERISTICS_KEY_INT_MAX_SUPPORTED_SECURE_HE_LTF_PROTO_VERSION,
+ capabilities.maxSupportedSecureHeLtfProtocolVersion);
return characteristics;
}
diff --git a/service/java/com/android/server/wifi/scanner/WifiScanningServiceImpl.java b/service/java/com/android/server/wifi/scanner/WifiScanningServiceImpl.java
index 120de83..4dead3e 100644
--- a/service/java/com/android/server/wifi/scanner/WifiScanningServiceImpl.java
+++ b/service/java/com/android/server/wifi/scanner/WifiScanningServiceImpl.java
@@ -244,7 +244,7 @@
return;
}
final ExternalClientInfo client = new ExternalClientInfo(uid, packageName,
- listener);
+ listener, featureId);
client.register();
localLog("register scan listener: " + client + " AttributionTag " + featureId);
logScanRequest("registerScanListener", client, null, null, null);
@@ -298,13 +298,13 @@
mWifiThreadRunner.post(() -> {
ExternalClientInfo client = (ExternalClientInfo) mClients.get(listener);
if (client == null) {
- client = new ExternalClientInfo(uid, packageName, listener);
+ client = new ExternalClientInfo(uid, packageName, listener, featureId);
client.register();
}
localLog("start background scan: " + client + " package " + packageName);
Message msg = Message.obtain();
msg.what = WifiScanner.CMD_START_BACKGROUND_SCAN;
- msg.obj = new ScanParams(listener, settings, workSource);
+ msg.obj = new ScanParams(listener, settings, workSource, featureId);
msg.sendingUid = uid;
mBackgroundScanStateMachine.sendMessage(msg);
}, TAG + "#startBackgroundScan");
@@ -332,7 +332,7 @@
localLog("stop background scan: " + client);
Message msg = Message.obtain();
msg.what = WifiScanner.CMD_STOP_BACKGROUND_SCAN;
- msg.obj = new ScanParams(listener, null, null);
+ msg.obj = new ScanParams(listener, null, null, featureId);
msg.sendingUid = uid;
mBackgroundScanStateMachine.sendMessage(msg);
}
@@ -363,8 +363,8 @@
public String featureId;
ScanParams(IWifiScannerListener listener, WifiScanner.ScanSettings settings,
- WorkSource workSource) {
- this(listener, settings, null, workSource, null, null);
+ WorkSource workSource, String featureId) {
+ this(listener, settings, null, workSource, null, featureId);
}
ScanParams(IWifiScannerListener listener, WifiScanner.ScanSettings settings,
@@ -399,14 +399,14 @@
mWifiThreadRunner.post(() -> {
ExternalClientInfo client = (ExternalClientInfo) mClients.get(listener);
if (client == null) {
- client = new ExternalClientInfo(uid, packageName, listener);
+ client = new ExternalClientInfo(uid, packageName, listener, featureId);
client.register();
}
localLog("start scan: " + client + " package " + packageName + " AttributionTag "
+ featureId);
Message msg = Message.obtain();
msg.what = WifiScanner.CMD_START_SINGLE_SCAN;
- msg.obj = new ScanParams(listener, settings, workSource);
+ msg.obj = new ScanParams(listener, settings, workSource, featureId);
msg.sendingUid = uid;
mSingleScanStateMachine.sendMessage(msg);
}, TAG + "#startScan");
@@ -434,7 +434,7 @@
localLog("stop scan: " + client + " AttributionTag " + featureId);
Message msg = Message.obtain();
msg.what = WifiScanner.CMD_STOP_SINGLE_SCAN;
- msg.obj = new ScanParams(listener, null, null);
+ msg.obj = new ScanParams(listener, null, null, featureId);
msg.sendingUid = uid;
mSingleScanStateMachine.sendMessage(msg);
}, TAG + "#stopScan");
@@ -504,7 +504,8 @@
localLog("start pno scan: " + clientInfoLog + " AttributionTag " + featureId);
Message msg = Message.obtain();
msg.what = WifiScanner.CMD_START_PNO_SCAN;
- msg.obj = new ScanParams(listener, scanSettings, pnoSettings, null, packageName, null);
+ msg.obj = new ScanParams(listener, scanSettings, pnoSettings, null, packageName,
+ featureId);
msg.sendingUid = uid;
mPnoScanStateMachine.sendMessage(msg);
}, TAG + "#startPnoScan");
@@ -531,7 +532,7 @@
localLog("stop pno scan: " + packageName + " AttributionTag " + featureId);
Message msg = Message.obtain();
msg.what = WifiScanner.CMD_STOP_PNO_SCAN;
- msg.obj = new ScanParams(listener, null, null);
+ msg.obj = new ScanParams(listener, null, null, featureId);
msg.sendingUid = uid;
mPnoScanStateMachine.sendMessage(msg);
}, TAG + "#stopPnoScan");
@@ -889,6 +890,70 @@
}
}
+ private String getWhatToStringInternal(int what) {
+ switch (what) {
+ case WifiScanner.CMD_START_BACKGROUND_SCAN:
+ return "WifiScanner.CMD_START_BACKGROUND_SCAN";
+ case WifiScanner.CMD_STOP_BACKGROUND_SCAN:
+ return "WifiScanner.CMD_STOP_BACKGROUND_SCAN";
+ case WifiScanner.CMD_GET_SCAN_RESULTS:
+ return "WifiScanner.CMD_GET_SCAN_RESULTS";
+ case WifiScanner.CMD_SCAN_RESULT:
+ return "WifiScanner.CMD_SCAN_RESULT";
+ case WifiScanner.CMD_CACHED_SCAN_DATA:
+ return "WifiScanner.CMD_CACHED_SCAN_DATA";
+ case WifiScanner.CMD_OP_SUCCEEDED:
+ return "WifiScanner.CMD_OP_SUCCEEDED";
+ case WifiScanner.CMD_OP_FAILED:
+ return "WifiScanner.CMD_OP_FAILED";
+ case WifiScanner.CMD_FULL_SCAN_RESULT:
+ return "WifiScanner.CMD_FULL_SCAN_RESULT";
+ case WifiScanner.CMD_START_SINGLE_SCAN:
+ return "WifiScanner.CMD_START_SINGLE_SCAN";
+ case WifiScanner.CMD_STOP_SINGLE_SCAN:
+ return "WifiScanner.CMD_STOP_SINGLE_SCAN";
+ case WifiScanner.CMD_SINGLE_SCAN_COMPLETED:
+ return "WifiScanner.CMD_SINGLE_SCAN_COMPLETED";
+ case WifiScanner.CMD_START_PNO_SCAN:
+ return "WifiScanner.CMD_START_PNO_SCAN";
+ case WifiScanner.CMD_STOP_PNO_SCAN:
+ return "WifiScanner.CMD_STOP_PNO_SCAN";
+ case WifiScanner.CMD_PNO_NETWORK_FOUND:
+ return "WifiScanner.CMD_PNO_NETWORK_FOUND";
+ case WifiScanner.CMD_REGISTER_SCAN_LISTENER:
+ return "WifiScanner.CMD_REGISTER_SCAN_LISTENER";
+ case WifiScanner.CMD_DEREGISTER_SCAN_LISTENER:
+ return "WifiScanner.CMD_DEREGISTER_SCAN_LISTENER";
+ case WifiScanner.CMD_GET_SINGLE_SCAN_RESULTS:
+ return "WifiScanner.CMD_GET_SINGLE_SCAN_RESULTS";
+ case WifiScanner.CMD_ENABLE:
+ return "WifiScanner.CMD_ENABLE";
+ case WifiScanner.CMD_DISABLE:
+ return "WifiScanner.CMD_DISABLE";
+ case CMD_SCAN_RESULTS_AVAILABLE:
+ return "CMD_SCAN_RESULTS_AVAILABLE";
+ case CMD_FULL_SCAN_SINGLE_RESULT:
+ return "CMD_FULL_SCAN_SINGLE_RESULT";
+ case CMD_FULL_SCAN_ALL_RESULTS:
+ return "CMD_FULL_SCAN_ALL_RESULTS";
+ case CMD_SCAN_PAUSED:
+ return "CMD_SCAN_PAUSED";
+ case CMD_SCAN_RESTARTED:
+ return "CMD_SCAN_RESTARTED";
+ case CMD_SCAN_FAILED:
+ return "CMD_SCAN_FAILED";
+ case CMD_PNO_NETWORK_FOUND:
+ return "CMD_PNO_NETWORK_FOUND";
+ case CMD_PNO_SCAN_FAILED:
+ return "CMD_PNO_SCAN_FAILED";
+ case CMD_SW_PNO_SCAN:
+ return "CMD_SW_PNO_SCAN";
+ default:
+ return "what:" + what;
+ }
+ }
+
+
/**
* State machine that holds the state of single scans. Scans should only be active in the
* ScanningState. The pending scans and active scans maps are swapped when entering
@@ -954,6 +1019,30 @@
}
/**
+ * @return the string for msg.what
+ */
+ @Override
+ protected String getWhatToString(int what) {
+ return getWhatToStringInternal(what);
+ }
+
+ /**
+ * Return the additional string to be logged by LogRec, default
+ *
+ * @param msg that was processed
+ * @return information to be logged as a String
+ */
+ @Override
+ protected String getLogRecString(Message msg) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(" ");
+ sb.append(Integer.toString(msg.arg1));
+ sb.append(" ");
+ sb.append(Integer.toString(msg.arg2));
+ return sb.toString();
+ }
+
+ /**
* Tracks a single scan request across all the available scanner impls.
*
* a) Initiates the scan using the same ScanSettings across all the available impls.
@@ -1696,7 +1785,7 @@
}
for (RequestInfo<Void> entry : mSingleScanListeners) {
- logCallback("singleScanResults", entry.clientInfo,
+ logCallback("singleScanResults listener", entry.clientInfo,
describeForLog(allResults));
entry.clientInfo.reportEvent((listener) -> {
try {
@@ -2338,6 +2427,30 @@
setInitialState(mDefaultState);
}
+ /**
+ * @return the string for msg.what
+ */
+ @Override
+ protected String getWhatToString(int what) {
+ return getWhatToStringInternal(what);
+ }
+
+ /**
+ * Return the additional string to be logged by LogRec, default
+ *
+ * @param msg that was processed
+ * @return information to be logged as a String
+ */
+ @Override
+ protected String getLogRecString(Message msg) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(" ");
+ sb.append(Integer.toString(msg.arg1));
+ sb.append(" ");
+ sb.append(Integer.toString(msg.arg2));
+ return sb.toString();
+ }
+
public void removePnoSettings(ClientInfo ci) {
mActivePnoScans.removeAllForClient(ci);
}
@@ -2543,7 +2656,7 @@
ClientInfo ci = mClients.get(scanParams.listener);
if (ci == null) {
ci = new ExternalClientInfo(msg.sendingUid, scanParams.packageName,
- scanParams.listener);
+ scanParams.listener, scanParams.featureId);
ci.register();
}
if (scanParams.pnoSettings == null || scanParams.settings == null) {
@@ -2603,7 +2716,7 @@
ClientInfo ci = mClients.get(scanParams.listener);
if (ci == null) {
ci = new ExternalClientInfo(msg.sendingUid, scanParams.packageName,
- scanParams.listener);
+ scanParams.listener, scanParams.featureId);
ci.register();
}
if (scanParams.pnoSettings == null || scanParams.settings == null) {
@@ -2917,7 +3030,8 @@
ClientInfo clientInfo = mClients.get(scanParams.listener);
if (clientInfo == null) {
clientInfo = new ExternalClientInfo(msg.sendingUid,
- scanParams.packageName, scanParams.listener);
+ scanParams.packageName, scanParams.listener,
+ scanParams.featureId);
clientInfo.register();
}
@@ -3056,7 +3170,7 @@
private void addInternalClient(ClientInfo ci) {
if (mInternalClientInfo == null) {
mInternalClientInfo = new InternalClientInfo(ci.getUid(), "internal",
- new InternalListener());
+ new InternalListener(), ci.mAttributionTag);
mInternalClientInfo.register();
} else {
Log.w(TAG, "Internal client for PNO already exists");
@@ -3141,7 +3255,7 @@
Message msg = Message.obtain();
msg.what = WifiScanner.CMD_START_SINGLE_SCAN;
msg.obj = new ScanParams(mInternalClientInfo.mListener, settings,
- ClientModeImpl.WIFI_WORK_SOURCE);
+ ClientModeImpl.WIFI_WORK_SOURCE, "WIFI_INTERNAL");
mSingleScanStateMachine.sendMessage(msg);
}
mWifiMetrics.getScanMetrics().setWorkSource(ClientModeImpl.WIFI_WORK_SOURCE);
@@ -3170,6 +3284,7 @@
private abstract class ClientInfo {
private final int mUid;
private final String mPackageName;
+ private final String mAttributionTag;
private final WorkSource mWorkSource;
private boolean mScanWorkReported = false;
protected final IWifiScannerListener mListener;
@@ -3186,11 +3301,13 @@
}
};
- ClientInfo(int uid, String packageName, IWifiScannerListener listener) {
+ ClientInfo(int uid, String packageName, IWifiScannerListener listener,
+ String attributionTag) {
mUid = uid;
mPackageName = packageName;
mListener = listener;
mWorkSource = new WorkSource(uid);
+ mAttributionTag = attributionTag;
}
/**
@@ -3312,8 +3429,8 @@
@Override
public String toString() {
- return "ClientInfo[uid=" + mUid + ", package=" + mPackageName + ", " + mListener
- + "]";
+ return "ClientInfo[uid=" + mUid + ", package=" + mPackageName + ", attributionTag="
+ + mAttributionTag + ", " + mListener + "]";
}
}
@@ -3327,8 +3444,9 @@
*/
private boolean mDisconnected = false;
- ExternalClientInfo(int uid, String packageName, IWifiScannerListener listener) {
- super(uid, packageName, listener);
+ ExternalClientInfo(int uid, String packageName, IWifiScannerListener listener,
+ String attributionTag) {
+ super(uid, packageName, listener, attributionTag);
if (DBG) localLog("New client, listener: " + listener);
try {
listener.asBinder().linkToDeath(mDeathRecipient, 0);
@@ -3361,8 +3479,9 @@
/**
* The UID here is used to proxy the original external requester UID.
*/
- InternalClientInfo(int requesterUid, String packageName, IWifiScannerListener listener) {
- super(requesterUid, packageName, listener);
+ InternalClientInfo(int requesterUid, String packageName, IWifiScannerListener listener,
+ String attributionTag) {
+ super(requesterUid, packageName, listener, attributionTag);
}
@Override
diff --git a/service/java/com/android/server/wifi/usd/UsdService.java b/service/java/com/android/server/wifi/usd/UsdService.java
new file mode 100644
index 0000000..6b3aeaa
--- /dev/null
+++ b/service/java/com/android/server/wifi/usd/UsdService.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wifi.usd;
+
+import android.content.Context;
+import android.net.wifi.WifiContext;
+import android.net.wifi.util.Environment;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+
+import com.android.server.SystemService;
+import com.android.server.wifi.WifiInjector;
+
+/**
+ * Service implementing USD functionality. Delegates actual interface implementation to
+ * {@link UsdServiceImpl}.
+ */
+public class UsdService extends SystemService {
+ private static final String TAG = UsdService.class.getName();
+ final UsdServiceImpl mUsdServiceImpl;
+
+ public UsdService(@NonNull Context context) {
+ super(new WifiContext(context));
+ mUsdServiceImpl = new UsdServiceImpl(getContext());
+ }
+
+ @Override
+ public void onStart() {
+ if (!Environment.isSdkAtLeastB()) {
+ return;
+ }
+ Log.i(TAG, "Registering " + Context.WIFI_USD_SERVICE);
+ publishBinderService(Context.WIFI_USD_SERVICE, mUsdServiceImpl);
+ }
+
+ @Override
+ public void onBootPhase(int phase) {
+ if (!Environment.isSdkAtLeastB()) {
+ return;
+ }
+ if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
+ WifiInjector wifiInjector = WifiInjector.getInstance();
+ if (wifiInjector == null) {
+ Log.e(TAG, "onBootPhase(PHASE_SYSTEM_SERVICES_READY): NULL injector!");
+ return;
+ }
+ mUsdServiceImpl.start(wifiInjector);
+ } else if (phase == SystemService.PHASE_BOOT_COMPLETED) {
+ mUsdServiceImpl.startLate();
+ }
+ }
+}
diff --git a/service/java/com/android/server/wifi/usd/UsdServiceImpl.java b/service/java/com/android/server/wifi/usd/UsdServiceImpl.java
new file mode 100644
index 0000000..f1528c9
--- /dev/null
+++ b/service/java/com/android/server/wifi/usd/UsdServiceImpl.java
@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wifi.usd;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.net.wifi.IBooleanListener;
+import android.net.wifi.usd.Characteristics;
+import android.net.wifi.usd.IAvailabilityCallback;
+import android.net.wifi.usd.IPublishSessionCallback;
+import android.net.wifi.usd.ISubscribeSessionCallback;
+import android.net.wifi.usd.IUsdManager;
+import android.net.wifi.usd.PublishConfig;
+import android.net.wifi.usd.PublishSession;
+import android.net.wifi.usd.PublishSessionCallback;
+import android.net.wifi.usd.SubscribeConfig;
+import android.net.wifi.usd.SubscribeSession;
+import android.net.wifi.usd.SubscribeSessionCallback;
+import android.net.wifi.usd.UsdManager;
+import android.os.Binder;
+import android.os.Bundle;
+import android.util.Log;
+
+import com.android.server.wifi.RunnerHandler;
+import com.android.server.wifi.WifiInjector;
+import com.android.server.wifi.util.WifiPermissionsUtil;
+
+import java.util.Objects;
+import java.util.concurrent.Executor;
+import java.util.function.Consumer;
+
+/**
+ * Implementation of the IUsdManager.
+ */
+public class UsdServiceImpl extends IUsdManager.Stub {
+ private static final String TAG = UsdServiceImpl.class.getName();
+ private final Context mContext;
+ private RunnerHandler mHandler;
+ private WifiInjector mWifiInjector;
+ WifiPermissionsUtil mWifiPermissionsUtil;
+
+
+ /**
+ * Constructor
+ */
+ public UsdServiceImpl(Context context) {
+ mContext = context;
+ }
+
+ /**
+ * Start the service
+ */
+ public void start(@NonNull WifiInjector wifiInjector) {
+ mWifiInjector = wifiInjector;
+ mWifiPermissionsUtil = mWifiInjector.getWifiPermissionsUtil();
+ Log.i(TAG, "start");
+ }
+
+ /**
+ * Start/initialize portions of the service which require the boot stage to be complete.
+ */
+ public void startLate() {
+ Log.i(TAG, "startLate");
+ }
+
+ /**
+ * Proxy for the final native call of the parent class. Enables mocking of
+ * the function.
+ */
+ public int getMockableCallingUid() {
+ return Binder.getCallingUid();
+ }
+
+ /**
+ * See {@link UsdManager#isSubscriberAvailable()}
+ */
+ @Override
+ public boolean isSubscriberAvailable() {
+ int uid = getMockableCallingUid();
+ if (!mWifiPermissionsUtil.checkManageWifiNetworkSelectionPermission(uid)) {
+ throw new SecurityException("App not allowed to use USD (uid = " + uid + ")");
+ }
+ Log.i(TAG, "Subscriber is not available");
+ return false;
+ }
+
+ /**
+ * See {@link UsdManager#isPublisherAvailable()}
+ */
+ @Override
+ public boolean isPublisherAvailable() {
+ int uid = getMockableCallingUid();
+ if (!mWifiPermissionsUtil.checkManageWifiNetworkSelectionPermission(uid)) {
+ throw new SecurityException("App not allowed to use USD (uid = " + uid + ")");
+ }
+ Log.i(TAG, "Publisher is not available");
+ return false;
+ }
+
+ /**
+ * See
+ * {@link UsdManager#registerAvailabilityCallback(Executor, UsdManager.AvailabilityCallback)}
+ */
+ @Override
+ public void registerAvailabilityCallback(IAvailabilityCallback callback) {
+ int uid = getMockableCallingUid();
+ if (!mWifiPermissionsUtil.checkManageWifiNetworkSelectionPermission(uid)) {
+ throw new SecurityException("App not allowed to use USD (uid = " + uid + ")");
+ }
+ }
+
+ /**
+ * See {@link UsdManager#unregisterAvailabilityCallback(UsdManager.AvailabilityCallback)}
+ */
+ @Override
+ public void unregisterAvailabilityCallback(IAvailabilityCallback callback) {
+ int uid = getMockableCallingUid();
+ if (!mWifiPermissionsUtil.checkManageWifiNetworkSelectionPermission(uid)) {
+ throw new SecurityException("App not allowed to use USD (uid = " + uid + ")");
+ }
+ }
+
+ /**
+ * See {@link UsdManager#getCharacteristics()}
+ */
+ @Override
+ public Characteristics getCharacteristics() {
+ int uid = getMockableCallingUid();
+ if (!mWifiPermissionsUtil.checkManageWifiNetworkSelectionPermission(uid)) {
+ throw new SecurityException("App not allowed to use USD (uid = " + uid + ")");
+ }
+
+ Bundle bundle = new Bundle();
+ bundle.putInt(Characteristics.KEY_MAX_NUM_SUBSCRIBE_SESSIONS, 0);
+ bundle.putInt(Characteristics.KEY_MAX_NUM_SUBSCRIBE_SESSIONS, 0);
+ bundle.putInt(Characteristics.KEY_MAX_SERVICE_SPECIFIC_INFO_LENGTH, 0);
+ bundle.putInt(Characteristics.KEY_MAX_MATCH_FILTER_LENGTH, 0);
+ bundle.putInt(Characteristics.KEY_MAX_SERVICE_NAME_LENGTH, 0);
+ return new Characteristics(bundle);
+ }
+
+ /**
+ * See {@link SubscribeSession#sendMessage(int, byte[], Executor, Consumer)}
+ */
+ public void sendMessage(int peerId, @NonNull byte[] message,
+ @NonNull IBooleanListener listener) {
+ Objects.requireNonNull(message, "message must not be null");
+ Objects.requireNonNull(listener, "listener must not be null");
+ int uid = getMockableCallingUid();
+ if (!mWifiPermissionsUtil.checkManageWifiNetworkSelectionPermission(uid)) {
+ throw new SecurityException("App not allowed to use USD (uid = " + uid + ")");
+ }
+ Log.i(TAG, "sendMessage ( peerId = " + peerId + " , message length = " + message.length
+ + " )");
+ }
+
+ /**
+ * See {@link SubscribeSession#cancel()}
+ */
+ public void cancelSubscribe(int sessionId) {
+ int uid = getMockableCallingUid();
+ if (!mWifiPermissionsUtil.checkManageWifiNetworkSelectionPermission(uid)) {
+ throw new SecurityException("App not allowed to use USD (uid = " + uid + ")");
+ }
+ Log.i(TAG, "cancelSubscribe: ( sessionId = " + sessionId + " )");
+ }
+
+ /**
+ * See {@link PublishSession#cancel()}
+ */
+ public void cancelPublish(int sessionId) {
+ int uid = getMockableCallingUid();
+ if (!mWifiPermissionsUtil.checkManageWifiNetworkSelectionPermission(uid)) {
+ throw new SecurityException("App not allowed to use USD (uid = " + uid + ")");
+ }
+ Log.i(TAG, "cancelPublish: ( sessionId = " + sessionId + " )");
+ }
+
+ /**
+ * See {@link PublishSession#updatePublish(byte[])}
+ */
+ public void updatePublish(int sessionId, @NonNull byte[] ssi) {
+ Objects.requireNonNull(ssi, "Service specific info must not be null");
+ int uid = getMockableCallingUid();
+ if (!mWifiPermissionsUtil.checkManageWifiNetworkSelectionPermission(uid)) {
+ throw new SecurityException("App not allowed to use USD (uid = " + uid + ")");
+ }
+ Log.i(TAG, "updatePublish: ( sessionId = " + sessionId + " )");
+ }
+
+ /**
+ * See {@link UsdManager#publish(PublishConfig, Executor, PublishSessionCallback)}
+ */
+ @Override
+ public void publish(PublishConfig publishConfig, IPublishSessionCallback callback) {
+ Objects.requireNonNull(publishConfig, "publishConfig must not be null");
+ Objects.requireNonNull(callback, "callback must not be null");
+ int uid = getMockableCallingUid();
+ if (!mWifiPermissionsUtil.checkManageWifiNetworkSelectionPermission(uid)) {
+ throw new SecurityException("App not allowed to use USD (uid = " + uid + ")");
+ }
+ Log.i(TAG, "publish " + publishConfig);
+ }
+
+ /**
+ * See {@link UsdManager#subscribe(SubscribeConfig, Executor, SubscribeSessionCallback)}
+ */
+ @Override
+ public void subscribe(SubscribeConfig subscribeConfig, ISubscribeSessionCallback callback) {
+ Objects.requireNonNull(subscribeConfig, "subscribeConfig must not be null");
+ Objects.requireNonNull(callback, "callback must not be null");
+ int uid = getMockableCallingUid();
+ if (!mWifiPermissionsUtil.checkManageWifiNetworkSelectionPermission(uid)) {
+ throw new SecurityException("App not allowed to use USD (uid = " + uid + ")");
+ }
+ Log.i(TAG, "subscribe " + subscribeConfig);
+ }
+}
diff --git a/service/java/com/android/server/wifi/util/ApConfigUtil.java b/service/java/com/android/server/wifi/util/ApConfigUtil.java
index 3da0bf1..b2bb510 100644
--- a/service/java/com/android/server/wifi/util/ApConfigUtil.java
+++ b/service/java/com/android/server/wifi/util/ApConfigUtil.java
@@ -36,6 +36,8 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.content.Context;
+import android.content.res.Resources;
import android.net.wifi.CoexUnsafeChannel;
import android.net.wifi.ScanResult;
import android.net.wifi.SoftApCapability;
@@ -55,12 +57,16 @@
import android.util.SparseArray;
import android.util.SparseIntArray;
+import androidx.annotation.Keep;
+
import com.android.internal.annotations.VisibleForTesting;
import com.android.modules.utils.build.SdkLevel;
import com.android.server.wifi.SoftApManager;
+import com.android.server.wifi.WifiInjector;
import com.android.server.wifi.WifiNative;
import com.android.server.wifi.WifiSettingsConfigStore;
import com.android.server.wifi.coex.CoexManager;
+import com.android.wifi.flags.Flags;
import com.android.wifi.resources.R;
import java.util.ArrayList;
@@ -464,16 +470,20 @@
*
* @param band to get channels for
* @param wifiNative reference used to get regulatory restrictions.
- * @param resources used to get OEM restrictions
+ * @param resources used to get OEM restrictions.
* @param inFrequencyMHz true to convert channel to frequency.
* @return A list of frequencies that are allowed, null on error.
+ * TODO(b/380087289): Resources will be removed in the future together with the @keep annotation
*/
+ @Keep
public static List<Integer> getAvailableChannelFreqsForBand(
- @BandType int band, WifiNative wifiNative, WifiResourceCache resources,
+ @BandType int band, WifiNative wifiNative, Resources resources,
boolean inFrequencyMHz) {
if (!isBandValid(band) || isMultiband(band)) {
return null;
}
+ WifiResourceCache resourceCache = WifiInjector.getInstance().getContext()
+ .getResourceCache();
int scannerBand = apConfig2wifiScannerBand(band);
List<Integer> regulatoryList = null;
@@ -488,7 +498,7 @@
// HAL is not started, return null
return null;
}
- regulatoryList = getHalAvailableChannelsForBand(scannerBand, wifiNative, resources,
+ regulatoryList = getHalAvailableChannelsForBand(scannerBand, wifiNative, resourceCache,
inFrequencyMHz);
if (regulatoryList == null) {
// HAL API not supported by HAL, fallback to wificond
@@ -496,10 +506,10 @@
}
}
if (useWifiCond) {
- regulatoryList = getWifiCondAvailableChannelsForBand(scannerBand, wifiNative, resources,
- inFrequencyMHz);
+ regulatoryList = getWifiCondAvailableChannelsForBand(scannerBand, wifiNative,
+ resourceCache, inFrequencyMHz);
}
- List<Integer> configuredList = getConfiguredChannelList(resources, band);
+ List<Integer> configuredList = getConfiguredChannelList(resourceCache, band);
if (configuredList == null || configuredList.isEmpty() || regulatoryList == null) {
return regulatoryList;
}
@@ -894,24 +904,40 @@
* IEEE80211BE & single link MLO in bridged mode from the resource file.
* @param config The current {@link SoftApConfiguration}.
* @param isBridgedMode true if bridged mode is enabled, false otherwise.
+ * @param currentExistingMLD number of existing 11BE SoftApManager.
+ * @param isMLDApSupportMLO true if the chip reports the support multiple links
+ * on a single MLD AP.
*
* @return true if IEEE80211BE is allowed for the given configuration, false otherwise.
*/
public static boolean is11beAllowedForThisConfiguration(DeviceWiphyCapabilities capabilities,
@NonNull WifiContext context,
SoftApConfiguration config,
- boolean isBridgedMode) {
+ boolean isBridgedMode, int currentExistingMLD,
+ boolean isMLDApSupportMLO) {
if (!ApConfigUtil.isIeee80211beSupported(context)) {
return false;
}
- if (capabilities == null || !capabilities.isWifiStandardSupported(
- ScanResult.WIFI_STANDARD_11BE)) {
- return false;
+ if (!isMLDApSupportMLO) {
+ // For non-MLO case, check capabilities
+ if (capabilities == null || !capabilities.isWifiStandardSupported(
+ ScanResult.WIFI_STANDARD_11BE)) {
+ return false;
+ }
}
- if (isBridgedMode
- && !context.getResourceCache().getBoolean(
- R.bool.config_wifiSoftApSingleLinkMloInBridgedModeSupported)) {
- return false;
+ if (Flags.mloSap()) {
+ if (!hasAvailableMLD(context, isBridgedMode,
+ currentExistingMLD, isMLDApSupportMLO)) {
+ Log.i(TAG, "No available MLD, hence downgrading from 11be. currentExistingMLD = "
+ + currentExistingMLD + ", isMLDApSupportMLO = " + isMLDApSupportMLO);
+ return false;
+ }
+ } else {
+ if (isBridgedMode
+ && !context.getResourceCache().getBoolean(
+ R.bool.config_wifiSoftApSingleLinkMloInBridgedModeSupported)) {
+ return false;
+ }
}
if (is11beDisabledForSecurityType(config.getSecurityType())) {
return false;
@@ -919,6 +945,34 @@
return true;
}
+ private static boolean hasAvailableMLD(@NonNull WifiContext context,
+ boolean isBridgedMode, int currentExistingMLD,
+ boolean isMLDApSupportMLO) {
+ int numberOfMLDStillAllowed =
+ maximumNumberOfMLDForMLOAp(context) - currentExistingMLD;
+ if (numberOfMLDStillAllowed < 1) {
+ return false;
+ }
+ if (isBridgedMode && !isMLDApSupportMLO && numberOfMLDStillAllowed < 2) {
+ // For non multilink MLO bridged mode, it requires two 11be instances.
+ return false;
+ }
+ return true;
+ }
+
+ private static int maximumNumberOfMLDForMLOAp(@NonNull WifiContext context) {
+ int numberOfMLDSupported = context.getResourceCache()
+ .getInteger(R.integer.config_wifiSoftApMaxNumberMLDSupported);
+ if (numberOfMLDSupported != 0) {
+ return numberOfMLDSupported;
+ }
+ if (context.getResourceCache().getBoolean(
+ R.bool.config_wifiSoftApSingleLinkMloInBridgedModeSupported)) {
+ return 2;
+ }
+ return 1;
+ }
+
/**
* Update AP band and channel based on the provided country code and band.
* This will also set
@@ -1044,7 +1098,14 @@
* @return SoftApCapability which updated the feature support or not from resource.
*/
@NonNull
- public static SoftApCapability updateCapabilityFromResource(@NonNull WifiContext context) {
+ @Keep
+ public static SoftApCapability updateCapabilityFromResource(@NonNull Context contextIn) {
+ WifiContext context;
+ if (contextIn instanceof WifiContext) {
+ context = (WifiContext) contextIn;
+ } else {
+ context = new WifiContext(contextIn);
+ }
long features = 0;
if (isAcsSupported(context)) {
Log.d(TAG, "Update Softap capability, add acs feature support");
@@ -1246,7 +1307,14 @@
* @param context the caller context used to get value from resource file.
* @return true if supported, false otherwise.
*/
- public static boolean isWpa3SaeSupported(@NonNull WifiContext context) {
+ @Keep
+ public static boolean isWpa3SaeSupported(@NonNull Context contextIn) {
+ WifiContext context;
+ if (contextIn instanceof WifiContext) {
+ context = (WifiContext) contextIn;
+ } else {
+ context = new WifiContext(contextIn);
+ }
return context.getResourceCache().getBoolean(
R.bool.config_wifi_softap_sae_supported);
}
@@ -1280,9 +1348,15 @@
* @param band the band soft AP to operate on.
* @return true if supported, false otherwise.
*/
- public static boolean isSoftApBandSupported(@NonNull WifiContext context,
+ @Keep
+ public static boolean isSoftApBandSupported(@NonNull Context contextIn,
@BandType int band) {
-
+ WifiContext context;
+ if (contextIn instanceof WifiContext) {
+ context = (WifiContext) contextIn;
+ } else {
+ context = new WifiContext(contextIn);
+ }
switch (band) {
case SoftApConfiguration.BAND_2GHZ:
return context.getResourceCache().getBoolean(R.bool.config_wifi24ghzSupport)
@@ -1681,7 +1755,7 @@
for (int band : SoftApConfiguration.BAND_TYPES) {
if (isSoftApBandSupported(context, band)) {
supportedChannelList = getAvailableChannelFreqsForBand(
- band, wifiNative, context.getResourceCache(), false);
+ band, wifiNative, null, false);
if (supportedChannelList != null) {
newSoftApCapability.setSupportedChannelList(
band,
diff --git a/service/java/com/android/server/wifi/util/InformationElementUtil.java b/service/java/com/android/server/wifi/util/InformationElementUtil.java
index ea49957..37a07a5 100644
--- a/service/java/com/android/server/wifi/util/InformationElementUtil.java
+++ b/service/java/com/android/server/wifi/util/InformationElementUtil.java
@@ -1870,6 +1870,8 @@
private static final int RSN_AKM_PSK = 0x02ac0f00;
private static final int RSN_AKM_FT_EAP = 0x03ac0f00;
private static final int RSN_AKM_FT_PSK = 0x04ac0f00;
+ private static final int RSN_AKM_FT_PSK_SHA384 = 0x13ac0f00;
+ private static final int RSN_AKM_EAP_FT_SHA384 = 0x0dac0f00;
private static final int RSN_AKM_EAP_SHA256 = 0x05ac0f00;
private static final int RSN_AKM_PSK_SHA256 = 0x06ac0f00;
private static final int RSN_AKM_SAE = 0x08ac0f00;
@@ -1882,6 +1884,7 @@
private static final int RSN_AKM_SAE_EXT_KEY = 0x18ac0f00;
private static final int RSN_AKM_FT_SAE_EXT_KEY = 0x19ac0f00;
private static final int RSN_AKM_DPP = 0x029a6f50;
+ private static final int RSN_AKM_PASN = 0x15ac0f00;
private static final int WPA_CIPHER_NONE = 0x00f25000;
private static final int WPA_CIPHER_TKIP = 0x02f25000;
@@ -2024,6 +2027,15 @@
case RSN_AKM_DPP:
rsnKeyManagement.add(ScanResult.KEY_MGMT_DPP);
break;
+ case RSN_AKM_FT_PSK_SHA384:
+ rsnKeyManagement.add(ScanResult.KEY_MGMT_FT_PSK_SHA384);
+ break;
+ case RSN_AKM_EAP_FT_SHA384:
+ rsnKeyManagement.add(ScanResult.KEY_MGMT_EAP_FT_SHA384);
+ break;
+ case RSN_AKM_PASN:
+ rsnKeyManagement.add(ScanResult.KEY_MGMT_PASN);
+ break;
default: {
int akmScheme =
getScanResultAkmSchemeOfUnknownAkmIfConfigured(
@@ -2380,6 +2392,12 @@
return ScanResult.KEY_MGMT_FILS_SHA384;
case RSN_AKM_DPP:
return ScanResult.KEY_MGMT_DPP;
+ case RSN_AKM_FT_PSK_SHA384:
+ return ScanResult.KEY_MGMT_FT_PSK_SHA384;
+ case RSN_AKM_EAP_FT_SHA384:
+ return ScanResult.KEY_MGMT_EAP_FT_SHA384;
+ case RSN_AKM_PASN:
+ return ScanResult.KEY_MGMT_PASN;
default:
return ScanResult.KEY_MGMT_UNKNOWN;
}
@@ -2455,6 +2473,12 @@
return "EAP-FILS-SHA384";
case ScanResult.KEY_MGMT_DPP:
return "DPP";
+ case ScanResult.KEY_MGMT_FT_PSK_SHA384:
+ return "FT/PSK-SHA384";
+ case ScanResult.KEY_MGMT_EAP_FT_SHA384:
+ return "EAP-FT-SHA384";
+ case ScanResult.KEY_MGMT_PASN:
+ return "PASN";
default:
return "?";
}
@@ -2853,4 +2877,49 @@
return mCountryCode;
}
}
+
+ /*
+ * RSNXE (Robust Security Network Extended) Field
+ *
+ * RSNXE is a field within Wi-Fi beacon frames that provides extra information about the
+ * access point's security capabilities, going beyond the basics of RSN (Robust Security
+ * Network).
+ */
+ public static class Rsnxe {
+ private static final int SECURE_HE_LTF_SUPPORT_BIT = 8;
+ private static final int URNM_MFPR_BIT = 15;
+ private boolean mIsSecureHeLtfSupported;
+ private boolean mIsRangingFrameProtectionRequired;
+
+ /**
+ * Parse RSN extension element
+ * @param ie Information element
+ */
+ public void from(InformationElement ie) {
+ if (ie == null || ie.id != InformationElement.EID_RSN_EXTENSION) return;
+ BitSet rsnxBitset = BitSet.valueOf(
+ ByteBuffer.wrap(ie.bytes).order(ByteOrder.LITTLE_ENDIAN));
+ mIsSecureHeLtfSupported = rsnxBitset.get(SECURE_HE_LTF_SUPPORT_BIT);
+ mIsRangingFrameProtectionRequired = rsnxBitset.get(URNM_MFPR_BIT);
+ }
+
+ /**
+ * The secure HE-LTF is a security enhancement for ranging measurements where the HE-LTF
+ * sequence is randomized using cryptographic keys derived from the security association.
+ *
+ * @return Whether the secure HE-LTF is supported or not.
+ */
+ public boolean isSecureHeLtfSupported() {
+ return mIsSecureHeLtfSupported;
+ }
+
+ /**
+ * A security policy that specifies whether ranging frames are required to be protected
+ * without association.
+ * @return Whether ranging frames are required to be protected or not.
+ */
+ public boolean isRangingFrameProtectionRequired() {
+ return mIsRangingFrameProtectionRequired;
+ }
+ }
}
diff --git a/service/java/com/android/server/wifi/util/XmlUtil.java b/service/java/com/android/server/wifi/util/XmlUtil.java
index 0f70340..3c07365 100644
--- a/service/java/com/android/server/wifi/util/XmlUtil.java
+++ b/service/java/com/android/server/wifi/util/XmlUtil.java
@@ -20,6 +20,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SuppressLint;
import android.app.compat.CompatChanges;
import android.net.InetAddresses;
import android.net.IpConfiguration;
@@ -41,6 +42,7 @@
import android.net.wifi.WifiManager;
import android.net.wifi.WifiMigration;
import android.net.wifi.WifiSsid;
+import android.net.wifi.util.Environment;
import android.os.ParcelUuid;
import android.os.PersistableBundle;
import android.text.TextUtils;
@@ -49,6 +51,7 @@
import android.util.SparseIntArray;
import com.android.modules.utils.build.SdkLevel;
+import com.android.wifi.flags.Flags;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -1975,6 +1978,7 @@
public static final String XML_TAG_PERSISTENT_RANDOMIZED_MAC_ADDRESS =
"PersistentRandomizedMacAddress";
public static final String XML_TAG_MAX_CHANNEL_WIDTH = "MaxChannelWidth";
+ public static final String XML_TAG_CLIENT_ISOLATION = "ClientIsolation";
/**
@@ -2129,6 +2133,7 @@
* @param out XmlSerializer instance pointing to the XML stream.
* @param softApConfig configuration of the Soft AP.
*/
+ @SuppressLint("NewApi")
public static void writeSoftApConfigurationToXml(@NonNull XmlSerializer out,
@NonNull SoftApConfiguration softApConfig,
WifiConfigStoreEncryptionUtil encryptionUtil)
@@ -2206,6 +2211,10 @@
if (SdkLevel.isAtLeastV()) {
writeVendorDataListToXml(out, softApConfig.getVendorData());
}
+ if (Flags.apIsolate() && Environment.isSdkAtLeastB()) {
+ XmlUtil.writeNextValue(out, XML_TAG_CLIENT_ISOLATION,
+ softApConfig.isClientIsolationEnabled());
+ }
} // End of writeSoftApConfigurationToXml
/**
@@ -2215,6 +2224,7 @@
* @param outerTagDepth depth of the outer tag in the XML document.
* @param settingsMigrationDataHolder the class instance of SettingsMigrationDataHolder
*/
+ @SuppressLint("NewApi")
@Nullable
public static SoftApConfiguration parseFromXml(XmlPullParser in, int outerTagDepth,
SettingsMigrationDataHolder settingsMigrationDataHolder,
@@ -2361,6 +2371,11 @@
softApConfigBuilder.setMaxChannelBandwidth((int) value);
}
break;
+ case XML_TAG_CLIENT_ISOLATION:
+ if (Flags.apIsolate() && Environment.isSdkAtLeastB()) {
+ softApConfigBuilder.setClientIsolationEnabled((boolean) value);
+ }
+ break;
default:
Log.w(TAG, "Ignoring unknown value name " + valueName[0]);
break;
diff --git a/service/proto/src/metrics.proto b/service/proto/src/metrics.proto
index a27864f..4a53854 100644
--- a/service/proto/src/metrics.proto
+++ b/service/proto/src/metrics.proto
@@ -774,6 +774,12 @@
// and telephony.
// Bucket value is capped to WifiMetrics.MAX_COUNTRY_CODE_COUNT.
repeated Int32Count country_code_scan_histogram = 219;
+
+ // Each WifiUsabilityStatsTraining instance contains a list of WifiUsabilityStatsEntry objects,
+ // representing a time series of WiFi usability statistics recorded within a specific data
+ // capture period. It also includes information about the type of data capture and the duration
+ // of the capture period.
+ repeated WifiUsabilityStatsTraining wifi_usability_stats_training = 220;
}
// Information that gets logged for every WiFi connection.
@@ -1466,6 +1472,15 @@
// Wi-Fi 7 support for this network has been enabled or disabled.
DISCONNECT_NETWORK_WIFI7_TOGGLED = 17;
+
+ // IP configuration is lost. Triggered by connectivity
+ DISCONNECT_IP_CONFIGURATION_LOST = 18;
+
+ // IP reachability is lost. Triggered by connectivity
+ DISCONNECT_IP_REACHABILITY_LOST = 19;
+
+ // No credentials
+ DISCONNECT_NO_CREDENTIALS = 20;
}
// Authentication Failure reasons as reported through the API.
@@ -2563,6 +2578,32 @@
NETWORK_TYPE_NR = 7;
}
+ enum CaptureEventType {
+ // Unknown event
+ CAPTURE_EVENT_TYPE_UNKNOWN = 0;
+
+ // This is a synchronous event
+ CAPTURE_EVENT_TYPE_SYNCHRONOUS = 1;
+
+ // RSSI polling turned on
+ CAPTURE_EVENT_TYPE_RSSI_POLLING_ENABLED = 2;
+
+ // RSSI polling turned off
+ CAPTURE_EVENT_TYPE_RSSI_POLLING_DISABLED = 3;
+
+ // Data sample came from CMD_ONESHOT_RSSI_POLL
+ CAPTURE_EVENT_TYPE_ONESHOT_RSSI_POLL = 4;
+
+ // IP reachability lost
+ CAPTURE_EVENT_TYPE_IP_REACHABILITY_LOST = 5;
+
+ // IP reachability failure
+ CAPTURE_EVENT_TYPE_IP_REACHABILITY_FAILURE = 6;
+
+ // Firmware alert
+ CAPTURE_EVENT_TYPE_FIRMWARE_ALERT = 7;
+ }
+
// Absolute milliseconds from device boot when these stats were sampled
optional int64 time_stamp_ms = 1;
@@ -2709,6 +2750,71 @@
// Link layer radio stats for all the radios
repeated RadioStats radio_stats = 44;
+
+ // Number of WiFi links.
+ optional int32 wifi_link_count = 45;
+
+ // Link layer radio stats for all WiFi links
+ repeated LinkStats link_stats = 46;
+
+ // The MLO mode
+ // See details in @WifiManager.MloMode
+ optional int32 mlo_mode = 47;
+
+ // The number of tx bytes transmitted on current interface
+ optional int64 tx_transmitted_bytes = 48;
+
+ // The number of rx bytes transmitted on current interface
+ optional int64 rx_transmitted_bytes = 49;
+
+ // The total number of LABEL_BAD event happens
+ optional int32 label_bad_event_count = 50;
+
+ // Current WiFi state in framework
+ optional int32 wifi_framework_state = 51;
+
+ // Downstream throughput estimation provided by Network Capabilities
+ optional int32 is_network_capabilities_downstream_sufficient = 52;
+
+ // Upstream throughput estimation provided by Network Capabilities
+ optional int32 is_network_capabilities_upstream_sufficient = 53;
+
+ // Downstream throughput estimation used in Network Selection
+ optional int32 is_throughput_predictor_downstream_sufficient = 54;
+
+ // Upstream throughput estimation provided by Network Capabilities
+ optional int32 is_throughput_predictor_upstream_sufficient = 55;
+
+ // If bluetooth is connected
+ optional bool is_bluetooth_connected = 56;
+
+ // State of UWB adapter. Refers to
+ // UwbManager#registerAdapterStateCallback(Executor, AdapterStateCallback)
+ optional int32 uwb_adapter_state = 57;
+
+ // Wifi Low Latency mode state
+ optional bool is_low_latency_activated = 58;
+
+ // Maximum supported tx link speed in Mbps
+ optional int32 max_supported_tx_linkspeed = 59;
+
+ // Maximum supported rx link speed in Mbps
+ optional int32 max_supported_rx_linkspeed = 60;
+
+ // Wifi Voip mode state
+ optional int32 voip_mode = 61;
+
+ // Device Role of thread. Refers to ThreadNetworkController@DeviceRole
+ optional int32 thread_device_role = 62;
+
+ // Capture buffer event type
+ optional CaptureEventType capture_event_type = 63;
+
+ // Some capture event types (eg. ip reachability lost) have a code associated
+ // with them. This code is stored here.
+ optional int32 capture_event_type_subcode = 64;
+
+ optional int32 status_data_stall = 65;
}
message ContentionTimeStats {
@@ -2742,6 +2848,37 @@
optional int64 contention_num_samples = 5;
}
+message PacketStats {
+ enum AccessCategory {
+ // WME Best Effort Access Category
+ WME_ACCESS_CATEGORY_BE = 0;
+
+ // WME Background Access Category
+ WME_ACCESS_CATEGORY_BK = 1;
+
+ // WME Video Access Category
+ WME_ACCESS_CATEGORY_VI = 2;
+
+ // WME Voice Access Category
+ WME_ACCESS_CATEGORY_VO = 3;
+ }
+
+ // WME access category
+ optional AccessCategory access_category = 1;
+
+ // The number of tx success counted from the last radio chip reset
+ optional int64 tx_success = 2;
+
+ // The number of MPDU data packet retries counted from the last radio chip reset
+ optional int64 tx_retries = 3;
+
+ // The number of tx bad counted from the last radio chip reset
+ optional int64 tx_bad = 4;
+
+ // The number of rx success counted from the last radio chip reset
+ optional int64 rx_success = 5;
+}
+
message RateStats {
enum WifiPreambleType {
// Preamble type for IEEE 802.11a/g, IEEE Std 802.11-2020, Section 17
@@ -2786,6 +2923,8 @@
WIFI_BANDWIDTH_5_MHZ = 5;
// Channel bandwidth: 10MHz
WIFI_BANDWIDTH_10_MHZ = 6;
+ // Channel bandwidth: 320MHz
+ WIFI_BANDWIDTH_320_MHZ = 7;
// Invalid channel bandwidth
WIFI_BANDWIDTH_INVALID = -1;
}
@@ -2849,6 +2988,123 @@
// The total time spent on hotspot2.0 scans and GAS exchange in ms counted from the last radio
// chip reset
optional int64 total_hotspot_2_scan_time_ms = 10;
+
+ // Time for which the radio is in active tranmission per tx level
+ repeated int32 tx_time_ms_per_level = 11;
+}
+
+message LinkStats {
+ enum LinkState {
+ // Chip does not support reporting the state of the link
+ LINK_STATE_UNKNOWN = 0;
+
+ // Link has not been in use since last report. It is placed in power save
+ LINK_STATE_NOT_IN_USE = 1;
+
+ // Link is in use. In presence of traffic, it is set to be power active.
+ LINK_STATE_IN_USE = 2;
+ }
+
+ enum WifiChannelBandwidth {
+ // Channel bandwidth: 20MHz
+ WIFI_BANDWIDTH_20_MHZ = 0;
+ // Channel bandwidth: 40MHz
+ WIFI_BANDWIDTH_40_MHZ = 1;
+ // Channel bandwidth: 80MHz
+ WIFI_BANDWIDTH_80_MHZ = 2;
+ // Channel bandwidth: 160MHz
+ WIFI_BANDWIDTH_160_MHZ = 3;
+ // Channel bandwidth: 80MHz + 80MHz
+ WIFI_BANDWIDTH_80P80_MHZ = 4;
+ // Channel bandwidth: 5MHz
+ WIFI_BANDWIDTH_5_MHZ = 5;
+ // Channel bandwidth: 10MHz
+ WIFI_BANDWIDTH_10_MHZ = 6;
+ // Channel bandwidth: 320MHz
+ WIFI_BANDWIDTH_320_MHZ = 7;
+ // Invalid channel bandwidth
+ WIFI_BANDWIDTH_INVALID = -1;
+ }
+
+ // The Link ID
+ optional int32 link_id = 1;
+
+ // Link state
+ optional LinkState state = 2;
+
+ // Identifier of the radio on which link is currently operating
+ optional int32 radio_id = 3;
+
+ // Frequency of the link in MHz
+ optional int32 frequency_mhz = 4;
+
+ // Number of beacons received from our own AP
+ optional int32 beacon_rx = 5;
+
+ // RSSI of management frames
+ optional int32 rssi_mgmt = 6;
+
+ // Duty cycle of the link.
+ optional int32 time_slice_duty_cycle_in_percent = 7;
+
+ // Overall RSSI from wpa_supplicant signal_poll
+ optional int32 rssi = 8;
+
+ // channel width of WiFi link.
+ optional WifiChannelBandwidth channel_width = 9;
+
+ // Center frequency (MHz) of first segment.
+ optional int32 center_freq_first_seg = 10;
+
+ // Center frequency (MHz) of second segment.
+ optional int32 center_freq_second_seg = 11;
+
+ // Total time for which the radio is awake on this channel.
+ optional int64 on_time_in_ms = 12;
+
+ // Total time for which CCA is held busy on this channel.
+ optional int64 cca_busy_time_in_ms = 13;
+
+ // WME data packet contention time statistics for all four categories: BE, BK, VI, VO
+ repeated ContentionTimeStats contention_time_stats = 14;
+
+ // Packet statistics for all four categories: BE, BK, VI, VO
+ repeated PacketStats packet_stats = 15;
+
+ // Peer statistics on this WiFi link
+ repeated PeerInfo peer_info = 16;
+
+ // List of scan results who have the same freq with current WiFi link
+ repeated ScanResultWithSameFreq scan_result_with_same_freq = 17;
+
+ // TX linkspeed in this WiFi link
+ optional int32 tx_linkspeed = 18;
+
+ // RX linkspeed in this WiFi link
+ optional int32 rx_linkspeed = 19;
+}
+
+message PeerInfo {
+ // Station count.
+ optional int32 sta_count = 1;
+
+ // Channel utilization.
+ optional int32 chan_util = 2;
+
+ // Rate statistics, including number of successful packets, retries, etc.,
+ // indexed by preamble, bandwidth, number of spatial streams, MCS.
+ repeated RateStats rate_stats = 3;
+}
+
+message ScanResultWithSameFreq {
+ // timestamp in microseconds (since boot) when this result was last seen.
+ optional int64 scan_result_timestamp_micros = 1;
+
+ // The detected signal level in dBm
+ optional int32 rssi = 2;
+
+ // The center frequency of the primary 20 MHz frequency (in MHz) of the channel
+ optional int32 frequencyMhz = 3;
}
message WifiUsabilityStats {
@@ -2900,6 +3156,21 @@
optional int64 time_stamp_ms = 5;
}
+message TrainingData {
+ // The list of timestamped wifi usability stats
+ repeated WifiUsabilityStatsEntry stats = 1;
+}
+
+message WifiUsabilityStatsTraining {
+ // Data capture type
+ optional int32 data_capture_type = 1;
+
+ // Capture period start timestamp floored to the nearest hour.
+ optional int64 capture_start_timestamp_secs = 2;
+
+ optional TrainingData training_data = 3;
+}
+
message DeviceMobilityStatePnoScanStats {
// see WifiManager.DEVICE_MOBILITY_STATE_* constants
enum DeviceMobilityState {
diff --git a/service/tests/wifitests/src/com/android/server/wifi/ActiveModeWardenTest.java b/service/tests/wifitests/src/com/android/server/wifi/ActiveModeWardenTest.java
index 18d1fbe..b859e2a 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/ActiveModeWardenTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/ActiveModeWardenTest.java
@@ -18,9 +18,11 @@
import static android.net.wifi.WifiManager.SAP_START_FAILURE_GENERAL;
import static android.net.wifi.WifiManager.WIFI_AP_STATE_FAILED;
+import static android.net.wifi.WifiManager.WIFI_STATE_DISABLED;
import static android.net.wifi.WifiManager.WIFI_STATE_DISABLING;
import static android.net.wifi.WifiManager.WIFI_STATE_ENABLED;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_LOCAL_ONLY;
import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_PRIMARY;
import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_SCAN_ONLY;
@@ -29,6 +31,9 @@
import static com.android.server.wifi.ActiveModeManager.ROLE_SOFTAP_LOCAL_ONLY;
import static com.android.server.wifi.ActiveModeManager.ROLE_SOFTAP_TETHERED;
import static com.android.server.wifi.ActiveModeWarden.INTERNAL_REQUESTOR_WS;
+import static com.android.server.wifi.TestUtil.addCapabilitiesToBitset;
+import static com.android.server.wifi.TestUtil.combineBitsets;
+import static com.android.server.wifi.TestUtil.createCapabilityBitset;
import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_NATIVE_SUPPORTED_STA_BANDS;
import static com.google.common.truth.Truth.assertThat;
@@ -51,6 +56,7 @@
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.isNull;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.mockingDetails;
import static org.mockito.Mockito.never;
@@ -71,6 +77,7 @@
import android.net.wifi.ISubsystemRestartCallback;
import android.net.wifi.IWifiConnectedNetworkScorer;
import android.net.wifi.IWifiNetworkStateChangedListener;
+import android.net.wifi.IWifiStateChangedListener;
import android.net.wifi.SoftApCapability;
import android.net.wifi.SoftApConfiguration;
import android.net.wifi.SoftApConfiguration.Builder;
@@ -84,6 +91,7 @@
import android.net.wifi.util.WifiResourceCache;
import android.os.BatteryStatsManager;
import android.os.Build;
+import android.os.Handler;
import android.os.IBinder;
import android.os.Process;
import android.os.RemoteException;
@@ -96,6 +104,7 @@
import androidx.test.filters.SmallTest;
+import com.android.dx.mockito.inline.extended.StaticMockitoSession;
import com.android.modules.utils.build.SdkLevel;
import com.android.server.wifi.ActiveModeManager.ClientConnectivityRole;
import com.android.server.wifi.ActiveModeManager.Listener;
@@ -119,6 +128,8 @@
import java.io.ByteArrayOutputStream;
import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.BitSet;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
@@ -148,7 +159,9 @@
private static final int TEST_AP_FREQUENCY = 2412;
private static final int TEST_AP_BANDWIDTH = SoftApInfo.CHANNEL_WIDTH_20MHZ;
private static final int TEST_UID = 435546654;
- private static final long TEST_FEATURE_SET = 0xAB3DEF;
+ private static final BitSet TEST_FEATURE_SET = createCapabilityBitset(
+ WifiManager.WIFI_FEATURE_P2P, WifiManager.WIFI_FEATURE_PNO,
+ WifiManager.WIFI_FEATURE_OWE, WifiManager.WIFI_FEATURE_DPP);
private static final String TEST_PACKAGE = "com.test";
private static final String TEST_COUNTRYCODE = "US";
private static final WorkSource TEST_WORKSOURCE = new WorkSource(TEST_UID, TEST_PACKAGE);
@@ -206,6 +219,7 @@
private BroadcastReceiver mEmergencyCallbackModeChangedBr;
private BroadcastReceiver mEmergencyCallStateChangedBr;
+ private StaticMockitoSession mStaticMockSession;
/**
* Set up the test environment.
@@ -215,8 +229,12 @@
Log.d(TAG, "Setting up ...");
MockitoAnnotations.initMocks(this);
+ mStaticMockSession = mockitoSession()
+ .mockStatic(WifiInjector.class)
+ .startMocking();
mLooper = new TestLooper();
+ when(WifiInjector.getInstance()).thenReturn(mWifiInjector);
when(mWifiInjector.getScanRequestProxy()).thenReturn(mScanRequestProxy);
when(mWifiInjector.getSarManager()).thenReturn(mSarManager);
when(mWifiInjector.getHalDeviceManager()).thenReturn(mHalDeviceManager);
@@ -273,6 +291,8 @@
any(WifiServiceImpl.SoftApCallbackInternal.class), any(), any(), any(),
anyBoolean());
when(mWifiNative.initialize()).thenReturn(true);
+ when(mWifiNative.getSupportedFeatureSet(isNull())).thenReturn(new BitSet());
+ when(mWifiNative.getSupportedFeatureSet(anyString())).thenReturn(new BitSet());
when(mWifiPermissionsUtil.isSystem(TEST_PACKAGE, TEST_UID)).thenReturn(true);
mActiveModeWarden = createActiveModeWarden();
@@ -341,6 +361,7 @@
@After
public void cleanUp() throws Exception {
mActiveModeWarden = null;
+ mStaticMockSession.finishMocking();
mLooper.dispatchAll();
}
@@ -375,7 +396,7 @@
* @param isClientModeSwitch true if switching from another mode, false if creating a new one
* @param testFeatureSet a customized feature set to test
*/
- private void enterClientModeActiveState(boolean isClientModeSwitch, long testFeatureSet)
+ private void enterClientModeActiveState(boolean isClientModeSwitch, BitSet testFeatureSet)
throws Exception {
String fromState = mActiveModeWarden.getCurrentMode();
when(mSettingsStore.isWifiToggleEnabled()).thenReturn(true);
@@ -385,7 +406,8 @@
when(mClientModeManager.getRole()).thenReturn(ROLE_CLIENT_PRIMARY);
when(mClientModeManager.getCurrentNetwork()).thenReturn(mNetwork);
- when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn(testFeatureSet);
+ when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME))
+ .thenReturn(testFeatureSet);
// ClientModeManager starts in SCAN_ONLY role.
mClientListener.onRoleChanged(mClientModeManager);
mLooper.dispatchAll();
@@ -406,7 +428,7 @@
}
verify(mClientModeManager, atLeastOnce()).getInterfaceName();
verify(mWifiNative, atLeastOnce()).getSupportedFeatureSet(WIFI_IFACE_NAME);
- assertEquals(testFeatureSet, mActiveModeWarden.getSupportedFeatureSet());
+ assertTrue(testFeatureSet.equals(mActiveModeWarden.getSupportedFeatureSet()));
verify(mScanRequestProxy, times(4)).enableScanning(true, true);
assertEquals(mClientModeManager, mActiveModeWarden.getPrimaryClientModeManager());
verify(mModeChangeCallback).onActiveModeManagerRoleChanged(mClientModeManager);
@@ -448,7 +470,7 @@
verify(mModeChangeCallback, times(2))
.onActiveModeManagerRoleChanged(mClientModeManager);
verify(mWifiNative, atLeastOnce()).getSupportedFeatureSet(null);
- assertEquals(TEST_FEATURE_SET, mActiveModeWarden.getSupportedFeatureSet());
+ assertTrue(TEST_FEATURE_SET.equals(mActiveModeWarden.getSupportedFeatureSet()));
}
assertInEnabledState();
verify(mScanRequestProxy).enableScanning(true, false);
@@ -489,7 +511,7 @@
any(), any(), any(), eq(TEST_WORKSOURCE), eq(softApRole), anyBoolean());
mTimesCreatedSoftApManager++;
if (fromState.equals(DISABLED_STATE_STRING)) {
- verify(mBatteryStats).reportWifiOn();
+ verify(mBatteryStats, atLeastOnce()).reportWifiOn();
}
if (softApRole == ROLE_SOFTAP_TETHERED) {
assertEquals(mSoftApManager, mActiveModeWarden.getTetheredSoftApManager());
@@ -865,6 +887,30 @@
}
@Test
+ public void testClientModeChangeRoleDuringTransition() throws Exception {
+ enterClientModeActiveState();
+ verify(mWifiInjector).makeClientModeManager(
+ any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_PRIMARY), anyBoolean());
+
+ // Simulate the primary not fully started by making the role null and targetRole primary.
+ when(mClientModeManager.getRole()).thenReturn(null);
+ when(mClientModeManager.getTargetRole()).thenReturn(ROLE_CLIENT_PRIMARY);
+ List<ClientModeManager> currentCMMs = mActiveModeWarden.getClientModeManagers();
+ assertEquals(1, currentCMMs.size());
+ ConcreteClientModeManager currentCmm = (ConcreteClientModeManager) currentCMMs.get(0);
+ assertTrue(currentCmm.getTargetRole() == ROLE_CLIENT_PRIMARY);
+
+ // toggle wifi off while wifi scanning is on
+ when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(true);
+ when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false);
+ mActiveModeWarden.wifiToggled(TEST_WORKSOURCE);
+ mLooper.dispatchAll();
+
+ // expect transition to scan only mode
+ verify(mClientModeManager).setRole(eq(ROLE_CLIENT_SCAN_ONLY), any());
+ }
+
+ @Test
public void testPrimaryNotCreatedTwice() throws Exception {
enterClientModeActiveState();
verify(mWifiInjector).makeClientModeManager(
@@ -1063,6 +1109,21 @@
}
/**
+ * Verifies that ClientsDisconnected event is being passed from SoftApManager
+ * to WifiServiceImpl.
+ */
+ @Test
+ public void callsWifiServiceCallbackOnSoftApClientsDisconnected() throws Exception {
+ List<WifiClient> testClients = new ArrayList<>();
+ enterSoftApActiveMode();
+ mSoftApManagerCallback.onClientsDisconnected(mTestSoftApInfo, testClients);
+ mLooper.dispatchAll();
+
+ verify(mSoftApStateMachineCallback).onClientsDisconnected(
+ mTestSoftApInfo, testClients);
+ }
+
+ /**
* Test that we remain in the active state when we get a state change update that scan mode is
* active.
*/
@@ -1505,9 +1566,13 @@
ArgumentCaptor<BroadcastReceiver> bcastRxCaptor =
ArgumentCaptor.forClass(BroadcastReceiver.class);
- verify(mContext).registerReceiver(
+ // Note: Ignore lint warning UnspecifiedRegisterReceiverFlag since here is using
+ // to test receiving for system broadcasts. The lint warning is a false alarm since
+ // here is using argThat and hasAction.
+ verify(mContext).registerReceiverForAllUsers(
bcastRxCaptor.capture(),
- argThat(filter -> filter.hasAction(LocationManager.MODE_CHANGED_ACTION)));
+ argThat(filter -> filter.hasAction(LocationManager.MODE_CHANGED_ACTION)),
+ eq(null), any(Handler.class));
BroadcastReceiver broadcastReceiver = bcastRxCaptor.getValue();
assertInDisabledState();
@@ -1656,9 +1721,10 @@
ArgumentCaptor<BroadcastReceiver> bcastRxCaptor =
ArgumentCaptor.forClass(BroadcastReceiver.class);
- verify(mContext).registerReceiver(
+ verify(mContext).registerReceiverForAllUsers(
bcastRxCaptor.capture(),
- argThat(filter -> filter.hasAction(LocationManager.MODE_CHANGED_ACTION)));
+ argThat(filter -> filter.hasAction(LocationManager.MODE_CHANGED_ACTION)),
+ eq(null), any(Handler.class));
BroadcastReceiver broadcastReceiver = bcastRxCaptor.getValue();
assertInEnabledState();
@@ -2661,6 +2727,52 @@
}
/**
+ * The command to trigger WiFi restart on Bootup.
+ * WiFi is in connect mode, calls to reset the wifi stack due to connection failures
+ * should trigger a supplicant stop, and subsequently, a driver reload. (Reboot)
+ * Create and start WifiController in EnabledState, start softAP and then
+ * send command to restart WiFi
+ * <p>
+ * Expected: Wi-Fi should be restarted successfully on bootup.
+ */
+ @Test
+ public void testRestartWifiStackInStaConnectEnabledStatewithSap() throws Exception {
+ enableWifi();
+ assertInEnabledState();
+ verify(mWifiInjector).makeClientModeManager(
+ any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_PRIMARY), anyBoolean());
+
+ assertWifiShutDown(() -> {
+ mActiveModeWarden.recoveryRestartWifi(SelfRecovery.REASON_WIFINATIVE_FAILURE,
+ true);
+ mLooper.dispatchAll();
+ // Complete the stop
+ mClientListener.onStopped(mClientModeManager);
+ mLooper.dispatchAll();
+ });
+
+ verify(mModeChangeCallback).onActiveModeManagerRemoved(mClientModeManager);
+
+ // still only started once
+ verify(mWifiInjector).makeClientModeManager(
+ any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_PRIMARY), anyBoolean());
+
+ // start softAp
+ enterSoftApActiveMode();
+ assertInEnabledState();
+
+ mLooper.moveTimeForward(TEST_WIFI_RECOVERY_DELAY_MS);
+ mLooper.dispatchAll();
+
+ // started again
+ verify(mWifiInjector, times(2)).makeClientModeManager(any(), any(), any(), anyBoolean());
+ assertInEnabledState();
+
+ verify(mSubsystemRestartCallback).onSubsystemRestarting();
+ verify(mSubsystemRestartCallback).onSubsystemRestarted();
+ }
+
+ /**
* The command to trigger a WiFi reset should not trigger a reset when in ECM mode.
* Enable wifi and enter ECM state, send command to restart wifi.
* <p>
@@ -3004,13 +3116,13 @@
enterClientModeActiveState();
when(mWifiNative.isStaApConcurrencySupported()).thenReturn(false);
mClientListener.onStarted(mClientModeManager);
- assertEquals(0L,
- mActiveModeWarden.getSupportedFeatureSet() & WifiManager.WIFI_FEATURE_AP_STA);
+ assertFalse(mActiveModeWarden.getSupportedFeatureSet()
+ .get(WifiManager.WIFI_FEATURE_AP_STA));
when(mWifiNative.isStaApConcurrencySupported()).thenReturn(true);
mClientListener.onStarted(mClientModeManager);
- assertEquals(WifiManager.WIFI_FEATURE_AP_STA,
- mActiveModeWarden.getSupportedFeatureSet() & WifiManager.WIFI_FEATURE_AP_STA);
+ assertTrue(mActiveModeWarden.getSupportedFeatureSet()
+ .get(WifiManager.WIFI_FEATURE_AP_STA));
}
@Test
@@ -3159,7 +3271,7 @@
private void requestRemoveAdditionalClientModeManagerWhenNotAllowed(
ClientConnectivityRole role, boolean clientIsExpected,
- long featureSet) throws Exception {
+ BitSet featureSet) throws Exception {
enterClientModeActiveState(false, featureSet);
// Connected to ssid1/bssid1
@@ -3514,8 +3626,10 @@
.thenReturn(true);
assertFalse(mActiveModeWarden.canRequestMoreClientModeManagersInRole(
TEST_WORKSOURCE, ROLE_CLIENT_LOCAL_ONLY, false));
+ BitSet expectedFeatureSet = addCapabilitiesToBitset(
+ TEST_FEATURE_SET, WifiManager.WIFI_FEATURE_ADDITIONAL_STA_LOCAL_ONLY);
requestRemoveAdditionalClientModeManagerWhenNotAllowed(ROLE_CLIENT_LOCAL_ONLY,
- true, TEST_FEATURE_SET | WifiManager.WIFI_FEATURE_ADDITIONAL_STA_LOCAL_ONLY);
+ true, expectedFeatureSet);
}
private void testLoFallbackAboveAndroidS(boolean isStaStaSupported) throws Exception {
@@ -3529,9 +3643,9 @@
.thenReturn(false);
assertFalse(mActiveModeWarden.canRequestMoreClientModeManagersInRole(
TEST_WORKSOURCE, ROLE_CLIENT_LOCAL_ONLY, false));
- long expectedFeatureSet = TEST_FEATURE_SET;
+ BitSet expectedFeatureSet = (BitSet) TEST_FEATURE_SET.clone();
if (isStaStaSupported) {
- expectedFeatureSet |= WifiManager.WIFI_FEATURE_ADDITIONAL_STA_LOCAL_ONLY;
+ expectedFeatureSet.set(WifiManager.WIFI_FEATURE_ADDITIONAL_STA_LOCAL_ONLY);
}
requestRemoveAdditionalClientModeManagerWhenNotAllowed(ROLE_CLIENT_LOCAL_ONLY,
@@ -4864,20 +4978,21 @@
@Test
public void testGetSupportedFeaturesForStaApConcurrency() throws Exception {
enterScanOnlyModeActiveState();
- long supportedFeaturesFromWifiNative = WifiManager.WIFI_FEATURE_OWE;
- when(mWifiNative.getSupportedFeatureSet(null)).thenReturn(
- supportedFeaturesFromWifiNative);
+ BitSet supportedFeaturesFromWifiNative =
+ createCapabilityBitset(WifiManager.WIFI_FEATURE_OWE);
+ when(mWifiNative.getSupportedFeatureSet(null)).thenReturn(supportedFeaturesFromWifiNative);
when(mWifiNative.isStaApConcurrencySupported()).thenReturn(false);
mClientListener.onStarted(mClientModeManager);
- assertEquals(supportedFeaturesFromWifiNative,
- mActiveModeWarden.getSupportedFeatureSet());
+ assertTrue(supportedFeaturesFromWifiNative
+ .equals(mActiveModeWarden.getSupportedFeatureSet()));
when(mWifiNative.isStaApConcurrencySupported()).thenReturn(true);
mClientListener.onStarted(mClientModeManager);
- assertEquals(supportedFeaturesFromWifiNative | WifiManager.WIFI_FEATURE_AP_STA,
- mActiveModeWarden.getSupportedFeatureSet());
+ assertTrue(addCapabilitiesToBitset(
+ supportedFeaturesFromWifiNative, WifiManager.WIFI_FEATURE_AP_STA)
+ .equals(mActiveModeWarden.getSupportedFeatureSet()));
}
/**
@@ -4888,45 +5003,47 @@
public void testGetSupportedFeaturesForStaStaConcurrency() throws Exception {
assumeTrue(SdkLevel.isAtLeastS());
enterScanOnlyModeActiveState();
- long supportedFeaturesFromWifiNative = WifiManager.WIFI_FEATURE_OWE;
+ BitSet supportedFeaturesFromWifiNative =
+ createCapabilityBitset(WifiManager.WIFI_FEATURE_OWE);
when(mWifiNative.getSupportedFeatureSet(null)).thenReturn(
supportedFeaturesFromWifiNative);
mClientListener.onStarted(mClientModeManager);
- assertEquals(supportedFeaturesFromWifiNative, mActiveModeWarden.getSupportedFeatureSet());
+ assertTrue(supportedFeaturesFromWifiNative
+ .equals(mActiveModeWarden.getSupportedFeatureSet()));
when(mWifiNative.isStaStaConcurrencySupported()).thenReturn(true);
when(mWifiResourceCache.getBoolean(R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled))
.thenReturn(true);
mClientListener.onStarted(mClientModeManager);
- assertEquals(supportedFeaturesFromWifiNative
- | WifiManager.WIFI_FEATURE_ADDITIONAL_STA_LOCAL_ONLY,
- mActiveModeWarden.getSupportedFeatureSet());
+ assertTrue(addCapabilitiesToBitset(supportedFeaturesFromWifiNative,
+ WifiManager.WIFI_FEATURE_ADDITIONAL_STA_LOCAL_ONLY)
+ .equals(mActiveModeWarden.getSupportedFeatureSet()));
when(mWifiResourceCache.getBoolean(
R.bool.config_wifiMultiStaNetworkSwitchingMakeBeforeBreakEnabled))
.thenReturn(true);
mClientListener.onStarted(mClientModeManager);
- assertEquals(supportedFeaturesFromWifiNative
- | WifiManager.WIFI_FEATURE_ADDITIONAL_STA_LOCAL_ONLY
- | WifiManager.WIFI_FEATURE_ADDITIONAL_STA_MBB,
- mActiveModeWarden.getSupportedFeatureSet());
+ assertTrue(addCapabilitiesToBitset(supportedFeaturesFromWifiNative,
+ WifiManager.WIFI_FEATURE_ADDITIONAL_STA_LOCAL_ONLY,
+ WifiManager.WIFI_FEATURE_ADDITIONAL_STA_MBB)
+ .equals(mActiveModeWarden.getSupportedFeatureSet()));
when(mWifiResourceCache.getBoolean(R.bool.config_wifiMultiStaRestrictedConcurrencyEnabled))
.thenReturn(true);
when(mWifiResourceCache.getBoolean(
R.bool.config_wifiMultiStaMultiInternetConcurrencyEnabled)).thenReturn(true);
mClientListener.onStarted(mClientModeManager);
- assertEquals(supportedFeaturesFromWifiNative
- | WifiManager.WIFI_FEATURE_ADDITIONAL_STA_LOCAL_ONLY
- | WifiManager.WIFI_FEATURE_ADDITIONAL_STA_MBB
- | WifiManager.WIFI_FEATURE_ADDITIONAL_STA_RESTRICTED
- | WifiManager.WIFI_FEATURE_ADDITIONAL_STA_MULTI_INTERNET,
- mActiveModeWarden.getSupportedFeatureSet());
+ assertTrue(addCapabilitiesToBitset(supportedFeaturesFromWifiNative,
+ WifiManager.WIFI_FEATURE_ADDITIONAL_STA_LOCAL_ONLY,
+ WifiManager.WIFI_FEATURE_ADDITIONAL_STA_MBB,
+ WifiManager.WIFI_FEATURE_ADDITIONAL_STA_RESTRICTED,
+ WifiManager.WIFI_FEATURE_ADDITIONAL_STA_MULTI_INTERNET)
+ .equals(mActiveModeWarden.getSupportedFeatureSet()));
}
- private long testGetSupportedFeaturesCaseForMacRandomization(
- long supportedFeaturesFromWifiNative, boolean apMacRandomizationEnabled,
+ private BitSet testGetSupportedFeaturesCaseForMacRandomization(
+ BitSet supportedFeaturesFromWifiNative, boolean apMacRandomizationEnabled,
boolean staConnectedMacRandomizationEnabled, boolean p2pMacRandomizationEnabled) {
when(mWifiResourceCache.getBoolean(
R.bool.config_wifi_connected_mac_randomization_supported))
@@ -4947,28 +5064,29 @@
/** Verifies that syncGetSupportedFeatures() masks out capabilities based on system flags. */
@Test
public void syncGetSupportedFeaturesForMacRandomization() throws Exception {
- final long featureStaConnectedMacRandomization =
- WifiManager.WIFI_FEATURE_CONNECTED_RAND_MAC;
- final long featureApMacRandomization =
- WifiManager.WIFI_FEATURE_AP_RAND_MAC;
- final long featureP2pMacRandomization =
- WifiManager.WIFI_FEATURE_CONNECTED_RAND_MAC;
+ final BitSet featureStaConnectedMacRandomization =
+ createCapabilityBitset(WifiManager.WIFI_FEATURE_CONNECTED_RAND_MAC);
+ final BitSet featureApMacRandomization =
+ createCapabilityBitset(WifiManager.WIFI_FEATURE_AP_RAND_MAC);
+ final BitSet featureP2pMacRandomization =
+ createCapabilityBitset(WifiManager.WIFI_FEATURE_CONNECTED_RAND_MAC);
enterClientModeActiveState();
- assertEquals(featureStaConnectedMacRandomization | featureApMacRandomization
- | featureP2pMacRandomization,
- testGetSupportedFeaturesCaseForMacRandomization(
- featureP2pMacRandomization, true, true, true));
+ assertTrue(combineBitsets(featureStaConnectedMacRandomization, featureApMacRandomization,
+ featureP2pMacRandomization)
+ .equals(testGetSupportedFeaturesCaseForMacRandomization(
+ featureP2pMacRandomization, true, true, true)));
// p2p supported by HAL, but disabled by overlay.
- assertEquals(featureStaConnectedMacRandomization | featureApMacRandomization,
- testGetSupportedFeaturesCaseForMacRandomization(
- featureP2pMacRandomization, true, true, false));
- assertEquals(featureStaConnectedMacRandomization | featureApMacRandomization,
- testGetSupportedFeaturesCaseForMacRandomization(0, true, true, false));
+ assertTrue(combineBitsets(featureStaConnectedMacRandomization, featureApMacRandomization)
+ .equals(testGetSupportedFeaturesCaseForMacRandomization(
+ featureP2pMacRandomization, true, true, false)));
+ assertTrue(combineBitsets(featureStaConnectedMacRandomization, featureApMacRandomization)
+ .equals(testGetSupportedFeaturesCaseForMacRandomization(
+ new BitSet(), true, true, false)));
}
- private long testGetSupportedFeaturesCaseForRtt(
- long supportedFeaturesFromWifiNative, boolean rttDisabled) {
+ private BitSet testGetSupportedFeaturesCaseForRtt(
+ BitSet supportedFeaturesFromWifiNative, boolean rttDisabled) {
when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_WIFI_RTT)).thenReturn(
!rttDisabled);
when(mWifiNative.getSupportedFeatureSet(anyString())).thenReturn(
@@ -4981,39 +5099,41 @@
/** Verifies that syncGetSupportedFeatures() masks out capabilities based on system flags. */
@Test
public void syncGetSupportedFeaturesForRtt() throws Exception {
- final long featureAware = WifiManager.WIFI_FEATURE_AWARE;
- final long featureInfra = WifiManager.WIFI_FEATURE_INFRA;
- final long featureD2dRtt = WifiManager.WIFI_FEATURE_D2D_RTT;
- final long featureD2apRtt = WifiManager.WIFI_FEATURE_D2AP_RTT;
- final long featureLongBits = 0x1000000000L;
- enterClientModeActiveState();
- assertEquals(0, testGetSupportedFeaturesCaseForRtt(0, false));
- assertEquals(0, testGetSupportedFeaturesCaseForRtt(0, true));
- assertEquals(featureAware | featureInfra,
- testGetSupportedFeaturesCaseForRtt(featureAware | featureInfra, false));
- assertEquals(featureAware | featureInfra,
- testGetSupportedFeaturesCaseForRtt(featureAware | featureInfra, true));
- assertEquals(featureInfra | featureD2dRtt,
- testGetSupportedFeaturesCaseForRtt(featureInfra | featureD2dRtt, false));
- assertEquals(featureInfra,
- testGetSupportedFeaturesCaseForRtt(featureInfra | featureD2dRtt, true));
- assertEquals(featureInfra | featureD2apRtt,
- testGetSupportedFeaturesCaseForRtt(featureInfra | featureD2apRtt, false));
- assertEquals(featureInfra,
- testGetSupportedFeaturesCaseForRtt(featureInfra | featureD2apRtt, true));
- assertEquals(featureInfra | featureD2dRtt | featureD2apRtt,
- testGetSupportedFeaturesCaseForRtt(
- featureInfra | featureD2dRtt | featureD2apRtt, false));
- assertEquals(featureInfra,
- testGetSupportedFeaturesCaseForRtt(
- featureInfra | featureD2dRtt | featureD2apRtt, true));
+ final BitSet featureAware = createCapabilityBitset(WifiManager.WIFI_FEATURE_AWARE);
+ final BitSet featureInfra = createCapabilityBitset(WifiManager.WIFI_FEATURE_INFRA);
+ final BitSet featureD2dRtt = createCapabilityBitset(WifiManager.WIFI_FEATURE_D2D_RTT);
+ final BitSet featureD2apRtt = createCapabilityBitset(WifiManager.WIFI_FEATURE_D2AP_RTT);
- assertEquals(featureLongBits | featureInfra | featureD2dRtt | featureD2apRtt,
+ enterClientModeActiveState();
+
+ assertTrue(testGetSupportedFeaturesCaseForRtt(new BitSet(), false).equals(new BitSet()));
+ assertTrue(testGetSupportedFeaturesCaseForRtt(new BitSet(), true).equals(new BitSet()));
+ assertTrue(combineBitsets(featureAware, featureInfra).equals(
+ testGetSupportedFeaturesCaseForRtt(combineBitsets(featureAware, featureInfra),
+ false)));
+ assertTrue(combineBitsets(featureAware, featureInfra).equals(
+ testGetSupportedFeaturesCaseForRtt(combineBitsets(featureAware, featureInfra),
+ true)));
+ assertTrue(combineBitsets(featureInfra, featureD2dRtt).equals(
+ testGetSupportedFeaturesCaseForRtt(combineBitsets(featureInfra, featureD2dRtt),
+ false)));
+ assertTrue(featureInfra.equals(
+ testGetSupportedFeaturesCaseForRtt(combineBitsets(featureInfra, featureD2dRtt),
+ true)));
+ assertTrue(combineBitsets(featureInfra, featureD2apRtt).equals(
+ testGetSupportedFeaturesCaseForRtt(combineBitsets(featureInfra, featureD2apRtt),
+ false)));
+ assertTrue(featureInfra.equals(
+ testGetSupportedFeaturesCaseForRtt(combineBitsets(featureInfra, featureD2apRtt),
+ true)));
+ assertTrue(combineBitsets(featureInfra, featureD2dRtt, featureD2apRtt).equals(
testGetSupportedFeaturesCaseForRtt(
- featureLongBits | featureInfra | featureD2dRtt | featureD2apRtt, false));
- assertEquals(featureLongBits | featureInfra,
+ combineBitsets(featureInfra, featureD2dRtt, featureD2apRtt),
+ false)));
+ assertTrue(featureInfra.equals(
testGetSupportedFeaturesCaseForRtt(
- featureLongBits | featureInfra | featureD2dRtt | featureD2apRtt, true));
+ combineBitsets(featureInfra, featureD2dRtt, featureD2apRtt),
+ true)));
}
@Test
@@ -5345,9 +5465,10 @@
// Location state changes
ArgumentCaptor<BroadcastReceiver> bcastRxCaptor =
ArgumentCaptor.forClass(BroadcastReceiver.class);
- verify(mContext).registerReceiver(
+ verify(mContext).registerReceiverForAllUsers(
bcastRxCaptor.capture(),
- argThat(filter -> filter.hasAction(LocationManager.MODE_CHANGED_ACTION)));
+ argThat(filter -> filter.hasAction(LocationManager.MODE_CHANGED_ACTION)),
+ eq(null), any(Handler.class));
BroadcastReceiver broadcastReceiver = bcastRxCaptor.getValue();
when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(true);
@@ -5373,13 +5494,17 @@
@Test
public void testWepNotDeprecated() throws Exception {
when(mWifiGlobals.isWepSupported()).thenReturn(true);
- enterClientModeActiveState(false, TEST_FEATURE_SET | WifiManager.WIFI_FEATURE_WEP);
+ BitSet featureSet =
+ addCapabilitiesToBitset(TEST_FEATURE_SET, WifiManager.WIFI_FEATURE_WEP);
+ enterClientModeActiveState(false, featureSet);
}
@Test
public void testWpaPersonalNotDeprecated() throws Exception {
when(mWifiGlobals.isWpaPersonalDeprecated()).thenReturn(false);
- enterClientModeActiveState(false, TEST_FEATURE_SET | WifiManager.WIFI_FEATURE_WPA_PERSONAL);
+ BitSet featureSet =
+ addCapabilitiesToBitset(TEST_FEATURE_SET, WifiManager.WIFI_FEATURE_WPA_PERSONAL);
+ enterClientModeActiveState(false, featureSet);
}
@Test
@@ -5405,4 +5530,82 @@
verify(mWifiGlobals).setD2dStaConcurrencySupported(true);
verify(mWifiGlobals, atLeastOnce()).isD2dSupportedWhenInfraStaDisabled();
}
+
+ @Test
+ public void testGetNumberOf11beSoftApManager() throws Exception {
+ assumeTrue(SdkLevel.isAtLeastT());
+ enterSoftApActiveMode();
+ when(mSoftApManager.isStarted()).thenReturn(true);
+ SoftApModeConfiguration mockSoftApModeConfiguration = mock(SoftApModeConfiguration.class);
+ SoftApConfiguration mockSoftApConfiguration = mock(SoftApConfiguration.class);
+ when(mockSoftApConfiguration.isIeee80211beEnabled()).thenReturn(true);
+ when(mockSoftApModeConfiguration.getSoftApConfiguration())
+ .thenReturn(mockSoftApConfiguration);
+ when(mSoftApManager.getSoftApModeConfiguration()).thenReturn(mockSoftApModeConfiguration);
+ assertEquals(1, mActiveModeWarden.getCurrentMLDAp());
+ when(mSoftApManager.isBridgedMode()).thenReturn(true);
+ when(mSoftApManager.isUsingMlo()).thenReturn(false);
+ assertEquals(2, mActiveModeWarden.getCurrentMLDAp());
+ when(mSoftApManager.isUsingMlo()).thenReturn(true);
+ assertEquals(1, mActiveModeWarden.getCurrentMLDAp());
+ when(mockSoftApConfiguration.isIeee80211beEnabled()).thenReturn(false);
+ assertEquals(0, mActiveModeWarden.getCurrentMLDAp());
+ }
+
+ /**
+ * Verifies that registered remote WifiStateChangedListeners are notified when the Wifi state
+ * changes.
+ */
+ @Test
+ public void testRegisteredWifiStateChangedListenerIsNotifiedWhenWifiStateChanges()
+ throws RemoteException {
+ // Start off ENABLED
+ mActiveModeWarden.setWifiStateForApiCalls(WIFI_STATE_ENABLED);
+
+ // Registering should give the current state of ENABLED.
+ IWifiStateChangedListener remoteCallback1 = mock(IWifiStateChangedListener.class);
+ when(remoteCallback1.asBinder()).thenReturn(mock(IBinder.class));
+ IWifiStateChangedListener remoteCallback2 = mock(IWifiStateChangedListener.class);
+ when(remoteCallback2.asBinder()).thenReturn(mock(IBinder.class));
+ mActiveModeWarden.addWifiStateChangedListener(remoteCallback1);
+ mActiveModeWarden.addWifiStateChangedListener(remoteCallback2);
+
+ // Change the state to DISABLED and verify the listeners were called.
+ final int newState = WIFI_STATE_DISABLED;
+ mActiveModeWarden.setWifiStateForApiCalls(newState);
+
+ verify(remoteCallback1, times(1)).onWifiStateChanged();
+ verify(remoteCallback2, times(1)).onWifiStateChanged();
+
+ // Duplicate wifi state should not notify the callbacks again.
+ mActiveModeWarden.setWifiStateForApiCalls(newState);
+ mActiveModeWarden.setWifiStateForApiCalls(newState);
+ mActiveModeWarden.setWifiStateForApiCalls(newState);
+
+ verify(remoteCallback1, times(1)).onWifiStateChanged();
+ verify(remoteCallback2, times(1)).onWifiStateChanged();
+ }
+
+ /**
+ * Verifies that unregistered remote WifiStateChangedListeners are not notified when the Wifi
+ * state changes.
+ */
+ @Test
+ public void testUnregisteredWifiStateChangedListenerIsNotNotifiedWhenWifiStateChanges()
+ throws RemoteException {
+ IWifiStateChangedListener remoteCallback1 = mock(IWifiStateChangedListener.class);
+ when(remoteCallback1.asBinder()).thenReturn(mock(IBinder.class));
+ IWifiStateChangedListener remoteCallback2 = mock(IWifiStateChangedListener.class);
+ when(remoteCallback2.asBinder()).thenReturn(mock(IBinder.class));
+ mActiveModeWarden.addWifiStateChangedListener(remoteCallback1);
+ mActiveModeWarden.addWifiStateChangedListener(remoteCallback2);
+ mActiveModeWarden.removeWifiStateChangedListener(remoteCallback1);
+ mActiveModeWarden.removeWifiStateChangedListener(remoteCallback2);
+
+ final int newState = WIFI_STATE_ENABLED;
+ mActiveModeWarden.setWifiStateForApiCalls(newState);
+
+ verify(remoteCallback1, never()).onWifiStateChanged();
+ verify(remoteCallback2, never()).onWifiStateChanged();
+ }
}
diff --git a/service/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java b/service/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java
index 2d114d2..8b705f0 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java
@@ -44,8 +44,10 @@
import static com.android.server.wifi.ClientModeImpl.CMD_PRE_DHCP_ACTION_COMPLETE;
import static com.android.server.wifi.ClientModeImpl.CMD_UNWANTED_NETWORK;
import static com.android.server.wifi.ClientModeImpl.WIFI_WORK_SOURCE;
+import static com.android.server.wifi.WifiBlocklistMonitor.REASON_APP_DISALLOW;
import static com.android.server.wifi.WifiSettingsConfigStore.SECONDARY_WIFI_STA_FACTORY_MAC_ADDRESS;
import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_STA_FACTORY_MAC_ADDRESS;
+import static com.android.server.wifi.TestUtil.createCapabilityBitset;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
@@ -123,6 +125,7 @@
import android.net.networkstack.aidl.ip.ReachabilityLossReason;
import android.net.vcn.VcnManager;
import android.net.vcn.VcnNetworkPolicyResult;
+import android.net.wifi.BlockingOption;
import android.net.wifi.IActionListener;
import android.net.wifi.MloLink;
import android.net.wifi.ScanResult;
@@ -186,7 +189,7 @@
import com.android.server.wifi.proto.nano.WifiMetricsProto;
import com.android.server.wifi.proto.nano.WifiMetricsProto.StaEvent;
import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiIsUnusableEvent;
-import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiUsabilityStats;
+import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiUsabilityStatsEntry;
import com.android.server.wifi.util.ActionListenerWrapper;
import com.android.server.wifi.util.NativeUtil;
import com.android.server.wifi.util.RssiUtilTest;
@@ -641,6 +644,7 @@
when(mWifiNative.connectToNetwork(any(), any())).thenReturn(true);
when(mWifiNative.getApfCapabilities(anyString())).thenReturn(APF_CAP);
when(mWifiNative.isQosPolicyFeatureEnabled()).thenReturn(true);
+ when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn(new BitSet());
}
/** Reset verify() counters on WifiNative, and restore when() mocks on mWifiNative */
@@ -733,7 +737,8 @@
when(mWifiInjector.getActiveModeWarden()).thenReturn(mActiveModeWarden);
when(mActiveModeWarden.getPrimaryClientModeManager()).thenReturn(mPrimaryClientModeManager);
when(mPrimaryClientModeManager.getSupportedFeatures()).thenReturn(
- WifiManager.WIFI_FEATURE_WPA3_SAE | WifiManager.WIFI_FEATURE_OWE);
+ createCapabilityBitset(
+ WifiManager.WIFI_FEATURE_WPA3_SAE, WifiManager.WIFI_FEATURE_OWE));
when(mWifiInjector.getWifiGlobals()).thenReturn(mWifiGlobals);
when(mWifiInjector.getWifiHandlerThread()).thenReturn(mWifiHandlerThread);
when(mWifiInjector.getSsidTranslator()).thenReturn(mSsidTranslator);
@@ -852,6 +857,7 @@
assertNotNull(mOffloadDisabledListenerArgumentCaptor.getValue());
mCmi.enableVerboseLogging(true);
+ mCmi.disconnect();
mLooper.dispatchAll();
verify(mWifiLastResortWatchdog, atLeastOnce()).clearAllFailureCounts();
@@ -3347,7 +3353,7 @@
// "normal" commands.
mCmi.sendMessage(ClientModeImpl.CMD_DISCONNECT);
mLooper.dispatchAll();
- assertEquals(1, mCmi.copyLogRecs()
+ assertEquals(2, mCmi.copyLogRecs()
.stream()
.filter(logRec -> logRec.getWhat() == ClientModeImpl.CMD_DISCONNECT)
.count());
@@ -4023,7 +4029,7 @@
WifiSignalPollResults signalPollResults = new WifiSignalPollResults();
signalPollResults.addEntry(0, -42, 65, 54, sFreq);
when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn(
- WifiManager.WIFI_FEATURE_LINK_LAYER_STATS);
+ createCapabilityBitset(WifiManager.WIFI_FEATURE_LINK_LAYER_STATS));
when(mWifiNative.getWifiLinkLayerStats(any())).thenReturn(llStats);
when(mWifiNative.signalPoll(any())).thenReturn(signalPollResults);
when(mClock.getWallClockMillis()).thenReturn(startMillis + 0);
@@ -4058,7 +4064,7 @@
WifiSignalPollResults signalPollResults = new WifiSignalPollResults();
signalPollResults.addEntry(0, -42, 65, 54, sFreq);
when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn(
- WifiManager.WIFI_FEATURE_LINK_LAYER_STATS);
+ createCapabilityBitset(WifiManager.WIFI_FEATURE_LINK_LAYER_STATS));
when(mWifiNative.getWifiLinkLayerStats(any())).thenReturn(llStats);
when(mWifiNative.signalPoll(any())).thenReturn(signalPollResults);
when(mClock.getWallClockMillis()).thenReturn(startMillis + 0);
@@ -4112,7 +4118,7 @@
WifiSignalPollResults signalPollResults = new WifiSignalPollResults();
signalPollResults.addEntry(0, -42, 65, 54, sFreq);
when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn(
- WifiManager.WIFI_FEATURE_LINK_LAYER_STATS);
+ createCapabilityBitset(WifiManager.WIFI_FEATURE_LINK_LAYER_STATS));
when(mWifiNative.getWifiLinkLayerStats(any())).thenReturn(llStats);
when(mWifiNative.signalPoll(any())).thenReturn(signalPollResults);
when(mClock.getWallClockMillis()).thenReturn(startMillis + 0);
@@ -4139,6 +4145,76 @@
}
/**
+ * Verify that RSSI polling starts/ stops/ one-offs are properly recorded in the capture buffer.
+ */
+ @Test
+ public void testCaptureBufferRssiOnOff() throws Exception {
+ // Log should indicate RSSI polling turned on.
+ mCmi.enableRssiPolling(true);
+ connect();
+ verify(mWifiMetrics).logAsynchronousEvent(
+ eq(WIFI_IFACE_NAME),
+ eq(WifiUsabilityStatsEntry.CAPTURE_EVENT_TYPE_RSSI_POLLING_ENABLED));
+ reset(mWifiMetrics);
+
+ // Normal RSSI polling loop. No events should be logged.
+ mLooper.moveTimeForward(3000);
+ mLooper.dispatchAll();
+ verify(mWifiMetrics, never()).logAsynchronousEvent(anyString(), anyInt());
+ verify(mWifiMetrics, never()).logAsynchronousEvent(anyString(), anyInt(), anyInt());
+ reset(mWifiMetrics);
+
+ // Normal RSSI polling loop. No events should be logged here either.
+ mLooper.moveTimeForward(3000);
+ mLooper.dispatchAll();
+ verify(mWifiMetrics, never()).logAsynchronousEvent(anyString(), anyInt());
+ verify(mWifiMetrics, never()).logAsynchronousEvent(anyString(), anyInt(), anyInt());
+ reset(mWifiMetrics);
+
+ // Turn off RSSI polling. This should show up in the capture buffer.
+ mCmi.enableRssiPolling(false);
+ mLooper.moveTimeForward(3000);
+ mLooper.dispatchAll();
+ verify(mWifiMetrics).logAsynchronousEvent(
+ eq(WIFI_IFACE_NAME),
+ eq(WifiUsabilityStatsEntry.CAPTURE_EVENT_TYPE_RSSI_POLLING_DISABLED));
+ reset(mWifiMetrics);
+ }
+
+ /**
+ * Verify that IP reachability problems are recorded in the capture buffer.
+ */
+ @Test
+ public void testCaptureBufferReachabilityLost() throws Exception {
+ // Log should indicate RSSI polling turned on.
+ connect();
+ verify(mWifiMetrics).logAsynchronousEvent(
+ eq(WIFI_IFACE_NAME),
+ eq(WifiUsabilityStatsEntry.CAPTURE_EVENT_TYPE_RSSI_POLLING_ENABLED));
+ reset(mWifiMetrics);
+
+ // Simulate an IP_REACHABILITY_LOST event.
+ mIpClientCallback.onReachabilityLost("CMD_IP_REACHABILITY_LOST");
+ mLooper.dispatchAll();
+ verify(mWifiMetrics).logAsynchronousEvent(
+ eq(WIFI_IFACE_NAME),
+ eq(WifiUsabilityStatsEntry.CAPTURE_EVENT_TYPE_IP_REACHABILITY_LOST),
+ eq(-1));
+ reset(mWifiMetrics);
+
+ // Simulate an IP_REACHABILITY_FAILURE event.
+ ReachabilityLossInfoParcelable lossInfo =
+ new ReachabilityLossInfoParcelable("", ReachabilityLossReason.CONFIRM);
+ mIpClientCallback.onReachabilityFailure(lossInfo);
+ mLooper.dispatchAll();
+ verify(mWifiMetrics).logAsynchronousEvent(
+ eq(WIFI_IFACE_NAME),
+ eq(WifiUsabilityStatsEntry.CAPTURE_EVENT_TYPE_IP_REACHABILITY_FAILURE),
+ eq(ReachabilityLossReason.CONFIRM));
+ reset(mWifiMetrics);
+ }
+
+ /**
* Verify link bandwidth update in connected mode
*/
@Test
@@ -4172,7 +4248,7 @@
WifiSignalPollResults signalPollResults = new WifiSignalPollResults();
signalPollResults.addEntry(0, -42, 65, 54, sFreq);
when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn(
- WifiManager.WIFI_FEATURE_LINK_LAYER_STATS);
+ createCapabilityBitset(WifiManager.WIFI_FEATURE_LINK_LAYER_STATS));
when(mWifiNative.getWifiLinkLayerStats(any())).thenReturn(llStats);
when(mWifiNative.signalPoll(any())).thenReturn(signalPollResults);
when(mClock.getWallClockMillis()).thenReturn(startMillis + 0);
@@ -4713,7 +4789,7 @@
WifiSignalPollResults signalPollResults = new WifiSignalPollResults();
signalPollResults.addEntry(0, TEST_RSSI, 65, 54, sFreq);
when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn(
- WifiManager.WIFI_FEATURE_LINK_LAYER_STATS);
+ createCapabilityBitset(WifiManager.WIFI_FEATURE_LINK_LAYER_STATS));
when(mWifiNative.getWifiLinkLayerStats(any())).thenReturn(llStats);
when(mWifiNative.signalPoll(any())).thenReturn(signalPollResults);
@@ -4740,7 +4816,7 @@
WifiSignalPollResults signalPollResults = new WifiSignalPollResults();
signalPollResults.addEntry(0, TEST_RSSI, 65, 54, sFreq);
when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn(
- WifiManager.WIFI_FEATURE_LINK_LAYER_STATS);
+ createCapabilityBitset(WifiManager.WIFI_FEATURE_LINK_LAYER_STATS));
when(mWifiNative.getWifiLinkLayerStats(any())).thenReturn(llStats);
when(mWifiNative.signalPoll(any())).thenReturn(signalPollResults);
@@ -5460,7 +5536,7 @@
WifiSignalPollResults signalPollResults = new WifiSignalPollResults();
signalPollResults.addEntry(0, RSSI_THRESHOLD_BREACH_MIN, 65, 54, sFreq);
when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn(
- WifiManager.WIFI_FEATURE_LINK_LAYER_STATS);
+ createCapabilityBitset(WifiManager.WIFI_FEATURE_LINK_LAYER_STATS));
when(mWifiNative.getWifiLinkLayerStats(any())).thenReturn(llStats);
when(mWifiNative.signalPoll(any())).thenReturn(signalPollResults);
@@ -6081,7 +6157,7 @@
failOnRssiChangeBroadcast();
when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn(
- WifiManager.WIFI_FEATURE_LINK_LAYER_STATS);
+ createCapabilityBitset(WifiManager.WIFI_FEATURE_LINK_LAYER_STATS));
WifiLinkLayerStats oldLLStats = new WifiLinkLayerStats();
when(mWifiNative.getWifiLinkLayerStats(any())).thenReturn(oldLLStats);
mCmi.sendMessage(ClientModeImpl.CMD_RSSI_POLL, 1);
@@ -6108,7 +6184,7 @@
failOnRssiChangeBroadcast();
when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn(
- WifiManager.WIFI_FEATURE_LINK_LAYER_STATS);
+ createCapabilityBitset(WifiManager.WIFI_FEATURE_LINK_LAYER_STATS));
WifiLinkLayerStats stats = new WifiLinkLayerStats();
when(mWifiNative.getWifiLinkLayerStats(any())).thenReturn(stats);
when(mWifiDataStall.checkDataStallAndThroughputSufficiency(any(),
@@ -6116,9 +6192,8 @@
.thenReturn(WifiIsUnusableEvent.TYPE_UNKNOWN);
mCmi.sendMessage(ClientModeImpl.CMD_RSSI_POLL, 1);
mLooper.dispatchAll();
- verify(mWifiMetrics).updateWifiUsabilityStatsEntries(any(), any(), eq(stats));
- verify(mWifiMetrics, never()).addToWifiUsabilityStatsList(any(),
- WifiUsabilityStats.LABEL_BAD, eq(anyInt()), eq(-1));
+ verify(mWifiMetrics).updateWifiUsabilityStatsEntries(any(), any(), eq(stats), eq(false),
+ anyInt());
when(mWifiDataStall.checkDataStallAndThroughputSufficiency(any(), any(), any(), any(),
any(), anyLong(), anyLong()))
@@ -6126,13 +6201,8 @@
when(mClock.getElapsedSinceBootMillis()).thenReturn(10L);
mCmi.sendMessage(ClientModeImpl.CMD_RSSI_POLL, 1);
mLooper.dispatchAll();
- verify(mWifiMetrics, times(2)).updateWifiUsabilityStatsEntries(any(), any(), eq(stats));
- when(mClock.getElapsedSinceBootMillis())
- .thenReturn(10L + ClientModeImpl.DURATION_TO_WAIT_ADD_STATS_AFTER_DATA_STALL_MS);
- mCmi.sendMessage(ClientModeImpl.CMD_RSSI_POLL, 1);
- mLooper.dispatchAll();
- verify(mWifiMetrics).addToWifiUsabilityStatsList(WIFI_IFACE_NAME,
- WifiUsabilityStats.LABEL_BAD, WifiIsUnusableEvent.TYPE_DATA_STALL_BAD_TX, -1);
+ verify(mWifiMetrics, times(2)).updateWifiUsabilityStatsEntries(any(), any(), eq(stats),
+ eq(false), anyInt());
}
/**
@@ -6530,9 +6600,6 @@
mLooper.dispatchAll();
verify(mWifiMetrics).logWifiIsUnusableEvent(WIFI_IFACE_NAME,
WifiIsUnusableEvent.TYPE_IP_REACHABILITY_LOST);
- verify(mWifiMetrics).addToWifiUsabilityStatsList(WIFI_IFACE_NAME,
- WifiUsabilityStats.LABEL_BAD,
- WifiUsabilityStats.TYPE_IP_REACHABILITY_LOST, -1);
}
/**
@@ -6551,9 +6618,6 @@
mLooper.dispatchAll();
verify(mWifiMetrics).logWifiIsUnusableEvent(WIFI_IFACE_NAME,
WifiIsUnusableEvent.TYPE_IP_REACHABILITY_LOST);
- verify(mWifiMetrics).addToWifiUsabilityStatsList(WIFI_IFACE_NAME,
- WifiUsabilityStats.LABEL_BAD,
- WifiUsabilityStats.TYPE_IP_REACHABILITY_LOST, -1);
}
/**
@@ -6575,9 +6639,6 @@
mLooper.dispatchAll();
verify(mWifiMetrics, never()).logWifiIsUnusableEvent(WIFI_IFACE_NAME,
WifiIsUnusableEvent.TYPE_IP_REACHABILITY_LOST);
- verify(mWifiMetrics, never()).addToWifiUsabilityStatsList(WIFI_IFACE_NAME,
- WifiUsabilityStats.LABEL_BAD,
- WifiUsabilityStats.TYPE_IP_REACHABILITY_LOST, -1);
}
/**
@@ -6944,9 +7005,10 @@
when(mWifiConfigManager.getConfiguredNetworkWithoutMasking(anyInt())).thenReturn(config);
if (isDriverSupportFils) {
when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn(
- WifiManager.WIFI_FEATURE_FILS_SHA256 | WifiManager.WIFI_FEATURE_FILS_SHA384);
+ createCapabilityBitset(WifiManager.WIFI_FEATURE_FILS_SHA256,
+ WifiManager.WIFI_FEATURE_FILS_SHA384));
} else {
- when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn((long) 0);
+ when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn(new BitSet());
}
return config;
@@ -8038,7 +8100,7 @@
@Test
public void testWifiScoreReportDump() throws Exception {
when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn(
- WifiManager.WIFI_FEATURE_LINK_LAYER_STATS);
+ createCapabilityBitset(WifiManager.WIFI_FEATURE_LINK_LAYER_STATS));
InOrder inOrder = inOrder(mWifiNative, mWifiScoreReport);
inOrder.verify(mWifiNative, never()).getWifiLinkLayerStats(any());
connect();
@@ -9051,7 +9113,7 @@
clearInvocations(mWifiNative, mWifiMetrics, mWifiDataStall);
when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn(
- WifiManager.WIFI_FEATURE_LINK_LAYER_STATS);
+ createCapabilityBitset(WifiManager.WIFI_FEATURE_LINK_LAYER_STATS));
WifiLinkLayerStats oldLLStats = new WifiLinkLayerStats();
when(mWifiNative.getWifiLinkLayerStats(any())).thenReturn(oldLLStats);
mLooper.moveTimeForward(mWifiGlobals.getPollRssiIntervalMillis());
@@ -9095,7 +9157,7 @@
verifyNoMoreInteractions(mWifiNative, mWifiMetrics, mWifiDataStall);
when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn(
- WifiManager.WIFI_FEATURE_LINK_LAYER_STATS);
+ createCapabilityBitset(WifiManager.WIFI_FEATURE_LINK_LAYER_STATS));
when(mWifiNative.getWifiLinkLayerStats(any())).thenReturn(new WifiLinkLayerStats());
// No link layer stats collection on secondary CMM.
@@ -9114,7 +9176,7 @@
clearInvocations(mWifiNative, mWifiMetrics, mWifiDataStall);
when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn(
- WifiManager.WIFI_FEATURE_LINK_LAYER_STATS);
+ createCapabilityBitset(WifiManager.WIFI_FEATURE_LINK_LAYER_STATS));
when(mWifiNative.getWifiLinkLayerStats(any())).thenReturn(new WifiLinkLayerStats());
// No link layer stats collection on secondary CMM.
@@ -9147,7 +9209,7 @@
// RSSI polling is enabled on primary.
when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn(
- WifiManager.WIFI_FEATURE_LINK_LAYER_STATS);
+ createCapabilityBitset(WifiManager.WIFI_FEATURE_LINK_LAYER_STATS));
WifiLinkLayerStats oldLLStats = new WifiLinkLayerStats();
when(mWifiNative.getWifiLinkLayerStats(any())).thenReturn(oldLLStats);
mLooper.moveTimeForward(mWifiGlobals.getPollRssiIntervalMillis());
@@ -9176,7 +9238,7 @@
connect();
clearInvocations(mWifiNative, mWifiMetrics, mWifiDataStall);
- when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn(0L);
+ when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn(new BitSet());
WifiLinkLayerStats stats = new WifiLinkLayerStats();
when(mWifiNative.getWifiLinkLayerStats(any())).thenReturn(stats);
mLooper.moveTimeForward(mWifiGlobals.getPollRssiIntervalMillis());
@@ -9799,7 +9861,7 @@
throws Exception {
if (isTrustOnFirstUseSupported) {
when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn(
- WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE);
+ createCapabilityBitset(WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE));
}
mCmi.mInsecureEapNetworkHandler = mInsecureEapNetworkHandler;
@@ -10876,7 +10938,7 @@
connect();
when(mWifiNative.getMaxSupportedConcurrentTdlsSessions(WIFI_IFACE_NAME)).thenReturn(1);
when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME))
- .thenReturn(WifiManager.WIFI_FEATURE_TDLS);
+ .thenReturn(createCapabilityBitset(WifiManager.WIFI_FEATURE_TDLS));
when(mWifiNative.startTdls(eq(WIFI_IFACE_NAME), eq(TEST_TDLS_PEER_ADDR_STR), anyBoolean()))
.thenReturn(true);
assertEquals(1, mCmi.getMaxSupportedConcurrentTdlsSessions());
@@ -10970,7 +11032,7 @@
WifiSignalPollResults signalPollResults = new WifiSignalPollResults();
signalPollResults.addEntry(TEST_MLO_LINK_ID, -42, 65, 54, sFreq);
when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn(
- WifiManager.WIFI_FEATURE_LINK_LAYER_STATS);
+ createCapabilityBitset(WifiManager.WIFI_FEATURE_LINK_LAYER_STATS));
when(mWifiNative.getWifiLinkLayerStats(any())).thenReturn(llStats);
when(mWifiNative.signalPoll(any())).thenReturn(signalPollResults);
when(mClock.getWallClockMillis()).thenReturn(startMillis + 0);
@@ -11210,7 +11272,7 @@
public void testSaeH2eSetEvenThoughConfigForSaeH2eIsNotTrue() throws Exception {
when(mWifiNative.isSupplicantAidlServiceVersionAtLeast(3)).thenReturn(true);
when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn(
- WifiManager.WIFI_FEATURE_WPA3_SAE);
+ createCapabilityBitset(WifiManager.WIFI_FEATURE_WPA3_SAE));
initializeCmi();
if (SdkLevel.isAtLeastV()) {
verify(mWifiGlobals).enableWpa3SaeH2eSupport();
@@ -11218,4 +11280,15 @@
verify(mWifiGlobals, never()).enableWpa3SaeH2eSupport();
}
}
+
+ @Test
+ public void testBlockNetwork() throws Exception {
+ connect();
+ BlockingOption option = new BlockingOption.Builder(100)
+ .setBlockingBssidOnly(true).build();
+ mCmi.blockNetwork(option);
+ verify(mWifiBlocklistMonitor).blockBssidForDurationMs(eq(TEST_BSSID_STR), any(),
+ eq(100 * 1000L), eq(REASON_APP_DISALLOW), eq(0));
+ verify(mWifiBlocklistMonitor).updateAndGetBssidBlocklistForSsids(any());
+ }
}
diff --git a/service/tests/wifitests/src/com/android/server/wifi/ConcreteClientModeManagerTest.java b/service/tests/wifitests/src/com/android/server/wifi/ConcreteClientModeManagerTest.java
index e30e8f8..0f6ebe8 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/ConcreteClientModeManagerTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/ConcreteClientModeManagerTest.java
@@ -187,13 +187,15 @@
* * no deferring time for wifi off
*/
mStaticMockSession = mockitoSession()
- .mockStatic(ImsMmTelManager.class)
- .mockStatic(SubscriptionManager.class)
- .startMocking();
+ .mockStatic(ImsMmTelManager.class)
+ .mockStatic(SubscriptionManager.class)
+ .mockStatic(WifiInjector.class)
+ .startMocking();
lenient().when(ImsMmTelManager.createForSubscriptionId(eq(TEST_ACTIVE_SUBSCRIPTION_ID)))
.thenReturn(mImsMmTelManager);
lenient().when(SubscriptionManager.isValidSubscriptionId(eq(TEST_ACTIVE_SUBSCRIPTION_ID)))
.thenReturn(true);
+ when(WifiInjector.getInstance()).thenReturn(mWifiInjector);
doAnswer(new AnswerWithArguments() {
public void answer(Executor executor, RegistrationManager.RegistrationCallback c) {
mImsMmTelManagerRegistrationCallback = c;
diff --git a/service/tests/wifitests/src/com/android/server/wifi/ConfigurationMapTest.java b/service/tests/wifitests/src/com/android/server/wifi/ConfigurationMapTest.java
index dc8f7f6..b282fd1 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/ConfigurationMapTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/ConfigurationMapTest.java
@@ -17,6 +17,7 @@
package com.android.server.wifi;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
+import static com.android.server.wifi.TestUtil.createCapabilityBitset;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
@@ -111,7 +112,8 @@
when(mWifiInjector.getWifiGlobals()).thenReturn(mWifiGlobals);
when(mActiveModeWarden.getPrimaryClientModeManager()).thenReturn(mPrimaryClientModeManager);
when(mPrimaryClientModeManager.getSupportedFeatures()).thenReturn(
- WifiManager.WIFI_FEATURE_WPA3_SAE | WifiManager.WIFI_FEATURE_OWE);
+ createCapabilityBitset(
+ WifiManager.WIFI_FEATURE_WPA3_SAE, WifiManager.WIFI_FEATURE_OWE));
when(mWifiGlobals.isWpa3SaeUpgradeEnabled()).thenReturn(true);
when(mWifiGlobals.isOweUpgradeEnabled()).thenReturn(true);
diff --git a/service/tests/wifitests/src/com/android/server/wifi/HalDeviceManagerTest.java b/service/tests/wifitests/src/com/android/server/wifi/HalDeviceManagerTest.java
index f4fe281..40fd259 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/HalDeviceManagerTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/HalDeviceManagerTest.java
@@ -23,7 +23,7 @@
import static com.android.server.wifi.HalDeviceManager.HDM_CREATE_IFACE_NAN;
import static com.android.server.wifi.HalDeviceManager.HDM_CREATE_IFACE_P2P;
import static com.android.server.wifi.HalDeviceManager.HDM_CREATE_IFACE_STA;
-import static com.android.server.wifi.util.GeneralUtil.longToBitset;
+import static com.android.server.wifi.TestUtil.createCapabilityBitset;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNotNull;
@@ -38,6 +38,7 @@
import static org.junit.Assume.assumeFalse;
import static org.junit.Assume.assumeTrue;
import static org.mockito.ArgumentMatchers.anyList;
+import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyString;
@@ -1022,6 +1023,24 @@
HDM_CREATE_IFACE_AP, TEST_WORKSOURCE_1));
}
+ /**
+ * Test that BitSet comparisons are performed correctly in
+ * {@link HalDeviceManager#areChipCapabilitiesSupported(BitSet, BitSet)}
+ */
+ @Test
+ public void testRequiredCapabilitiesComparison() {
+ BitSet capabilitySubset = createCapabilityBitset(WifiManager.WIFI_FEATURE_INFRA_60G);
+ BitSet capabilitySuperset = (BitSet) capabilitySubset.clone();
+ capabilitySuperset.set(WifiManager.WIFI_FEATURE_BRIDGED_AP);
+
+ assertTrue(HalDeviceManager.areChipCapabilitiesSupported(
+ capabilitySuperset /* current caps */, new BitSet() /* no desired caps */));
+ assertTrue(HalDeviceManager.areChipCapabilitiesSupported(
+ capabilitySuperset /* current caps */, capabilitySubset /* desired caps */));
+ assertFalse(HalDeviceManager.areChipCapabilitiesSupported(
+ capabilitySubset /* current caps */, capabilitySuperset /* desired caps */));
+ }
+
//////////////////////////////////////////////////////////////////////////////////////
// Chip Specific Tests - but should work on all chips!
// (i.e. add copies for each test chip)
@@ -1787,7 +1806,6 @@
"["
+ " {"
+ " \"chipId\": 10,"
- + " \"chipCapabilities\": -1,"
+ " \"availableModes\": ["
+ " {"
+ " \"id\": 0,"
@@ -1863,6 +1881,92 @@
}));
}
+ /**
+ * Validates that {@link HalDeviceManager#canDeviceSupportCreateTypeCombo(SparseArray)} with
+ * a faulty stored static chip info will be updated once we load the chip info when the driver
+ * is up.
+ */
+ @Test
+ public void testCanDeviceSupportCreateTypeComboChipV1WithFaultyStoredStaticChipInfo()
+ throws Exception {
+ TestChipV1 chipMock = new TestChipV1();
+ chipMock.initialize();
+ mInOrder = inOrder(mWifiMock, chipMock.chip, mManagerStatusListenerMock);
+
+ // Try to query iface support before starting the HAL. Should return false with the outdated
+ // stored static chip info that's missing AP capabilities.
+ String faultyStaticChipInfo =
+ "["
+ + " {"
+ + " \"chipId\": 10,"
+ + " \"chipCapabilities\": -1,"
+ + " \"availableModes\": ["
+ + " {"
+ + " \"id\": 0,"
+ + " \"availableCombinations\": ["
+ + " {"
+ + " \"limits\": ["
+ + " {"
+ + " \"maxIfaces\": 1,"
+ + " \"types\": [0]"
+ + " },"
+ + " {"
+ + " \"maxIfaces\": 1,"
+ + " \"types\": [3, 4]";
+ when(mWifiMock.isStarted()).thenReturn(false);
+ when(mWifiSettingsConfigStore.get(WifiSettingsConfigStore.WIFI_STATIC_CHIP_INFO))
+ .thenReturn(faultyStaticChipInfo);
+
+ // Can't create anything since the stored static chip info is faulty.
+ assertFalse(
+ mDut.canDeviceSupportCreateTypeCombo(
+ new SparseArray<Integer>() {
+ {
+ put(WifiChip.IFACE_CONCURRENCY_TYPE_NAN, 1);
+ }
+ }));
+ assertFalse(
+ mDut.canDeviceSupportCreateTypeCombo(
+ new SparseArray<Integer>() {
+ {
+ put(WifiChip.IFACE_CONCURRENCY_TYPE_AP, 1);
+ }
+ }));
+
+ verify(mWifiMock, never()).getChipIds();
+ when(mWifiMock.isStarted()).thenReturn(true);
+ executeAndValidateStartupSequence();
+ clearInvocations(mWifiMock);
+
+ // Create a STA to get the static chip info from driver and save it to store.
+ validateInterfaceSequence(
+ chipMock,
+ false, // chipModeValid
+ -1000, // chipModeId (only used if chipModeValid is true)
+ HDM_CREATE_IFACE_STA, // ifaceTypeToCreate
+ "wlan0", // ifaceName
+ TestChipV1.STA_CHIP_MODE_ID, // finalChipMode
+ null, // tearDownList
+ mock(InterfaceDestroyedListener.class), // destroyedListener
+ TEST_WORKSOURCE_0 // requestorWs
+ );
+
+ // Verify that the latest static chip info is saved to store.
+ verify(mWifiSettingsConfigStore)
+ .put(
+ eq(WifiSettingsConfigStore.WIFI_STATIC_CHIP_INFO),
+ eq(new JSONArray(TestChipV1.STATIC_CHIP_INFO_JSON_STRING).toString()));
+
+ // Now we can create an AP.
+ assertTrue(
+ mDut.canDeviceSupportCreateTypeCombo(
+ new SparseArray<Integer>() {
+ {
+ put(WifiChip.IFACE_CONCURRENCY_TYPE_AP, 1);
+ }
+ }));
+ }
+
@Test
public void testIsItPossibleToCreateIfaceTestChipV1() throws Exception {
assumeTrue(SdkLevel.isAtLeastS());
@@ -3288,7 +3392,8 @@
public void verify60GhzIfaceCreation(
ChipMockBase chipMock, int chipModeId, int finalChipModeId, boolean isWigigSupported)
throws Exception {
- long requiredChipCapabilities = WifiManager.WIFI_FEATURE_INFRA_60G;
+ BitSet requiredChipCapabilities =
+ createCapabilityBitset(WifiManager.WIFI_FEATURE_INFRA_60G);
chipMock.initialize();
mInOrder = inOrder(mWifiMock, chipMock.chip, mManagerStatusListenerMock);
executeAndValidateStartupSequence();
@@ -3350,7 +3455,7 @@
when(mWorkSourceHelper1.getRequestorWsPriority())
.thenReturn(WorkSourceHelper.PRIORITY_PRIVILEGED);
assertThat(mDut.isItPossibleToCreateIface(HDM_CREATE_IFACE_P2P,
- WifiManager.WIFI_FEATURE_INFRA_60G,
+ createCapabilityBitset(WifiManager.WIFI_FEATURE_INFRA_60G),
TEST_WORKSOURCE_1), is(isWigigSupported));
}
}
@@ -4117,6 +4222,157 @@
collector.checkThat("interface was null", p2pIface, IsNull.notNullValue());
}
+ /**
+ * Validate an AP request from requestors not on the AP/NAN concurrency allowlist.
+ */
+ @Test
+ public void testApNanConcurrencyNotAllowedTestChipV11()
+ throws Exception {
+ when(mResources.getStringArray(R.array.config_wifiSoftApAwareConcurrencyAllowlist))
+ .thenReturn(new String[]{"Some other package"});
+
+ TestChipV11 chipMock = new TestChipV11();
+ chipMock.initialize();
+ mInOrder = inOrder(mWifiMock, chipMock.chip, mManagerStatusListenerMock);
+ executeAndValidateStartupSequence();
+
+ InterfaceDestroyedListener idl = mock(InterfaceDestroyedListener.class);
+
+ // Create a NAN
+ WifiInterface nanIface = validateInterfaceSequence(chipMock,
+ false, // chipModeValid
+ -1000, // chipModeId (only used if chipModeValid is true)
+ HDM_CREATE_IFACE_NAN,
+ "wlan0",
+ TestChipV11.CHIP_MODE_ID,
+ null, // tearDownList
+ idl, // destroyedListener
+ TEST_WORKSOURCE_0 // requestorWs
+ );
+ collector.checkThat("interface was null", nanIface, IsNull.notNullValue());
+
+ // AP request from Worksource 1 (lower priority) should be blocked.
+ when(mWorkSourceHelper1.getRequestorWsPriority())
+ .thenReturn(WorkSourceHelper.PRIORITY_FG_APP);
+ List<Pair<Integer, WorkSource>> apDetails = mDut.reportImpactToCreateIface(
+ HDM_CREATE_IFACE_AP, true, TEST_WORKSOURCE_1);
+ if (SdkLevel.isAtLeastS()) {
+ assertNull("Should not be able to create this AP", apDetails);
+ } else {
+ // Pre-S lets AP/NAN destroy each other.
+ assertEquals(apDetails.get(0).second, TEST_WORKSOURCE_0);
+ }
+
+ // Bridged AP request should also be blocked
+ apDetails = mDut.reportImpactToCreateIface(
+ HDM_CREATE_IFACE_AP_BRIDGE, true, TEST_WORKSOURCE_1);
+ if (SdkLevel.isAtLeastS()) {
+ assertNull("Should not be able to create this Bridged AP", apDetails);
+ } else {
+ // Pre-S lets AP/NAN destroy each other.
+ assertEquals(apDetails.get(0).second, TEST_WORKSOURCE_0);
+ }
+
+ // AP request from Worksource 2 (same privileged priority) should tear down NAN.
+ WifiInterface ApIface = validateInterfaceSequence(chipMock,
+ true, // chipModeValid
+ TestChipV11.CHIP_MODE_ID, // chipModeId (only used if chipModeValid is true)
+ HDM_CREATE_IFACE_AP,
+ "wlan1",
+ TestChipV11.CHIP_MODE_ID,
+ new WifiInterface[]{nanIface}, // tearDownList
+ idl, // destroyedListener
+ TEST_WORKSOURCE_2 // requestorWs
+ );
+ collector.checkThat("interface was null", ApIface, IsNull.notNullValue());
+ }
+
+ /**
+ * Validate an AP request from a requestor on the AP/NAN concurrency allowlist.
+ */
+ @Test
+ public void testSingleApNanConcurrencyAllowedTestChipV11()
+ throws Exception {
+ when(mResources.getStringArray(R.array.config_wifiSoftApAwareConcurrencyAllowlist))
+ .thenReturn(new String[]{TEST_WORKSOURCE_1.getPackageName(0)});
+
+ TestChipV11 chipMock = new TestChipV11();
+ chipMock.initialize();
+ mInOrder = inOrder(mWifiMock, chipMock.chip, mManagerStatusListenerMock);
+ executeAndValidateStartupSequence();
+
+ InterfaceDestroyedListener idl = mock(InterfaceDestroyedListener.class);
+
+ // Create a NAN
+ WifiInterface nanIface = validateInterfaceSequence(chipMock,
+ false, // chipModeValid
+ -1000, // chipModeId (only used if chipModeValid is true)
+ HDM_CREATE_IFACE_NAN,
+ "wlan0",
+ TestChipV11.CHIP_MODE_ID,
+ null, // tearDownList
+ idl, // destroyedListener
+ TEST_WORKSOURCE_0 // requestorWs
+ );
+ collector.checkThat("interface was null", nanIface, IsNull.notNullValue());
+
+ // AP request from Worksource 1 (on allowlist) should be allowed.
+ WifiInterface apIface = validateInterfaceSequence(chipMock,
+ true, // chipModeValid
+ TestChipV11.CHIP_MODE_ID, // chipModeId (only used if chipModeValid is true)
+ HDM_CREATE_IFACE_AP,
+ "wlan1",
+ TestChipV11.CHIP_MODE_ID,
+ null, // tearDownList
+ idl, // destroyedListener
+ TEST_WORKSOURCE_1 // requestorWs
+ );
+ collector.checkThat("interface was null", apIface, IsNull.notNullValue());
+ }
+
+ /**
+ * Validate a Bridged AP request from a requestor on the AP/NAN concurrency allowlist.
+ */
+ @Test
+ public void testBridgedApNanConcurrencyAllowedTestChipV11()
+ throws Exception {
+ when(mResources.getStringArray(R.array.config_wifiSoftApAwareConcurrencyAllowlist))
+ .thenReturn(new String[]{TEST_WORKSOURCE_1.getPackageName(0)});
+
+ TestChipV11 chipMock = new TestChipV11();
+ chipMock.initialize();
+ mInOrder = inOrder(mWifiMock, chipMock.chip, mManagerStatusListenerMock);
+ executeAndValidateStartupSequence();
+
+ InterfaceDestroyedListener idl = mock(InterfaceDestroyedListener.class);
+
+ // Create a NAN
+ WifiInterface nanIface = validateInterfaceSequence(chipMock,
+ false, // chipModeValid
+ -1000, // chipModeId (only used if chipModeValid is true)
+ HDM_CREATE_IFACE_NAN,
+ "wlan0",
+ TestChipV11.CHIP_MODE_ID,
+ null, // tearDownList
+ idl, // destroyedListener
+ TEST_WORKSOURCE_0 // requestorWs
+ );
+ collector.checkThat("interface was null", nanIface, IsNull.notNullValue());
+
+ // Bridged AP request from Worksource 1 (on allowlist) should be allowed.
+ WifiInterface apIface = validateInterfaceSequence(chipMock,
+ true, // chipModeValid
+ TestChipV11.CHIP_MODE_ID, // chipModeId (only used if chipModeValid is true)
+ HDM_CREATE_IFACE_AP_BRIDGE,
+ "wlan1",
+ TestChipV11.CHIP_MODE_ID,
+ null, // tearDownList
+ idl, // destroyedListener
+ TEST_WORKSOURCE_1 // requestorWs
+ );
+ collector.checkThat("interface was null", apIface, IsNull.notNullValue());
+ }
+
///////////////////////////////////////////////////////////////////////////////////////
// utilities
///////////////////////////////////////////////////////////////////////////////////////
@@ -4294,7 +4550,7 @@
private WifiInterface validateInterfaceSequence(ChipMockBase chipMock,
boolean chipModeValid, int chipModeId,
int createIfaceType, String ifaceName, int finalChipMode,
- long requiredChipCapabilities,
+ BitSet requiredChipCapabilities,
WifiInterface[] tearDownList,
InterfaceDestroyedListener destroyedListener,
WorkSource requestorWs,
@@ -4338,8 +4594,8 @@
}
doAnswer(new CreateApIfaceAnswer(chipMock, true, iface))
.when(chipMock.chip).createApIface(anyList());
- doAnswer(new CreateApIfaceAnswer(chipMock, true, iface))
- .when(chipMock.chip).createBridgedApIface(anyList());
+ doAnswer(new CreateBridgedApIfaceAnswer(chipMock, true, iface))
+ .when(chipMock.chip).createBridgedApIface(anyList(), anyBoolean());
mDut.createApIface(requiredChipCapabilities,
destroyedListener, mHandler, requestorWs,
createIfaceType == HDM_CREATE_IFACE_AP_BRIDGE, mSoftApManager,
@@ -4395,7 +4651,7 @@
mInOrder.verify(chipMock.chip).createStaIface();
break;
case HDM_CREATE_IFACE_AP_BRIDGE:
- mInOrder.verify(chipMock.chip).createBridgedApIface(anyList());
+ mInOrder.verify(chipMock.chip).createBridgedApIface(anyList(), anyBoolean());
break;
case HDM_CREATE_IFACE_AP:
mInOrder.verify(chipMock.chip).createApIface(anyList());
@@ -4493,7 +4749,7 @@
public WifiChip.Response<BitSet> answer() {
WifiChip.Response<BitSet> response =
- new WifiChip.Response<>(longToBitset(mChipMockBase.chipCapabilities));
+ new WifiChip.Response<>(mChipMockBase.chipCapabilities);
response.setStatusCode(mChipMockBase.allowGetCapsBeforeIfaceCreated
? WifiHal.WIFI_STATUS_SUCCESS : WifiHal.WIFI_STATUS_ERROR_UNKNOWN);
return response;
@@ -4669,6 +4925,20 @@
}
}
+ private class CreateBridgedApIfaceAnswer extends CreateXxxIfaceAnswer {
+ CreateBridgedApIfaceAnswer(ChipMockBase chipMockBase, boolean success,
+ WifiInterface wifiIface) {
+ super(chipMockBase, success, wifiIface, WifiChip.IFACE_TYPE_AP);
+ }
+
+ @SuppressWarnings("unused")
+ public WifiApIface answer(@NonNull List<OuiKeyedData> vendorData,
+ boolean isUsingMultiLinkOperation) {
+ addInterfaceInfo();
+ return mSuccess ? (WifiApIface) mWifiIface : null;
+ }
+ }
+
private class CreateP2pIfaceAnswer extends CreateXxxIfaceAnswer {
CreateP2pIfaceAnswer(ChipMockBase chipMockBase, boolean success, WifiInterface wifiIface) {
super(chipMockBase, success, wifiIface, WifiChip.IFACE_TYPE_P2P);
@@ -4809,7 +5079,7 @@
public boolean chipModeValid = false;
public int chipModeId = -1000;
public int chipModeIdValidForRtt = -1; // single chip mode ID where RTT can be created
- public long chipCapabilities = 0L;
+ public BitSet chipCapabilities = new BitSet();
public boolean allowGetCapsBeforeIfaceCreated = true;
public List<WifiChip.WifiRadioCombination> chipSupportedRadioCombinations = null;
public Map<Integer, ArrayList<String>> interfaceNames = new HashMap<>();
@@ -4886,7 +5156,6 @@
static final String STATIC_CHIP_INFO_JSON_STRING = "["
+ " {"
+ " \"chipId\": 10,"
- + " \"chipCapabilities\": 0,"
+ " \"availableModes\": ["
+ " {"
+ " \"id\": 0,"
@@ -4963,7 +5232,6 @@
static final String STATIC_CHIP_INFO_JSON_STRING = "["
+ " {"
+ " \"chipId\": 12,"
- + " \"chipCapabilities\": 0,"
+ " \"availableModes\": ["
+ " {"
+ " \"id\": 5,"
@@ -5112,7 +5380,7 @@
super.initialize();
chipMockId = CHIP_MOCK_V5;
- chipCapabilities |= WifiManager.WIFI_FEATURE_INFRA_60G;
+ chipCapabilities.set(WifiManager.WIFI_FEATURE_INFRA_60G);
// chip Id configuration
ArrayList<Integer> chipIds;
@@ -5169,7 +5437,6 @@
static final String STATIC_CHIP_INFO_JSON_STRING = "["
+ " {"
+ " \"chipId\": 6,"
- + " \"chipCapabilities\": 0,"
+ " \"availableModes\": ["
+ " {"
+ " \"id\": 60,"
@@ -5352,7 +5619,6 @@
static final String STATIC_CHIP_INFO_JSON_STRING = "["
+ " {"
+ " \"chipId\": 10,"
- + " \"chipCapabilities\": -1,"
+ " \"availableModes\": ["
+ " {"
+ " \"id\": 100,"
@@ -5418,7 +5684,7 @@
// Test chip configuration V11 for P2P/NAN concurrency
// mode:
- // (STA + AP + NAN + P2P)
+ // (STA + AP + AP_BRIDGE + NAN + P2P)
private class TestChipV11 extends ChipMockBase {
static final int CHIP_MODE_ID = 90;
@@ -5440,6 +5706,7 @@
WifiChip.ChipConcurrencyCombination combo1 = createConcurrencyCombo(
createConcurrencyComboLimit(1, WifiChip.IFACE_CONCURRENCY_TYPE_STA),
createConcurrencyComboLimit(1, WifiChip.IFACE_CONCURRENCY_TYPE_AP),
+ createConcurrencyComboLimit(1, WifiChip.IFACE_CONCURRENCY_TYPE_AP_BRIDGED),
createConcurrencyComboLimit(1, WifiChip.IFACE_CONCURRENCY_TYPE_P2P),
createConcurrencyComboLimit(1, WifiChip.IFACE_CONCURRENCY_TYPE_NAN));
availableModes.add(createChipMode(CHIP_MODE_ID, combo1));
diff --git a/service/tests/wifitests/src/com/android/server/wifi/HostapdHalAidlImpTest.java b/service/tests/wifitests/src/com/android/server/wifi/HostapdHalAidlImpTest.java
index 0d54c81..0055781 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/HostapdHalAidlImpTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/HostapdHalAidlImpTest.java
@@ -34,8 +34,10 @@
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.validateMockitoUsage;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.withSettings;
import android.app.test.MockAnswerUtil;
import android.hardware.wifi.hostapd.ApInfo;
@@ -53,11 +55,13 @@
import android.hardware.wifi.hostapd.IfaceParams;
import android.hardware.wifi.hostapd.NetworkParams;
import android.net.MacAddress;
+import android.net.wifi.DeauthenticationReasonCode;
import android.net.wifi.OuiKeyedData;
import android.net.wifi.SoftApConfiguration;
import android.net.wifi.SoftApConfiguration.Builder;
import android.net.wifi.WifiContext;
import android.net.wifi.WifiManager;
+import android.net.wifi.util.Environment;
import android.net.wifi.util.PersistableBundleUtils;
import android.net.wifi.util.WifiResourceCache;
import android.os.Binder;
@@ -72,19 +76,24 @@
import androidx.test.filters.SmallTest;
+import com.android.dx.mockito.inline.extended.ExtendedMockito;
import com.android.modules.utils.build.SdkLevel;
import com.android.server.wifi.util.ApConfigUtil;
import com.android.server.wifi.util.NativeUtil;
+import com.android.wifi.flags.Flags;
import com.android.wifi.resources.R;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.mockito.MockitoSession;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
/**
* Unit tests for HostapdHal
@@ -102,6 +111,10 @@
private static final int TEST_FREQ_5G = 5745;
private static final int TEST_BANDWIDTH = ChannelBandwidth.BANDWIDTH_20;
private static final int TEST_GENERATION = Generation.WIFI_STANDARD_11N;
+ private static final int TEST_HAL_DEAUTHENTICATION_REASON_CODE =
+ android.hardware.wifi.common.DeauthenticationReasonCode.GROUP_CIPHER_NOT_VALID;
+ private static final int DEFAULT_DISCONNECT_REASON =
+ DeauthenticationReasonCode.REASON_UNKNOWN;
private final int mBand256G = SoftApConfiguration.BAND_2GHZ | SoftApConfiguration.BAND_5GHZ
| SoftApConfiguration.BAND_6GHZ;
@@ -115,6 +128,7 @@
private IHostapdCallback mIHostapdCallback;
private MockResources mResources;
+ private MockitoSession mSession;
private TestLooper mLooper = new TestLooper();
private HostapdHalAidlImp mHostapdHal;
@@ -182,6 +196,9 @@
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
+ mSession = ExtendedMockito.mockitoSession()
+ .mockStatic(Flags.class, withSettings().lenient())
+ .startMocking();
mResources = new MockResources();
mResources.setBoolean(R.bool.config_wifi_softap_acs_supported, false);
mResources.setBoolean(R.bool.config_wifi_softap_ieee80211ac_supported, false);
@@ -201,6 +218,17 @@
}
/**
+ * Called after each test
+ */
+ @After
+ public void cleanup() {
+ validateMockitoUsage();
+ if (mSession != null) {
+ mSession.finishMocking();
+ }
+ }
+
+ /**
* Sunny day scenario for HostapdHal initialization
* Asserts successful initialization
*/
@@ -267,7 +295,7 @@
configurationBuilder.setChannel(apChannel, SoftApConfiguration.BAND_2GHZ);
assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME,
- configurationBuilder.build(), true,
+ configurationBuilder.build(), true, false, Collections.emptyList(),
() -> mSoftApHalCallback.onFailure()));
verify(mIHostapdMock).addAccessPoint(any(), any());
@@ -300,7 +328,7 @@
configurationBuilder.setChannel(apChannel, SoftApConfiguration.BAND_5GHZ);
assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME,
- configurationBuilder.build(), true,
+ configurationBuilder.build(), true, false, Collections.emptyList(),
() -> mSoftApHalCallback.onFailure()));
verify(mIHostapdMock).addAccessPoint(any(), any());
@@ -335,7 +363,7 @@
configurationBuilder.setChannel(apChannel, SoftApConfiguration.BAND_5GHZ);
assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME,
- configurationBuilder.build(), true,
+ configurationBuilder.build(), true, false, Collections.emptyList(),
() -> mSoftApHalCallback.onFailure()));
verify(mIHostapdMock).addAccessPoint(any(), any());
@@ -374,7 +402,7 @@
configurationBuilder.setChannel(apChannel, SoftApConfiguration.BAND_2GHZ);
assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME,
- configurationBuilder.build(), true,
+ configurationBuilder.build(), true, false, Collections.emptyList(),
() -> mSoftApHalCallback.onFailure()));
verify(mIHostapdMock).addAccessPoint(any(), any());
@@ -414,7 +442,7 @@
configurationBuilder.setChannel(apChannel, SoftApConfiguration.BAND_2GHZ);
assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME,
- configurationBuilder.build(), true,
+ configurationBuilder.build(), true, false, Collections.emptyList(),
() -> mSoftApHalCallback.onFailure()));
verify(mIHostapdMock).addAccessPoint(any(), any());
@@ -452,7 +480,7 @@
configurationBuilder.setBand(mBand256G);
assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME,
- configurationBuilder.build(), true,
+ configurationBuilder.build(), true, false, Collections.emptyList(),
() -> mSoftApHalCallback.onFailure()));
verify(mIHostapdMock).addAccessPoint(any(), any());
@@ -489,7 +517,7 @@
configurationBuilder.setBand(mBand256G);
assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME,
- configurationBuilder.build(), true,
+ configurationBuilder.build(), true, false, Collections.emptyList(),
() -> mSoftApHalCallback.onFailure()));
verify(mIHostapdMock).addAccessPoint(any(), any());
@@ -518,7 +546,7 @@
configurationBuilder.setChannel(6, SoftApConfiguration.BAND_2GHZ);
assertFalse(mHostapdHal.addAccessPoint(IFACE_NAME,
- configurationBuilder.build(), true,
+ configurationBuilder.build(), true, false, Collections.emptyList(),
() -> mSoftApHalCallback.onFailure()));
verify(mIHostapdMock).addAccessPoint(any(), any());
}
@@ -537,7 +565,7 @@
configurationBuilder.setChannel(6, SoftApConfiguration.BAND_2GHZ);
assertFalse(mHostapdHal.addAccessPoint(IFACE_NAME,
- configurationBuilder.build(), true,
+ configurationBuilder.build(), true, false, Collections.emptyList(),
() -> mSoftApHalCallback.onFailure()));
verify(mIHostapdMock).addAccessPoint(any(), any());
}
@@ -590,7 +618,7 @@
configurationBuilder.setBand(SoftApConfiguration.BAND_2GHZ);
assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME,
- configurationBuilder.build(), true,
+ configurationBuilder.build(), true, false, Collections.emptyList(),
() -> mSoftApHalCallback.onFailure()));
verify(mIHostapdMock).addAccessPoint(any(), any());
@@ -769,7 +797,7 @@
mIfaceParamsCaptor.capture(), mNetworkParamsCaptor.capture());
assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME,
- configurationBuilder.build(), true,
+ configurationBuilder.build(), true, false, Collections.emptyList(),
() -> mSoftApHalCallback.onFailure()));
verify(mIHostapdMock).addAccessPoint(any(), any());
@@ -808,7 +836,7 @@
mIfaceParamsCaptor.capture(), mNetworkParamsCaptor.capture());
assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME,
- configurationBuilder.build(), true,
+ configurationBuilder.build(), true, false, Collections.emptyList(),
() -> mSoftApHalCallback.onFailure()));
verify(mIHostapdMock).addAccessPoint(any(), any());
@@ -845,7 +873,7 @@
configurationBuilder.setBand(mBand256G);
assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME,
- configurationBuilder.build(), true,
+ configurationBuilder.build(), true, false, Collections.emptyList(),
() -> mSoftApHalCallback.onFailure()));
verify(mIHostapdMock).addAccessPoint(any(), any());
@@ -869,6 +897,7 @@
*/
@Test
public void testHostapdCallbackEvent() throws Exception {
+ when(mIHostapdMock.getInterfaceVersion()).thenReturn(3);
executeAndValidateInitializationSequence(true);
Builder configurationBuilder = new SoftApConfiguration.Builder();
configurationBuilder.setSsid(NETWORK_SSID);
@@ -876,7 +905,7 @@
doNothing().when(mIHostapdMock).addAccessPoint(any(), any());
assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME,
- configurationBuilder.build(), true,
+ configurationBuilder.build(), true, false, Collections.emptyList(),
() -> mSoftApHalCallback.onFailure()));
verify(mIHostapdMock).addAccessPoint(any(), any());
// Register SoftApManager callback
@@ -884,7 +913,7 @@
// Add second AP to test that the callbacks are triggered for the correct iface.
assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME_1,
- configurationBuilder.build(), true,
+ configurationBuilder.build(), true, false, Collections.emptyList(),
() -> mSoftApHalCallback1.onFailure()));
mHostapdHal.registerApCallback(IFACE_NAME_1, mSoftApHalCallback1);
@@ -906,16 +935,32 @@
clientInfo.isConnected = true;
mIHostapdCallback.onConnectedClientsChanged(clientInfo);
verify(mSoftApHalCallback).onConnectedClientsChanged(eq(TEST_AP_INSTANCE),
- eq(MacAddress.fromString(TEST_CLIENT_MAC)), eq(true));
+ eq(MacAddress.fromString(TEST_CLIENT_MAC)), eq(true),
+ eq(DEFAULT_DISCONNECT_REASON));
verify(mSoftApHalCallback1, never()).onConnectedClientsChanged(
- anyString(), any(), anyBoolean());
+ anyString(), any(), anyBoolean(), anyInt());
+
+ // Trigger client disconnect
+ clientInfo = new ClientInfo();
+ clientInfo.ifaceName = IFACE_NAME;
+ clientInfo.apIfaceInstance = TEST_AP_INSTANCE;
+ clientInfo.clientAddress = MacAddress.fromString(TEST_CLIENT_MAC).toByteArray();
+ clientInfo.isConnected = false;
+ clientInfo.disconnectReasonCode = TEST_HAL_DEAUTHENTICATION_REASON_CODE;
+ mIHostapdCallback.onConnectedClientsChanged(clientInfo);
+ verify(mSoftApHalCallback).onConnectedClientsChanged(eq(TEST_AP_INSTANCE),
+ eq(MacAddress.fromString(TEST_CLIENT_MAC)), eq(false),
+ eq(mHostapdHal.mapHalToFrameworkDeauthenticationReasonCode(
+ TEST_HAL_DEAUTHENTICATION_REASON_CODE)));
+ verify(mSoftApHalCallback1, never()).onConnectedClientsChanged(
+ anyString(), any(), anyBoolean(), anyInt());
}
/**
- * Verifies the successful addition of access point with SAE with metered indication.
+ * Verifies the successful addition of access point with SAE with metered.
*/
@Test
- public void testAddAccessPointSuccess_WithMeteredSAE() throws Exception {
+ public void testAddSAEAccessPointSuccess_WithMetered() throws Exception {
boolean isMetered = true;
mResources.setBoolean(R.bool.config_wifi_softap_acs_supported, true);
mHostapdHal = new HostapdHalSpy();
@@ -933,7 +978,7 @@
mIfaceParamsCaptor.capture(), mNetworkParamsCaptor.capture());
assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME,
- configurationBuilder.build(), isMetered,
+ configurationBuilder.build(), isMetered, false, Collections.emptyList(),
() -> mSoftApHalCallback.onFailure()));
verify(mIHostapdMock).addAccessPoint(any(), any());
@@ -973,7 +1018,7 @@
mIfaceParamsCaptor.capture(), mNetworkParamsCaptor.capture());
assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME,
- configurationBuilder.build(), isMetered,
+ configurationBuilder.build(), isMetered, false, Collections.emptyList(),
() -> mSoftApHalCallback.onFailure()));
verify(mIHostapdMock).addAccessPoint(any(), any());
@@ -1043,7 +1088,7 @@
mIfaceParamsCaptor.capture(), mNetworkParamsCaptor.capture());
assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME,
- configurationBuilder.build(), true,
+ configurationBuilder.build(), true, false, Collections.emptyList(),
() -> mSoftApHalCallback.onFailure()));
verify(mIHostapdMock).addAccessPoint(any(), any());
@@ -1109,7 +1154,7 @@
mIfaceParamsCaptor.capture(), mNetworkParamsCaptor.capture());
assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME,
- configurationBuilder.build(), isMetered,
+ configurationBuilder.build(), isMetered, false, Collections.emptyList(),
() -> mSoftApHalCallback.onFailure()));
verify(mIHostapdMock).addAccessPoint(any(), any());
@@ -1155,7 +1200,7 @@
mIfaceParamsCaptor.capture(), mNetworkParamsCaptor.capture());
assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME,
- configurationBuilder.build(), isMetered,
+ configurationBuilder.build(), isMetered, false, Collections.emptyList(),
() -> mSoftApHalCallback.onFailure()));
verify(mIHostapdMock).addAccessPoint(any(), any());
@@ -1188,7 +1233,7 @@
doNothing().when(mIHostapdMock).addAccessPoint(any(), any());
assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME,
- configurationBuilder.build(), true,
+ configurationBuilder.build(), true, false, Collections.emptyList(),
() -> mSoftApHalCallback.onFailure()));
verify(mIHostapdMock).addAccessPoint(any(), any());
@@ -1222,7 +1267,7 @@
doNothing().when(mIHostapdMock).addAccessPoint(any(), any());
assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME,
- configurationBuilder.build(), true,
+ configurationBuilder.build(), true, false, Collections.emptyList(),
() -> mSoftApHalCallback.onFailure()));
verify(mIHostapdMock).addAccessPoint(any(), any());
@@ -1246,7 +1291,11 @@
/**
* Verifies that SoftApConfigurations containing OEM-specific vendor data
* are handled currently in addAccessPoint.
+ *
+ * SuppressWarnings DirectInvocationOnMock for "mSoftApHalCallback.onFailure()"
+ * since it is a lambda callback implementation. Not a really function call.
*/
+ @SuppressWarnings("DirectInvocationOnMock")
@Test
public void testAddAccessPointWithVendorData() throws Exception {
assumeTrue(SdkLevel.isAtLeastV());
@@ -1259,7 +1308,7 @@
// SoftApConfig does not contain vendor data.
assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME,
- configurationBuilder.build(), true,
+ configurationBuilder.build(), true, false, Collections.emptyList(),
() -> mSoftApHalCallback.onFailure()));
verify(mIHostapdMock).addAccessPoint(any(), any());
assertNull(mIfaceParamsCaptor.getValue().vendorData);
@@ -1272,7 +1321,7 @@
// SoftApConfig contains vendor data.
assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME,
- configurationBuilder.build(), true,
+ configurationBuilder.build(), true, false, Collections.emptyList(),
() -> mSoftApHalCallback.onFailure()));
verify(mIHostapdMock, times(2)).addAccessPoint(any(), any());
android.hardware.wifi.common.OuiKeyedData[] halDataList =
@@ -1281,4 +1330,82 @@
assertEquals(oui, halDataList[0].oui);
assertTrue(PersistableBundleUtils.isEqual(bundle, halDataList[0].vendorData));
}
+
+ /**
+ * Verifies that MLO AP is handled currently in addAccessPoint.
+ *
+ * SuppressWarnings DirectInvocationOnMock for "mSoftApHalCallback.onFailure()"
+ * since it is a lambda callback implementation. Not a really function call.
+ */
+ @SuppressWarnings("DirectInvocationOnMock")
+ @Test
+ public void testAddAccessPointWithMLOConfiguration() throws Exception {
+ assumeTrue(SdkLevel.isAtLeastT());
+ when(mIHostapdMock.getInterfaceVersion()).thenReturn(3);
+ executeAndValidateInitializationSequence(true);
+ Builder configurationBuilder = new SoftApConfiguration.Builder();
+ configurationBuilder.setSsid(NETWORK_SSID);
+ configurationBuilder.setBands(new int[] {SoftApConfiguration.BAND_2GHZ,
+ SoftApConfiguration.BAND_5GHZ});
+ doNothing().when(mIHostapdMock).addAccessPoint(mIfaceParamsCaptor.capture(), any());
+ assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME,
+ configurationBuilder.build(), true, true, Arrays.asList(new String[] {"1", "2"}),
+ () -> mSoftApHalCallback.onFailure()));
+ verify(mIHostapdMock).addAccessPoint(any(), any());
+ assertTrue(mIfaceParamsCaptor.getValue().usesMlo);
+ assertTrue(Arrays.equals(new String[] {"1", "2"},
+ mIfaceParamsCaptor.getValue().instanceIdentities));
+ }
+
+ /*
+ * Verifies the successful addition of access point with SAE with
+ * client isolation indication.
+ *
+ * SuppressWarnings DirectInvocationOnMock for "mSoftApHalCallback.onFailure()"
+ * since it is a lambda callback implementation. Not a really function call.
+ */
+ @SuppressWarnings("DirectInvocationOnMock")
+ @Test
+ public void testAddSAEAccessPointSuccess_WithClientIsolationAndNullBridgedInstances()
+ throws Exception {
+ assumeTrue(Environment.isSdkAtLeastB());
+ mResources.setBoolean(R.bool.config_wifi_softap_acs_supported, true);
+ when(Flags.mloSap()).thenReturn(true);
+ when(Flags.apIsolate()).thenReturn(true);
+ when(mIHostapdMock.getInterfaceVersion()).thenReturn(3);
+ mHostapdHal = new HostapdHalSpy();
+
+ executeAndValidateInitializationSequence(true);
+
+ Builder configurationBuilder = new SoftApConfiguration.Builder();
+ configurationBuilder.setSsid(NETWORK_SSID);
+ configurationBuilder.setClientIsolationEnabled(true);
+ configurationBuilder.setHiddenSsid(false);
+ configurationBuilder.setPassphrase(NETWORK_PSK,
+ SoftApConfiguration.SECURITY_TYPE_WPA3_SAE);
+ configurationBuilder.setBand(mBand256G);
+
+ doNothing().when(mIHostapdMock).addAccessPoint(
+ mIfaceParamsCaptor.capture(), mNetworkParamsCaptor.capture());
+
+ // Null instanceIdentities won't cause crash.
+ assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME,
+ configurationBuilder.build(), true, false, null /* instanceIdentities */,
+ () -> mSoftApHalCallback.onFailure()));
+ verify(mIHostapdMock).addAccessPoint(any(), any());
+
+ assertEquals(IFACE_NAME, mIfaceParamsCaptor.getValue().name);
+ assertTrue(mIfaceParamsCaptor.getValue().hwModeParams.enable80211N);
+ assertFalse(mIfaceParamsCaptor.getValue().hwModeParams.enable80211AC);
+ assertTrue(mIfaceParamsCaptor.getValue().channelParams[0].enableAcs);
+
+ assertEquals(NETWORK_SSID,
+ NativeUtil.stringFromByteArray(mNetworkParamsCaptor.getValue().ssid));
+ assertTrue(mNetworkParamsCaptor.getValue().isClientIsolationEnabled);
+ assertFalse(mNetworkParamsCaptor.getValue().isHidden);
+ assertEquals(EncryptionType.WPA3_SAE,
+ mNetworkParamsCaptor.getValue().encryptionType);
+ assertEquals(NETWORK_PSK, mNetworkParamsCaptor.getValue().passphrase);
+ assertTrue(mNetworkParamsCaptor.getValue().isMetered);
+ }
}
diff --git a/service/tests/wifitests/src/com/android/server/wifi/HostapdHalHidlImpTest.java b/service/tests/wifitests/src/com/android/server/wifi/HostapdHalHidlImpTest.java
index a6a9010..0a2c12b 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/HostapdHalHidlImpTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/HostapdHalHidlImpTest.java
@@ -49,6 +49,7 @@
import android.hidl.manager.V1_0.IServiceManager;
import android.hidl.manager.V1_0.IServiceNotification;
import android.net.MacAddress;
+import android.net.wifi.DeauthenticationReasonCode;
import android.net.wifi.SoftApConfiguration;
import android.net.wifi.SoftApConfiguration.Builder;
import android.net.wifi.WifiContext;
@@ -74,6 +75,7 @@
import org.mockito.MockitoAnnotations;
import java.util.ArrayList;
+import java.util.Collections;
/**
* Unit tests for HostapdHal
@@ -86,6 +88,8 @@
private static final String NETWORK_PSK = "test-psk";
private static final String TEST_CLIENT_MAC = "11:22:33:44:55:66";
private static final String TEST_AP_INSTANCE = "instance-wlan0";
+ private static final int DEFAULT_DISCONNECT_REASON =
+ DeauthenticationReasonCode.REASON_UNKNOWN;
private final int mBand256G = SoftApConfiguration.BAND_2GHZ | SoftApConfiguration.BAND_5GHZ
| SoftApConfiguration.BAND_6GHZ;
@@ -300,7 +304,7 @@
configurationBuilder.setChannel(apChannel, SoftApConfiguration.BAND_2GHZ);
assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME,
- configurationBuilder.build(), true,
+ configurationBuilder.build(), true, false, Collections.emptyList(),
() -> mSoftApHalCallback.onFailure()));
verify(mIHostapdMock).addAccessPoint(any(), any());
@@ -333,7 +337,7 @@
configurationBuilder.setChannel(apChannel, SoftApConfiguration.BAND_5GHZ);
assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME,
- configurationBuilder.build(), true,
+ configurationBuilder.build(), true, false, Collections.emptyList(),
() -> mSoftApHalCallback.onFailure()));
verify(mIHostapdMock).addAccessPoint(any(), any());
@@ -368,7 +372,7 @@
configurationBuilder.setChannel(apChannel, SoftApConfiguration.BAND_5GHZ);
assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME,
- configurationBuilder.build(), true,
+ configurationBuilder.build(), true, false, Collections.emptyList(),
() -> mSoftApHalCallback.onFailure()));
verify(mIHostapdMock).addAccessPoint(any(), any());
@@ -407,7 +411,7 @@
configurationBuilder.setChannel(apChannel, SoftApConfiguration.BAND_2GHZ);
assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME,
- configurationBuilder.build(), true,
+ configurationBuilder.build(), true, false, Collections.emptyList(),
() -> mSoftApHalCallback.onFailure()));
verify(mIHostapdMock).addAccessPoint(any(), any());
@@ -447,7 +451,7 @@
configurationBuilder.setChannel(apChannel, SoftApConfiguration.BAND_2GHZ);
assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME,
- configurationBuilder.build(), true,
+ configurationBuilder.build(), true, false, Collections.emptyList(),
() -> mSoftApHalCallback.onFailure()));
verify(mIHostapdMock).addAccessPoint(any(), any());
@@ -485,7 +489,7 @@
configurationBuilder.setBand(mBand256G);
assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME,
- configurationBuilder.build(), true,
+ configurationBuilder.build(), true, false, Collections.emptyList(),
() -> mSoftApHalCallback.onFailure()));
verify(mIHostapdMock).addAccessPoint(any(), any());
@@ -522,7 +526,7 @@
configurationBuilder.setBand(mBand256G);
assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME,
- configurationBuilder.build(), true,
+ configurationBuilder.build(), true, false, Collections.emptyList(),
() -> mSoftApHalCallback.onFailure()));
verify(mIHostapdMock).addAccessPoint(any(), any());
@@ -591,7 +595,7 @@
configurationBuilder.setBand(mBand256G);
assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME,
- configurationBuilder.build(), true,
+ configurationBuilder.build(), true, false, Collections.emptyList(),
() -> mSoftApHalCallback.onFailure()));
verify(mIHostapdMockV11).addAccessPoint_1_1(any(), any());
@@ -626,7 +630,7 @@
configurationBuilder.setChannel(6, SoftApConfiguration.BAND_2GHZ);
assertFalse(mHostapdHal.addAccessPoint(IFACE_NAME,
- configurationBuilder.build(), true,
+ configurationBuilder.build(), true, false, Collections.emptyList(),
() -> mSoftApHalCallback.onFailure()));
verify(mIHostapdMock).addAccessPoint(any(), any());
}
@@ -645,7 +649,7 @@
configurationBuilder.setChannel(6, SoftApConfiguration.BAND_2GHZ);
assertFalse(mHostapdHal.addAccessPoint(IFACE_NAME,
- configurationBuilder.build(), true,
+ configurationBuilder.build(), true, false, Collections.emptyList(),
() -> mSoftApHalCallback.onFailure()));
verify(mIHostapdMock).addAccessPoint(any(), any());
}
@@ -704,7 +708,7 @@
configurationBuilder.setBand(SoftApConfiguration.BAND_2GHZ);
assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME,
- configurationBuilder.build(), true,
+ configurationBuilder.build(), true, false, Collections.emptyList(),
() -> mSoftApHalCallback.onFailure()));
verify(mIHostapdMockV11).addAccessPoint_1_1(any(), any());
@@ -1146,7 +1150,7 @@
assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME,
- configurationBuilder.build(), true,
+ configurationBuilder.build(), true, false, Collections.emptyList(),
() -> mSoftApHalCallback.onFailure()));
verify(mIHostapdMockV13).addAccessPoint_1_3(any(), any());
@@ -1193,7 +1197,7 @@
assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME,
- configurationBuilder.build(), true,
+ configurationBuilder.build(), true, false, Collections.emptyList(),
() -> mSoftApHalCallback.onFailure()));
verify(mIHostapdMockV13).addAccessPoint_1_3(any(), any());
@@ -1237,7 +1241,7 @@
configurationBuilder.setBand(mBand256G);
assertFalse(mHostapdHal.addAccessPoint(IFACE_NAME,
- configurationBuilder.build(), true,
+ configurationBuilder.build(), true, false, Collections.emptyList(),
() -> mSoftApHalCallback.onFailure()));
}
@@ -1261,7 +1265,7 @@
configurationBuilder.setBand(mBand256G);
assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME,
- configurationBuilder.build(), true,
+ configurationBuilder.build(), true, false, Collections.emptyList(),
() -> mSoftApHalCallback.onFailure()));
verify(mIHostapdMock).addAccessPoint(any(), any());
@@ -1309,7 +1313,7 @@
when(mIHostapdMockV13.addAccessPoint_1_3(any(), any()))
.thenReturn(mStatusSuccess12);
assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME,
- configurationBuilder.build(), true,
+ configurationBuilder.build(), true, false, Collections.emptyList(),
() -> mSoftApHalCallback.onFailure()));
verify(mIHostapdMockV13).addAccessPoint_1_3(any(), any());
// Register SoftApManager callback
@@ -1317,7 +1321,7 @@
// Add second AP to test that the callbacks are triggered for the correct iface.
assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME_1,
- configurationBuilder.build(), true,
+ configurationBuilder.build(), true, false, Collections.emptyList(),
() -> mSoftApHalCallback1.onFailure()));
mHostapdHal.registerApCallback(IFACE_NAME_1, mSoftApHalCallback1);
@@ -1344,9 +1348,10 @@
mIHostapdCallback13.onConnectedClientsChanged(IFACE_NAME, TEST_AP_INSTANCE,
MacAddress.fromString(TEST_CLIENT_MAC).toByteArray(), true);
verify(mSoftApHalCallback).onConnectedClientsChanged(eq(TEST_AP_INSTANCE),
- eq(MacAddress.fromString(TEST_CLIENT_MAC)), eq(true));
+ eq(MacAddress.fromString(TEST_CLIENT_MAC)), eq(true),
+ eq(DEFAULT_DISCONNECT_REASON));
verify(mSoftApHalCallback1, never()).onConnectedClientsChanged(anyString(), any(),
- anyBoolean());
+ anyBoolean(), anyInt());
}
/**
@@ -1378,7 +1383,7 @@
assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME,
- configurationBuilder.build(), isMetered,
+ configurationBuilder.build(), isMetered, false, Collections.emptyList(),
() -> mSoftApHalCallback.onFailure()));
verify(mIHostapdMockV13).addAccessPoint_1_3(any(), any());
@@ -1426,7 +1431,7 @@
assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME,
- configurationBuilder.build(), isMetered,
+ configurationBuilder.build(), isMetered, false, Collections.emptyList(),
() -> mSoftApHalCallback.onFailure()));
verify(mIHostapdMockV13).addAccessPoint_1_3(any(), any());
@@ -1508,7 +1513,7 @@
assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME,
- configurationBuilder.build(), true,
+ configurationBuilder.build(), true, false, Collections.emptyList(),
() -> mSoftApHalCallback.onFailure()));
verify(mIHostapdMockV13).addAccessPoint_1_3(any(), any());
@@ -1573,7 +1578,7 @@
assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME,
- configurationBuilder.build(), isMetered,
+ configurationBuilder.build(), isMetered, false, Collections.emptyList(),
() -> mSoftApHalCallback.onFailure()));
verify(mIHostapdMockV13).addAccessPoint_1_3(any(), any());
@@ -1627,7 +1632,7 @@
assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME,
- configurationBuilder.build(), isMetered,
+ configurationBuilder.build(), isMetered, false, Collections.emptyList(),
() -> mSoftApHalCallback.onFailure()));
verify(mIHostapdMockV13).addAccessPoint_1_3(any(), any());
diff --git a/service/tests/wifitests/src/com/android/server/wifi/HostapdHalTest.java b/service/tests/wifitests/src/com/android/server/wifi/HostapdHalTest.java
index a8ec7da..37634c5 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/HostapdHalTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/HostapdHalTest.java
@@ -23,6 +23,7 @@
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.anyList;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
@@ -43,6 +44,8 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.util.Collections;
+
/**
* Unit tests for HostapdHal
*/
@@ -181,21 +184,25 @@
/**
* Check that HostapdHal.addAccessPoint() returns the implementation's result
- * and that the implementation receives the expected arguments
+ * and that the implementation receives the expected arguments.
+ *
+ * SuppressWarnings DirectInvocationOnMock for "mSoftApHalCallback.onFailure()"
+ * since it is a lambda callback implementation. Not a really function call.
*/
+ @SuppressWarnings("DirectInvocationOnMock")
@Test
public void testAddAccessPoint() {
initializeWithAidlImp(true);
when(mIHostapdAidlMock.addAccessPoint(anyString(), any(SoftApConfiguration.class),
- anyBoolean(), any(Runnable.class)))
+ anyBoolean(), anyBoolean(), anyList(), any(Runnable.class)))
.thenReturn(true);
boolean isMetered = true;
Builder configurationBuilder = new SoftApConfiguration.Builder();
SoftApConfiguration config = configurationBuilder.build();
assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME, config,
- isMetered, () -> mSoftApHalCallback.onFailure()));
+ isMetered, false, Collections.emptyList(), () -> mSoftApHalCallback.onFailure()));
verify(mIHostapdAidlMock).addAccessPoint(eq(IFACE_NAME), eq(config),
- eq(isMetered), any(Runnable.class));
+ eq(isMetered), eq(false), eq(Collections.emptyList()), any(Runnable.class));
}
/**
diff --git a/service/tests/wifitests/src/com/android/server/wifi/MboOceControllerTest.java b/service/tests/wifitests/src/com/android/server/wifi/MboOceControllerTest.java
index f7a801b..96c6cb1 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/MboOceControllerTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/MboOceControllerTest.java
@@ -34,6 +34,7 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.util.BitSet;
/**
* unit tests for {@link com.android.server.wifi.MboOceController}.
@@ -75,14 +76,14 @@
* Helper function to initialize mboOceController
*/
private PhoneStateListener enableMboOceController(boolean isMboEnabled, boolean isOceEnabled) {
- long featureSet = 0;
+ BitSet featureSet = new BitSet();
PhoneStateListener dataConnectionStateListener = null;
if (isMboEnabled) {
- featureSet |= WifiManager.WIFI_FEATURE_MBO;
+ featureSet.set(WifiManager.WIFI_FEATURE_MBO);
}
if (isOceEnabled) {
- featureSet |= WifiManager.WIFI_FEATURE_OCE;
+ featureSet.set(WifiManager.WIFI_FEATURE_OCE);
}
when(mClientModeManager.getSupportedFeatures()).thenReturn(featureSet);
diff --git a/service/tests/wifitests/src/com/android/server/wifi/SavedNetworkNominatorTest.java b/service/tests/wifitests/src/com/android/server/wifi/SavedNetworkNominatorTest.java
index 850f8a7..9cc7f5b 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/SavedNetworkNominatorTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/SavedNetworkNominatorTest.java
@@ -19,6 +19,7 @@
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
import static com.android.server.wifi.WifiConfigurationTestUtil.SECURITY_NONE;
import static com.android.server.wifi.WifiConfigurationTestUtil.SECURITY_PSK;
+import static com.android.server.wifi.TestUtil.createCapabilityBitset;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.*;
@@ -68,7 +69,8 @@
when(mWifiInjector.getWifiGlobals()).thenReturn(mWifiGlobals);
when(mActiveModeWarden.getPrimaryClientModeManager()).thenReturn(mPrimaryClientModeManager);
when(mPrimaryClientModeManager.getSupportedFeatures()).thenReturn(
- WifiManager.WIFI_FEATURE_WPA3_SAE | WifiManager.WIFI_FEATURE_OWE);
+ createCapabilityBitset(
+ WifiManager.WIFI_FEATURE_WPA3_SAE, WifiManager.WIFI_FEATURE_OWE));
when(mWifiGlobals.isWpa3SaeUpgradeEnabled()).thenReturn(true);
when(mWifiGlobals.isOweUpgradeEnabled()).thenReturn(true);
diff --git a/service/tests/wifitests/src/com/android/server/wifi/ScanResultMatchInfoTest.java b/service/tests/wifitests/src/com/android/server/wifi/ScanResultMatchInfoTest.java
index eb38f5a..77c9351 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/ScanResultMatchInfoTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/ScanResultMatchInfoTest.java
@@ -18,6 +18,8 @@
import static android.net.wifi.WifiManager.WIFI_FEATURE_OWE;
import static android.net.wifi.WifiManager.WIFI_FEATURE_WPA3_SAE;
+import static com.android.server.wifi.TestUtil.createCapabilityBitset;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
@@ -73,7 +75,7 @@
when(mWifiInjector.getActiveModeWarden()).thenReturn(mActiveModeWarden);
when(mActiveModeWarden.getPrimaryClientModeManager()).thenReturn(mClientModeManager);
when(mClientModeManager.getSupportedFeatures()).thenReturn(
- WIFI_FEATURE_OWE | WIFI_FEATURE_WPA3_SAE);
+ createCapabilityBitset(WIFI_FEATURE_OWE, WIFI_FEATURE_WPA3_SAE));
when(mWifiGlobals.isWpa3SaeUpgradeEnabled()).thenReturn(true);
when(mWifiGlobals.isOweUpgradeEnabled()).thenReturn(true);
}
diff --git a/service/tests/wifitests/src/com/android/server/wifi/SoftApManagerTest.java b/service/tests/wifitests/src/com/android/server/wifi/SoftApManagerTest.java
index 5ba7e3a..aa11715 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/SoftApManagerTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/SoftApManagerTest.java
@@ -29,6 +29,7 @@
import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLING;
import static android.net.wifi.WifiManager.WIFI_AP_STATE_FAILED;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
import static com.android.server.wifi.ActiveModeManager.ROLE_SOFTAP_LOCAL_ONLY;
import static com.android.server.wifi.ActiveModeManager.ROLE_SOFTAP_TETHERED;
import static com.android.server.wifi.HalDeviceManager.HDM_CREATE_IFACE_AP_BRIDGE;
@@ -64,6 +65,7 @@
import android.net.MacAddress;
import android.net.TetheringManager;
import android.net.wifi.CoexUnsafeChannel;
+import android.net.wifi.DeauthenticationReasonCode;
import android.net.wifi.OuiKeyedData;
import android.net.wifi.ScanResult;
import android.net.wifi.SoftApCapability;
@@ -92,20 +94,24 @@
import androidx.test.filters.SmallTest;
+import com.android.dx.mockito.inline.extended.StaticMockitoSession;
import com.android.internal.util.StateMachine;
import com.android.internal.util.WakeupMessage;
import com.android.modules.utils.build.SdkLevel;
import com.android.server.wifi.coex.CoexManager;
+import com.android.wifi.flags.Flags;
import com.android.wifi.resources.R;
import com.google.common.collect.ImmutableList;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.mockito.quality.Strictness;
import java.util.ArrayList;
import java.util.Arrays;
@@ -131,6 +137,7 @@
private static final String TEST_SECOND_INSTANCE_NAME = "testif2";
private static final String OTHER_INTERFACE_NAME = "otherif";
private static final String TEST_STA_INTERFACE_NAME = "testif0sta";
+ private static final long TEST_START_TIME_MILLIS = 1234567890;
private static final long TEST_DEFAULT_SHUTDOWN_TIMEOUT_MILLIS = 600_000;
private static final long TEST_DEFAULT_SHUTDOWN_IDLE_INSTANCE_IN_BRIDGED_MODE_TIMEOUT_MILLIS =
300_000;
@@ -159,6 +166,17 @@
private static final int TEST_AP_BANDWIDTH_FROM_IFACE_CALLBACK =
SoftApInfo.CHANNEL_WIDTH_20MHZ_NOHT;
private static final int TEST_AP_BANDWIDTH_IN_SOFTAPINFO = SoftApInfo.CHANNEL_WIDTH_20MHZ_NOHT;
+ private static final int TEST_DISCONNECT_REASON =
+ DeauthenticationReasonCode.REASON_UNKNOWN;
+ private static final WifiClient TEST_DISCONNECTED_CLIENT =
+ new WifiClient(TEST_CLIENT_MAC_ADDRESS, TEST_INTERFACE_NAME,
+ TEST_DISCONNECT_REASON);
+ private static final WifiClient TEST_DISCONNECTED_CLIENT_2_ON_FIRST_IFACE =
+ new WifiClient(TEST_CLIENT_MAC_ADDRESS_2, TEST_FIRST_INSTANCE_NAME,
+ TEST_DISCONNECT_REASON);
+ private static final WifiClient TEST_DISCONNECTED_CLIENT_2_ON_SECOND_IFACE =
+ new WifiClient(TEST_CLIENT_MAC_ADDRESS_2, TEST_SECOND_INSTANCE_NAME,
+ TEST_DISCONNECT_REASON);
private static final int[] EMPTY_CHANNEL_ARRAY = {};
private static final int[] ALLOWED_2G_FREQS = {2462}; //ch# 11
private static final int[] ALLOWED_5G_FREQS = {5745, 5765}; //ch# 149, 153
@@ -218,6 +236,7 @@
@Mock InterfaceConflictManager mInterfaceConflictManager;
@Mock WifiInjector mWifiInjector;
@Mock WifiCountryCode mWifiCountryCode;
+ @Mock Clock mClock;
@Mock LocalLog mLocalLog;
@Mock DeviceWiphyCapabilities mDeviceWiphyCapabilities;
@@ -238,6 +257,7 @@
ArgumentCaptor.forClass(BroadcastReceiver.class);
SoftApManager mSoftApManager;
+ private StaticMockitoSession mStaticMockSession;
/** Old callback event from wificond */
private void mockChannelSwitchEvent(int frequency, int bandwidth) {
@@ -259,9 +279,9 @@
private void mockClientConnectedEvent(MacAddress mac, boolean isConnected,
String apIfaceInstance, boolean updateTheTestMap) {
mSoftApHalCallbackCaptor.getValue().onConnectedClientsChanged(
- apIfaceInstance, mac, isConnected);
+ apIfaceInstance, mac, isConnected, TEST_DISCONNECT_REASON);
if (mac == null || !updateTheTestMap) return;
- WifiClient client = new WifiClient(mac, apIfaceInstance);
+ WifiClient client = new WifiClient(mac, apIfaceInstance, TEST_DISCONNECT_REASON);
List<WifiClient> targetList = mTempConnectedClientListMap.get(apIfaceInstance);
if (isConnected) {
targetList.add(client);
@@ -323,17 +343,24 @@
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
+ mStaticMockSession = mockitoSession()
+ .mockStatic(WifiInjector.class)
+ .mockStatic(Flags.class)
+ .strictness(Strictness.LENIENT)
+ .startMocking();
mLooper = new TestLooper();
+ when(WifiInjector.getInstance()).thenReturn(mWifiInjector);
+ when(mWifiInjector.getContext()).thenReturn(mContext);
when(mWifiNative.isItPossibleToCreateApIface(any())).thenReturn(true);
when(mWifiNative.isItPossibleToCreateBridgedApIface(any())).thenReturn(true);
when(mWifiNative.isApSetMacAddressSupported(any())).thenReturn(true);
when(mWifiNative.setApMacAddress(any(), any())).thenReturn(true);
when(mWifiNative.startSoftAp(eq(TEST_INTERFACE_NAME), any(), anyBoolean(),
- any(WifiNative.SoftApHalCallback.class)))
+ any(WifiNative.SoftApHalCallback.class), anyBoolean()))
.thenReturn(SoftApManager.START_RESULT_SUCCESS);
when(mWifiNative.setupInterfaceForSoftApMode(any(), any(), anyInt(), anyBoolean(),
- any(), anyList()))
+ any(), anyList(), anyBoolean()))
.thenReturn(TEST_INTERFACE_NAME);
when(mFrameworkFacade.getIntegerSetting(
mContext, Settings.Global.SOFT_AP_TIMEOUT_ENABLED, 1)).thenReturn(1);
@@ -408,6 +435,8 @@
when(mWifiNative.forceClientDisconnect(any(), any(), anyInt())).thenReturn(true);
when(mWifiInjector.getWifiHandlerLocalLog()).thenReturn(mLocalLog);
when(mWifiInjector.getWifiCountryCode()).thenReturn(mWifiCountryCode);
+ when(mWifiInjector.getClock()).thenReturn(mClock);
+ when(mClock.getWallClockMillis()).thenReturn(TEST_START_TIME_MILLIS);
when(mWifiNative.getDeviceWiphyCapabilities(any(), anyBoolean())).thenReturn(
mDeviceWiphyCapabilities);
when(mDeviceWiphyCapabilities.isWifiStandardSupported(ScanResult.WIFI_STANDARD_11BE))
@@ -453,6 +482,12 @@
mTempConnectedClientListMap.forEach((key, value) -> value.clear());
}
+ @After
+ public void cleanUp() throws Exception {
+ mStaticMockSession.finishMocking();
+ }
+
+
private SoftApConfiguration createDefaultApConfig() {
Builder defaultConfigBuilder = new SoftApConfiguration.Builder();
defaultConfigBuilder.setSsid(DEFAULT_SSID);
@@ -479,6 +514,7 @@
TEST_WORKSOURCE,
role,
false);
+ verify(mWifiNative).isMLDApSupportMLO();
mLooper.dispatchAll();
return newSoftApManager;
@@ -626,7 +662,8 @@
public void testSetupForSoftApModeNullApInterfaceNameFailureIncrementsMetrics()
throws Exception {
when(mWifiNative.setupInterfaceForSoftApMode(
- any(), any(), anyInt(), anyBoolean(), any(), anyList())).thenReturn(null);
+ any(), any(), anyInt(), anyBoolean(), any(), anyList(), anyBoolean()))
+ .thenReturn(null);
when(mWifiApConfigStore.getApConfiguration()).thenReturn(null);
SoftApModeConfiguration nullApConfig =
new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null,
@@ -664,7 +701,8 @@
public void testStartSoftApNotPossibleToCreateApInterfaceIncrementsMetrics()
throws Exception {
when(mWifiNative.setupInterfaceForSoftApMode(
- any(), any(), anyInt(), anyBoolean(), any(), anyList())).thenReturn(null);
+ any(), any(), anyInt(), anyBoolean(), any(), anyList(), anyBoolean()))
+ .thenReturn(null);
when(mWifiNative.isItPossibleToCreateApIface(any())).thenReturn(false);
Builder configBuilder = new SoftApConfiguration.Builder();
configBuilder.setBand(SoftApConfiguration.BAND_2GHZ);
@@ -706,7 +744,8 @@
public void testSetupForSoftApModeEmptyInterfaceNameFailureIncrementsMetrics()
throws Exception {
when(mWifiNative.setupInterfaceForSoftApMode(
- any(), any(), anyInt(), anyBoolean(), any(), anyList())).thenReturn("");
+ any(), any(), anyInt(), anyBoolean(), any(), anyList(), anyBoolean()))
+ .thenReturn("");
SoftApModeConfiguration nullApConfig =
new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null,
mTestSoftApCapability, TEST_COUNTRY_CODE, TEST_TETHERING_REQUEST);
@@ -995,7 +1034,7 @@
@Test
public void startSoftApApInterfaceFailedToStart() throws Exception {
when(mWifiNative.startSoftAp(eq(TEST_INTERFACE_NAME), any(), anyBoolean(),
- any(WifiNative.SoftApHalCallback.class))).thenReturn(
+ any(WifiNative.SoftApHalCallback.class), anyBoolean())).thenReturn(
SoftApManager.START_RESULT_FAILURE_ADD_AP_HOSTAPD);
SoftApModeConfiguration softApModeConfig =
@@ -1028,9 +1067,13 @@
// reset to clear verified Intents for ap state change updates
reset(mContext);
+ when(mContext.getResourceCache()).thenReturn(mResourceCache);
InOrder order = inOrder(mCallback, mListener, mContext);
+ int sessionDurationSeconds = 3000;
+ when(mClock.getWallClockMillis()).thenReturn(
+ TEST_START_TIME_MILLIS + (sessionDurationSeconds * 1000));
mSoftApManager.stop();
mLooper.dispatchAll();
@@ -1066,6 +1109,10 @@
softApModeConfig.getTargetMode());
order.verify(mListener).onStopped(mSoftApManager);
verify(mCmiMonitor).unregisterListener(mCmiListenerCaptor.getValue());
+ verify(mWifiMetrics).writeSoftApStoppedEvent(eq(SoftApManager.STOP_EVENT_STOPPED),
+ any(), anyInt(), anyBoolean(), anyBoolean(), anyBoolean(), anyInt(), anyBoolean(),
+ eq(sessionDurationSeconds), anyInt(), anyInt(), anyInt(), anyBoolean(), anyInt(),
+ anyInt(), any());
}
/**
@@ -1591,6 +1638,7 @@
*/
@Test
public void testDoesNotTriggerCallbackForSameClients() throws Exception {
+ when(Flags.softapDisconnectReason()).thenReturn(true);
SoftApModeConfiguration apConfig =
new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null,
mTestSoftApCapability, TEST_COUNTRY_CODE, TEST_TETHERING_REQUEST);
@@ -1618,6 +1666,9 @@
// Should just trigger 1 time callback, the first time will be happen when softap enable
verify(mCallback, times(3)).onConnectedClientsOrInfoChanged(mTestSoftApInfoMap,
mTestWifiClientsMap, false);
+ // onClientsDisconnected should trigger 1 time from the update to zero client.
+ verify(mCallback).onClientsDisconnected(eq(mTestSoftApInfo),
+ eq(ImmutableList.of(TEST_DISCONNECTED_CLIENT)));
verify(mWifiMetrics)
.addSoftApNumAssociatedStationsChangedEvent(0, 0,
@@ -2452,10 +2503,18 @@
startSoftApAndVerifyEnabled(softApConfig, null, true);
}
- /** Starts soft AP and verifies that it is enabled successfully. */
+ /** Starts soft AP with non MLO and verifies that it is enabled successfully. */
protected void startSoftApAndVerifyEnabled(
SoftApModeConfiguration softApConfig,
SoftApConfiguration expectedConfig, boolean userApprovalNeeded) throws Exception {
+ startSoftApAndVerifyEnabled(softApConfig, expectedConfig, userApprovalNeeded, false);
+ }
+
+ /** Starts soft AP and verifies that it is enabled successfully. */
+ protected void startSoftApAndVerifyEnabled(
+ SoftApModeConfiguration softApConfig,
+ SoftApConfiguration expectedConfig, boolean userApprovalNeeded, boolean isUsingMlo)
+ throws Exception {
// The config which base on mDefaultApConfig and generate ramdonized mac address
SoftApConfiguration randomizedBssidConfig = null;
InOrder order = inOrder(mCallback, mWifiNative);
@@ -2518,7 +2577,7 @@
verify(mWifiNative, never()).setupInterfaceForSoftApMode(
mWifiNativeInterfaceCallbackCaptor.capture(), eq(TEST_WORKSOURCE),
eq(expectedConfig.getBand()), eq(expectedConfig.getBands().length > 1),
- eq(mSoftApManager), anyList());
+ eq(mSoftApManager), anyList(), anyBoolean());
// Simulate user approval
ArgumentCaptor<StateMachine> stateMachineCaptor =
ArgumentCaptor.forClass(StateMachine.class);
@@ -2544,7 +2603,8 @@
softApConfig.getCountryCode(),
softApConfig.getCapability().getCountryCode())) {
// Don't start SoftAP before driver country code change.
- verify(mWifiNative, never()).startSoftAp(any(), any(), anyBoolean(), any());
+ verify(mWifiNative, never()).startSoftAp(any(), any(), anyBoolean(), any(),
+ anyBoolean());
ArgumentCaptor<WifiCountryCode.ChangeListener> changeListenerCaptor =
ArgumentCaptor.forClass(WifiCountryCode.ChangeListener.class);
@@ -2554,7 +2614,8 @@
mLooper.dispatchAll();
// Ignore country code changes that don't match what we set.
- verify(mWifiNative, never()).startSoftAp(any(), any(), anyBoolean(), any());
+ verify(mWifiNative, never()).startSoftAp(any(), any(), anyBoolean(), any(),
+ anyBoolean());
// Now notify the correct country code.
changeListenerCaptor.getValue()
@@ -2566,7 +2627,8 @@
} else if (TextUtils.isEmpty(softApConfig.getCountryCode())
&& mIsDriverSupportedRegChangedEvent && expectedConfig.getBands().length == 1) {
// Don't start SoftAP before driver country code change.
- verify(mWifiNative, never()).startSoftAp(any(), any(), anyBoolean(), any());
+ verify(mWifiNative, never()).startSoftAp(any(), any(), anyBoolean(), any(),
+ anyBoolean());
ArgumentCaptor<WifiCountryCode.ChangeListener> changeListenerCaptor =
ArgumentCaptor.forClass(WifiCountryCode.ChangeListener.class);
@@ -2581,14 +2643,14 @@
order.verify(mWifiNative).setupInterfaceForSoftApMode(
mWifiNativeInterfaceCallbackCaptor.capture(), eq(TEST_WORKSOURCE),
eq(expectedConfig.getBand()), eq(expectedConfig.getBands().length > 1),
- eq(mSoftApManager), anyList());
+ eq(mSoftApManager), anyList(), anyBoolean());
order.verify(mCallback).onStateChanged(eq(new SoftApState(
WifiManager.WIFI_AP_STATE_ENABLING, 0,
softApConfig.getTetheringRequest(), TEST_INTERFACE_NAME)));
order.verify(mWifiNative).startSoftAp(eq(TEST_INTERFACE_NAME),
configCaptor.capture(),
eq(softApConfig.getTargetMode() == WifiManager.IFACE_IP_MODE_TETHERED),
- mSoftApHalCallbackCaptor.capture());
+ mSoftApHalCallbackCaptor.capture(), eq(isUsingMlo));
assertThat(configCaptor.getValue()).isEqualTo(expectedConfigWithFrameworkACS != null
? expectedConfigWithFrameworkACS : expectedConfig);
mWifiNativeInterfaceCallbackCaptor.getValue().onUp(TEST_INTERFACE_NAME);
@@ -3152,7 +3214,7 @@
mSoftApManager = createSoftApManager(dualBandConfig, ROLE_SOFTAP_TETHERED);
verify(mWifiNative).setupInterfaceForSoftApMode(
any(), any(), eq(SoftApConfiguration.BAND_2GHZ), eq(true), eq(mSoftApManager),
- anyList());
+ anyList(), anyBoolean());
}
@Test
@@ -3212,6 +3274,7 @@
@Test
public void schedulesTimeoutTimerWorkFlowInBridgedMode() throws Exception {
assumeTrue(SdkLevel.isAtLeastS());
+ when(Flags.softapDisconnectReason()).thenReturn(true);
SoftApModeConfiguration apConfig = new SoftApModeConfiguration(
WifiManager.IFACE_IP_MODE_TETHERED, generateBridgedModeSoftApConfig(null),
mTestSoftApCapability, TEST_COUNTRY_CODE, TEST_TETHERING_REQUEST);
@@ -3259,6 +3322,8 @@
mLooper.dispatchAll();
verify(mCallback).onConnectedClientsOrInfoChanged(
mTestSoftApInfoMap, mTestWifiClientsMap, true);
+ verify(mCallback).onClientsDisconnected(eq(mTestSoftApInfoOnFirstInstance),
+ eq(ImmutableList.of(TEST_DISCONNECTED_CLIENT_2_ON_FIRST_IFACE)));
reset(mCallback);
mockClientConnectedEvent(TEST_CLIENT_MAC_ADDRESS_2, true, TEST_SECOND_INSTANCE_NAME, true);
mLooper.dispatchAll();
@@ -3274,6 +3339,8 @@
mLooper.dispatchAll();
verify(mCallback).onConnectedClientsOrInfoChanged(
mTestSoftApInfoMap, mTestWifiClientsMap, true);
+ verify(mCallback).onClientsDisconnected(eq(mTestSoftApInfoOnSecondInstance),
+ eq(ImmutableList.of(TEST_DISCONNECTED_CLIENT_2_ON_SECOND_IFACE)));
// Verify idle timer in bridged mode is scheduled again
verify(mAlarmManager.getAlarmManager(), times(2)).setExact(anyInt(), anyLong(),
eq(mSoftApManager.SOFT_AP_SEND_MESSAGE_TIMEOUT_TAG + TEST_SECOND_INSTANCE_NAME),
@@ -3823,13 +3890,14 @@
ArgumentCaptor<WifiCountryCode.ChangeListener> changeListenerCaptor =
ArgumentCaptor.forClass(WifiCountryCode.ChangeListener.class);
verify(mWifiCountryCode).registerListener(changeListenerCaptor.capture());
- verify(mWifiNative, never()).startSoftAp(any(), any(), anyBoolean(), any());
+ verify(mWifiNative, never()).startSoftAp(any(), any(), anyBoolean(), any(),
+ anyBoolean());
// Trigger the timeout
mLooper.moveTimeForward(10_000);
mLooper.dispatchAll();
- verify(mWifiNative).startSoftAp(any(), any(), anyBoolean(), any());
+ verify(mWifiNative).startSoftAp(any(), any(), anyBoolean(), any(), anyBoolean());
verify(mWifiCountryCode).unregisterListener(changeListenerCaptor.getValue());
}
@@ -4210,6 +4278,95 @@
startSoftApAndVerifyEnabled(apConfig, configBuilder.build(), false);
}
+ /**
+ * Tests that 11BE configuration is disabled if there is existing 11Be SoftApManager.
+ */
+ @Test
+ public void testStartSoftApWith11BEConfigurationWhenExistingOther11BeSoftApManager()
+ throws Exception {
+ assumeTrue(SdkLevel.isAtLeastT());
+ when(Flags.mloSap()).thenReturn(true);
+ when(mResourceCache.getBoolean(R.bool.config_wifiSoftapIeee80211beSupported))
+ .thenReturn(true);
+ when(mResourceCache.getBoolean(R.bool.config_wifiSoftApSingleLinkMloInBridgedModeSupported))
+ .thenReturn(false);
+ when(mDeviceWiphyCapabilities.isWifiStandardSupported(ScanResult.WIFI_STANDARD_11BE))
+ .thenReturn(true);
+ when(mActiveModeWarden.getCurrentMLDAp()).thenReturn(1);
+ mDeviceWiphyCapabilitiesSupports11Be = true;
+ Builder configBuilder = new SoftApConfiguration.Builder();
+ configBuilder.setBand(SoftApConfiguration.BAND_5GHZ);
+ configBuilder.setSsid(TEST_SSID);
+ configBuilder.setIeee80211beEnabled(true);
+ configBuilder.setPassphrase("somepassword",
+ SoftApConfiguration.SECURITY_TYPE_WPA3_SAE);
+ SoftApModeConfiguration apConfig = new SoftApModeConfiguration(
+ WifiManager.IFACE_IP_MODE_TETHERED, configBuilder.build(),
+ mTestSoftApCapability, TEST_COUNTRY_CODE, TEST_TETHERING_REQUEST);
+ SoftApConfiguration expectedConfig = configBuilder.setIeee80211beEnabled(false).build();
+ startSoftApAndVerifyEnabled(apConfig, expectedConfig, false);
+ }
+
+ /**
+ * Tests that 11BE configuration is NOT disabled even if there is existing 11Be SoftApManager
+ * when device support single link MLO in bridged mode. (2 MLDs are allowed case)
+ */
+ @Test
+ public void testStartSoftApWith11BEWhenExistingOther11BeSoftApButDualSingleLinkMLoSupported()
+ throws Exception {
+ assumeTrue(SdkLevel.isAtLeastT());
+ when(Flags.mloSap()).thenReturn(true);
+ when(mResourceCache.getBoolean(R.bool.config_wifiSoftapIeee80211beSupported))
+ .thenReturn(true);
+ when(mResourceCache.getBoolean(R.bool.config_wifiSoftApSingleLinkMloInBridgedModeSupported))
+ .thenReturn(true);
+ when(mDeviceWiphyCapabilities.isWifiStandardSupported(ScanResult.WIFI_STANDARD_11BE))
+ .thenReturn(true);
+ when(mActiveModeWarden.getCurrentMLDAp()).thenReturn(1);
+ mDeviceWiphyCapabilitiesSupports11Be = true;
+ Builder configBuilder = new SoftApConfiguration.Builder();
+ configBuilder.setBand(SoftApConfiguration.BAND_5GHZ);
+ configBuilder.setSsid(TEST_SSID);
+ configBuilder.setIeee80211beEnabled(true);
+ configBuilder.setPassphrase("somepassword",
+ SoftApConfiguration.SECURITY_TYPE_WPA3_SAE);
+ SoftApModeConfiguration apConfig = new SoftApModeConfiguration(
+ WifiManager.IFACE_IP_MODE_TETHERED, configBuilder.build(),
+ mTestSoftApCapability, TEST_COUNTRY_CODE, TEST_TETHERING_REQUEST);
+ startSoftApAndVerifyEnabled(apConfig, configBuilder.build(), false);
+ }
+
+ /**
+ * Tests that 11BE configuration is NOT disabled when only 1 MLD supported. (MLO case)
+ */
+ @Test
+ public void testStartSoftApWith11BEForMLOSupportedCase()
+ throws Exception {
+ assumeTrue(SdkLevel.isAtLeastT());
+ when(Flags.mloSap()).thenReturn(true);
+ when(mResourceCache.getBoolean(R.bool.config_wifiSoftapIeee80211beSupported))
+ .thenReturn(true);
+ when(mResourceCache.getInteger(R.integer.config_wifiSoftApMaxNumberMLDSupported))
+ .thenReturn(1);
+ when(mWifiNative.isMLDApSupportMLO()).thenReturn(true);
+ when(mActiveModeWarden.getCurrentMLDAp()).thenReturn(0);
+ mDeviceWiphyCapabilitiesSupports11Be = true;
+ Builder configBuilder = new SoftApConfiguration.Builder();
+ configBuilder.setBands(new int[] {SoftApConfiguration.BAND_2GHZ,
+ SoftApConfiguration.BAND_5GHZ});
+ configBuilder.setSsid(TEST_SSID);
+ configBuilder.setIeee80211beEnabled(true);
+ configBuilder.setPassphrase("somepassword",
+ SoftApConfiguration.SECURITY_TYPE_WPA3_SAE);
+ SoftApModeConfiguration apConfig = new SoftApModeConfiguration(
+ WifiManager.IFACE_IP_MODE_TETHERED, configBuilder.build(),
+ mTestSoftApCapability, TEST_COUNTRY_CODE, TEST_TETHERING_REQUEST);
+ when(Flags.mloSap()).thenReturn(true);
+ startSoftApAndVerifyEnabled(apConfig, configBuilder.build(), false, true);
+
+ assertTrue(mSoftApManager.isUsingMlo());
+ }
+
@Test
public void testStartSoftApAutoUpgradeTo2g5gDbs() throws Exception {
assumeTrue(SdkLevel.isAtLeastS());
diff --git a/service/tests/wifitests/src/com/android/server/wifi/SoftApStoreDataTest.java b/service/tests/wifitests/src/com/android/server/wifi/SoftApStoreDataTest.java
index b87832c..ebb0c67 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/SoftApStoreDataTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/SoftApStoreDataTest.java
@@ -18,6 +18,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;
@@ -38,6 +39,7 @@
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiMigration;
import android.net.wifi.WifiSsid;
+import android.net.wifi.util.Environment;
import android.util.SparseIntArray;
import android.util.Xml;
@@ -50,6 +52,7 @@
import com.android.server.wifi.util.InformationElementUtil;
import com.android.server.wifi.util.SettingsMigrationDataHolder;
import com.android.server.wifi.util.WifiConfigStoreEncryptionUtil;
+import com.android.server.wifi.util.XmlUtil;
import com.android.wifi.flags.Flags;
import org.junit.After;
@@ -113,6 +116,8 @@
private static final boolean TEST_80211AX_ENABLED = false;
private static final boolean TEST_80211BE_ENABLED = false;
private static final boolean TEST_USER_CONFIGURATION = false;
+ // Use non default value true as test data
+ private static final boolean TEST_CLIENT_ISOLATION = true;
private static final String TEST_TWO_VENDOR_ELEMENTS_HEX = "DD04AABBCCDDDD0401020304";
private static final int TEST_MAX_CHANNEL_WIDTH = SoftApInfo.CHANNEL_WIDTH_40MHZ;
private MockitoSession mSession;
@@ -279,7 +284,7 @@
+ "<boolean name=\"UserConfiguration\" value=\""
+ TEST_USER_CONFIGURATION + "\" />\n";
- private static final String TEST_CONFIG_STRING_WITH_ALL_CONFIG_LAST_VERSION =
+ private static final String TEST_CONFIG_STRING_WITH_ALL_CONFIG_IN_T =
TEST_CONFIG_STRING_WITH_ALL_CONFIG_IN_S
+ "<long name=\"BridgedModeOpportunisticShutdownTimeoutMillis\" value=\""
+ TEST_BRIDTED_MODE_SHUTDOWN_TIMEOUT_MILLIS + "\" />\n"
@@ -290,6 +295,11 @@
+ "<boolean name=\"80211beEnabled\" value=\""
+ TEST_80211BE_ENABLED + "\" />\n";
+ private static final String TEST_CONFIG_STRING_WITH_ALL_CONFIG_IN_B =
+ TEST_CONFIG_STRING_WITH_ALL_CONFIG_IN_T
+ + "<boolean name=\"ClientIsolation\" value=\""
+ + TEST_CLIENT_ISOLATION + "\" />\n";
+
@Mock private Context mContext;
@Mock SoftApStoreData.DataSource mDataSource;
@Mock private WifiMigration.SettingsMigrationData mOemMigrationData;
@@ -327,6 +337,8 @@
}
}).when(mWifiConfigStoreEncryptionUtil).decrypt(any());
when(Flags.softapConfigStoreMaxChannelWidth()).thenReturn(false);
+ // Default flag is enabled.
+ when(Flags.apIsolate()).thenReturn(true);
}
/**
@@ -434,10 +446,15 @@
TEST_TWO_VENDOR_ELEMENTS_HEX)));
softApConfigBuilder.setIeee80211beEnabled(TEST_80211BE_ENABLED);
}
+ if (Environment.isSdkAtLeastB()) {
+ softApConfigBuilder.setClientIsolationEnabled(TEST_CLIENT_ISOLATION);
+ }
when(mDataSource.toSerialize()).thenReturn(softApConfigBuilder.build());
byte[] actualData = serializeData();
- if (SdkLevel.isAtLeastT()) {
- assertEquals(TEST_CONFIG_STRING_WITH_ALL_CONFIG_LAST_VERSION, new String(actualData));
+ if (Environment.isSdkAtLeastB()) {
+ assertEquals(TEST_CONFIG_STRING_WITH_ALL_CONFIG_IN_B, new String(actualData));
+ } else if (SdkLevel.isAtLeastT()) {
+ assertEquals(TEST_CONFIG_STRING_WITH_ALL_CONFIG_IN_T, new String(actualData));
} else if (SdkLevel.isAtLeastS()) {
assertEquals(TEST_CONFIG_STRING_WITH_ALL_CONFIG_IN_S, new String(actualData));
} else {
@@ -453,7 +470,6 @@
*/
@Test
public void serializeSoftApNonUtf8() throws Exception {
-
SoftApConfiguration.Builder softApConfigBuilder = new SoftApConfiguration.Builder();
softApConfigBuilder.setSsid(TEST_SSID);
softApConfigBuilder.setBssid(MacAddress.fromString(TEST_BSSID));
@@ -485,10 +501,15 @@
TEST_TWO_VENDOR_ELEMENTS_HEX)));
softApConfigBuilder.setIeee80211beEnabled(TEST_80211BE_ENABLED);
}
+ if (Environment.isSdkAtLeastB()) {
+ softApConfigBuilder.setClientIsolationEnabled(TEST_CLIENT_ISOLATION);
+ }
when(mDataSource.toSerialize()).thenReturn(softApConfigBuilder.build());
byte[] actualData = serializeData();
- if (SdkLevel.isAtLeastT()) {
- assertEquals(TEST_CONFIG_STRING_WITH_ALL_CONFIG_LAST_VERSION, new String(actualData));
+ if (Environment.isSdkAtLeastB()) {
+ assertEquals(TEST_CONFIG_STRING_WITH_ALL_CONFIG_IN_B, new String(actualData));
+ } else if (SdkLevel.isAtLeastT()) {
+ assertEquals(TEST_CONFIG_STRING_WITH_ALL_CONFIG_IN_T, new String(actualData));
} else if (SdkLevel.isAtLeastS()) {
assertEquals(TEST_CONFIG_STRING_WITH_ALL_CONFIG_IN_S, new String(actualData));
} else {
@@ -504,8 +525,10 @@
*/
@Test
public void deserializeSoftAp() throws Exception {
- if (SdkLevel.isAtLeastT()) {
- deserializeData(TEST_CONFIG_STRING_WITH_ALL_CONFIG_LAST_VERSION.getBytes());
+ if (Environment.isSdkAtLeastB()) {
+ deserializeData(TEST_CONFIG_STRING_WITH_ALL_CONFIG_IN_B.getBytes());
+ } else if (SdkLevel.isAtLeastT()) {
+ deserializeData(TEST_CONFIG_STRING_WITH_ALL_CONFIG_IN_T.getBytes());
} else if (SdkLevel.isAtLeastS()) {
deserializeData(TEST_CONFIG_STRING_WITH_ALL_CONFIG_IN_S.getBytes());
} else {
@@ -546,6 +569,9 @@
if (SdkLevel.isAtLeastT()) {
assertEquals(softApConfig.isIeee80211beEnabled(), TEST_80211BE_ENABLED);
}
+ if (Environment.isSdkAtLeastB()) {
+ assertEquals(TEST_CLIENT_ISOLATION, softApConfig.isClientIsolationEnabled());
+ }
}
/**
@@ -929,4 +955,31 @@
assertEquals(softApConfig.getSecurityType(),
softApConfigDeserialized.getSecurityType());
}
+
+ /**
+ * Verify that the store data is serialized/deserialized when clientIsolation is disabled.
+ *
+ * @throws Exception when test fails it throws exception
+ */
+ @Test
+ public void testSerializeDeserializeSoftApWhenClientIsolationFalgDisabled() throws Exception {
+ assumeTrue(Environment.isSdkAtLeastB());
+ when(Flags.apIsolate()).thenReturn(false);
+ SoftApConfiguration testSoftApConfig =
+ new SoftApConfiguration.Builder().setSsid(TEST_SSID)
+ .setClientIsolationEnabled(TEST_CLIENT_ISOLATION).build();
+ when(mDataSource.toSerialize()).thenReturn(testSoftApConfig);
+ byte[] actualData = serializeData();
+ String serializeDataString = new String(actualData);
+ assertFalse(serializeDataString.contains(
+ XmlUtil.SoftApConfigurationXmlUtil.XML_TAG_CLIENT_ISOLATION));
+ deserializeData(TEST_CONFIG_STRING_WITH_ALL_CONFIG_IN_B.getBytes());
+ ArgumentCaptor<SoftApConfiguration> softapConfigCaptor =
+ ArgumentCaptor.forClass(SoftApConfiguration.class);
+ verify(mDataSource).fromDeserialized(softapConfigCaptor.capture());
+ SoftApConfiguration softApConfig = softapConfigCaptor.getValue();
+ assertNotNull(softApConfig);
+ // Keep default value false which does NOT equals test data (true)
+ assertNotEquals(TEST_CLIENT_ISOLATION, softApConfig.isClientIsolationEnabled());
+ }
}
diff --git a/service/tests/wifitests/src/com/android/server/wifi/SupplicantStaIfaceHalAidlImplTest.java b/service/tests/wifitests/src/com/android/server/wifi/SupplicantStaIfaceHalAidlImplTest.java
index 57e0c12..9df178a 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/SupplicantStaIfaceHalAidlImplTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/SupplicantStaIfaceHalAidlImplTest.java
@@ -28,10 +28,8 @@
import static android.net.wifi.WifiManager.WIFI_FEATURE_WAPI;
import static android.net.wifi.WifiManager.WIFI_FEATURE_WPA3_SAE;
import static android.net.wifi.WifiManager.WIFI_FEATURE_WPA3_SUITE_B;
-import static android.os.Build.VERSION.SDK_INT;
-import static com.android.server.wifi.util.GeneralUtil.getCapabilityIndex;
-import static com.android.server.wifi.util.GeneralUtil.longToBitset;
+import static com.android.server.wifi.TestUtil.createCapabilityBitset;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
@@ -67,7 +65,6 @@
import android.annotation.Nullable;
import android.app.test.MockAnswerUtil;
import android.content.Context;
-import android.hardware.wifi.V1_0.WifiChannelWidthInMhz;
import android.hardware.wifi.supplicant.AnqpData;
import android.hardware.wifi.supplicant.AssociationRejectionData;
import android.hardware.wifi.supplicant.BssTmData;
@@ -104,6 +101,7 @@
import android.hardware.wifi.supplicant.StaIfaceStatusCode;
import android.hardware.wifi.supplicant.SupplicantStateChangeData;
import android.hardware.wifi.supplicant.SupplicantStatusCode;
+import android.hardware.wifi.supplicant.WifiChannelWidthInMhz;
import android.hardware.wifi.supplicant.WifiTechnology;
import android.hardware.wifi.supplicant.WpaDriverCapabilitiesMask;
import android.hardware.wifi.supplicant.WpsConfigError;
@@ -124,6 +122,7 @@
import android.net.wifi.WifiMigration;
import android.net.wifi.WifiSsid;
import android.net.wifi.flags.Flags;
+import android.net.wifi.util.Environment;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
@@ -1260,43 +1259,6 @@
}
/**
- * Tests the handling of association rejection for WPA3-Personal networks
- */
- @Test
- public void testWpa3AuthRejectionEverConnected() throws Exception {
- executeAndValidateInitializationSequence();
- assertNotNull(mISupplicantStaIfaceCallback);
-
- WifiConfiguration config = executeAndValidateConnectSequenceWithKeyMgmt(
- SUPPLICANT_NETWORK_ID, false, TRANSLATED_SUPPLICANT_SSID.toString(),
- WifiConfiguration.SECURITY_TYPE_SAE, null, true);
- mISupplicantStaIfaceCallback.onStateChanged(
- StaIfaceCallbackState.ASSOCIATING,
- NativeUtil.macAddressToByteArray(BSSID),
- SUPPLICANT_NETWORK_ID,
- NativeUtil.byteArrayFromArrayList(NativeUtil.decodeSsid(SUPPLICANT_SSID)), false);
- int statusCode = StaIfaceStatusCode.UNSPECIFIED_FAILURE;
- AssociationRejectionData rejectionData = createAssocRejectData(SUPPLICANT_SSID, BSSID,
- statusCode, false);
- mISupplicantStaIfaceCallback.onAssociationRejected(rejectionData);
- verify(mWifiMonitor, never()).broadcastAuthenticationFailureEvent(eq(WLAN0_IFACE_NAME),
- anyInt(), anyInt(), any(), any());
- ArgumentCaptor<AssocRejectEventInfo> assocRejectEventInfoCaptor =
- ArgumentCaptor.forClass(AssocRejectEventInfo.class);
- verify(mWifiMonitor).broadcastAssociationRejectionEvent(
- eq(WLAN0_IFACE_NAME), assocRejectEventInfoCaptor.capture());
- AssocRejectEventInfo assocRejectEventInfo = assocRejectEventInfoCaptor.getValue();
- assertNotNull(assocRejectEventInfo);
- assertEquals(TRANSLATED_SUPPLICANT_SSID.toString(), assocRejectEventInfo.ssid);
- assertEquals(BSSID, assocRejectEventInfo.bssid);
- assertEquals(SupplicantStaIfaceCallbackAidlImpl.halToFrameworkStatusCode(
- statusCode), assocRejectEventInfo.statusCode);
- assertFalse(assocRejectEventInfo.timedOut);
- assertNull(assocRejectEventInfo.oceRssiBasedAssocRejectInfo);
- assertNull(assocRejectEventInfo.mboAssocDisallowedInfo);
- }
-
- /**
* Tests that association rejection due to timeout doesn't broadcast authentication failure
* with reason code ERROR_AUTH_FAILURE_WRONG_PSWD.
* Driver/Supplicant sets the timedOut field when there is no ACK or response frame for
@@ -1845,7 +1807,7 @@
*/
@Test
public void testGetKeyMgmtCapabilitiesWpa3Sae() throws Exception {
- checkKeyMgmtCapabilities(KeyMgmtMask.SAE, longToBitset(WIFI_FEATURE_WPA3_SAE));
+ checkKeyMgmtCapabilities(KeyMgmtMask.SAE, createCapabilityBitset(WIFI_FEATURE_WPA3_SAE));
}
/**
@@ -1853,7 +1815,8 @@
*/
@Test
public void testGetKeyMgmtCapabilitiesWpa3SuiteB() throws Exception {
- checkKeyMgmtCapabilities(KeyMgmtMask.SUITE_B_192, longToBitset(WIFI_FEATURE_WPA3_SUITE_B));
+ checkKeyMgmtCapabilities(KeyMgmtMask.SUITE_B_192,
+ createCapabilityBitset(WIFI_FEATURE_WPA3_SUITE_B));
}
/**
@@ -1861,7 +1824,7 @@
*/
@Test
public void testGetKeyMgmtCapabilitiesOwe() throws Exception {
- checkKeyMgmtCapabilities(KeyMgmtMask.OWE, longToBitset(WIFI_FEATURE_OWE));
+ checkKeyMgmtCapabilities(KeyMgmtMask.OWE, createCapabilityBitset(WIFI_FEATURE_OWE));
}
/**
@@ -1870,7 +1833,7 @@
@Test
public void testGetKeyMgmtCapabilitiesOweAndSae() throws Exception {
checkKeyMgmtCapabilities(KeyMgmtMask.OWE | KeyMgmtMask.SAE,
- longToBitset(WIFI_FEATURE_OWE | WIFI_FEATURE_WPA3_SAE));
+ createCapabilityBitset(WIFI_FEATURE_OWE, WIFI_FEATURE_WPA3_SAE));
}
/**
@@ -1879,7 +1842,7 @@
@Test
public void testGetKeyMgmtCapabilitiesDpp() throws Exception {
checkKeyMgmtCapabilities(KeyMgmtMask.DPP,
- longToBitset(WIFI_FEATURE_DPP | WIFI_FEATURE_DPP_ENROLLEE_RESPONDER));
+ createCapabilityBitset(WIFI_FEATURE_DPP, WIFI_FEATURE_DPP_ENROLLEE_RESPONDER));
}
/**
@@ -1887,7 +1850,7 @@
*/
@Test
public void testGetKeyMgmtCapabilitiesWapi() throws Exception {
- checkKeyMgmtCapabilities(KeyMgmtMask.WAPI_PSK, longToBitset(WIFI_FEATURE_WAPI));
+ checkKeyMgmtCapabilities(KeyMgmtMask.WAPI_PSK, createCapabilityBitset(WIFI_FEATURE_WAPI));
}
/**
@@ -1895,7 +1858,8 @@
*/
@Test
public void testGetKeyMgmtCapabilitiesFilsSha256() throws Exception {
- checkKeyMgmtCapabilities(KeyMgmtMask.FILS_SHA256, longToBitset(WIFI_FEATURE_FILS_SHA256));
+ checkKeyMgmtCapabilities(KeyMgmtMask.FILS_SHA256,
+ createCapabilityBitset(WIFI_FEATURE_FILS_SHA256));
}
/**
@@ -1903,7 +1867,8 @@
*/
@Test
public void testGetKeyMgmtCapabilitiesFilsSha384() throws Exception {
- checkKeyMgmtCapabilities(KeyMgmtMask.FILS_SHA384, longToBitset(WIFI_FEATURE_FILS_SHA384));
+ checkKeyMgmtCapabilities(KeyMgmtMask.FILS_SHA384,
+ createCapabilityBitset(WIFI_FEATURE_FILS_SHA384));
}
/**
@@ -2167,7 +2132,7 @@
executeAndValidateInitializationSequence();
doReturn(WpaDriverCapabilitiesMask.MBO).when(mISupplicantStaIfaceMock)
.getWpaDriverCapabilities();
- assertTrue(longToBitset(WIFI_FEATURE_MBO)
+ assertTrue(createCapabilityBitset(WIFI_FEATURE_MBO)
.equals(mDut.getWpaDriverFeatureSet(WLAN0_IFACE_NAME)));
}
@@ -2179,7 +2144,7 @@
executeAndValidateInitializationSequence();
doReturn(WpaDriverCapabilitiesMask.MBO | WpaDriverCapabilitiesMask.OCE)
.when(mISupplicantStaIfaceMock).getWpaDriverCapabilities();
- assertTrue(longToBitset(WIFI_FEATURE_MBO | WIFI_FEATURE_OCE)
+ assertTrue(createCapabilityBitset(WIFI_FEATURE_MBO, WIFI_FEATURE_OCE)
.equals(mDut.getWpaDriverFeatureSet(WLAN0_IFACE_NAME)));
}
@@ -2191,11 +2156,26 @@
executeAndValidateInitializationSequence();
doReturn(WpaDriverCapabilitiesMask.TRUST_ON_FIRST_USE)
.when(mISupplicantStaIfaceMock).getWpaDriverCapabilities();
- assertTrue(longToBitset(WIFI_FEATURE_TRUST_ON_FIRST_USE)
+ assertTrue(createCapabilityBitset(WIFI_FEATURE_TRUST_ON_FIRST_USE)
.equals(mDut.getWpaDriverFeatureSet(WLAN0_IFACE_NAME)));
}
/**
+ * Test RSN Overriding feature capability.
+ */
+ @Test
+ public void testIsRsnOverridingSupported() throws Exception {
+ executeAndValidateInitializationSequence();
+ doReturn(WpaDriverCapabilitiesMask.RSN_OVERRIDING)
+ .when(mISupplicantStaIfaceMock).getWpaDriverCapabilities();
+ if (mDut.isServiceVersionAtLeast(4)) {
+ assertTrue(mDut.isRsnOverridingSupported(WLAN0_IFACE_NAME));
+ } else {
+ assertFalse(mDut.isRsnOverridingSupported(WLAN0_IFACE_NAME));
+ }
+ }
+
+ /**
* Test the handling of BSS transition request callback.
*/
@Test
@@ -2855,8 +2835,8 @@
* i.e. the latest HIDL version before the conversion to AIDL.
*/
private BitSet addDefaultKeyMgmtCap(BitSet capabilities) {
- capabilities.set(getCapabilityIndex(WIFI_FEATURE_PASSPOINT_TERMS_AND_CONDITIONS));
- capabilities.set(getCapabilityIndex(WIFI_FEATURE_DECORATED_IDENTITY));
+ capabilities.set(WIFI_FEATURE_PASSPOINT_TERMS_AND_CONDITIONS);
+ capabilities.set(WIFI_FEATURE_DECORATED_IDENTITY);
return capabilities;
}
@@ -3471,9 +3451,13 @@
*/
@Test
public void testLegacyKeystoreMigration() throws Exception {
- assumeTrue(SDK_INT >= 36);
- assertFalse(mDut.mHasMigratedLegacyKeystoreAliases);
+ assumeTrue(Environment.isSdkAtLeastB());
executeAndValidateInitializationSequence();
+ assertFalse(mDut.mHasMigratedLegacyKeystoreAliases);
+
+ // Migration is complete when the consumer receives a success code
+ mDut.mKeystoreMigrationStatusConsumer.accept(
+ WifiMigration.KEYSTORE_MIGRATION_SUCCESS_MIGRATION_COMPLETE);
assertTrue(mDut.mHasMigratedLegacyKeystoreAliases);
}
}
diff --git a/service/tests/wifitests/src/com/android/server/wifi/SupplicantStaIfaceHalHidlImplTest.java b/service/tests/wifitests/src/com/android/server/wifi/SupplicantStaIfaceHalHidlImplTest.java
index 4ba62fc..0bde06b 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/SupplicantStaIfaceHalHidlImplTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/SupplicantStaIfaceHalHidlImplTest.java
@@ -26,8 +26,7 @@
import static android.net.wifi.WifiManager.WIFI_FEATURE_WPA3_SAE;
import static android.net.wifi.WifiManager.WIFI_FEATURE_WPA3_SUITE_B;
-import static com.android.server.wifi.util.GeneralUtil.getCapabilityIndex;
-import static com.android.server.wifi.util.GeneralUtil.longToBitset;
+import static com.android.server.wifi.TestUtil.createCapabilityBitset;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
@@ -1471,42 +1470,6 @@
}
/**
- * Tests the handling of association rejection for WPA3-Personal networks
- */
- @Test
- public void testWpa3AuthRejectionEverConnected() throws Exception {
- executeAndValidateInitializationSequence();
- assertNotNull(mISupplicantStaIfaceCallback);
-
- WifiConfiguration config = executeAndValidateConnectSequenceWithKeyMgmt(
- SUPPLICANT_NETWORK_ID, false, TRANSLATED_SUPPLICANT_SSID.toString(),
- WifiConfiguration.SECURITY_TYPE_SAE, null, true);
- mISupplicantStaIfaceCallback.onStateChanged(
- ISupplicantStaIfaceCallback.State.ASSOCIATING,
- NativeUtil.macAddressToByteArray(BSSID),
- SUPPLICANT_NETWORK_ID,
- NativeUtil.decodeSsid(SUPPLICANT_SSID));
- int statusCode = ISupplicantStaIfaceCallback.StatusCode.UNSPECIFIED_FAILURE;
- mISupplicantStaIfaceCallback.onAssociationRejected(
- NativeUtil.macAddressToByteArray(BSSID), statusCode, false);
- verify(mWifiMonitor, never()).broadcastAuthenticationFailureEvent(eq(WLAN0_IFACE_NAME),
- anyInt(), anyInt(), any(), any());
- ArgumentCaptor<AssocRejectEventInfo> assocRejectEventInfoCaptor =
- ArgumentCaptor.forClass(AssocRejectEventInfo.class);
- verify(mWifiMonitor).broadcastAssociationRejectionEvent(
- eq(WLAN0_IFACE_NAME), assocRejectEventInfoCaptor.capture());
- AssocRejectEventInfo assocRejectEventInfo =
- (AssocRejectEventInfo) assocRejectEventInfoCaptor.getValue();
- assertNotNull(assocRejectEventInfo);
- assertEquals(TRANSLATED_SUPPLICANT_SSID.toString(), assocRejectEventInfo.ssid);
- assertEquals(BSSID, assocRejectEventInfo.bssid);
- assertEquals(statusCode, assocRejectEventInfo.statusCode);
- assertFalse(assocRejectEventInfo.timedOut);
- assertNull(assocRejectEventInfo.oceRssiBasedAssocRejectInfo);
- assertNull(assocRejectEventInfo.mboAssocDisallowedInfo);
- }
-
- /**
* Tests that association rejection due to timeout doesn't broadcast authentication failure
* with reason code ERROR_AUTH_FAILURE_WRONG_PSWD.
* Driver/Supplicant sets the timedOut field when there is no ACK or response frame for
@@ -2218,7 +2181,7 @@
android.hardware.wifi.supplicant.V1_2.ISupplicantStaIface
.getKeyMgmtCapabilitiesCallback.class));
- assertTrue(longToBitset(WIFI_FEATURE_WPA3_SAE)
+ assertTrue(createCapabilityBitset(WIFI_FEATURE_WPA3_SAE)
.equals(mDut.getAdvancedCapabilities(WLAN0_IFACE_NAME)));
}
@@ -2237,7 +2200,7 @@
android.hardware.wifi.supplicant.V1_2.ISupplicantStaIface
.getKeyMgmtCapabilitiesCallback.class));
- assertTrue(longToBitset(WIFI_FEATURE_WPA3_SUITE_B)
+ assertTrue(createCapabilityBitset(WIFI_FEATURE_WPA3_SUITE_B)
.equals(mDut.getAdvancedCapabilities(WLAN0_IFACE_NAME)));
}
@@ -2256,7 +2219,7 @@
android.hardware.wifi.supplicant.V1_2.ISupplicantStaIface
.getKeyMgmtCapabilitiesCallback.class));
- assertTrue(longToBitset(WIFI_FEATURE_OWE)
+ assertTrue(createCapabilityBitset(WIFI_FEATURE_OWE)
.equals(mDut.getAdvancedCapabilities(WLAN0_IFACE_NAME)));
}
@@ -2276,7 +2239,7 @@
android.hardware.wifi.supplicant.V1_2.ISupplicantStaIface
.getKeyMgmtCapabilitiesCallback.class));
- assertTrue(longToBitset(WIFI_FEATURE_OWE | WIFI_FEATURE_WPA3_SAE)
+ assertTrue(createCapabilityBitset(WIFI_FEATURE_OWE, WIFI_FEATURE_WPA3_SAE)
.equals(mDut.getAdvancedCapabilities(WLAN0_IFACE_NAME)));
}
@@ -2295,7 +2258,7 @@
android.hardware.wifi.supplicant.V1_2.ISupplicantStaIface
.getKeyMgmtCapabilitiesCallback.class));
- assertTrue(longToBitset(WIFI_FEATURE_DPP)
+ assertTrue(createCapabilityBitset(WIFI_FEATURE_DPP)
.equals(mDut.getAdvancedCapabilities(WLAN0_IFACE_NAME)));
}
@@ -2314,7 +2277,7 @@
.getKeyMgmtCapabilities_1_3Callback.class));
assertTrue(mDut.getAdvancedCapabilities(WLAN0_IFACE_NAME)
- .get(getCapabilityIndex(WIFI_FEATURE_DPP_ENROLLEE_RESPONDER)));
+ .get(WIFI_FEATURE_DPP_ENROLLEE_RESPONDER));
}
/**
@@ -2333,7 +2296,7 @@
.getKeyMgmtCapabilities_1_3Callback.class));
assertFalse(mDut.getAdvancedCapabilities(WLAN0_IFACE_NAME)
- .get(getCapabilityIndex(WIFI_FEATURE_DPP_ENROLLEE_RESPONDER)));
+ .get(WIFI_FEATURE_DPP_ENROLLEE_RESPONDER));
}
/**
@@ -2351,7 +2314,7 @@
android.hardware.wifi.supplicant.V1_3.ISupplicantStaIface
.getKeyMgmtCapabilities_1_3Callback.class));
- assertTrue(longToBitset(WIFI_FEATURE_WAPI)
+ assertTrue(createCapabilityBitset(WIFI_FEATURE_WAPI)
.equals(mDut.getAdvancedCapabilities(WLAN0_IFACE_NAME)));
}
@@ -2370,7 +2333,7 @@
android.hardware.wifi.supplicant.V1_3.ISupplicantStaIface
.getKeyMgmtCapabilities_1_3Callback.class));
- assertTrue(longToBitset(WIFI_FEATURE_FILS_SHA256)
+ assertTrue(createCapabilityBitset(WIFI_FEATURE_FILS_SHA256)
.equals(mDut.getAdvancedCapabilities(WLAN0_IFACE_NAME)));
}
@@ -2389,7 +2352,7 @@
android.hardware.wifi.supplicant.V1_3.ISupplicantStaIface
.getKeyMgmtCapabilities_1_3Callback.class));
- assertTrue(longToBitset(WIFI_FEATURE_FILS_SHA384)
+ assertTrue(createCapabilityBitset(WIFI_FEATURE_FILS_SHA384)
.equals(mDut.getAdvancedCapabilities(WLAN0_IFACE_NAME)));
}
@@ -3547,7 +3510,7 @@
android.hardware.wifi.supplicant.V1_3.ISupplicantStaIface
.getWpaDriverCapabilitiesCallback.class));
- assertTrue(longToBitset(WIFI_FEATURE_MBO)
+ assertTrue(createCapabilityBitset(WIFI_FEATURE_MBO)
.equals(mDut.getWpaDriverFeatureSet(WLAN0_IFACE_NAME)));
}
@@ -3568,7 +3531,7 @@
android.hardware.wifi.supplicant.V1_3.ISupplicantStaIface
.getWpaDriverCapabilitiesCallback.class));
- assertTrue(longToBitset(WIFI_FEATURE_MBO | WIFI_FEATURE_OCE)
+ assertTrue(createCapabilityBitset(WIFI_FEATURE_MBO, WIFI_FEATURE_OCE)
.equals(mDut.getWpaDriverFeatureSet(WLAN0_IFACE_NAME)));
}
@@ -3589,7 +3552,7 @@
android.hardware.wifi.supplicant.V1_4.ISupplicantStaIface
.getWpaDriverCapabilities_1_4Callback.class));
- assertTrue(longToBitset(WIFI_FEATURE_MBO | WIFI_FEATURE_OCE)
+ assertTrue(createCapabilityBitset(WIFI_FEATURE_MBO, WIFI_FEATURE_OCE)
.equals(mDut.getWpaDriverFeatureSet(WLAN0_IFACE_NAME)));
}
diff --git a/service/tests/wifitests/src/com/android/server/wifi/SupplicantStaIfaceHalTest.java b/service/tests/wifitests/src/com/android/server/wifi/SupplicantStaIfaceHalTest.java
index 84de1f8..e93932b 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/SupplicantStaIfaceHalTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/SupplicantStaIfaceHalTest.java
@@ -16,7 +16,9 @@
package com.android.server.wifi;
-import static com.android.server.wifi.util.GeneralUtil.longToBitset;
+import static android.net.wifi.WifiManager.WIFI_FEATURE_OWE;
+
+import static com.android.server.wifi.TestUtil.createCapabilityBitset;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -928,7 +930,7 @@
@Test
public void testGetAdvancedCapabilities() {
initializeWithAidlImpl(true);
- BitSet capabilities = longToBitset(0X1234);
+ BitSet capabilities = createCapabilityBitset(WIFI_FEATURE_OWE); // arbitrary feature
when(mStaIfaceHalAidlMock.getAdvancedCapabilities(anyString())).thenReturn(capabilities);
assertTrue(capabilities.equals(mDut.getAdvancedCapabilities(IFACE_NAME)));
verify(mStaIfaceHalAidlMock).getAdvancedCapabilities(eq(IFACE_NAME));
@@ -940,7 +942,7 @@
@Test
public void testGetWpaDriverFeatureSet() {
initializeWithAidlImpl(true);
- BitSet capabilities = longToBitset(0X1234);
+ BitSet capabilities = createCapabilityBitset(WIFI_FEATURE_OWE); // arbitrary feature
when(mStaIfaceHalAidlMock.getWpaDriverFeatureSet(anyString())).thenReturn(capabilities);
assertTrue(capabilities.equals(mDut.getWpaDriverFeatureSet(IFACE_NAME)));
verify(mStaIfaceHalAidlMock).getWpaDriverFeatureSet(eq(IFACE_NAME));
diff --git a/service/tests/wifitests/src/com/android/server/wifi/SupplicantStaNetworkHalAidlImplTest.java b/service/tests/wifitests/src/com/android/server/wifi/SupplicantStaNetworkHalAidlImplTest.java
index 9b08be9..4d399f1 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/SupplicantStaNetworkHalAidlImplTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/SupplicantStaNetworkHalAidlImplTest.java
@@ -15,8 +15,7 @@
*/
package com.android.server.wifi;
-import static com.android.server.wifi.util.GeneralUtil.getCapabilityIndex;
-import static com.android.server.wifi.util.GeneralUtil.longToBitset;
+import static com.android.server.wifi.TestUtil.createCapabilityBitset;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
@@ -125,7 +124,7 @@
when(mWifiGlobals.isWpa3SaeUpgradeOffloadEnabled()).thenReturn(true);
when(mWifiGlobals.isWpaPersonalDeprecated()).thenReturn(false);
- mAdvanceKeyMgmtFeatures.set(getCapabilityIndex(WifiManager.WIFI_FEATURE_WPA3_SUITE_B));
+ mAdvanceKeyMgmtFeatures.set(WifiManager.WIFI_FEATURE_WPA3_SUITE_B);
mSupplicantNetwork = new SupplicantStaNetworkHalAidlImpl(1,
mISupplicantStaNetworkMock, IFACE_NAME, mContext, mWifiMonitor,
mWifiGlobals, mAdvanceKeyMgmtFeatures, mWpaDriverFeatures);
@@ -1350,7 +1349,7 @@
public void testEapMinimumTlsVersionWifiConfigurationSaveLoadWithAidlV2TlsV13Supported()
throws Exception {
// Re-init mock to AIDL v2 with TLS v1.3 support.
- mWpaDriverFeatures = longToBitset(WifiManager.WIFI_FEATURE_TLS_V1_3);
+ mWpaDriverFeatures = createCapabilityBitset(WifiManager.WIFI_FEATURE_TLS_V1_3);
mSupplicantNetwork = new SupplicantStaNetworkHalAidlImpl(2,
mISupplicantStaNetworkMock, IFACE_NAME, mContext, mWifiMonitor,
mWifiGlobals, mAdvanceKeyMgmtFeatures, mWpaDriverFeatures);
diff --git a/service/tests/wifitests/src/com/android/server/wifi/SupplicantStaNetworkHalHidlImplTest.java b/service/tests/wifitests/src/com/android/server/wifi/SupplicantStaNetworkHalHidlImplTest.java
index b34402e..d1e32eb 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/SupplicantStaNetworkHalHidlImplTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/SupplicantStaNetworkHalHidlImplTest.java
@@ -15,7 +15,7 @@
*/
package com.android.server.wifi;
-import static com.android.server.wifi.util.GeneralUtil.longToBitset;
+import static com.android.server.wifi.TestUtil.createCapabilityBitset;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
@@ -192,7 +192,7 @@
when(mWifiGlobals.isWpa3SaeUpgradeOffloadEnabled()).thenReturn(true);
when(mWifiGlobals.isWpaPersonalDeprecated()).thenReturn(false);
- mAdvanceKeyMgmtFeatures = longToBitset(WifiManager.WIFI_FEATURE_WPA3_SUITE_B);
+ mAdvanceKeyMgmtFeatures = createCapabilityBitset(WifiManager.WIFI_FEATURE_WPA3_SUITE_B);
createSupplicantStaNetwork(SupplicantStaNetworkVersion.V1_0);
}
diff --git a/service/tests/wifitests/src/com/android/server/wifi/TestUtil.java b/service/tests/wifitests/src/com/android/server/wifi/TestUtil.java
index 2640209..c12e064 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/TestUtil.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/TestUtil.java
@@ -26,6 +26,7 @@
import android.os.PowerManager;
import java.util.ArrayList;
+import java.util.BitSet;
/**
* Utils for wifi tests.
@@ -106,4 +107,45 @@
Intent intent = new Intent(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
broadcastReceiver.onReceive(context, intent);
}
+
+ /**
+ * Create a new capability BitSet containing the provided capabilities.
+ *
+ * @param capabilities One or more WifiManager.WIFI_FEATURE_* capabilities
+ */
+ public static BitSet createCapabilityBitset(int... capabilities) {
+ BitSet capabilityBitset = new BitSet();
+ for (int capability : capabilities) {
+ capabilityBitset.set(capability);
+ }
+ return capabilityBitset;
+ }
+
+ /**
+ * Add additional capabilities to the provided BitSet.
+ *
+ * @param bitset BitSet that the capabilities should be added to
+ * @param capabilities One or more WifiManager.WIFI_FEATURE_* capabilities
+ */
+ public static BitSet addCapabilitiesToBitset(BitSet bitset, int... capabilities) {
+ // Clone to avoid modifying the input BitSet
+ BitSet clonedBitset = (BitSet) bitset.clone();
+ for (int capability : capabilities) {
+ clonedBitset.set(capability);
+ }
+ return clonedBitset;
+ }
+
+ /**
+ * Combine several BitSets using an OR operation.
+ *
+ * @param bitsets BitSets that should be combined
+ */
+ public static BitSet combineBitsets(BitSet... bitsets) {
+ BitSet combinedBitset = new BitSet();
+ for (BitSet bitset : bitsets) {
+ combinedBitset.or(bitset);
+ }
+ return combinedBitset;
+ }
}
diff --git a/service/tests/wifitests/src/com/android/server/wifi/WakeupControllerTest.java b/service/tests/wifitests/src/com/android/server/wifi/WakeupControllerTest.java
index 10ae4d9..8674ed3 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/WakeupControllerTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/WakeupControllerTest.java
@@ -17,6 +17,7 @@
package com.android.server.wifi;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
+import static com.android.server.wifi.TestUtil.createCapabilityBitset;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
@@ -128,7 +129,8 @@
when(mWifiInjector.getActiveModeWarden()).thenReturn(mActiveModeWarden);
when(mActiveModeWarden.getPrimaryClientModeManager()).thenReturn(mPrimaryClientModeManager);
when(mPrimaryClientModeManager.getSupportedFeatures()).thenReturn(
- WifiManager.WIFI_FEATURE_WPA3_SAE | WifiManager.WIFI_FEATURE_OWE);
+ createCapabilityBitset(
+ WifiManager.WIFI_FEATURE_WPA3_SAE, WifiManager.WIFI_FEATURE_OWE));
when(mWifiInjector.getWifiNative()).thenReturn(mWifiNative);
when(mWifiNative.getChannelsForBand(WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY))
.thenReturn(new int[]{DFS_CHANNEL_FREQ});
diff --git a/service/tests/wifitests/src/com/android/server/wifi/WakeupEvaluatorTest.java b/service/tests/wifitests/src/com/android/server/wifi/WakeupEvaluatorTest.java
index d256106..064283e 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/WakeupEvaluatorTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/WakeupEvaluatorTest.java
@@ -17,6 +17,7 @@
package com.android.server.wifi;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
+import static com.android.server.wifi.TestUtil.createCapabilityBitset;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -106,7 +107,8 @@
when(mWifiInjector.getActiveModeWarden()).thenReturn(mActiveModeWarden);
when(mActiveModeWarden.getPrimaryClientModeManager()).thenReturn(mPrimaryClientModeManager);
when(mPrimaryClientModeManager.getSupportedFeatures()).thenReturn(
- WifiManager.WIFI_FEATURE_WPA3_SAE | WifiManager.WIFI_FEATURE_OWE);
+ createCapabilityBitset(
+ WifiManager.WIFI_FEATURE_WPA3_SAE, WifiManager.WIFI_FEATURE_OWE));
when(mWifiInjector.getWifiGlobals()).thenReturn(mWifiGlobals);
when(mWifiGlobals.isWpa3SaeUpgradeEnabled()).thenReturn(true);
when(mWifiGlobals.isOweUpgradeEnabled()).thenReturn(true);
diff --git a/service/tests/wifitests/src/com/android/server/wifi/WepNetworkUsageControllerTest.java b/service/tests/wifitests/src/com/android/server/wifi/WepNetworkUsageControllerTest.java
new file mode 100644
index 0000000..f56db3a
--- /dev/null
+++ b/service/tests/wifitests/src/com/android/server/wifi/WepNetworkUsageControllerTest.java
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wifi;
+
+import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_WEP_ALLOWED;
+
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.anyBoolean;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.test.MockAnswerUtil.AnswerWithArguments;
+import android.net.wifi.WifiInfo;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.test.TestLooper;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.wifi.flags.FeatureFlags;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Unit tests for {@link com.android.server.wifi.WifiVoipDetectorTest}.
+ */
+@SmallTest
+public class WepNetworkUsageControllerTest extends WifiBaseTest {
+
+ @Mock HandlerThread mHandlerThread;
+ @Mock WifiDeviceStateChangeManager mWifiDeviceStateChangeManager;
+ @Mock WifiSettingsConfigStore mWifiSettingsConfigStore;
+ @Mock WifiGlobals mWifiGlobals;
+ @Mock ActiveModeWarden mActiveModeWarden;
+ @Mock FeatureFlags mFeatureFlags;
+
+ private WepNetworkUsageController mWepNetworkUsageController;
+ private TestLooper mLooper;
+ final ArgumentCaptor<WifiSettingsConfigStore.OnSettingsChangedListener>
+ mWepAllowedSettingChangedListenerCaptor =
+ ArgumentCaptor.forClass(WifiSettingsConfigStore.OnSettingsChangedListener.class);
+
+ final ArgumentCaptor<WifiDeviceStateChangeManager.StateChangeCallback>
+ mWifiDeviceStateChangeCallbackCaptor =
+ ArgumentCaptor.forClass(WifiDeviceStateChangeManager.StateChangeCallback.class);
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ mLooper = new TestLooper();
+ when(mHandlerThread.getLooper()).thenReturn(mLooper.getLooper());
+ when(mFeatureFlags.wepDisabledInApm()).thenReturn(true);
+ when(mWifiSettingsConfigStore.get(eq(WIFI_WEP_ALLOWED))).thenReturn(true);
+ doAnswer(new AnswerWithArguments() {
+ public void answer(WifiDeviceStateChangeManager.StateChangeCallback callback) {
+ callback.onAdvancedProtectionModeStateChanged(false);
+ }
+ }).when(mWifiDeviceStateChangeManager).registerStateChangeCallback(any());
+
+ doAnswer(new AnswerWithArguments() {
+ public void answer(boolean isWepAllowed) {
+ when(mWifiGlobals.isWepAllowed()).thenReturn(isWepAllowed);
+ }
+ }).when(mWifiGlobals).setWepAllowed(anyBoolean());
+ mWepNetworkUsageController = new WepNetworkUsageController(
+ mHandlerThread, mWifiDeviceStateChangeManager,
+ mWifiSettingsConfigStore, mWifiGlobals, mActiveModeWarden, mFeatureFlags);
+ }
+
+ @Test
+ public void testHandleBootCompleted() {
+ mWepNetworkUsageController.handleBootCompleted();
+ mLooper.dispatchAll();
+ verify(mWifiSettingsConfigStore).get(eq(WIFI_WEP_ALLOWED));
+ verify(mWifiSettingsConfigStore).registerChangeListener(
+ eq(WIFI_WEP_ALLOWED),
+ mWepAllowedSettingChangedListenerCaptor.capture(),
+ any(Handler.class));
+ verify(mWifiDeviceStateChangeManager).registerStateChangeCallback(
+ mWifiDeviceStateChangeCallbackCaptor.capture());
+ mLooper.dispatchAll();
+ // WEP should be allowed since WIFI_WEP_ALLOWED is true
+ // and isAdvancedProtectionEnabled is false. (no mock);
+ verify(mWifiGlobals).setWepAllowed(true);
+ }
+
+ @Test
+ public void testHandleWepAllowedSettingChange() {
+ mWepNetworkUsageController.handleBootCompleted();
+ mLooper.dispatchAll();
+ verify(mWifiSettingsConfigStore).registerChangeListener(
+ eq(WIFI_WEP_ALLOWED),
+ mWepAllowedSettingChangedListenerCaptor.capture(),
+ any(Handler.class));
+ // WIFI_WEP_ALLOWED is true in setUp
+ verify(mWifiGlobals).setWepAllowed(true);
+
+ // WIFI_WEP_ALLOWED Settings changed, B&R use case
+ mWepAllowedSettingChangedListenerCaptor.getValue()
+ .onSettingsChanged(WIFI_WEP_ALLOWED, false);
+ verify(mWifiGlobals).setWepAllowed(false);
+
+ mWepAllowedSettingChangedListenerCaptor.getValue()
+ .onSettingsChanged(WIFI_WEP_ALLOWED, true);
+ verify(mWifiGlobals, times(2)).setWepAllowed(true);
+ }
+
+ @Test
+ public void testAdvancedProtectionModeChanged() {
+ mWepNetworkUsageController.handleBootCompleted();
+ mLooper.dispatchAll();
+ verify(mWifiDeviceStateChangeManager).registerStateChangeCallback(
+ mWifiDeviceStateChangeCallbackCaptor.capture());
+ // WIFI_WEP_ALLOWED is true in setUp
+ verify(mWifiGlobals).setWepAllowed(true);
+ mWifiDeviceStateChangeCallbackCaptor.getValue()
+ .onAdvancedProtectionModeStateChanged(true);
+ verify(mWifiGlobals).setWepAllowed(false);
+
+ mWifiDeviceStateChangeCallbackCaptor.getValue()
+ .onAdvancedProtectionModeStateChanged(false);
+ verify(mWifiGlobals, times(2)).setWepAllowed(true);
+ }
+
+ @Test
+ public void testHandleWepAllowedChangedWhenWepIsConnected() {
+ mWepNetworkUsageController.handleBootCompleted();
+ mLooper.dispatchAll();
+ // WIFI_WEP_ALLOWED is true in setUp
+ verify(mWifiDeviceStateChangeManager).registerStateChangeCallback(
+ mWifiDeviceStateChangeCallbackCaptor.capture());
+ verify(mWifiGlobals).setWepAllowed(true);
+
+ // Mock wep connection to make sure it will disconnect
+ ConcreteClientModeManager cmmWep = mock(ConcreteClientModeManager.class);
+ ConcreteClientModeManager cmmWpa = mock(ConcreteClientModeManager.class);
+ WifiInfo mockWifiInfoWep = mock(WifiInfo.class);
+ WifiInfo mockWifiInfoWpa = mock(WifiInfo.class);
+ List<ClientModeManager> cmms = Arrays.asList(cmmWep, cmmWpa);
+ when(mActiveModeWarden.getClientModeManagers()).thenReturn(cmms);
+ when(mockWifiInfoWep.getCurrentSecurityType()).thenReturn(WifiInfo.SECURITY_TYPE_WEP);
+ when(mockWifiInfoWpa.getCurrentSecurityType()).thenReturn(WifiInfo.SECURITY_TYPE_PSK);
+ when(cmmWep.getConnectionInfo()).thenReturn(mockWifiInfoWep);
+ when(cmmWpa.getConnectionInfo()).thenReturn(mockWifiInfoWpa);
+ // Force setWepAllowed to false by enable APM mode.
+ mWifiDeviceStateChangeCallbackCaptor.getValue()
+ .onAdvancedProtectionModeStateChanged(true);
+ mLooper.dispatchAll();
+ verify(mWifiGlobals).setWepAllowed(false);
+ // Only WEP disconnect
+ verify(cmmWep).disconnect();
+ verify(cmmWpa, never()).disconnect();
+ }
+}
diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiCandidatesTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiCandidatesTest.java
index 1f5345c..40f94fe 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/WifiCandidatesTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/WifiCandidatesTest.java
@@ -19,6 +19,8 @@
import static android.net.wifi.WifiManager.WIFI_FEATURE_OWE;
import static android.net.wifi.WifiManager.WIFI_FEATURE_WPA3_SAE;
+import static com.android.server.wifi.TestUtil.createCapabilityBitset;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
@@ -97,7 +99,7 @@
when(mWifiInjector.getActiveModeWarden()).thenReturn(mActiveModeWarden);
when(mActiveModeWarden.getPrimaryClientModeManager()).thenReturn(mClientModeManager);
when(mClientModeManager.getSupportedFeatures()).thenReturn(
- WIFI_FEATURE_OWE | WIFI_FEATURE_WPA3_SAE);
+ createCapabilityBitset(WIFI_FEATURE_OWE, WIFI_FEATURE_WPA3_SAE));
when(mWifiGlobals.isWpa3SaeUpgradeEnabled()).thenReturn(true);
when(mWifiGlobals.isOweUpgradeEnabled()).thenReturn(true);
diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java
index 6e88ddb..75f044f 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java
@@ -16,9 +16,12 @@
package com.android.server.wifi;
+import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_PSK;
import static android.net.wifi.WifiManager.AddNetworkResult.STATUS_INVALID_CONFIGURATION_ENTERPRISE;
+import static com.android.server.wifi.TestUtil.createCapabilityBitset;
import static com.android.server.wifi.WifiConfigManager.BUFFERED_WRITE_ALARM_TAG;
+import static com.android.server.wifi.WifiConfigurationUtil.validatePassword;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -115,6 +118,7 @@
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.BitSet;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
@@ -364,7 +368,8 @@
when(mWifiInjector.getSsidTranslator()).thenReturn(mSsidTranslator);
when(mActiveModeWarden.getPrimaryClientModeManager()).thenReturn(mPrimaryClientModeManager);
when(mPrimaryClientModeManager.getSupportedFeatures()).thenReturn(
- WifiManager.WIFI_FEATURE_WPA3_SAE | WifiManager.WIFI_FEATURE_OWE);
+ createCapabilityBitset(
+ WifiManager.WIFI_FEATURE_WPA3_SAE, WifiManager.WIFI_FEATURE_OWE));
when(mWifiGlobals.isWpa3SaeUpgradeEnabled()).thenReturn(true);
when(mWifiGlobals.isOweUpgradeEnabled()).thenReturn(true);
when(mWifiGlobals.isWpa3SaeUpgradeOffloadEnabled()).thenReturn(true);
@@ -2030,8 +2035,8 @@
*/
@Test
public void testEnterpriseConfigTofuStateMerge() {
- long featureSet = WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE;
- when(mPrimaryClientModeManager.getSupportedFeatures()).thenReturn(featureSet);
+ when(mPrimaryClientModeManager.getSupportedFeatures()).thenReturn(
+ createCapabilityBitset(WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE));
// If the configuration has never connected, the merged TOFU connection state
// should be set based on the latest external configuration.
@@ -3335,7 +3340,7 @@
for (WifiConfiguration network : mWifiConfigManager.getLinkedNetworksWithoutMasking(
network1.networkId).values()) {
assertTrue(network.getNetworkSelectionStatus().getCandidateSecurityParams()
- .isSecurityType(WifiConfiguration.SECURITY_TYPE_PSK));
+ .isSecurityType(SECURITY_TYPE_PSK));
}
}
@@ -4608,7 +4613,7 @@
assertTrue(mWifiConfigManager.setNetworkCandidateScanResult(network2.networkId,
createScanDetailForNetwork(network2).getScanResult(), 54,
SecurityParams.createSecurityParamsBySecurityType(
- WifiConfiguration.SECURITY_TYPE_PSK)));
+ SECURITY_TYPE_PSK)));
// Retrieve the hidden network list & verify the order of the networks returned.
List<WifiScanner.ScanSettings.HiddenNetwork> hiddenNetworks =
@@ -4676,7 +4681,7 @@
// successfully.
WifiConfiguration network1 = new WifiConfiguration();
network1.SSID = ssid;
- network1.setSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK);
+ network1.setSecurityParams(SECURITY_TYPE_PSK);
network1.preSharedKey = "\"test_blah\"";
NetworkUpdateResult result = addNetworkToWifiConfigManager(network1);
assertTrue(result.getNetworkId() != WifiConfiguration.INVALID_NETWORK_ID);
@@ -6836,7 +6841,13 @@
// Two networks should be merged into one.
assertEquals(1, retrievedNetworks.size());
WifiConfiguration mergedNetwork = retrievedNetworks.get(0);
- assertTrue(mergedNetwork.isSecurityType(baseSecurityType));
+ if (baseConfig.isSecurityType(SECURITY_TYPE_PSK)
+ && !validatePassword(upgradableConfig.preSharedKey, false, false, false)) {
+ // PSK should be removed if we saved an SAE-only passphrase over it.
+ assertFalse(mergedNetwork.isSecurityType(SECURITY_TYPE_PSK));
+ } else {
+ assertTrue(mergedNetwork.isSecurityType(baseSecurityType));
+ }
assertTrue(mergedNetwork.isSecurityType(upgradableSecurityType));
assertEquals(upgradableConfig.getDefaultSecurityParams().isAddedByAutoUpgrade(),
mergedNetwork.getSecurityParams(upgradableSecurityType).isAddedByAutoUpgrade());
@@ -6851,7 +6862,7 @@
public void testAddUpgradableNetworkForPskSae() {
WifiConfiguration baseConfig = new WifiConfiguration();
baseConfig.SSID = "\"upgradableNetwork\"";
- baseConfig.setSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK);
+ baseConfig.setSecurityParams(SECURITY_TYPE_PSK);
baseConfig.preSharedKey = "\"Passw0rd\"";
WifiConfiguration upgradableConfig = new WifiConfiguration();
upgradableConfig.SSID = "\"upgradableNetwork\"";
@@ -6862,6 +6873,24 @@
}
/**
+ * Verifies the addition of an SAE network with an SAE-only passphrase over a PSK/SAE network.
+ * {@link WifiConfigManager#addOrUpdateNetwork(WifiConfiguration, int)}
+ */
+ @Test
+ public void testAddUpgradableNetworkForPskSaeIncompatiblePassphrase() {
+ WifiConfiguration baseConfig = new WifiConfiguration();
+ baseConfig.SSID = "\"upgradableNetwork\"";
+ baseConfig.setSecurityParams(SECURITY_TYPE_PSK);
+ baseConfig.preSharedKey = "\"Passw0rd\"";
+ WifiConfiguration upgradableConfig = new WifiConfiguration();
+ upgradableConfig.SSID = "\"upgradableNetwork\"";
+ upgradableConfig.setSecurityParams(WifiConfiguration.SECURITY_TYPE_SAE);
+ upgradableConfig.preSharedKey = "\"P\"";
+
+ verifyAddUpgradableNetwork(baseConfig, upgradableConfig);
+ }
+
+ /**
* Verifies that updating an existing upgradable network that was added by auto upgrade will
* retain the isAddedByAutoUpgrade() value.
* {@link WifiConfigManager#addOrUpdateNetwork(WifiConfiguration, int)}
@@ -6870,7 +6899,7 @@
public void testUpdateUpgradedNetworkKeepsIsAddedByAutoUpgradeValue() {
WifiConfiguration baseConfig = new WifiConfiguration();
baseConfig.SSID = "\"upgradableNetwork\"";
- baseConfig.setSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK);
+ baseConfig.setSecurityParams(SECURITY_TYPE_PSK);
baseConfig.preSharedKey = "\"Passw0rd\"";
WifiConfiguration upgradedConfig = new WifiConfiguration();
upgradedConfig.SSID = "\"upgradableNetwork\"";
@@ -6890,7 +6919,7 @@
public void testAddUnhiddenUpgradedNetworkOverwritesHiddenSsidValue() {
WifiConfiguration baseConfig = new WifiConfiguration();
baseConfig.SSID = "\"upgradableNetwork\"";
- baseConfig.setSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK);
+ baseConfig.setSecurityParams(SECURITY_TYPE_PSK);
baseConfig.preSharedKey = "\"Passw0rd\"";
baseConfig.hiddenSSID = true;
WifiConfiguration upgradedConfig = new WifiConfiguration();
@@ -6910,7 +6939,7 @@
public void testAddHiddenUpgradedNetworkOverwritesHiddenSsidValue() {
WifiConfiguration baseConfig = new WifiConfiguration();
baseConfig.SSID = "\"upgradableNetwork\"";
- baseConfig.setSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK);
+ baseConfig.setSecurityParams(SECURITY_TYPE_PSK);
baseConfig.preSharedKey = "\"Passw0rd\"";
baseConfig.hiddenSSID = false;
WifiConfiguration upgradedConfig = new WifiConfiguration();
@@ -7011,7 +7040,7 @@
baseConfig.preSharedKey = "\"Passw0rd\"";
WifiConfiguration downgradableConfig = new WifiConfiguration();
downgradableConfig.SSID = "\"downgradableNetwork\"";
- downgradableConfig.setSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK);
+ downgradableConfig.setSecurityParams(SECURITY_TYPE_PSK);
downgradableConfig.preSharedKey = "\"Passw0rd\"";
verifyAddDowngradableNetwork(
@@ -7072,7 +7101,7 @@
baseConfig.hiddenSSID = true;
WifiConfiguration downgradableConfig = new WifiConfiguration();
downgradableConfig.SSID = "\"downgradableConfig\"";
- downgradableConfig.setSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK);
+ downgradableConfig.setSecurityParams(SECURITY_TYPE_PSK);
downgradableConfig.preSharedKey = "\"Passw0rd\"";
downgradableConfig.hiddenSSID = false;
@@ -7092,7 +7121,7 @@
baseConfig.hiddenSSID = false;
WifiConfiguration downgradableConfig = new WifiConfiguration();
downgradableConfig.SSID = "\"downgradableConfig\"";
- downgradableConfig.setSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK);
+ downgradableConfig.setSecurityParams(SECURITY_TYPE_PSK);
downgradableConfig.preSharedKey = "\"Passw0rd\"";
downgradableConfig.hiddenSSID = true;
@@ -7135,7 +7164,7 @@
public void testLoadFromStoreMergeUpgradableConfigurationsPskSae() {
WifiConfiguration baseConfig = new WifiConfiguration();
baseConfig.SSID = "\"upgradableNetwork\"";
- baseConfig.setSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK);
+ baseConfig.setSecurityParams(SECURITY_TYPE_PSK);
baseConfig.preSharedKey = "\"Passw0rd\"";
WifiConfiguration upgradableConfig = new WifiConfiguration();
upgradableConfig.SSID = "\"upgradableNetwork\"";
@@ -7436,7 +7465,7 @@
int networkIdBefore = verifyAddNetworkToWifiConfigManager(testNetwork).getNetworkId();
WifiConfiguration configBefore = mWifiConfigManager.getConfiguredNetwork(networkIdBefore);
assertFalse(configBefore.isSecurityType(WifiConfiguration.SECURITY_TYPE_OPEN));
- assertTrue(configBefore.isSecurityType(WifiConfiguration.SECURITY_TYPE_PSK));
+ assertTrue(configBefore.isSecurityType(SECURITY_TYPE_PSK));
// Change the type from PSK to Open.
testNetwork.networkId = networkIdBefore;
@@ -7446,7 +7475,7 @@
assertEquals(networkIdBefore, networkIdAfter);
WifiConfiguration configAfter = mWifiConfigManager.getConfiguredNetwork(networkIdAfter);
- assertFalse(configAfter.isSecurityType(WifiConfiguration.SECURITY_TYPE_PSK));
+ assertFalse(configAfter.isSecurityType(SECURITY_TYPE_PSK));
assertTrue(configAfter.isSecurityType(WifiConfiguration.SECURITY_TYPE_OPEN));
}
@@ -7976,7 +8005,10 @@
}
private void verifyAddTofuEnterpriseConfig(boolean isTofuSupported) {
- long featureSet = isTofuSupported ? WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE : 0L;
+ BitSet featureSet = new BitSet();
+ if (isTofuSupported) {
+ featureSet.set(WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE);
+ }
when(mPrimaryClientModeManager.getSupportedFeatures()).thenReturn(featureSet);
WifiConfiguration config = prepareTofuEapConfig(
@@ -8098,7 +8130,7 @@
@Test
public void testUpdateCaCertificateSuccess() throws Exception {
when(mPrimaryClientModeManager.getSupportedFeatures()).thenReturn(
- WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE);
+ createCapabilityBitset(WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE));
int eapPeapNetId = verifyAddNetwork(prepareTofuEapConfig(
WifiEnterpriseConfig.Eap.PEAP, WifiEnterpriseConfig.Phase2.NONE), true);
@@ -8113,7 +8145,7 @@
@Test
public void testUpdateCaCertificatePathSuccess() throws Exception {
when(mPrimaryClientModeManager.getSupportedFeatures()).thenReturn(
- WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE);
+ createCapabilityBitset(WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE));
int eapPeapNetId = verifyAddNetwork(prepareTofuEapConfig(
WifiEnterpriseConfig.Eap.PEAP, WifiEnterpriseConfig.Phase2.NONE), true);
@@ -8131,7 +8163,7 @@
@Test
public void testUpdateCaCertificateWithoutAltSubjectNames() throws Exception {
when(mPrimaryClientModeManager.getSupportedFeatures()).thenReturn(
- WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE);
+ createCapabilityBitset(WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE));
verifyAddNetwork(WifiConfigurationTestUtil.createOpenNetwork(), true);
int eapPeapNetId = verifyAddNetwork(prepareTofuEapConfig(
@@ -8157,7 +8189,7 @@
@Test
public void testUpdateCaCertificateWithAltSubjectNames() throws Exception {
when(mPrimaryClientModeManager.getSupportedFeatures()).thenReturn(
- WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE);
+ createCapabilityBitset(WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE));
verifyAddNetwork(WifiConfigurationTestUtil.createOpenNetwork(), true);
int eapPeapNetId = verifyAddNetwork(prepareTofuEapConfig(
@@ -8197,7 +8229,7 @@
@Test
public void testUpdateCaCertificateFaiulreInvalidArgument() throws Exception {
when(mPrimaryClientModeManager.getSupportedFeatures()).thenReturn(
- WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE);
+ createCapabilityBitset(WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE));
int openNetId = verifyAddNetwork(WifiConfigurationTestUtil.createOpenNetwork(), true);
int eapPeapNetId = verifyAddNetwork(prepareTofuEapConfig(
@@ -8233,7 +8265,7 @@
@Test
public void testUpdateCaCertificateSuccessWithSelfSignedCertificate() throws Exception {
when(mPrimaryClientModeManager.getSupportedFeatures()).thenReturn(
- WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE);
+ createCapabilityBitset(WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE));
int eapPeapNetId = verifyAddNetwork(prepareTofuEapConfig(
WifiEnterpriseConfig.Eap.PEAP, WifiEnterpriseConfig.Phase2.NONE), true);
X509Certificate mockCaCert = mock(X509Certificate.class);
@@ -8249,7 +8281,7 @@
@Test
public void testUpdateServerCertificateHashSuccess() throws Exception {
when(mPrimaryClientModeManager.getSupportedFeatures()).thenReturn(
- WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE);
+ createCapabilityBitset(WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE));
int eapPeapNetId = verifyAddNetwork(prepareTofuEapConfig(
WifiEnterpriseConfig.Eap.PEAP, WifiEnterpriseConfig.Phase2.NONE), true);
assertTrue(mWifiConfigManager.updateCaCertificate(eapPeapNetId, FakeKeys.CA_CERT1,
@@ -8264,7 +8296,7 @@
public void testUpdateCaCertificateFailureWithSelfSignedCertificateAndTofuNotEnabled()
throws Exception {
when(mPrimaryClientModeManager.getSupportedFeatures()).thenReturn(
- WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE);
+ createCapabilityBitset(WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE));
int eapPeapNetId = verifyAddNetwork(WifiConfigurationTestUtil.createEapNetwork(
WifiEnterpriseConfig.Eap.PEAP, WifiEnterpriseConfig.Phase2.NONE), true);
X509Certificate mockCaCert = mock(X509Certificate.class);
diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiConfigurationUtilTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiConfigurationUtilTest.java
index 81b182c..f938371 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/WifiConfigurationUtilTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/WifiConfigurationUtilTest.java
@@ -58,6 +58,7 @@
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.BitSet;
import java.util.Collections;
import java.util.List;
@@ -78,7 +79,7 @@
static final List<UserInfo> PROFILES = Arrays.asList(
new UserInfo(CURRENT_USER_ID, "owner", 0),
new UserInfo(CURRENT_USER_MANAGED_PROFILE_USER_ID, "managed profile", 0));
- private static final long SUPPORTED_FEATURES_ALL = Long.MAX_VALUE;
+ private static final BitSet SUPPORTED_FEATURES_ALL = new BitSet();
private final String mGeneratedString256 = "a".repeat(256);
private MockitoSession mSession;
@@ -98,6 +99,7 @@
.startMocking();
when(WifiInjector.getInstance()).thenReturn(mWifiInjector);
when(mWifiInjector.getWifiGlobals()).thenReturn(mWifiGlobals);
+ SUPPORTED_FEATURES_ALL.set(0, 63); // mark all features as supported
}
@After
@@ -1501,7 +1503,8 @@
*/
@Test
public void testValidateSecurityTypeDppAkm() {
- long supportedFeatures = SUPPORTED_FEATURES_ALL & ~WifiManager.WIFI_FEATURE_DPP_AKM;
+ BitSet supportedFeatures = SUPPORTED_FEATURES_ALL;
+ supportedFeatures.set(WifiManager.WIFI_FEATURE_DPP_AKM, false);
WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork();
config.setSecurityParams(WifiInfo.SECURITY_TYPE_DPP);
@@ -1510,7 +1513,7 @@
assertFalse(WifiConfigurationUtil.validate(config, supportedFeatures,
WifiConfigurationUtil.VALIDATE_FOR_UPDATE));
- supportedFeatures = WifiManager.WIFI_FEATURE_DPP_AKM;
+ supportedFeatures.set(WifiManager.WIFI_FEATURE_DPP_AKM, true);
assertTrue(WifiConfigurationUtil.validate(config, supportedFeatures,
WifiConfigurationUtil.VALIDATE_FOR_ADD));
assertTrue(WifiConfigurationUtil.validate(config, supportedFeatures,
diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiConnectivityHelperTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiConnectivityHelperTest.java
index bbe9cf7..f78f6ec 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/WifiConnectivityHelperTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/WifiConnectivityHelperTest.java
@@ -18,6 +18,8 @@
import static android.net.wifi.WifiManager.WIFI_FEATURE_CONTROL_ROAMING;
+import static com.android.server.wifi.TestUtil.createCapabilityBitset;
+
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
@@ -32,6 +34,7 @@
import org.mockito.MockitoAnnotations;
import java.util.ArrayList;
+import java.util.BitSet;
/**
* Unit tests for {@link com.android.server.wifi.WifiConnectivityHelper}.
@@ -68,7 +71,8 @@
when(mActiveModeWarden.getPrimaryClientModeManager()).thenReturn(mClientModeManager);
// Return firmware roaming feature as supported by default.
- when(mClientModeManager.getSupportedFeatures()).thenReturn(WIFI_FEATURE_CONTROL_ROAMING);
+ when(mClientModeManager.getSupportedFeatures())
+ .thenReturn(createCapabilityBitset(WIFI_FEATURE_CONTROL_ROAMING));
WifiNative.RoamingCapabilities roamCap = new WifiNative.RoamingCapabilities();
roamCap.maxBlocklistSize = MAX_BSSID_BLOCKLIST_SIZE;
@@ -119,7 +123,9 @@
*/
@Test
public void returnFirmwareRoamingNotSupported() {
- when(mClientModeManager.getSupportedFeatures()).thenReturn(~WIFI_FEATURE_CONTROL_ROAMING);
+ BitSet supportedFeatures = new BitSet();
+ supportedFeatures.set(WIFI_FEATURE_CONTROL_ROAMING, false);
+ when(mClientModeManager.getSupportedFeatures()).thenReturn(supportedFeatures);
assertTrue(mWifiConnectivityHelper.getFirmwareRoamingInfo());
assertFalse(mWifiConnectivityHelper.isFirmwareRoamingSupported());
}
diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiConnectivityManagerTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiConnectivityManagerTest.java
index d0f3ad6..05464fd 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/WifiConnectivityManagerTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/WifiConnectivityManagerTest.java
@@ -107,7 +107,6 @@
import com.android.server.wifi.scanner.WifiScannerInternal;
import com.android.server.wifi.util.LruConnectionTracker;
import com.android.server.wifi.util.WifiPermissionsUtil;
-import com.android.wifi.flags.FeatureFlags;
import com.android.wifi.resources.R;
import org.junit.After;
@@ -180,8 +179,6 @@
when(mPrimaryClientModeManager.getRole()).thenReturn(ActiveModeManager.ROLE_CLIENT_PRIMARY);
when(mPrimaryClientModeManager.getConnectionInfo()).thenReturn(mWifiInfo);
when(mActiveModeWarden.getPrimaryClientModeManager()).thenReturn(mPrimaryClientModeManager);
- when(mDeviceConfigFacade.getFeatureFlags()).thenReturn(mFeatureFlags);
- when(mFeatureFlags.delayedCarrierNetworkSelection()).thenReturn(true);
when(mWifiCarrierInfoManager.isCarrierNetworkOffloadEnabled(anyInt(), anyBoolean()))
.thenReturn(true);
doAnswer(new AnswerWithArguments() {
@@ -322,7 +319,6 @@
@Mock private WifiNetworkSuggestion mWifiNetworkSuggestion;
@Mock private IPowerManager mPowerManagerService;
@Mock private DeviceConfigFacade mDeviceConfigFacade;
- @Mock private FeatureFlags mFeatureFlags;
@Mock private ActiveModeWarden mActiveModeWarden;
@Mock private ConcreteClientModeManager mPrimaryClientModeManager;
@Mock private ConcreteClientModeManager mSecondaryClientModeManager;
@@ -589,7 +585,7 @@
mCandidateList = new ArrayList<WifiCandidates.Candidate>();
mCandidateList.add(mCandidate1);
when(ns.getCandidatesFromScan(any(), any(), any(), anyBoolean(), anyBoolean(),
- anyBoolean(), any(), anyBoolean())).thenReturn(mCandidateList);
+ anyBoolean(), any(), anyBoolean(), anyInt())).thenReturn(mCandidateList);
when(ns.selectNetwork(any()))
.then(new AnswerWithArguments() {
public WifiConfiguration answer(List<WifiCandidates.Candidate> candidateList) {
@@ -1417,7 +1413,7 @@
mCandidateList.add(mCandidate3);
}
when(mWifiNS.getCandidatesFromScan(any(), any(), any(), anyBoolean(), anyBoolean(),
- anyBoolean(), any(), anyBoolean())).thenReturn(mCandidateList);
+ anyBoolean(), any(), anyBoolean(), anyInt())).thenReturn(mCandidateList);
doAnswer(new AnswerWithArguments() {
public void answer(ExternalClientModeManagerRequestListener listener,
@@ -2342,7 +2338,7 @@
// Issue a partial scan that does not locate any candidates. This should not affect
// the cache populated by the full scan.
when(mWifiNS.getCandidatesFromScan(any(), any(), any(), anyBoolean(), anyBoolean(),
- anyBoolean(), any(), anyBoolean())).thenReturn(null);
+ anyBoolean(), any(), anyBoolean(), anyInt())).thenReturn(null);
when(mScanData.getScannedBandsInternal()).thenReturn(WifiScanner.WIFI_BAND_6_GHZ);
when(mClock.getElapsedSinceBootMillis())
.thenReturn(DELAYED_CARRIER_SELECTION_TIME_MS - 1000L);
@@ -2353,7 +2349,8 @@
// Issue a full scan after the delay period has passed. Since the cache was not modified by
// the partial scan, the delayed carrier candidate should still be in the timestamp cache.
when(mWifiNS.getCandidatesFromScan(any(), any(), any(), anyBoolean(), anyBoolean(),
- anyBoolean(), any(), anyBoolean())).thenReturn(Arrays.asList(mCandidate1));
+ anyBoolean(), any(), anyBoolean(), anyInt())).thenReturn(Arrays.asList(
+ mCandidate1));
when(mScanData.getScannedBandsInternal()).thenReturn(WifiScanner.WIFI_BAND_ALL);
when(mClock.getElapsedSinceBootMillis())
.thenReturn(DELAYED_CARRIER_SELECTION_TIME_MS + 1000L);
@@ -2423,7 +2420,7 @@
candidateList.add(mCandidate1);
candidateList.add(otherCandidate);
when(mWifiNS.getCandidatesFromScan(any(), any(), any(), anyBoolean(), anyBoolean(),
- anyBoolean(), any(), anyBoolean())).thenReturn(candidateList);
+ anyBoolean(), any(), anyBoolean(), anyInt())).thenReturn(candidateList);
// Set WiFi to disconnected state to trigger scan
mWifiConnectivityManager.handleConnectionStateChanged(
@@ -2476,7 +2473,7 @@
candidateList.add(mCandidate1);
candidateList.add(otherCandidate);
when(mWifiNS.getCandidatesFromScan(any(), any(), any(), anyBoolean(), anyBoolean(),
- anyBoolean(), any(), anyBoolean())).thenReturn(candidateList);
+ anyBoolean(), any(), anyBoolean(), anyInt())).thenReturn(candidateList);
// Set WiFi to disconnected state to trigger scan
mWifiConnectivityManager.handleConnectionStateChanged(
@@ -2517,7 +2514,7 @@
candidateList.add(candidate1);
candidateList.add(candidate2);
when(mWifiNS.getCandidatesFromScan(any(), any(), any(), anyBoolean(), anyBoolean(),
- anyBoolean(), any(), anyBoolean())).thenReturn(candidateList);
+ anyBoolean(), any(), anyBoolean(), anyInt())).thenReturn(candidateList);
// Set WiFi to disconnected state to trigger scan
mWifiConnectivityManager.handleConnectionStateChanged(
@@ -2552,7 +2549,7 @@
candidateList.add(mCandidate1);
candidateList.add(otherCandidate);
when(mWifiNS.getCandidatesFromScan(any(), any(), any(), anyBoolean(), anyBoolean(),
- anyBoolean(), any(), anyBoolean())).thenReturn(candidateList);
+ anyBoolean(), any(), anyBoolean(), anyInt())).thenReturn(candidateList);
// Set WiFi to disconnected state to trigger scan
mWifiConnectivityManager.handleConnectionStateChanged(
@@ -2594,7 +2591,7 @@
candidateList.add(mCandidate1);
candidateList.add(otherCandidate);
when(mWifiNS.getCandidatesFromScan(any(), any(), any(), anyBoolean(), anyBoolean(),
- anyBoolean(), any(), anyBoolean())).thenReturn(candidateList);
+ anyBoolean(), any(), anyBoolean(), anyInt())).thenReturn(candidateList);
// Set WiFi to disconnected state to trigger scan
mWifiConnectivityManager.handleConnectionStateChanged(
@@ -2649,7 +2646,7 @@
candidateList.add(mCandidate1);
candidateList.add(otherCandidate);
when(mWifiNS.getCandidatesFromScan(any(), any(), any(), anyBoolean(), anyBoolean(),
- anyBoolean(), any(), anyBoolean())).thenReturn(candidateList);
+ anyBoolean(), any(), anyBoolean(), anyInt())).thenReturn(candidateList);
// Set WiFi to disconnected state to trigger scan
mWifiConnectivityManager.handleConnectionStateChanged(
@@ -2689,7 +2686,7 @@
candidateList.add(mCandidate1);
candidateList.add(otherCandidate);
when(mWifiNS.getCandidatesFromScan(any(), any(), any(), anyBoolean(), anyBoolean(),
- anyBoolean(), any(), anyBoolean())).thenReturn(candidateList);
+ anyBoolean(), any(), anyBoolean(), anyInt())).thenReturn(candidateList);
// Set WiFi to disconnected state to trigger scan
mWifiConnectivityManager.handleConnectionStateChanged(
@@ -2733,7 +2730,7 @@
candidateList.add(mCandidate1);
candidateList.add(otherCandidate);
when(mWifiNS.getCandidatesFromScan(any(), any(), any(), anyBoolean(), anyBoolean(),
- anyBoolean(), any(), anyBoolean())).thenReturn(candidateList);
+ anyBoolean(), any(), anyBoolean(), anyInt())).thenReturn(candidateList);
// Set WiFi to disconnected state to trigger scan
mWifiConnectivityManager.handleConnectionStateChanged(
@@ -2776,7 +2773,7 @@
candidateList.add(mCandidate1);
candidateList.add(otherCandidate);
when(mWifiNS.getCandidatesFromScan(any(), any(), any(), anyBoolean(), anyBoolean(),
- anyBoolean(), any(), anyBoolean())).thenReturn(candidateList);
+ anyBoolean(), any(), anyBoolean(), anyInt())).thenReturn(candidateList);
// Set WiFi to disconnected state to trigger scan
mWifiConnectivityManager.handleConnectionStateChanged(
@@ -2899,7 +2896,7 @@
public void wifiDisconnected_noCandidatesInScan_openNetworkNotifierScanResultsHandled() {
// no connection candidates from scan.
when(mWifiNS.getCandidatesFromScan(any(), any(), any(), anyBoolean(), anyBoolean(),
- anyBoolean(), any(), anyBoolean())).thenReturn(null);
+ anyBoolean(), any(), anyBoolean(), anyInt())).thenReturn(null);
List<ScanDetail> expectedOpenNetworks = new ArrayList<>();
expectedOpenNetworks.add(
@@ -4922,6 +4919,30 @@
assertFalse(mWifiConnectivityManager.getAutoJoinEnabledExternal());
}
+ /**
+ * Verify if setAutojoinDisallowedSecurityTypes method is working correctly.
+ * Also verify getAutojoinDisallowedSecurityTypes method is working correctly.
+ */
+ @Test
+ public void testSetAndGetAutojoinDisallowedSecurityTypes() {
+ // test default value of auto-join restriction secirity types (NONE)
+ assertEquals(0/*restrict none by default*/,
+ mWifiConnectivityManager.getAutojoinDisallowedSecurityTypes());
+
+ // test setting auto-join restriction on secirity types OPEN, WEP, and OWE
+ int restrictOpenWepOwe = (0x1 << WifiInfo.SECURITY_TYPE_OPEN)
+ | (0x1 << WifiInfo.SECURITY_TYPE_WEP)
+ | (0x1 << WifiInfo.SECURITY_TYPE_OWE);
+ mWifiConnectivityManager.setAutojoinDisallowedSecurityTypes(restrictOpenWepOwe);
+ assertEquals(restrictOpenWepOwe, mWifiConnectivityManager
+ .getAutojoinDisallowedSecurityTypes());
+
+ // test resetting auto-join restriction on all secirity types
+ mWifiConnectivityManager.setAutojoinDisallowedSecurityTypes(0/*restrict none*/);
+ assertEquals(0/*restrict none*/, mWifiConnectivityManager
+ .getAutojoinDisallowedSecurityTypes());
+ }
+
/*
* Firmware supports controlled roaming.
* Connect to a network which doesn't have a config specified BSSID.
@@ -5261,7 +5282,7 @@
* on a DBS supported device.
*
* Expected behavior: WifiConnectivityManager invokes
- * {@link WifiNetworkSelector#getCandidatesFromScan(List, Set, List, boolean, boolean, Set, boolean)}
+ * {@link WifiNetworkSelector#getCandidatesFromScan(List, Set, List, boolean, boolean, Set, boolean, int)}
* boolean, boolean, boolean)} after filtering out the scan results obtained via DBS scan.
*/
@Test
@@ -5282,12 +5303,14 @@
List<WifiNetworkSelector.ClientModeManagerState> cmmStates,
boolean untrustedNetworkAllowed,
boolean oemPaidNetworkAllowed, boolean oemPrivateNetworkAllowed,
- Set<Integer> restrictedNetworkAllowedUids, boolean multiInternetNetworkAllowed)
+ Set<Integer> restrictedNetworkAllowedUids, boolean skipSufficiencyCheck,
+ int autojoinRestrictionSecurityTypes)
throws Exception {
capturedScanDetails.addAll(scanDetails);
return null;
}}).when(mWifiNS).getCandidatesFromScan(
- any(), any(), any(), anyBoolean(), eq(true), eq(false), any(), eq(false));
+ any(), any(), any(), anyBoolean(), eq(true), eq(false), any(), eq(false),
+ anyInt());
mWifiConnectivityManager.setTrustedConnectionAllowed(true);
mWifiConnectivityManager.setOemPaidConnectionAllowed(true, new WorkSource());
@@ -5341,12 +5364,13 @@
List<WifiNetworkSelector.ClientModeManagerState> cmmStates,
boolean untrustedNetworkAllowed,
boolean oemPaidNetworkAllowed, boolean oemPrivateNetworkAllowed,
- Set<Integer> restrictedNetworkAllowedUids, boolean multiInternetNetworkAllowed)
+ Set<Integer> restrictedNetworkAllowedUids, boolean skipSufficiencyCheck,
+ int autojoinRestrictionSecurityTypes)
throws Exception {
capturedScanDetails.addAll(scanDetails);
return null;
}}).when(mWifiNS).getCandidatesFromScan(
- any(), any(), any(), anyBoolean(), eq(false), eq(true), any(), eq(false));
+ any(), any(), any(), anyBoolean(), eq(false), eq(true), any(), eq(false), anyInt());
mWifiConnectivityManager.setTrustedConnectionAllowed(true);
mWifiConnectivityManager.setOemPrivateConnectionAllowed(true, new WorkSource());
@@ -6313,7 +6337,7 @@
ROLE_CLIENT_SECONDARY_LONG_LIVED));
verify(mWifiNS).getCandidatesFromScan(any(), any(),
eq(expectedCmmStates), anyBoolean(), anyBoolean(), anyBoolean(), any(),
- eq(false));
+ eq(false), anyInt());
}
@Test
@@ -6345,7 +6369,7 @@
mLooper.dispatchAll();
verify(mWifiNS).getCandidatesFromScan(any(), any(),
any(), anyBoolean(), anyBoolean(), anyBoolean(), any(),
- eq(true));
+ eq(true), anyInt());
}
@Test
@@ -6378,7 +6402,7 @@
mLooper.dispatchAll();
verify(mWifiNS).getCandidatesFromScan(any(), any(),
any(), anyBoolean(), anyBoolean(), anyBoolean(), any(),
- eq(true));
+ eq(true), anyInt());
}
/**
diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiDeviceStateChangeManagerTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiDeviceStateChangeManagerTest.java
index 95eac5f..ec3c259 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/WifiDeviceStateChangeManagerTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/WifiDeviceStateChangeManagerTest.java
@@ -20,9 +20,11 @@
import static android.content.Intent.ACTION_SCREEN_ON;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assume.assumeTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
@@ -31,12 +33,16 @@
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
+import android.net.wifi.util.Environment;
import android.os.Handler;
import android.os.PowerManager;
import android.os.test.TestLooper;
+import android.security.advancedprotection.AdvancedProtectionManager;
import androidx.test.filters.SmallTest;
+import com.android.wifi.flags.FeatureFlags;
+
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
@@ -50,6 +56,9 @@
@Mock Context mContext;
@Mock WifiDeviceStateChangeManager.StateChangeCallback mStateChangeCallback;
@Mock PowerManager mPowerManager;
+ @Mock WifiInjector mWifiInjector;
+ @Mock DeviceConfigFacade mDeviceConfigFacade;
+ @Mock FeatureFlags mFeatureFlags;
@Captor ArgumentCaptor<BroadcastReceiver> mBroadcastReceiverCaptor;
private TestLooper mLooper;
@@ -60,10 +69,13 @@
public void setUp() {
MockitoAnnotations.initMocks(this);
when(mContext.getSystemService(PowerManager.class)).thenReturn(mPowerManager);
+ when(mWifiInjector.getDeviceConfigFacade()).thenReturn(mDeviceConfigFacade);
+ when(mDeviceConfigFacade.getFeatureFlags()).thenReturn(mFeatureFlags);
when(mPowerManager.isInteractive()).thenReturn(true);
mLooper = new TestLooper();
mHandler = new Handler(mLooper.getLooper());
- mWifiDeviceStateChangeManager = new WifiDeviceStateChangeManager(mContext, mHandler);
+ mWifiDeviceStateChangeManager = new WifiDeviceStateChangeManager(mContext, mHandler,
+ mWifiInjector);
}
@@ -72,6 +84,7 @@
mWifiDeviceStateChangeManager.registerStateChangeCallback(mStateChangeCallback);
// Should be no callback event before the boot completed
verify(mStateChangeCallback, never()).onScreenStateChanged(anyBoolean());
+ verify(mStateChangeCallback, never()).onAdvancedProtectionModeStateChanged(anyBoolean());
mWifiDeviceStateChangeManager.handleBootCompleted();
verify(mContext, atLeastOnce())
.registerReceiver(mBroadcastReceiverCaptor.capture(), any());
@@ -95,6 +108,8 @@
mWifiDeviceStateChangeManager.registerStateChangeCallback(mStateChangeCallback);
// Register after boot completed should immediately get a callback
verify(mStateChangeCallback).onScreenStateChanged(true);
+ // No Advance protection manager, should false.
+ verify(mStateChangeCallback).onAdvancedProtectionModeStateChanged(false);
}
private void setScreenState(boolean screenOn) {
@@ -104,4 +119,38 @@
broadcastReceiver.onReceive(mContext, intent);
mLooper.dispatchAll();
}
+
+ @Test
+ public void testCallbackWhenAdvancedProtectionModeSupported() {
+ assumeTrue(Environment.isSdkAtLeastB());
+ assumeTrue(android.security.Flags.aapmApi());
+ ArgumentCaptor<AdvancedProtectionManager.Callback> apmCallbackCaptor =
+ ArgumentCaptor.forClass(AdvancedProtectionManager.Callback.class);
+ when(mFeatureFlags.wepDisabledInApm()).thenReturn(true);
+ AdvancedProtectionManager mockAdvancedProtectionManager =
+ mock(AdvancedProtectionManager.class);
+ when(mContext.getSystemService(AdvancedProtectionManager.class))
+ .thenReturn(mockAdvancedProtectionManager);
+ when(mockAdvancedProtectionManager.isAdvancedProtectionEnabled()).thenReturn(false);
+ mWifiDeviceStateChangeManager.registerStateChangeCallback(mStateChangeCallback);
+ // Should be no callback event before the boot completed
+ verify(mStateChangeCallback, never()).onAdvancedProtectionModeStateChanged(anyBoolean());
+
+ mWifiDeviceStateChangeManager.handleBootCompleted();
+ verify(mockAdvancedProtectionManager).registerAdvancedProtectionCallback(any(),
+ apmCallbackCaptor.capture());
+ verify(mStateChangeCallback).onAdvancedProtectionModeStateChanged(false);
+
+ reset(mStateChangeCallback);
+ apmCallbackCaptor.getValue().onAdvancedProtectionChanged(true);
+ verify(mStateChangeCallback).onAdvancedProtectionModeStateChanged(true);
+
+ apmCallbackCaptor.getValue().onAdvancedProtectionChanged(false);
+ verify(mStateChangeCallback).onAdvancedProtectionModeStateChanged(false);
+
+ reset(mStateChangeCallback);
+ mWifiDeviceStateChangeManager.unregisterStateChangeCallback(mStateChangeCallback);
+ apmCallbackCaptor.getValue().onAdvancedProtectionChanged(true);
+ verify(mStateChangeCallback, never()).onAdvancedProtectionModeStateChanged(anyBoolean());
+ }
}
diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiDiagnosticsTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiDiagnosticsTest.java
index 4457977..1501289 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/WifiDiagnosticsTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/WifiDiagnosticsTest.java
@@ -979,6 +979,58 @@
verify(mBugreportManager, never()).requestBugreport(any(), any(), any());
}
+ @Test
+ public void takeBugReportDoesNothingWhenSSRConfigOverlayDisabled() {
+ when(mBuildProperties.isUserBuild()).thenReturn(false);
+ mResources.setBoolean(R.bool.config_wifi_diagnostics_bugreport_enabled, true);
+ mResources.setBoolean(R.bool.config_wifi_subsystem_restart_bugreport_enabled, false);
+ mWifiDiagnostics = new WifiDiagnostics(
+ mContext, mWifiInjector, mWifiNative, mBuildProperties, mLastMileLogger, mClock,
+ mTestLooper.getLooper());
+
+ mWifiDiagnostics.takeBugReport("", "Subsystem Restart");
+ verify(mPackageManager, never()).queryIntentActivities(any(), anyInt());
+ }
+
+ @Test
+ public void takeBugReportWhenSSRConfigOverlayEnabled() {
+ when(mBuildProperties.isUserBuild()).thenReturn(false);
+ mResources.setBoolean(R.bool.config_wifi_diagnostics_bugreport_enabled, true);
+ mResources.setBoolean(R.bool.config_wifi_subsystem_restart_bugreport_enabled, true);
+ mWifiDiagnostics = new WifiDiagnostics(
+ mContext, mWifiInjector, mWifiNative, mBuildProperties, mLastMileLogger, mClock,
+ mTestLooper.getLooper());
+
+ mWifiDiagnostics.takeBugReport("", "Subsystem Restart");
+ verify(mPackageManager, times(1)).queryIntentActivities(any(), anyInt());
+ }
+
+ @Test
+ public void takeBugReportWhenSSRConfigOverlayDisabledWhenNonSRREvent() {
+ when(mBuildProperties.isUserBuild()).thenReturn(false);
+ mResources.setBoolean(R.bool.config_wifi_diagnostics_bugreport_enabled, true);
+ mResources.setBoolean(R.bool.config_wifi_subsystem_restart_bugreport_enabled, false);
+ mWifiDiagnostics = new WifiDiagnostics(
+ mContext, mWifiInjector, mWifiNative, mBuildProperties, mLastMileLogger, mClock,
+ mTestLooper.getLooper());
+
+ mWifiDiagnostics.takeBugReport("", "Last Resort Watchdog");
+ verify(mPackageManager, times(1)).queryIntentActivities(any(), anyInt());
+ }
+
+ @Test
+ public void takeBugReportWhenSSRConfigOverlayEnabledWhenNonSRREvent() {
+ when(mBuildProperties.isUserBuild()).thenReturn(false);
+ mResources.setBoolean(R.bool.config_wifi_diagnostics_bugreport_enabled, true);
+ mResources.setBoolean(R.bool.config_wifi_subsystem_restart_bugreport_enabled, true);
+ mWifiDiagnostics = new WifiDiagnostics(
+ mContext, mWifiInjector, mWifiNative, mBuildProperties, mLastMileLogger, mClock,
+ mTestLooper.getLooper());
+
+ mWifiDiagnostics.takeBugReport("", "Last Resort Watchdog");
+ verify(mPackageManager, times(1)).queryIntentActivities(any(), anyInt());
+ }
+
/** Verifies that we flush HAL ringbuffer when capture bugreport. */
@Test
public void triggerBugReportFlushRingBufferDataCapture() {
diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiDialogManagerTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiDialogManagerTest.java
index 58ff485..362fc6a 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/WifiDialogManagerTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/WifiDialogManagerTest.java
@@ -70,13 +70,13 @@
*/
@SmallTest
public class WifiDialogManagerTest extends WifiBaseTest {
- private static final int TIMEOUT_MILLIS = 30_000;
private static final String TEST_TITLE = "Title";
private static final String TEST_MESSAGE = "Message";
private static final String TEST_POSITIVE_BUTTON_TEXT = "Yes";
private static final String TEST_NEGATIVE_BUTTON_TEXT = "No";
private static final String TEST_NEUTRAL_BUTTON_TEXT = "Maybe";
private static final String TEST_DEVICE_NAME = "TEST_DEVICE_NAME";
+ private static final int TEST_P2P_TIMEOUT_MS = 15 * 60 * 1000;
private static final String WIFI_DIALOG_APK_PKG_NAME = "WifiDialogApkPkgName";
@Mock WifiContext mWifiContext;
@@ -115,14 +115,12 @@
/**
* Helper method to synchronously call {@link DialogHandle#launchDialog(long)}.
* @param dialogHandle Dialog handle to call on.
- * @param timeoutMs Timeout for {@link DialogHandle#launchDialog(long)}.
* @param wifiThreadRunner Main Wi-Fi thread runner of the WifiDialogManager.
*/
private void launchDialogSynchronous(
@NonNull DialogHandle dialogHandle,
- long timeoutMs,
@NonNull WifiThreadRunner wifiThreadRunner) {
- dialogHandle.launchDialog(timeoutMs);
+ dialogHandle.launchDialog();
ArgumentCaptor<Runnable> launchRunnableArgumentCaptor =
ArgumentCaptor.forClass(Runnable.class);
verify(wifiThreadRunner, atLeastOnce()).post(launchRunnableArgumentCaptor.capture(),
@@ -250,7 +248,7 @@
DialogHandle dialogHandle = mDialogManager.createSimpleDialog(TEST_TITLE, TEST_MESSAGE,
TEST_POSITIVE_BUTTON_TEXT, TEST_NEGATIVE_BUTTON_TEXT, TEST_NEUTRAL_BUTTON_TEXT,
callback, callbackThreadRunner);
- launchDialogSynchronous(dialogHandle, 0, mWifiThreadRunner);
+ launchDialogSynchronous(dialogHandle, mWifiThreadRunner);
Intent intent = verifyStartActivityAsUser(1, mWifiContext);
int dialogId = verifySimpleDialogLaunchIntent(intent, TEST_TITLE, TEST_MESSAGE,
TEST_POSITIVE_BUTTON_TEXT, TEST_NEGATIVE_BUTTON_TEXT, TEST_NEUTRAL_BUTTON_TEXT);
@@ -273,7 +271,7 @@
dialogHandle = mDialogManager.createSimpleDialog(TEST_TITLE, TEST_MESSAGE,
TEST_POSITIVE_BUTTON_TEXT, TEST_NEGATIVE_BUTTON_TEXT, TEST_NEUTRAL_BUTTON_TEXT,
callback, callbackThreadRunner);
- launchDialogSynchronous(dialogHandle, 0, mWifiThreadRunner);
+ launchDialogSynchronous(dialogHandle, mWifiThreadRunner);
intent = verifyStartActivityAsUser(2, mWifiContext);
dialogId = verifySimpleDialogLaunchIntent(intent, TEST_TITLE, TEST_MESSAGE,
TEST_POSITIVE_BUTTON_TEXT, TEST_NEGATIVE_BUTTON_TEXT, TEST_NEUTRAL_BUTTON_TEXT);
@@ -288,7 +286,7 @@
dialogHandle = mDialogManager.createSimpleDialog(
TEST_TITLE, TEST_MESSAGE, TEST_POSITIVE_BUTTON_TEXT, TEST_NEGATIVE_BUTTON_TEXT,
TEST_NEUTRAL_BUTTON_TEXT, callback, callbackThreadRunner);
- launchDialogSynchronous(dialogHandle, 0, mWifiThreadRunner);
+ launchDialogSynchronous(dialogHandle, mWifiThreadRunner);
intent = verifyStartActivityAsUser(3, mWifiContext);
dialogId = verifySimpleDialogLaunchIntent(intent, TEST_TITLE, TEST_MESSAGE,
TEST_POSITIVE_BUTTON_TEXT, TEST_NEGATIVE_BUTTON_TEXT, TEST_NEUTRAL_BUTTON_TEXT);
@@ -303,7 +301,7 @@
dialogHandle = mDialogManager.createSimpleDialog(TEST_TITLE, TEST_MESSAGE,
TEST_POSITIVE_BUTTON_TEXT, TEST_NEGATIVE_BUTTON_TEXT, TEST_NEUTRAL_BUTTON_TEXT,
callback, callbackThreadRunner);
- launchDialogSynchronous(dialogHandle, 0, mWifiThreadRunner);
+ launchDialogSynchronous(dialogHandle, mWifiThreadRunner);
intent = verifyStartActivityAsUser(4, mWifiContext);
dialogId = verifySimpleDialogLaunchIntent(intent, TEST_TITLE, TEST_MESSAGE,
TEST_POSITIVE_BUTTON_TEXT, TEST_NEGATIVE_BUTTON_TEXT, TEST_NEUTRAL_BUTTON_TEXT);
@@ -330,7 +328,7 @@
DialogHandle dialogHandle = mDialogManager.createSimpleDialog(TEST_TITLE, TEST_MESSAGE,
TEST_POSITIVE_BUTTON_TEXT, TEST_NEGATIVE_BUTTON_TEXT, TEST_NEUTRAL_BUTTON_TEXT,
callback, callbackThreadRunner);
- launchDialogSynchronous(dialogHandle, 0, mWifiThreadRunner);
+ launchDialogSynchronous(dialogHandle, mWifiThreadRunner);
Intent intent = verifyStartActivityAsUser(1, mWifiContext);
int dialogId = verifySimpleDialogLaunchIntent(intent, TEST_TITLE, TEST_MESSAGE,
TEST_POSITIVE_BUTTON_TEXT, TEST_NEGATIVE_BUTTON_TEXT, TEST_NEUTRAL_BUTTON_TEXT);
@@ -352,7 +350,7 @@
dialogHandle = mDialogManager.createSimpleDialog(TEST_TITLE, TEST_MESSAGE,
TEST_POSITIVE_BUTTON_TEXT, TEST_NEGATIVE_BUTTON_TEXT, TEST_NEUTRAL_BUTTON_TEXT,
callback, callbackThreadRunner);
- launchDialogSynchronous(dialogHandle, 0, mWifiThreadRunner);
+ launchDialogSynchronous(dialogHandle, mWifiThreadRunner);
intent = verifyStartActivityAsUser(3, mWifiContext);
dialogId = verifySimpleDialogLaunchIntent(intent, TEST_TITLE, TEST_MESSAGE,
TEST_POSITIVE_BUTTON_TEXT, TEST_NEGATIVE_BUTTON_TEXT, TEST_NEUTRAL_BUTTON_TEXT);
@@ -377,7 +375,7 @@
DialogHandle dialogHandle1 = mDialogManager.createSimpleDialog(TEST_TITLE, TEST_MESSAGE,
TEST_POSITIVE_BUTTON_TEXT, TEST_NEGATIVE_BUTTON_TEXT, TEST_NEUTRAL_BUTTON_TEXT,
callback1, callbackThreadRunner);
- launchDialogSynchronous(dialogHandle1, 0, mWifiThreadRunner);
+ launchDialogSynchronous(dialogHandle1, mWifiThreadRunner);
Intent intent = verifyStartActivityAsUser(1, mWifiContext);
int dialogId1 = verifySimpleDialogLaunchIntent(intent, TEST_TITLE, TEST_MESSAGE,
TEST_POSITIVE_BUTTON_TEXT, TEST_NEGATIVE_BUTTON_TEXT, TEST_NEUTRAL_BUTTON_TEXT);
@@ -387,7 +385,7 @@
DialogHandle dialogHandle2 = mDialogManager.createSimpleDialog(TEST_TITLE, TEST_MESSAGE,
TEST_POSITIVE_BUTTON_TEXT, TEST_NEGATIVE_BUTTON_TEXT, TEST_NEUTRAL_BUTTON_TEXT,
callback2, callbackThreadRunner);
- launchDialogSynchronous(dialogHandle2, 0, mWifiThreadRunner);
+ launchDialogSynchronous(dialogHandle2, mWifiThreadRunner);
intent = verifyStartActivityAsUser(2, mWifiContext);
int dialogId2 = verifySimpleDialogLaunchIntent(intent, TEST_TITLE, TEST_MESSAGE,
TEST_POSITIVE_BUTTON_TEXT, TEST_NEGATIVE_BUTTON_TEXT, TEST_NEUTRAL_BUTTON_TEXT);
@@ -434,7 +432,7 @@
DialogHandle dialogHandle = mDialogManager.createSimpleDialog(TEST_TITLE, TEST_MESSAGE,
TEST_POSITIVE_BUTTON_TEXT, TEST_NEGATIVE_BUTTON_TEXT, TEST_NEUTRAL_BUTTON_TEXT,
callback, callbackThreadRunner);
- launchDialogSynchronous(dialogHandle, 0, mWifiThreadRunner);
+ launchDialogSynchronous(dialogHandle, mWifiThreadRunner);
ArgumentCaptor<DialogInterface.OnClickListener> positiveButtonListenerCaptor =
ArgumentCaptor.forClass(DialogInterface.OnClickListener.class);
@@ -479,90 +477,6 @@
}
@Test
- public void testSimpleDialog_timeoutCancelsDialog_preT() {
- Assume.assumeTrue(!SdkLevel.isAtLeastT());
- SimpleDialogCallback callback = mock(SimpleDialogCallback.class);
- WifiThreadRunner callbackThreadRunner = mock(WifiThreadRunner.class);
-
-
- AlertDialog.Builder builder = mock(AlertDialog.Builder.class);
- AlertDialog dialog = mock(AlertDialog.class);
- when(builder.setTitle(any())).thenReturn(builder);
- when(builder.setMessage(any())).thenReturn(builder);
- when(builder.setPositiveButton(any(), any())).thenReturn(builder);
- when(builder.setNegativeButton(any(), any())).thenReturn(builder);
- when(builder.setNeutralButton(any(), any())).thenReturn(builder);
- when(builder.setOnCancelListener(any())).thenReturn(builder);
- when(builder.setOnDismissListener(any())).thenReturn(builder);
- when(builder.create()).thenReturn(dialog);
- Window window = mock(Window.class);
- WindowManager.LayoutParams layoutParams = mock(WindowManager.LayoutParams.class);
- when(window.getAttributes()).thenReturn(layoutParams);
- when(dialog.getWindow()).thenReturn(window);
- when(mFrameworkFacade.makeAlertDialogBuilder(any())).thenReturn(builder);
- DialogHandle dialogHandle = mDialogManager.createSimpleDialog(TEST_TITLE, TEST_MESSAGE,
- TEST_POSITIVE_BUTTON_TEXT, TEST_NEGATIVE_BUTTON_TEXT, TEST_NEUTRAL_BUTTON_TEXT,
- callback, callbackThreadRunner);
- launchDialogSynchronous(dialogHandle, TIMEOUT_MILLIS, mWifiThreadRunner);
-
- // Verify the timeout runnable was posted and run it.
- ArgumentCaptor<Runnable> runnableArgumentCaptor = ArgumentCaptor.forClass(Runnable.class);
- verify(mWifiThreadRunner, times(1))
- .postDelayed(runnableArgumentCaptor.capture(), eq((long) TIMEOUT_MILLIS),
- anyString());
- runnableArgumentCaptor.getValue().run();
-
- // Verify that the dialog was cancelled.
- verify(dialog).cancel();
- }
-
- @Test
- public void testSimpleDialog_dismissedBeforeTimeout_preT() {
- Assume.assumeTrue(!SdkLevel.isAtLeastT());
- SimpleDialogCallback callback = mock(SimpleDialogCallback.class);
- WifiThreadRunner callbackThreadRunner = mock(WifiThreadRunner.class);
-
-
- AlertDialog.Builder builder = mock(AlertDialog.Builder.class);
- AlertDialog dialog = mock(AlertDialog.class);
- when(builder.setTitle(any())).thenReturn(builder);
- when(builder.setMessage(any())).thenReturn(builder);
- when(builder.setPositiveButton(any(), any())).thenReturn(builder);
- when(builder.setNegativeButton(any(), any())).thenReturn(builder);
- when(builder.setNeutralButton(any(), any())).thenReturn(builder);
- when(builder.setOnCancelListener(any())).thenReturn(builder);
- when(builder.setOnDismissListener(any())).thenReturn(builder);
- when(builder.create()).thenReturn(dialog);
- Window window = mock(Window.class);
- WindowManager.LayoutParams layoutParams = mock(WindowManager.LayoutParams.class);
- when(window.getAttributes()).thenReturn(layoutParams);
- when(dialog.getWindow()).thenReturn(window);
- when(mFrameworkFacade.makeAlertDialogBuilder(any())).thenReturn(builder);
-
- DialogHandle dialogHandle = mDialogManager.createSimpleDialog(TEST_TITLE, TEST_MESSAGE,
- TEST_POSITIVE_BUTTON_TEXT, TEST_NEGATIVE_BUTTON_TEXT, TEST_NEUTRAL_BUTTON_TEXT,
- callback, callbackThreadRunner);
- launchDialogSynchronous(dialogHandle, TIMEOUT_MILLIS, mWifiThreadRunner);
-
- // Verify the timeout runnable was posted.
- ArgumentCaptor<Runnable> runnableArgumentCaptor = ArgumentCaptor.forClass(Runnable.class);
- verify(mWifiThreadRunner, times(1))
- .postDelayed(runnableArgumentCaptor.capture(), eq((long) TIMEOUT_MILLIS),
- anyString());
- runnableArgumentCaptor.getValue().run();
-
- // Dismiss the dialog before the timeout runnable executes.
- ArgumentCaptor<DialogInterface.OnDismissListener> dismissListenerCaptor =
- ArgumentCaptor.forClass(DialogInterface.OnDismissListener.class);
- verify(builder).setOnDismissListener(dismissListenerCaptor.capture());
- dismissListenerCaptor.getValue().onDismiss(dialog);
- dispatchMockWifiThreadRunner(mWifiThreadRunner);
-
- // Verify that the timeout runnable was removed.
- verify(mWifiThreadRunner).removeCallbacks(runnableArgumentCaptor.getValue());
- }
-
- @Test
public void testSimpleDialog_nullWifiResourceApkName_doesNotLaunchDialog() {
Assume.assumeTrue(SdkLevel.isAtLeastT());
when(mWifiContext.getWifiDialogApkPkgName()).thenReturn(null);
@@ -573,7 +487,7 @@
DialogHandle dialogHandle = mDialogManager.createSimpleDialog(TEST_TITLE, TEST_MESSAGE,
TEST_POSITIVE_BUTTON_TEXT, TEST_NEGATIVE_BUTTON_TEXT, TEST_NEUTRAL_BUTTON_TEXT,
callback, callbackThreadRunner);
- launchDialogSynchronous(dialogHandle, 0, mWifiThreadRunner);
+ launchDialogSynchronous(dialogHandle, mWifiThreadRunner);
verify(mWifiContext, never()).startActivityAsUser(any(), eq(UserHandle.CURRENT));
}
@@ -607,7 +521,7 @@
TEST_MESSAGE, TEST_POSITIVE_BUTTON_TEXT, TEST_NEGATIVE_BUTTON_TEXT,
TEST_NEUTRAL_BUTTON_TEXT,
callback, callbackThreadRunner);
- launchDialogSynchronous(dialogHandle, 0, mWifiThreadRunner);
+ launchDialogSynchronous(dialogHandle, mWifiThreadRunner);
ArgumentCaptor<DialogInterface.OnClickListener> positiveButtonListenerCaptor =
ArgumentCaptor.forClass(DialogInterface.OnClickListener.class);
@@ -652,90 +566,6 @@
}
@Test
- public void testLegacySimpleDialog_timeoutCancelsDialog() {
- SimpleDialogCallback callback = mock(SimpleDialogCallback.class);
- WifiThreadRunner callbackThreadRunner = mock(WifiThreadRunner.class);
-
-
- AlertDialog.Builder builder = mock(AlertDialog.Builder.class);
- AlertDialog dialog = mock(AlertDialog.class);
- when(builder.setTitle(any())).thenReturn(builder);
- when(builder.setMessage(any())).thenReturn(builder);
- when(builder.setPositiveButton(any(), any())).thenReturn(builder);
- when(builder.setNegativeButton(any(), any())).thenReturn(builder);
- when(builder.setNeutralButton(any(), any())).thenReturn(builder);
- when(builder.setOnCancelListener(any())).thenReturn(builder);
- when(builder.setOnDismissListener(any())).thenReturn(builder);
- when(builder.create()).thenReturn(dialog);
- Window window = mock(Window.class);
- WindowManager.LayoutParams layoutParams = mock(WindowManager.LayoutParams.class);
- when(window.getAttributes()).thenReturn(layoutParams);
- when(dialog.getWindow()).thenReturn(window);
- when(mFrameworkFacade.makeAlertDialogBuilder(any())).thenReturn(builder);
- DialogHandle dialogHandle = mDialogManager.createLegacySimpleDialog(TEST_TITLE,
- TEST_MESSAGE, TEST_POSITIVE_BUTTON_TEXT, TEST_NEGATIVE_BUTTON_TEXT,
- TEST_NEUTRAL_BUTTON_TEXT,
- callback, callbackThreadRunner);
- launchDialogSynchronous(dialogHandle, TIMEOUT_MILLIS, mWifiThreadRunner);
-
- // Verify the timeout runnable was posted and run it.
- ArgumentCaptor<Runnable> runnableArgumentCaptor = ArgumentCaptor.forClass(Runnable.class);
- verify(mWifiThreadRunner, times(1))
- .postDelayed(runnableArgumentCaptor.capture(), eq((long) TIMEOUT_MILLIS),
- anyString());
- runnableArgumentCaptor.getValue().run();
-
- // Verify that the dialog was cancelled.
- verify(dialog).cancel();
- }
-
- @Test
- public void testLegacySimpleDialog_dismissedBeforeTimeout() {
- SimpleDialogCallback callback = mock(SimpleDialogCallback.class);
- WifiThreadRunner callbackThreadRunner = mock(WifiThreadRunner.class);
-
-
- AlertDialog.Builder builder = mock(AlertDialog.Builder.class);
- AlertDialog dialog = mock(AlertDialog.class);
- when(builder.setTitle(any())).thenReturn(builder);
- when(builder.setMessage(any())).thenReturn(builder);
- when(builder.setPositiveButton(any(), any())).thenReturn(builder);
- when(builder.setNegativeButton(any(), any())).thenReturn(builder);
- when(builder.setNeutralButton(any(), any())).thenReturn(builder);
- when(builder.setOnCancelListener(any())).thenReturn(builder);
- when(builder.setOnDismissListener(any())).thenReturn(builder);
- when(builder.create()).thenReturn(dialog);
- Window window = mock(Window.class);
- WindowManager.LayoutParams layoutParams = mock(WindowManager.LayoutParams.class);
- when(window.getAttributes()).thenReturn(layoutParams);
- when(dialog.getWindow()).thenReturn(window);
- when(mFrameworkFacade.makeAlertDialogBuilder(any())).thenReturn(builder);
-
- DialogHandle dialogHandle = mDialogManager.createLegacySimpleDialog(TEST_TITLE,
- TEST_MESSAGE, TEST_POSITIVE_BUTTON_TEXT, TEST_NEGATIVE_BUTTON_TEXT,
- TEST_NEUTRAL_BUTTON_TEXT,
- callback, callbackThreadRunner);
- launchDialogSynchronous(dialogHandle, TIMEOUT_MILLIS, mWifiThreadRunner);
-
- // Verify the timeout runnable was posted.
- ArgumentCaptor<Runnable> runnableArgumentCaptor = ArgumentCaptor.forClass(Runnable.class);
- verify(mWifiThreadRunner, times(1))
- .postDelayed(runnableArgumentCaptor.capture(), eq((long) TIMEOUT_MILLIS),
- anyString());
- runnableArgumentCaptor.getValue().run();
-
- // Dismiss the dialog before the timeout runnable executes.
- ArgumentCaptor<DialogInterface.OnDismissListener> dismissListenerCaptor =
- ArgumentCaptor.forClass(DialogInterface.OnDismissListener.class);
- verify(builder).setOnDismissListener(dismissListenerCaptor.capture());
- dismissListenerCaptor.getValue().onDismiss(dialog);
- dispatchMockWifiThreadRunner(mWifiThreadRunner);
-
- // Verify that the timeout runnable was removed.
- verify(mWifiThreadRunner).removeCallbacks(runnableArgumentCaptor.getValue());
- }
-
- @Test
public void testLegacySimpleDialog_cancelledDueToActionCloseSystemDialogs() {
SimpleDialogCallback callback = mock(SimpleDialogCallback.class);
WifiThreadRunner callbackThreadRunner = mock(WifiThreadRunner.class);
@@ -761,7 +591,7 @@
TEST_MESSAGE, TEST_POSITIVE_BUTTON_TEXT, TEST_NEGATIVE_BUTTON_TEXT,
TEST_NEUTRAL_BUTTON_TEXT,
callback, callbackThreadRunner);
- launchDialogSynchronous(dialogHandle, TIMEOUT_MILLIS, mWifiThreadRunner);
+ launchDialogSynchronous(dialogHandle, mWifiThreadRunner);
// ACTION_CLOSE_SYSTEM_DIALOGS with EXTRA_CLOSE_SYSTEM_DIALOGS_EXCEPT_WIFI should be
// ignored.
@@ -807,7 +637,7 @@
TEST_MESSAGE, TEST_POSITIVE_BUTTON_TEXT, TEST_NEGATIVE_BUTTON_TEXT,
TEST_NEUTRAL_BUTTON_TEXT,
callback, callbackThreadRunner);
- launchDialogSynchronous(dialogHandle, TIMEOUT_MILLIS, mWifiThreadRunner);
+ launchDialogSynchronous(dialogHandle, mWifiThreadRunner);
verify(window).setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
// Receive screen off event.
@@ -833,7 +663,8 @@
@NonNull Intent launchIntent,
String expectedDeviceName,
boolean expectedIsPinRequested,
- @Nullable String expectedDisplayPin) {
+ @Nullable String expectedDisplayPin,
+ long expectedTimeoutMs) {
assertThat(launchIntent.getAction()).isEqualTo(WifiManager.ACTION_LAUNCH_DIALOG);
ComponentName component = launchIntent.getComponent();
assertThat(component.getPackageName()).isEqualTo(WIFI_DIALOG_APK_PKG_NAME);
@@ -855,6 +686,9 @@
assertThat(launchIntent.hasExtra(WifiManager.EXTRA_P2P_DISPLAY_PIN)).isTrue();
assertThat(launchIntent.getStringExtra(WifiManager.EXTRA_P2P_DISPLAY_PIN))
.isEqualTo(expectedDisplayPin);
+ assertThat(launchIntent.hasExtra(WifiManager.EXTRA_DIALOG_TIMEOUT_MS)).isTrue();
+ assertThat(launchIntent.getIntExtra(WifiManager.EXTRA_DIALOG_TIMEOUT_MS, -1))
+ .isEqualTo(expectedTimeoutMs);
return dialogId;
}
@@ -871,12 +705,12 @@
// Accept without PIN
DialogHandle dialogHandle = mDialogManager.createP2pInvitationReceivedDialog(
- TEST_DEVICE_NAME, false, null, Display.DEFAULT_DISPLAY,
+ TEST_DEVICE_NAME, false, null, TEST_P2P_TIMEOUT_MS, Display.DEFAULT_DISPLAY,
callback, callbackThreadRunner);
- launchDialogSynchronous(dialogHandle, 0, mWifiThreadRunner);
+ launchDialogSynchronous(dialogHandle, mWifiThreadRunner);
Intent intent = verifyStartActivityAsUser(1, mWifiContext);
int dialogId = verifyP2pInvitationReceivedDialogLaunchIntent(intent,
- TEST_DEVICE_NAME, false, null);
+ TEST_DEVICE_NAME, false, null, TEST_P2P_TIMEOUT_MS);
mDialogManager.replyToP2pInvitationReceivedDialog(dialogId, true, null);
dispatchMockWifiThreadRunner(callbackThreadRunner);
verify(callback, times(1)).onAccepted(null);
@@ -887,86 +721,87 @@
// Accept with PIN
dialogHandle = mDialogManager.createP2pInvitationReceivedDialog(
- TEST_DEVICE_NAME, true, null, Display.DEFAULT_DISPLAY,
+ TEST_DEVICE_NAME, true, null, TEST_P2P_TIMEOUT_MS, Display.DEFAULT_DISPLAY,
callback, callbackThreadRunner);
- launchDialogSynchronous(dialogHandle, 0, mWifiThreadRunner);
+ launchDialogSynchronous(dialogHandle, mWifiThreadRunner);
intent = verifyStartActivityAsUser(2, mWifiContext);
dialogId = verifyP2pInvitationReceivedDialogLaunchIntent(intent,
- TEST_DEVICE_NAME, true, null);
+ TEST_DEVICE_NAME, true, null, TEST_P2P_TIMEOUT_MS);
mDialogManager.replyToP2pInvitationReceivedDialog(dialogId, true, "012345");
dispatchMockWifiThreadRunner(callbackThreadRunner);
verify(callback, times(1)).onAccepted("012345");
// Accept with PIN but PIN was not requested
dialogHandle = mDialogManager.createP2pInvitationReceivedDialog(
- TEST_DEVICE_NAME, false, null, 123, callback, callbackThreadRunner);
- launchDialogSynchronous(dialogHandle, 0, mWifiThreadRunner);
+ TEST_DEVICE_NAME, false, null, TEST_P2P_TIMEOUT_MS, 123, callback,
+ callbackThreadRunner);
+ launchDialogSynchronous(dialogHandle, mWifiThreadRunner);
if (SdkLevel.isAtLeastT()) {
verifyStartActivityAsUser(1, 123, mWifiContext);
}
intent = verifyStartActivityAsUser(3, mWifiContext);
dialogId = verifyP2pInvitationReceivedDialogLaunchIntent(intent,
- TEST_DEVICE_NAME, false, null);
+ TEST_DEVICE_NAME, false, null, TEST_P2P_TIMEOUT_MS);
mDialogManager.replyToP2pInvitationReceivedDialog(dialogId, true, "012345");
dispatchMockWifiThreadRunner(callbackThreadRunner);
verify(callback, times(2)).onAccepted("012345");
// Accept without PIN but PIN was requested
dialogHandle = mDialogManager.createP2pInvitationReceivedDialog(
- TEST_DEVICE_NAME, true, null, Display.DEFAULT_DISPLAY,
+ TEST_DEVICE_NAME, true, null, TEST_P2P_TIMEOUT_MS, Display.DEFAULT_DISPLAY,
callback, callbackThreadRunner);
- launchDialogSynchronous(dialogHandle, 0, mWifiThreadRunner);
+ launchDialogSynchronous(dialogHandle, mWifiThreadRunner);
intent = verifyStartActivityAsUser(4, mWifiContext);
dialogId = verifyP2pInvitationReceivedDialogLaunchIntent(intent,
- TEST_DEVICE_NAME, true, null);
+ TEST_DEVICE_NAME, true, null, TEST_P2P_TIMEOUT_MS);
mDialogManager.replyToP2pInvitationReceivedDialog(dialogId, true, null);
dispatchMockWifiThreadRunner(callbackThreadRunner);
verify(callback, times(2)).onAccepted(null);
// Decline without PIN
dialogHandle = mDialogManager.createP2pInvitationReceivedDialog(
- TEST_DEVICE_NAME, false, null, Display.DEFAULT_DISPLAY,
+ TEST_DEVICE_NAME, false, null, TEST_P2P_TIMEOUT_MS, Display.DEFAULT_DISPLAY,
callback, callbackThreadRunner);
- launchDialogSynchronous(dialogHandle, 0, mWifiThreadRunner);
+ launchDialogSynchronous(dialogHandle, mWifiThreadRunner);
intent = verifyStartActivityAsUser(5, mWifiContext);
dialogId = verifyP2pInvitationReceivedDialogLaunchIntent(intent,
- TEST_DEVICE_NAME, false, null);
+ TEST_DEVICE_NAME, false, null, TEST_P2P_TIMEOUT_MS);
mDialogManager.replyToP2pInvitationReceivedDialog(dialogId, false, null);
dispatchMockWifiThreadRunner(callbackThreadRunner);
verify(callback, times(1)).onDeclined();
// Decline with PIN
dialogHandle = mDialogManager.createP2pInvitationReceivedDialog(
- TEST_DEVICE_NAME, true, null, Display.DEFAULT_DISPLAY,
+ TEST_DEVICE_NAME, true, null, TEST_P2P_TIMEOUT_MS, Display.DEFAULT_DISPLAY,
callback, callbackThreadRunner);
- launchDialogSynchronous(dialogHandle, 0, mWifiThreadRunner);
+ launchDialogSynchronous(dialogHandle, mWifiThreadRunner);
intent = verifyStartActivityAsUser(6, mWifiContext);
dialogId = verifyP2pInvitationReceivedDialogLaunchIntent(intent,
- TEST_DEVICE_NAME, true, null);
+ TEST_DEVICE_NAME, true, null, TEST_P2P_TIMEOUT_MS);
mDialogManager.replyToP2pInvitationReceivedDialog(dialogId, false, "012345");
dispatchMockWifiThreadRunner(callbackThreadRunner);
verify(callback, times(2)).onDeclined();
// Decline with PIN but PIN was not requested
dialogHandle = mDialogManager.createP2pInvitationReceivedDialog(
- TEST_DEVICE_NAME, false, null, Display.DEFAULT_DISPLAY,
+ TEST_DEVICE_NAME, false, null, TEST_P2P_TIMEOUT_MS, Display.DEFAULT_DISPLAY,
callback, callbackThreadRunner);
- launchDialogSynchronous(dialogHandle, 0, mWifiThreadRunner);
+ launchDialogSynchronous(dialogHandle, mWifiThreadRunner);
intent = verifyStartActivityAsUser(7, mWifiContext);
dialogId = verifyP2pInvitationReceivedDialogLaunchIntent(intent,
- TEST_DEVICE_NAME, false, null);
+ TEST_DEVICE_NAME, false, null, TEST_P2P_TIMEOUT_MS);
mDialogManager.replyToP2pInvitationReceivedDialog(dialogId, false, "012345");
dispatchMockWifiThreadRunner(callbackThreadRunner);
verify(callback, times(3)).onDeclined();
// Decline without PIN but PIN was requested
dialogHandle = mDialogManager.createP2pInvitationReceivedDialog(
- TEST_DEVICE_NAME, true, null, Display.DEFAULT_DISPLAY,
+ TEST_DEVICE_NAME, true, null, TEST_P2P_TIMEOUT_MS, Display.DEFAULT_DISPLAY,
callback, callbackThreadRunner);
- launchDialogSynchronous(dialogHandle, 0, mWifiThreadRunner);
+ launchDialogSynchronous(dialogHandle, mWifiThreadRunner);
intent = verifyStartActivityAsUser(8, mWifiContext);
dialogId = verifyP2pInvitationReceivedDialogLaunchIntent(intent,
- TEST_DEVICE_NAME, true, null);
+ TEST_DEVICE_NAME, true, null, TEST_P2P_TIMEOUT_MS);
mDialogManager.replyToP2pInvitationReceivedDialog(dialogId, false, null);
dispatchMockWifiThreadRunner(callbackThreadRunner);
verify(callback, times(4)).onDeclined();
@@ -985,12 +820,12 @@
// Launch and dismiss dialog.
DialogHandle dialogHandle = mDialogManager.createP2pInvitationReceivedDialog(
- TEST_DEVICE_NAME, false, null, Display.DEFAULT_DISPLAY,
+ TEST_DEVICE_NAME, false, null, TEST_P2P_TIMEOUT_MS, Display.DEFAULT_DISPLAY,
callback, callbackThreadRunner);
- launchDialogSynchronous(dialogHandle, 0, mWifiThreadRunner);
+ launchDialogSynchronous(dialogHandle, mWifiThreadRunner);
Intent intent = verifyStartActivityAsUser(1, mWifiContext);
int dialogId = verifyP2pInvitationReceivedDialogLaunchIntent(intent,
- TEST_DEVICE_NAME, false, null);
+ TEST_DEVICE_NAME, false, null, TEST_P2P_TIMEOUT_MS);
dismissDialogSynchronous(dialogHandle, mWifiThreadRunner);
intent = verifyStartActivityAsUser(2, mWifiContext);
verifyDismissIntent(intent);
@@ -1007,12 +842,12 @@
// Launch dialog again
dialogHandle = mDialogManager.createP2pInvitationReceivedDialog(
- TEST_DEVICE_NAME, false, null, Display.DEFAULT_DISPLAY,
+ TEST_DEVICE_NAME, false, null, TEST_P2P_TIMEOUT_MS, Display.DEFAULT_DISPLAY,
callback, callbackThreadRunner);
- launchDialogSynchronous(dialogHandle, 0, mWifiThreadRunner);
+ launchDialogSynchronous(dialogHandle, mWifiThreadRunner);
intent = verifyStartActivityAsUser(3, mWifiContext);
dialogId = verifyP2pInvitationReceivedDialogLaunchIntent(intent,
- TEST_DEVICE_NAME, false, null);
+ TEST_DEVICE_NAME, false, null, TEST_P2P_TIMEOUT_MS);
// Callback should receive replies to the corresponding dialogId now.
mDialogManager.replyToP2pInvitationReceivedDialog(dialogId, true, null);
@@ -1032,23 +867,23 @@
mock(P2pInvitationReceivedDialogCallback.class);
WifiThreadRunner callbackThreadRunner = mock(WifiThreadRunner.class);
DialogHandle dialogHandle1 = mDialogManager.createP2pInvitationReceivedDialog(
- TEST_DEVICE_NAME, false, null, Display.DEFAULT_DISPLAY,
+ TEST_DEVICE_NAME, false, null, TEST_P2P_TIMEOUT_MS, Display.DEFAULT_DISPLAY,
callback1, callbackThreadRunner);
- launchDialogSynchronous(dialogHandle1, 0, mWifiThreadRunner);
+ launchDialogSynchronous(dialogHandle1, mWifiThreadRunner);
Intent intent1 = verifyStartActivityAsUser(1, mWifiContext);
int dialogId1 = verifyP2pInvitationReceivedDialogLaunchIntent(intent1,
- TEST_DEVICE_NAME, false, null);
+ TEST_DEVICE_NAME, false, null, TEST_P2P_TIMEOUT_MS);
// Launch Dialog2
P2pInvitationReceivedDialogCallback callback2 =
mock(P2pInvitationReceivedDialogCallback.class);
DialogHandle dialogHandle2 = mDialogManager.createP2pInvitationReceivedDialog(
- TEST_DEVICE_NAME, false, null, Display.DEFAULT_DISPLAY,
+ TEST_DEVICE_NAME, false, null, TEST_P2P_TIMEOUT_MS, Display.DEFAULT_DISPLAY,
callback2, callbackThreadRunner);
- launchDialogSynchronous(dialogHandle2, 0, mWifiThreadRunner);
+ launchDialogSynchronous(dialogHandle2, mWifiThreadRunner);
Intent intent2 = verifyStartActivityAsUser(2, mWifiContext);
int dialogId2 = verifyP2pInvitationReceivedDialogLaunchIntent(intent2,
- TEST_DEVICE_NAME, false, null);
+ TEST_DEVICE_NAME, false, null, TEST_P2P_TIMEOUT_MS);
// callback1 notified
mDialogManager.replyToP2pInvitationReceivedDialog(dialogId1, true, null);
@@ -1103,7 +938,7 @@
// Launch and dismiss dialog.
DialogHandle dialogHandle = mDialogManager.createP2pInvitationSentDialog(
TEST_DEVICE_NAME, null, Display.DEFAULT_DISPLAY);
- launchDialogSynchronous(dialogHandle, 0, mWifiThreadRunner);
+ launchDialogSynchronous(dialogHandle, mWifiThreadRunner);
verifyP2pInvitationSentDialogLaunchIntent(verifyStartActivityAsUser(1, mWifiContext),
TEST_DEVICE_NAME, null);
dismissDialogSynchronous(dialogHandle, mWifiThreadRunner);
diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiGlobalsTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiGlobalsTest.java
index 0fefd7a..41ff5ce 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/WifiGlobalsTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/WifiGlobalsTest.java
@@ -337,4 +337,12 @@
mWifiGlobals.setD2dStaConcurrencySupported(false);
assertTrue(mWifiGlobals.isD2dSupportedWhenInfraStaDisabled());
}
+
+ @Test
+ public void testIsMLDApSupported() {
+ assertFalse(mWifiGlobals.isMLDApSupported());
+ mWifiResourceCache.reset();
+ mResources.setInteger(R.integer.config_wifiSoftApMaxNumberMLDSupported, 1);
+ assertTrue(mWifiGlobals.isMLDApSupported());
+ }
}
diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiLockManagerTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiLockManagerTest.java
index 6af6d0c..4706593 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/WifiLockManagerTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/WifiLockManagerTest.java
@@ -19,6 +19,7 @@
import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_LOCAL_ONLY;
import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_PRIMARY;
import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_SECONDARY_TRANSIENT;
+import static com.android.server.wifi.TestUtil.createCapabilityBitset;
import static org.hamcrest.CoreMatchers.not;
import static org.junit.Assert.assertEquals;
@@ -69,6 +70,7 @@
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
+import java.util.BitSet;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Random;
@@ -133,6 +135,7 @@
when(mContext.getSystemService(PowerManager.class)).thenReturn(mPowerManager);
when(mClientModeManager.getRole()).thenReturn(ROLE_CLIENT_PRIMARY);
+ when(mClientModeManager.getSupportedFeatures()).thenReturn(new BitSet());
when(mActiveModeWarden.getPrimaryClientModeManager()).thenReturn(mClientModeManager);
when(mClientModeManager2.getRole()).thenReturn(ROLE_CLIENT_SECONDARY_TRANSIENT);
@@ -529,7 +532,7 @@
when(mActivityManager.getUidImportance(anyInt())).thenReturn(
ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND);
when(mClientModeManager.getSupportedFeatures())
- .thenReturn((long) WifiManager.WIFI_FEATURE_LOW_LATENCY);
+ .thenReturn(createCapabilityBitset(WifiManager.WIFI_FEATURE_LOW_LATENCY));
when(mClientModeManager.setLowLatencyMode(anyBoolean())).thenReturn(true);
}
@@ -560,7 +563,7 @@
when(mActivityManager.getUidImportance(anyInt())).thenReturn(
ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND);
when(mClientModeManager.getSupportedFeatures())
- .thenReturn((long) WifiManager.WIFI_FEATURE_LOW_LATENCY);
+ .thenReturn(createCapabilityBitset(WifiManager.WIFI_FEATURE_LOW_LATENCY));
when(mClientModeManager.setLowLatencyMode(anyBoolean())).thenReturn(true);
expectedMode = WifiManager.WIFI_MODE_FULL_LOW_LATENCY;
}
@@ -702,7 +705,7 @@
when(mActivityManager.getUidImportance(anyInt())).thenReturn(
ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND);
when(mClientModeManager.getSupportedFeatures())
- .thenReturn((long) WifiManager.WIFI_FEATURE_LOW_LATENCY);
+ .thenReturn(createCapabilityBitset(WifiManager.WIFI_FEATURE_LOW_LATENCY));
when(mClientModeManager.setLowLatencyMode(anyBoolean())).thenReturn(true);
expectedMode = WifiManager.WIFI_MODE_FULL_LOW_LATENCY;
}
@@ -747,7 +750,7 @@
when(mActivityManager.getUidImportance(anyInt())).thenReturn(
ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND);
when(mClientModeManager.getSupportedFeatures())
- .thenReturn((long) WifiManager.WIFI_MODE_FULL_LOW_LATENCY);
+ .thenReturn(createCapabilityBitset(WifiManager.WIFI_MODE_FULL_LOW_LATENCY));
when(mClientModeManager.setLowLatencyMode(anyBoolean())).thenReturn(true);
expectedMode = WifiManager.WIFI_MODE_FULL_LOW_LATENCY;
}
@@ -1009,7 +1012,7 @@
ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND);
when(mClientModeManager.setLowLatencyMode(anyBoolean())).thenReturn(true);
when(mClientModeManager.getSupportedFeatures())
- .thenReturn(WifiManager.WIFI_FEATURE_LOW_LATENCY);
+ .thenReturn(createCapabilityBitset(WifiManager.WIFI_FEATURE_LOW_LATENCY));
acquireWifiLockSuccessful(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, "",
mBinder, mWorkSource);
@@ -1029,7 +1032,7 @@
when(mActivityManager.getUidImportance(anyInt())).thenReturn(
ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND);
when(mClientModeManager.getSupportedFeatures())
- .thenReturn((long) WifiManager.WIFI_FEATURE_TX_POWER_LIMIT);
+ .thenReturn(createCapabilityBitset(WifiManager.WIFI_FEATURE_TX_POWER_LIMIT));
acquireWifiLockSuccessful(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, "",
mBinder, mWorkSource);
@@ -1049,7 +1052,7 @@
when(mActivityManager.getUidImportance(anyInt())).thenReturn(
ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND);
when(mClientModeManager.getSupportedFeatures())
- .thenReturn((long) WifiManager.WIFI_FEATURE_LOW_LATENCY);
+ .thenReturn(createCapabilityBitset(WifiManager.WIFI_FEATURE_LOW_LATENCY));
// Make sure setLowLatencyMode() is successful
when(mClientModeManager.setLowLatencyMode(anyBoolean())).thenReturn(true);
@@ -1088,7 +1091,7 @@
when(mActivityManager.getUidImportance(anyInt())).thenReturn(
ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND);
when(mClientModeManager.getSupportedFeatures())
- .thenReturn((long) WifiManager.WIFI_FEATURE_LOW_LATENCY);
+ .thenReturn(createCapabilityBitset(WifiManager.WIFI_FEATURE_LOW_LATENCY));
// Fail the call to ClientModeManager
when(mClientModeManager.setLowLatencyMode(true)).thenReturn(false);
@@ -1118,7 +1121,7 @@
when(mActivityManager.getUidImportance(anyInt())).thenReturn(
ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND);
when(mClientModeManager.getSupportedFeatures())
- .thenReturn((long) WifiManager.WIFI_FEATURE_LOW_LATENCY);
+ .thenReturn(createCapabilityBitset(WifiManager.WIFI_FEATURE_LOW_LATENCY));
// Succeed to setLowLatencyMode()
when(mClientModeManager.setLowLatencyMode(anyBoolean())).thenReturn(true);
@@ -1147,7 +1150,7 @@
when(mActivityManager.getUidImportance(anyInt())).thenReturn(
ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND);
when(mClientModeManager.getSupportedFeatures())
- .thenReturn((long) WifiManager.WIFI_FEATURE_LOW_LATENCY);
+ .thenReturn(createCapabilityBitset(WifiManager.WIFI_FEATURE_LOW_LATENCY));
// Make sure setLowLatencyMode() is successful
when(mClientModeManager.setLowLatencyMode(anyBoolean())).thenReturn(true);
@@ -1186,7 +1189,7 @@
when(mActivityManager.getUidImportance(anyInt())).thenReturn(
ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND);
when(mClientModeManager.getSupportedFeatures())
- .thenReturn((long) WifiManager.WIFI_FEATURE_LOW_LATENCY);
+ .thenReturn(createCapabilityBitset(WifiManager.WIFI_FEATURE_LOW_LATENCY));
// Make sure setLowLatencyMode() is successful
when(mClientModeManager.setLowLatencyMode(anyBoolean())).thenReturn(true);
@@ -1229,7 +1232,7 @@
setScreenState(true);
when(mFrameworkFacade.isAppForeground(any(), anyInt())).thenReturn(false);
when(mClientModeManager.getSupportedFeatures())
- .thenReturn((long) WifiManager.WIFI_FEATURE_LOW_LATENCY);
+ .thenReturn(createCapabilityBitset(WifiManager.WIFI_FEATURE_LOW_LATENCY));
// Make sure setLowLatencyMode() is successful
when(mClientModeManager.setLowLatencyMode(anyBoolean())).thenReturn(true);
@@ -1272,7 +1275,7 @@
setScreenState(true);
when(mFrameworkFacade.isAppForeground(any(), anyInt())).thenReturn(false);
when(mClientModeManager.getSupportedFeatures())
- .thenReturn((long) WifiManager.WIFI_FEATURE_LOW_LATENCY);
+ .thenReturn(createCapabilityBitset(WifiManager.WIFI_FEATURE_LOW_LATENCY));
mWifiLockManager.updateWifiClientConnected(mClientModeManager, true);
// Make sure setLowLatencyMode()/setPowerSave() is successful
@@ -1324,7 +1327,7 @@
when(mClientModeManager.setPowerSave(eq(ClientMode.POWER_SAVE_CLIENT_WIFI_LOCK),
anyBoolean())).thenReturn(true);
when(mClientModeManager.getSupportedFeatures())
- .thenReturn((long) WifiManager.WIFI_FEATURE_LOW_LATENCY);
+ .thenReturn(createCapabilityBitset(WifiManager.WIFI_FEATURE_LOW_LATENCY));
InOrder inOrder = inOrder(mClientModeManager);
@@ -1359,7 +1362,7 @@
anyBoolean())).thenReturn(true);
setScreenState(false);
when(mClientModeManager.getSupportedFeatures())
- .thenReturn((long) WifiManager.WIFI_FEATURE_LOW_LATENCY);
+ .thenReturn(createCapabilityBitset(WifiManager.WIFI_FEATURE_LOW_LATENCY));
mWifiLockManager.updateWifiClientConnected(mClientModeManager, true);
InOrder inOrder = inOrder(mClientModeManager);
@@ -1400,7 +1403,7 @@
when(mActivityManager.getUidImportance(anyInt())).thenReturn(
ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND);
when(mClientModeManager.getSupportedFeatures())
- .thenReturn((long) WifiManager.WIFI_FEATURE_LOW_LATENCY);
+ .thenReturn(createCapabilityBitset(WifiManager.WIFI_FEATURE_LOW_LATENCY));
InOrder inOrder = inOrder(mClientModeManager);
@@ -1446,7 +1449,7 @@
when(mClientModeManager.setPowerSave(eq(ClientMode.POWER_SAVE_CLIENT_WIFI_LOCK),
anyBoolean())).thenReturn(true);
when(mClientModeManager.getSupportedFeatures())
- .thenReturn((long) WifiManager.WIFI_FEATURE_LOW_LATENCY);
+ .thenReturn(createCapabilityBitset(WifiManager.WIFI_FEATURE_LOW_LATENCY));
mWifiLockManager.updateWifiClientConnected(mClientModeManager, true);
InOrder inOrder = inOrder(mClientModeManager);
@@ -1475,7 +1478,7 @@
when(mClientModeManager.setPowerSave(eq(ClientMode.POWER_SAVE_CLIENT_WIFI_LOCK),
anyBoolean())).thenReturn(true);
when(mClientModeManager.getSupportedFeatures())
- .thenReturn((long) WifiManager.WIFI_FEATURE_LOW_LATENCY);
+ .thenReturn(createCapabilityBitset(WifiManager.WIFI_FEATURE_LOW_LATENCY));
mWifiLockManager.updateWifiClientConnected(mClientModeManager, true);
InOrder inOrder = inOrder(mClientModeManager);
@@ -1508,7 +1511,7 @@
when(mClientModeManager.setPowerSave(eq(ClientMode.POWER_SAVE_CLIENT_WIFI_LOCK),
anyBoolean())).thenReturn(true);
when(mClientModeManager.getSupportedFeatures())
- .thenReturn((long) WifiManager.WIFI_FEATURE_LOW_LATENCY);
+ .thenReturn(createCapabilityBitset(WifiManager.WIFI_FEATURE_LOW_LATENCY));
mWifiLockManager.updateWifiClientConnected(mClientModeManager, true);
InOrder inOrder = inOrder(mClientModeManager);
@@ -1541,7 +1544,7 @@
int expectedMode = WifiManager.WIFI_MODE_FULL_HIGH_PERF;
when(mClientModeManager.setLowLatencyMode(anyBoolean())).thenReturn(false);
when(mClientModeManager.getSupportedFeatures())
- .thenReturn((long) WifiManager.WIFI_FEATURE_LOW_LATENCY);
+ .thenReturn(createCapabilityBitset(WifiManager.WIFI_FEATURE_LOW_LATENCY));
InOrder inOrder = inOrder(mClientModeManager);
@@ -1699,7 +1702,7 @@
when(mActivityManager.getUidImportance(anyInt())).thenReturn(
ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND);
when(mClientModeManager.getSupportedFeatures())
- .thenReturn((long) WifiManager.WIFI_FEATURE_LOW_LATENCY);
+ .thenReturn(createCapabilityBitset(WifiManager.WIFI_FEATURE_LOW_LATENCY));
when(mClientModeManager.setLowLatencyMode(anyBoolean())).thenReturn(true);
expectedMode = WifiManager.WIFI_MODE_FULL_LOW_LATENCY;
}
@@ -1752,7 +1755,7 @@
when(mActivityManager.getUidImportance(anyInt())).thenReturn(
ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND);
when(mClientModeManager.getSupportedFeatures())
- .thenReturn((long) WifiManager.WIFI_FEATURE_LOW_LATENCY);
+ .thenReturn(createCapabilityBitset(WifiManager.WIFI_FEATURE_LOW_LATENCY));
InOrder inOrder = inOrder(mWifiMetrics);
@@ -1899,7 +1902,7 @@
when(mClientModeManager.setPowerSave(eq(ClientMode.POWER_SAVE_CLIENT_WIFI_LOCK),
anyBoolean())).thenReturn(false);
when(mClientModeManager.getSupportedFeatures())
- .thenReturn((long) WifiManager.WIFI_FEATURE_LOW_LATENCY);
+ .thenReturn(createCapabilityBitset(WifiManager.WIFI_FEATURE_LOW_LATENCY));
InOrder inOrder = inOrder(mClientModeManager);
@@ -1945,12 +1948,13 @@
when(mActivityManager.getUidImportance(DEFAULT_TEST_UID_1)).thenReturn(
ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND);
when(mClientModeManager.setLowLatencyMode(anyBoolean())).thenReturn(true);
- when(mClientModeManager.getSupportedFeatures()).thenReturn(
- WifiManager.WIFI_FEATURE_LOW_LATENCY);
+ when(mClientModeManager.getSupportedFeatures())
+ .thenReturn(createCapabilityBitset(WifiManager.WIFI_FEATURE_LOW_LATENCY));
acquireWifiLockSuccessful(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, "", mBinder, mWorkSource);
mWifiLockManager.updateWifiClientConnected(mClientModeManager, true);
inOrder.verify(testListener).onOwnershipChanged(eq(new int[]{DEFAULT_TEST_UID_1}));
inOrder.verify(testListener).onActivatedStateChanged(true);
+ verify(mWifiMetrics).setLowLatencyState(eq(true));
inOrder.verify(testListener).onActiveUsersChanged(eq(new int[]{DEFAULT_TEST_UID_1}));
// Acquire a second lock and check the owners & active users changed.
@@ -2032,8 +2036,13 @@
when(mActivityManager.getUidImportance(DEFAULT_TEST_UID_1)).thenReturn(
ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND);
when(mClientModeManager.setLowLatencyMode(anyBoolean())).thenReturn(true);
- when(mClientModeManager.getSupportedFeatures()).thenReturn(
- ~WifiManager.WIFI_FEATURE_LOW_LATENCY);
+
+ // Disable low latency, but support other arbitrary features
+ BitSet supportedFeatures = new BitSet();
+ supportedFeatures.set(WifiManager.WIFI_FEATURE_LOW_LATENCY, false);
+ supportedFeatures.set(WifiManager.WIFI_FEATURE_DPP, true);
+ when(mClientModeManager.getSupportedFeatures()).thenReturn(supportedFeatures);
+
acquireWifiLockSuccessful(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, "", mBinder, mWorkSource);
mWifiLockManager.updateWifiClientConnected(mClientModeManager, true);
inOrder.verify(testListener).onOwnershipChanged(eq(new int[]{DEFAULT_TEST_UID_1}));
@@ -2057,8 +2066,8 @@
when(mActivityManager.getUidImportance(DEFAULT_TEST_UID_1)).thenReturn(
ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND);
when(mClientModeManager.setLowLatencyMode(anyBoolean())).thenReturn(true);
- when(mClientModeManager.getSupportedFeatures()).thenReturn(
- WifiManager.WIFI_FEATURE_LOW_LATENCY);
+ when(mClientModeManager.getSupportedFeatures())
+ .thenReturn(createCapabilityBitset(WifiManager.WIFI_FEATURE_LOW_LATENCY));
mWifiLockManager.updateWifiClientConnected(mClientModeManager, true);
// Acquire the lock should report
@@ -2103,8 +2112,8 @@
when(mActivityManager.getUidImportance(DEFAULT_TEST_UID_1)).thenReturn(
ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND);
when(mClientModeManager.setLowLatencyMode(anyBoolean())).thenReturn(true);
- when(mClientModeManager.getSupportedFeatures()).thenReturn(
- WifiManager.WIFI_FEATURE_LOW_LATENCY);
+ when(mClientModeManager.getSupportedFeatures())
+ .thenReturn(createCapabilityBitset(WifiManager.WIFI_FEATURE_LOW_LATENCY));
mWifiLockManager.updateWifiClientConnected(mClientModeManager, true);
// Acquire the lock should report
@@ -2151,8 +2160,8 @@
when(mActivityManager.getUidImportance(DEFAULT_TEST_UID_1)).thenReturn(
ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND);
when(mClientModeManager.setLowLatencyMode(anyBoolean())).thenReturn(true);
- when(mClientModeManager.getSupportedFeatures()).thenReturn(
- WifiManager.WIFI_FEATURE_LOW_LATENCY);
+ when(mClientModeManager.getSupportedFeatures())
+ .thenReturn(createCapabilityBitset(WifiManager.WIFI_FEATURE_LOW_LATENCY));
mWifiLockManager.updateWifiClientConnected(mClientModeManager, true);
// Acquire --> reportFullWifiLockAcquiredFromSource
diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java
index 8035444..e317d31 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java
@@ -251,6 +251,7 @@
@Mock Network mNetwork;
@Mock WifiInfo mWifiInfo;
@Mock WifiNative.ConnectionCapabilities mCapabilities;
+ @Mock WifiGlobals mWifiGlobals;
@Captor ArgumentCaptor<ActiveModeWarden.ModeChangeCallback> mModeChangeCallbackArgumentCaptor;
@Captor ArgumentCaptor<Handler> mHandlerCaptor;
@Captor
@@ -284,7 +285,8 @@
mWifiP2pMetrics,
mDppMetrics,
mWifiMonitor,
- mWifiDeviceStateChangeManager);
+ mWifiDeviceStateChangeManager,
+ mWifiGlobals);
mWifiMetrics.setWifiConfigManager(mWcm);
mWifiMetrics.setWifiBlocklistMonitor(mWifiBlocklistMonitor);
mWifiMetrics.setPasspointManager(mPpm);
@@ -4332,7 +4334,7 @@
when(info.getLinkSpeed()).thenReturn(nextRandInt());
WifiLinkLayerStats stats = start;
for (int i = 0; i < WifiMetrics.NUM_WIFI_USABILITY_STATS_ENTRIES_PER_WIFI_GOOD; i++) {
- mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, stats);
+ mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, stats, false, 0);
stats = nextRandomStats(stats);
}
return stats;
@@ -4345,8 +4347,8 @@
when(info.getLinkSpeed()).thenReturn(nextRandInt());
WifiLinkLayerStats stats1 = start;
WifiLinkLayerStats stats2 = nextRandomStats(stats1);
- mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, stats1);
- mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, stats2);
+ mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, stats1, false, 0);
+ mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, stats2, false, 0);
mWifiMetrics.addToWifiUsabilityStatsList(TEST_IFACE_NAME, WifiUsabilityStats.LABEL_BAD,
WifiUsabilityStats.TYPE_DATA_STALL_BAD_TX, -1);
return nextRandomStats(stats2);
@@ -4379,64 +4381,18 @@
mWifiMetrics.incrementWifiUsabilityScoreCount(TEST_IFACE_NAME, 2, 55, 15);
mWifiMetrics.logLinkProbeSuccess(
TEST_IFACE_NAME, nextRandInt(), nextRandInt(), nextRandInt(), 12);
- mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, stats1);
+ mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, stats1, false, 0);
mWifiMetrics.incrementWifiScoreCount(TEST_IFACE_NAME, 58);
mWifiMetrics.incrementWifiUsabilityScoreCount(TEST_IFACE_NAME, 3, 56, 15);
mWifiMetrics.logLinkProbeFailure(TEST_IFACE_NAME, nextRandInt(), nextRandInt(),
nextRandInt(), nextRandInt());
mWifiMetrics.enterDeviceMobilityState(DEVICE_MOBILITY_STATE_HIGH_MVMT);
- mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, stats2);
+ mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, stats2, false, 0);
assertEquals(stats2.beacon_rx, mWifiMetrics.getTotalBeaconRxCount());
- mWifiMetrics.addToWifiUsabilityStatsList(TEST_IFACE_NAME, WifiUsabilityStats.LABEL_BAD,
- WifiUsabilityStats.TYPE_DATA_STALL_BAD_TX, -1);
-
- // Add 2 LABEL_GOOD but only 1 should remain in the converted proto
- WifiLinkLayerStats statsGood = addGoodWifiUsabilityStats(nextRandomStats(stats2));
- statsGood.timeStampInMs += WifiMetrics.MIN_WIFI_GOOD_USABILITY_STATS_PERIOD_MS;
- addGoodWifiUsabilityStats(statsGood);
dumpProtoAndDeserialize();
- assertEquals(2, mDecodedProto.wifiUsabilityStatsList.length);
- assertEquals(WifiUsabilityStats.LABEL_GOOD, mDecodedProto.wifiUsabilityStatsList[0].label);
- assertEquals(WifiUsabilityStats.LABEL_BAD, mDecodedProto.wifiUsabilityStatsList[1].label);
- assertUsabilityStatsAssignment(info, stats1,
- mDecodedProto.wifiUsabilityStatsList[1].stats[0]);
- assertUsabilityStatsAssignment(info, stats2,
- mDecodedProto.wifiUsabilityStatsList[1].stats[1]);
-
- assertEquals(2, mDecodedProto.wifiUsabilityStatsList[1].stats[0].seqNumToFramework);
- assertEquals(3, mDecodedProto.wifiUsabilityStatsList[1].stats[1].seqNumToFramework);
- assertEquals(0, mDecodedProto.wifiUsabilityStatsList[1].stats[0].seqNumInsideFramework);
- assertEquals(1, mDecodedProto.wifiUsabilityStatsList[1].stats[1].seqNumInsideFramework);
- assertEquals(60, mDecodedProto.wifiUsabilityStatsList[1].stats[0].wifiScore);
- assertEquals(58, mDecodedProto.wifiUsabilityStatsList[1].stats[1].wifiScore);
- assertEquals(55, mDecodedProto.wifiUsabilityStatsList[1].stats[0].wifiUsabilityScore);
- assertEquals(56, mDecodedProto.wifiUsabilityStatsList[1].stats[1].wifiUsabilityScore);
- assertEquals(15, mDecodedProto.wifiUsabilityStatsList[1].stats[0].predictionHorizonSec);
- assertEquals(true, mDecodedProto.wifiUsabilityStatsList[1].stats[0].isSameBssidAndFreq);
- assertEquals(android.net.wifi.WifiUsabilityStatsEntry.PROBE_STATUS_SUCCESS,
- mDecodedProto.wifiUsabilityStatsList[1].stats[0].probeStatusSinceLastUpdate);
- assertEquals(android.net.wifi.WifiUsabilityStatsEntry.PROBE_STATUS_FAILURE,
- mDecodedProto.wifiUsabilityStatsList[1].stats[1].probeStatusSinceLastUpdate);
- assertEquals(android.net.wifi.WifiUsabilityStatsEntry.PROBE_STATUS_NO_PROBE,
- mDecodedProto.wifiUsabilityStatsList[0].stats[0].probeStatusSinceLastUpdate);
- assertEquals(12,
- mDecodedProto.wifiUsabilityStatsList[1].stats[0].probeElapsedTimeSinceLastUpdateMs);
- assertEquals(Integer.MAX_VALUE, mDecodedProto.wifiUsabilityStatsList[1]
- .stats[1].probeElapsedTimeSinceLastUpdateMs);
- assertEquals(-1, mDecodedProto.wifiUsabilityStatsList[0]
- .stats[0].probeElapsedTimeSinceLastUpdateMs);
- assertEquals(DEVICE_MOBILITY_STATE_HIGH_MVMT, mDecodedProto.wifiUsabilityStatsList[1]
- .stats[mDecodedProto.wifiUsabilityStatsList[1].stats.length - 1]
- .deviceMobilityState);
- assertEquals(true, mDecodedProto.wifiUsabilityStatsList[0].stats[0].isWifiScoringEnabled);
- assertEquals(true,
- mDecodedProto.wifiUsabilityStatsList[1].stats[0].isCellularDataAvailable);
- assertEquals(false,
- mDecodedProto.wifiUsabilityStatsList[1].stats[1].isThroughputSufficient);
- assertEquals(150,
- mDecodedProto.wifiUsabilityStatsList[0].stats[0].channelUtilizationRatio);
+ // TODO (b/377723852) Add more verifications when new data capture is implemented
}
private WifiLinkLayerStats createNewWifiLinkLayerStats() {
@@ -4498,124 +4454,74 @@
}
/**
- * Verify that the buffer for WifiUsabilityStats does not exceed the max length.
- * Do this by trying to add more WifiUsabilityStats than the max length and then
- * verifying that the decoded proto's length does not exceed the max length.
+ * Verify that records are properly added to mWifiUsabilityStatsEntriesRingBuffer and that the
+ * size does not grow indefinitely.
*
- * Also verify that the length for the list of WifiUsabilityStatsEntry is capped.
* @throws Exception
*/
@Test
- public void testWifiUsabilityStatsBufferSizeIsCapped() throws Exception {
- // simulate adding LABEL_GOOD WifiUsabilityStats 1 time over the max limit
- WifiLinkLayerStats stats = new WifiLinkLayerStats();
- for (int j = 0; j < WifiMetrics.MAX_WIFI_USABILITY_STATS_LIST_SIZE_PER_TYPE + 1; j++) {
- stats = addGoodWifiUsabilityStats(stats);
- stats = addBadWifiUsabilityStats(stats);
- stats.timeStampInMs += WifiMetrics.MIN_WIFI_GOOD_USABILITY_STATS_PERIOD_MS;
+ public void testLogAsynchronousEvent() throws Exception {
+ when(mClock.getElapsedSinceBootMillis()).thenReturn((long) 123);
+
+ // Buffer starts out empty.
+ assertEquals(0, mWifiMetrics.mWifiUsabilityStatsEntriesRingBuffer.size());
+
+ // Check that exactly one record is added and with default subcode.
+ mWifiMetrics.logAsynchronousEvent(TEST_IFACE_NAME,
+ WifiUsabilityStatsEntry.CAPTURE_EVENT_TYPE_RSSI_POLLING_ENABLED);
+ assertEquals(1, mWifiMetrics.mWifiUsabilityStatsEntriesRingBuffer.size());
+ WifiUsabilityStatsEntry actual = mWifiMetrics.mWifiUsabilityStatsEntriesRingBuffer.get(0);
+ assertEquals(123, actual.timeStampMs);
+ assertEquals(WifiUsabilityStatsEntry.CAPTURE_EVENT_TYPE_RSSI_POLLING_ENABLED,
+ actual.captureEventType);
+ assertEquals(-1, actual.captureEventTypeSubcode);
+
+ // Check that exactly one record is added with given subcode.
+ mWifiMetrics.logAsynchronousEvent(TEST_IFACE_NAME,
+ WifiUsabilityStatsEntry.CAPTURE_EVENT_TYPE_RSSI_POLLING_DISABLED, -9876);
+ assertEquals(2, mWifiMetrics.mWifiUsabilityStatsEntriesRingBuffer.size());
+ actual = mWifiMetrics.mWifiUsabilityStatsEntriesRingBuffer.get(1);
+ assertEquals(123, actual.timeStampMs);
+ assertEquals(WifiUsabilityStatsEntry.CAPTURE_EVENT_TYPE_RSSI_POLLING_DISABLED,
+ actual.captureEventType);
+ assertEquals(-9876, actual.captureEventTypeSubcode);
+
+ // Fill the ring buffer
+ for (int i = 0; i < WifiMetrics.MAX_WIFI_USABILITY_STATS_ENTRIES_RING_BUFFER_SIZE - 2;
+ i++) {
+ mWifiMetrics.logAsynchronousEvent(TEST_IFACE_NAME,
+ WifiUsabilityStatsEntry.CAPTURE_EVENT_TYPE_RSSI_POLLING_ENABLED);
}
- dumpProtoAndDeserialize();
- assertEquals(2 * WifiMetrics.MAX_WIFI_USABILITY_STATS_PER_TYPE_TO_UPLOAD,
- mDecodedProto.wifiUsabilityStatsList.length);
- for (int i = 0; i < WifiMetrics.MAX_WIFI_USABILITY_STATS_PER_TYPE_TO_UPLOAD; i++) {
- assertEquals(WifiMetrics.MAX_WIFI_USABILITY_STATS_ENTRIES_LIST_SIZE,
- mDecodedProto.wifiUsabilityStatsList[2 * i].stats.length);
- assertEquals(2, mDecodedProto.wifiUsabilityStatsList[2 * i + 1].stats.length);
- }
+ assertEquals(WifiMetrics.MAX_WIFI_USABILITY_STATS_ENTRIES_RING_BUFFER_SIZE,
+ mWifiMetrics.mWifiUsabilityStatsEntriesRingBuffer.size());
+
+ // Should not grow further.
+ mWifiMetrics.logAsynchronousEvent(TEST_IFACE_NAME,
+ WifiUsabilityStatsEntry.CAPTURE_EVENT_TYPE_RSSI_POLLING_ENABLED);
+ assertEquals(WifiMetrics.MAX_WIFI_USABILITY_STATS_ENTRIES_RING_BUFFER_SIZE,
+ mWifiMetrics.mWifiUsabilityStatsEntriesRingBuffer.size());
}
/**
- * Verify that LABEL_GOOD stats are not generated more frequently than
- * |MIN_WIFI_GOOD_USABILITY_STATS_PERIOD_MS|
- * @throws Exception
+ * Verify that firmware alerts appear in the ring buffer.
*/
@Test
- public void testWifiUsabilityStatsLabelGoodHasMinimumPeriod() throws Exception {
- // simulate adding LABEL_GOOD WifiUsabilityStats 1 time over the max limit
- WifiLinkLayerStats stats = new WifiLinkLayerStats();
- for (int j = 0; j < 2; j++) {
- stats = addGoodWifiUsabilityStats(stats);
- stats = addBadWifiUsabilityStats(stats);
- }
- dumpProtoAndDeserialize();
- assertEquals(2, mDecodedProto.wifiUsabilityStatsList.length);
- }
+ public void testLogFirmwareAlert() throws Exception {
+ when(mClock.getElapsedSinceBootMillis()).thenReturn((long) 123);
- /**
- * Verify that LABEL_BAD stats are not generated more frequently than |MIN_DATA_STALL_WAIT_MS|
- * @throws Exception
- */
- @Test
- public void testWifiUsabilityStatsLabelBadNotGeneratedGapLessThanMinimum() throws Exception {
- // simulate adding two LABEL_GOOD WifiUsabilityStats
- WifiInfo info = mock(WifiInfo.class);
- when(info.getRssi()).thenReturn(nextRandInt());
- when(info.getLinkSpeed()).thenReturn(nextRandInt());
- WifiLinkLayerStats stats1 = new WifiLinkLayerStats();
- WifiLinkLayerStats stats2 = new WifiLinkLayerStats();
- stats1 = addGoodWifiUsabilityStats(stats1);
- stats2.timeStampInMs = stats1.timeStampInMs
- + WifiMetrics.MIN_WIFI_GOOD_USABILITY_STATS_PERIOD_MS;
- addGoodWifiUsabilityStats(stats2);
+ // Buffer starts out empty.
+ assertEquals(0, mWifiMetrics.mWifiUsabilityStatsEntriesRingBuffer.size());
- WifiLinkLayerStats stats3 = new WifiLinkLayerStats();
- WifiLinkLayerStats stats4 = new WifiLinkLayerStats();
- for (int i = 0; i < WifiMetrics.MAX_WIFI_USABILITY_STATS_ENTRIES_LIST_SIZE - 1; i++) {
- mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, stats3);
- stats3 = nextRandomStats(stats3);
- }
- mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, stats3);
- mWifiMetrics.addToWifiUsabilityStatsList(TEST_IFACE_NAME, WifiUsabilityStats.LABEL_BAD,
- WifiUsabilityStats.TYPE_DATA_STALL_BAD_TX, -1);
- for (int i = 0; i < WifiMetrics.MAX_WIFI_USABILITY_STATS_ENTRIES_LIST_SIZE - 1; i++) {
- mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, stats4);
- stats4 = nextRandomStats(stats4);
- }
- stats4.timeStampInMs = stats3.timeStampInMs - 1 + WifiMetrics.MIN_DATA_STALL_WAIT_MS;
- mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, stats4);
- mWifiMetrics.addToWifiUsabilityStatsList(TEST_IFACE_NAME, WifiUsabilityStats.LABEL_BAD,
- WifiUsabilityStats.TYPE_DATA_STALL_BAD_TX, -1);
- dumpProtoAndDeserialize();
- assertEquals(2, mDecodedProto.wifiUsabilityStatsList.length);
- }
+ // Add record
+ mWifiMetrics.logFirmwareAlert(TEST_IFACE_NAME, 789);
- /**
- * Verify that LABEL_BAD stats are generated if timestamp gap is larger than
- * |MIN_DATA_STALL_WAIT_MS|
- * @throws Exception
- */
- @Test
- public void testWifiUsabilityStatsLabelBadGeneratedGapLargerThanMinimum() throws Exception {
- // simulate adding two LABEL_GOOD WifiUsabilityStats
- WifiInfo info = mock(WifiInfo.class);
- when(info.getRssi()).thenReturn(nextRandInt());
- when(info.getLinkSpeed()).thenReturn(nextRandInt());
- WifiLinkLayerStats stats1 = new WifiLinkLayerStats();
- WifiLinkLayerStats stats2 = new WifiLinkLayerStats();
- stats1 = addGoodWifiUsabilityStats(stats1);
- stats2.timeStampInMs = stats1.timeStampInMs
- + WifiMetrics.MIN_WIFI_GOOD_USABILITY_STATS_PERIOD_MS;
- addGoodWifiUsabilityStats(stats2);
-
- WifiLinkLayerStats stats3 = new WifiLinkLayerStats();
- WifiLinkLayerStats stats4 = new WifiLinkLayerStats();
- for (int i = 0; i < WifiMetrics.MAX_WIFI_USABILITY_STATS_ENTRIES_LIST_SIZE - 1; i++) {
- mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, stats3);
- stats3 = nextRandomStats(stats3);
- }
- mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, stats3);
- mWifiMetrics.addToWifiUsabilityStatsList(TEST_IFACE_NAME, WifiUsabilityStats.LABEL_BAD,
- WifiUsabilityStats.TYPE_DATA_STALL_BAD_TX, -1);
- for (int i = 0; i < WifiMetrics.MAX_WIFI_USABILITY_STATS_ENTRIES_LIST_SIZE - 1; i++) {
- mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, stats4);
- stats4 = nextRandomStats(stats4);
- }
- stats4.timeStampInMs = stats3.timeStampInMs + 1 + WifiMetrics.MIN_DATA_STALL_WAIT_MS;
- mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, stats4);
- mWifiMetrics.addToWifiUsabilityStatsList(TEST_IFACE_NAME, WifiUsabilityStats.LABEL_BAD,
- WifiUsabilityStats.TYPE_DATA_STALL_BAD_TX, -1);
- dumpProtoAndDeserialize();
- assertEquals(4, mDecodedProto.wifiUsabilityStatsList.length);
+ // Confirm that exactly one record is added and with default subcode.
+ assertEquals(1, mWifiMetrics.mWifiUsabilityStatsEntriesRingBuffer.size());
+ WifiUsabilityStatsEntry actual = mWifiMetrics.mWifiUsabilityStatsEntriesRingBuffer.get(0);
+ assertEquals(123, actual.timeStampMs);
+ assertEquals(WifiUsabilityStatsEntry.CAPTURE_EVENT_TYPE_FIRMWARE_ALERT,
+ actual.captureEventType);
+ assertEquals(789, actual.captureEventTypeSubcode);
}
/**
@@ -4782,7 +4688,8 @@
ActiveModeManager.ROLE_CLIENT_SECONDARY_LONG_LIVED);
mModeChangeCallbackArgumentCaptor.getValue()
.onActiveModeManagerRoleChanged(concreteClientModeManager);
- mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, linkLayerStats);
+ mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, linkLayerStats, false,
+ 0);
verify(mOnWifiUsabilityStatsListener, never()).onWifiUsabilityStats(anyInt(), anyBoolean(),
any());
@@ -4792,7 +4699,8 @@
when(concreteClientModeManager.getRole()).thenReturn(ActiveModeManager.ROLE_CLIENT_PRIMARY);
mModeChangeCallbackArgumentCaptor.getValue()
.onActiveModeManagerRoleChanged(concreteClientModeManager);
- mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, linkLayerStats);
+ mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, linkLayerStats, false,
+ 0);
// Client should get the stats.
verify(mOnWifiUsabilityStatsListener).onWifiUsabilityStats(anyInt(), anyBoolean(),
@@ -4928,7 +4836,8 @@
when(info.getRssi()).thenReturn(nextRandInt());
when(info.getLinkSpeed()).thenReturn(nextRandInt());
WifiLinkLayerStats linkLayerStats = nextRandomStats(new WifiLinkLayerStats());
- mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, linkLayerStats);
+ mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, linkLayerStats, false,
+ 0);
verify(mOnWifiUsabilityStatsListener, never()).onWifiUsabilityStats(anyInt(),
anyBoolean(), any());
@@ -4957,7 +4866,8 @@
when(info.getRssi()).thenReturn(nextRandInt());
when(info.getLinkSpeed()).thenReturn(nextRandInt());
WifiLinkLayerStats linkLayerStats = nextRandomStats(new WifiLinkLayerStats());
- mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, linkLayerStats);
+ mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, linkLayerStats, false,
+ 0);
// Client should not get any message listener add failed.
verify(mOnWifiUsabilityStatsListener, never()).onWifiUsabilityStats(anyInt(),
@@ -4977,52 +4887,13 @@
long eventTimeMs = nextRandInt();
when(mClock.getElapsedSinceBootMillis()).thenReturn(eventTimeMs);
WifiLinkLayerStats stats1 = nextRandomStats(new WifiLinkLayerStats());
- mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, stats1);
+ mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, stats1, false, 0);
- // Add 1 LABEL_GOOD
- WifiLinkLayerStats statsGood = addGoodWifiUsabilityStats(nextRandomStats(stats1));
// Firmware alert occurs
mWifiMetrics.logFirmwareAlert(TEST_IFACE_NAME, 2);
dumpProtoAndDeserialize();
- assertEquals(2, mDecodedProto.wifiUsabilityStatsList.length);
-
- WifiUsabilityStats[] statsList = mDecodedProto.wifiUsabilityStatsList;
- assertEquals(WifiUsabilityStats.LABEL_GOOD, statsList[0].label);
- assertEquals(WifiUsabilityStats.LABEL_BAD, statsList[1].label);
- assertEquals(WifiIsUnusableEvent.TYPE_FIRMWARE_ALERT, statsList[1].triggerType);
- assertEquals(eventTimeMs, statsList[1].timeStampMs);
- assertEquals(2, statsList[1].firmwareAlertCode);
- }
-
- /**
- * Verify that the label and the triggerType of Wifi usability stats are saved correctly
- * during Wifi data stall is triggered.
- * @throws Exception
- */
- @Test
- public void verifyWifiDataStallUpdatesWifiUsabilityMetrics() throws Exception {
- WifiInfo info = mock(WifiInfo.class);
- when(info.getRssi()).thenReturn(nextRandInt());
- when(info.getLinkSpeed()).thenReturn(nextRandInt());
- long eventTimeMs = nextRandInt();
- when(mClock.getElapsedSinceBootMillis()).thenReturn(eventTimeMs);
- WifiLinkLayerStats stats1 = nextRandomStats(new WifiLinkLayerStats());
- mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, stats1);
-
- // Add 1 LABEL_GOOD
- WifiLinkLayerStats statsGood = addGoodWifiUsabilityStats(nextRandomStats(stats1));
- // Wifi data stall occurs
- mWifiMetrics.addToWifiUsabilityStatsList(TEST_IFACE_NAME, WifiUsabilityStats.LABEL_BAD,
- WifiIsUnusableEvent.TYPE_DATA_STALL_BAD_TX, -1);
-
- dumpProtoAndDeserialize();
- assertEquals(2, mDecodedProto.wifiUsabilityStatsList.length);
- WifiUsabilityStats[] statsList = mDecodedProto.wifiUsabilityStatsList;
- assertEquals(WifiUsabilityStats.LABEL_BAD, statsList[1].label);
- assertEquals(WifiIsUnusableEvent.TYPE_DATA_STALL_BAD_TX, statsList[1].triggerType);
- assertEquals(-1, statsList[1].firmwareAlertCode);
- assertEquals(eventTimeMs, statsList[1].timeStampMs);
+ // TODO(b/377723852) Verify asynchronous events are logged correctly
}
/**
@@ -5510,35 +5381,6 @@
}
/**
- * Verify that the label and the triggerType of Wifi usability stats are saved correctly
- * during IP reachability lost message is received.
- * @throws Exception
- */
- @Test
- public void verifyIpReachabilityLostUpdatesWifiUsabilityMetrics() throws Exception {
- WifiInfo info = mock(WifiInfo.class);
- when(info.getRssi()).thenReturn(nextRandInt());
- when(info.getLinkSpeed()).thenReturn(nextRandInt());
- long eventTimeMs = nextRandInt();
- when(mClock.getElapsedSinceBootMillis()).thenReturn(eventTimeMs);
- WifiLinkLayerStats stats1 = nextRandomStats(new WifiLinkLayerStats());
- mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, stats1);
-
- // Add 1 LABEL_GOOD
- WifiLinkLayerStats statsGood = addGoodWifiUsabilityStats(nextRandomStats(stats1));
- // IP reachability lost occurs
- mWifiMetrics.addToWifiUsabilityStatsList(TEST_IFACE_NAME, WifiUsabilityStats.LABEL_BAD,
- WifiUsabilityStats.TYPE_IP_REACHABILITY_LOST, -1);
-
- dumpProtoAndDeserialize();
- assertEquals(2, mDecodedProto.wifiUsabilityStatsList.length);
- WifiUsabilityStats[] statsList = mDecodedProto.wifiUsabilityStatsList;
- assertEquals(WifiUsabilityStats.LABEL_BAD, statsList[1].label);
- assertEquals(WifiUsabilityStats.TYPE_IP_REACHABILITY_LOST, statsList[1].triggerType);
- assertEquals(eventTimeMs, statsList[1].timeStampMs);
- }
-
- /**
* Test the WifiLock active session statistics
*/
@Test
@@ -5727,21 +5569,6 @@
}
/**
- * Verify that LABEL_GOOD stats are generated if Wifi score breaches low and there
- * is no WifiIsUnusableEvent in MIN_SCORE_BREACH_TO_GOOD_STATS_WAIT_TIME_MS millis
- * @throws Exception
- */
- @Test
- public void testGoodStatsAreGeneratedByWifiScoreBreachLow() throws Exception {
- // The elapsed time falls into the interval for adding good stats
- createTestForDataCollectionByScoreBreach(
- WifiMetrics.MIN_SCORE_BREACH_TO_GOOD_STATS_WAIT_TIME_MS + 1,
- false, true);
- dumpProtoAndDeserialize();
- assertEquals(2, mDecodedProto.wifiUsabilityStatsList.length);
- }
-
- /**
* Verify that LABEL_GOOD stats are not generated if Wifi score breaches low and the checking
* time is less than MIN_SCORE_BREACH_TO_GOOD_STATS_WAIT_TIME_MS millis
* @throws Exception
@@ -5787,21 +5614,6 @@
}
/**
- * Verify that LABEL_GOOD stats are generated if Wifi usability score breaches low and there
- * is no WifiIsUnusableEvent in MIN_SCORE_BREACH_TO_GOOD_STATS_WAIT_TIME_MS millis
- * @throws Exception
- */
- @Test
- public void testGoodStatsAreGeneratedByWifiUsabilityScoreBreachLow() throws Exception {
- // The elapsed time falls into the interval for adding good stats
- createTestForDataCollectionByScoreBreach(
- WifiMetrics.MIN_SCORE_BREACH_TO_GOOD_STATS_WAIT_TIME_MS + 1,
- false, false);
- dumpProtoAndDeserialize();
- assertEquals(2, mDecodedProto.wifiUsabilityStatsList.length);
- }
-
- /**
* Verify that LABEL_GOOD stats are not generated if Wifi usability score breaches low and
* the checking time is less than MIN_SCORE_BREACH_TO_GOOD_STATS_WAIT_TIME_MS millis
* @throws Exception
@@ -5954,13 +5766,13 @@
WifiIsUnusableEvent.TYPE_DATA_STALL_BAD_TX, -1);
}
when(mClock.getElapsedSinceBootMillis()).thenReturn(elapsedTimeAfterBreach);
- mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, stats2);
+ mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, stats2, false, 0);
}
// Simulate adding one LABEL_BAD WifiUsabilityStats
private void addOneBadWifiUsabilityStats(WifiInfo info) {
WifiLinkLayerStats stats1 = new WifiLinkLayerStats();
- mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, stats1);
+ mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, stats1, false, 0);
mWifiMetrics.addToWifiUsabilityStatsList(TEST_IFACE_NAME, WifiUsabilityStats.LABEL_BAD,
WifiUsabilityStats.TYPE_DATA_STALL_BAD_TX, -1);
}
@@ -5970,13 +5782,13 @@
int upper = WifiMetrics.LOW_WIFI_SCORE + 7;
int lower = WifiMetrics.LOW_WIFI_SCORE - 8;
mWifiMetrics.incrementWifiScoreCount(TEST_IFACE_NAME, upper);
- mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, stats2);
+ mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, stats2, false, 0);
stats2 = nextRandomStats(stats2);
long timeMs = 0;
when(mClock.getElapsedSinceBootMillis()).thenReturn(timeMs);
// Wifi score breaches low
mWifiMetrics.incrementWifiScoreCount(TEST_IFACE_NAME, lower);
- mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, stats2);
+ mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, stats2, false, 0);
stats2 = nextRandomStats(stats2);
return stats2;
}
@@ -5987,13 +5799,13 @@
int upper = WifiMetrics.LOW_WIFI_USABILITY_SCORE + 7;
int lower = WifiMetrics.LOW_WIFI_USABILITY_SCORE - 8;
mWifiMetrics.incrementWifiUsabilityScoreCount(TEST_IFACE_NAME, 1, upper, 30);
- mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, stats2);
+ mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, stats2, false, 0);
stats2 = nextRandomStats(stats2);
long timeMs = 0;
when(mClock.getElapsedSinceBootMillis()).thenReturn(timeMs);
// Wifi usability score breaches low
mWifiMetrics.incrementWifiUsabilityScoreCount(TEST_IFACE_NAME, 2, lower, 30);
- mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, stats2);
+ mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, stats2, false, 0);
stats2 = nextRandomStats(stats2);
return stats2;
}
@@ -6037,7 +5849,7 @@
when(info.getRssi()).thenReturn(nextRandInt());
when(info.getLinkSpeed()).thenReturn(nextRandInt());
WifiLinkLayerStats stats1 = nextRandomStats(new WifiLinkLayerStats());
- mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, stats1);
+ mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, stats1, false, 0);
// Add 1 LABEL_GOOD
WifiLinkLayerStats statsGood = addGoodWifiUsabilityStats(nextRandomStats(stats1));
@@ -7618,11 +7430,13 @@
WifiMetrics.SessionData currentSession =
new WifiMetrics.SessionData(connectionEvent, "", (long) 1000, 0, 0);
mWifiMetrics.mCurrentSession = currentSession;
+ mWifiMetrics.mLastScreenOffTimeMillis = 1000;
+ mWifiMetrics.mLastIgnoredPollTimeMillis = 3000;
+ mWifiMetrics.updateWiFiEvaluationAndScorerStats(true, null, null);
mWifiMetrics.logScorerPredictionResult(false, false, false, POLLING_INTERVAL_DEFAULT,
WIFI_IS_UNUSABLE_REPORTED__WIFI_PREDICTED_USABILITY_STATE__WIFI_USABILITY_PREDICTED_USABLE,
- WIFI_IS_UNUSABLE_REPORTED__WIFI_PREDICTED_USABILITY_STATE__WIFI_USABILITY_PREDICTED_USABLE,
- true, mWifiInfo, mCapabilities);
+ WIFI_IS_UNUSABLE_REPORTED__WIFI_PREDICTED_USABILITY_STATE__WIFI_USABILITY_PREDICTED_USABLE);
ExtendedMockito.verify(() -> WifiStatsLog.write_non_chained(
SCORER_PREDICTION_RESULT_REPORTED,
@@ -7632,7 +7446,7 @@
false,
SCORER_PREDICTION_RESULT_REPORTED__DEVICE_STATE__STATE_NO_CELLULAR_MODEM,
POLLING_INTERVAL_DEFAULT,
- SCORER_PREDICTION_RESULT_REPORTED__WIFI_FRAMEWORK_STATE__FRAMEWORK_STATE_AWAKENING,
+ SCORER_PREDICTION_RESULT_REPORTED__WIFI_FRAMEWORK_STATE__FRAMEWORK_STATE_LINGERING,
SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_NETWORK_CAPABILITIES_DS__UNKNOWN,
SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_NETWORK_CAPABILITIES_US__UNKNOWN,
SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_THROUGHPUT_PREDICTOR_DS__UNKNOWN,
@@ -7650,11 +7464,13 @@
WifiMetrics.SessionData currentSession =
new WifiMetrics.SessionData(connectionEvent, "", (long) 1000, 0, 0);
mWifiMetrics.mCurrentSession = currentSession;
+ mWifiMetrics.mLastScreenOffTimeMillis = 1000;
+ mWifiMetrics.mLastIgnoredPollTimeMillis = 3000;
+ mWifiMetrics.updateWiFiEvaluationAndScorerStats(true, null, null);
mWifiMetrics.logScorerPredictionResult(false, false, false, POLLING_INTERVAL_DEFAULT,
WIFI_IS_UNUSABLE_REPORTED__WIFI_PREDICTED_USABILITY_STATE__WIFI_USABILITY_PREDICTED_USABLE,
- WIFI_IS_UNUSABLE_REPORTED__WIFI_PREDICTED_USABILITY_STATE__WIFI_USABILITY_PREDICTED_USABLE,
- true, mWifiInfo, mCapabilities);
+ WIFI_IS_UNUSABLE_REPORTED__WIFI_PREDICTED_USABILITY_STATE__WIFI_USABILITY_PREDICTED_USABLE);
ExtendedMockito.verify(() -> WifiStatsLog.write_non_chained(
SCORER_PREDICTION_RESULT_REPORTED,
@@ -7664,7 +7480,7 @@
false,
SCORER_PREDICTION_RESULT_REPORTED__DEVICE_STATE__STATE_NO_CELLULAR_MODEM,
POLLING_INTERVAL_DEFAULT,
- SCORER_PREDICTION_RESULT_REPORTED__WIFI_FRAMEWORK_STATE__FRAMEWORK_STATE_AWAKENING,
+ SCORER_PREDICTION_RESULT_REPORTED__WIFI_FRAMEWORK_STATE__FRAMEWORK_STATE_LINGERING,
SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_NETWORK_CAPABILITIES_DS__UNKNOWN,
SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_NETWORK_CAPABILITIES_US__UNKNOWN,
SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_THROUGHPUT_PREDICTOR_DS__UNKNOWN,
@@ -7678,7 +7494,7 @@
false,
SCORER_PREDICTION_RESULT_REPORTED__DEVICE_STATE__STATE_NO_CELLULAR_MODEM,
POLLING_INTERVAL_DEFAULT,
- SCORER_PREDICTION_RESULT_REPORTED__WIFI_FRAMEWORK_STATE__FRAMEWORK_STATE_AWAKENING,
+ SCORER_PREDICTION_RESULT_REPORTED__WIFI_FRAMEWORK_STATE__FRAMEWORK_STATE_LINGERING,
SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_NETWORK_CAPABILITIES_DS__UNKNOWN,
SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_NETWORK_CAPABILITIES_US__UNKNOWN,
SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_THROUGHPUT_PREDICTOR_DS__UNKNOWN,
@@ -7695,11 +7511,13 @@
WifiMetrics.SessionData currentSession =
new WifiMetrics.SessionData(connectionEvent, "", (long) 1000, 0, 0);
mWifiMetrics.mCurrentSession = currentSession;
+ mWifiMetrics.mLastScreenOffTimeMillis = 1000;
+ mWifiMetrics.mLastIgnoredPollTimeMillis = 3000;
+ mWifiMetrics.updateWiFiEvaluationAndScorerStats(true, null, null);
mWifiMetrics.logScorerPredictionResult(false, false, false, POLLING_INTERVAL_NOT_DEFAULT,
WIFI_IS_UNUSABLE_REPORTED__WIFI_PREDICTED_USABILITY_STATE__WIFI_USABILITY_PREDICTED_USABLE,
- WIFI_IS_UNUSABLE_REPORTED__WIFI_PREDICTED_USABILITY_STATE__WIFI_USABILITY_PREDICTED_USABLE,
- true, mWifiInfo, mCapabilities);
+ WIFI_IS_UNUSABLE_REPORTED__WIFI_PREDICTED_USABILITY_STATE__WIFI_USABILITY_PREDICTED_USABLE);
ExtendedMockito.verify(() -> WifiStatsLog.write_non_chained(
SCORER_PREDICTION_RESULT_REPORTED,
@@ -7709,7 +7527,7 @@
false,
SCORER_PREDICTION_RESULT_REPORTED__DEVICE_STATE__STATE_NO_CELLULAR_MODEM,
POLLING_INTERVAL_NOT_DEFAULT,
- SCORER_PREDICTION_RESULT_REPORTED__WIFI_FRAMEWORK_STATE__FRAMEWORK_STATE_AWAKENING,
+ SCORER_PREDICTION_RESULT_REPORTED__WIFI_FRAMEWORK_STATE__FRAMEWORK_STATE_LINGERING,
SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_NETWORK_CAPABILITIES_DS__UNKNOWN,
SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_NETWORK_CAPABILITIES_US__UNKNOWN,
SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_THROUGHPUT_PREDICTOR_DS__UNKNOWN,
@@ -7726,14 +7544,15 @@
WifiMetrics.SessionData currentSession =
new WifiMetrics.SessionData(connectionEvent, "", (long) 1000, 0, 0);
mWifiMetrics.mCurrentSession = currentSession;
+ mWifiMetrics.mLastScreenOffTimeMillis = 1000;
+ mWifiMetrics.mLastIgnoredPollTimeMillis = 3000;
mWifiMetrics.logWifiIsUnusableEvent(TEST_IFACE_NAME,
WifiIsUnusableEvent.TYPE_DATA_STALL_BAD_TX);
-
+ mWifiMetrics.updateWiFiEvaluationAndScorerStats(true, null, null);
mWifiMetrics.logScorerPredictionResult(false, false, false, POLLING_INTERVAL_DEFAULT,
WIFI_IS_UNUSABLE_REPORTED__WIFI_PREDICTED_USABILITY_STATE__WIFI_USABILITY_PREDICTED_USABLE,
- WIFI_IS_UNUSABLE_REPORTED__WIFI_PREDICTED_USABILITY_STATE__WIFI_USABILITY_PREDICTED_USABLE,
- true, mWifiInfo, mCapabilities);
+ WIFI_IS_UNUSABLE_REPORTED__WIFI_PREDICTED_USABILITY_STATE__WIFI_USABILITY_PREDICTED_USABLE);
ExtendedMockito.verify(() -> WifiStatsLog.write_non_chained(
SCORER_PREDICTION_RESULT_REPORTED,
@@ -7743,7 +7562,7 @@
false,
SCORER_PREDICTION_RESULT_REPORTED__DEVICE_STATE__STATE_NO_CELLULAR_MODEM,
POLLING_INTERVAL_DEFAULT,
- SCORER_PREDICTION_RESULT_REPORTED__WIFI_FRAMEWORK_STATE__FRAMEWORK_STATE_AWAKENING,
+ SCORER_PREDICTION_RESULT_REPORTED__WIFI_FRAMEWORK_STATE__FRAMEWORK_STATE_LINGERING,
SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_NETWORK_CAPABILITIES_DS__UNKNOWN,
SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_NETWORK_CAPABILITIES_US__UNKNOWN,
SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_THROUGHPUT_PREDICTOR_DS__UNKNOWN,
@@ -7760,11 +7579,13 @@
WifiMetrics.SessionData currentSession =
new WifiMetrics.SessionData(connectionEvent, "", (long) 1000, 0, 0);
mWifiMetrics.mCurrentSession = currentSession;
+ mWifiMetrics.mLastScreenOffTimeMillis = 1000;
+ mWifiMetrics.mLastIgnoredPollTimeMillis = 3000;
+ mWifiMetrics.updateWiFiEvaluationAndScorerStats(true, null, null);
mWifiMetrics.logScorerPredictionResult(false, false, false, POLLING_INTERVAL_DEFAULT,
WIFI_IS_UNUSABLE_REPORTED__WIFI_PREDICTED_USABILITY_STATE__WIFI_USABILITY_PREDICTED_USABLE,
- WIFI_IS_UNUSABLE_REPORTED__WIFI_PREDICTED_USABILITY_STATE__WIFI_USABILITY_PREDICTED_USABLE,
- true, mWifiInfo, mCapabilities);
+ WIFI_IS_UNUSABLE_REPORTED__WIFI_PREDICTED_USABILITY_STATE__WIFI_USABILITY_PREDICTED_USABLE);
ExtendedMockito.verify(() -> WifiStatsLog.write_non_chained(
SCORER_PREDICTION_RESULT_REPORTED,
@@ -7774,7 +7595,7 @@
true,
SCORER_PREDICTION_RESULT_REPORTED__DEVICE_STATE__STATE_NO_CELLULAR_MODEM,
POLLING_INTERVAL_DEFAULT,
- SCORER_PREDICTION_RESULT_REPORTED__WIFI_FRAMEWORK_STATE__FRAMEWORK_STATE_AWAKENING,
+ SCORER_PREDICTION_RESULT_REPORTED__WIFI_FRAMEWORK_STATE__FRAMEWORK_STATE_LINGERING,
SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_NETWORK_CAPABILITIES_DS__UNKNOWN,
SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_NETWORK_CAPABILITIES_US__UNKNOWN,
SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_THROUGHPUT_PREDICTOR_DS__UNKNOWN,
diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiMulticastLockManagerTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiMulticastLockManagerTest.java
index 8464293..f57f8c4 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/WifiMulticastLockManagerTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/WifiMulticastLockManagerTest.java
@@ -22,8 +22,9 @@
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
+import android.app.ActivityManager;
+import android.content.Context;
import android.os.BatteryStatsManager;
-import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.WorkSource;
@@ -50,6 +51,7 @@
public class WifiMulticastLockManagerTest extends WifiBaseTest {
private static final String WL_1_TAG = "Wakelock-1";
private static final String WL_2_TAG = "Wakelock-2";
+ private static final int TEST_UID = 123;
private TestLooper mLooper;
@Mock ConcreteClientModeManager mClientModeManager;
@@ -58,7 +60,11 @@
@Spy FakeFilterController mFilterController2 = new FakeFilterController();
@Mock BatteryStatsManager mBatteryStats;
@Mock ActiveModeWarden mActiveModeWarden;
+ @Mock Context mContext;
+ @Mock ActivityManager mActivityManager;
@Captor ArgumentCaptor<PrimaryClientModeManagerChangedCallback> mPrimaryChangedCallbackCaptor;
+ @Captor ArgumentCaptor<ActivityManager.OnUidImportanceListener> mUidImportanceListenerCaptor =
+ ArgumentCaptor.forClass(ActivityManager.OnUidImportanceListener.class);
WifiMulticastLockManager mManager;
/**
@@ -78,11 +84,14 @@
when(mClientModeManager2.getRole()).thenReturn(ROLE_CLIENT_SECONDARY_TRANSIENT);
when(mActiveModeWarden.getPrimaryClientModeManager()).thenReturn(mClientModeManager);
+ when(mContext.getSystemService(ActivityManager.class)).thenReturn(mActivityManager);
mManager = new WifiMulticastLockManager(mActiveModeWarden, mBatteryStats,
- mLooper.getLooper());
+ mLooper.getLooper(), mContext);
verify(mActiveModeWarden).registerPrimaryClientModeManagerChangedCallback(
mPrimaryChangedCallbackCaptor.capture());
+ verify(mActivityManager).addOnUidImportanceListener(
+ mUidImportanceListenerCaptor.capture(), anyInt());
}
/**
@@ -91,7 +100,7 @@
@Test
public void noLocks() {
assertFalse(mManager.isMulticastEnabled());
- mManager.initializeFiltering();
+ mManager.startFilteringMulticastPackets();
verify(mFilterController, times(1)).startFilteringMulticastPackets();
}
@@ -101,21 +110,21 @@
@Test
public void oneLock() throws RemoteException {
IBinder binder = mock(IBinder.class);
- mManager.acquireLock(binder, WL_1_TAG);
+ mManager.acquireLock(TEST_UID, binder, WL_1_TAG);
assertTrue(mManager.isMulticastEnabled());
verify(mFilterController).stopFilteringMulticastPackets();
- mManager.initializeFiltering();
+ mManager.startFilteringMulticastPackets();
verify(mFilterController, times(0)).startFilteringMulticastPackets();
ArgumentCaptor<WorkSource> wsCaptor = ArgumentCaptor.forClass(WorkSource.class);
verify(mBatteryStats).reportWifiMulticastEnabled(wsCaptor.capture());
assertNotNull(wsCaptor.getValue());
- assertEquals(Binder.getCallingUid(), wsCaptor.getValue().getAttributionUid());
+ assertEquals(TEST_UID, wsCaptor.getValue().getAttributionUid());
verify(mBatteryStats, times(0)).reportWifiMulticastDisabled(any());
- mManager.releaseLock(WL_1_TAG);
+ mManager.releaseLock(TEST_UID, binder, WL_1_TAG);
verify(mBatteryStats).reportWifiMulticastDisabled(wsCaptor.capture());
assertNotNull(wsCaptor.getValue());
- assertEquals(Binder.getCallingUid(), wsCaptor.getValue().getAttributionUid());
+ assertEquals(TEST_UID, wsCaptor.getValue().getAttributionUid());
assertFalse(mManager.isMulticastEnabled());
}
@@ -151,7 +160,7 @@
assertTrue(mFilterController2.isFilteringStarted());
IBinder binder = mock(IBinder.class);
- mManager.acquireLock(binder, WL_1_TAG);
+ mManager.acquireLock(TEST_UID, binder, WL_1_TAG);
assertTrue(mManager.isMulticastEnabled());
// CMM1 filtering stopped
assertFalse(mFilterController.isFilteringStarted());
@@ -172,7 +181,7 @@
// CMM2 filter stopped
assertFalse(mFilterController2.isFilteringStarted());
- mManager.releaseLock(WL_1_TAG);
+ mManager.releaseLock(TEST_UID, binder, WL_1_TAG);
assertFalse(mManager.isMulticastEnabled());
// CMM1 filter started
assertTrue(mFilterController.isFilteringStarted());
@@ -186,15 +195,15 @@
@Test
public void oneLock_wrongName() throws RemoteException {
IBinder binder = mock(IBinder.class);
- mManager.acquireLock(binder, WL_1_TAG);
+ mManager.acquireLock(TEST_UID, binder, WL_1_TAG);
assertTrue(mManager.isMulticastEnabled());
verify(mFilterController).stopFilteringMulticastPackets();
- mManager.initializeFiltering();
+ mManager.startFilteringMulticastPackets();
verify(mFilterController, never()).startFilteringMulticastPackets();
verify(mBatteryStats).reportWifiMulticastEnabled(any());
verify(mBatteryStats, never()).reportWifiMulticastDisabled(any());
- mManager.releaseLock(WL_2_TAG);
+ mManager.releaseLock(TEST_UID, binder, WL_2_TAG);
verify(mBatteryStats, never()).reportWifiMulticastDisabled(any());
assertTrue(mManager.isMulticastEnabled());
}
@@ -209,25 +218,25 @@
InOrder inOrderHandler = inOrder(mFilterController);
InOrder inOrderBatteryStats = inOrder(mBatteryStats);
- mManager.acquireLock(binder, WL_1_TAG);
+ mManager.acquireLock(TEST_UID, binder, WL_1_TAG);
inOrderHandler.verify(mFilterController).stopFilteringMulticastPackets();
inOrderBatteryStats.verify(mBatteryStats).reportWifiMulticastEnabled(any());
assertTrue(mManager.isMulticastEnabled());
- mManager.acquireLock(binder, WL_2_TAG);
+ mManager.acquireLock(TEST_UID, binder, WL_2_TAG);
inOrderHandler.verify(mFilterController).stopFilteringMulticastPackets();
inOrderBatteryStats.verify(mBatteryStats).reportWifiMulticastEnabled(any());
assertTrue(mManager.isMulticastEnabled());
- mManager.initializeFiltering();
+ mManager.startFilteringMulticastPackets();
inOrderHandler.verify(mFilterController, never()).startFilteringMulticastPackets();
- mManager.releaseLock(WL_2_TAG);
+ mManager.releaseLock(TEST_UID, binder, WL_2_TAG);
inOrderHandler.verify(mFilterController, never()).startFilteringMulticastPackets();
inOrderBatteryStats.verify(mBatteryStats).reportWifiMulticastDisabled(any());
assertTrue(mManager.isMulticastEnabled());
- mManager.releaseLock(WL_1_TAG);
+ mManager.releaseLock(TEST_UID, binder, WL_1_TAG);
inOrderHandler.verify(mFilterController).startFilteringMulticastPackets();
inOrderBatteryStats.verify(mBatteryStats).reportWifiMulticastDisabled(any());
assertFalse(mManager.isMulticastEnabled());
@@ -243,27 +252,131 @@
InOrder inOrderHandler = inOrder(mFilterController);
InOrder inOrderBatteryStats = inOrder(mBatteryStats);
- mManager.acquireLock(binder, WL_1_TAG);
+ mManager.acquireLock(TEST_UID, binder, WL_1_TAG);
inOrderHandler.verify(mFilterController).stopFilteringMulticastPackets();
inOrderBatteryStats.verify(mBatteryStats).reportWifiMulticastEnabled(any());
assertTrue(mManager.isMulticastEnabled());
- mManager.acquireLock(binder, WL_2_TAG);
+ mManager.acquireLock(TEST_UID, binder, WL_2_TAG);
inOrderHandler.verify(mFilterController).stopFilteringMulticastPackets();
inOrderBatteryStats.verify(mBatteryStats).reportWifiMulticastEnabled(any());
assertTrue(mManager.isMulticastEnabled());
- mManager.initializeFiltering();
+ mManager.startFilteringMulticastPackets();
inOrderHandler.verify(mFilterController, never()).startFilteringMulticastPackets();
- mManager.releaseLock(WL_1_TAG);
+ mManager.releaseLock(TEST_UID, binder, WL_1_TAG);
inOrderHandler.verify(mFilterController, never()).startFilteringMulticastPackets();
inOrderBatteryStats.verify(mBatteryStats).reportWifiMulticastDisabled(any());
assertTrue(mManager.isMulticastEnabled());
- mManager.releaseLock(WL_2_TAG);
+ mManager.releaseLock(TEST_UID, binder, WL_2_TAG);
inOrderHandler.verify(mFilterController).startFilteringMulticastPackets();
inOrderBatteryStats.verify(mBatteryStats).reportWifiMulticastDisabled(any());
assertFalse(mManager.isMulticastEnabled());
}
+
+ /**
+ * Verify the behavior when two separate locks are created using the same tag.
+ *
+ * Since locks are uniquely identified by (binder, tag), we expect that multicast is
+ * enabled until both locks have been released.
+ */
+ @Test
+ public void testMultipleLocksWithSameTag() throws RemoteException {
+ IBinder binder1 = mock(IBinder.class);
+ IBinder binder2 = mock(IBinder.class);
+
+ // Both acquired locks have the same tag
+ mManager.acquireLock(TEST_UID, binder1, WL_1_TAG);
+ mManager.acquireLock(TEST_UID, binder2, WL_1_TAG);
+ assertTrue(mManager.isMulticastEnabled());
+
+ mManager.releaseLock(TEST_UID, binder1, WL_1_TAG);
+ verify(mBatteryStats, times(1)).reportWifiMulticastDisabled(any());
+ assertTrue(mManager.isMulticastEnabled());
+
+ mManager.releaseLock(TEST_UID, binder2, WL_1_TAG);
+ verify(mBatteryStats, times(2)).reportWifiMulticastDisabled(any());
+ assertFalse(mManager.isMulticastEnabled());
+ }
+
+ /**
+ * Test that mulicast filtering is toggled correctly when the owner of
+ * a single lock transitions between importance levels.
+ */
+ @Test
+ public void testSingleLockActiveStateChange() {
+ IBinder binder = mock(IBinder.class);
+ mManager.acquireLock(TEST_UID, binder, WL_1_TAG);
+ assertTrue(mManager.isMulticastEnabled());
+ verify(mFilterController).stopFilteringMulticastPackets();
+
+ // Transition UID to low importance
+ mUidImportanceListenerCaptor.getValue().onUidImportance(
+ TEST_UID, ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED);
+ mLooper.dispatchAll();
+ assertFalse(mManager.isMulticastEnabled());
+ verify(mFilterController).startFilteringMulticastPackets();
+
+ // Transition UID to high importance
+ mUidImportanceListenerCaptor.getValue().onUidImportance(
+ TEST_UID, ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND);
+ mLooper.dispatchAll();
+ assertTrue(mManager.isMulticastEnabled());
+ verify(mFilterController, times(2)).stopFilteringMulticastPackets();
+
+ mManager.releaseLock(TEST_UID, binder, WL_1_TAG);
+ assertFalse(mManager.isMulticastEnabled());
+ verify(mFilterController, times(2)).startFilteringMulticastPackets();
+ }
+
+ /**
+ * Test that mulicast filtering is toggled correctly when multiple lock owners
+ * transition between importance levels.
+ */
+ @Test
+ public void testMultipleOwnersActiveStateChange() {
+ int uid1 = TEST_UID;
+ int uid2 = TEST_UID + 1;
+ IBinder binder1 = mock(IBinder.class);
+ IBinder binder2 = mock(IBinder.class);
+
+ mManager.acquireLock(uid1, binder1, WL_1_TAG);
+ mManager.acquireLock(uid2, binder2, WL_2_TAG);
+ assertTrue(mManager.isMulticastEnabled());
+ verify(mFilterController, times(2)).stopFilteringMulticastPackets();
+
+ // Transition UID 1 to low importance. Since UID 2 is still active,
+ // multicast should still be enabled.
+ mUidImportanceListenerCaptor.getValue().onUidImportance(
+ uid1, ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED);
+ mLooper.dispatchAll();
+ assertTrue(mManager.isMulticastEnabled());
+ verify(mFilterController, never()).startFilteringMulticastPackets();
+
+ // Transition UID 2 to low importance. Since no lock owners are active,
+ // multicast should be disabled.
+ mUidImportanceListenerCaptor.getValue().onUidImportance(
+ uid2, ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED);
+ mLooper.dispatchAll();
+ assertFalse(mManager.isMulticastEnabled());
+ verify(mFilterController).startFilteringMulticastPackets();
+
+ // Transition UID 2 back to high importance. Multicast should be re-enabled.
+ mUidImportanceListenerCaptor.getValue().onUidImportance(
+ uid2, ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND);
+ mLooper.dispatchAll();
+ assertTrue(mManager.isMulticastEnabled());
+ verify(mFilterController, times(3)).stopFilteringMulticastPackets();
+
+ // Release the lock held by UID 1. An active lock is still held by UID 2.
+ mManager.releaseLock(uid1, binder1, WL_1_TAG);
+ assertTrue(mManager.isMulticastEnabled());
+
+ // Release the lock held by UID 2. No locks are active.
+ mManager.releaseLock(uid2, binder2, WL_2_TAG);
+ assertFalse(mManager.isMulticastEnabled());
+ verify(mFilterController, times(2)).startFilteringMulticastPackets();
+ }
}
diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiNativeInterfaceManagementTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiNativeInterfaceManagementTest.java
index e2806fe..6b1de98 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/WifiNativeInterfaceManagementTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/WifiNativeInterfaceManagementTest.java
@@ -40,11 +40,13 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.withSettings;
import android.app.test.MockAnswerUtil;
import android.net.wifi.OuiKeyedData;
import android.net.wifi.SoftApConfiguration;
import android.net.wifi.WifiContext;
+import android.net.wifi.WifiMigration;
import android.net.wifi.WifiScanner;
import android.net.wifi.nl80211.WifiNl80211Manager;
import android.os.Handler;
@@ -53,6 +55,7 @@
import androidx.test.filters.SmallTest;
+import com.android.dx.mockito.inline.extended.ExtendedMockito;
import com.android.modules.utils.build.SdkLevel;
import com.android.server.wifi.HalDeviceManager.InterfaceDestroyedListener;
import com.android.server.wifi.WifiNative.SupplicantDeathEventHandler;
@@ -61,6 +64,7 @@
import com.android.server.wifi.p2p.WifiP2pNative;
import com.android.server.wifi.util.NetdWrapper;
import com.android.server.wifi.util.NetdWrapper.NetdEventObserver;
+import com.android.wifi.flags.Flags;
import com.android.wifi.resources.R;
import org.junit.After;
@@ -70,6 +74,7 @@
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.mockito.MockitoSession;
import java.util.ArrayList;
import java.util.BitSet;
@@ -85,6 +90,7 @@
private static final String IFACE_NAME_0 = "mockWlan0";
private static final String IFACE_NAME_1 = "mockWlan1";
private static final String SELF_RECOVERY_IFACE_NAME = "mockWlan2";
+ private static final String IFACE_NAME_AWARE = "MockAware";
private static final WorkSource TEST_WORKSOURCE = new WorkSource();
private static final long[] TEST_SUPPORTED_FEATURES = new long[]{ 0 };
private static final int STA_FAILURE_CODE_START_DAEMON = 1;
@@ -127,6 +133,7 @@
@Mock private SoftApManager mSoftApManager;
@Mock private WifiNanIface mActiveWifiNanIface;
@Mock DeviceConfigFacade mDeviceConfigFacade;
+ private MockitoSession mSession;
private TestLooper mLooper;
private WifiNative.Iface mActiveP2pIface;
@@ -214,7 +221,8 @@
when(mHostapdHal.isInitializationStarted()).thenReturn(false);
when(mHostapdHal.isInitializationComplete()).thenReturn(true);
when(mHostapdHal.startDaemon()).thenReturn(true);
- when(mHostapdHal.addAccessPoint(any(), any(), anyBoolean(), any())).thenReturn(true);
+ when(mHostapdHal.addAccessPoint(any(), any(), anyBoolean(),
+ anyBoolean(), any(), any())).thenReturn(true);
when(mHostapdHal.removeAccessPoint(any())).thenReturn(true);
when(mHostapdHal.registerApCallback(any(), any())).thenReturn(true);
@@ -241,6 +249,13 @@
eq(WifiSettingsConfigStore.WIFI_NATIVE_SUPPORTED_STA_BANDS)))
.thenReturn(TEST_SUPPORTED_BANDS);
+ mSession = ExtendedMockito.mockitoSession()
+ .mockStatic(Flags.class, withSettings().lenient())
+ .mockStatic(WifiMigration.class, withSettings().lenient())
+ .startMocking();
+ when(Flags.rsnOverriding()).thenReturn(false);
+ when(mActiveWifiNanIface.getName()).thenReturn(IFACE_NAME_AWARE);
+
mInOrder = inOrder(mWifiVendorHal, mWificondControl, mSupplicantStaIfaceHal, mHostapdHal,
mWifiMonitor, mNetdWrapper, mIfaceCallback0, mIfaceCallback1, mIfaceEventCallback0,
mWifiMetrics, mWifiP2pNative);
@@ -263,6 +278,9 @@
@After
public void tearDown() throws Exception {
+ if (mSession != null) {
+ mSession.finishMocking();
+ }
verifyNoMoreInteractions(mWifiVendorHal, mWificondControl, mSupplicantStaIfaceHal,
mHostapdHal, mWifiMonitor, mNetdWrapper, mIfaceCallback0, mIfaceCallback1,
mIfaceEventCallback0, mWifiMetrics);
@@ -562,7 +580,7 @@
}).when(mWifiVendorHal).createApIface(any(), any(), anyInt(), eq(false), any(), anyList());
assertEquals(IFACE_NAME_0, mWifiNative.setupInterfaceForSoftApMode(mIfaceCallback1,
TEST_WORKSOURCE, SoftApConfiguration.BAND_2GHZ, false, mSoftApManager,
- new ArrayList<>()));
+ new ArrayList<>(), false));
validateHostApdStart();
// Creation of AP interface should trigger the STA interface destroy
@@ -881,7 +899,7 @@
assertEquals(IFACE_NAME_0, mWifiNative.setupInterfaceForSoftApMode(mIfaceCallback1,
TEST_WORKSOURCE, SoftApConfiguration.BAND_2GHZ, false, mSoftApManager,
- new ArrayList<>()));
+ new ArrayList<>(), false));
validateHostApdStart();
// Creation of AP interface should trigger the STA interface destroy
validateOnDestroyedClientInterface(
@@ -973,11 +991,14 @@
// Start softap
assertEquals(SoftApManager.START_RESULT_SUCCESS,
mWifiNative.startSoftAp(IFACE_NAME_0, new SoftApConfiguration.Builder().build(),
- true, mock(WifiNative.SoftApHalCallback.class)));
+ true, mock(WifiNative.SoftApHalCallback.class), false));
mInOrder.verify(mHostapdHal).isApInfoCallbackSupported();
mInOrder.verify(mHostapdHal).registerApCallback(any(), any());
- mInOrder.verify(mHostapdHal).addAccessPoint(any(), any(), anyBoolean(), any());
+ mInOrder.verify(mWifiVendorHal).isVendorHalSupported();
+ mInOrder.verify(mWifiVendorHal).getBridgedApInstances(IFACE_NAME_0);
+ mInOrder.verify(mHostapdHal).addAccessPoint(any(), any(), anyBoolean(),
+ anyBoolean(), any(), any());
// Trigger vendor HAL death
mHostapdDeathHandlerCaptor.getValue().onDeath();
@@ -1002,12 +1023,15 @@
// Start softap
assertEquals(SoftApManager.START_RESULT_SUCCESS,
mWifiNative.startSoftAp(IFACE_NAME_0, new SoftApConfiguration.Builder().build(),
- true, mock(WifiNative.SoftApHalCallback.class)));
+ true, mock(WifiNative.SoftApHalCallback.class), false));
mInOrder.verify(mHostapdHal).isApInfoCallbackSupported();
mInOrder.verify(mWificondControl).registerApCallback(any(), any(), any());
verify(mHostapdHal, never()).registerApCallback(any(), any());
- mInOrder.verify(mHostapdHal).addAccessPoint(any(), any(), anyBoolean(), any());
+ mInOrder.verify(mWifiVendorHal).isVendorHalSupported();
+ mInOrder.verify(mWifiVendorHal).getBridgedApInstances(IFACE_NAME_0);
+ mInOrder.verify(mHostapdHal).addAccessPoint(any(), any(), anyBoolean(),
+ anyBoolean(), any(), any());
// Trigger vendor HAL death
mHostapdDeathHandlerCaptor.getValue().onDeath();
@@ -1130,7 +1154,7 @@
when(mWifiVendorHal.startVendorHal()).thenReturn(false);
assertNull(mWifiNative.setupInterfaceForSoftApMode(mIfaceCallback0, TEST_WORKSOURCE,
SoftApConfiguration.BAND_2GHZ, false, mSoftApManager,
- new ArrayList<>()));
+ new ArrayList<>(), false));
mInOrder.verify(mWifiVendorHal).isVendorHalSupported();
mInOrder.verify(mWifiVendorHal).startVendorHal();
@@ -1572,6 +1596,30 @@
executeAndValidateTeardownNanInterface(false, false, false, false, mActiveNanIface);
}
+ @Test
+ public void testCreateNanIfaceFailureWhenFailToCreateNan() throws Exception {
+ when(mHalDeviceManager.createNanIface(any(), any(), any()))
+ .thenReturn(null);
+ mActiveNanIface = mWifiNative.createNanIface(mTestInterfaceDestroyedListener,
+ mCreateIfaceEventHandler, TEST_WORKSOURCE);
+ validateStartHal(false, true);
+ assertNull(mActiveNanIface);
+ validateOnDestroyedNanInterface(false, false, false, false);
+ }
+
+ @Test
+ public void testCreateNanIfaceFailureWhenFailToGetNanIfaceName() throws Exception {
+ when(mHalDeviceManager.createNanIface(any(), any(), any()))
+ .thenReturn(mActiveWifiNanIface);
+ // The empty aware iface will cause failure
+ when(mActiveWifiNanIface.getName()).thenReturn(null);
+ mActiveNanIface = mWifiNative.createNanIface(mTestInterfaceDestroyedListener,
+ mCreateIfaceEventHandler, TEST_WORKSOURCE);
+ validateStartHal(false, true);
+ assertNull(mActiveNanIface);
+ validateOnDestroyedNanInterface(false, false, false, false);
+ }
+
private void executeAndValidateSetupClientInterface(
boolean hasStaIface, boolean hasApIface,
String ifaceName, @Mock WifiNative.InterfaceCallback callback,
@@ -1955,7 +2003,7 @@
.thenReturn(ifaceName);
assertEquals(failureCode == 0 ? ifaceName : null, mWifiNative.setupInterfaceForSoftApMode(
callback, TEST_WORKSOURCE, SoftApConfiguration.BAND_2GHZ, isBridged,
- mSoftApManager, new ArrayList<>()));
+ mSoftApManager, new ArrayList<>(), false));
validateSetupSoftApInterface(
hasStaIface, hasApIface, hasP2pIface, hasNanIface, ifaceName,
diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiNativeTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiNativeTest.java
index a970e18..0ac9231 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/WifiNativeTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/WifiNativeTest.java
@@ -21,7 +21,8 @@
import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_NATIVE_SUPPORTED_FEATURES;
import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_NATIVE_EXTENDED_SUPPORTED_FEATURES;
-import static com.android.server.wifi.util.GeneralUtil.longToBitset;
+import static com.android.server.wifi.util.GeneralUtil.bitsetToLong;
+import static com.android.server.wifi.TestUtil.createCapabilityBitset;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
@@ -74,6 +75,7 @@
import com.android.modules.utils.build.SdkLevel;
import com.android.server.wifi.coex.CoexManager;
import com.android.server.wifi.hal.WifiChip;
+import com.android.server.wifi.p2p.WifiP2pNative;
import com.android.server.wifi.proto.WifiStatsLog;
import com.android.server.wifi.util.NativeUtil;
import com.android.server.wifi.util.NetdWrapper;
@@ -256,8 +258,8 @@
return result;
}
- private static final BitSet WIFI_TEST_FEATURE = longToBitset(0x800000000L);
-
+ private static final BitSet WIFI_TEST_FEATURE =
+ createCapabilityBitset(WifiManager.WIFI_FEATURE_OWE);
private static final RadioChainInfo MOCK_NATIVE_RADIO_CHAIN_INFO_1 = new RadioChainInfo(1, -89);
private static final RadioChainInfo MOCK_NATIVE_RADIO_CHAIN_INFO_2 = new RadioChainInfo(0, -78);
private static final WorkSource TEST_WORKSOURCE = new WorkSource();
@@ -289,6 +291,7 @@
@Mock private WifiGlobals mWifiGlobals;
@Mock DeviceConfigFacade mDeviceConfigFacade;
@Mock WifiChip.AfcChannelAllowance mAfcChannelAllowance;
+ @Mock private WifiP2pNative mWifiP2pNative;
private MockitoSession mSession;
ArgumentCaptor<WifiNl80211Manager.ScanEventCallback> mScanCallbackCaptor =
@@ -309,6 +312,8 @@
when(mWifiVendorHal.createApIface(any(), any(), anyInt(), anyBoolean(), any(), anyList()))
.thenReturn(WIFI_IFACE_NAME);
when(mWifiVendorHal.getSupportedFeatureSet(anyString())).thenReturn(new BitSet());
+ when(mWifiVendorHal.replaceStaIfaceRequestorWs(WIFI_IFACE_NAME, TEST_WORKSOURCE))
+ .thenReturn(true);
when(mBuildProperties.isEngBuild()).thenReturn(false);
when(mBuildProperties.isUserdebugBuild()).thenReturn(false);
@@ -338,6 +343,7 @@
when(mWifiInjector.getContext()).thenReturn(mContext);
when(mWifiInjector.getSsidTranslator()).thenReturn(mSsidTranslator);
when(mWifiInjector.getWifiGlobals()).thenReturn(mWifiGlobals);
+ when(mWifiInjector.getWifiP2pNative()).thenReturn(mWifiP2pNative);
mResources = getMockResources();
mResources.setBoolean(R.bool.config_wifiNetworkCentricQosPolicyFeatureEnabled, false);
when(mContext.getResources()).thenReturn(mResources);
@@ -357,7 +363,7 @@
.mockStatic(WifiMigration.class, withSettings().lenient())
.startMocking();
- when(Flags.rsnOverriding()).thenReturn(false);
+ when(Flags.rsnOverriding()).thenReturn(true);
mWifiNative = new WifiNative(
mWifiVendorHal, mStaIfaceHal, mHostapdHal, mWificondControl,
@@ -725,6 +731,51 @@
}
/**
+ * Verifies valules of ScanResultWithSameFreq in getWifiLinkLayerStats() call
+ *
+ */
+ @Test
+ public void testGetWifiLinkLayerStatsForScanResultWithSameFreq() {
+ WifiLinkLayerStats testWifiLinkLayerStats = new WifiLinkLayerStats();
+ testWifiLinkLayerStats.links = new WifiLinkLayerStats.LinkSpecificStats[2];
+ // Define 2 test WiFi links, whose frequencyMhz are 0, 1, respectively
+ for (int i = 0; i < 2; ++i) {
+ testWifiLinkLayerStats.links[i] = new WifiLinkLayerStats.LinkSpecificStats();
+ testWifiLinkLayerStats.links[i].frequencyMhz = i;
+ }
+ when(mWifiVendorHal.getWifiLinkLayerStats(WIFI_IFACE_NAME))
+ .thenReturn(testWifiLinkLayerStats);
+
+ // Define 6 test WiFi scan results with unique BSSID
+ // Their frequency are 0, 1, 2, 0, 1, 2, respectively
+ ScanResult[] scanResults = new ScanResult[6];
+ for (int i = 0; i < 6; i++) {
+ ScanResult scanResult = new ScanResult();
+ scanResult.BSSID = Integer.toString(i);
+ scanResult.frequency = i < 3 ? i : (i - 3);
+ // Make sure the timestamp is valid
+ scanResult.timestamp = Long.MAX_VALUE;
+ scanResults[i] = scanResult;
+ }
+ ScanData testScanData = new ScanData(0, 0,
+ 0, WifiScanner.WIFI_BAND_UNSPECIFIED, scanResults);
+ when(mWifiVendorHal.getCachedScanData(WIFI_IFACE_NAME)).thenReturn(testScanData);
+ mWifiNative.setLocationModeEnabled(true);
+
+ WifiLinkLayerStats resultWifiLinkLayerStats =
+ mWifiNative.getWifiLinkLayerStats(WIFI_IFACE_NAME);
+ assertEquals(2, resultWifiLinkLayerStats.links.length);
+ // WiFi link 0's frequency is 0, scan results 0 and 3 have the same frequency
+ assertEquals(2, resultWifiLinkLayerStats.links[0].scan_results_same_freq.size());
+ assertEquals("0", resultWifiLinkLayerStats.links[0].scan_results_same_freq.get(0).bssid);
+ assertEquals("3", resultWifiLinkLayerStats.links[0].scan_results_same_freq.get(1).bssid);
+ // WiFi link 1's frequency is 1, scan results 1 and 4 have the same frequency
+ assertEquals(2, resultWifiLinkLayerStats.links[1].scan_results_same_freq.size());
+ assertEquals("1", resultWifiLinkLayerStats.links[1].scan_results_same_freq.get(0).bssid);
+ assertEquals("4", resultWifiLinkLayerStats.links[1].scan_results_same_freq.get(1).bssid);
+ }
+
+ /**
* Verifies client mode + scan success.
*/
@Test
@@ -819,7 +870,7 @@
when(mWifiVendorHal.getBridgedApInstances(WIFI_IFACE_NAME))
.thenReturn(Arrays.asList(instance1, instance2));
mWifiNative.setupInterfaceForSoftApMode(null, TEST_WORKSOURCE, SoftApConfiguration.BAND_2GHZ
- | SoftApConfiguration.BAND_5GHZ, true, mSoftApManager, new ArrayList<>());
+ | SoftApConfiguration.BAND_5GHZ, true, mSoftApManager, new ArrayList<>(), false);
ArgumentCaptor<HalDeviceManager.InterfaceDestroyedListener> ifaceDestroyedListenerCaptor =
ArgumentCaptor.forClass(HalDeviceManager.InterfaceDestroyedListener.class);
verify(mWifiVendorHal).createApIface(ifaceDestroyedListenerCaptor.capture(), any(),
@@ -908,7 +959,7 @@
mWifiNative.teardownAllInterfaces();
mWifiNative.setupInterfaceForSoftApMode(null, TEST_WORKSOURCE, WIFI_BAND_24_GHZ, false,
- mSoftApManager, new ArrayList<>());
+ mSoftApManager, new ArrayList<>(), false);
verify(mWifiVendorHal, times(4)).setCoexUnsafeChannels(unsafeChannels, restrictions);
}
@@ -1609,7 +1660,7 @@
.thenReturn(legacyFeatures);
when(mSettingsConfigStore.get(eq(WIFI_NATIVE_EXTENDED_SUPPORTED_FEATURES)))
.thenReturn(WIFI_TEST_FEATURE.toLongArray());
- BitSet featureSet = longToBitset(mWifiNative.getSupportedFeatureSet(null));
+ BitSet featureSet = mWifiNative.getSupportedFeatureSet(null);
assertTrue(featureSet.equals(WIFI_TEST_FEATURE));
}
@@ -1620,13 +1671,13 @@
*/
@Test
public void testGetLegacyFeaturesWhenInterfaceDoesntExist() throws Exception {
- long legacyFeatures = 0x321;
+ long legacyFeatures = bitsetToLong(WIFI_TEST_FEATURE);
when(mSettingsConfigStore.get(eq(WIFI_NATIVE_SUPPORTED_FEATURES)))
.thenReturn(legacyFeatures);
when(mSettingsConfigStore.get(eq(WIFI_NATIVE_EXTENDED_SUPPORTED_FEATURES)))
.thenReturn(new long[0]); // no extended features
- BitSet featureSet = longToBitset(mWifiNative.getSupportedFeatureSet(null));
- assertTrue(featureSet.equals(longToBitset(legacyFeatures)));
+ BitSet featureSet = mWifiNative.getSupportedFeatureSet(null);
+ assertTrue(featureSet.equals(WIFI_TEST_FEATURE));
}
/**
@@ -1667,8 +1718,8 @@
mWifiNative.setupInterfaceForClientInScanMode(null, TEST_WORKSOURCE,
mConcreteClientModeManager);
mWifiNative.switchClientInterfaceToConnectivityMode(WIFI_IFACE_NAME, TEST_WORKSOURCE);
- verify(mWificondControl).getChannelsMhzForBand(WifiScanner.WIFI_BAND_24_GHZ);
- verify(mWificondControl).getChannelsMhzForBand(WifiScanner.WIFI_BAND_5_GHZ);
+ verify(mWificondControl, times(2)).getChannelsMhzForBand(WifiScanner.WIFI_BAND_24_GHZ);
+ verify(mWificondControl, times(2)).getChannelsMhzForBand(WifiScanner.WIFI_BAND_5_GHZ);
assertEquals(3, mWifiNative.getSupportedBandsForSta(WIFI_IFACE_NAME));
}
@@ -1856,16 +1907,69 @@
}
@Test
- public void testRsnOverridingFeatureFlag() throws Exception {
+ public void testRsnOverridingFeatureSupportOnOlderHals() throws Exception {
+ when(mStaIfaceHal.isAidlServiceVersionAtLeast(4)).thenReturn(false);
+
+ /* RSN Overriding feature is enabled when overlay config item is set to true */
mResources.setBoolean(R.bool.config_wifiRsnOverridingEnabled, true);
- when(Flags.rsnOverriding()).thenReturn(false);
mWifiNative.setupInterfaceForClientInScanMode(null, TEST_WORKSOURCE,
mConcreteClientModeManager);
+ mWifiNative.switchClientInterfaceToConnectivityMode(WIFI_IFACE_NAME, TEST_WORKSOURCE);
+ assertTrue(mWifiNative.mIsRsnOverridingSupported);
+ mWifiNative.teardownAllInterfaces();
+
+ /* RSN Overriding feature is disabled when overlay config item is set to false */
+ mResources.setBoolean(R.bool.config_wifiRsnOverridingEnabled, false);
+ mWifiNative.setupInterfaceForClientInScanMode(null, TEST_WORKSOURCE,
+ mConcreteClientModeManager);
+ mWifiNative.switchClientInterfaceToConnectivityMode(WIFI_IFACE_NAME, TEST_WORKSOURCE);
assertFalse(mWifiNative.mIsRsnOverridingSupported);
mWifiNative.teardownAllInterfaces();
- when(Flags.rsnOverriding()).thenReturn(true);
+ }
+
+ @Test
+ public void testRsnOverridingFeatureSupportOnNewerHals() throws Exception {
+ when(mStaIfaceHal.isAidlServiceVersionAtLeast(4)).thenReturn(true);
+
+ /* RSN Overriding feature is enabled based on chip capability */
+ mResources.setBoolean(R.bool.config_wifiRsnOverridingEnabled, false);
+ when(mStaIfaceHal.isRsnOverridingSupported(WIFI_IFACE_NAME)).thenReturn(true);
mWifiNative.setupInterfaceForClientInScanMode(null, TEST_WORKSOURCE,
mConcreteClientModeManager);
+ mWifiNative.switchClientInterfaceToConnectivityMode(WIFI_IFACE_NAME, TEST_WORKSOURCE);
assertTrue(mWifiNative.mIsRsnOverridingSupported);
+ mWifiNative.teardownAllInterfaces();
+
+ /* Overlay config has no effect on newer HALs */
+ mResources.setBoolean(R.bool.config_wifiRsnOverridingEnabled, true);
+
+ when(mStaIfaceHal.isRsnOverridingSupported(WIFI_IFACE_NAME)).thenReturn(false);
+ mWifiNative.setupInterfaceForClientInScanMode(null, TEST_WORKSOURCE,
+ mConcreteClientModeManager);
+ mWifiNative.switchClientInterfaceToConnectivityMode(WIFI_IFACE_NAME, TEST_WORKSOURCE);
+ assertFalse(mWifiNative.mIsRsnOverridingSupported);
+ mWifiNative.teardownAllInterfaces();
+ }
+
+ @Test
+ public void testIsMLDApSupportMLO() throws Exception {
+ when(Flags.mloSap()).thenReturn(true);
+ BitSet mloFeature =
+ createCapabilityBitset(WifiManager.WIFI_FEATURE_SOFTAP_MLO);
+ when(mWifiGlobals.isMLDApSupported()).thenReturn(true);
+ assertFalse(mWifiNative.isMLDApSupportMLO());
+
+ when(mSettingsConfigStore.get(eq(WIFI_NATIVE_EXTENDED_SUPPORTED_FEATURES)))
+ .thenReturn(mloFeature.toLongArray());
+ mWifiNative = new WifiNative(
+ mWifiVendorHal, mStaIfaceHal, mHostapdHal, mWificondControl,
+ mWifiMonitor, mPropertyService, mWifiMetrics,
+ mHandler, mRandom, mBuildProperties, mWifiInjector);
+ assertTrue(mWifiNative.isMLDApSupportMLO());
+ when(Flags.mloSap()).thenReturn(false);
+ assertFalse(mWifiNative.isMLDApSupportMLO());
+ when(Flags.mloSap()).thenReturn(true);
+ when(mWifiGlobals.isMLDApSupported()).thenReturn(false);
+ assertFalse(mWifiNative.isMLDApSupportMLO());
}
}
diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiNetworkFactoryTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiNetworkFactoryTest.java
index 1404810..0a8fcca 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/WifiNetworkFactoryTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/WifiNetworkFactoryTest.java
@@ -22,6 +22,7 @@
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
import static com.android.server.wifi.WifiNetworkFactory.PERIODIC_SCAN_INTERVAL_MS;
+import static com.android.server.wifi.TestUtil.createCapabilityBitset;
import static com.android.server.wifi.util.NativeUtil.addEnclosingQuotes;
import static org.junit.Assert.assertArrayEquals;
@@ -299,7 +300,8 @@
new WorkSource(Process.SYSTEM_UID, "system-service"));
when(mPrimaryClientModeManager.getSupportedFeatures()).thenReturn(
- WifiManager.WIFI_FEATURE_WPA3_SAE | WifiManager.WIFI_FEATURE_OWE);
+ createCapabilityBitset(
+ WifiManager.WIFI_FEATURE_WPA3_SAE, WifiManager.WIFI_FEATURE_OWE));
mWifiNetworkFactory = new WifiNetworkFactory(mLooper.getLooper(), mContext,
mNetworkCapabilities, mActivityManager, mAlarmManager, mAppOpsManager,
diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiNetworkSelectorTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiNetworkSelectorTest.java
index d5e1023..e966f51 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/WifiNetworkSelectorTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/WifiNetworkSelectorTest.java
@@ -28,6 +28,7 @@
import static com.android.server.wifi.WifiConfigurationTestUtil.SECURITY_SAE;
import static com.android.server.wifi.WifiConfigurationTestUtil.SECURITY_WEP;
import static com.android.server.wifi.WifiNetworkSelector.experimentIdFromIdentifier;
+import static com.android.server.wifi.TestUtil.createCapabilityBitset;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
@@ -72,6 +73,7 @@
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.BitSet;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
@@ -157,6 +159,7 @@
when(mWifiInjector.getWifiGlobals()).thenReturn(mWifiGlobals);
when(mWifiGlobals.getWifiLowConnectedScoreThresholdToTriggerScanForMbb()).thenReturn(
ConnectedScore.WIFI_TRANSITION_SCORE);
+ when(mClientModeManager.getSupportedFeatures()).thenReturn(new BitSet());
when(mActiveModeWarden.getPrimaryClientModeManager()).thenReturn(mClientModeManager);
if (WifiNetworkSelector.PRESET_CANDIDATE_SCORER_NAME.equals(
mThroughputScorer.getIdentifier())) {
@@ -555,7 +558,7 @@
scanDetails, blocklist,
Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo,
false, ROLE_CLIENT_PRIMARY)),
- false, true, true, Collections.emptySet(), false);
+ false, true, true, Collections.emptySet(), false, 0);
WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates);
assertEquals("Expect null configuration", null, candidate);
assertTrue(mWifiNetworkSelector.getConnectableScanDetails().isEmpty());
@@ -589,7 +592,7 @@
scanDetails, blocklist,
Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo,
false, ROLE_CLIENT_PRIMARY)),
- false, true, true, Collections.emptySet(), false);
+ false, true, true, Collections.emptySet(), false, 0);
WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates);
assertEquals("Expect null configuration", null, candidate);
assertTrue(mWifiNetworkSelector.getConnectableScanDetails().isEmpty());
@@ -626,7 +629,7 @@
scanDetails, blocklist,
Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo,
false, ROLE_CLIENT_PRIMARY)),
- false, true, true, Collections.emptySet(), false);
+ false, true, true, Collections.emptySet(), false, 0);
WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates);
assertNotNull(candidate);
@@ -638,7 +641,7 @@
scanDetails, blocklist,
Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, true, false, mWifiInfo,
false, ROLE_CLIENT_PRIMARY)),
- false, true, true, Collections.emptySet(), false);
+ false, true, true, Collections.emptySet(), false, 0);
candidate = mWifiNetworkSelector.selectNetwork(candidates);
assertNull("Expect null configuration", candidate);
@@ -680,7 +683,7 @@
scanDetails, blocklist,
Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo,
false, ROLE_CLIENT_PRIMARY)),
- false, true, true, Collections.emptySet(), false);
+ false, true, true, Collections.emptySet(), false, 0);
WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates);
WifiConfigurationTestUtil.assertConfigurationEqual(savedConfigs[0], candidate);
@@ -692,7 +695,7 @@
scanDetails, blocklist,
Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo,
false, ROLE_CLIENT_PRIMARY)),
- false, true, true, Collections.emptySet(), false);
+ false, true, true, Collections.emptySet(), false, 0);
candidate = mWifiNetworkSelector.selectNetwork(candidates);
ScanResult chosenScanResult = scanDetails.get(0).getScanResult();
@@ -732,7 +735,7 @@
scanDetails, blocklist,
Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo,
false, ROLE_CLIENT_PRIMARY)),
- false, true, true, Collections.emptySet(), false);
+ false, true, true, Collections.emptySet(), false, 0);
WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates);
when(mWifiInfo.getSupplicantState()).thenReturn(SupplicantState.COMPLETED);
when(mWifiInfo.getNetworkId()).thenReturn(0);
@@ -750,7 +753,7 @@
scanDetails, blocklist,
Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, true, false, mWifiInfo,
false, ROLE_CLIENT_PRIMARY)),
- false, true, true, Collections.emptySet(), false);
+ false, true, true, Collections.emptySet(), false, 0);
candidate = mWifiNetworkSelector.selectNetwork(candidates);
ScanResult chosenScanResult = scanDetails.get(0).getScanResult();
@@ -792,7 +795,7 @@
scanDetails, blocklist,
Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo,
false, ROLE_CLIENT_PRIMARY)),
- false, true, true, Collections.emptySet(), false);
+ false, true, true, Collections.emptySet(), false, 0);
WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates);
when(mWifiInfo.getSupplicantState()).thenReturn(SupplicantState.COMPLETED);
when(mWifiInfo.getNetworkId()).thenReturn(0);
@@ -818,7 +821,7 @@
scanDetails, blocklist,
Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, true, false, mWifiInfo,
false, ROLE_CLIENT_PRIMARY)),
- false, true, true, Collections.emptySet(), false);
+ false, true, true, Collections.emptySet(), false, 0);
candidate = mWifiNetworkSelector.selectNetwork(candidates);
ScanResult chosenScanResult = scanDetails.get(0).getScanResult();
@@ -854,7 +857,7 @@
scanDetails, blocklist,
Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo,
false, ROLE_CLIENT_PRIMARY)),
- false, true, true, Collections.emptySet(), false);
+ false, true, true, Collections.emptySet(), false, 0);
WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates);
verify(mWifiMetrics).incrementNetworkSelectionFilteredBssidCount(0);
@@ -895,7 +898,7 @@
scanDetails, blocklist,
Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo,
false, ROLE_CLIENT_PRIMARY)),
- false, true, true, Collections.emptySet(), false);
+ false, true, true, Collections.emptySet(), false, 0);
WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates);
verify(mWifiMetrics).incrementNetworkSelectionFilteredBssidCount(1);
assertEquals("Expect null configuration", null, candidate);
@@ -935,7 +938,7 @@
scanDetails, blocklist,
Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo,
false, ROLE_CLIENT_PRIMARY)),
- false, true, true, Collections.emptySet(), false);
+ false, true, true, Collections.emptySet(), false, 0);
WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates);
assertEquals("Expect null configuration", null, candidate);
}
@@ -973,7 +976,7 @@
scanDetails, blocklist,
Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo,
false, ROLE_CLIENT_PRIMARY)),
- false, true, true, Collections.emptySet(), false);
+ false, true, true, Collections.emptySet(), false, 0);
WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates);
assertEquals("Expect null configuration", null, candidate);
}
@@ -1013,7 +1016,7 @@
scanDetails, blocklist,
Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo,
false, ROLE_CLIENT_PRIMARY)),
- false, true, true, Collections.emptySet(), false);
+ false, true, true, Collections.emptySet(), false, 0);
WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates);
assertEquals("Expect null configuration", null, candidate);
}
@@ -1056,7 +1059,7 @@
scanDetails, blocklist,
Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo,
false, ROLE_CLIENT_PRIMARY)),
- false, true, true, Collections.emptySet(), false);
+ false, true, true, Collections.emptySet(), false, 0);
WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates);
assertEquals("Expect null configuration", null, candidate);
}
@@ -1105,7 +1108,7 @@
scanDetails, blocklist,
Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo,
false, ROLE_CLIENT_PRIMARY)),
- false, true, true, Collections.emptySet(), false);
+ false, true, true, Collections.emptySet(), false, 0);
WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates);
}
@@ -1139,7 +1142,7 @@
scanDetails, blocklist,
Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo,
false, ROLE_CLIENT_PRIMARY)),
- false, true, true, Collections.emptySet(), false);
+ false, true, true, Collections.emptySet(), false, 0);
WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates);
assertEquals("Expect null configuration", null, candidate);
}
@@ -1174,12 +1177,47 @@
scanDetails, blocklist,
Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo,
false, ROLE_CLIENT_PRIMARY)),
- false, true, true, Collections.emptySet(), false);
+ false, true, true, Collections.emptySet(), false, 0);
WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates);
assertEquals("Expect null configuration", null, candidate);
}
/**
+ * Autojoin restricted security type network is filtered out for network selection.
+ *
+ * ClientModeImpl is disconnected.
+ * scanDetails contains a network which is Autojoin restricted security type.
+ *
+ * Expected behavior: no network recommended by Network Selector
+ */
+ @Test
+ public void filterOutAutojoinRestrictionSecurityTypeBssid() {
+ String[] ssids = {"\"test1\""};
+ String[] bssids = {"6c:f3:7f:ae:8c:f3"};
+ int[] freqs = {5180};
+ String[] caps = {"[WEP][ESS]"};
+ int[] levels = {mThresholdQualifiedRssi5G + 8};
+ int[] securities = {SECURITY_WEP};
+ when(WifiInfo.convertWifiConfigurationSecurityType(
+ WifiConfiguration.SECURITY_TYPE_WEP)).thenReturn(WifiInfo.SECURITY_TYPE_WEP);
+
+ ScanDetailsAndWifiConfigs scanDetailsAndConfigs =
+ WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids,
+ freqs, caps, levels, securities, mWifiConfigManager, mClock);
+ List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails();
+ HashSet<String> blocklist = new HashSet<String>();
+
+ List<WifiCandidates.Candidate> candidates = mWifiNetworkSelector.getCandidatesFromScan(
+ scanDetails, blocklist,
+ Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo,
+ false, ROLE_CLIENT_PRIMARY)),
+ false, true, true, Collections.emptySet(), false,
+ (0x1 << WifiInfo.SECURITY_TYPE_WEP));
+ WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates);
+ assertNull("Expect null configuration", candidate);
+ }
+
+ /**
* Unsupported security type WPA-Personal should not filter WPA/WPA2 networks.
*
* ClientModeImpl is disconnected.
@@ -1209,7 +1247,7 @@
scanDetails, blocklist,
Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo,
false, ROLE_CLIENT_PRIMARY)),
- false, true, true, Collections.emptySet(), false);
+ false, true, true, Collections.emptySet(), false, 0);
WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates);
assertEquals(ssids[0], candidate.SSID);
}
@@ -1243,7 +1281,7 @@
scanDetails, blocklist,
Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo,
false, ROLE_CLIENT_PRIMARY)),
- false, true, true, Collections.emptySet(), false);
+ false, true, true, Collections.emptySet(), false, 0);
WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates);
when(mWifiInfo.getSupplicantState()).thenReturn(SupplicantState.COMPLETED);
@@ -1269,7 +1307,7 @@
scanDetails, blocklist,
Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, true, false, mWifiInfo,
false, ROLE_CLIENT_PRIMARY)),
- false, true, true, Collections.emptySet(), false);
+ false, true, true, Collections.emptySet(), false, 0);
candidate = mWifiNetworkSelector.selectNetwork(candidates);
// The second network selection is skipped since current connected network is
@@ -1308,7 +1346,7 @@
scanDetails, blocklist,
Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo,
false, ROLE_CLIENT_PRIMARY)),
- false, true, true, Collections.emptySet(), false);
+ false, true, true, Collections.emptySet(), false, 0);
WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates);
WifiConfiguration[] configs = scanDetailsAndConfigs.getWifiConfigs();
@@ -1339,7 +1377,7 @@
scanDetails, blocklist,
Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, true, false, mWifiInfo,
false, ROLE_CLIENT_PRIMARY)),
- false, true, true, Collections.emptySet(), false);
+ false, true, true, Collections.emptySet(), false, 0);
assertEquals(2, candidates.size());
assertEquals(100, candidates.get(0).getPredictedThroughputMbps());
}
@@ -1379,7 +1417,7 @@
scanDetails, blocklist,
Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo,
false, ROLE_CLIENT_PRIMARY)),
- false, true, true, Collections.emptySet(), false);
+ false, true, true, Collections.emptySet(), false, 0);
WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates);
ArgumentCaptor<Integer> nominatorIdCaptor = ArgumentCaptor.forClass(int.class);
@@ -1405,7 +1443,7 @@
scanDetails, blocklist,
Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo,
false, ROLE_CLIENT_PRIMARY)),
- false, true, true, Collections.emptySet(), false);
+ false, true, true, Collections.emptySet(), false, 0);
candidate = mWifiNetworkSelector.selectNetwork(candidates);
verify(mWifiMetrics, atLeastOnce()).setNominatorForNetwork(eq(candidate.networkId),
@@ -1458,7 +1496,7 @@
scanDetails, blocklist,
Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo,
false, ROLE_CLIENT_PRIMARY)),
- false, true, true, Collections.emptySet(), false);
+ false, true, true, Collections.emptySet(), false, 0);
WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates);
WifiConfigurationTestUtil.assertConfigurationEqual(userChoice, candidate);
@@ -1473,7 +1511,7 @@
scanDetails, blocklist,
Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo,
false, ROLE_CLIENT_PRIMARY)),
- false, true, true, Collections.emptySet(), false);
+ false, true, true, Collections.emptySet(), false, 0);
candidate = mWifiNetworkSelector.selectNetwork(candidates);
WifiConfigurationTestUtil.assertConfigurationEqual(networkSelectorChoice, candidate);
}
@@ -1514,7 +1552,7 @@
scanDetails, blocklist,
Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo,
false, ROLE_CLIENT_PRIMARY)),
- false, true, true, Collections.emptySet(), false);
+ false, true, true, Collections.emptySet(), false, 0);
WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates);
WifiConfigurationTestUtil.assertConfigurationEqual(userChoice, candidate);
@@ -1527,7 +1565,7 @@
scanDetails, blocklist,
Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo,
false, ROLE_CLIENT_PRIMARY)),
- false, true, true, Collections.emptySet(), false);
+ false, true, true, Collections.emptySet(), false, 0);
candidate = mWifiNetworkSelector.selectNetwork(candidates);
// Should now select the non user choice network.
@@ -1569,7 +1607,7 @@
scanDetails, blocklist,
Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo,
false, ROLE_CLIENT_PRIMARY)),
- false, true, true, Collections.emptySet(), false);
+ false, true, true, Collections.emptySet(), false, 0);
WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates);
WifiConfigurationTestUtil.assertConfigurationEqual(userChoice, candidate);
@@ -1580,7 +1618,7 @@
scanDetails, blocklist,
Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo,
false, ROLE_CLIENT_PRIMARY)),
- false, true, true, Collections.emptySet(), false);
+ false, true, true, Collections.emptySet(), false, 0);
candidate = mWifiNetworkSelector.selectNetwork(candidates);
WifiConfigurationTestUtil.assertConfigurationEqual(networkSelectorChoice, candidate);
}
@@ -1615,7 +1653,7 @@
scanDetails, blocklist,
Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo,
false, ROLE_CLIENT_PRIMARY)),
- false, true, true, Collections.emptySet(), false);
+ false, true, true, Collections.emptySet(), false, 0);
assertFalse(candidates.isEmpty());
for (WifiCandidates.Candidate candidate: candidates) {
@@ -1632,7 +1670,7 @@
scanDetails, blocklist,
Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo,
false, ROLE_CLIENT_PRIMARY)),
- false, true, true, Collections.emptySet(), false);
+ false, true, true, Collections.emptySet(), false, 0);
assertFalse(candidates.isEmpty());
for (WifiCandidates.Candidate candidate: candidates) {
@@ -1682,7 +1720,7 @@
scanDetails, blocklist,
Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo,
false, ROLE_CLIENT_PRIMARY)),
- false, true, true, Collections.emptySet(), false);
+ false, true, true, Collections.emptySet(), false, 0);
WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates);
ArgumentCaptor<Integer> nominatorIdCaptor = ArgumentCaptor.forClass(int.class);
@@ -1898,7 +1936,7 @@
scanDetails, blocklist,
Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo,
false, ROLE_CLIENT_PRIMARY)),
- false, true, true, Collections.emptySet(), false);
+ false, true, true, Collections.emptySet(), false, 0);
//WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates);
assertEquals(1, candidates.size());
assertTrue(candidates.get(0).getLastSelectionWeight() > 0);
@@ -1910,7 +1948,7 @@
scanDetails, blocklist,
Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo,
false, ROLE_CLIENT_PRIMARY)),
- false, true, true, Collections.emptySet(), false);
+ false, true, true, Collections.emptySet(), false, 0);
//WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates);
assertEquals(1, candidates.size());
assertEquals(0, candidates.get(0).getLastSelectionWeight(), 0);
@@ -2026,7 +2064,7 @@
scanDetails, blocklist,
Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo,
false, ROLE_CLIENT_PRIMARY)),
- true, true, true, Collections.emptySet(), false);
+ true, true, true, Collections.emptySet(), false, 0);
WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates);
assertNotNull("Result should be not null", candidate);
WifiNetworkSelectorTestUtil.verifySelectedScanResult(mWifiConfigManager,
@@ -2068,7 +2106,7 @@
scanDetails, blocklist,
Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, true, false, mWifiInfo,
false, ROLE_CLIENT_PRIMARY)),
- true, true, true, Collections.emptySet(), false);
+ true, true, true, Collections.emptySet(), false, 0);
candidate = mWifiNetworkSelector.selectNetwork(candidates);
// PlaceholderNominator always return the first network in the scan results
@@ -2106,7 +2144,7 @@
scanDetails, blocklist,
Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo,
false, ROLE_CLIENT_PRIMARY)),
- false, true, true, Collections.emptySet(), false);
+ false, true, true, Collections.emptySet(), false, 0);
WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates);
List<ScanDetail> expectedOpenUnsavedNetworks = new ArrayList<>();
expectedOpenUnsavedNetworks.add(scanDetails.get(1));
@@ -2141,7 +2179,7 @@
unSavedScanDetails, blocklist,
Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo,
false, ROLE_CLIENT_PRIMARY)),
- false, true, true, Collections.emptySet(), false);
+ false, true, true, Collections.emptySet(), false, 0);
WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates);
assertEquals("Expect open unsaved networks",
unSavedScanDetails,
@@ -2156,7 +2194,7 @@
savedScanDetails, blocklist,
Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo,
false, ROLE_CLIENT_PRIMARY)),
- false, true, true, Collections.emptySet(), false);
+ false, true, true, Collections.emptySet(), false, 0);
candidate = mWifiNetworkSelector.selectNetwork(candidates);
// Saved networks are filtered out.
assertTrue(mWifiNetworkSelector.getFilteredScanDetailsForOpenUnsavedNetworks().isEmpty());
@@ -2186,7 +2224,7 @@
scanDetails, blocklist,
Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo,
false, ROLE_CLIENT_PRIMARY)),
- false, true, true, Collections.emptySet(), false);
+ false, true, true, Collections.emptySet(), false, 0);
WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates);
List<ScanDetail> expectedOpenUnsavedNetworks = new ArrayList<>();
expectedOpenUnsavedNetworks.add(scanDetails.get(1));
@@ -2218,7 +2256,7 @@
scanDetails, blocklist,
Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo,
false, ROLE_CLIENT_PRIMARY)),
- false, true, true, Collections.emptySet(), false);
+ false, true, true, Collections.emptySet(), false, 0);
WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates);
assertTrue(mWifiNetworkSelector.getFilteredScanDetailsForOpenUnsavedNetworks().isEmpty());
}
@@ -2250,7 +2288,8 @@
int[] levels = {mThresholdMinimumRssi2G, mThresholdMinimumRssi5G + RSSI_BUMP,
mThresholdMinimumRssi2G + RSSI_BUMP};
mPlaceholderNominator.setNominatorToSelectCandidate(false);
- when(mClientModeManager.getSupportedFeatures()).thenReturn(WIFI_FEATURE_OWE);
+ when(mClientModeManager.getSupportedFeatures()).thenReturn(
+ createCapabilityBitset(WIFI_FEATURE_OWE));
List<ScanDetail> scanDetails = WifiNetworkSelectorTestUtil.buildScanDetails(
ssids, bssids, freqs, caps, levels, mClock);
@@ -2260,7 +2299,7 @@
scanDetails, blocklist,
Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo,
false, ROLE_CLIENT_PRIMARY)),
- false, true, true, Collections.emptySet(), false);
+ false, true, true, Collections.emptySet(), false, 0);
WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates);
List<ScanDetail> expectedOpenUnsavedNetworks = new ArrayList<>();
expectedOpenUnsavedNetworks.add(scanDetails.get(1));
@@ -2286,7 +2325,10 @@
int[] levels = {mThresholdMinimumRssi2G, mThresholdMinimumRssi5G + RSSI_BUMP,
mThresholdMinimumRssi2G + RSSI_BUMP};
mPlaceholderNominator.setNominatorToSelectCandidate(false);
- when(mClientModeManager.getSupportedFeatures()).thenReturn(~WIFI_FEATURE_OWE);
+
+ BitSet supportedFeatures = new BitSet();
+ supportedFeatures.set(WIFI_FEATURE_OWE, false);
+ when(mClientModeManager.getSupportedFeatures()).thenReturn(supportedFeatures);
List<ScanDetail> scanDetails = WifiNetworkSelectorTestUtil.buildScanDetails(
ssids, bssids, freqs, caps, levels, mClock);
@@ -2296,7 +2338,7 @@
scanDetails, blocklist,
Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo,
false, ROLE_CLIENT_PRIMARY)),
- false, true, true, Collections.emptySet(), false);
+ false, true, true, Collections.emptySet(), false, 0);
WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates);
List<ScanDetail> expectedOpenUnsavedNetworks = new ArrayList<>();
expectedOpenUnsavedNetworks.add(scanDetails.get(1));
@@ -2327,7 +2369,7 @@
EMPTY_BLOCKLIST,
Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo,
false, ROLE_CLIENT_PRIMARY)),
- true, true, true, Collections.emptySet(), false);
+ true, true, true, Collections.emptySet(), false, 0);
WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates);
verify(mCandidateScorer, atLeastOnce()).scoreCandidates(any());
@@ -2465,7 +2507,7 @@
scanDetails, blocklist,
Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo,
false, ROLE_CLIENT_PRIMARY)),
- true, true, true, Collections.emptySet(), false);
+ true, true, true, Collections.emptySet(), false, 0);
WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates);
// Check if the wifiConfig is updated with the latest
verify(mWifiConfigManager).addOrUpdateNetwork(existingConfig,
@@ -2496,7 +2538,7 @@
scanDetails, blocklist,
Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo,
false, ROLE_CLIENT_PRIMARY)),
- false, true, true, Collections.emptySet(), false);
+ false, true, true, Collections.emptySet(), false, 0);
// Expect one privileged and one regular candidate.
assertEquals(2, candidates.size());
boolean foundCarrierOrPrivilegedAppCandidate = false;
@@ -2546,7 +2588,7 @@
scanDetails, blocklist,
Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo,
false, ROLE_CLIENT_PRIMARY)),
- false, true, true, Collections.emptySet(), false);
+ false, true, true, Collections.emptySet(), false, 0);
WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates);
verify(mWifiMetrics, times(1))
.incrementNetworkSelectionFilteredBssidCountDueToMboAssocDisallowInd();
@@ -2673,7 +2715,7 @@
new ClientModeManagerState(
TEST_IFACE_NAME_SECONDARY, true, false, mSecondaryWifiInfo,
false, ROLE_CLIENT_SECONDARY_LONG_LIVED)),
- false, true, true, Collections.emptySet(), false);
+ false, true, true, Collections.emptySet(), false, 0);
WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates);
ScanResult chosenScanResult = scanDetails.get(0).getScanResult();
@@ -2743,7 +2785,7 @@
// Do network selection.
List<WifiCandidates.Candidate> candidates = mWifiNetworkSelector.getCandidatesFromScan(
scanDetails, blocklist, cmmStates, false, true, true, Collections.emptySet(),
- false);
+ false, 0);
assertNull(candidates);
// Mock that the primary connection has a user connect choice pointing something
@@ -2757,7 +2799,7 @@
primaryConfig);
candidates = mWifiNetworkSelector.getCandidatesFromScan(
scanDetails, blocklist, cmmStates, false, true, true, Collections.emptySet(),
- false);
+ false, 0);
// Candidate should not be null
assertNotNull(candidates);
@@ -2766,7 +2808,7 @@
R.bool.config_wifi_framework_enable_associated_network_selection);
assertNull(mWifiNetworkSelector.getCandidatesFromScan(
scanDetails, blocklist, cmmStates, false, true, true, Collections.emptySet(),
- false));
+ false, 0));
}
private void runNetworkSelectionWith(ScanDetailsAndWifiConfigs scanDetailsAndConfigs) {
@@ -2778,7 +2820,7 @@
true, // untrustedNetworkAllowed
true, // oemPaid
true, // oemPrivate
- Collections.emptySet(), false);
+ Collections.emptySet(), false, 0);
WifiConfiguration wifiConfiguration = mWifiNetworkSelector.selectNetwork(candidates);
assertNotNull(wifiConfiguration);
}
@@ -2817,7 +2859,8 @@
*/
@Test
public void testSaeAutoUpgradeWithPskNetworkWhenAutoUpgradeEnabled() {
- when(mClientModeManager.getSupportedFeatures()).thenReturn(WIFI_FEATURE_WPA3_SAE);
+ when(mClientModeManager.getSupportedFeatures())
+ .thenReturn(createCapabilityBitset(WIFI_FEATURE_WPA3_SAE));
when(mWifiGlobals.isWpa3SaeUpgradeEnabled()).thenReturn(true);
when(mWifiGlobals.isWpa3SaeUpgradeOffloadEnabled()).thenReturn(true);
@@ -2834,7 +2877,7 @@
scanDetails, new HashSet<>(),
Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo,
false, ROLE_CLIENT_PRIMARY)),
- false, true, true, Collections.emptySet(), false);
+ false, true, true, Collections.emptySet(), false, 0);
assertEquals(2, candidates.size());
// Verify that SAE network is selected if offload is supported.
@@ -2872,7 +2915,8 @@
*/
@Test
public void testSaeAutoUpgradeWithPskNetworkWhenPskTypeIsDisabled() {
- when(mClientModeManager.getSupportedFeatures()).thenReturn(WIFI_FEATURE_WPA3_SAE);
+ when(mClientModeManager.getSupportedFeatures())
+ .thenReturn(createCapabilityBitset(WIFI_FEATURE_WPA3_SAE));
when(mWifiGlobals.isWpa3SaeUpgradeEnabled()).thenReturn(true);
when(mWifiGlobals.isWpa3SaeUpgradeOffloadEnabled()).thenReturn(false);
@@ -2890,7 +2934,7 @@
scanDetails, new HashSet<>(),
Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo,
false, ROLE_CLIENT_PRIMARY)),
- false, true, true, Collections.emptySet(), false);
+ false, true, true, Collections.emptySet(), false, 0);
// PSK type is disabled, PSK network is not matched.
assertEquals(1, candidates.size());
@@ -2907,7 +2951,8 @@
*/
@Test
public void testSaeNoAutoUpgradeWithPskNetworkWhenAutoUpgradeDisabled() {
- when(mClientModeManager.getSupportedFeatures()).thenReturn(WIFI_FEATURE_WPA3_SAE);
+ when(mClientModeManager.getSupportedFeatures())
+ .thenReturn(createCapabilityBitset(WIFI_FEATURE_WPA3_SAE));
when(mWifiGlobals.isWpa3SaeUpgradeEnabled()).thenReturn(false);
when(mWifiGlobals.isWpa3SaeUpgradeOffloadEnabled()).thenReturn(false);
@@ -2924,7 +2969,7 @@
scanDetails, new HashSet<>(),
Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo,
false, ROLE_CLIENT_PRIMARY)),
- false, true, true, Collections.emptySet(), false);
+ false, true, true, Collections.emptySet(), false, 0);
assertEquals(2, candidates.size());
// Verify that PSK network is selected.
@@ -2940,7 +2985,7 @@
*/
@Test
public void testSaeNoAutoUpgradeWithPskNetworkWhenSaeNotSupported() {
- when(mClientModeManager.getSupportedFeatures()).thenReturn(0L);
+ when(mClientModeManager.getSupportedFeatures()).thenReturn(new BitSet());
when(mWifiGlobals.isWpa3SaeUpgradeEnabled()).thenReturn(true);
when(mWifiGlobals.isWpa3SaeUpgradeOffloadEnabled()).thenReturn(true);
@@ -2957,7 +3002,7 @@
scanDetails, new HashSet<>(),
Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo,
false, ROLE_CLIENT_PRIMARY)),
- false, true, true, Collections.emptySet(), false);
+ false, true, true, Collections.emptySet(), false, 0);
// The SAE-only network should be filtered.
assertEquals(1, candidates.size());
@@ -2976,7 +3021,8 @@
*/
@Test
public void testOweAutoUpgradeWithOpenNetworkWhenAutoUpgradeEnabled() {
- when(mClientModeManager.getSupportedFeatures()).thenReturn(WIFI_FEATURE_OWE);
+ when(mClientModeManager.getSupportedFeatures()).thenReturn(
+ createCapabilityBitset(WIFI_FEATURE_OWE));
when(mWifiGlobals.isOweUpgradeEnabled()).thenReturn(true);
when(mScanRequestProxy.isOpenOnlyNetworkInRange(eq(TEST_AUTO_UPGRADE_SSID)))
@@ -2992,7 +3038,7 @@
scanDetails, new HashSet<>(),
Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo,
false, ROLE_CLIENT_PRIMARY)),
- false, true, true, Collections.emptySet(), false);
+ false, true, true, Collections.emptySet(), false, 0);
assertEquals(2, candidates.size());
// Verify that OWE network is selected (assume offload is not supported.).
@@ -3018,7 +3064,8 @@
*/
@Test
public void testOweAutoUpgradeWithOpenNetworkWhenOpenTypeIsDisabled() {
- when(mClientModeManager.getSupportedFeatures()).thenReturn(WIFI_FEATURE_OWE);
+ when(mClientModeManager.getSupportedFeatures()).thenReturn(
+ createCapabilityBitset(WIFI_FEATURE_OWE));
when(mWifiGlobals.isOweUpgradeEnabled()).thenReturn(true);
when(mScanRequestProxy.isOpenOnlyNetworkInRange(eq(TEST_AUTO_UPGRADE_SSID)))
@@ -3036,7 +3083,7 @@
scanDetails, new HashSet<>(),
Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo,
false, ROLE_CLIENT_PRIMARY)),
- false, true, true, Collections.emptySet(), false);
+ false, true, true, Collections.emptySet(), false, 0);
// OPEN type is disabled, OPEN network is not matched.
assertEquals(1, candidates.size());
@@ -3053,7 +3100,8 @@
*/
@Test
public void testOweNoAutoUpgradeWithOpenNetworkWhenAutoUpgradeDisabled() {
- when(mClientModeManager.getSupportedFeatures()).thenReturn(WIFI_FEATURE_OWE);
+ when(mClientModeManager.getSupportedFeatures()).thenReturn(
+ createCapabilityBitset(WIFI_FEATURE_OWE));
when(mWifiGlobals.isOweUpgradeEnabled()).thenReturn(false);
when(mScanRequestProxy.isOpenOnlyNetworkInRange(eq(TEST_AUTO_UPGRADE_SSID)))
@@ -3069,7 +3117,7 @@
scanDetails, new HashSet<>(),
Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo,
false, ROLE_CLIENT_PRIMARY)),
- false, true, true, Collections.emptySet(), false);
+ false, true, true, Collections.emptySet(), false, 0);
assertEquals(2, candidates.size());
// Verify that OPEN network is selected.
@@ -3085,7 +3133,7 @@
*/
@Test
public void testOweNoAutoUpgradeWithOweNetworkWhenOweNotSupported() {
- when(mClientModeManager.getSupportedFeatures()).thenReturn(0L);
+ when(mClientModeManager.getSupportedFeatures()).thenReturn(new BitSet());
when(mWifiGlobals.isOweUpgradeEnabled()).thenReturn(true);
when(mScanRequestProxy.isOpenOnlyNetworkInRange(eq(TEST_AUTO_UPGRADE_SSID)))
@@ -3102,7 +3150,7 @@
scanDetails, new HashSet<>(),
Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo,
false, ROLE_CLIENT_PRIMARY)),
- false, true, true, Collections.emptySet(), false);
+ false, true, true, Collections.emptySet(), false, 0);
// The OWE-only network should be filtered.
assertEquals(1, candidates.size());
@@ -3135,7 +3183,7 @@
scanDetails, new HashSet<>(),
Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo,
false, ROLE_CLIENT_PRIMARY)),
- false, true, true, Collections.emptySet(), false);
+ false, true, true, Collections.emptySet(), false, 0);
assertEquals(2, candidates.size());
// Verify that WPA2 Enterprise network is selected (assume offload is not supported.).
@@ -3179,7 +3227,7 @@
scanDetails, new HashSet<>(),
Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo,
false, ROLE_CLIENT_PRIMARY)),
- false, true, true, Collections.emptySet(), false);
+ false, true, true, Collections.emptySet(), false, 0);
// WPA2 Enterprise type is disabled, WPA2 Enterprise network is not matched.
assertEquals(1, candidates.size());
@@ -3194,7 +3242,8 @@
@Test
public void verifySecurityParamsSelectionForPskSaeConfigAndSaeScan() {
- when(mClientModeManager.getSupportedFeatures()).thenReturn(WIFI_FEATURE_WPA3_SAE);
+ when(mClientModeManager.getSupportedFeatures())
+ .thenReturn(createCapabilityBitset(WIFI_FEATURE_WPA3_SAE));
when(mWifiGlobals.isWpa3SaeUpgradeEnabled()).thenReturn(true);
setupMultiConfigAndSingleScanAndVerify("[RSN-SAE-CCMP][ESS][MFPR]",
SECURITY_PSK | SECURITY_SAE, WifiConfiguration.SECURITY_TYPE_SAE);
@@ -3202,14 +3251,17 @@
@Test
public void verifySecurityParamsSelectionForPskSaeConfigAndSaeScanNegative() {
- when(mClientModeManager.getSupportedFeatures()).thenReturn(~WIFI_FEATURE_WPA3_SAE);
+ BitSet supportedFeatures = new BitSet();
+ supportedFeatures.set(WIFI_FEATURE_WPA3_SAE, false);
+ when(mClientModeManager.getSupportedFeatures()).thenReturn(supportedFeatures);
setupMultiConfigAndSingleScanAndVerify("[RSN-SAE-CCMP][ESS][MFPR]",
SECURITY_PSK | SECURITY_SAE, -1);
}
@Test
public void verifySecurityParamsSelectionForOpenOweConfigAndOweScan() {
- when(mClientModeManager.getSupportedFeatures()).thenReturn(WIFI_FEATURE_OWE);
+ when(mClientModeManager.getSupportedFeatures()).thenReturn(
+ createCapabilityBitset(WIFI_FEATURE_OWE));
when(mWifiGlobals.isOweUpgradeEnabled()).thenReturn(true);
setupMultiConfigAndSingleScanAndVerify("[OWE-SAE-CCMP][ESS][MFPR]",
SECURITY_NONE | SECURITY_OWE, WifiConfiguration.SECURITY_TYPE_OWE);
@@ -3217,7 +3269,9 @@
@Test
public void verifySecurityParamsSelectionForOpenOweConfigAndOweScanNegative() {
- when(mClientModeManager.getSupportedFeatures()).thenReturn(~WIFI_FEATURE_OWE);
+ BitSet supportedFeatures = new BitSet();
+ supportedFeatures.set(WIFI_FEATURE_OWE, false);
+ when(mClientModeManager.getSupportedFeatures()).thenReturn(supportedFeatures);
setupMultiConfigAndSingleScanAndVerify("[OWE-SAE-CCMP][ESS][MFPR]",
SECURITY_NONE | SECURITY_OWE, -1);
}
@@ -3251,7 +3305,7 @@
scanDetails, blocklist,
Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo,
false, ROLE_CLIENT_PRIMARY)),
- false, true, true, Collections.emptySet(), false);
+ false, true, true, Collections.emptySet(), false, 0);
assertNotNull(candidates);
if (expectedSecurityParamType == -1) {
assertEquals(0, candidates.size());
@@ -3271,7 +3325,8 @@
*/
@Test
public void testPskWithPskOnlyForPskSaeTransitionNetworks() {
- when(mClientModeManager.getSupportedFeatures()).thenReturn(WIFI_FEATURE_WPA3_SAE);
+ when(mClientModeManager.getSupportedFeatures())
+ .thenReturn(createCapabilityBitset(WIFI_FEATURE_WPA3_SAE));
when(mWifiGlobals.isWpa3SaeUpgradeEnabled()).thenReturn(true);
when(mWifiGlobals.isWpa3SaeUpgradeOffloadEnabled()).thenReturn(true);
@@ -3290,7 +3345,7 @@
scanDetails, new HashSet<>(),
Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo,
false, ROLE_CLIENT_PRIMARY)),
- false, true, true, Collections.emptySet(), false);
+ false, true, true, Collections.emptySet(), false, 0);
assertEquals(2, candidates.size());
// Verify that PSK network is still selected if offload is not supported
@@ -3308,7 +3363,8 @@
*/
@Test
public void testNetworkSelectionForUserSelectedNetwork() {
- when(mClientModeManager.getSupportedFeatures()).thenReturn(WIFI_FEATURE_WPA3_SAE);
+ when(mClientModeManager.getSupportedFeatures())
+ .thenReturn(createCapabilityBitset(WIFI_FEATURE_WPA3_SAE));
when(mWifiGlobals.isWpa3SaeUpgradeEnabled()).thenReturn(true);
ScanDetailsAndWifiConfigs scanDetailsAndConfigs = setupAutoUpgradeNetworks(
@@ -3398,7 +3454,7 @@
scanDetails, blocklist,
Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo,
false, ROLE_CLIENT_PRIMARY)),
- false, true, true, Collections.emptySet(), false);
+ false, true, true, Collections.emptySet(), false, 0);
return candidates;
}
diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiNetworkSelectorTestUtil.java b/service/tests/wifitests/src/com/android/server/wifi/WifiNetworkSelectorTestUtil.java
index 59e62ca..77c9809 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/WifiNetworkSelectorTestUtil.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/WifiNetworkSelectorTestUtil.java
@@ -46,6 +46,7 @@
import com.android.server.wifi.util.NativeUtil;
import java.util.ArrayList;
+import java.util.BitSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@@ -57,7 +58,7 @@
*/
public class WifiNetworkSelectorTestUtil {
private static final String TAG = "WifiNetworkSelectorTestUtil";
- private static final long SUPPORTED_FEATURES_ALL = Long.MAX_VALUE;
+
/**
* A class that holds a list of scanDetail and their associated WifiConfiguration.
*/
@@ -273,6 +274,9 @@
throw new IllegalArgumentException();
}
+ BitSet supportedFeaturesAll = new BitSet();
+ supportedFeaturesAll.set(0, 63); // mark all features as supported
+
Map<String, Integer> netIdMap = new HashMap<>();
int netId = 0;
@@ -292,7 +296,7 @@
|| (securities[index] & SECURITY_WAPI_PSK) != 0) {
configs[index].preSharedKey = "\"PA55W0RD\""; // needed to validate with PSK
}
- if (!WifiConfigurationUtil.validate(configs[index], SUPPORTED_FEATURES_ALL, true)) {
+ if (!WifiConfigurationUtil.validate(configs[index], supportedFeaturesAll, true)) {
throw new IllegalArgumentException("Invalid generated config: " + configs[index]);
}
}
diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiNetworkSuggestionsManagerTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiNetworkSuggestionsManagerTest.java
index 09f5969..00aa72a 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/WifiNetworkSuggestionsManagerTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/WifiNetworkSuggestionsManagerTest.java
@@ -31,6 +31,7 @@
import static com.android.server.wifi.WifiNetworkSuggestionsManager.NOTIFICATION_USER_ALLOWED_APP_INTENT_ACTION;
import static com.android.server.wifi.WifiNetworkSuggestionsManager.NOTIFICATION_USER_DISALLOWED_APP_INTENT_ACTION;
import static com.android.server.wifi.WifiNetworkSuggestionsManager.NOTIFICATION_USER_DISMISSED_INTENT_ACTION;
+import static com.android.server.wifi.TestUtil.createCapabilityBitset;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -265,7 +266,8 @@
.thenReturn(true);
when(mActiveModeWarden.getPrimaryClientModeManager()).thenReturn(mPrimaryClientModeManager);
when(mPrimaryClientModeManager.getSupportedFeatures()).thenReturn(
- WifiManager.WIFI_FEATURE_WPA3_SAE | WifiManager.WIFI_FEATURE_OWE);
+ createCapabilityBitset(
+ WifiManager.WIFI_FEATURE_WPA3_SAE, WifiManager.WIFI_FEATURE_OWE));
when(mWifiGlobals.isWpa3SaeUpgradeEnabled()).thenReturn(true);
when(mWifiGlobals.isOweUpgradeEnabled()).thenReturn(true);
when(mSsidTranslator.getAllPossibleOriginalSsids(any())).thenAnswer(
diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiPulledAtomLoggerTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiPulledAtomLoggerTest.java
index adaddf5..276bbca 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/WifiPulledAtomLoggerTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/WifiPulledAtomLoggerTest.java
@@ -184,12 +184,13 @@
when(mWifiInjector.getWakeupController()).thenReturn(mock(WakeupController.class));
when(mWifiInjector.getOpenNetworkNotifier()).thenReturn(mock(OpenNetworkNotifier.class));
when(mWifiInjector.getWifiPermissionsUtil()).thenReturn(mock(WifiPermissionsUtil.class));
+ when(mWifiInjector.getDeviceConfigFacade()).thenReturn(mock(DeviceConfigFacade.class));
- // Verify that all 8 settings were retrieved.
+ // Verify that all settings were retrieved.
List<StatsEvent> data = new ArrayList<>();
assertEquals(StatsManager.PULL_SUCCESS, mPullAtomCallbackArgumentCaptor.getValue()
.onPullAtom(WifiStatsLog.WIFI_SETTING_INFO, data));
- assertEquals(8, data.size());
+ assertEquals(9, data.size());
}
@Test
diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java
index 25cbb86..522967a 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java
@@ -66,6 +66,7 @@
import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_SECONDARY_TRANSIENT;
import static com.android.server.wifi.LocalOnlyHotspotRequestInfo.HOTSPOT_NO_ERROR;
import static com.android.server.wifi.SelfRecovery.REASON_API_CALL;
+import static com.android.server.wifi.TestUtil.createCapabilityBitset;
import static com.android.server.wifi.WifiConfigurationTestUtil.SECURITY_NONE;
import static com.android.server.wifi.WifiSettingsConfigStore.D2D_ALLOWED_WHEN_INFRA_STA_DISABLED;
import static com.android.server.wifi.WifiSettingsConfigStore.SHOW_DIALOG_WHEN_THIRD_PARTY_APPS_ENABLE_WIFI;
@@ -148,6 +149,7 @@
import android.net.NetworkStack;
import android.net.TetheringManager;
import android.net.Uri;
+import android.net.wifi.BlockingOption;
import android.net.wifi.CoexUnsafeChannel;
import android.net.wifi.IActionListener;
import android.net.wifi.IBooleanListener;
@@ -182,6 +184,7 @@
import android.net.wifi.IWifiLowLatencyLockListener;
import android.net.wifi.IWifiNetworkSelectionConfigListener;
import android.net.wifi.IWifiNetworkStateChangedListener;
+import android.net.wifi.IWifiStateChangedListener;
import android.net.wifi.IWifiVerboseLoggingStatusChangedListener;
import android.net.wifi.MscsParams;
import android.net.wifi.QosCharacteristics;
@@ -213,6 +216,7 @@
import android.net.wifi.hotspot2.pps.HomeSp;
import android.net.wifi.twt.TwtRequest;
import android.net.wifi.twt.TwtSessionCallback;
+import android.net.wifi.util.Environment;
import android.net.wifi.util.WifiResourceCache;
import android.os.Binder;
import android.os.Build;
@@ -248,6 +252,8 @@
import com.android.modules.utils.build.SdkLevel;
import com.android.server.wifi.WifiServiceImpl.LocalOnlyRequestorCallback;
import com.android.server.wifi.WifiServiceImpl.SoftApCallbackInternal;
+import com.android.server.wifi.WifiServiceImpl.ThreadStateListener;
+import com.android.server.wifi.WifiServiceImpl.UwbAdapterStateListener;
import com.android.server.wifi.b2b.WifiRoamingModeManager;
import com.android.server.wifi.coex.CoexManager;
import com.android.server.wifi.entitlement.PseudonymInfo;
@@ -284,6 +290,7 @@
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.BitSet;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
@@ -449,6 +456,7 @@
@Mock IDppCallback mDppCallback;
@Mock ILocalOnlyHotspotCallback mLohsCallback;
@Mock ICoexCallback mCoexCallback;
+ @Mock IWifiStateChangedListener mWifiStateChangedListener;
@Mock IScanResultsCallback mScanResultsCallback;
@Mock ISuggestionConnectionStatusListener mSuggestionConnectionStatusListener;
@Mock ILocalOnlyConnectionStatusListener mLocalOnlyConnectionStatusListener;
@@ -534,6 +542,7 @@
WifiInjector.sWifiInjector = mWifiInjector;
when(mRequestInfo.getPid()).thenReturn(mPid);
when(mRequestInfo2.getPid()).thenReturn(mPid2);
+ when(mWifiInjector.getContext()).thenReturn(mContext);
when(mWifiInjector.getUserManager()).thenReturn(mUserManager);
when(mWifiInjector.getWifiCountryCode()).thenReturn(mWifiCountryCode);
when(mWifiInjector.getWifiMetrics()).thenReturn(mWifiMetrics);
@@ -676,6 +685,7 @@
when(mWifiInjector.getSarManager()).thenReturn(mSarManager);
mClientModeManagers = Arrays.asList(mClientModeManager, mock(ClientModeManager.class));
when(mActiveModeWarden.getClientModeManagers()).thenReturn(mClientModeManagers);
+ when(mActiveModeWarden.getSupportedFeatureSet()).thenReturn(new BitSet());
when(mWifiInjector.getSelfRecovery()).thenReturn(mSelfRecovery);
when(mWifiInjector.getLastCallerInfoManager()).thenReturn(mLastCallerInfoManager);
when(mUserManager.getUserRestrictions()).thenReturn(mBundle);
@@ -701,6 +711,12 @@
}
}).when(mMakeBeforeBreakManager).stopAllSecondaryTransientClientModeManagers(any());
+ doAnswer(new AnswerWithArguments() {
+ public void answer(boolean isWepAllowed) {
+ when(mWifiGlobals.isWepAllowed()).thenReturn(isWepAllowed);
+ }
+ }).when(mWifiGlobals).setWepAllowed(anyBoolean());
+
when(mWifiSettingsConfigStore.get(eq(WIFI_WEP_ALLOWED))).thenReturn(true);
mWifiServiceImpl = makeWifiServiceImpl();
mDppCallback = new IDppCallback() {
@@ -3555,7 +3571,7 @@
mLooper.startAutoDispatch();
setupLohsPermissions();
int result = mWifiServiceImpl.startLocalOnlyHotspot(mLohsCallback, TEST_PACKAGE_NAME,
- TEST_FEATURE_ID, null, mExtras);
+ TEST_FEATURE_ID, null, mExtras, false);
mLooper.stopAutoDispatchAndIgnoreExceptions();
assertEquals(LocalOnlyHotspotCallback.REQUEST_REGISTERED, result);
verifyCheckChangePermission(TEST_PACKAGE_NAME);
@@ -3583,7 +3599,7 @@
.enforceCallingOrSelfPermission(eq(android.Manifest.permission.CHANGE_WIFI_STATE),
eq("WifiService"));
mWifiServiceImpl.startLocalOnlyHotspot(
- mLohsCallback, TEST_PACKAGE_NAME, TEST_FEATURE_ID, null, mExtras);
+ mLohsCallback, TEST_PACKAGE_NAME, TEST_FEATURE_ID, null, mExtras, false);
}
/**
@@ -3597,7 +3613,7 @@
eq(TEST_FEATURE_ID),
anyInt());
mWifiServiceImpl.startLocalOnlyHotspot(
- mLohsCallback, TEST_PACKAGE_NAME, TEST_FEATURE_ID, null, mExtras);
+ mLohsCallback, TEST_PACKAGE_NAME, TEST_FEATURE_ID, null, mExtras, false);
}
/**
@@ -3613,7 +3629,7 @@
.when(mWifiPermissionsUtil).enforceNearbyDevicesPermission(
any(), anyBoolean(), any());
mWifiServiceImpl.startLocalOnlyHotspot(
- mLohsCallback, TEST_PACKAGE_NAME, TEST_FEATURE_ID, null, mExtras);
+ mLohsCallback, TEST_PACKAGE_NAME, TEST_FEATURE_ID, null, mExtras, false);
}
/**
@@ -3627,7 +3643,7 @@
when(mWifiPermissionsUtil.isTargetSdkLessThan(anyString(),
eq(Build.VERSION_CODES.TIRAMISU), anyInt())).thenReturn(true);
mWifiServiceImpl.startLocalOnlyHotspot(
- mLohsCallback, TEST_PACKAGE_NAME, TEST_FEATURE_ID, null, mExtras);
+ mLohsCallback, TEST_PACKAGE_NAME, TEST_FEATURE_ID, null, mExtras, false);
verify(mWifiPermissionsUtil, never()).enforceNearbyDevicesPermission(any(), anyBoolean(),
any());
}
@@ -3640,7 +3656,7 @@
public void testStartLocalOnlyHotspotThrowsSecurityExceptionWithoutLocationEnabled() {
when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(false);
mWifiServiceImpl.startLocalOnlyHotspot(
- mLohsCallback, TEST_PACKAGE_NAME, TEST_FEATURE_ID, null, mExtras);
+ mLohsCallback, TEST_PACKAGE_NAME, TEST_FEATURE_ID, null, mExtras, false);
}
/**
@@ -3652,7 +3668,7 @@
when(mFrameworkFacade.isAppForeground(any(), anyInt())).thenReturn(false);
int result = mWifiServiceImpl.startLocalOnlyHotspot(
- mLohsCallback, TEST_PACKAGE_NAME, TEST_FEATURE_ID, null, mExtras);
+ mLohsCallback, TEST_PACKAGE_NAME, TEST_FEATURE_ID, null, mExtras, false);
assertEquals(LocalOnlyHotspotCallback.ERROR_INCOMPATIBLE_MODE, result);
}
@@ -3760,7 +3776,7 @@
when(mFrameworkFacade.isAppForeground(any(), anyInt())).thenReturn(true);
mLooper.dispatchAll();
int returnCode = mWifiServiceImpl.startLocalOnlyHotspot(
- mLohsCallback, TEST_PACKAGE_NAME, TEST_FEATURE_ID, null, mExtras);
+ mLohsCallback, TEST_PACKAGE_NAME, TEST_FEATURE_ID, null, mExtras, false);
assertEquals(ERROR_INCOMPATIBLE_MODE, returnCode);
}
@@ -3775,7 +3791,7 @@
eq(UserManager.DISALLOW_CONFIG_TETHERING), any()))
.thenReturn(true);
int returnCode = mWifiServiceImpl.startLocalOnlyHotspot(
- mLohsCallback, TEST_PACKAGE_NAME, TEST_FEATURE_ID, null, mExtras);
+ mLohsCallback, TEST_PACKAGE_NAME, TEST_FEATURE_ID, null, mExtras, false);
assertEquals(ERROR_TETHERING_DISALLOWED, returnCode);
}
@@ -3788,7 +3804,7 @@
// now do the second request that will fail
mWifiServiceImpl.startLocalOnlyHotspot(
- mLohsCallback, TEST_PACKAGE_NAME, TEST_FEATURE_ID, null, mExtras);
+ mLohsCallback, TEST_PACKAGE_NAME, TEST_FEATURE_ID, null, mExtras, false);
}
/**
@@ -3905,14 +3921,16 @@
@Test(expected = SecurityException.class)
public void testCustomLohs_FailsWithoutPermission() {
- SoftApConfiguration customConfig = new SoftApConfiguration.Builder()
- .setSsid("customConfig")
- .build();
+ SoftApConfiguration.Builder customConfigBuilder = new SoftApConfiguration.Builder()
+ .setSsid("customConfig");
+ if (Environment.isSdkAtLeastB()) {
+ customConfigBuilder.setUserConfiguration(false);
+ }
// set up basic permissions, but not NETWORK_SETUP_WIZARD
setupLohsPermissions();
setupWardenForCustomLohs();
mWifiServiceImpl.startLocalOnlyHotspot(mLohsCallback, TEST_PACKAGE_NAME, TEST_FEATURE_ID,
- customConfig, mExtras);
+ customConfigBuilder.build(), mExtras, true);
}
private static void nopDeathCallback(LocalOnlyHotspotRequestInfo requestor) {
@@ -3932,7 +3950,7 @@
new LocalOnlyHotspotRequestInfo(mLooper.getLooper(), new WorkSource(),
sharedCallback, WifiServiceImplTest::nopDeathCallback, null));
assertThat(mWifiServiceImpl.startLocalOnlyHotspot(exclusiveCallback, TEST_PACKAGE_NAME,
- TEST_FEATURE_ID, exclusiveConfig, mExtras)).isEqualTo(ERROR_GENERIC);
+ TEST_FEATURE_ID, exclusiveConfig, mExtras, true)).isEqualTo(ERROR_GENERIC);
stopAutoDispatchWithDispatchAllBeforeStopAndIgnoreExceptions(mLooper);
assertThat(sharedCallback.mIsStarted).isTrue();
assertThat(exclusiveCallback.mIsStarted).isFalse();
@@ -3953,7 +3971,7 @@
exclusiveCallback, WifiServiceImplTest::nopDeathCallback, exclusiveConfig));
stopAutoDispatchWithDispatchAllBeforeStopAndIgnoreExceptions(mLooper);
assertThat(mWifiServiceImpl.startLocalOnlyHotspot(sharedCallback, TEST_PACKAGE_NAME,
- TEST_FEATURE_ID, null, mExtras)).isEqualTo(ERROR_GENERIC);
+ TEST_FEATURE_ID, null, mExtras, false)).isEqualTo(ERROR_GENERIC);
assertThat(exclusiveCallback.mIsStarted).isTrue();
assertThat(sharedCallback.mIsStarted).isFalse();
}
@@ -3971,7 +3989,7 @@
setupForCustomLohs();
assertThat(
mWifiServiceImpl.startLocalOnlyHotspot(callback, TEST_PACKAGE_NAME, TEST_FEATURE_ID,
- config, mExtras)).isEqualTo(REQUEST_REGISTERED);
+ config, mExtras, true)).isEqualTo(REQUEST_REGISTERED);
stopAutoDispatchWithDispatchAllBeforeStopAndIgnoreExceptions(mLooper);
verify(mWifiApConfigStore).generateLocalOnlyHotspotConfig(
eq(mContext), eq(config), any());
@@ -3997,7 +4015,7 @@
setupForCustomLohs();
assertThat(
mWifiServiceImpl.startLocalOnlyHotspot(callback, TEST_PACKAGE_NAME, TEST_FEATURE_ID,
- config, mExtras)).isEqualTo(REQUEST_REGISTERED);
+ config, mExtras, true)).isEqualTo(REQUEST_REGISTERED);
stopAutoDispatchWithDispatchAllBeforeStopAndIgnoreExceptions(mLooper);
verify(mWifiApConfigStore).generateLocalOnlyHotspotConfig(
eq(mContext), eq(config), any());
@@ -4026,7 +4044,7 @@
setupForCustomLohs();
assertThat(
mWifiServiceImpl.startLocalOnlyHotspot(callback, TEST_PACKAGE_NAME, TEST_FEATURE_ID,
- customizedConfig, mExtras)).isEqualTo(REQUEST_REGISTERED);
+ customizedConfig, mExtras, true)).isEqualTo(REQUEST_REGISTERED);
stopAutoDispatchWithDispatchAllBeforeStopAndIgnoreExceptions(mLooper);
verify(mWifiApConfigStore).generateLocalOnlyHotspotConfig(
eq(mContext), eq(customizedConfig), any());
@@ -4057,7 +4075,7 @@
setupForCustomLohs();
assertThat(
mWifiServiceImpl.startLocalOnlyHotspot(callback, TEST_PACKAGE_NAME, TEST_FEATURE_ID,
- customizedConfig, mExtras)).isEqualTo(REQUEST_REGISTERED);
+ customizedConfig, mExtras, true)).isEqualTo(REQUEST_REGISTERED);
stopAutoDispatchWithDispatchAllBeforeStopAndIgnoreExceptions(mLooper);
// Use app's worksouce.
@@ -4330,6 +4348,19 @@
}
/**
+ * Verify that soft AP callback is called on ClientsDisconnected event
+ */
+ @Test
+ public void callsRegisteredCallbacksOnClientsDisconnectedEvent() throws Exception {
+ List<WifiClient> testClients = new ArrayList<>();
+ registerSoftApCallbackAndVerify(mClientSoftApCallback);
+
+ mStateMachineSoftApCallback.onClientsDisconnected(mTestSoftApInfo, testClients);
+ mLooper.dispatchAll();
+ verify(mClientSoftApCallback).onClientsDisconnected(eq(mTestSoftApInfo), eq(testClients));
+ }
+
+ /**
* Verify that mSoftApState and mSoftApNumClients in WifiServiceImpl are being updated on soft
* Ap events, even when no callbacks are registered.
*/
@@ -4745,7 +4776,7 @@
when(callback2.asBinder()).thenReturn(mock(IBinder.class));
int result = mWifiServiceImpl.startLocalOnlyHotspot(
- callback2, TEST_PACKAGE_NAME, TEST_FEATURE_ID, null, mExtras);
+ callback2, TEST_PACKAGE_NAME, TEST_FEATURE_ID, null, mExtras, false);
assertEquals(LocalOnlyHotspotCallback.REQUEST_REGISTERED, result);
mLooper.dispatchAll();
@@ -8959,7 +8990,7 @@
*/
@Test
public void getWifiActivityEnergyInfoAsyncFeatureUnsupported() throws Exception {
- when(mActiveModeWarden.getSupportedFeatureSet()).thenReturn(0L);
+ when(mActiveModeWarden.getSupportedFeatureSet()).thenReturn(new BitSet());
mWifiServiceImpl.getWifiActivityEnergyInfoAsync(mOnWifiActivityEnergyInfoListener);
verify(mOnWifiActivityEnergyInfoListener).onWifiActivityEnergyInfo(null);
@@ -8971,7 +9002,8 @@
*/
@Test
public void getWifiActivityEnergyInfoAsyncSuccess() throws Exception {
- when(mActiveModeWarden.getSupportedFeatureSet()).thenReturn(Long.MAX_VALUE);
+ when(mActiveModeWarden.getSupportedFeatureSet()).thenReturn(
+ createCapabilityBitset(WifiManager.WIFI_FEATURE_LINK_LAYER_STATS));
setupReportActivityInfo();
mWifiServiceImpl.getWifiActivityEnergyInfoAsync(mOnWifiActivityEnergyInfoListener);
mLooper.dispatchAll();
@@ -9229,18 +9261,20 @@
}
@Test
- public void getSupportedFeaturesVerboseLoggingThrottled() {
+ public void supportedFeaturesVerboseLoggingThrottled() {
mWifiServiceImpl.enableVerboseLogging(
WifiManager.VERBOSE_LOGGING_LEVEL_ENABLED); // this logs
when(mClock.getElapsedSinceBootMillis()).thenReturn(1000L);
- when(mActiveModeWarden.getSupportedFeatureSet()).thenReturn(0x110L);
- mWifiServiceImpl.getSupportedFeatures();
+ when(mActiveModeWarden.getSupportedFeatureSet()).thenReturn(
+ createCapabilityBitset(WifiManager.WIFI_FEATURE_P2P));
+ mWifiServiceImpl.isFeatureSupported(WifiManager.WIFI_FEATURE_P2P);
when(mClock.getElapsedSinceBootMillis()).thenReturn(1001L);
- mWifiServiceImpl.getSupportedFeatures(); // should not log
+ mWifiServiceImpl.isFeatureSupported(WifiManager.WIFI_FEATURE_P2P); // should not log
when(mClock.getElapsedSinceBootMillis()).thenReturn(5000L);
- mWifiServiceImpl.getSupportedFeatures();
- when(mActiveModeWarden.getSupportedFeatureSet()).thenReturn(0x100L);
- mWifiServiceImpl.getSupportedFeatures();
+ mWifiServiceImpl.isFeatureSupported(WifiManager.WIFI_FEATURE_P2P);
+ when(mActiveModeWarden.getSupportedFeatureSet()).thenReturn(createCapabilityBitset(
+ WifiManager.WIFI_FEATURE_P2P, WifiManager.WIFI_FEATURE_PASSPOINT));
+ mWifiServiceImpl.isFeatureSupported(WifiManager.WIFI_FEATURE_P2P);
verify(mLog, times(4)).info(any());
}
@@ -10174,7 +10208,7 @@
}
private List<WifiConfiguration> setupMultiTypeConfigs(
- long featureFlags, boolean saeAutoUpgradeEnabled, boolean oweAutoUpgradeEnabled) {
+ BitSet featureFlags, boolean saeAutoUpgradeEnabled, boolean oweAutoUpgradeEnabled) {
when(mActiveModeWarden.getSupportedFeatureSet()).thenReturn(featureFlags);
when(mWifiGlobals.isWpa3SaeUpgradeEnabled()).thenReturn(saeAutoUpgradeEnabled);
when(mWifiGlobals.isOweUpgradeEnabled()).thenReturn(oweAutoUpgradeEnabled);
@@ -10247,7 +10281,8 @@
*/
@Test
public void testGetConfiguredNetworksForMultiTypeConfigs() {
- long featureFlags = WifiManager.WIFI_FEATURE_WPA3_SAE | WifiManager.WIFI_FEATURE_OWE;
+ BitSet featureFlags = createCapabilityBitset(
+ WifiManager.WIFI_FEATURE_WPA3_SAE, WifiManager.WIFI_FEATURE_OWE);
List<WifiConfiguration> testConfigs = setupMultiTypeConfigs(
featureFlags, true, true);
when(mWifiConfigManager.getSavedNetworks(anyInt()))
@@ -10279,7 +10314,8 @@
*/
@Test
public void testGetConfiguredNetworksForMultiTypeConfigsWithoutAutoUpgradeEnabled() {
- long featureFlags = WifiManager.WIFI_FEATURE_WPA3_SAE | WifiManager.WIFI_FEATURE_OWE;
+ BitSet featureFlags = createCapabilityBitset(
+ WifiManager.WIFI_FEATURE_WPA3_SAE, WifiManager.WIFI_FEATURE_OWE);
List<WifiConfiguration> testConfigs = setupMultiTypeConfigs(
featureFlags, false, false);
when(mWifiConfigManager.getSavedNetworks(anyInt()))
@@ -10311,7 +10347,7 @@
*/
@Test
public void testGetConfiguredNetworksForMultiTypeConfigsWithoutHwSupport() {
- long featureFlags = 0L;
+ BitSet featureFlags = new BitSet();
List<WifiConfiguration> testConfigs = setupMultiTypeConfigs(
featureFlags, true, true);
when(mWifiConfigManager.getSavedNetworks(anyInt()))
@@ -10539,7 +10575,7 @@
assumeTrue(SdkLevel.isAtLeastT());
when(mWifiGlobals.isBackgroundScanSupported()).thenReturn(true);
when(mActiveModeWarden.getSupportedFeatureSet())
- .thenReturn(WifiManager.WIFI_FEATURE_PNO);
+ .thenReturn(createCapabilityBitset(WifiManager.WIFI_FEATURE_PNO));
when(mWifiPermissionsUtil.checkRequestCompanionProfileAutomotiveProjectionPermission(
anyInt())).thenReturn(true);
when(mWifiPermissionsUtil.checkCallersLocationPermissionInManifest(
@@ -10559,7 +10595,7 @@
@Test
public void testSetExternalPnoScanRequest_PnoNotSupported() throws Exception {
assumeTrue(SdkLevel.isAtLeastT());
- when(mActiveModeWarden.getSupportedFeatureSet()).thenReturn(0L);
+ when(mActiveModeWarden.getSupportedFeatureSet()).thenReturn(new BitSet());
when(mWifiPermissionsUtil.checkRequestCompanionProfileAutomotiveProjectionPermission(
anyInt())).thenReturn(true);
when(mWifiPermissionsUtil.checkCallersLocationPermissionInManifest(
@@ -10781,7 +10817,7 @@
// Expect the result is registered but it should get failure because non-supported
// configuration
int result = mWifiServiceImpl.startLocalOnlyHotspot(mLohsCallback, TEST_PACKAGE_NAME,
- TEST_FEATURE_ID, customizedConfig, mExtras);
+ TEST_FEATURE_ID, customizedConfig, mExtras, true);
assertEquals(LocalOnlyHotspotCallback.REQUEST_REGISTERED, result);
mLooper.dispatchAll();
verify(mLohsCallback).onHotspotFailed(ERROR_GENERIC);
@@ -12326,17 +12362,24 @@
@Test
public void testSetWepAllowedWithPermission() {
+ // Test if WIFI_WEP_ALLOWED starts with false.
when(mWifiSettingsConfigStore.get(eq(WIFI_WEP_ALLOWED))).thenReturn(false);
mWifiServiceImpl.checkAndStartWifi();
mLooper.dispatchAll();
verify(mWifiSettingsConfigStore).get(eq(WIFI_WEP_ALLOWED));
verify(mWifiGlobals).setWepAllowed(eq(false));
+ verify(mWifiSettingsConfigStore).registerChangeListener(
+ eq(WIFI_WEP_ALLOWED),
+ mWepAllowedSettingChangedListenerCaptor.capture(),
+ any(Handler.class));
// verify setWepAllowed with MANAGE_WIFI_NETWORK_SETTING
when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(true);
mWifiServiceImpl.setWepAllowed(true);
+ verify(mWifiSettingsConfigStore).put(eq(WIFI_WEP_ALLOWED), eq(true));
+ mWepAllowedSettingChangedListenerCaptor.getValue()
+ .onSettingsChanged(WIFI_WEP_ALLOWED, true);
mLooper.dispatchAll();
verify(mWifiGlobals).setWepAllowed(true);
- verify(mWifiSettingsConfigStore).put(eq(WIFI_WEP_ALLOWED), eq(true));
}
@Test
@@ -12352,10 +12395,21 @@
when(mockWifiInfoWpa.getCurrentSecurityType()).thenReturn(WifiInfo.SECURITY_TYPE_PSK);
when(cmmWep.getConnectionInfo()).thenReturn(mockWifiInfoWep);
when(cmmWpa.getConnectionInfo()).thenReturn(mockWifiInfoWpa);
+ mWifiServiceImpl.checkAndStartWifi();
+ mLooper.dispatchAll();
+ verify(mWifiSettingsConfigStore).get(eq(WIFI_WEP_ALLOWED));
+ verify(mWifiGlobals).setWepAllowed(eq(true));
+ verify(mWifiSettingsConfigStore).registerChangeListener(
+ eq(WIFI_WEP_ALLOWED),
+ mWepAllowedSettingChangedListenerCaptor.capture(),
+ any(Handler.class));
+
mWifiServiceImpl.setWepAllowed(false);
+ verify(mWifiSettingsConfigStore).put(eq(WIFI_WEP_ALLOWED), eq(false));
+ mWepAllowedSettingChangedListenerCaptor.getValue()
+ .onSettingsChanged(WIFI_WEP_ALLOWED, false);
mLooper.dispatchAll();
verify(mWifiGlobals).setWepAllowed(false);
- verify(mWifiSettingsConfigStore).put(eq(WIFI_WEP_ALLOWED), eq(false));
// Only WEP disconnect
verify(cmmWep).disconnect();
verify(cmmWpa, never()).disconnect();
@@ -12493,8 +12547,8 @@
@Test
public void testSetPerSsidRoamingModeByDeviceAdmin() throws RemoteException {
assumeTrue(SdkLevel.isAtLeastV());
- when(mActiveModeWarden.getSupportedFeatureSet())
- .thenReturn(WifiManager.WIFI_FEATURE_AGGRESSIVE_ROAMING_MODE_SUPPORT);
+ when(mActiveModeWarden.getSupportedFeatureSet()).thenReturn(
+ createCapabilityBitset(WifiManager.WIFI_FEATURE_AGGRESSIVE_ROAMING_MODE_SUPPORT));
assertThrows(SecurityException.class,
() -> mWifiServiceImpl.setPerSsidRoamingMode(
WifiSsid.fromString(TEST_SSID_WITH_QUOTES),
@@ -12516,8 +12570,8 @@
@Test
public void testSetPerSsidRoamingModeByNonAdmin() throws RemoteException {
assumeTrue(SdkLevel.isAtLeastV());
- when(mActiveModeWarden.getSupportedFeatureSet())
- .thenReturn(WifiManager.WIFI_FEATURE_AGGRESSIVE_ROAMING_MODE_SUPPORT);
+ when(mActiveModeWarden.getSupportedFeatureSet()).thenReturn(
+ createCapabilityBitset(WifiManager.WIFI_FEATURE_AGGRESSIVE_ROAMING_MODE_SUPPORT));
assertThrows(SecurityException.class,
() -> mWifiServiceImpl.setPerSsidRoamingMode(
WifiSsid.fromString(TEST_SSID_WITH_QUOTES),
@@ -12539,8 +12593,8 @@
@Test
public void testRemovePerSsidRoamingModeByDeviceAdmin() throws RemoteException {
assumeTrue(SdkLevel.isAtLeastV());
- when(mActiveModeWarden.getSupportedFeatureSet())
- .thenReturn(WifiManager.WIFI_FEATURE_AGGRESSIVE_ROAMING_MODE_SUPPORT);
+ when(mActiveModeWarden.getSupportedFeatureSet()).thenReturn(
+ createCapabilityBitset(WifiManager.WIFI_FEATURE_AGGRESSIVE_ROAMING_MODE_SUPPORT));
assertThrows(SecurityException.class,
() -> mWifiServiceImpl.removePerSsidRoamingMode(
WifiSsid.fromString(TEST_SSID_WITH_QUOTES), TEST_PACKAGE_NAME));
@@ -12557,8 +12611,8 @@
@Test
public void testRemovePerSsidRoamingModeByNonAdmin() throws RemoteException {
assumeTrue(SdkLevel.isAtLeastV());
- when(mActiveModeWarden.getSupportedFeatureSet())
- .thenReturn(WifiManager.WIFI_FEATURE_AGGRESSIVE_ROAMING_MODE_SUPPORT);
+ when(mActiveModeWarden.getSupportedFeatureSet()).thenReturn(
+ createCapabilityBitset(WifiManager.WIFI_FEATURE_AGGRESSIVE_ROAMING_MODE_SUPPORT));
assertThrows(SecurityException.class,
() -> mWifiServiceImpl.removePerSsidRoamingMode(
WifiSsid.fromString(TEST_SSID_WITH_QUOTES), TEST_PACKAGE_NAME));
@@ -12574,8 +12628,8 @@
@Test
public void testGetPerSsidRoamingModesByDeviceAdmin() throws RemoteException {
assumeTrue(SdkLevel.isAtLeastV());
- when(mActiveModeWarden.getSupportedFeatureSet())
- .thenReturn(WifiManager.WIFI_FEATURE_AGGRESSIVE_ROAMING_MODE_SUPPORT);
+ when(mActiveModeWarden.getSupportedFeatureSet()).thenReturn(
+ createCapabilityBitset(WifiManager.WIFI_FEATURE_AGGRESSIVE_ROAMING_MODE_SUPPORT));
IMapListener listener = mock(IMapListener.class);
InOrder inOrder = inOrder(listener);
assertThrows(SecurityException.class,
@@ -12602,8 +12656,8 @@
@Test
public void testGetPerSsidRoamingModesByNonAdmin() throws RemoteException {
assumeTrue(SdkLevel.isAtLeastV());
- when(mActiveModeWarden.getSupportedFeatureSet())
- .thenReturn(WifiManager.WIFI_FEATURE_AGGRESSIVE_ROAMING_MODE_SUPPORT);
+ when(mActiveModeWarden.getSupportedFeatureSet()).thenReturn(
+ createCapabilityBitset(WifiManager.WIFI_FEATURE_AGGRESSIVE_ROAMING_MODE_SUPPORT));
IMapListener listener = mock(IMapListener.class);
InOrder inOrder = inOrder(listener);
assertThrows(SecurityException.class,
@@ -12633,9 +12687,9 @@
when(mWifiGlobals.isSwPnoEnabled()).thenReturn(isSwPnoEnabled);
if (isPnoFeatureSet) {
when(mActiveModeWarden.getSupportedFeatureSet())
- .thenReturn(WifiManager.WIFI_FEATURE_PNO);
+ .thenReturn(createCapabilityBitset(WifiManager.WIFI_FEATURE_PNO));
} else {
- when(mActiveModeWarden.getSupportedFeatureSet()).thenReturn(0L);
+ when(mActiveModeWarden.getSupportedFeatureSet()).thenReturn(new BitSet());
}
assertEquals(mWifiServiceImpl.isPnoSupported(),
(isBackgroundScanSupported && isPnoFeatureSet) || isSwPnoEnabled);
@@ -12881,7 +12935,8 @@
@Test
public void testGetWifiConfigForMatchedNetworkSuggestionsSharedWithUserForMultiTypeConfigs() {
- long featureFlags = WifiManager.WIFI_FEATURE_WPA3_SAE | WifiManager.WIFI_FEATURE_OWE;
+ BitSet featureFlags = createCapabilityBitset(
+ WifiManager.WIFI_FEATURE_WPA3_SAE, WifiManager.WIFI_FEATURE_OWE);
List<WifiConfiguration> testConfigs = setupMultiTypeConfigs(featureFlags, true, true);
when(mWifiNetworkSuggestionsManager
.getWifiConfigForMatchedNetworkSuggestionsSharedWithUser(anyList()))
@@ -12906,4 +12961,221 @@
expectedConfigs, configs.getList());
}
+ @Test
+ public void testSetAutojoinDisallowedSecurityTypesWithPermission() throws RemoteException {
+ assumeTrue(SdkLevel.isAtLeastT());
+ // No permission to call API
+ when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(false);
+ when(mWifiPermissionsUtil.checkManageWifiNetworkSelectionPermission(anyInt()))
+ .thenReturn(false);
+ assertThrows(SecurityException.class,
+ () -> mWifiServiceImpl.setAutojoinDisallowedSecurityTypes(0/*restrict none*/,
+ mExtras));
+ // Has permission to call API
+ when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(true);
+ // Null argument
+ assertThrows(IllegalArgumentException.class,
+ () -> mWifiServiceImpl.setAutojoinDisallowedSecurityTypes(0/*restrict none*/,
+ null));
+ // Invalid argument
+ assertThrows(IllegalArgumentException.class,
+ () -> mWifiServiceImpl.setAutojoinDisallowedSecurityTypes(
+ 0x1 << WifiInfo.SECURITY_TYPE_OWE, mExtras));
+ assertThrows(IllegalArgumentException.class,
+ () -> mWifiServiceImpl.setAutojoinDisallowedSecurityTypes(
+ 0x1 << WifiInfo.SECURITY_TYPE_SAE, mExtras));
+ assertThrows(IllegalArgumentException.class,
+ () -> mWifiServiceImpl.setAutojoinDisallowedSecurityTypes(
+ 0x1 << WifiInfo.SECURITY_TYPE_EAP_WPA3_ENTERPRISE, mExtras));
+ // Valid argument
+ int restrictions = (0x1 << WifiInfo.SECURITY_TYPE_OPEN)
+ | (0x1 << WifiInfo.SECURITY_TYPE_OWE) | (0x1 << WifiInfo.SECURITY_TYPE_WEP);
+ mWifiServiceImpl.setAutojoinDisallowedSecurityTypes(restrictions, mExtras);
+ mLooper.dispatchAll();
+ verify(mWifiConnectivityManager).setAutojoinDisallowedSecurityTypes(eq(restrictions));
+ }
+
+ @Test
+ public void testGetAutojoinDisallowedSecurityTypesWithPermission() throws RemoteException {
+ assumeTrue(SdkLevel.isAtLeastT());
+ // Mock listener.
+ IIntegerListener listener = mock(IIntegerListener.class);
+ InOrder inOrder = inOrder(listener);
+ // No permission to call API
+ when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(false);
+ when(mWifiPermissionsUtil.checkManageWifiNetworkSelectionPermission(anyInt()))
+ .thenReturn(false);
+ assertThrows(SecurityException.class,
+ () -> mWifiServiceImpl.getAutojoinDisallowedSecurityTypes(listener, mExtras));
+ // Null arguments
+ assertThrows(IllegalArgumentException.class,
+ () -> mWifiServiceImpl.getAutojoinDisallowedSecurityTypes(null, mExtras));
+ assertThrows(IllegalArgumentException.class,
+ () -> mWifiServiceImpl.getAutojoinDisallowedSecurityTypes(listener, null));
+ // has permission to call API
+ when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(true);
+ when(mWifiConnectivityManager.getAutojoinDisallowedSecurityTypes()).thenReturn(7);
+ mWifiServiceImpl.getAutojoinDisallowedSecurityTypes(listener, mExtras);
+ mLooper.dispatchAll();
+ inOrder.verify(listener).onResult(7);
+ }
+ /**
+ * Verify UwbManager.AdapterStateCallback onStateChanged could update mLastUwbState in
+ * WifiMetrics properly
+ */
+ @Test
+ public void testServiceImplAdapterStateCallback() {
+ assumeTrue(SdkLevel.isAtLeastT());
+ UwbAdapterStateListener uwbAdapterStateListener =
+ mWifiServiceImpl.new UwbAdapterStateListener();
+
+ uwbAdapterStateListener.onStateChanged(2, 1);
+ verify(mWifiMetrics).setLastUwbState(2);
+ }
+
+ /**
+ * Verify ThreadNetworkController.StateCallback onDeviceRoleChanged could update
+ * mLastThreadDeviceRole in WifiMetrics properly
+ */
+ @Test
+ public void testServiceImplThreadStateCallback() {
+ assumeTrue(SdkLevel.isAtLeastV());
+ ThreadStateListener threadStateListener =
+ mWifiServiceImpl.new ThreadStateListener();
+
+ threadStateListener.onDeviceRoleChanged(3);
+ verify(mWifiMetrics).setLastThreadDeviceRole(3);
+ }
+
+ @Test
+ public void testSetQueryAllowedWhenWepUsageControllerSupported() {
+ when(mFeatureFlags.wepDisabledInApm()).thenReturn(true);
+ WepNetworkUsageController testWepNetworkUsageController =
+ mock(WepNetworkUsageController.class);
+ when(mWifiInjector.getWepNetworkUsageController())
+ .thenReturn(testWepNetworkUsageController);
+ when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(true);
+ ConcreteClientModeManager cmmWep = mock(ConcreteClientModeManager.class);
+ WifiInfo mockWifiInfoWep = mock(WifiInfo.class);
+ List<ClientModeManager> cmms = Arrays.asList(cmmWep);
+ when(mActiveModeWarden.getClientModeManagers()).thenReturn(cmms);
+ when(mockWifiInfoWep.getCurrentSecurityType()).thenReturn(WifiInfo.SECURITY_TYPE_WEP);
+ when(cmmWep.getConnectionInfo()).thenReturn(mockWifiInfoWep);
+ mWifiServiceImpl = makeWifiServiceImpl();
+ mWifiServiceImpl.checkAndStartWifi();
+ mWifiServiceImpl.handleBootCompleted();
+ mLooper.dispatchAll();
+ // Verify boot complete go through the new design.
+ verify(mWifiSettingsConfigStore, never()).registerChangeListener(
+ eq(WIFI_WEP_ALLOWED),
+ mWepAllowedSettingChangedListenerCaptor.capture(),
+ any(Handler.class));
+ verify(mWifiGlobals, never()).setWepAllowed(anyBoolean());
+ verify(testWepNetworkUsageController).handleBootCompleted();
+
+ mWifiServiceImpl.setWepAllowed(false);
+ mLooper.dispatchAll();
+ verify(mWifiGlobals, never()).setWepAllowed(anyBoolean());
+ verify(mWifiSettingsConfigStore).put(eq(WIFI_WEP_ALLOWED), eq(false));
+ // WEP disconnect logic moved to WepNetworkUsageController.
+ verify(cmmWep, never()).disconnect();
+ verify(mWifiGlobals, never()).setWepAllowed(anyBoolean());
+ }
+
+ @Test
+ public void testUpdateSoftApCapabilityCheckMLOSupport() throws Exception {
+ lenient().when(SubscriptionManager.getActiveDataSubscriptionId())
+ .thenReturn(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID);
+ ArgumentCaptor<SoftApCapability> capabilityArgumentCaptor = ArgumentCaptor.forClass(
+ SoftApCapability.class);
+ when(mWifiNative.isMLDApSupportMLO()).thenReturn(true);
+ mWifiServiceImpl.checkAndStartWifi();
+ mLooper.dispatchAll();
+ verify(mContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
+ argThat((IntentFilter filter) ->
+ filter.hasAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED)),
+ isNull(),
+ any(Handler.class));
+
+ // Send the broadcast
+ Intent intent = new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
+ mBroadcastReceiverCaptor.getValue().onReceive(mContext, intent);
+ mLooper.dispatchAll();
+ verify(mActiveModeWarden).updateSoftApCapability(capabilityArgumentCaptor.capture(),
+ eq(WifiManager.IFACE_IP_MODE_TETHERED));
+ assertTrue(capabilityArgumentCaptor.getValue()
+ .areFeaturesSupported(SoftApCapability.SOFTAP_FEATURE_MLO));
+ }
+
+ @Test
+ public void testCustomUserLohs() {
+ assumeTrue(Environment.isSdkAtLeastB());
+ SoftApConfiguration customConfig = new SoftApConfiguration.Builder()
+ .setSsid("customConfig")
+ .build();
+ assertThrows(SecurityException.class,
+ () -> mWifiServiceImpl.startLocalOnlyHotspot(
+ mLohsCallback, TEST_PACKAGE_NAME, TEST_FEATURE_ID,
+ customConfig, mExtras, false));
+ setupLohsPermissions();
+ mWifiServiceImpl.startLocalOnlyHotspot(mLohsCallback, TEST_PACKAGE_NAME, TEST_FEATURE_ID,
+ customConfig, mExtras, false);
+ }
+
+ @Test
+ public void testDisallowCurrentSuggestedNetwork() {
+ BlockingOption blockingOption = new BlockingOption.Builder(100).build();
+ WifiInfo info = new WifiInfo();
+ info.setRequestingPackageName(TEST_PACKAGE_NAME);
+ when(mActiveModeWarden.getWifiState()).thenReturn(WIFI_STATE_ENABLED);
+ when(mActiveModeWarden.getConnectionInfo()).thenReturn(info);
+ mWifiServiceImpl.disallowCurrentSuggestedNetwork(blockingOption, TEST_PACKAGE_NAME);
+ mLooper.dispatchAll();
+ verify(mClientModeManager).blockNetwork(eq(blockingOption));
+ }
+
+ /**
+ * Test add and remove listener will go to ActiveModeWarden.
+ */
+ @Test
+ public void testAddRemoveWifiStateChangedListener() throws Exception {
+ assumeTrue(SdkLevel.isAtLeastS());
+ when(mWifiStateChangedListener.asBinder()).thenReturn(mAppBinder);
+ mWifiServiceImpl.addWifiStateChangedListener(mWifiStateChangedListener);
+ mLooper.dispatchAll();
+ verify(mActiveModeWarden).addWifiStateChangedListener(mWifiStateChangedListener);
+ mWifiServiceImpl.removeWifiStateChangedListener(mWifiStateChangedListener);
+ mLooper.dispatchAll();
+ verify(mActiveModeWarden).removeWifiStateChangedListener(mWifiStateChangedListener);
+ }
+
+ /**
+ * Verify that a call to addWifiStateChangedListener throws a SecurityException if the
+ * caller does not have the ACCESS_WIFI_STATE permission.
+ */
+ @Test
+ public void testAddWifiStateChangedListenerThrowsSecurityExceptionOnMissingPermissions() {
+ doThrow(new SecurityException()).when(mContext)
+ .enforceCallingOrSelfPermission(eq(ACCESS_WIFI_STATE),
+ eq("WifiService"));
+ try {
+ mWifiServiceImpl.addWifiStateChangedListener(mWifiStateChangedListener);
+ fail("expected SecurityException");
+ } catch (SecurityException expected) { }
+ }
+
+ /**
+ * Verify that a call to removeWifiStateChangedListener throws a SecurityException if the caller
+ * does not have the ACCESS_WIFI_STATE permission.
+ */
+ @Test
+ public void testRemoveWifiStateChangedListenerThrowsSecurityExceptionOnMissingPermissions() {
+ doThrow(new SecurityException()).when(mContext)
+ .enforceCallingOrSelfPermission(eq(ACCESS_WIFI_STATE),
+ eq("WifiService"));
+ try {
+ mWifiServiceImpl.addWifiStateChangedListener(mWifiStateChangedListener);
+ fail("expected SecurityException");
+ } catch (SecurityException expected) { }
+ }
}
diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiShellCommandTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiShellCommandTest.java
index a63c4d4..d972c23 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/WifiShellCommandTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/WifiShellCommandTest.java
@@ -598,7 +598,7 @@
ArgumentCaptor<SoftApConfiguration> softApConfigurationCaptor = ArgumentCaptor.forClass(
SoftApConfiguration.class);
verify(mWifiService).startLocalOnlyHotspot(any(), eq(SHELL_PACKAGE_NAME), any(),
- softApConfigurationCaptor.capture(), any());
+ softApConfigurationCaptor.capture(), any(), eq(false));
assertEquals(SoftApConfiguration.BAND_5GHZ,
softApConfigurationCaptor.getValue().getBand());
assertEquals(SoftApConfiguration.SECURITY_TYPE_WPA2_PSK,
diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiVendorHalTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiVendorHalTest.java
index 0862fd7..b1ba78e 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/WifiVendorHalTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/WifiVendorHalTest.java
@@ -18,7 +18,7 @@
import static com.android.server.wifi.HalDeviceManager.HDM_CREATE_IFACE_AP;
import static com.android.server.wifi.HalDeviceManager.HDM_CREATE_IFACE_STA;
-import static com.android.server.wifi.util.GeneralUtil.longToBitset;
+import static com.android.server.wifi.TestUtil.createCapabilityBitset;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
@@ -32,7 +32,6 @@
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyBoolean;
import static org.mockito.Mockito.anyInt;
-import static org.mockito.Mockito.anyLong;
import static org.mockito.Mockito.anyObject;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.eq;
@@ -175,7 +174,7 @@
}).when(mHalDeviceManager).stop();
when(mHalDeviceManager.createStaIface(any(), any(), any(), eq(mConcreteClientModeManager)))
.thenReturn(mWifiStaIface);
- when(mHalDeviceManager.createApIface(anyLong(), any(), any(), any(), anyBoolean(),
+ when(mHalDeviceManager.createApIface(any(), any(), any(), any(), anyBoolean(),
eq(mSoftApManager), anyList()))
.thenReturn(mWifiApIface);
when(mHalDeviceManager.removeIface(any())).thenReturn(true);
@@ -256,7 +255,7 @@
verify(mWifiChip).registerCallback(any(WifiChip.Callback.class));
verify(mHalDeviceManager, never()).createApIface(
- anyLong(), any(), any(), any(), anyBoolean(), eq(mSoftApManager), anyList());
+ any(), any(), any(), any(), anyBoolean(), eq(mSoftApManager), anyList());
}
/**
@@ -280,7 +279,7 @@
verify(mHalDeviceManager, never()).createStaIface(any(), any(), any(),
eq(mConcreteClientModeManager));
verify(mHalDeviceManager, never()).createApIface(
- anyLong(), any(), any(), any(), anyBoolean(), eq(mSoftApManager), anyList());
+ any(), any(), any(), any(), anyBoolean(), eq(mSoftApManager), anyList());
verify(mHalDeviceManager, never()).getChip(any(WifiHal.WifiInterface.class));
verify(mWifiStaIface, never())
.registerFrameworkCallback(any(WifiStaIface.Callback.class));
@@ -303,7 +302,7 @@
verify(mHalDeviceManager).stop();
verify(mHalDeviceManager, never()).createApIface(
- anyLong(), any(), any(), any(), anyBoolean(), eq(mSoftApManager), anyList());
+ any(), any(), any(), any(), anyBoolean(), eq(mSoftApManager), anyList());
verify(mHalDeviceManager, never()).getChip(any(WifiHal.WifiInterface.class));
verify(mWifiStaIface, never())
.registerFrameworkCallback(any(WifiStaIface.Callback.class));
@@ -327,7 +326,7 @@
verify(mWifiStaIface).registerFrameworkCallback(any(WifiStaIface.Callback.class));
verify(mHalDeviceManager, never()).createApIface(
- anyLong(), any(), any(), any(), anyBoolean(), eq(mSoftApManager), anyList());
+ any(), any(), any(), any(), anyBoolean(), eq(mSoftApManager), anyList());
}
/**
@@ -349,7 +348,7 @@
verify(mHalDeviceManager, never()).getChip(any(WifiHal.WifiInterface.class));
verify(mHalDeviceManager, never()).createApIface(
- anyLong(), any(), any(), any(), anyBoolean(), eq(mSoftApManager), anyList());
+ any(), any(), any(), any(), anyBoolean(), eq(mSoftApManager), anyList());
}
/**
@@ -372,7 +371,7 @@
verify(mWifiChip).registerCallback(any(WifiChip.Callback.class));
verify(mHalDeviceManager, never()).createApIface(
- anyLong(), any(), any(), any(), anyBoolean(), eq(mSoftApManager), anyList());
+ any(), any(), any(), any(), anyBoolean(), eq(mSoftApManager), anyList());
}
/**
@@ -396,7 +395,7 @@
verify(mHalDeviceManager, times(2)).isStarted();
verify(mHalDeviceManager, never()).createApIface(
- anyLong(), any(), any(), any(), anyBoolean(), eq(mSoftApManager), anyList());
+ any(), any(), any(), any(), anyBoolean(), eq(mSoftApManager), anyList());
}
/**
@@ -417,7 +416,7 @@
verify(mHalDeviceManager).start();
verify(mHalDeviceManager).stop();
verify(mHalDeviceManager).createApIface(
- anyLong(), any(), any(), any(), anyBoolean(), eq(mSoftApManager), anyList());
+ any(), any(), any(), any(), anyBoolean(), eq(mSoftApManager), anyList());
verify(mHalDeviceManager).getChip(eq(mWifiApIface));
verify(mHalDeviceManager, times(2)).isReady();
verify(mHalDeviceManager, times(2)).isStarted();
@@ -475,7 +474,7 @@
assertTrue(mWifiVendorHal.isHalStarted());
verify(mHalDeviceManager).start();
- verify(mHalDeviceManager).createApIface(anyLong(),
+ verify(mHalDeviceManager).createApIface(any(),
internalListenerCaptor.capture(), any(), eq(TEST_WORKSOURCE), eq(false),
eq(mSoftApManager), anyList());
verify(mHalDeviceManager).getChip(eq(mWifiApIface));
@@ -555,9 +554,9 @@
*/
@Test
public void testGetSupportedFeatures() throws Exception {
- BitSet staIfaceCaps = longToBitset(
- WifiManager.WIFI_FEATURE_SCANNER | WifiManager.WIFI_FEATURE_LINK_LAYER_STATS);
- BitSet chipCaps = longToBitset(WifiManager.WIFI_FEATURE_TX_POWER_LIMIT);
+ BitSet staIfaceCaps = createCapabilityBitset(
+ WifiManager.WIFI_FEATURE_SCANNER, WifiManager.WIFI_FEATURE_LINK_LAYER_STATS);
+ BitSet chipCaps = createCapabilityBitset(WifiManager.WIFI_FEATURE_TX_POWER_LIMIT);
WifiChip.Response<BitSet> chipCapsResponse = new WifiChip.Response<>(chipCaps);
chipCapsResponse.setStatusCode(WifiHal.WIFI_STATUS_SUCCESS);
when(mWifiStaIface.getCapabilities()).thenReturn(staIfaceCaps);
@@ -570,15 +569,13 @@
when(mWifiGlobals.isWpa3SaeH2eSupported()).thenReturn(true);
when(mHalDeviceManager.is24g5gDbsSupported(any())).thenReturn(true);
- BitSet expectedFeatureSet = longToBitset(
- WifiManager.WIFI_FEATURE_SCANNER
- | WifiManager.WIFI_FEATURE_LINK_LAYER_STATS
- | WifiManager.WIFI_FEATURE_TX_POWER_LIMIT
- | WifiManager.WIFI_FEATURE_INFRA
- | WifiManager.WIFI_FEATURE_P2P
- | WifiManager.WIFI_FEATURE_SAE_H2E
- | WifiManager.WIFI_FEATURE_DUAL_BAND_SIMULTANEOUS
- );
+ BitSet expectedFeatureSet = createCapabilityBitset(WifiManager.WIFI_FEATURE_SCANNER,
+ WifiManager.WIFI_FEATURE_LINK_LAYER_STATS,
+ WifiManager.WIFI_FEATURE_TX_POWER_LIMIT,
+ WifiManager.WIFI_FEATURE_INFRA,
+ WifiManager.WIFI_FEATURE_P2P,
+ WifiManager.WIFI_FEATURE_SAE_H2E,
+ WifiManager.WIFI_FEATURE_DUAL_BAND_SIMULTANEOUS);
assertTrue(mWifiVendorHal.startVendorHalSta(mConcreteClientModeManager));
assertTrue(expectedFeatureSet.equals(
mWifiVendorHal.getSupportedFeatureSet(TEST_IFACE_NAME)));
@@ -606,11 +603,8 @@
when(mPackageManager.hasSystemFeature(eq(PackageManager.FEATURE_WIFI_AWARE)))
.thenReturn(true);
- BitSet expectedFeatureSet = longToBitset(
- WifiManager.WIFI_FEATURE_INFRA
- | WifiManager.WIFI_FEATURE_P2P
- | WifiManager.WIFI_FEATURE_AWARE
- );
+ BitSet expectedFeatureSet = createCapabilityBitset(WifiManager.WIFI_FEATURE_INFRA,
+ WifiManager.WIFI_FEATURE_P2P, WifiManager.WIFI_FEATURE_AWARE);
assertTrue(expectedFeatureSet.equals(
mWifiVendorHal.getSupportedFeatureSet(TEST_IFACE_NAME)));
}
@@ -1468,7 +1462,7 @@
null, TEST_WORKSOURCE, SoftApConfiguration.BAND_2GHZ, false, mSoftApManager,
new ArrayList<>()));
verify(mHalDeviceManager).createApIface(
- anyLong(), any(), any(), eq(TEST_WORKSOURCE), eq(false), eq(mSoftApManager),
+ any(), any(), any(), eq(TEST_WORKSOURCE), eq(false), eq(mSoftApManager),
anyList());
}
@@ -1497,7 +1491,7 @@
null, TEST_WORKSOURCE, SoftApConfiguration.BAND_2GHZ, false, mSoftApManager,
new ArrayList<>());
verify(mHalDeviceManager).createApIface(
- anyLong(), any(), any(), eq(TEST_WORKSOURCE), eq(false), eq(mSoftApManager),
+ any(), any(), any(), eq(TEST_WORKSOURCE), eq(false), eq(mSoftApManager),
anyList());
assertEquals(TEST_IFACE_NAME, ifaceName);
assertTrue(mWifiVendorHal.removeApIface(ifaceName));
diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiVoipDetectorTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiVoipDetectorTest.java
index 9741a2c..1c8264a 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/WifiVoipDetectorTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/WifiVoipDetectorTest.java
@@ -66,6 +66,7 @@
@Mock private TelephonyManager mTelephonyManager;
@Mock private WifiNative mWifiNative;
@Mock private WifiCarrierInfoManager mWifiCarrierInfoManager;
+ @Mock private WifiMetrics mWifiMetrics;
private WifiVoipDetector mWifiVoipDetector;
private TestLooper mLooper;
@@ -84,13 +85,15 @@
when(mWifiInjector.makeTelephonyManager()).thenReturn(mTelephonyManager);
when(mContext.getSystemService(AudioManager.class)).thenReturn(mAudioManager);
when(mWifiInjector.getWifiNative()).thenReturn(mWifiNative);
+ when(mWifiInjector.getWifiMetrics()).thenReturn(mWifiMetrics);
when(mWifiNative.setVoipMode(anyInt())).thenReturn(true);
mWifiVoipDetector = new WifiVoipDetector(mContext,
new Handler(mLooper.getLooper()), mWifiInjector, mWifiCarrierInfoManager);
}
- private void resetWifiNativeAndReSetupforMock() {
+ private void resetWifiNativeAndWifiMetricsAndReSetupforMock() {
reset(mWifiNative);
+ reset(mWifiMetrics);
when(mWifiNative.setVoipMode(anyInt())).thenReturn(true);
}
@@ -111,38 +114,46 @@
when(mWifiCarrierInfoManager.isWifiCallingAvailable()).thenReturn(true);
mWifiVoipDetector.notifyWifiConnected(true, true, TEST_PRIMARY_INTERFACE_NAME);
verify(mWifiNative).setVoipMode(WifiChip.WIFI_VOIP_MODE_VOICE);
+ verify(mWifiInjector.getWifiMetrics()).setVoipMode(WifiChip.WIFI_VOIP_MODE_VOICE);
// Test VoWifi call off -> switch to VoLte
mTelephonyCallbackCaptor.getValue().onCallAttributesChanged(TEST_LTE_CALL_ATT);
verify(mWifiNative).setVoipMode(WifiChip.WIFI_VOIP_MODE_OFF);
- resetWifiNativeAndReSetupforMock();
+ verify(mWifiInjector.getWifiMetrics()).setVoipMode(WifiChip.WIFI_VOIP_MODE_OFF);
+ resetWifiNativeAndWifiMetricsAndReSetupforMock();
// Test VoWifi Call
mTelephonyCallbackCaptor.getValue().onCallAttributesChanged(TEST_VOWIFI_CALL_ATT);
verify(mWifiNative).setVoipMode(WifiChip.WIFI_VOIP_MODE_VOICE);
- resetWifiNativeAndReSetupforMock();
+ verify(mWifiInjector.getWifiMetrics()).setVoipMode(WifiChip.WIFI_VOIP_MODE_VOICE);
+ resetWifiNativeAndWifiMetricsAndReSetupforMock();
// Test VoWifi call off -> switch to VoLte
mTelephonyCallbackCaptor.getValue().onCallAttributesChanged(TEST_LTE_CALL_ATT);
verify(mWifiNative).setVoipMode(WifiChip.WIFI_VOIP_MODE_OFF);
- resetWifiNativeAndReSetupforMock();
+ verify(mWifiInjector.getWifiMetrics()).setVoipMode(WifiChip.WIFI_VOIP_MODE_OFF);
+ resetWifiNativeAndWifiMetricsAndReSetupforMock();
// Test MODE_IN_COMMUNICATION to trigger voice mode
mAudioModeChangedListeneCaptor.getValue().onModeChanged(AudioManager.MODE_IN_COMMUNICATION);
verify(mWifiNative).setVoipMode(WifiChip.WIFI_VOIP_MODE_VOICE);
- resetWifiNativeAndReSetupforMock();
+ verify(mWifiInjector.getWifiMetrics()).setVoipMode(WifiChip.WIFI_VOIP_MODE_VOICE);
+ resetWifiNativeAndWifiMetricsAndReSetupforMock();
// Test MODE_NORMAL off WifiChip.WIFI_VOIP_MODE_OFF
mAudioModeChangedListeneCaptor.getValue().onModeChanged(AudioManager.MODE_NORMAL);
verify(mWifiNative).setVoipMode(WifiChip.WIFI_VOIP_MODE_OFF);
- resetWifiNativeAndReSetupforMock();
+ verify(mWifiInjector.getWifiMetrics()).setVoipMode(WifiChip.WIFI_VOIP_MODE_OFF);
+ resetWifiNativeAndWifiMetricsAndReSetupforMock();
// Test MODE_COMMUNICATION_REDIRECT to trigger voice mode
mAudioModeChangedListeneCaptor.getValue().onModeChanged(
AudioManager.MODE_COMMUNICATION_REDIRECT);
verify(mWifiNative).setVoipMode(WifiChip.WIFI_VOIP_MODE_VOICE);
- resetWifiNativeAndReSetupforMock();
+ verify(mWifiInjector.getWifiMetrics()).setVoipMode(WifiChip.WIFI_VOIP_MODE_VOICE);
+ resetWifiNativeAndWifiMetricsAndReSetupforMock();
// Do nothing when mode change between two OTT modes.
mAudioModeChangedListeneCaptor.getValue().onModeChanged(AudioManager.MODE_IN_COMMUNICATION);
verify(mWifiNative, never()).setVoipMode(anyInt());
mWifiVoipDetector.notifyWifiConnected(false, true, TEST_PRIMARY_INTERFACE_NAME);
verify(mWifiNative).setVoipMode(WifiChip.WIFI_VOIP_MODE_OFF);
+ verify(mWifiInjector.getWifiMetrics()).setVoipMode(WifiChip.WIFI_VOIP_MODE_OFF);
// Test OTT on when wifi is disconnected, should do nothing since it doesn't relate to wifi.
- resetWifiNativeAndReSetupforMock();
+ resetWifiNativeAndWifiMetricsAndReSetupforMock();
mAudioModeChangedListeneCaptor.getValue().onModeChanged(
AudioManager.MODE_COMMUNICATION_REDIRECT);
verify(mWifiNative, never()).setVoipMode(anyInt());
@@ -150,6 +161,7 @@
when(mAudioManager.getMode()).thenReturn(AudioManager.MODE_COMMUNICATION_REDIRECT);
mWifiVoipDetector.notifyWifiConnected(true, true, TEST_PRIMARY_INTERFACE_NAME);
verify(mWifiNative).setVoipMode(WifiChip.WIFI_VOIP_MODE_VOICE);
+ verify(mWifiInjector.getWifiMetrics()).setVoipMode(WifiChip.WIFI_VOIP_MODE_VOICE);
}
@Test
diff --git a/service/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareDataPathStateManagerTest.java b/service/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareDataPathStateManagerTest.java
index 809fa1a..681db5b 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareDataPathStateManagerTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareDataPathStateManagerTest.java
@@ -88,6 +88,8 @@
import androidx.test.filters.SmallTest;
+import com.android.dx.mockito.inline.extended.ExtendedMockito;
+import com.android.dx.mockito.inline.extended.StaticMockitoSession;
import com.android.modules.utils.build.SdkLevel;
import com.android.server.wifi.Clock;
import com.android.server.wifi.DeviceConfigFacade;
@@ -117,6 +119,7 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;
+import org.mockito.quality.Strictness;
import java.nio.ByteOrder;
import java.util.ArrayList;
@@ -172,6 +175,7 @@
public ErrorCollector collector = new ErrorCollector();
private MockResources mResources;
private Bundle mExtras = new Bundle();
+ private StaticMockitoSession mSession;
/**
* Initialize mocks.
@@ -179,6 +183,12 @@
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
+ mSession = ExtendedMockito.mockitoSession()
+ .strictness(Strictness.LENIENT)
+ .mockStatic(WifiInjector.class)
+ .startMocking();
+
+ when(WifiInjector.getInstance()).thenReturn(mWifiInjector);
mAlarmManager = new TestAlarmManager();
when(mMockContext.getSystemService(Context.ALARM_SERVICE))
@@ -244,6 +254,7 @@
@After
public void tearDown() throws Exception {
mMockNative.validateUniqueTransactionIds();
+ mSession.finishMocking();
}
/**
diff --git a/service/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareServiceImplTest.java b/service/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareServiceImplTest.java
index 8342171..0e06d03 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareServiceImplTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareServiceImplTest.java
@@ -43,6 +43,7 @@
import android.content.Context;
import android.content.pm.PackageManager;
import android.net.wifi.OuiKeyedData;
+import android.net.wifi.ScanResult;
import android.net.wifi.WifiScanner;
import android.net.wifi.aware.Characteristics;
import android.net.wifi.aware.ConfigRequest;
@@ -1064,7 +1065,7 @@
// constructed configs.
PublishConfig publishConfig = new PublishConfig(serviceName.getBytes(), ssi, matchFilter,
PublishConfig.PUBLISH_TYPE_UNSOLICITED, 0, true, false, false,
- WifiScanner.WIFI_BAND_24_GHZ, null, null, false, Collections.emptyList());
+ WifiScanner.WIFI_BAND_24_GHZ, null, null, false, Collections.emptyList(), false);
int clientId = doConnect();
IWifiAwareDiscoverySessionCallback mockCallback = mock(
IWifiAwareDiscoverySessionCallback.class);
@@ -1081,7 +1082,9 @@
// constructed configs.
SubscribeConfig subscribeConfig = new SubscribeConfig(serviceName.getBytes(), ssi,
matchFilter, SubscribeConfig.SUBSCRIBE_TYPE_PASSIVE, 0, true, false, 0, false, 0,
- false, WifiScanner.WIFI_BAND_24_GHZ, null, false, Collections.emptyList());
+ false, WifiScanner.WIFI_BAND_24_GHZ, null, false, Collections.emptyList(),
+ SubscribeConfig.PERIODIC_RANGING_INTERVAL_512TU, false, 2, 2437, 0, 0,
+ ScanResult.PREAMBLE_HT, 0);
int clientId = doConnect();
IWifiAwareDiscoverySessionCallback mockCallback = mock(
IWifiAwareDiscoverySessionCallback.class);
diff --git a/service/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareStateManagerTest.java b/service/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareStateManagerTest.java
index ee53e22..c2f2e83 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareStateManagerTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareStateManagerTest.java
@@ -34,6 +34,7 @@
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeFalse;
import static org.junit.Assume.assumeTrue;
+import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyByte;
@@ -215,9 +216,11 @@
MockitoAnnotations.initMocks(this);
mSession = ExtendedMockito.mockitoSession()
.strictness(Strictness.LENIENT)
+ .mockStatic(WifiInjector.class)
.mockStatic(WifiStatsLog.class)
.startMocking();
+ when(WifiInjector.getInstance()).thenReturn(mWifiInjector);
mAlarmManager = new TestAlarmManager();
when(mMockContext.getSystemService(Context.ALARM_SERVICE))
.thenReturn(mAlarmManager.getAlarmManager());
@@ -276,8 +279,7 @@
mDut.start(mMockContext, mMockLooper.getLooper(), mAwareMetricsMock,
mWifiPermissionsUtil, mPermissionsWrapperMock, new Clock(),
mock(NetdWrapper.class), mInterfaceConflictManager);
- verify(mMockContext, never()).registerReceiver(any(), any(IntentFilter.class), isNull(),
- any(Handler.class));
+ verify(mMockContext, never()).registerReceiver(any(), any(IntentFilter.class));
mDut.startLate();
mDut.enableVerboseLogging(true, true, true);
mMockLooper.dispatchAll();
@@ -288,14 +290,17 @@
callbackArgumentCaptor.capture());
mActiveCountryCodeChangedCallback = callbackArgumentCaptor.getValue();
}
- verify(mMockContext, times(3))
+ verify(mMockContext)
+ .registerReceiverForAllUsers(
+ bcastRxCaptor.capture(),
+ argThat(filter -> filter.hasAction(LocationManager.MODE_CHANGED_ACTION)),
+ isNull(), isNull());
+ verify(mMockContext, times(2))
.registerReceiver(
bcastRxCaptor.capture(),
- any(IntentFilter.class),
- isNull(),
- any(Handler.class));
- mPowerBcastReceiver = bcastRxCaptor.getAllValues().get(0);
- mLocationModeReceiver = bcastRxCaptor.getAllValues().get(1);
+ any(IntentFilter.class));
+ mLocationModeReceiver = bcastRxCaptor.getAllValues().get(0);
+ mPowerBcastReceiver = bcastRxCaptor.getAllValues().get(1);
mWifiStateChangedReceiver = bcastRxCaptor.getAllValues().get(2);
verify(mWifiSettingsConfigStore).registerChangeListener(
eq(D2D_ALLOWED_WHEN_INFRA_STA_DISABLED),
diff --git a/service/tests/wifitests/src/com/android/server/wifi/hal/WifiChipAidlImplTest.java b/service/tests/wifitests/src/com/android/server/wifi/hal/WifiChipAidlImplTest.java
index 2850a1a..f4104ab 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/hal/WifiChipAidlImplTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/hal/WifiChipAidlImplTest.java
@@ -17,7 +17,7 @@
package com.android.server.wifi.hal;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
-import static com.android.server.wifi.util.GeneralUtil.longToBitset;
+import static com.android.server.wifi.TestUtil.createCapabilityBitset;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -125,11 +125,8 @@
| android.hardware.wifi.IWifiChip.FeatureSetMask.D2D_RTT
| android.hardware.wifi.IWifiChip.FeatureSetMask.D2AP_RTT
);
- BitSet expected = longToBitset(
- WifiManager.WIFI_FEATURE_TX_POWER_LIMIT
- | WifiManager.WIFI_FEATURE_D2D_RTT
- | WifiManager.WIFI_FEATURE_D2AP_RTT
- );
+ BitSet expected = createCapabilityBitset(WifiManager.WIFI_FEATURE_TX_POWER_LIMIT,
+ WifiManager.WIFI_FEATURE_D2D_RTT, WifiManager.WIFI_FEATURE_D2AP_RTT);
assertTrue(expected.equals(mDut.halToFrameworkChipFeatureSet(halFeatures)));
}
diff --git a/service/tests/wifitests/src/com/android/server/wifi/hal/WifiChipHidlImplTest.java b/service/tests/wifitests/src/com/android/server/wifi/hal/WifiChipHidlImplTest.java
index 53dd5b4..52d505c 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/hal/WifiChipHidlImplTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/hal/WifiChipHidlImplTest.java
@@ -16,7 +16,7 @@
package com.android.server.wifi.hal;
-import static com.android.server.wifi.util.GeneralUtil.longToBitset;
+import static com.android.server.wifi.TestUtil.createCapabilityBitset;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -156,11 +156,8 @@
| android.hardware.wifi.V1_1.IWifiChip.ChipCapabilityMask.D2D_RTT
| android.hardware.wifi.V1_1.IWifiChip.ChipCapabilityMask.D2AP_RTT
);
- BitSet expected = longToBitset(
- WifiManager.WIFI_FEATURE_TX_POWER_LIMIT
- | WifiManager.WIFI_FEATURE_D2D_RTT
- | WifiManager.WIFI_FEATURE_D2AP_RTT
- );
+ BitSet expected = createCapabilityBitset(WifiManager.WIFI_FEATURE_TX_POWER_LIMIT,
+ WifiManager.WIFI_FEATURE_D2D_RTT, WifiManager.WIFI_FEATURE_D2AP_RTT);
assertTrue(expected.equals(mDut.wifiFeatureMaskFromChipCapabilities(caps)));
}
@@ -173,10 +170,8 @@
android.hardware.wifi.V1_3.IWifiChip.ChipCapabilityMask.SET_LATENCY_MODE
| android.hardware.wifi.V1_1.IWifiChip.ChipCapabilityMask.D2D_RTT
);
- BitSet expected = longToBitset(
- WifiManager.WIFI_FEATURE_LOW_LATENCY
- | WifiManager.WIFI_FEATURE_D2D_RTT
- );
+ BitSet expected = createCapabilityBitset(
+ WifiManager.WIFI_FEATURE_LOW_LATENCY, WifiManager.WIFI_FEATURE_D2D_RTT);
assertTrue(expected.equals(mDut.wifiFeatureMaskFromChipCapabilities_1_3(caps)));
}
diff --git a/service/tests/wifitests/src/com/android/server/wifi/hal/WifiStaIfaceAidlImplTest.java b/service/tests/wifitests/src/com/android/server/wifi/hal/WifiStaIfaceAidlImplTest.java
index 4a0a4e3..5bd0b26 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/hal/WifiStaIfaceAidlImplTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/hal/WifiStaIfaceAidlImplTest.java
@@ -16,7 +16,7 @@
package com.android.server.wifi.hal;
-import static com.android.server.wifi.util.GeneralUtil.longToBitset;
+import static com.android.server.wifi.TestUtil.createCapabilityBitset;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
@@ -58,6 +58,8 @@
import android.net.wifi.WifiScanner.ScanData;
import android.net.wifi.WifiSsid;
+import com.android.dx.mockito.inline.extended.ExtendedMockito;
+import com.android.dx.mockito.inline.extended.StaticMockitoSession;
import com.android.server.wifi.SsidTranslator;
import com.android.server.wifi.WifiBaseTest;
import com.android.server.wifi.WifiLinkLayerStats;
@@ -65,6 +67,7 @@
import com.android.server.wifi.WifiNative;
import com.android.wifi.resources.R;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
@@ -83,12 +86,21 @@
@Mock private Context mContextMock;
@Mock private Resources mResourcesMock;
@Mock private SsidTranslator mSsidTranslatorMock;
+ private StaticMockitoSession mSession;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
when(mContextMock.getResources()).thenReturn(mResourcesMock);
mDut = new WifiStaIfaceAidlImpl(mIWifiStaIfaceMock, mContextMock, mSsidTranslatorMock);
+ mSession = ExtendedMockito.mockitoSession()
+ .mockStatic(WifiHalAidlImpl.class)
+ .startMocking();
+ }
+
+ @After
+ public void teardown() {
+ mSession.finishMocking();
}
/**
@@ -100,9 +112,8 @@
IWifiStaIface.FeatureSetMask.BACKGROUND_SCAN
| IWifiStaIface.FeatureSetMask.LINK_LAYER_STATS
);
- BitSet expected = longToBitset(
- WifiManager.WIFI_FEATURE_SCANNER
- | WifiManager.WIFI_FEATURE_LINK_LAYER_STATS);
+ BitSet expected = createCapabilityBitset(
+ WifiManager.WIFI_FEATURE_SCANNER, WifiManager.WIFI_FEATURE_LINK_LAYER_STATS);
assertTrue(expected.equals(mDut.halToFrameworkStaFeatureSet(halFeatures)));
}
@@ -334,6 +345,7 @@
*/
@Test
public void testGetCachedScanData() throws Exception {
+ when(WifiHalAidlImpl.isServiceVersionAtLeast(2)).thenReturn(true);
CachedScanData halData = new CachedScanData();
CachedScanResult[] halResults = new CachedScanResult[2];
CachedScanResult halResult = new CachedScanResult();
diff --git a/service/tests/wifitests/src/com/android/server/wifi/hal/WifiStaIfaceHidlImplTest.java b/service/tests/wifitests/src/com/android/server/wifi/hal/WifiStaIfaceHidlImplTest.java
index 8adb4fd..21e8c84 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/hal/WifiStaIfaceHidlImplTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/hal/WifiStaIfaceHidlImplTest.java
@@ -16,7 +16,7 @@
package com.android.server.wifi.hal;
-import static com.android.server.wifi.util.GeneralUtil.longToBitset;
+import static com.android.server.wifi.TestUtil.createCapabilityBitset;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
@@ -146,9 +146,8 @@
IWifiStaIface.StaIfaceCapabilityMask.BACKGROUND_SCAN
| IWifiStaIface.StaIfaceCapabilityMask.LINK_LAYER_STATS
);
- BitSet expected = longToBitset(
- WifiManager.WIFI_FEATURE_SCANNER
- | WifiManager.WIFI_FEATURE_LINK_LAYER_STATS);
+ BitSet expected = createCapabilityBitset(
+ WifiManager.WIFI_FEATURE_SCANNER, WifiManager.WIFI_FEATURE_LINK_LAYER_STATS);
assertTrue(expected.equals(mDut.halToFrameworkStaIfaceCapability(caps)));
}
diff --git a/service/tests/wifitests/src/com/android/server/wifi/mainline_supplicant/MainlineSupplicantTest.java b/service/tests/wifitests/src/com/android/server/wifi/mainline_supplicant/MainlineSupplicantTest.java
new file mode 100644
index 0000000..e27c46f
--- /dev/null
+++ b/service/tests/wifitests/src/com/android/server/wifi/mainline_supplicant/MainlineSupplicantTest.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wifi.mainline_supplicant;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.net.wifi.util.Environment;
+import android.os.IBinder;
+import android.system.wifi.mainline_supplicant.IMainlineSupplicant;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+/**
+ * Unit tests for {@link MainlineSupplicant}.
+ */
+public class MainlineSupplicantTest {
+ private @Mock IMainlineSupplicant mIMainlineSupplicantMock;
+ private @Mock IBinder mIBinderMock;
+ private MainlineSupplicantSpy mDut;
+
+ private ArgumentCaptor<IBinder.DeathRecipient> mDeathRecipientCaptor =
+ ArgumentCaptor.forClass(IBinder.DeathRecipient.class);
+
+ // Spy version of this class allows us to override methods for testing.
+ private class MainlineSupplicantSpy extends MainlineSupplicant {
+ MainlineSupplicantSpy() {
+ super();
+ }
+
+ @Override
+ protected IMainlineSupplicant getNewServiceBinderMockable() {
+ return mIMainlineSupplicantMock;
+ }
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ assumeTrue(Environment.isSdkAtLeastB());
+ MockitoAnnotations.initMocks(this);
+ when(mIMainlineSupplicantMock.asBinder()).thenReturn(mIBinderMock);
+ mDut = new MainlineSupplicantSpy();
+ }
+
+ private void validateServiceStart() throws Exception {
+ assertTrue(mDut.startService());
+ verify(mIBinderMock).linkToDeath(mDeathRecipientCaptor.capture(), anyInt());
+ assertTrue(mDut.isActive());
+ }
+
+ private void validateServiceStop() {
+ mDut.stopService();
+ mDeathRecipientCaptor.getValue().binderDied(mIBinderMock);
+ assertFalse(mDut.isActive());
+ }
+
+ /**
+ * Verify that the class can be started and stopped successfully.
+ */
+ @Test
+ public void testStartAndStopSuccess() throws Exception {
+ validateServiceStart();
+ validateServiceStop();
+ }
+
+ /**
+ * Verify that unsolicited death notifications (ex. caused by a service crash)
+ * are handled correctly.
+ */
+ @Test
+ public void testUnsolicitedDeathNotification() throws Exception {
+ validateServiceStart();
+
+ // Notification with an unknown binder should be ignored
+ IBinder otherBinder = mock(IBinder.class);
+ mDeathRecipientCaptor.getValue().binderDied(otherBinder);
+ assertTrue(mDut.isActive());
+
+ // Notification with the correct binder should be handled
+ mDeathRecipientCaptor.getValue().binderDied(mIBinderMock);
+ assertFalse(mDut.isActive());
+ }
+}
diff --git a/service/tests/wifitests/src/com/android/server/wifi/p2p/SupplicantP2pIfaceCallbackAidlImplTest.java b/service/tests/wifitests/src/com/android/server/wifi/p2p/SupplicantP2pIfaceCallbackAidlImplTest.java
index df9120d..4b3135a 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/p2p/SupplicantP2pIfaceCallbackAidlImplTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/p2p/SupplicantP2pIfaceCallbackAidlImplTest.java
@@ -29,9 +29,12 @@
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.withSettings;
import android.app.test.MockAnswerUtil.AnswerWithArguments;
import android.hardware.wifi.common.OuiKeyedData;
+import android.hardware.wifi.supplicant.KeyMgmtMask;
import android.hardware.wifi.supplicant.P2pClientEapolIpAddressInfo;
import android.hardware.wifi.supplicant.P2pDeviceFoundEventParams;
import android.hardware.wifi.supplicant.P2pGoNegotiationReqEventParams;
@@ -46,26 +49,32 @@
import android.hardware.wifi.supplicant.WpsDevPasswordId;
import android.net.MacAddress;
import android.net.wifi.ScanResult;
+import android.net.wifi.WifiMigration;
import android.net.wifi.WpsInfo;
import android.net.wifi.p2p.WifiP2pConfig;
import android.net.wifi.p2p.WifiP2pDevice;
import android.net.wifi.p2p.WifiP2pGroup;
import android.net.wifi.p2p.WifiP2pProvDiscEvent;
import android.net.wifi.p2p.nsd.WifiP2pServiceResponse;
+import android.net.wifi.util.Environment;
import android.os.PersistableBundle;
import androidx.test.filters.SmallTest;
+import com.android.dx.mockito.inline.extended.ExtendedMockito;
import com.android.modules.utils.build.SdkLevel;
import com.android.server.wifi.WifiBaseTest;
import com.android.server.wifi.p2p.WifiP2pServiceImpl.P2pStatus;
import com.android.server.wifi.util.HalAidlUtil;
import com.android.server.wifi.util.NativeUtil;
+import com.android.wifi.flags.Flags;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.MockitoAnnotations;
+import org.mockito.MockitoSession;
import java.util.ArrayList;
import java.util.Arrays;
@@ -81,6 +90,7 @@
private String mGroupIface = "test_p2p-p2p0-3";
private WifiP2pMonitor mMonitor;
private SupplicantP2pIfaceCallbackAidlImpl mDut;
+ private MockitoSession mSession;
private byte[] mDeviceAddressInvalid1 = { 0x00 };
private byte[] mDeviceAddressInvalid2 = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66 };
@@ -113,6 +123,18 @@
MockitoAnnotations.initMocks(this);
mMonitor = mock(WifiP2pMonitor.class);
initializeDut(DEFAULT_SERVICE_VERSION);
+ mSession = ExtendedMockito.mockitoSession()
+ .mockStatic(Flags.class, withSettings().lenient())
+ .mockStatic(WifiMigration.class, withSettings().lenient())
+ .startMocking();
+ when(Flags.wifiDirectR2()).thenReturn(false);
+ }
+
+ @After
+ public void tearDown() {
+ if (mSession != null) {
+ mSession.finishMocking();
+ }
}
private void initializeDut(int serviceVersion) {
@@ -673,6 +695,30 @@
}
/**
+ * Verify onGroupStartedWithParams call when the parameters
+ * include Authentication Key Management.
+ */
+ @Test
+ public void testOnGroupStartedWithKeyMgmtMask() throws Exception {
+ assumeTrue(Environment.isSdkAtLeastB());
+ initializeDut(4 /* serviceVersion */);
+ when(Flags.wifiDirectR2()).thenReturn(true);
+ P2pGroupStartedEventParams params = new P2pGroupStartedEventParams();
+ params.groupInterfaceName = "group name";
+ params.ssid = new byte[] {0x30, 0x31, 0x32, 0x33};
+ params.goDeviceAddress = mDeviceAddress1Bytes;
+ params.keyMgmtMask = KeyMgmtMask.SAE | KeyMgmtMask.WPA_PSK;
+
+ ArgumentCaptor<WifiP2pGroup> p2pGroupCaptor =
+ ArgumentCaptor.forClass(WifiP2pGroup.class);
+ mDut.onGroupStartedWithParams(params);
+ verify(mMonitor).broadcastP2pGroupStarted(eq(mIface), p2pGroupCaptor.capture());
+
+ assertEquals(WifiP2pGroup.SECURITY_TYPE_WPA3_COMPATIBILITY,
+ p2pGroupCaptor.getValue().getSecurityType());
+ }
+
+ /**
* Failing scenarios for onGroupStartedWithParams call.
*/
@Test
diff --git a/service/tests/wifitests/src/com/android/server/wifi/p2p/SupplicantP2pIfaceHalAidlImplTest.java b/service/tests/wifitests/src/com/android/server/wifi/p2p/SupplicantP2pIfaceHalAidlImplTest.java
index 9cb54e7..c04ce9a 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/p2p/SupplicantP2pIfaceHalAidlImplTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/p2p/SupplicantP2pIfaceHalAidlImplTest.java
@@ -50,6 +50,7 @@
import android.hardware.wifi.supplicant.ISupplicantP2pIfaceCallback;
import android.hardware.wifi.supplicant.ISupplicantP2pNetwork;
import android.hardware.wifi.supplicant.IfaceInfo;
+import android.hardware.wifi.supplicant.KeyMgmtMask;
import android.hardware.wifi.supplicant.MacAddress;
import android.hardware.wifi.supplicant.MiracastMode;
import android.hardware.wifi.supplicant.P2pConnectInfo;
@@ -68,6 +69,7 @@
import android.net.wifi.p2p.WifiP2pGroupList;
import android.net.wifi.p2p.WifiP2pManager;
import android.net.wifi.p2p.nsd.WifiP2pServiceInfo;
+import android.net.wifi.util.Environment;
import android.os.IBinder;
import android.os.PersistableBundle;
import android.os.RemoteException;
@@ -1304,7 +1306,8 @@
eq(mPeerMacAddressBytes),
anyBoolean());
// Default value when service is not initialized.
- assertFalse(mDut.groupAdd(mNetworkName, mPassphrase, mIsPersistent,
+ assertFalse(mDut.groupAdd(mNetworkName, mPassphrase,
+ WifiP2pConfig.PCC_MODE_CONNECTION_TYPE_LEGACY_ONLY, mIsPersistent,
mGroupOwnerBand, mPeerMacAddress, true));
verify(mISupplicantP2pIfaceMock, never()).addGroupWithConfig(
any(byte[].class), anyString(),
@@ -1312,7 +1315,8 @@
any(byte[].class), anyBoolean());
executeAndValidateInitializationSequence(false, false);
- assertTrue(mDut.groupAdd(mNetworkName, mPassphrase, mIsPersistent,
+ assertTrue(mDut.groupAdd(mNetworkName, mPassphrase,
+ WifiP2pConfig.PCC_MODE_CONNECTION_TYPE_LEGACY_ONLY, mIsPersistent,
mGroupOwnerBand, mPeerMacAddress, true));
verify(mISupplicantP2pIfaceMock).addGroupWithConfig(
eq(NativeUtil.byteArrayFromArrayList(
@@ -1325,6 +1329,35 @@
}
/**
+ * Sunny day scenario for groupAdd() with config
+ */
+ @Test
+ public void testGroupAddWithConfigurationParamsSuccess() throws Exception {
+ assumeTrue(Environment.isSdkAtLeastB());
+ setCachedServiceVersion(4);
+ ArgumentCaptor<android.hardware.wifi.supplicant.P2pAddGroupConfigurationParams>
+ addGroupParamsCaptor = ArgumentCaptor.forClass(android.hardware.wifi.supplicant
+ .P2pAddGroupConfigurationParams.class);
+
+ executeAndValidateInitializationSequence(false, false);
+ assertTrue(mDut.groupAdd(mNetworkName, mPassphrase,
+ WifiP2pConfig.PCC_MODE_CONNECTION_TYPE_LEGACY_OR_R2, mIsPersistent,
+ mGroupOwnerBand, mPeerMacAddress, true));
+ verify(mISupplicantP2pIfaceMock).addGroupWithConfigurationParams(
+ addGroupParamsCaptor.capture());
+ android.hardware.wifi.supplicant.P2pAddGroupConfigurationParams params =
+ addGroupParamsCaptor.getValue();
+ assertArrayEquals(NativeUtil.byteArrayFromArrayList(
+ NativeUtil.decodeSsid("\"" + mNetworkName + "\"")), params.ssid);
+ assertEquals(mGroupOwnerBand, params.frequencyMHzOrBand);
+ assertEquals(mPassphrase, params.passphrase);
+ assertArrayEquals(mPeerMacAddressBytes, params.goInterfaceAddress);
+ assertEquals(mIsPersistent, params.isPersistent);
+ assertEquals(true, params.joinExistingGroup);
+ assertEquals(KeyMgmtMask.WPA_PSK | KeyMgmtMask.SAE, params.keyMgmtMask);
+ }
+
+ /**
* Verify that groupAdd with config returns false, if HAL call did not succeed.
*/
@Test
@@ -1339,7 +1372,8 @@
eq(mGroupOwnerBand),
eq(mPeerMacAddressBytes),
anyBoolean());
- assertFalse(mDut.groupAdd(mNetworkName, mPassphrase, mIsPersistent,
+ assertFalse(mDut.groupAdd(mNetworkName, mPassphrase,
+ WifiP2pConfig.PCC_MODE_CONNECTION_TYPE_LEGACY_ONLY, mIsPersistent,
mGroupOwnerBand, mPeerMacAddress, true));
verify(mISupplicantP2pIfaceMock).addGroupWithConfig(
eq(NativeUtil.byteArrayFromArrayList(
@@ -1369,7 +1403,8 @@
eq(mGroupOwnerBand),
eq(mPeerMacAddressBytes),
anyBoolean());
- assertFalse(mDut.groupAdd(mNetworkName, mPassphrase, mIsPersistent,
+ assertFalse(mDut.groupAdd(mNetworkName, mPassphrase,
+ WifiP2pConfig.PCC_MODE_CONNECTION_TYPE_LEGACY_ONLY, mIsPersistent,
mGroupOwnerBand, mPeerMacAddress, true));
verify(mISupplicantP2pIfaceMock).addGroupWithConfig(
eq(NativeUtil.byteArrayFromArrayList(
@@ -2688,24 +2723,22 @@
* Test that getSupportedFeatures returns the expected feature sets.
*/
@Test
- public void testGetSupportedFeatures() {
+ public void testGetSupportedFeatures() throws Exception {
WifiSettingsConfigStore mockConfigStore = mock(WifiSettingsConfigStore.class);
when(mWifiInjector.getSettingsConfigStore()).thenReturn(mockConfigStore);
-
- // If the service version cannot be retrieved, expect the default feature set.
when(mockConfigStore.get(any())).thenReturn(-1);
- long defaultFeatureSet = mDut.getSupportedFeatures();
- verify(mockConfigStore).get(any());
+ when(mISupplicantP2pIfaceMock.getFeatureSet())
+ .thenReturn(mISupplicantP2pIfaceMock.P2P_FEATURE_V2);
+ executeAndValidateInitializationSequence(false, false);
- // Full feature set can be retrieved once we have the service version.
- when(mockConfigStore.get(any())).thenReturn(2);
- long fullFeatureSet = mDut.getSupportedFeatures();
- assertNotEquals(defaultFeatureSet, fullFeatureSet);
+ // getSupportedFeatures() HAL API is supported only on version 4 or later.
+ assertEquals(0, mDut.getSupportedFeatures());
verify(mockConfigStore, times(2)).get(any());
- // Service version should be cached on subsequent calls.
- assertEquals(fullFeatureSet, mDut.getSupportedFeatures());
- verifyNoMoreInteractions(mockConfigStore);
+ // Feature set can be retrieved only on service version set to at least version 4.
+ when(mockConfigStore.get(any())).thenReturn(4);
+ assertNotEquals(mISupplicantP2pIfaceMock.P2P_FEATURE_V2, mDut.getSupportedFeatures());
+ verify(mockConfigStore, times(3)).get(any());
}
/**
diff --git a/service/tests/wifitests/src/com/android/server/wifi/p2p/SupplicantP2pIfaceHalHidlImplTest.java b/service/tests/wifitests/src/com/android/server/wifi/p2p/SupplicantP2pIfaceHalHidlImplTest.java
index 2520a7b..fff3d7b 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/p2p/SupplicantP2pIfaceHalHidlImplTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/p2p/SupplicantP2pIfaceHalHidlImplTest.java
@@ -1358,7 +1358,8 @@
anyBoolean()))
.thenReturn(mStatusSuccess);
// Default value when service is not initialized.
- assertFalse(mDut.groupAdd(mNetworkName, mPassphrase, mIsPersistent,
+ assertFalse(mDut.groupAdd(mNetworkName, mPassphrase,
+ WifiP2pConfig.PCC_MODE_CONNECTION_TYPE_LEGACY_ONLY, mIsPersistent,
mGroupOwnerBand, mPeerMacAddress, true));
verify(mISupplicantP2pIfaceMockV12, never()).addGroup_1_2(
any(ArrayList.class), anyString(),
@@ -1366,7 +1367,8 @@
any(byte[].class), anyBoolean());
executeAndValidateInitializationSequence(false, false, false);
- assertTrue(mDut.groupAdd(mNetworkName, mPassphrase, mIsPersistent,
+ assertTrue(mDut.groupAdd(mNetworkName, mPassphrase,
+ WifiP2pConfig.PCC_MODE_CONNECTION_TYPE_LEGACY_ONLY, mIsPersistent,
mGroupOwnerBand, mPeerMacAddress, true));
verify(mISupplicantP2pIfaceMockV12).addGroup_1_2(
eq(NativeUtil.decodeSsid("\"" + mNetworkName + "\"")),
@@ -1388,7 +1390,8 @@
anyBoolean(), anyInt(),
any(byte[].class), anyBoolean()))
.thenReturn(mStatusFailure);
- assertFalse(mDut.groupAdd(mNetworkName, mPassphrase, mIsPersistent,
+ assertFalse(mDut.groupAdd(mNetworkName, mPassphrase,
+ WifiP2pConfig.PCC_MODE_CONNECTION_TYPE_LEGACY_ONLY, mIsPersistent,
mGroupOwnerBand, mPeerMacAddress, true));
verify(mISupplicantP2pIfaceMockV12).addGroup_1_2(
eq(NativeUtil.decodeSsid("\"" + mNetworkName + "\"")),
@@ -1415,7 +1418,8 @@
// disable 1.2 interface to simulator since older revision cannot be casted to v1.2
mISupplicantV12Enabled = false;
- assertFalse(mDut.groupAdd(mNetworkName, mPassphrase, mIsPersistent,
+ assertFalse(mDut.groupAdd(mNetworkName, mPassphrase,
+ WifiP2pConfig.PCC_MODE_CONNECTION_TYPE_LEGACY_ONLY, mIsPersistent,
mGroupOwnerBand, mPeerMacAddress, true));
verify(mISupplicantP2pIfaceMockV12, never()).addGroup_1_2(
any(ArrayList.class), anyString(),
@@ -1437,7 +1441,8 @@
anyBoolean(), anyInt(),
any(byte[].class), anyBoolean()))
.thenThrow(mRemoteException);
- assertFalse(mDut.groupAdd(mNetworkName, mPassphrase, mIsPersistent,
+ assertFalse(mDut.groupAdd(mNetworkName, mPassphrase,
+ WifiP2pConfig.PCC_MODE_CONNECTION_TYPE_LEGACY_ONLY, mIsPersistent,
mGroupOwnerBand, mPeerMacAddress, true));
verify(mISupplicantP2pIfaceMockV12).addGroup_1_2(
eq(NativeUtil.decodeSsid("\"" + mNetworkName + "\"")),
diff --git a/service/tests/wifitests/src/com/android/server/wifi/p2p/SupplicantP2pIfaceHalTest.java b/service/tests/wifitests/src/com/android/server/wifi/p2p/SupplicantP2pIfaceHalTest.java
index bf7194b..dd8a5f6 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/p2p/SupplicantP2pIfaceHalTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/p2p/SupplicantP2pIfaceHalTest.java
@@ -447,13 +447,17 @@
initializeWithAidlImpl(true);
String networkName = "someName";
String passphrase = "somePassword";
+ @WifiP2pConfig.PccModeConnectionType int connectionType =
+ WifiP2pConfig.PCC_MODE_CONNECTION_TYPE_LEGACY_ONLY;
boolean persistent = true;
boolean join = true;
int freq = 10;
- when(mP2pIfaceHalAidlMock.groupAdd(anyString(), anyString(),
+ when(mP2pIfaceHalAidlMock.groupAdd(anyString(), anyString(), anyInt(),
anyBoolean(), anyInt(), anyString(), anyBoolean())).thenReturn(true);
- assertTrue(mDut.groupAdd(networkName, passphrase, persistent, freq, BSSID, join));
- verify(mP2pIfaceHalAidlMock).groupAdd(eq(networkName), eq(passphrase), eq(persistent),
+ assertTrue(mDut.groupAdd(networkName, passphrase, connectionType, persistent,
+ freq, BSSID, join));
+ verify(mP2pIfaceHalAidlMock).groupAdd(eq(networkName), eq(passphrase),
+ eq(connectionType), eq(persistent),
eq(freq), eq(BSSID), eq(join));
}
diff --git a/service/tests/wifitests/src/com/android/server/wifi/p2p/WifiP2pNativeInterfaceManagementTest.java b/service/tests/wifitests/src/com/android/server/wifi/p2p/WifiP2pNativeInterfaceManagementTest.java
index 7080a1d..a217d7e 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/p2p/WifiP2pNativeInterfaceManagementTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/p2p/WifiP2pNativeInterfaceManagementTest.java
@@ -30,6 +30,8 @@
import android.hardware.wifi.V1_0.WifiStatus;
import android.hardware.wifi.V1_0.WifiStatusCode;
import android.net.wifi.nl80211.WifiNl80211Manager;
+import android.net.wifi.p2p.WifiP2pManager;
+import android.net.wifi.util.Environment;
import android.os.Handler;
import android.os.WorkSource;
@@ -44,6 +46,7 @@
import com.android.server.wifi.WifiInjector;
import com.android.server.wifi.WifiMetrics;
import com.android.server.wifi.WifiNative;
+import com.android.server.wifi.WifiSettingsConfigStore;
import com.android.server.wifi.WifiVendorHal;
import com.android.server.wifi.hal.WifiHal;
import com.android.wifi.flags.FeatureFlags;
@@ -78,6 +81,7 @@
@Mock private WifiInjector mWifiInjector;
@Mock private DeviceConfigFacade mDeviceConfigFacade;
@Mock private FeatureFlags mFeatureFlags;
+ private @Mock WifiSettingsConfigStore mWifiSettingsConfigStore;
private WifiP2pNative mWifiP2pNative;
private WifiStatus mWifiStatusSuccess;
@@ -108,6 +112,20 @@
.thenReturn(TEST_P2P_IFACE_NAME);
when(mWifiInjector.getDeviceConfigFacade()).thenReturn(mDeviceConfigFacade);
when(mDeviceConfigFacade.getFeatureFlags()).thenReturn(mFeatureFlags);
+ when(mWifiInjector.getSettingsConfigStore()).thenReturn(mWifiSettingsConfigStore);
+ when(mWifiSettingsConfigStore
+ .get(eq(WifiSettingsConfigStore.SUPPLICANT_HAL_AIDL_SERVICE_VERSION)))
+ .thenReturn(2);
+ if (Environment.isSdkAtLeastB()) {
+ when(mWifiSettingsConfigStore
+ .get(eq(WifiSettingsConfigStore.WIFI_P2P_SUPPORTED_FEATURES)))
+ .thenReturn(WifiP2pManager.FEATURE_WIFI_DIRECT_R2
+ | WifiP2pManager.FEATURE_PCC_MODE_ALLOW_LEGACY_AND_R2_CONNECTION);
+ } else {
+ when(mWifiSettingsConfigStore
+ .get(eq(WifiSettingsConfigStore.WIFI_P2P_SUPPORTED_FEATURES)))
+ .thenReturn(0L);
+ }
mWifiP2pNative = new WifiP2pNative(mWifiNl80211Manager, mWifiNative, mWifiMetrics,
mWifiVendorHal, mSupplicantP2pIfaceHal, mHalDeviceManager, mPropertyService,
mWifiInjector);
diff --git a/service/tests/wifitests/src/com/android/server/wifi/p2p/WifiP2pNativeTest.java b/service/tests/wifitests/src/com/android/server/wifi/p2p/WifiP2pNativeTest.java
index d271570..0a32786 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/p2p/WifiP2pNativeTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/p2p/WifiP2pNativeTest.java
@@ -19,6 +19,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -32,6 +33,7 @@
import android.app.test.MockAnswerUtil.AnswerWithArguments;
import android.hardware.wifi.V1_0.IWifiP2pIface;
+import android.net.wifi.WifiMigration;
import android.net.wifi.nl80211.WifiNl80211Manager;
import android.net.wifi.p2p.WifiP2pConfig;
import android.net.wifi.p2p.WifiP2pDevice;
@@ -40,6 +42,7 @@
import android.net.wifi.p2p.WifiP2pManager;
import android.net.wifi.p2p.nsd.WifiP2pDnsSdServiceInfo;
import android.net.wifi.p2p.nsd.WifiP2pServiceInfo;
+import android.net.wifi.util.Environment;
import android.os.Handler;
import android.os.WorkSource;
@@ -53,9 +56,11 @@
import com.android.server.wifi.WifiInjector;
import com.android.server.wifi.WifiMetrics;
import com.android.server.wifi.WifiNative;
+import com.android.server.wifi.WifiSettingsConfigStore;
import com.android.server.wifi.WifiVendorHal;
import com.android.server.wifi.hal.WifiHal;
import com.android.wifi.flags.FeatureFlags;
+import com.android.wifi.flags.Flags;
import org.junit.After;
import org.junit.Before;
@@ -111,6 +116,7 @@
@Mock private WifiInjector mWifiInjector;
@Mock private DeviceConfigFacade mDeviceConfigFacade;
@Mock private FeatureFlags mFeatureFlags;
+ private @Mock WifiSettingsConfigStore mWifiSettingsConfigStore;
private MockitoSession mSession;
private WifiP2pNative mWifiP2pNative;
@@ -135,14 +141,46 @@
mSession = ExtendedMockito.mockitoSession()
.mockStatic(HalDeviceManager.class, withSettings().lenient())
.strictness(Strictness.LENIENT)
+ .mockStatic(Flags.class, withSettings().lenient())
+ .mockStatic(WifiMigration.class, withSettings().lenient())
.startMocking();
+ when(Flags.wifiDirectR2()).thenReturn(false);
mWifiClientInterfaceNames.add("wlan0");
mWifiClientInterfaceNames.add("wlan1");
when(mWifiInjector.getDeviceConfigFacade()).thenReturn(mDeviceConfigFacade);
when(mDeviceConfigFacade.getFeatureFlags()).thenReturn(mFeatureFlags);
+ when(mWifiInjector.getSettingsConfigStore()).thenReturn(mWifiSettingsConfigStore);
+ when(mWifiSettingsConfigStore
+ .get(eq(WifiSettingsConfigStore.SUPPLICANT_HAL_AIDL_SERVICE_VERSION)))
+ .thenReturn(2);
+ if (Environment.isSdkAtLeastB()) {
+ when(mWifiSettingsConfigStore
+ .get(eq(WifiSettingsConfigStore.WIFI_P2P_SUPPORTED_FEATURES)))
+ .thenReturn(WifiP2pManager.FEATURE_WIFI_DIRECT_R2
+ | WifiP2pManager.FEATURE_PCC_MODE_ALLOW_LEGACY_AND_R2_CONNECTION);
+ } else {
+ when(mWifiSettingsConfigStore
+ .get(eq(WifiSettingsConfigStore.WIFI_P2P_SUPPORTED_FEATURES)))
+ .thenReturn(0L);
+ }
mWifiP2pNative = new WifiP2pNative(mWifiCondManager, mWifiNative, mWifiMetrics,
mWifiVendorHalMock, mSupplicantP2pIfaceHalMock, mHalDeviceManagerMock,
mPropertyServiceMock, mWifiInjector);
+ if (Environment.isSdkAtLeastB()) {
+ assertEquals(WifiP2pManager.FEATURE_SET_VENDOR_ELEMENTS
+ | WifiP2pManager.FEATURE_FLEXIBLE_DISCOVERY
+ | WifiP2pManager.FEATURE_GROUP_CLIENT_REMOVAL
+ | WifiP2pManager.FEATURE_GROUP_OWNER_IPV6_LINK_LOCAL_ADDRESS_PROVIDED
+ | WifiP2pManager.FEATURE_WIFI_DIRECT_R2
+ | WifiP2pManager.FEATURE_PCC_MODE_ALLOW_LEGACY_AND_R2_CONNECTION,
+ mWifiP2pNative.getSupportedFeatures());
+ } else {
+ assertEquals(WifiP2pManager.FEATURE_SET_VENDOR_ELEMENTS
+ | WifiP2pManager.FEATURE_FLEXIBLE_DISCOVERY
+ | WifiP2pManager.FEATURE_GROUP_CLIENT_REMOVAL
+ | WifiP2pManager.FEATURE_GROUP_OWNER_IPV6_LINK_LOCAL_ADDRESS_PROVIDED,
+ mWifiP2pNative.getSupportedFeatures());
+ }
when(mWifiNative.getClientInterfaceNames()).thenReturn(mWifiClientInterfaceNames);
@@ -733,8 +771,9 @@
*/
@Test
public void testJoinGroupWithConfig() {
+ when(Flags.wifiDirectR2()).thenReturn(true);
when(mSupplicantP2pIfaceHalMock.groupAdd(
- anyString(), anyString(), anyBoolean(),
+ anyString(), anyString(), anyInt(), anyBoolean(),
anyInt(), anyString(), anyBoolean())).thenReturn(true);
WifiP2pConfig config = new WifiP2pConfig.Builder()
.setNetworkName(TEST_NETWORK_NAME)
@@ -748,13 +787,90 @@
verify(mWifiCondManager).abortScan(eq(intf));
}
+ if (!Environment.isSdkAtLeastB()) {
+ verify(mSupplicantP2pIfaceHalMock).groupAdd(
+ eq(TEST_NETWORK_NAME),
+ eq(TEST_PASSPHRASE),
+ eq(WifiP2pConfig.PCC_MODE_CONNECTION_TYPE_LEGACY_ONLY),
+ eq(true),
+ eq(TEST_GROUP_FREQ),
+ eq(config.deviceAddress),
+ eq(true));
+ } else {
+ verify(mSupplicantP2pIfaceHalMock).groupAdd(
+ eq(TEST_NETWORK_NAME),
+ eq(TEST_PASSPHRASE),
+ eq(WifiP2pConfig.PCC_MODE_CONNECTION_TYPE_LEGACY_OR_R2),
+ eq(true),
+ eq(TEST_GROUP_FREQ),
+ eq(config.deviceAddress),
+ eq(true));
+ }
+ }
+
+ /**
+ * Verifies joining p2p group with Pcc Mode config.
+ */
+ @Test
+ public void testJoinGroupWithPccModeConfig() {
+ assumeTrue(Environment.isSdkAtLeastB());
+ when(Flags.wifiDirectR2()).thenReturn(true);
+ when(mSupplicantP2pIfaceHalMock.groupAdd(
+ anyString(), anyString(), anyInt(), anyBoolean(),
+ anyInt(), anyString(), anyBoolean())).thenReturn(true);
+
+ /* Check if we are upgrading LEGACY to R1/R2 compatible mode */
+ WifiP2pConfig config = new WifiP2pConfig.Builder()
+ .setNetworkName(TEST_NETWORK_NAME)
+ .setPassphrase(TEST_PASSPHRASE)
+ .setPccModeConnectionType(WifiP2pConfig.PCC_MODE_CONNECTION_TYPE_LEGACY_ONLY)
+ .setGroupOperatingFrequency(TEST_GROUP_FREQ)
+ .build();
+ assertTrue(mWifiP2pNative.p2pGroupAdd(config, true));
+
verify(mSupplicantP2pIfaceHalMock).groupAdd(
eq(TEST_NETWORK_NAME),
eq(TEST_PASSPHRASE),
- eq(true),
+ eq(WifiP2pConfig.PCC_MODE_CONNECTION_TYPE_LEGACY_OR_R2),
+ eq(false),
eq(TEST_GROUP_FREQ),
eq(config.deviceAddress),
eq(true));
+
+ /* Check the 6GHz configuration success case */
+ config = new WifiP2pConfig.Builder()
+ .setNetworkName(TEST_NETWORK_NAME)
+ .setPassphrase(TEST_PASSPHRASE)
+ .setPccModeConnectionType(WifiP2pConfig.PCC_MODE_CONNECTION_TYPE_R2_ONLY)
+ .setGroupOperatingBand(WifiP2pConfig.GROUP_OWNER_BAND_6GHZ)
+ .build();
+ assertTrue(mWifiP2pNative.p2pGroupAdd(config, true));
+ verify(mSupplicantP2pIfaceHalMock).groupAdd(
+ eq(TEST_NETWORK_NAME),
+ eq(TEST_PASSPHRASE),
+ eq(WifiP2pConfig.PCC_MODE_CONNECTION_TYPE_R2_ONLY),
+ eq(false),
+ eq(6),
+ eq(config.deviceAddress),
+ eq(true));
+
+ /* Check the 6GHz request fails in legacy mode */
+ config = new WifiP2pConfig.Builder()
+ .setNetworkName(TEST_NETWORK_NAME)
+ .setPassphrase(TEST_PASSPHRASE)
+ .setPccModeConnectionType(WifiP2pConfig.PCC_MODE_CONNECTION_TYPE_LEGACY_ONLY)
+ .setGroupOperatingBand(WifiP2pConfig.GROUP_OWNER_BAND_6GHZ)
+ .build();
+ assertFalse(mWifiP2pNative.p2pGroupAdd(config, true));
+
+ /* Check the 6GHz request fails in R1/R2 compatible mode */
+ config = new WifiP2pConfig.Builder()
+ .setNetworkName(TEST_NETWORK_NAME)
+ .setPassphrase(TEST_PASSPHRASE)
+ .setPccModeConnectionType(WifiP2pConfig.PCC_MODE_CONNECTION_TYPE_LEGACY_OR_R2)
+ .setGroupOperatingBand(WifiP2pConfig.GROUP_OWNER_BAND_6GHZ)
+ .build();
+ assertFalse(mWifiP2pNative.p2pGroupAdd(config, true));
}
/**
@@ -1083,4 +1199,28 @@
mWifiP2pNative.stopP2pSupplicantIfNecessary();
verify(mSupplicantP2pIfaceHalMock).terminate();
}
+
+ /**
+ * Verifies that the supported features retrieved from wpa_supplicant is cached in the
+ * config store
+ */
+ @Test
+ public void testSupportedFeatures() throws Exception {
+ when(mSupplicantP2pIfaceHalMock.initialize()).thenReturn(true);
+ when(mSupplicantP2pIfaceHalMock.isInitializationComplete()).thenReturn(true);
+ when(mSupplicantP2pIfaceHalMock.setupIface(eq(TEST_IFACE))).thenReturn(true);
+ when(mSupplicantP2pIfaceHalMock.registerDeathHandler(any())).thenReturn(true);
+ when(mSupplicantP2pIfaceHalMock.getSupportedFeatures())
+ .thenReturn(WifiP2pManager.FEATURE_WIFI_DIRECT_R2
+ | WifiP2pManager.FEATURE_PCC_MODE_ALLOW_LEGACY_AND_R2_CONNECTION);
+ assertEquals(TEST_IFACE, mWifiP2pNative.setupInterface(
+ mDestroyedListenerMock, mHandlerMock, mWorkSourceMock));
+ assertEquals(WifiP2pManager.FEATURE_WIFI_DIRECT_R2
+ | WifiP2pManager.FEATURE_PCC_MODE_ALLOW_LEGACY_AND_R2_CONNECTION
+ | WifiP2pManager.FEATURE_SET_VENDOR_ELEMENTS
+ | WifiP2pManager.FEATURE_FLEXIBLE_DISCOVERY
+ | WifiP2pManager.FEATURE_GROUP_CLIENT_REMOVAL
+ | WifiP2pManager.FEATURE_GROUP_OWNER_IPV6_LINK_LOCAL_ADDRESS_PROVIDED,
+ mWifiP2pNative.getSupportedFeatures());
+ }
}
diff --git a/service/tests/wifitests/src/com/android/server/wifi/p2p/WifiP2pServiceImplTest.java b/service/tests/wifitests/src/com/android/server/wifi/p2p/WifiP2pServiceImplTest.java
index 2ec2e59..1298be0 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/p2p/WifiP2pServiceImplTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/p2p/WifiP2pServiceImplTest.java
@@ -109,6 +109,7 @@
import android.net.wifi.p2p.WifiP2pWfdInfo;
import android.net.wifi.p2p.nsd.WifiP2pServiceInfo;
import android.net.wifi.p2p.nsd.WifiP2pServiceRequest;
+import android.net.wifi.util.Environment;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
@@ -1456,7 +1457,7 @@
when(mWifiInjector.getWifiP2pConnection()).thenReturn(mWifiP2pConnection);
when(mWifiDialogManager.createP2pInvitationReceivedDialog(any(), anyBoolean(), any(),
- anyInt(), any(), any())).thenReturn(mDialogHandle);
+ anyInt(), anyInt(), any(), any())).thenReturn(mDialogHandle);
when(mWifiDialogManager.createP2pInvitationSentDialog(any(), any(), anyInt()))
.thenReturn(mDialogHandle);
when(mWifiInjector.getClock()).thenReturn(mClock);
@@ -1535,20 +1536,24 @@
// * LocationManager.MODE_CHANGED_ACTION -- always
// * TetheringManager.ACTION_TETHER_STATE_CHANGED -- < S
// * UserManager.ACTION_USER_RESTRICTIONS_CHANGED -- >= T
+ verify(mContext).registerReceiverForAllUsers(
+ mBcastRxCaptor.capture(),
+ argThat(filter -> filter.hasAction(LocationManager.MODE_CHANGED_ACTION)),
+ eq(null), any(Handler.class));
if (SdkLevel.isAtLeastT()) {
- verify(mContext, times(3)).registerReceiver(mBcastRxCaptor.capture(),
+ verify(mContext, times(2)).registerReceiver(mBcastRxCaptor.capture(),
any(IntentFilter.class));
mUserRestrictionReceiver = mBcastRxCaptor.getAllValues().get(2);
} else if (SdkLevel.isAtLeastS()) {
- verify(mContext, times(2)).registerReceiver(mBcastRxCaptor.capture(),
+ verify(mContext).registerReceiver(mBcastRxCaptor.capture(),
any(IntentFilter.class));
} else {
- verify(mContext, times(3)).registerReceiver(mBcastRxCaptor.capture(),
+ verify(mContext, times(2)).registerReceiver(mBcastRxCaptor.capture(),
any(IntentFilter.class));
mTetherStateReceiver = mBcastRxCaptor.getAllValues().get(2);
}
- mWifiStateChangedReceiver = mBcastRxCaptor.getAllValues().get(0);
- mLocationModeReceiver = mBcastRxCaptor.getAllValues().get(1);
+ mWifiStateChangedReceiver = mBcastRxCaptor.getAllValues().get(1);
+ mLocationModeReceiver = mBcastRxCaptor.getAllValues().get(0);
verify(mWifiSettingsConfigStore).registerChangeListener(
eq(D2D_ALLOWED_WHEN_INFRA_STA_DISABLED),
mD2DAllowedSettingsCallbackCaptor.capture(), any());
@@ -1568,9 +1573,11 @@
mStaticMockSession = mockitoSession()
.mockStatic(NetworkInterface.class)
.mockStatic(Process.class)
+ .mockStatic(WifiInjector.class)
.startMocking();
lenient().when(NetworkInterface.getByName(eq(IFACE_NAME_P2P)))
.thenReturn(mP2pNetworkInterface);
+ when(WifiInjector.getInstance()).thenReturn(mWifiInjector);
when(mLayoutInflater.cloneInContext(any())).thenReturn(mLayoutInflater);
when(mLayoutInflater.inflate(anyInt(), any())).thenReturn(mView);
when(mLayoutInflater.inflate(anyInt(), any(), anyBoolean())).thenReturn(mView);
@@ -6776,7 +6783,7 @@
} else {
verify(mWifiDialogManager).createP2pInvitationReceivedDialog(
eq(pdEvent.device.deviceName), eq(false), eq(pdEvent.pin),
- anyInt(), any(), any());
+ anyInt(), anyInt(), any(), any());
verify(mDialogHandle).launchDialog();
}
}
@@ -7300,8 +7307,9 @@
verify(mAlertDialog).show();
} else {
verify(mWifiDialogManager).createP2pInvitationReceivedDialog(anyString(), anyBoolean(),
- any(), eq(Display.DEFAULT_DISPLAY), any(), any());
- verify(mDialogHandle).launchDialog(P2P_INVITATION_RECEIVED_TIMEOUT_MS);
+ any(), eq(P2P_INVITATION_RECEIVED_TIMEOUT_MS), eq(Display.DEFAULT_DISPLAY),
+ any(), any());
+ verify(mDialogHandle).launchDialog();
}
}
@@ -7328,8 +7336,9 @@
sendNegotiationRequestEvent(config);
verify(mWifiDialogManager).createP2pInvitationReceivedDialog(anyString(),
- anyBoolean(), any(), eq(someNonDefaultDisplayId), any(), any());
- verify(mDialogHandle).launchDialog(P2P_INVITATION_RECEIVED_TIMEOUT_MS);
+ anyBoolean(), any(), eq(P2P_INVITATION_RECEIVED_TIMEOUT_MS),
+ eq(someNonDefaultDisplayId), any(), any());
+ verify(mDialogHandle).launchDialog();
}
/**
@@ -7356,8 +7365,9 @@
// "simple" client connect (no display ID)
sendNegotiationRequestEvent(config);
verify(mWifiDialogManager).createP2pInvitationReceivedDialog(anyString(), anyBoolean(),
- any(), eq(Display.DEFAULT_DISPLAY), any(), any());
- verify(mDialogHandle).launchDialog(P2P_INVITATION_RECEIVED_TIMEOUT_MS);
+ any(), eq(P2P_INVITATION_RECEIVED_TIMEOUT_MS), eq(Display.DEFAULT_DISPLAY), any(),
+ any());
+ verify(mDialogHandle).launchDialog();
}
private void verifySetVendorElement(boolean isP2pActivated, boolean shouldSucceed,
@@ -8132,7 +8142,7 @@
mockEnterGroupCreatedState();
- // The first provision discvoery request triggers the dialog.
+ // The first provision discovery request triggers the dialog.
WifiP2pProvDiscEvent pdEvent = new WifiP2pProvDiscEvent();
pdEvent.device = mTestWifiP2pDevice;
sendSimpleMsg(null, WifiP2pMonitor.P2P_PROV_DISC_PBC_REQ_EVENT,
@@ -8140,8 +8150,8 @@
verify(mWifiDialogManager).createP2pInvitationReceivedDialog(
eq(mTestWifiP2pDevice.deviceAddress), anyBoolean(),
- any(), anyInt(), any(), any());
- verify(mDialogHandle).launchDialog(P2P_INVITATION_RECEIVED_TIMEOUT_MS);
+ any(), eq(P2P_INVITATION_RECEIVED_TIMEOUT_MS), anyInt(), any(), any());
+ verify(mDialogHandle).launchDialog();
// Handle it programmatically.
sendSimpleMsg(null, WifiP2pServiceImpl.PEER_CONNECTION_USER_REJECT);
@@ -8154,10 +8164,10 @@
reset(mWifiDialogManager);
reset(mDialogHandle);
verify(mWifiDialogManager, never()).createP2pInvitationReceivedDialog(
- any(), anyBoolean(), any(), anyInt(), any(), any());
+ any(), anyBoolean(), any(), anyInt(), anyInt(), any(), any());
when(mWifiDialogManager.createP2pInvitationReceivedDialog(any(), anyBoolean(), any(),
- anyInt(), any(), any())).thenReturn(mDialogHandle);
+ anyInt(), anyInt(), any(), any())).thenReturn(mDialogHandle);
when(mWifiDialogManager.createP2pInvitationSentDialog(any(), any(), anyInt()))
.thenReturn(mDialogHandle);
when(mClock.getElapsedSinceBootMillis()).thenReturn(P2P_PEER_AUTH_TIMEOUT_MS + 1L);
@@ -8169,8 +8179,8 @@
// Another dialog should be triggered.
verify(mWifiDialogManager).createP2pInvitationReceivedDialog(
eq(mTestWifiP2pDevice.deviceAddress), anyBoolean(),
- any(), anyInt(), any(), any());
- verify(mDialogHandle).launchDialog(P2P_INVITATION_RECEIVED_TIMEOUT_MS);
+ any(), eq(P2P_INVITATION_RECEIVED_TIMEOUT_MS), anyInt(), any(), any());
+ verify(mDialogHandle).launchDialog();
}
@Test
@@ -8627,4 +8637,48 @@
verify(mWifiNative).teardownInterface();
verify(mWifiMonitor).stopMonitoring(anyString());
}
+
+ /**
+ * Verify {@link WifiP2pManager#GET_DIR_INFO} message.
+ */
+ @Test
+ public void testGetDirInfo() throws Exception {
+ assumeTrue(Environment.isSdkAtLeastB());
+ forceP2pEnabled(mClient1);
+ when(mWifiPermissionsUtil.checkNearbyDevicesPermission(any(), anyBoolean(), any()))
+ .thenReturn(false);
+ sendSimpleMsg(mClientMessenger, WifiP2pManager.GET_DIR_INFO);
+ assertTrue(mClientHandler.hasMessages(WifiP2pManager.GET_DIR_INFO_FAILED));
+
+ when(mWifiPermissionsUtil.checkNearbyDevicesPermission(any(), anyBoolean(), any()))
+ .thenReturn(true);
+ sendSimpleMsg(mClientMessenger, WifiP2pManager.GET_DIR_INFO);
+
+ verify(mClientHandler, times(2)).sendMessage(mMessageCaptor.capture());
+ List<Message> messages = mMessageCaptor.getAllValues();
+ assertEquals(WifiP2pManager.GET_DIR_INFO_FAILED, messages.get(0).what);
+ assertEquals(WifiP2pManager.RESPONSE_GET_DIR_INFO, messages.get(1).what);
+ }
+
+ /**
+ * Verify {@link WifiP2pManager#VALIDATE_DIR_INFO} message.
+ */
+ @Test
+ public void testValidateDirInfo() throws Exception {
+ assumeTrue(Environment.isSdkAtLeastB());
+ forceP2pEnabled(mClient1);
+ when(mWifiPermissionsUtil.checkNearbyDevicesPermission(any(), anyBoolean(), any()))
+ .thenReturn(false);
+ sendSimpleMsg(mClientMessenger, WifiP2pManager.VALIDATE_DIR_INFO);
+ assertTrue(mClientHandler.hasMessages(WifiP2pManager.VALIDATE_DIR_INFO_FAILED));
+
+ when(mWifiPermissionsUtil.checkNearbyDevicesPermission(any(), anyBoolean(), any()))
+ .thenReturn(true);
+ sendSimpleMsg(mClientMessenger, WifiP2pManager.VALIDATE_DIR_INFO);
+
+ verify(mClientHandler, times(2)).sendMessage(mMessageCaptor.capture());
+ List<Message> messages = mMessageCaptor.getAllValues();
+ assertEquals(WifiP2pManager.VALIDATE_DIR_INFO_FAILED, messages.get(0).what);
+ assertEquals(WifiP2pManager.RESPONSE_VALIDATE_DIR_INFO, messages.get(1).what);
+ }
}
diff --git a/service/tests/wifitests/src/com/android/server/wifi/rtt/RttServiceImplTest.java b/service/tests/wifitests/src/com/android/server/wifi/rtt/RttServiceImplTest.java
index c961169..cc570c7 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/rtt/RttServiceImplTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/rtt/RttServiceImplTest.java
@@ -32,6 +32,7 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Mockito.doAnswer;
@@ -51,7 +52,6 @@
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
-import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.location.LocationManager;
import android.net.MacAddress;
@@ -252,8 +252,11 @@
mMockLooper.dispatchAll();
ArgumentCaptor<BroadcastReceiver> bcastRxCaptor = ArgumentCaptor.forClass(
BroadcastReceiver.class);
- verify(mockContext, times(2)).registerReceiver(bcastRxCaptor.capture(),
- any(IntentFilter.class));
+ verify(mockContext).registerReceiver(bcastRxCaptor.capture(),
+ argThat(filter -> filter.hasAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED)));
+ verify(mockContext).registerReceiverForAllUsers(bcastRxCaptor.capture(),
+ argThat(filter -> filter.hasAction(LocationManager.MODE_CHANGED_ACTION)),
+ eq(null), any(Handler.class));
mPowerBcastReceiver = bcastRxCaptor.getAllValues().get(0);
mLocationModeReceiver = bcastRxCaptor.getAllValues().get(1);
diff --git a/service/tests/wifitests/src/com/android/server/wifi/scanner/WifiScanningServiceTest.java b/service/tests/wifitests/src/com/android/server/wifi/scanner/WifiScanningServiceTest.java
index 971722a..ff8bcfb 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/scanner/WifiScanningServiceTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/scanner/WifiScanningServiceTest.java
@@ -461,6 +461,7 @@
String serviceDump = dumpService();
Pattern logLineRegex = Pattern.compile("^.+" + type
+ ": ClientInfo\\[uid=\\d+, package=" + TEST_PACKAGE_NAME
+ + ", attributionTag=" + TEST_FEATURE_ID
+ ", Mock for Stub, hashCode: \\d+\\]",
Pattern.MULTILINE);
assertTrue("dump did not contain log with {" + logLineRegex
@@ -473,6 +474,7 @@
String extraPattern = extra == null ? "" : "," + extra;
Pattern logLineRegex = Pattern.compile("^.+" + callback
+ ": ClientInfo\\[uid=\\d+, package=" + TEST_PACKAGE_NAME
+ + ", attributionTag=" + TEST_FEATURE_ID
+ ", Mock for Stub, hashCode: \\d+\\]"
+ extraPattern + "$", Pattern.MULTILINE);
assertTrue("dump did not contain callback log with callback {" + logLineRegex
@@ -2178,7 +2180,7 @@
verifyNoMoreInteractions(client.listener);
verifyNoMoreInteractions(client1.listener);
assertDumpContainsRequestLog("registerScanListener");
- assertDumpContainsCallbackLog("singleScanResults",
+ assertDumpContainsCallbackLog("singleScanResults listener",
"results=" + results.getScanData().getResults().length);
}
@@ -2314,9 +2316,9 @@
client.verifyScanResultsReceived(results2and3.getScanData());
assertDumpContainsRequestLog("registerScanListener");
- assertDumpContainsCallbackLog("singleScanResults",
+ assertDumpContainsCallbackLog("singleScanResults listener",
"results=" + results1.getRawScanResults().length);
- assertDumpContainsCallbackLog("singleScanResults",
+ assertDumpContainsCallbackLog("singleScanResults listener",
"results=" + results2and3.getRawScanResults().length);
}
@@ -2754,6 +2756,7 @@
Pattern logLineRegex = Pattern.compile(
"^.+" + "Successfully stopped all requests for client "
+ "ClientInfo\\[uid=\\d+, package=" + TEST_PACKAGE_NAME
+ + ", attributionTag=" + TEST_FEATURE_ID
+ ", Mock for Stub, hashCode: \\d+\\]",
Pattern.MULTILINE);
assertTrue("dump did not contain log with [" + logLineRegex + "]\n" + serviceDump + "\n",
diff --git a/service/tests/wifitests/src/com/android/server/wifi/util/ApConfigUtilTest.java b/service/tests/wifitests/src/com/android/server/wifi/util/ApConfigUtilTest.java
index 749d05e..aabfb38 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/util/ApConfigUtilTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/util/ApConfigUtilTest.java
@@ -39,8 +39,10 @@
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.validateMockitoUsage;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.withSettings;
import android.net.MacAddress;
import android.net.wifi.CoexUnsafeChannel;
@@ -59,18 +61,23 @@
import androidx.test.filters.SmallTest;
+import com.android.dx.mockito.inline.extended.ExtendedMockito;
import com.android.modules.utils.build.SdkLevel;
import com.android.server.wifi.SoftApManager;
import com.android.server.wifi.WifiBaseTest;
+import com.android.server.wifi.WifiInjector;
import com.android.server.wifi.WifiNative;
import com.android.server.wifi.WifiSettingsConfigStore;
import com.android.server.wifi.coex.CoexManager;
+import com.android.wifi.flags.Flags;
import com.android.wifi.resources.R;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.mockito.MockitoSession;
import java.util.ArrayList;
import java.util.Arrays;
@@ -173,15 +180,23 @@
@Mock WifiSettingsConfigStore mConfigStore;
@Mock
DeviceWiphyCapabilities mDeviceWiphyCapabilities;
+ @Mock WifiInjector mWifiInjector;
private SoftApCapability mCapability;
private boolean mApBridgeIfaceCobinationSupported = false;
private boolean mApBridgeWithStaIfaceCobinationSupported = false;
+ private MockitoSession mSession;
+
/**
* Setup test.
*/
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
+ // Mock WifiMigration to avoid calling into its static methods
+ mSession = ExtendedMockito.mockitoSession()
+ .mockStatic(Flags.class, withSettings().lenient())
+ .mockStatic(WifiInjector.class, withSettings().lenient())
+ .startMocking();
final long testFeatures = SoftApCapability.SOFTAP_FEATURE_CLIENT_FORCE_DISCONNECT
| SoftApCapability.SOFTAP_FEATURE_BAND_6G_SUPPORTED
| SoftApCapability.SOFTAP_FEATURE_BAND_60G_SUPPORTED;
@@ -189,6 +204,8 @@
mCapability.setSupportedChannelList(SoftApConfiguration.BAND_2GHZ, ALLOWED_2G_CHANS);
mCapability.setSupportedChannelList(SoftApConfiguration.BAND_5GHZ, ALLOWED_5G_CHANS);
mCapability.setSupportedChannelList(SoftApConfiguration.BAND_60GHZ, ALLOWED_60G_CHANS);
+ when(WifiInjector.getInstance()).thenReturn(mWifiInjector);
+ when(mWifiInjector.getContext()).thenReturn(mContext);
when(mContext.getResourceCache()).thenReturn(mResources);
when(mResources.getBoolean(R.bool.config_wifi24ghzSupport)).thenReturn(true);
when(mResources.getBoolean(R.bool.config_wifi5ghzSupport)).thenReturn(true);
@@ -221,6 +238,17 @@
}
/**
+ * Called after each test
+ */
+ @After
+ public void cleanup() {
+ validateMockitoUsage();
+ if (mSession != null) {
+ mSession.finishMocking();
+ }
+ }
+
+ /**
* Verify Bridge AP support when Iface combination for AP bridge is allowed.
*/
@Test
@@ -1377,7 +1405,7 @@
.thenReturn(TEST_5G_DFS_FREQS);
when(mWifiNative.getChannelsForBand(anyInt())).thenReturn(new int[0]);
List<Integer> result = ApConfigUtil.getAvailableChannelFreqsForBand(
- SoftApConfiguration.BAND_5GHZ, mWifiNative, mResources, true);
+ SoftApConfiguration.BAND_5GHZ, mWifiNative, null, true);
// make sure we try to get dfs channel.
verify(mWifiNative).getChannelsForBand(WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY);
for (int freq : result) {
@@ -1412,7 +1440,7 @@
when(mWifiNative.getChannelsForBand(WifiScanner.WIFI_BAND_5_GHZ))
.thenReturn(ALLOWED_5G_FREQS);
List<Integer> result = ApConfigUtil.getAvailableChannelFreqsForBand(
- SoftApConfiguration.BAND_5GHZ, mWifiNative, mResources, true);
+ SoftApConfiguration.BAND_5GHZ, mWifiNative, null, true);
// make sure we try to get available channels from wificond.
verify(mWifiNative).getChannelsForBand(WifiScanner.WIFI_BAND_5_GHZ);
verify(mWifiNative, never()).getUsableChannels(anyInt(), anyInt(), anyInt());
@@ -1432,7 +1460,7 @@
.thenReturn(ALLOWED_5G_FREQS);
when(mWifiNative.getUsableChannels(anyInt(), anyInt(), anyInt())).thenReturn(null);
List<Integer> result = ApConfigUtil.getAvailableChannelFreqsForBand(
- SoftApConfiguration.BAND_5GHZ, mWifiNative, mResources, true);
+ SoftApConfiguration.BAND_5GHZ, mWifiNative, null, true);
// make sure we try to get available channels from HAL and fallback to wificond.
verify(mWifiNative).getChannelsForBand(WifiScanner.WIFI_BAND_5_GHZ);
verify(mWifiNative).getUsableChannels(eq(WifiScanner.WIFI_BAND_5_GHZ), anyInt(), anyInt());
@@ -1455,7 +1483,7 @@
.thenReturn(false);
/* 11be is disallowed when IEEE80211_BE feature is not supported */
assertFalse(ApConfigUtil.is11beAllowedForThisConfiguration(mDeviceWiphyCapabilities,
- mContext, config, true));
+ mContext, config, true, 0, false));
when(mResources.getBoolean(R.bool.config_wifiSoftapIeee80211beSupported))
.thenReturn(true);
@@ -1465,13 +1493,34 @@
.thenReturn(true);
/* 11be is allowed if chip supports single link MLO in bridged mode */
assertTrue(ApConfigUtil.is11beAllowedForThisConfiguration(mDeviceWiphyCapabilities,
- mContext, config, true));
+ mContext, config, true, 0, false));
/* 11be is not allowed if chip doesn't support single link MLO in bridged mode */
when(mResources.getBoolean(R.bool.config_wifiSoftApSingleLinkMloInBridgedModeSupported))
.thenReturn(false);
assertFalse(ApConfigUtil.is11beAllowedForThisConfiguration(mDeviceWiphyCapabilities,
- mContext, config, true));
+ mContext, config, true, 0, false));
+
+ when(Flags.mloSap()).thenReturn(true);
+ // two MLDs supported, allow 11be on bridged mode.
+ when(mResources.getInteger(R.integer.config_wifiSoftApMaxNumberMLDSupported))
+ .thenReturn(2);
+ assertTrue(ApConfigUtil.is11beAllowedForThisConfiguration(mDeviceWiphyCapabilities,
+ mContext, config, true, 0, false));
+
+ // One MLD only, disallow 11be on bridged AP.
+ when(mResources.getInteger(R.integer.config_wifiSoftApMaxNumberMLDSupported))
+ .thenReturn(1);
+ assertFalse(ApConfigUtil.is11beAllowedForThisConfiguration(mDeviceWiphyCapabilities,
+ mContext, config, true, 0, false));
+
+ // One MLD only, disallow 11be when there is existing 11be AP.
+ assertFalse(ApConfigUtil.is11beAllowedForThisConfiguration(mDeviceWiphyCapabilities,
+ mContext, config, false, 1, false));
+
+ // One MLD only but chip support MultilinksOnMLD, allow 11be on bridged AP.
+ assertTrue(ApConfigUtil.is11beAllowedForThisConfiguration(mDeviceWiphyCapabilities,
+ mContext, config, true, 0, true));
}
@Test
public void testIs11beDisabledForSecurityType() throws Exception {
diff --git a/tests/OWNERS b/tests/OWNERS
index bde7824..288dd24 100644
--- a/tests/OWNERS
+++ b/tests/OWNERS
@@ -4,4 +4,3 @@
# Engprod - Not owner of the test but help maintaining the module as an example
jdesprez@google.com
frankfeng@google.com
-murj@google.com
diff --git a/tests/hostsidetests/multidevices/com.google.snippet.wifi/aware/Android.bp b/tests/hostsidetests/multidevices/com.google.snippet.wifi/aware/Android.bp
index 09249b5..c0edd52 100644
--- a/tests/hostsidetests/multidevices/com.google.snippet.wifi/aware/Android.bp
+++ b/tests/hostsidetests/multidevices/com.google.snippet.wifi/aware/Android.bp
@@ -53,6 +53,7 @@
"compatibility-device-util-axt",
"guava",
"mobly-snippet-lib",
+ "mobly-bundled-snippets-lib",
],
min_sdk_version: "31",
}
diff --git a/tests/hostsidetests/multidevices/com.google.snippet.wifi/aware/AndroidManifestNew.xml b/tests/hostsidetests/multidevices/com.google.snippet.wifi/aware/AndroidManifestNew.xml
index 7dc04df..cf13a13 100644
--- a/tests/hostsidetests/multidevices/com.google.snippet.wifi/aware/AndroidManifestNew.xml
+++ b/tests/hostsidetests/multidevices/com.google.snippet.wifi/aware/AndroidManifestNew.xml
@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
package="com.google.snippet.wifi.aware">
<!-- Declare the minimum Android SDK version and internet permission,
which are required by Mobly Snippet Lib since it uses network socket. -->
@@ -20,8 +21,10 @@
of a snippet class -->
<meta-data
android:name="mobly-snippets"
+ tools:replace="android:value"
android:value="com.google.snippet.wifi.aware.WifiAwareManagerSnippet,
- com.google.snippet.wifi.aware.ConnectivityManagerSnippet,"/>
+ com.google.snippet.wifi.aware.ConnectivityManagerSnippet,
+ com.google.android.mobly.snippet.bundled.WifiManagerSnippet"/>
<meta-data
android:name="mobly-object-converter"
android:value="com.google.snippet.wifi.aware.WifiAwareSnippetConverter"/>
diff --git a/tests/hostsidetests/multidevices/com.google.snippet.wifi/aware/WifiAwareJsonDeserializer.java b/tests/hostsidetests/multidevices/com.google.snippet.wifi/aware/WifiAwareJsonDeserializer.java
index 7c4eb88..70a0a63 100644
--- a/tests/hostsidetests/multidevices/com.google.snippet.wifi/aware/WifiAwareJsonDeserializer.java
+++ b/tests/hostsidetests/multidevices/com.google.snippet.wifi/aware/WifiAwareJsonDeserializer.java
@@ -96,7 +96,6 @@
private static final String RANGING_REQUEST_PEER_IDS = "peer_ids";
private static final String RANGING_REQUEST_PEER_MACS = "peer_mac_addresses";
-
private WifiAwareJsonDeserializer() {
}
diff --git a/tests/hostsidetests/multidevices/com.google.snippet.wifi/aware/WifiAwareManagerSnippet.java b/tests/hostsidetests/multidevices/com.google.snippet.wifi/aware/WifiAwareManagerSnippet.java
index f7d8673..3cf9fff 100644
--- a/tests/hostsidetests/multidevices/com.google.snippet.wifi/aware/WifiAwareManagerSnippet.java
+++ b/tests/hostsidetests/multidevices/com.google.snippet.wifi/aware/WifiAwareManagerSnippet.java
@@ -43,6 +43,7 @@
import android.net.wifi.rtt.RangingResult;
import android.net.wifi.rtt.RangingResultCallback;
import android.net.wifi.rtt.WifiRttManager;
+import android.net.wifi.ScanResult;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Bundle;
@@ -65,11 +66,15 @@
import com.google.android.mobly.snippet.rpc.RpcOptional;
import com.google.android.mobly.snippet.util.Log;
+import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
+import java.util.ListIterator;
import java.util.concurrent.ConcurrentHashMap;
/**
@@ -347,6 +352,10 @@
/**
* Checks if Wi-Fi RTT is available.
*/
+ @Rpc(description = "Check if Wi-Fi Aware is available")
+ public Boolean wifiRttIsAvailable() {
+ return mWifiRttManager.isAvailable();
+ }
private void checkWifiRttAvailable() throws WifiAwareManagerSnippetException {
if (!mWifiRttManager.isAvailable()) {
throw new WifiAwareManagerSnippetException("WiFi RTT is not available now.");
@@ -833,6 +842,98 @@
}
/**
+ * Converts a JSON representation of a ScanResult to an actual ScanResult object. Mirror of
+ * the code in
+ * {@link com.googlecode.android_scripting.jsonrpc.JsonBuilder#buildJsonScanResult(ScanResult)}.
+ *
+ * @param j JSON object representing a ScanResult.
+ * @return a ScanResult object
+ * @throws JSONException on any JSON errors
+ */
+ public static ScanResult getScanResult(JSONObject j) throws JSONException {
+ if (j == null) {
+ return null;
+ }
+
+ ScanResult scanResult = new ScanResult();
+
+ if (j.has("BSSID")) {
+ scanResult.BSSID = j.getString("BSSID");
+ }
+ if (j.has("SSID")) {
+ scanResult.SSID = j.getString("SSID");
+ }
+ if (j.has("frequency")) {
+ scanResult.frequency = j.getInt("frequency");
+ }
+ if (j.has("level")) {
+ scanResult.level = j.getInt("level");
+ }
+ if (j.has("capabilities")) {
+ scanResult.capabilities = j.getString("capabilities");
+ }
+ if (j.has("timestamp")) {
+ scanResult.timestamp = j.getLong("timestamp");
+ }
+ if (j.has("centerFreq0")) {
+ scanResult.centerFreq0 = j.getInt("centerFreq0");
+ }
+ if (j.has("centerFreq1")) {
+ scanResult.centerFreq1 = j.getInt("centerFreq1");
+ }
+ if (j.has("channelWidth")) {
+ scanResult.channelWidth = j.getInt("channelWidth");
+ }
+ if (j.has("operatorFriendlyName")) {
+ scanResult.operatorFriendlyName = j.getString("operatorFriendlyName");
+ }
+ if (j.has("venueName")) {
+ scanResult.venueName = j.getString("venueName");
+ }
+
+ return scanResult;
+ }
+
+ /**
+ * Converts a JSONArray toa a list of ScanResult.
+ *
+ * @param j JSONArray representing a collection of ScanResult objects
+ * @return a list of ScanResult objects
+ * @throws JSONException on any JSON error
+ */
+ public static List<ScanResult> getScanResults(JSONArray j) throws JSONException {
+ if (j == null || j.length() == 0) {
+ return null;
+ }
+
+ ArrayList<ScanResult> scanResults = new ArrayList<>(j.length());
+ for (int i = 0; i < j.length(); ++i) {
+ scanResults.add(getScanResult(j.getJSONObject(i)));
+ }
+
+ return scanResults;
+ }
+
+ /**
+ * Starts Wi-Fi RTT ranging with Wi-Fi Aware access points.
+ *
+ * @param callbackId Assigned automatically by mobly for all async RPCs.
+ * @param requestJsonObject The ranging request in JSONArray type for calling {@link
+ * android.net.wifi.ScanResult}.
+ */
+ @AsyncRpc(description = "Start ranging to an Access Points.")
+ public void wifiRttStartRangingToAccessPoints(
+ String callbackId, JSONArray requestJsonObject
+ ) throws JSONException, WifiAwareManagerSnippetException {
+ Log.v("wifiRttStartRangingToAccessPoints: " + requestJsonObject);
+ RangingRequest request = new RangingRequest.Builder().addAccessPoints(
+ getScanResults(requestJsonObject)).build();
+ Log.v("Starting Wi-Fi RTT ranging with access point: " + request.toString());
+ RangingCallback rangingCb = new RangingCallback(eventCache, callbackId);
+ mWifiRttManager.startRanging(request, command -> mHandler.post(command), rangingCb);
+ }
+
+ /**
* Starts Wi-Fi RTT ranging with Wi-Fi Aware peers.
*
* @param callbackId Assigned automatically by mobly for all async RPCs.
@@ -869,7 +970,7 @@
public void onRangingFailure(int code) {
SnippetEvent event = new SnippetEvent(mCallbackId, EVENT_NAME_RANGING_RESULT);
event.getData().putString("callbackName", "onRangingFailure");
- event.getData().putInt("statusCode", code);
+ event.getData().putInt("status", code);
mEventCache.postEvent(event);
}
diff --git a/tests/hostsidetests/multidevices/com.google.snippet.wifi/aware/WifiAwareSnippetConverter.java b/tests/hostsidetests/multidevices/com.google.snippet.wifi/aware/WifiAwareSnippetConverter.java
index 154d0eb..edcfeac 100644
--- a/tests/hostsidetests/multidevices/com.google.snippet.wifi/aware/WifiAwareSnippetConverter.java
+++ b/tests/hostsidetests/multidevices/com.google.snippet.wifi/aware/WifiAwareSnippetConverter.java
@@ -19,14 +19,17 @@
import android.net.NetworkRequest;
import android.net.wifi.aware.PublishConfig;
import android.net.wifi.aware.SubscribeConfig;
+import android.net.wifi.ScanResult;
import android.net.wifi.aware.WifiAwareNetworkSpecifier;
import com.google.android.mobly.snippet.SnippetObjectConverter;
+import com.google.android.mobly.snippet.util.Log;
import org.json.JSONException;
import org.json.JSONObject;
import java.lang.reflect.Type;
+import java.util.List;
/**
* The converter class that allows users to use custom type as snippet RPC arguments and return
@@ -34,6 +37,19 @@
*/
public class WifiAwareSnippetConverter implements SnippetObjectConverter {
+
+ public static String trimQuotationMarks(String originalString) {
+ String result = originalString;
+ if (originalString == null)
+ return result;
+ if (originalString.length() > 2
+ && originalString.charAt(0) == '"'
+ && originalString.charAt(originalString.length() - 1) == '"') {
+ result = originalString.substring(1, originalString.length() - 1);
+ }
+ return result;
+ }
+
@Override
public JSONObject serialize(Object object) throws JSONException {
// If the RPC method requires a custom return type, e.g. SubscribeConfig, PublishConfig, we
@@ -49,6 +65,24 @@
return null;
}
+ public static JSONObject serializeScanResult(ScanResult data) throws JSONException {
+ JSONObject result = new JSONObject();
+ result.put("BSSID", data.BSSID);
+ result.put("SSID", trimQuotationMarks(data.getWifiSsid().toString()));
+ result.put("capabilities", data.capabilities);
+ result.put("centerFreq0", data.centerFreq0);
+ result.put("centerFreq1", data.centerFreq1);
+ result.put("channelWidth", data.channelWidth);
+ result.put("frequency", data.frequency);
+ result.put("level", data.level);
+ result.put("operatorFriendlyName",
+ (data.operatorFriendlyName != null) ? data.operatorFriendlyName.toString() : "");
+ result.put("timestamp", data.timestamp);
+ result.put("venueName", (data.venueName != null) ? data.venueName.toString() : "");
+ result.put("scan_result_parcel", SerializationUtil.parcelableToString(data));
+ return result;
+ }
+
@Override
public Object deserialize(JSONObject jsonObject, Type type) throws JSONException {
// The parameters of Mobly RPC directly reference the Object type.
diff --git a/tests/hostsidetests/multidevices/test/Android.bp b/tests/hostsidetests/multidevices/test/Android.bp
index 81c7eb8..fb559e3 100644
--- a/tests/hostsidetests/multidevices/test/Android.bp
+++ b/tests/hostsidetests/multidevices/test/Android.bp
@@ -42,11 +42,6 @@
"cts",
"general-tests",
],
- version: {
- py3: {
- embedded_launcher: true,
- },
- },
}
python_test_host {
@@ -88,11 +83,6 @@
tags: ["mobly"],
},
test_suites: ["general-tests"],
- version: {
- py3: {
- embedded_launcher: true,
- },
- },
}
python_library_host {
@@ -123,11 +113,6 @@
tags: ["mobly"],
},
test_suites: ["general-tests"],
- version: {
- py3: {
- embedded_launcher: true,
- },
- },
}
python_test_host {
@@ -153,9 +138,4 @@
tags: ["mobly"],
},
test_suites: ["general-tests"],
- version: {
- py3: {
- embedded_launcher: true,
- },
- },
}
diff --git a/tests/hostsidetests/multidevices/test/aware/integration/Android.bp b/tests/hostsidetests/multidevices/test/aware/integration/Android.bp
index aa7c0cd..55483e3 100644
--- a/tests/hostsidetests/multidevices/test/aware/integration/Android.bp
+++ b/tests/hostsidetests/multidevices/test/aware/integration/Android.bp
@@ -134,6 +134,7 @@
"aware_lib_utils",
"mobly",
"wifi_aware_constants",
+ "platform-test-py-annotations",
],
test_suites: [
"general-tests",
@@ -176,6 +177,7 @@
"aware_lib_utils",
"mobly",
"wifi_aware_constants",
+ "platform-test-py-annotations",
],
test_suites: [
"general-tests",
@@ -224,3 +226,22 @@
tags: ["mobly"],
},
}
+
+python_test_host {
+ name: "WifiRttDisableTestCases",
+ main: "wifi_rtt_disable_test.py",
+ srcs: ["wifi_rtt_disable_test.py"],
+ device_common_data: [":wifi_aware_snippet_new"],
+ libs: [
+ "aware_lib_utils",
+ "mobly",
+ "wifi_aware_constants",
+ ],
+ test_suites: [
+ "general-tests",
+ ],
+ test_options: {
+ unit_test: false,
+ tags: ["mobly"],
+ },
+}
diff --git a/tests/hostsidetests/multidevices/test/aware/integration/wifi_aware_datapath_test.py b/tests/hostsidetests/multidevices/test/aware/integration/wifi_aware_datapath_test.py
index 21d26aa..6233347 100644
--- a/tests/hostsidetests/multidevices/test/aware/integration/wifi_aware_datapath_test.py
+++ b/tests/hostsidetests/multidevices/test/aware/integration/wifi_aware_datapath_test.py
@@ -1046,7 +1046,7 @@
_DATA_PATH_INITIATOR,
resp_mac,
init_passphrase,
- resp_pmk,
+ init_pmk,
network_id
)
# Initiator & Responder:
@@ -1657,6 +1657,14 @@
# peer using the Aware-provided peer handle (as opposed to a MAC address).
#######################################
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.PublishConfig.Builder#setPublishType(PublishConfig.PUBLISH_TYPE_UNSOLICITED)',
+ 'android.net.wifi.aware.SubscribeConfig.Builder#setSubscribeType(SubscribeConfig.SUBSCRIBE_TYPE_PASSIVE)',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build()',
+ ]
+ )
+
def test_ib_unsolicited_passive_open_specific(self):
"""Data-path: in-band, unsolicited/passive, open encryption, specific peer
@@ -1668,6 +1676,14 @@
encr_type=self.ENCR_TYPE_OPEN,
use_peer_id=True)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.PublishConfig.Builder#setPublishType(PublishConfig.PUBLISH_TYPE_UNSOLICITED)',
+ 'android.net.wifi.aware.SubscribeConfig.Builder#setSubscribeType(SubscribeConfig.SUBSCRIBE_TYPE_PASSIVE)',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build()',
+ ]
+ )
+
def test_ib_unsolicited_passive_open_any(self):
"""Data-path: in-band, unsolicited/passive, open encryption, any peer
@@ -1679,6 +1695,15 @@
encr_type=self.ENCR_TYPE_OPEN,
use_peer_id=False)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.PublishConfig.Builder#setPublishType(PublishConfig.PUBLISH_TYPE_UNSOLICITED)',
+ 'android.net.wifi.aware.SubscribeConfig.Builder#setSubscribeType(SubscribeConfig.SUBSCRIBE_TYPE_PASSIVE)',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build()',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#setPskPassphrase(String)',
+ ]
+ )
+
def test_ib_unsolicited_passive_passphrase_specific(self):
"""Data-path: in-band, unsolicited/passive, passphrase, specific peer
@@ -1690,6 +1715,15 @@
encr_type=self.ENCR_TYPE_PASSPHRASE,
use_peer_id=True)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.PublishConfig.Builder#setPublishType(PublishConfig.PUBLISH_TYPE_UNSOLICITED)',
+ 'android.net.wifi.aware.SubscribeConfig.Builder#setSubscribeType(SubscribeConfig.SUBSCRIBE_TYPE_PASSIVE)',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build()',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#setPskPassphrase(String)',
+ ]
+ )
+
def test_ib_unsolicited_passive_passphrase_any(self):
"""Data-path: in-band, unsolicited/passive, passphrase, any peer
@@ -1701,6 +1735,15 @@
encr_type=self.ENCR_TYPE_PASSPHRASE,
use_peer_id=False)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.PublishConfig.Builder#setPublishType(PublishConfig.PUBLISH_TYPE_UNSOLICITED)',
+ 'android.net.wifi.aware.SubscribeConfig.Builder#setSubscribeType(SubscribeConfig.SUBSCRIBE_TYPE_PASSIVE)',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build()',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#setPmk(byte[])',
+ ]
+ )
+
def test_ib_unsolicited_passive_pmk_specific(self):
"""Data-path: in-band, unsolicited/passive, PMK, specific peer
@@ -1712,6 +1755,15 @@
encr_type=self.ENCR_TYPE_PMK,
use_peer_id=True)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.PublishConfig.Builder#setPublishType(PublishConfig.PUBLISH_TYPE_UNSOLICITED)',
+ 'android.net.wifi.aware.SubscribeConfig.Builder#setSubscribeType(SubscribeConfig.SUBSCRIBE_TYPE_PASSIVE)',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build()',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#setPmk(byte[])',
+ ]
+ )
+
def test_ib_unsolicited_passive_pmk_any(self):
"""Data-path: in-band, unsolicited/passive, PMK, any peer
@@ -1723,6 +1775,14 @@
encr_type=self.ENCR_TYPE_PMK,
use_peer_id=False)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.PublishConfig.Builder#setPublishType(PublishConfig.PUBLISH_TYPE_SOLICITED)',
+ 'android.net.wifi.aware.SubscribeConfig.Builder#setSubscribeType(SubscribeConfig.SUBSCRIBE_TYPE_ACTIVE)',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build()',
+ ]
+ )
+
def test_ib_solicited_active_open_specific(self):
"""Data-path: in-band, solicited/active, open encryption, specific peer
@@ -1734,6 +1794,14 @@
encr_type=self.ENCR_TYPE_OPEN,
use_peer_id=True)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.PublishConfig.Builder#setPublishType(PublishConfig.PUBLISH_TYPE_SOLICITED)',
+ 'android.net.wifi.aware.SubscribeConfig.Builder#setSubscribeType(SubscribeConfig.SUBSCRIBE_TYPE_ACTIVE)',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build()',
+ ]
+ )
+
def test_ib_solicited_active_open_any(self):
"""Data-path: in-band, solicited/active, open encryption, any peer
@@ -1745,6 +1813,15 @@
encr_type=self.ENCR_TYPE_OPEN,
use_peer_id=False)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.PublishConfig.Builder#setPublishType(PublishConfig.PUBLISH_TYPE_SOLICITED)',
+ 'android.net.wifi.aware.SubscribeConfig.Builder#setSubscribeType(SubscribeConfig.SUBSCRIBE_TYPE_ACTIVE)',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build()',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#setPskPassphrase(String)',
+ ]
+ )
+
def test_ib_solicited_active_passphrase_specific(self):
"""Data-path: in-band, solicited/active, passphrase, specific peer
@@ -1756,6 +1833,15 @@
encr_type=self.ENCR_TYPE_PASSPHRASE,
use_peer_id=True)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.PublishConfig.Builder#setPublishType(PublishConfig.PUBLISH_TYPE_SOLICITED)',
+ 'android.net.wifi.aware.SubscribeConfig.Builder#setSubscribeType(SubscribeConfig.SUBSCRIBE_TYPE_ACTIVE)',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build()',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#setPskPassphrase(String)',
+ ]
+ )
+
def test_ib_solicited_active_passphrase_any(self):
"""Data-path: in-band, solicited/active, passphrase, any peer
@@ -1767,6 +1853,15 @@
encr_type=self.ENCR_TYPE_PASSPHRASE,
use_peer_id=False)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.PublishConfig.Builder#setPublishType(PublishConfig.PUBLISH_TYPE_SOLICITED)',
+ 'android.net.wifi.aware.SubscribeConfig.Builder#setSubscribeType(SubscribeConfig.SUBSCRIBE_TYPE_ACTIVE)',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build()',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#setPmk(byte[])',
+ ]
+ )
+
def test_ib_solicited_active_pmk_specific(self):
"""Data-path: in-band, solicited/active, PMK, specific peer
@@ -1778,6 +1873,15 @@
encr_type=self.ENCR_TYPE_PMK,
use_peer_id=True)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.PublishConfig.Builder#setPublishType(PublishConfig.PUBLISH_TYPE_SOLICITED)',
+ 'android.net.wifi.aware.SubscribeConfig.Builder#setSubscribeType(SubscribeConfig.SUBSCRIBE_TYPE_ACTIVE)',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build()',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#setPmk(byte[])',
+ ]
+ )
+
def test_ib_solicited_active_pmk_any(self):
"""Data-path: in-band, solicited/active, PMK, any peer
@@ -1809,9 +1913,17 @@
# peer using the Aware-provided peer handle (as opposed to a MAC address).
#######################################
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.PublishConfig.Builder#setPublishType(PublishConfig.PUBLISH_TYPE_UNSOLICITED)',
+ 'android.net.wifi.aware.SubscribeConfig.Builder#setSubscribeType(SubscribeConfig.SUBSCRIBE_TYPE_PASSIVE)',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build()',
+ ]
+ )
+
def test_ib_extra_pub_same_unsolicited_passive_open_specific(self):
"""Data-path: in-band, unsolicited/passive, open encryption.
- specific peer.
+ specific peer.
Configuration contains a publisher (for the same service)
running on *both* devices.
@@ -1826,10 +1938,17 @@
pub_on_both=True,
pub_on_both_same=True)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.PublishConfig.Builder#setPublishType(PublishConfig.PUBLISH_TYPE_UNSOLICITED)',
+ 'android.net.wifi.aware.SubscribeConfig.Builder#setSubscribeType(SubscribeConfig.SUBSCRIBE_TYPE_PASSIVE)',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build()',
+ ]
+ )
def test_ib_extra_pub_same_unsolicited_passive_open_any(self):
"""Data-path: in-band, unsolicited/passive, open encryption.
- any peer.
+ any peer.
Configuration contains a publisher (for the same service) running on
*both* devices.
@@ -1844,9 +1963,17 @@
pub_on_both=True,
pub_on_both_same=True)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.PublishConfig.Builder#setPublishType(PublishConfig.PUBLISH_TYPE_UNSOLICITED)',
+ 'android.net.wifi.aware.SubscribeConfig.Builder#setSubscribeType(SubscribeConfig.SUBSCRIBE_TYPE_PASSIVE)',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build()',
+ ]
+ )
+
def test_ib_extra_pub_diff_unsolicited_passive_open_specific(self):
"""Data-path: in-band, unsolicited/passive, open encryption.
- specific peer.
+ specific peer.
Configuration contains a publisher (for a different service) running on
*both* devices.
@@ -1861,6 +1988,14 @@
pub_on_both=True,
pub_on_both_same=False)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.PublishConfig.Builder#setPublishType(PublishConfig.PUBLISH_TYPE_UNSOLICITED)',
+ 'android.net.wifi.aware.SubscribeConfig.Builder#setSubscribeType(SubscribeConfig.SUBSCRIBE_TYPE_PASSIVE)',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build()',
+ ]
+ )
+
def test_ib_extra_pub_diff_unsolicited_passive_open_any(self):
"""Data-path: in-band, unsolicited/passive, open encryption, any peer.
@@ -1879,6 +2014,14 @@
##############################################################
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareSession#subscrible(android.net.wifi.aware.SubscribeConfig, android.net.wifi.aware.DiscoverySessionCallback, android.os.Handler)',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build()',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#setPskPassphrase(String)',
+ ]
+ )
+
def test_passphrase_min(self):
"""Data-path: minimum passphrase length
@@ -1891,11 +2034,19 @@
use_peer_id=False,
passphrase_to_use=self.PASSPHRASE_MIN)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareSession#subscrible(android.net.wifi.aware.SubscribeConfig, android.net.wifi.aware.DiscoverySessionCallback, android.os.Handler)',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build()',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#setPskPassphrase(String)',
+ ]
+ )
+
def test_passphrase_max(self):
"""Data-path: maximum passphrase length
Use in-band, unsolicited/passive, any peer combination
- """
+ """
self.run_ib_data_path_test(
ptype=_PUBLISH_TYPE_UNSOLICITED,
stype=_SUBSCRIBE_TYPE_PASSIVE,
@@ -1903,22 +2054,51 @@
use_peer_id=False,
passphrase_to_use=self.PASSPHRASE_MAX)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareManager#attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler)',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierOpen(byte[])',
+ ]
+ )
+
def test_negative_mismatch_init_mac(self):
"""Data-path: failure when Initiator MAC address mismatch"""
self.run_mismatched_oob_data_path_test(
init_mismatch_mac=True, resp_mismatch_mac=False)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareManager#attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler)',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierOpen(byte[])',
+ ]
+ )
+
def test_negative_mismatch_resp_mac(self):
"""Data-path: failure when Responder MAC address mismatch"""
self.run_mismatched_oob_data_path_test(
init_mismatch_mac=False, resp_mismatch_mac=True)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareManager#attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler)',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierPassphrase(byte[],string)',
+ ]
+ )
+
def test_negative_mismatch_passphrase(self):
"""Data-path: failure when passphrases mismatch"""
self.run_mismatched_oob_data_path_test(
init_encr_type=self.ENCR_TYPE_PASSPHRASE,
resp_encr_type=self.ENCR_TYPE_PASSPHRASE)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareManager#attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler)',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierOpen(byte[])',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierPassphrase(byte[],string)',
+ ]
+ )
+
def test_negative_mismatch_open_passphrase(self):
"""Data-path:
failure when initiator is open, and responder passphrase
@@ -1927,6 +2107,14 @@
init_encr_type=self.ENCR_TYPE_OPEN,
resp_encr_type=self.ENCR_TYPE_PASSPHRASE)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareManager#attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler)',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierOpen(byte[])',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierPassphrase(byte[],string)',
+ ]
+ )
+
def test_negative_mismatch_passphrase_open(self):
"""Data-path:
failure when initiator is passphrase, and responder open
@@ -1935,30 +2123,69 @@
init_encr_type=self.ENCR_TYPE_PASSPHRASE,
resp_encr_type=self.ENCR_TYPE_OPEN)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareManager#attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler)',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierPmk(byte[],string)',
+ ]
+ )
+
def test_negative_mismatch_pmk(self):
"""Data-path: failure when PMK mismatch"""
self.run_mismatched_oob_data_path_test(
init_encr_type=self.ENCR_TYPE_PMK,
resp_encr_type=self.ENCR_TYPE_PMK)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareManager#attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler)',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierOpen(byte[])',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierPmk(byte[],string)',
+ ]
+ )
+
def test_negative_mismatch_open_pmk(self):
"""Data-path: failure when initiator is open, and responder PMK"""
self.run_mismatched_oob_data_path_test(
init_encr_type=self.ENCR_TYPE_OPEN,
resp_encr_type=self.ENCR_TYPE_PMK)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareManager#attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler)',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierPmk(byte[],string)',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierPassphrase(byte[],string)',
+ ]
+ )
+
def test_negative_mismatch_pmk_passphrase(self):
"""Data-path: failure when initiator is pmk, and responder passphrase"""
self.run_mismatched_oob_data_path_test(
init_encr_type=self.ENCR_TYPE_PMK,
resp_encr_type=self.ENCR_TYPE_PASSPHRASE)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareManager#attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler)',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierOpen(byte[])',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierPmk(byte[],string)',
+ ]
+ )
+
def test_negative_mismatch_pmk_open(self):
"""Data-path: failure when initiator is PMK, and responder open"""
self.run_mismatched_oob_data_path_test(
init_encr_type=self.ENCR_TYPE_PMK,
resp_encr_type=self.ENCR_TYPE_OPEN)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareManager#attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler)',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierPassphrase(byte[],string)',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierPmk(byte[],string)',
+ ]
+ )
+
def test_negative_mismatch_passphrase_pmk(self):
"""Data-path: failure when initiator is passphrase, and responder pmk"""
self.run_mismatched_oob_data_path_test(
@@ -1981,6 +2208,13 @@
# and exchange of MAC addresses and then Wi-Fi Aware for data-path.
#######################################
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareManager#attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler)',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierOpen(byte[])',
+ ]
+ )
+
def test_oob_open_specific(self):
"""Data-path: out-of-band, open encryption, specific peer
@@ -1989,6 +2223,13 @@
self.run_oob_data_path_test(
encr_type=self.ENCR_TYPE_OPEN, use_peer_id=True)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareManager#attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler)',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierPassphrase(byte[],string)',
+ ]
+ )
+
def test_oob_passphrase_specific(self):
"""Data-path: out-of-band, passphrase, specific peer
@@ -1997,6 +2238,13 @@
self.run_oob_data_path_test(
encr_type=self.ENCR_TYPE_PASSPHRASE, use_peer_id=True)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareManager#attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler)',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierPmk(byte[],string)',
+ ]
+ )
+
def test_oob_pmk_specific(self):
"""Data-path: out-of-band, PMK, specific peer
@@ -2005,6 +2253,15 @@
self.run_oob_data_path_test(
encr_type=self.ENCR_TYPE_PMK, use_peer_id=True)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareManager#attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler)',
+ 'android.net.wifi.aware.PublishConfig.Builder#setPublishType(PublishConfig.PUBLISH_TYPE_UNSOLICITED)',
+ 'android.net.wifi.aware.SubscribeConfig.Builder#setSubscribeType(SubscribeConfig.SUBSCRIBE_TYPE_PASSIVE)',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierOpen(byte[])',
+ ]
+ )
+
def test_oob_ib_coex_open_specific(self):
"""Data-path: out-of-band, open encryption, specific peer - in-band coex:
set up a concurrent discovery session to verify no impact. The session
@@ -2016,6 +2273,15 @@
encr_type=self.ENCR_TYPE_OPEN,
setup_discovery_sessions=True , use_peer_id=True)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareManager#attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler)',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierPmk(byte[],string)',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierPassphrase(byte[],string)',
+ 'android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE',
+ ]
+ )
+
def test_multiple_identical_networks(self):
"""Validate that creating multiple networks between 2 devices, each network
with identical configuration is supported over a single NDP.
@@ -2150,6 +2416,15 @@
init_dut.wifi_aware_snippet.connectivityUnregisterNetwork(
init_req_callback_event.callback_id)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareManager#attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler)',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierPmk(byte[],string)',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierPassphrase(byte[],string)',
+ 'android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE',
+ ]
+ )
+
def test_identical_network_from_both_sides(self):
"""Validate that requesting two identical NDPs (Open) each being initiated
from a different side, results in the same/single NDP.
@@ -2550,6 +2825,15 @@
dut2.wifi_aware_snippet.connectivityUnregisterNetwork(
dut2_key_even.callback_id)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareManager#attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler)',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierOpen(byte[])',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierPassphrase(byte[],string)',
+ 'android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE',
+ ]
+ )
+
def test_multiple_ndi_open_passphrase(self):
"""Verify that between 2 DUTs can create 2 NDPs with different security
configuration (one open, one using passphrase). The result should use
@@ -2558,6 +2842,14 @@
# self.run_multiple_ndi(self.PASSPHRASE)
self.run_multiple_ndi([None, self.PASSPHRASE])
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareManager#attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler)',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierPassphrase(byte[],string)',
+ 'android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE',
+ ]
+ )
+
def test_multiple_ndi_passphrases(self):
"""Verify that between 2 DUTs can create 2 NDPs with different security
configuration (using different passphrases). The result should use two
@@ -2565,6 +2857,15 @@
"""
self.run_multiple_ndi([self.PASSPHRASE, self.PASSPHRASE2])
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareManager#attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler)',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierOpen(byte[])',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierPassphrase(byte[],string)',
+ 'android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE',
+ ]
+ )
+
def test_multiple_ndi_open_passphrase_flip(self):
"""Verify that between 2 DUTs can create 2 NDPs with different security
configuration (one open, one using passphrase). The result should use
@@ -2574,6 +2875,14 @@
"""
self.run_multiple_ndi([None, self.PASSPHRASE], flip_init_resp=True)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareManager#attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler)',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierPassphrase(byte[],string)',
+ 'android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE',
+ ]
+ )
+
def test_multiple_ndi_passphrases_flip(self):
"""Verify that between 2 DUTs can create 2 NDPs with different security
configuration (using different passphrases). The result should use two
@@ -2584,6 +2893,15 @@
self.run_multiple_ndi(
[self.PASSPHRASE, self.PASSPHRASE2], flip_init_resp=True)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareManager#attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler)',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierOpen(byte[])',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierPmk(byte[],string)',
+ 'android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE',
+ ]
+ )
+
def test_multiple_ndi_open_pmk(self):
"""Verify that between 2 DUTs can create 2 NDPs with different security
configuration (one open, one using pmk). The result should use two
@@ -2591,6 +2909,15 @@
"""
self.run_multiple_ndi([None, self.PMK])
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareManager#attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler)',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierPassphrase(byte[],string)',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierPmk(byte[],string)',
+ 'android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE',
+ ]
+ )
+
def test_multiple_ndi_passphrase_pmk(self):
"""Verify that between 2 DUTs can create 2 NDPs with different security
configuration (one using passphrase, one using pmk). The result should
@@ -2598,6 +2925,14 @@
"""
self.run_multiple_ndi([self.PASSPHRASE, self.PMK])
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareManager#attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler)',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierPmk(byte[],string)',
+ 'android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE',
+ ]
+ )
+
def test_multiple_ndi_pmks(self):
"""Verify that between 2 DUTs can create 2 NDPs with different security
configuration (using different PMKS). The result should use two
@@ -2605,6 +2940,15 @@
"""
self.run_multiple_ndi([self.PMK, self.PMK2])
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareManager#attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler)',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierOpen(byte[])',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierPmk(byte[],string)',
+ 'android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE',
+ ]
+ )
+
def test_multiple_ndi_open_pmk_flip(self):
"""Verify that between 2 DUTs can create 2 NDPs with different security
configuration (one open, one using pmk). The result should use two
@@ -2614,6 +2958,15 @@
"""
self.run_multiple_ndi([None, self.PMK], flip_init_resp=True)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareManager#attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler)',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierPassphrase(byte[],string)',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierPmk(byte[],string)',
+ 'android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE',
+ ]
+ )
+
def test_multiple_ndi_passphrase_pmk_flip(self):
"""Verify that between 2 DUTs can create 2 NDPs with different security
configuration (one using passphrase, one using pmk). The result should
@@ -2623,6 +2976,14 @@
"""
self.run_multiple_ndi([self.PASSPHRASE, self.PMK], flip_init_resp=True)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareManager#attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler)',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierPmk(byte[],string)',
+ 'android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE',
+ ]
+ )
+
def test_multiple_ndi_pmks_flip(self):
"""Verify that between 2 DUTs can create 2 NDPs with different security
configuration (using different PMKS). The result should use two
@@ -2649,6 +3010,16 @@
#
#######################################
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareManager#attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler)',
+ 'android.net.wifi.aware.PublishConfig.Builder#setPublishType(PublishConfig.PUBLISH_TYPE_UNSOLICITED)',
+ 'android.net.wifi.aware.SubscribeConfig.Builder#setSubscribeType(SubscribeConfig.SUBSCRIBE_TYPE_PASSIVE)',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build()',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierOpen(byte[])',
+ ]
+ )
+
def test_identical_ndps_mix_ib_oob_ib_first_same_polarity(self):
"""Validate that a single NDP is created for multiple identical
requests which are issued through either in-band (ib) or out-of-band
@@ -2660,6 +3031,16 @@
self.run_mix_ib_oob(
same_request=True, ib_first=True, inits_on_same_dut=True)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareManager#attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler)',
+ 'android.net.wifi.aware.PublishConfig.Builder#setPublishType(PublishConfig.PUBLISH_TYPE_UNSOLICITED)',
+ 'android.net.wifi.aware.SubscribeConfig.Builder#setSubscribeType(SubscribeConfig.SUBSCRIBE_TYPE_PASSIVE)',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build()',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierOpen(byte[])',
+ ]
+ )
+
def test_identical_ndps_mix_ib_oob_oob_first_same_polarity(self):
"""Validate that a single NDP is created for multiple identical
requests which are issued through either in-band (ib) or out-of-band
@@ -2672,6 +3053,16 @@
self.run_mix_ib_oob(
same_request=True, ib_first=False, inits_on_same_dut=True)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareManager#attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler)',
+ 'android.net.wifi.aware.PublishConfig.Builder#setPublishType(PublishConfig.PUBLISH_TYPE_UNSOLICITED)',
+ 'android.net.wifi.aware.SubscribeConfig.Builder#setSubscribeType(SubscribeConfig.SUBSCRIBE_TYPE_PASSIVE)',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build()',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierOpen(byte[])',
+ ]
+ )
+
def test_identical_ndps_mix_ib_oob_ib_first_diff_polarity(self):
"""Validate that a single NDP is created for multiple identical
requests which are issued through either in-band (ib) or out-of-band
@@ -2683,6 +3074,16 @@
self.run_mix_ib_oob(
same_request=True, ib_first=True, inits_on_same_dut=False)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareManager#attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler)',
+ 'android.net.wifi.aware.PublishConfig.Builder#setPublishType(PublishConfig.PUBLISH_TYPE_UNSOLICITED)',
+ 'android.net.wifi.aware.SubscribeConfig.Builder#setSubscribeType(SubscribeConfig.SUBSCRIBE_TYPE_PASSIVE)',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build()',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierOpen(byte[])',
+ ]
+ )
+
def test_identical_ndps_mix_ib_oob_oob_first_diff_polarity(self):
"""Validate that a single NDP is created for multiple identical
requests which are issued through either in-band (ib) or out-of-band
@@ -2694,6 +3095,16 @@
self.run_mix_ib_oob(
same_request=True, ib_first=False, inits_on_same_dut=False)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareManager#attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler)',
+ 'android.net.wifi.aware.PublishConfig.Builder#setPublishType(PublishConfig.PUBLISH_TYPE_UNSOLICITED)',
+ 'android.net.wifi.aware.SubscribeConfig.Builder#setSubscribeType(SubscribeConfig.SUBSCRIBE_TYPE_PASSIVE)',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build()',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierPassphrase(byte[],string)',
+ ]
+ )
+
def test_multiple_ndis_mix_ib_oob_ib_first_same_polarity(self):
"""Validate that multiple NDIs are created for NDPs which are requested
@@ -2706,6 +3117,16 @@
self.run_mix_ib_oob(
same_request=False, ib_first=True, inits_on_same_dut=True)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareManager#attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler)',
+ 'android.net.wifi.aware.PublishConfig.Builder#setPublishType(PublishConfig.PUBLISH_TYPE_UNSOLICITED)',
+ 'android.net.wifi.aware.SubscribeConfig.Builder#setSubscribeType(SubscribeConfig.SUBSCRIBE_TYPE_PASSIVE)',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build()',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierPassphrase(byte[],string)',
+ ]
+ )
+
def test_multiple_ndis_mix_ib_oob_oob_first_same_polarity(self):
"""Validate that multiple NDIs are created for NDPs which are requested
with different security configurations. Use a mix of in-band and
@@ -2717,6 +3138,16 @@
self.run_mix_ib_oob(
same_request=False, ib_first=False, inits_on_same_dut=True)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareManager#attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler)',
+ 'android.net.wifi.aware.PublishConfig.Builder#setPublishType(PublishConfig.PUBLISH_TYPE_UNSOLICITED)',
+ 'android.net.wifi.aware.SubscribeConfig.Builder#setSubscribeType(SubscribeConfig.SUBSCRIBE_TYPE_PASSIVE)',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build()',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierPassphrase(byte[],string)',
+ ]
+ )
+
def test_multiple_ndis_mix_ib_oob_ib_first_diff_polarity(self):
"""Validate that multiple NDIs are created for NDPs which are requested
with different security configurations. Use a mix of in-band and
@@ -2728,6 +3159,15 @@
self.run_mix_ib_oob(
same_request=False, ib_first=True, inits_on_same_dut=False)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareManager#attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler)',
+ 'android.net.wifi.aware.PublishConfig.Builder#setPublishType(PublishConfig.PUBLISH_TYPE_UNSOLICITED)',
+ 'android.net.wifi.aware.SubscribeConfig.Builder#setSubscribeType(SubscribeConfig.SUBSCRIBE_TYPE_PASSIVE)',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build()',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierPassphrase(byte[],string)',
+ ]
+ )
def test_multiple_ndis_mix_ib_oob_oob_first_diff_polarity(self):
"""Validate that multiple NDIs are created for NDPs which are requested
@@ -2749,6 +3189,16 @@
#
#######################################
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareManager#attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler)',
+ 'android.net.wifi.aware.WifiAwareSession#publish(android.net.wifi.aware.PublishConfig, android.net.wifi.aware.DiscoverySessionCallback, android.os.Handler)',
+ 'android.net.wifi.aware.WifiAwareSession#subscrible(android.net.wifi.aware.SubscribeConfig, android.net.wifi.aware.DiscoverySessionCallback, android.os.Handler)',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierOpen(byte[])',
+ ]
+ )
+
def test_multiple_regulator_domains_ib_us_jp(self):
"""Verify data-path setup across multiple regulator domains.
diff --git a/tests/hostsidetests/multidevices/test/aware/integration/wifi_aware_mac_random_test.py b/tests/hostsidetests/multidevices/test/aware/integration/wifi_aware_mac_random_test.py
index 9999ee5..89aec46 100644
--- a/tests/hostsidetests/multidevices/test/aware/integration/wifi_aware_mac_random_test.py
+++ b/tests/hostsidetests/multidevices/test/aware/integration/wifi_aware_mac_random_test.py
@@ -18,6 +18,7 @@
import sys
import time
+from android.platform.test.annotations import ApiTest
from aware import aware_lib_utils as autils
from aware import constants
from mobly import asserts
@@ -162,6 +163,12 @@
'cmd wifiaware native_api set mac_random_interval_sec %d' % interval_sec
)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.WifiManager#getConnectionInfo()',
+ 'android.net.wifi.WifiInfo#getMacAddress()',
+ ]
+ )
def test_nmi_ndi_randomization_on_enable(self):
"""Validate randomization of the NMI.
@@ -219,6 +226,11 @@
% (infra_mac, mac_addresses),
)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.IdentityChangedListener#onIdentityChanged(byte[] mac)',
+ ]
+ )
def test_nmi_randomization_on_interval(self):
"""Validate randomization of the NMI on different intervals.
diff --git a/tests/hostsidetests/multidevices/test/aware/integration/wifi_aware_protocols_multi_country_test.py b/tests/hostsidetests/multidevices/test/aware/integration/wifi_aware_protocols_multi_country_test.py
index d45671a..6c8467f 100644
--- a/tests/hostsidetests/multidevices/test/aware/integration/wifi_aware_protocols_multi_country_test.py
+++ b/tests/hostsidetests/multidevices/test/aware/integration/wifi_aware_protocols_multi_country_test.py
@@ -18,6 +18,7 @@
import sys
import time
+from android.platform.test.annotations import ApiTest
from aware import aware_lib_utils as autils
from aware import constants
from mobly import asserts
@@ -235,6 +236,14 @@
s_ipv6,
)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.PublishConfig.Builder#setPublishType(PublishConfig.PUBLISH_TYPE_UNSOLICITED)',
+ 'android.net.wifi.aware.SubscribeConfig.Builder#setSubscribeType(SubscribeConfig.SUBSCRIBE_TYPE_PASSIVE)',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build()',
+ 'android.net.ConnectivityManager#requestNetwork(android.net.NetworkRequest request, android.net.ConnectivityManager.NetworkCallback networkCallback, int timeoutMs)',
+ ]
+ )
def test_ping6_ib_unsolicited_passive_multicountry(self):
"""Validate ping6 works with UNSOLICITED/PASSIVE sessions.
@@ -244,6 +253,14 @@
self.ib_ping6_test(pub_type=constants.PublishType.UNSOLICITED,
sub_type=constants.SubscribeType.PASSIVE)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.PublishConfig.Builder#setPublishType(PublishConfig.PUBLISH_TYPE_SOLICITED)',
+ 'android.net.wifi.aware.SubscribeConfig.Builder#setSubscribeType(SubscribeConfig.SUBSCRIBE_TYPE_ACTIVE)',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build()',
+ 'android.net.ConnectivityManager#requestNetwork(android.net.NetworkRequest request, android.net.ConnectivityManager.NetworkCallback networkCallback, int timeoutMs)',
+ ]
+ )
def test_ping6_ib_solicited_active_multicountry(self):
""""Validate ping6 works with SOLICITED/ACTIVE session.
diff --git a/tests/hostsidetests/multidevices/test/aware/integration/wifi_rtt_disable_test.py b/tests/hostsidetests/multidevices/test/aware/integration/wifi_rtt_disable_test.py
new file mode 100644
index 0000000..d87de30
--- /dev/null
+++ b/tests/hostsidetests/multidevices/test/aware/integration/wifi_rtt_disable_test.py
@@ -0,0 +1,375 @@
+# Copyright (C) 2024 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Lint as: python3
+"""Wi-Fi Aware Rtt Disable test reimplemented in Mobly."""
+import functools
+import logging
+import signal
+import sys
+import time
+
+from aware import aware_lib_utils as autils
+from aware import constants
+from mobly import asserts
+from mobly import base_test
+from mobly import records
+from mobly import test_runner
+from mobly import utils
+from mobly.controllers import android_device
+from mobly.snippet import errors
+
+RUNTIME_PERMISSIONS = (
+ 'android.permission.ACCESS_FINE_LOCATION',
+ 'android.permission.ACCESS_COARSE_LOCATION',
+ 'android.permission.NEARBY_WIFI_DEVICES',
+)
+PACKAGE_NAME = constants.WIFI_AWARE_SNIPPET_PACKAGE_NAME
+
+# Alias variable.
+_DEFAULT_TIMEOUT = constants.WAIT_WIFI_STATE_TIME_OUT.total_seconds()
+_CALLBACK_NAME = constants.DiscoverySessionCallbackParamsType.CALLBACK_NAME
+
+######################################################
+# status codes
+######################################################
+_RANGING_FAIL_CODE_GENERIC = 1
+_RANGING_FAIL_CODE_RTT_NOT_AVAILABLE = 2
+
+
+# Timeout decorator block
+class TimeoutError(Exception):
+ """Exception for timeout decorator related errors."""
+
+
+def _timeout_handler():
+ """Handler function used by signal to terminate a timed out function."""
+ raise TimeoutError()
+
+
+def timeout(sec):
+ """A decorator used to add time out check to a function.
+
+ This only works in main thread due to its dependency on signal module.
+ Do NOT use it if the decorated function does not run in the Main thread.
+
+ Args:
+ sec: Number of seconds to wait before the function times out. No timeout
+ if set to 0
+
+ Returns:
+ What the decorated function returns.
+
+ Raises:
+ TimeoutError is raised when time out happens.
+ """
+
+ def decorator(func):
+
+ @functools.wraps(func)
+ def wrapper(*args, **kwargs):
+ if sec:
+ signal.signal(signal.SIGALRM, _timeout_handler)
+ signal.alarm(sec)
+ try:
+ return func(*args, **kwargs)
+ except TimeoutError as exc:
+ raise TimeoutError(
+ ('Function {} timed out after {} seconds.').format(
+ func.__name__, sec
+ )
+ ) from exc
+ finally:
+ signal.alarm(0)
+
+ return wrapper
+
+ return decorator
+
+
+class RttDisableTest(base_test.BaseTestClass):
+ """Test class for RTT ranging enable/disable flows."""
+
+ MODE_DISABLE_WIFI = 0
+ MODE_DISABLE_LOCATIONING = 1
+
+ ads: list[android_device.AndroidDevice]
+
+ def setup_class(self):
+ self.ads = self.register_controller(android_device, min_number=1)
+
+ def setup_device(device: android_device.AndroidDevice):
+ autils.control_wifi(device, True)
+ device.load_snippet('wifi_aware_snippet', PACKAGE_NAME)
+ for permission in RUNTIME_PERMISSIONS:
+ device.adb.shell(['pm', 'grant', PACKAGE_NAME, permission])
+ asserts.abort_all_if(
+ not device.wifi_aware_snippet.wifiAwareIsAvailable(),
+ f'{device} Wi-Fi Aware is not available.',
+ )
+
+ # Set up devices in parallel.
+ utils.concurrent_exec(
+ setup_device,
+ param_list=[[ad] for ad in self.ads],
+ max_workers=1,
+ raise_on_exception=True,
+ )
+
+ def setup_test(self):
+ for ad in self.ads:
+ autils.control_wifi(ad, True)
+ self.set_location_service(ad, True)
+ aware_avail = ad.wifi_aware_snippet.wifiAwareIsAvailable()
+ if not aware_avail:
+ ad.log.info('Aware not available. Waiting ...')
+ state_handler = ad.wifi_aware_snippet.wifiAwareMonitorStateChange()
+ state_handler.waitAndGet(
+ constants.WifiAwareBroadcast.WIFI_AWARE_AVAILABLE
+ )
+
+ def teardown_test(self):
+ utils.concurrent_exec(
+ self._teardown_test_on_device,
+ param_list=[[ad] for ad in self.ads],
+ max_workers=1,
+ raise_on_exception=True,
+ )
+ utils.concurrent_exec(
+ lambda d: d.services.create_output_excerpts_all(self.current_test_info),
+ param_list=[[ad] for ad in self.ads],
+ raise_on_exception=True,
+ )
+
+ def _teardown_test_on_device(self, ad: android_device.AndroidDevice) -> None:
+ ad.wifi_aware_snippet.wifiAwareCloseAllWifiAwareSession()
+ ad.wifi_aware_snippet.wifiAwareMonitorStopStateChange()
+ # autils.control_wifi(ad, True)
+
+ def on_fail(self, record: records.TestResult) -> None:
+ android_device.take_bug_reports(
+ self.ads, destination=self.current_test_info.output_path
+ )
+
+ def scan_networks(
+ self, dut: android_device.AndroidDevice, max_tries: int = 3
+ ) -> list[dict[str, str]]:
+ """Perform a scan and return scan results.
+
+ Args:
+ dut: Device under test.
+ max_tries: Retry scan to ensure network is found
+
+ Returns:
+ an array of scan results.
+ """
+ scan_results = []
+ for _ in range(max_tries):
+ scan_results = dut.wifi_aware_snippet.wifiScanAndGetResults()
+ if scan_results:
+ break
+
+ return scan_results
+
+ def select_best_scan_results(
+ self,
+ scans: list[dict[str, str]],
+ select_count: int,
+ lowest_rssi: int = -80,
+ ):
+ """Select best result based on RSSI.
+
+ Select the strongest 'select_count' scans in the input list based on
+ highest RSSI. Exclude all very weak signals, even if results in a shorter
+ list.
+
+ Args:
+ scans: List of scan results.
+ select_count: An integer specifying how many scans to return at most.
+ lowest_rssi: The lowest RSSI to accept into the output.
+
+ Returns:
+ a list of the strongest 'select_count' scan results from the scans
+ list.
+ """
+
+ def _take_rssi(element):
+ return element['level']
+
+ result = []
+ scans.sort(key=_take_rssi, reverse=True)
+ for scan in scans:
+ logging.info(
+ 'scan type: %s, %s, %s', scan['SSID'], scan['level'], scan['BSSID']
+ )
+ if len(result) == select_count:
+ break
+ if scan['level'] < lowest_rssi:
+ break # rest are lower since we're sorted
+ result.append(scan)
+
+ return result
+
+ def set_location_service(self, ad, new_state):
+ """Set Location service on/off in Settings->Location.
+
+ Args:
+ ad: android device object.
+ new_state: new state for "Location service".
+ If new_state is False, turn off location service.
+ If new_state if True, set location service to "High accuracy".
+ """
+ ad.adb.shell('content insert --uri '
+ ' content://com.google.settings/partner --bind '
+ 'name:s:network_location_opt_in --bind value:s:1')
+ ad.adb.shell('content insert --uri '
+ ' content://com.google.settings/partner --bind '
+ 'name:s:use_location_for_services --bind value:s:1')
+ if new_state:
+ ad.adb.shell('settings put secure location_mode 3')
+ else:
+ ad.adb.shell('settings put secure location_mode 0')
+
+ def force_airplane_mode(self, ad, new_state, timeout_value=60):
+ """Force the device to set airplane mode on or off by adb shell command.
+
+ Args:
+ ad: android device object.
+ new_state: Turn on airplane mode if True.
+ Turn off airplane mode if False.
+ timeout_value: max wait time for 'adb wait-for-device'
+
+ Returns:
+ True if success.
+ False if timeout.
+ """
+
+ # Using timeout decorator.
+ # Wait for device with timeout. If after <timeout_value> seconds, adb
+ # is still waiting for device, throw TimeoutError exception.
+ @timeout(timeout_value)
+ def wait_for_device_with_timeout(ad):
+ ad.adb.wait_for_device()
+
+ try:
+ wait_for_device_with_timeout(ad)
+ ad.adb.shell('settings put global airplane_mode_on {}'.format(
+ 1 if new_state else 0))
+ ad.adb.shell('am broadcast -a android.intent.action.AIRPLANE_MODE')
+ except TimeoutError:
+ # adb wait for device timeout
+ return False
+ return True
+
+ def run_disable_rtt(self, disable_mode):
+ """Validate the RTT ranging feature if RTT disabled.
+
+ Validate the RTT disabled flows: whether by disabling Wi-Fi or entering
+ doze mode.
+
+ Args:
+ disable_mode: The particular mechanism in which RTT is disabled. One of
+ the MODE_* constants.
+ """
+ dut = self.ads[0]
+
+ # validate start-up conditions
+ asserts.assert_true(
+ dut.wifi_aware_snippet.wifiRttIsAvailable(), 'RTT is not available'
+ )
+
+ # scan to get some APs to be used later
+ all_aps = self.select_best_scan_results(
+ self.scan_networks(dut), select_count=1
+ )
+ asserts.assert_true(all_aps, 'Need at least one visible AP!')
+
+ # disable RTT and validate broadcast & API
+ if disable_mode == self.MODE_DISABLE_WIFI:
+ # disabling Wi-Fi is not sufficient: since scan mode (and hence RTT) will
+ # remain enabled - we need to disable the Wi-Fi chip aka Airplane Mode
+ asserts.assert_true(
+ self.force_airplane_mode(dut, True),
+ 'Can not turn on airplane mode on: %s' % dut.serial,
+ )
+ autils.control_wifi(dut, False)
+ elif disable_mode == self.MODE_DISABLE_LOCATIONING:
+ self.set_location_service(dut, False)
+ time.sleep(10)
+ dut.log.info(
+ 'WiFi RTT status: %s', dut.wifi_aware_snippet.wifiRttIsAvailable()
+ )
+ asserts.assert_false(
+ dut.wifi_aware_snippet.wifiRttIsAvailable(), 'RTT is available'
+ )
+
+ # request a range and validate error
+ dut.log.info('access points input: %s', all_aps[0:1])
+ ranging_cb_handler = (
+ dut.wifi_aware_snippet.wifiRttStartRangingToAccessPoints(all_aps[0:1])
+ )
+ event = ranging_cb_handler.waitAndGet(
+ event_name=constants.RangingResultCb.EVENT_NAME_ON_RANGING_RESULT,
+ timeout=_DEFAULT_TIMEOUT,
+ )
+
+ callback_name = event.data.get(
+ constants.RangingResultCb.DATA_KEY_CALLBACK_NAME, None
+ )
+ dut.log.info('StartRangingToAccessPoints callback = %s', callback_name)
+ asserts.assert_equal(
+ callback_name,
+ constants.RangingResultCb.CB_METHOD_ON_RANGING_FAILURE,
+ 'Should be ranging failed.',
+ )
+ status_code = event.data.get(
+ constants.RangingResultCb.DATA_KEY_RESULT_STATUS, None
+ )
+ dut.log.info('StartRangingToAccessPoints status code = %s', status_code)
+ asserts.assert_equal(
+ status_code, _RANGING_FAIL_CODE_RTT_NOT_AVAILABLE, 'Invalid error code'
+ )
+
+ # enable RTT and validate broadcast & API
+ if disable_mode == self.MODE_DISABLE_WIFI:
+ asserts.assert_true(
+ self.force_airplane_mode(dut, False),
+ 'Can not turn off airplane mode on: %s' % dut.serial,
+ )
+ autils.control_wifi(dut, True)
+ elif disable_mode == self.MODE_DISABLE_LOCATIONING:
+ self.set_location_service(dut, True)
+
+ asserts.assert_true(
+ dut.wifi_aware_snippet.wifiRttIsAvailable(), 'RTT is not available'
+ )
+
+ def test_disable_wifi(self):
+ """Validate that getting expected broadcast when Wi-Fi is disabled and that any range requests are rejected.
+ """
+ self.run_disable_rtt(self.MODE_DISABLE_WIFI)
+
+ def test_disable_location(self):
+ """Validate that getting expected broadcast when locationing is disabled and that any range requests are rejected.
+ """
+ self.run_disable_rtt(self.MODE_DISABLE_LOCATIONING)
+
+
+if __name__ == '__main__':
+ # Take test args
+ if '--' in sys.argv:
+ index = sys.argv.index('--')
+ sys.argv = sys.argv[:1] + sys.argv[index + 1 :]
+
+ test_runner.main()
diff --git a/tests/hostsidetests/multidevices/test/direct/integration/Android.bp b/tests/hostsidetests/multidevices/test/direct/integration/Android.bp
index ed1d057..6ee454d 100644
--- a/tests/hostsidetests/multidevices/test/direct/integration/Android.bp
+++ b/tests/hostsidetests/multidevices/test/direct/integration/Android.bp
@@ -42,11 +42,6 @@
tags: ["mobly"],
},
test_suites: ["general-tests"],
- version: {
- py3: {
- embedded_launcher: true,
- },
- },
}
python_test_host {