/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.net.wifi;

import static android.Manifest.permission.ACCESS_FINE_LOCATION;
import static android.Manifest.permission.ACCESS_WIFI_STATE;
import static android.Manifest.permission.READ_WIFI_CREDENTIAL;

import android.annotation.CallbackExecutor;
import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.app.ActivityManager;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.ConnectivityManager.NetworkCallback;
import android.net.DhcpInfo;
import android.net.LinkProperties;
import android.net.MacAddress;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkStack;
import android.net.Uri;
import android.net.wifi.hotspot2.IProvisioningCallback;
import android.net.wifi.hotspot2.OsuProvider;
import android.net.wifi.hotspot2.PasspointConfiguration;
import android.net.wifi.hotspot2.ProvisioningCallback;
import android.os.Binder;
import android.os.Build;
import android.os.Handler;
import android.os.HandlerExecutor;
import android.os.IBinder;
import android.os.Looper;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.RemoteException;
import android.os.WorkSource;
import android.os.connectivity.WifiActivityEnergyInfo;
import android.telephony.SubscriptionInfo;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.CloseGuard;
import android.util.Log;
import android.util.Pair;
import android.util.SparseArray;

import androidx.annotation.RequiresApi;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.modules.utils.ParceledListSlice;
import com.android.modules.utils.build.SdkLevel;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.concurrent.Executor;

/**
 * This class provides the primary API for managing all aspects of Wi-Fi
 * connectivity.
 * <p>
 * On releases before {@link android.os.Build.VERSION_CODES#N}, this object
 * should only be obtained from an {@linkplain Context#getApplicationContext()
 * application context}, and not from any other derived context to avoid memory
 * leaks within the calling process.
 * <p>
 * It deals with several categories of items:
 * </p>
 * <ul>
 * <li>The list of configured networks. The list can be viewed and updated, and
 * attributes of individual entries can be modified.</li>
 * <li>The currently active Wi-Fi network, if any. Connectivity can be
 * established or torn down, and dynamic information about the state of the
 * network can be queried.</li>
 * <li>Results of access point scans, containing enough information to make
 * decisions about what access point to connect to.</li>
 * <li>It defines the names of various Intent actions that are broadcast upon
 * any sort of change in Wi-Fi state.
 * </ul>
 * <p>
 * This is the API to use when performing Wi-Fi specific operations. To perform
 * operations that pertain to network connectivity at an abstract level, use
 * {@link android.net.ConnectivityManager}.
 * </p>
 */
@SystemService(Context.WIFI_SERVICE)
public class WifiManager {

    private static final String TAG = "WifiManager";
    // Supplicant error codes:
    /**
     * The error code if there was a problem authenticating.
     * @deprecated This is no longer supported.
     */
    @Deprecated
    public static final int ERROR_AUTHENTICATING = 1;

    /**
     * The reason code if there is no error during authentication.
     * It could also imply that there no authentication in progress,
     * this reason code also serves as a reset value.
     * @deprecated This is no longer supported.
     * @hide
     */
    @Deprecated
    public static final int ERROR_AUTH_FAILURE_NONE = 0;

    /**
     * The reason code if there was a timeout authenticating.
     * @deprecated This is no longer supported.
     * @hide
     */
    @Deprecated
    public static final int ERROR_AUTH_FAILURE_TIMEOUT = 1;

    /**
     * The reason code if there was a wrong password while
     * authenticating.
     * @deprecated This is no longer supported.
     * @hide
     */
    @Deprecated
    public static final int ERROR_AUTH_FAILURE_WRONG_PSWD = 2;

    /**
     * The reason code if there was EAP failure while
     * authenticating.
     * @deprecated This is no longer supported.
     * @hide
     */
    @Deprecated
    public static final int ERROR_AUTH_FAILURE_EAP_FAILURE = 3;

    /** @hide */
    public static final int NETWORK_SUGGESTIONS_MAX_PER_APP_LOW_RAM = 256;

    /** @hide */
    public static final int NETWORK_SUGGESTIONS_MAX_PER_APP_HIGH_RAM = 1024;

    /**
     * Reason code if all of the network suggestions were successfully added or removed.
     */
    public static final int STATUS_NETWORK_SUGGESTIONS_SUCCESS = 0;

    /**
     * Reason code if there was an internal error in the platform while processing the addition or
     * removal of suggestions.
     */
    public static final int STATUS_NETWORK_SUGGESTIONS_ERROR_INTERNAL = 1;

    /**
     * Reason code if the user has disallowed "android:change_wifi_state" app-ops from the app.
     * @see android.app.AppOpsManager#unsafeCheckOp(String, int, String).
     */
    public static final int STATUS_NETWORK_SUGGESTIONS_ERROR_APP_DISALLOWED = 2;

    /**
     * Reason code if one or more of the network suggestions added already exists in platform's
     * database.
     * Note: this code will not be returned with Android 11 as in-place modification is allowed,
     * please check {@link #addNetworkSuggestions(List)}.
     * @see WifiNetworkSuggestion#equals(Object)
     */
    public static final int STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_DUPLICATE = 3;

    /**
     * Reason code if the number of network suggestions provided by the app crosses the max
     * threshold set per app.
     * The framework will reject all suggestions provided by {@link #addNetworkSuggestions(List)} if
     * the total size exceeds the limit.
     * @see #getMaxNumberOfNetworkSuggestionsPerApp()
     */
    public static final int STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_EXCEEDS_MAX_PER_APP = 4;

    /**
     * Reason code if one or more of the network suggestions removed does not exist in platform's
     * database.
     * The framework won't remove any suggestions if one or more of suggestions provided
     * by {@link #removeNetworkSuggestions(List)} does not exist in database.
     * @see WifiNetworkSuggestion#equals(Object)
     */
    public static final int STATUS_NETWORK_SUGGESTIONS_ERROR_REMOVE_INVALID = 5;

    /**
     * Reason code if one or more of the network suggestions added is not allowed.
     * The framework will reject all suggestions provided by {@link #addNetworkSuggestions(List)}
     * if one or more of them is not allowed.
     * This error may be caused by suggestion is using SIM-based encryption method, but calling app
     * is not carrier privileged.
     */
    public static final int STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_NOT_ALLOWED = 6;

    /**
     * Reason code if one or more of the network suggestions added is invalid. Framework will reject
     * all the suggestions in the list.
     * The framework will reject all suggestions provided by {@link #addNetworkSuggestions(List)}
     * if one or more of them is invalid.
     * Please use {@link WifiNetworkSuggestion.Builder} to create network suggestions.
     */
    public static final int STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_INVALID = 7;

    /** @hide */
    @IntDef(prefix = { "STATUS_NETWORK_SUGGESTIONS_" }, value = {
            STATUS_NETWORK_SUGGESTIONS_SUCCESS,
            STATUS_NETWORK_SUGGESTIONS_ERROR_INTERNAL,
            STATUS_NETWORK_SUGGESTIONS_ERROR_APP_DISALLOWED,
            STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_DUPLICATE,
            STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_EXCEEDS_MAX_PER_APP,
            STATUS_NETWORK_SUGGESTIONS_ERROR_REMOVE_INVALID,
            STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_NOT_ALLOWED,
            STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_INVALID,
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface NetworkSuggestionsStatusCode {}

    /**
     * Reason code if suggested network connection attempt failed with an unknown failure.
     */
    public static final int STATUS_SUGGESTION_CONNECTION_FAILURE_UNKNOWN = 0;
    /**
     * Reason code if suggested network connection attempt failed with association failure.
     */
    public static final int STATUS_SUGGESTION_CONNECTION_FAILURE_ASSOCIATION = 1;
    /**
     * Reason code if suggested network connection attempt failed with an authentication failure.
     */
    public static final int STATUS_SUGGESTION_CONNECTION_FAILURE_AUTHENTICATION = 2;
    /**
     * Reason code if suggested network connection attempt failed with an IP provision failure.
     */
    public static final int STATUS_SUGGESTION_CONNECTION_FAILURE_IP_PROVISIONING = 3;

    /** @hide */
    @IntDef(prefix = {"STATUS_SUGGESTION_CONNECTION_FAILURE_"},
            value = {STATUS_SUGGESTION_CONNECTION_FAILURE_UNKNOWN,
                    STATUS_SUGGESTION_CONNECTION_FAILURE_ASSOCIATION,
                    STATUS_SUGGESTION_CONNECTION_FAILURE_AUTHENTICATION,
                    STATUS_SUGGESTION_CONNECTION_FAILURE_IP_PROVISIONING
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface SuggestionConnectionStatusCode {}

    /**
     * Status code if suggestion approval status is unknown, an App which hasn't made any
     * suggestions will get this code.
     */
    public static final int STATUS_SUGGESTION_APPROVAL_UNKNOWN = 0;

    /**
     * Status code if the calling app is still pending user approval for suggestions.
     */
    public static final int STATUS_SUGGESTION_APPROVAL_PENDING = 1;

    /**
     * Status code if the calling app got the user approval for suggestions.
     */
    public static final int STATUS_SUGGESTION_APPROVAL_APPROVED_BY_USER = 2;

    /**
     * Status code if the calling app suggestions were rejected by the user.
     */
    public static final int STATUS_SUGGESTION_APPROVAL_REJECTED_BY_USER = 3;

    /**
     * Status code if the calling app was approved by virtue of being a carrier privileged app.
     * @see TelephonyManager#hasCarrierPrivileges().
     */
    public static final int STATUS_SUGGESTION_APPROVAL_APPROVED_BY_CARRIER_PRIVILEGE = 4;

    /** @hide */
    @IntDef(prefix = {"STATUS_SUGGESTION_APPROVAL_"},
            value = {STATUS_SUGGESTION_APPROVAL_UNKNOWN,
                    STATUS_SUGGESTION_APPROVAL_PENDING,
                    STATUS_SUGGESTION_APPROVAL_APPROVED_BY_USER,
                    STATUS_SUGGESTION_APPROVAL_REJECTED_BY_USER,
                    STATUS_SUGGESTION_APPROVAL_APPROVED_BY_CARRIER_PRIVILEGE
            })
    @Retention(RetentionPolicy.SOURCE)
    public @interface SuggestionUserApprovalStatus {}

    /**
     * Broadcast intent action indicating whether Wi-Fi scanning is currently available.
     * Available extras:
     * - {@link #EXTRA_SCAN_AVAILABLE}
     */
    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    public static final String ACTION_WIFI_SCAN_AVAILABILITY_CHANGED =
            "android.net.wifi.action.WIFI_SCAN_AVAILABILITY_CHANGED";

    /**
     * A boolean extra indicating whether scanning is currently available.
     * Sent in the broadcast {@link #ACTION_WIFI_SCAN_AVAILABILITY_CHANGED}.
     * Its value is true if scanning is currently available, false otherwise.
     */
    public static final String EXTRA_SCAN_AVAILABLE = "android.net.wifi.extra.SCAN_AVAILABLE";

    /**
     * Broadcast intent action indicating that the credential of a Wi-Fi network
     * has been changed. One extra provides the ssid of the network. Another
     * extra provides the event type, whether the credential is saved or forgot.
     * @hide
     */
    @SystemApi
    public static final String WIFI_CREDENTIAL_CHANGED_ACTION =
            "android.net.wifi.WIFI_CREDENTIAL_CHANGED";
    /** @hide */
    @SystemApi
    public static final String EXTRA_WIFI_CREDENTIAL_EVENT_TYPE = "et";
    /** @hide */
    @SystemApi
    public static final String EXTRA_WIFI_CREDENTIAL_SSID = "ssid";
    /** @hide */
    @SystemApi
    public static final int WIFI_CREDENTIAL_SAVED = 0;
    /** @hide */
    @SystemApi
    public static final int WIFI_CREDENTIAL_FORGOT = 1;

    /** @hide */
    @SystemApi
    public static final int PASSPOINT_HOME_NETWORK = 0;

    /** @hide */
    @SystemApi
    public static final int PASSPOINT_ROAMING_NETWORK = 1;

    /**
     * Broadcast intent action indicating that a Passpoint provider icon has been received.
     *
     * Included extras:
     * {@link #EXTRA_BSSID_LONG}
     * {@link #EXTRA_FILENAME}
     * {@link #EXTRA_ICON}
     *
     * Receiver Required Permission: android.Manifest.permission.ACCESS_WIFI_STATE
     *
     * <p>Note: The broadcast is only delivered to registered receivers - no manifest registered
     * components will be launched.
     *
     * @hide
     */
    public static final String ACTION_PASSPOINT_ICON = "android.net.wifi.action.PASSPOINT_ICON";
    /**
     * BSSID of an AP in long representation.  The {@link #EXTRA_BSSID} contains BSSID in
     * String representation.
     *
     * Retrieve with {@link android.content.Intent#getLongExtra(String, long)}.
     *
     * @hide
     */
    public static final String EXTRA_BSSID_LONG = "android.net.wifi.extra.BSSID_LONG";
    /**
     * Icon data.
     *
     * Retrieve with {@link android.content.Intent#getParcelableExtra(String)} and cast into
     * {@link android.graphics.drawable.Icon}.
     *
     * @hide
     */
    public static final String EXTRA_ICON = "android.net.wifi.extra.ICON";
    /**
     * Name of a file.
     *
     * Retrieve with {@link android.content.Intent#getStringExtra(String)}.
     *
     * @hide
     */
    public static final String EXTRA_FILENAME = "android.net.wifi.extra.FILENAME";

    /**
     * Broadcast intent action indicating a Passpoint OSU Providers List element has been received.
     *
     * Included extras:
     * {@link #EXTRA_BSSID_LONG}
     * {@link #EXTRA_ANQP_ELEMENT_DATA}
     *
     * Receiver Required Permission: android.Manifest.permission.ACCESS_WIFI_STATE
     *
     * <p>Note: The broadcast is only delivered to registered receivers - no manifest registered
     * components will be launched.
     *
     * @hide
     */
    public static final String ACTION_PASSPOINT_OSU_PROVIDERS_LIST =
            "android.net.wifi.action.PASSPOINT_OSU_PROVIDERS_LIST";
    /**
     * Raw binary data of an ANQP (Access Network Query Protocol) element.
     *
     * Retrieve with {@link android.content.Intent#getByteArrayExtra(String)}.
     *
     * @hide
     */
    public static final String EXTRA_ANQP_ELEMENT_DATA =
            "android.net.wifi.extra.ANQP_ELEMENT_DATA";

    /**
     * Broadcast intent action indicating that a Passpoint Deauth Imminent frame has been received.
     *
     * Included extras:
     * {@link #EXTRA_BSSID_LONG}
     * {@link #EXTRA_ESS}
     * {@link #EXTRA_DELAY}
     * {@link #EXTRA_URL}
     *
     * Receiver Required Permission: android.Manifest.permission.ACCESS_WIFI_STATE
     *
     * <p>Note: The broadcast is only delivered to registered receivers - no manifest registered
     * components will be launched.
     *
     * @hide
     */
    public static final String ACTION_PASSPOINT_DEAUTH_IMMINENT =
            "android.net.wifi.action.PASSPOINT_DEAUTH_IMMINENT";
    /**
     * Flag indicating BSS (Basic Service Set) or ESS (Extended Service Set). This will be set to
     * {@code true} for ESS.
     *
     * Retrieve with {@link android.content.Intent#getBooleanExtra(String, boolean)}.
     *
     * @hide
     */
    public static final String EXTRA_ESS = "android.net.wifi.extra.ESS";
    /**
     * Delay in seconds.
     *
     * Retrieve with {@link android.content.Intent#getIntExtra(String, int)}.
     *
     * @hide
     */
    public static final String EXTRA_DELAY = "android.net.wifi.extra.DELAY";

    /**
     * Broadcast intent action indicating a Passpoint subscription remediation frame has been
     * received.
     *
     * Included extras:
     * {@link #EXTRA_BSSID_LONG}
     * {@link #EXTRA_SUBSCRIPTION_REMEDIATION_METHOD}
     * {@link #EXTRA_URL}
     *
     * Receiver Required Permission: android.Manifest.permission.ACCESS_WIFI_STATE
     *
     * <p>Note: The broadcast is only delivered to registered receivers - no manifest registered
     * components will be launched.
     *
     * @hide
     */
    public static final String ACTION_PASSPOINT_SUBSCRIPTION_REMEDIATION =
            "android.net.wifi.action.PASSPOINT_SUBSCRIPTION_REMEDIATION";
    /**
     * The protocol supported by the subscription remediation server. The possible values are:
     * 0 - OMA DM
     * 1 - SOAP XML SPP
     *
     * Retrieve with {@link android.content.Intent#getIntExtra(String, int)}.
     *
     * @hide
     */
    public static final String EXTRA_SUBSCRIPTION_REMEDIATION_METHOD =
            "android.net.wifi.extra.SUBSCRIPTION_REMEDIATION_METHOD";

    /**
     * Activity Action: Receiver should launch Passpoint OSU (Online Sign Up) view.
     * Included extras:
     *
     * {@link #EXTRA_OSU_NETWORK}: {@link Network} instance associated with OSU AP.
     * {@link #EXTRA_URL}: String representation of a server URL used for OSU process.
     *
     * @hide
     */
    @SystemApi
    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
    public static final String ACTION_PASSPOINT_LAUNCH_OSU_VIEW =
            "android.net.wifi.action.PASSPOINT_LAUNCH_OSU_VIEW";

    /**
     * The lookup key for a {@link android.net.Network} associated with a Passpoint OSU server.
     * Included in the {@link #ACTION_PASSPOINT_LAUNCH_OSU_VIEW} broadcast.
     *
     * Retrieve with {@link android.content.Intent#getParcelableExtra(String)}.
     *
     * @hide
     */
    @SystemApi
    public static final String EXTRA_OSU_NETWORK = "android.net.wifi.extra.OSU_NETWORK";

    /**
     * String representation of an URL for Passpoint OSU.
     * Included in the {@link #ACTION_PASSPOINT_LAUNCH_OSU_VIEW} broadcast.
     *
     * Retrieve with {@link android.content.Intent#getStringExtra(String)}.
     *
     * @hide
     */
    @SystemApi
    public static final String EXTRA_URL = "android.net.wifi.extra.URL";

    /**
     * Broadcast intent action indicating that Wi-Fi has been enabled, disabled,
     * enabling, disabling, or unknown. One extra provides this state as an int.
     * Another extra provides the previous state, if available.  No network-related
     * permissions are required to subscribe to this broadcast.
     *
     * <p class="note">This broadcast is not delivered to manifest receivers in
     * applications that target API version 26 or later.
     *
     * @see #EXTRA_WIFI_STATE
     * @see #EXTRA_PREVIOUS_WIFI_STATE
     */
    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    public static final String WIFI_STATE_CHANGED_ACTION =
        "android.net.wifi.WIFI_STATE_CHANGED";
    /**
     * The lookup key for an int that indicates whether Wi-Fi is enabled,
     * disabled, enabling, disabling, or unknown.  Retrieve it with
     * {@link android.content.Intent#getIntExtra(String,int)}.
     *
     * @see #WIFI_STATE_DISABLED
     * @see #WIFI_STATE_DISABLING
     * @see #WIFI_STATE_ENABLED
     * @see #WIFI_STATE_ENABLING
     * @see #WIFI_STATE_UNKNOWN
     */
    public static final String EXTRA_WIFI_STATE = "wifi_state";
    /**
     * The previous Wi-Fi state.
     *
     * @see #EXTRA_WIFI_STATE
     */
    public static final String EXTRA_PREVIOUS_WIFI_STATE = "previous_wifi_state";

    /**
     * Wi-Fi is currently being disabled. The state will change to {@link #WIFI_STATE_DISABLED} if
     * it finishes successfully.
     *
     * @see #WIFI_STATE_CHANGED_ACTION
     * @see #getWifiState()
     */
    public static final int WIFI_STATE_DISABLING = 0;
    /**
     * Wi-Fi is disabled.
     *
     * @see #WIFI_STATE_CHANGED_ACTION
     * @see #getWifiState()
     */
    public static final int WIFI_STATE_DISABLED = 1;
    /**
     * Wi-Fi is currently being enabled. The state will change to {@link #WIFI_STATE_ENABLED} if
     * it finishes successfully.
     *
     * @see #WIFI_STATE_CHANGED_ACTION
     * @see #getWifiState()
     */
    public static final int WIFI_STATE_ENABLING = 2;
    /**
     * Wi-Fi is enabled.
     *
     * @see #WIFI_STATE_CHANGED_ACTION
     * @see #getWifiState()
     */
    public static final int WIFI_STATE_ENABLED = 3;
    /**
     * Wi-Fi is in an unknown state. This state will occur when an error happens while enabling
     * or disabling.
     *
     * @see #WIFI_STATE_CHANGED_ACTION
     * @see #getWifiState()
     */
    public static final int WIFI_STATE_UNKNOWN = 4;

    /**
     * Broadcast intent action indicating that Wi-Fi AP has been enabled, disabled,
     * enabling, disabling, or failed.
     *
     * @hide
     */
    @SystemApi
    public static final String WIFI_AP_STATE_CHANGED_ACTION =
        "android.net.wifi.WIFI_AP_STATE_CHANGED";

    /**
     * The lookup key for an int that indicates whether Wi-Fi AP is enabled,
     * disabled, enabling, disabling, or failed.  Retrieve it with
     * {@link android.content.Intent#getIntExtra(String,int)}.
     *
     * @see #WIFI_AP_STATE_DISABLED
     * @see #WIFI_AP_STATE_DISABLING
     * @see #WIFI_AP_STATE_ENABLED
     * @see #WIFI_AP_STATE_ENABLING
     * @see #WIFI_AP_STATE_FAILED
     *
     * @hide
     */
    @SystemApi
    public static final String EXTRA_WIFI_AP_STATE = "wifi_state";

    /**
     * An extra containing the int error code for Soft AP start failure.
     * Can be obtained from the {@link #WIFI_AP_STATE_CHANGED_ACTION} using
     * {@link android.content.Intent#getIntExtra}.
     * This extra will only be attached if {@link #EXTRA_WIFI_AP_STATE} is
     * attached and is equal to {@link #WIFI_AP_STATE_FAILED}.
     *
     * The error code will be one of:
     * {@link #SAP_START_FAILURE_GENERAL},
     * {@link #SAP_START_FAILURE_NO_CHANNEL},
     * {@link #SAP_START_FAILURE_UNSUPPORTED_CONFIGURATION}
     *
     * @hide
     */
    @SystemApi
    public static final String EXTRA_WIFI_AP_FAILURE_REASON =
            "android.net.wifi.extra.WIFI_AP_FAILURE_REASON";
    /**
     * The previous Wi-Fi state.
     *
     * @see #EXTRA_WIFI_AP_STATE
     *
     * @hide
     */
    @SystemApi
    public static final String EXTRA_PREVIOUS_WIFI_AP_STATE = "previous_wifi_state";
    /**
     * The lookup key for a String extra that stores the interface name used for the Soft AP.
     * This extra is included in the broadcast {@link #WIFI_AP_STATE_CHANGED_ACTION}.
     * Retrieve its value with {@link android.content.Intent#getStringExtra(String)}.
     *
     * @hide
     */
    @SystemApi
    public static final String EXTRA_WIFI_AP_INTERFACE_NAME =
            "android.net.wifi.extra.WIFI_AP_INTERFACE_NAME";
    /**
     * The lookup key for an int extra that stores the intended IP mode for this Soft AP.
     * One of {@link #IFACE_IP_MODE_TETHERED} or {@link #IFACE_IP_MODE_LOCAL_ONLY}.
     * This extra is included in the broadcast {@link #WIFI_AP_STATE_CHANGED_ACTION}.
     * Retrieve its value with {@link android.content.Intent#getIntExtra(String, int)}.
     *
     * @hide
     */
    @SystemApi
    public static final String EXTRA_WIFI_AP_MODE = "android.net.wifi.extra.WIFI_AP_MODE";

    /** @hide */
    @IntDef(flag = false, prefix = { "WIFI_AP_STATE_" }, value = {
        WIFI_AP_STATE_DISABLING,
        WIFI_AP_STATE_DISABLED,
        WIFI_AP_STATE_ENABLING,
        WIFI_AP_STATE_ENABLED,
        WIFI_AP_STATE_FAILED,
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface WifiApState {}

    /**
     * Wi-Fi AP is currently being disabled. The state will change to
     * {@link #WIFI_AP_STATE_DISABLED} if it finishes successfully.
     *
     * @see #WIFI_AP_STATE_CHANGED_ACTION
     * @see #getWifiApState()
     *
     * @hide
     */
    @SystemApi
    public static final int WIFI_AP_STATE_DISABLING = 10;
    /**
     * Wi-Fi AP is disabled.
     *
     * @see #WIFI_AP_STATE_CHANGED_ACTION
     * @see #getWifiState()
     *
     * @hide
     */
    @SystemApi
    public static final int WIFI_AP_STATE_DISABLED = 11;
    /**
     * Wi-Fi AP is currently being enabled. The state will change to
     * {@link #WIFI_AP_STATE_ENABLED} if it finishes successfully.
     *
     * @see #WIFI_AP_STATE_CHANGED_ACTION
     * @see #getWifiApState()
     *
     * @hide
     */
    @SystemApi
    public static final int WIFI_AP_STATE_ENABLING = 12;
    /**
     * Wi-Fi AP is enabled.
     *
     * @see #WIFI_AP_STATE_CHANGED_ACTION
     * @see #getWifiApState()
     *
     * @hide
     */
    @SystemApi
    public static final int WIFI_AP_STATE_ENABLED = 13;
    /**
     * Wi-Fi AP is in a failed state. This state will occur when an error occurs during
     * enabling or disabling
     *
     * @see #WIFI_AP_STATE_CHANGED_ACTION
     * @see #getWifiApState()
     *
     * @hide
     */
    @SystemApi
    public static final int WIFI_AP_STATE_FAILED = 14;

    /** @hide */
    @IntDef(flag = false, prefix = { "SAP_START_FAILURE_" }, value = {
        SAP_START_FAILURE_GENERAL,
        SAP_START_FAILURE_NO_CHANNEL,
        SAP_START_FAILURE_UNSUPPORTED_CONFIGURATION,
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface SapStartFailure {}

    /**
     *  All other reasons for AP start failure besides {@link #SAP_START_FAILURE_NO_CHANNEL} and
     *  {@link #SAP_START_FAILURE_UNSUPPORTED_CONFIGURATION}.
     *
     *  @hide
     */
    @SystemApi
    public static final int SAP_START_FAILURE_GENERAL= 0;

    /**
     *  If Wi-Fi AP start failed, this reason code means that no legal channel exists on user
     *  selected band due to regulatory constraints.
     *
     *  @hide
     */
    @SystemApi
    public static final int SAP_START_FAILURE_NO_CHANNEL = 1;

    /**
     *  If Wi-Fi AP start failed, this reason code means that the specified configuration
     *  is not supported by the current HAL version.
     *
     *  @hide
     */
    @SystemApi
    public static final int SAP_START_FAILURE_UNSUPPORTED_CONFIGURATION = 2;


    /** @hide */
    @IntDef(flag = false, prefix = { "SAP_CLIENT_BLOCKED_REASON_" }, value = {
        SAP_CLIENT_BLOCK_REASON_CODE_BLOCKED_BY_USER,
        SAP_CLIENT_BLOCK_REASON_CODE_NO_MORE_STAS,
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface SapClientBlockedReason {}

    /**
     *  If Soft Ap client is blocked, this reason code means that client doesn't exist in the
     *  specified configuration {@link SoftApConfiguration.Builder#setBlockedClientList(List)}
     *  and {@link SoftApConfiguration.Builder#setAllowedClientList(List)}
     *  and the {@link SoftApConfiguration.Builder#setClientControlByUserEnabled(boolean)}
     *  is configured as well.
     *  @hide
     */
    @SystemApi
    public static final int SAP_CLIENT_BLOCK_REASON_CODE_BLOCKED_BY_USER = 0;

    /**
     *  If Soft Ap client is blocked, this reason code means that no more clients can be
     *  associated to this AP since it reached maximum capacity. The maximum capacity is
     *  the minimum of {@link SoftApConfiguration.Builder#setMaxNumberOfClients(int)} and
     *  {@link SoftApCapability#getMaxSupportedClients} which get from
     *  {@link WifiManager.SoftApCallback#onCapabilityChanged(SoftApCapability)}.
     *
     *  @hide
     */
    @SystemApi
    public static final int SAP_CLIENT_BLOCK_REASON_CODE_NO_MORE_STAS = 1;

    /**
     * Client disconnected for unspecified reason. This could for example be because the AP is being
     * shut down.
     * @hide
     */
    public static final int SAP_CLIENT_DISCONNECT_REASON_CODE_UNSPECIFIED = 2;

    /** @hide */
    @Retention(RetentionPolicy.SOURCE)
    @IntDef(prefix = {"IFACE_IP_MODE_"}, value = {
            IFACE_IP_MODE_UNSPECIFIED,
            IFACE_IP_MODE_CONFIGURATION_ERROR,
            IFACE_IP_MODE_TETHERED,
            IFACE_IP_MODE_LOCAL_ONLY})
    public @interface IfaceIpMode {}

    /**
     * Interface IP mode unspecified.
     *
     * @see #updateInterfaceIpState(String, int)
     *
     * @hide
     */
    @SystemApi
    public static final int IFACE_IP_MODE_UNSPECIFIED = -1;

    /**
     * Interface IP mode for configuration error.
     *
     * @see #updateInterfaceIpState(String, int)
     *
     * @hide
     */
    @SystemApi
    public static final int IFACE_IP_MODE_CONFIGURATION_ERROR = 0;

    /**
     * Interface IP mode for tethering.
     *
     * @see #updateInterfaceIpState(String, int)
     *
     * @hide
     */
    @SystemApi
    public static final int IFACE_IP_MODE_TETHERED = 1;

    /**
     * Interface IP mode for Local Only Hotspot.
     *
     * @see #updateInterfaceIpState(String, int)
     *
     * @hide
     */
    @SystemApi
    public static final int IFACE_IP_MODE_LOCAL_ONLY = 2;

    /**
     * Broadcast intent action indicating that the wifi network settings
     * had been reset.
     *
     * Note: This intent is sent as a directed broadcast to each manifest registered receiver.
     * Intent will not be received by dynamically registered receivers.
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.NETWORK_CARRIER_PROVISIONING)
    public static final String ACTION_NETWORK_SETTINGS_RESET =
            "android.net.wifi.action.NETWORK_SETTINGS_RESET";

    /**
     * Broadcast intent action indicating that the wifi network profiles provisioned
     * may need refresh.
     *
     * Note: This intent is sent as a directed broadcast to each manifest registered receiver;
     * And restricted to those apps which have the NETWORK_CARRIER_PROVISIONING permission.
     * Intent will not be received by dynamically registered receivers.
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.NETWORK_CARRIER_PROVISIONING)
    public static final String ACTION_REFRESH_USER_PROVISIONING =
            "android.net.wifi.action.REFRESH_USER_PROVISIONING";

    /**
     * Broadcast intent action indicating that a connection to the supplicant has
     * been established (and it is now possible
     * to perform Wi-Fi operations) or the connection to the supplicant has been
     * lost. One extra provides the connection state as a boolean, where {@code true}
     * means CONNECTED.
     * @deprecated This is no longer supported.
     * @see #EXTRA_SUPPLICANT_CONNECTED
     */
    @Deprecated
    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    public static final String SUPPLICANT_CONNECTION_CHANGE_ACTION =
        "android.net.wifi.supplicant.CONNECTION_CHANGE";
    /**
     * The lookup key for a boolean that indicates whether a connection to
     * the supplicant daemon has been gained or lost. {@code true} means
     * a connection now exists.
     * Retrieve it with {@link android.content.Intent#getBooleanExtra(String,boolean)}.
     * @deprecated This is no longer supported.
     */
    @Deprecated
    public static final String EXTRA_SUPPLICANT_CONNECTED = "connected";
    /**
     * Broadcast intent action indicating that the state of Wi-Fi connectivity
     * has changed. An extra provides the new state
     * in the form of a {@link android.net.NetworkInfo} object.  No network-related
     * permissions are required to subscribe to this broadcast.
     *
     * <p class="note">This broadcast is not delivered to manifest receivers in
     * applications that target API version 26 or later.
     * @see #EXTRA_NETWORK_INFO
     */
    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    public static final String NETWORK_STATE_CHANGED_ACTION = "android.net.wifi.STATE_CHANGE";
    /**
     * The lookup key for a {@link android.net.NetworkInfo} object associated with the
     * Wi-Fi network. Retrieve with
     * {@link android.content.Intent#getParcelableExtra(String)}.
     */
    public static final String EXTRA_NETWORK_INFO = "networkInfo";
    /**
     * The lookup key for a String giving the BSSID of the access point to which
     * we are connected. No longer used.
     */
    @Deprecated
    public static final String EXTRA_BSSID = "bssid";
    /**
     * The lookup key for a {@link android.net.wifi.WifiInfo} object giving the
     * information about the access point to which we are connected.
     * No longer used.
     */
    @Deprecated
    public static final String EXTRA_WIFI_INFO = "wifiInfo";
    /**
     * Broadcast intent action indicating that the state of establishing a connection to
     * an access point has changed.One extra provides the new
     * {@link SupplicantState}. Note that the supplicant state is Wi-Fi specific, and
     * is not generally the most useful thing to look at if you are just interested in
     * the overall state of connectivity.
     * @see #EXTRA_NEW_STATE
     * @see #EXTRA_SUPPLICANT_ERROR
     * @deprecated This is no longer supported.
     */
    @Deprecated
    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    public static final String SUPPLICANT_STATE_CHANGED_ACTION =
        "android.net.wifi.supplicant.STATE_CHANGE";
    /**
     * The lookup key for a {@link SupplicantState} describing the new state
     * Retrieve with
     * {@link android.content.Intent#getParcelableExtra(String)}.
     * @deprecated This is no longer supported.
     */
    @Deprecated
    public static final String EXTRA_NEW_STATE = "newState";

    /**
     * The lookup key for a {@link SupplicantState} describing the supplicant
     * error code if any
     * Retrieve with
     * {@link android.content.Intent#getIntExtra(String, int)}.
     * @see #ERROR_AUTHENTICATING
     * @deprecated This is no longer supported.
     */
    @Deprecated
    public static final String EXTRA_SUPPLICANT_ERROR = "supplicantError";

    /**
     * The lookup key for a {@link SupplicantState} describing the supplicant
     * error reason if any
     * Retrieve with
     * {@link android.content.Intent#getIntExtra(String, int)}.
     * @see #ERROR_AUTH_FAILURE_#REASON_CODE
     * @deprecated This is no longer supported.
     * @hide
     */
    @Deprecated
    public static final String EXTRA_SUPPLICANT_ERROR_REASON = "supplicantErrorReason";

    /**
     * Broadcast intent action indicating that the configured networks changed.
     * This can be as a result of adding/updating/deleting a network.
     * <br />
     * {@link #EXTRA_CHANGE_REASON} contains whether the configuration was added/changed/removed.
     * {@link #EXTRA_WIFI_CONFIGURATION} is never set beginning in
     * {@link android.os.Build.VERSION_CODES#R}.
     * {@link #EXTRA_MULTIPLE_NETWORKS_CHANGED} is set for backwards compatibility reasons, but
     * its value is always true beginning in {@link android.os.Build.VERSION_CODES#R}, even if only
     * a single network changed.
     * <br />
     * The {@link android.Manifest.permission#ACCESS_WIFI_STATE ACCESS_WIFI_STATE} permission is
     * required to receive this broadcast.
     *
     * @hide
     */
    @SystemApi
    public static final String CONFIGURED_NETWORKS_CHANGED_ACTION =
        "android.net.wifi.CONFIGURED_NETWORKS_CHANGE";
    /**
     * The lookup key for a {@link android.net.wifi.WifiConfiguration} object representing
     * the changed Wi-Fi configuration when the {@link #CONFIGURED_NETWORKS_CHANGED_ACTION}
     * broadcast is sent.
     * @deprecated This extra is never set beginning in {@link android.os.Build.VERSION_CODES#R},
     * regardless of the target SDK version. Use {@link #getConfiguredNetworks} to get the full list
     * of configured networks.
     * @hide
     */
    @Deprecated
    @SystemApi
    public static final String EXTRA_WIFI_CONFIGURATION = "wifiConfiguration";
    /**
     * Multiple network configurations have changed.
     * @see #CONFIGURED_NETWORKS_CHANGED_ACTION
     * @deprecated This extra's value is always true beginning in
     * {@link android.os.Build.VERSION_CODES#R}, regardless of the target SDK version.
     * @hide
     */
    @Deprecated
    @SystemApi
    public static final String EXTRA_MULTIPLE_NETWORKS_CHANGED = "multipleChanges";
    /**
     * The lookup key for an integer indicating the reason a Wi-Fi network configuration
     * has changed. One of {@link #CHANGE_REASON_ADDED}, {@link #CHANGE_REASON_REMOVED},
     * {@link #CHANGE_REASON_CONFIG_CHANGE}.
     *
     * @see #CONFIGURED_NETWORKS_CHANGED_ACTION
     * @hide
     */
    @SystemApi
    public static final String EXTRA_CHANGE_REASON = "changeReason";
    /**
     * The configuration is new and was added.
     * @hide
     */
    @SystemApi
    public static final int CHANGE_REASON_ADDED = 0;
    /**
     * The configuration was removed and is no longer present in the system's list of
     * configured networks.
     * @hide
     */
    @SystemApi
    public static final int CHANGE_REASON_REMOVED = 1;
    /**
     * The configuration has changed as a result of explicit action or because the system
     * took an automated action such as disabling a malfunctioning configuration.
     * @hide
     */
    @SystemApi
    public static final int CHANGE_REASON_CONFIG_CHANGE = 2;
    /**
     * An access point scan has completed, and results are available.
     * Call {@link #getScanResults()} to obtain the results.
     * The broadcast intent may contain an extra field with the key {@link #EXTRA_RESULTS_UPDATED}
     * and a {@code boolean} value indicating if the scan was successful.
     */
    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    public static final String SCAN_RESULTS_AVAILABLE_ACTION = "android.net.wifi.SCAN_RESULTS";

    /**
     * Lookup key for a {@code boolean} extra in intent {@link #SCAN_RESULTS_AVAILABLE_ACTION}
     * representing if the scan was successful or not.
     * Scans may fail for multiple reasons, these may include:
     * <ol>
     * <li>An app requested too many scans in a certain period of time.
     * This may lead to additional scan request rejections via "scan throttling" for both
     * foreground and background apps.
     * Note: Apps holding android.Manifest.permission.NETWORK_SETTINGS permission are
     * exempted from scan throttling.
     * </li>
     * <li>The device is idle and scanning is disabled.</li>
     * <li>Wifi hardware reported a scan failure.</li>
     * </ol>
     * @return true scan was successful, results are updated
     * @return false scan was not successful, results haven't been updated since previous scan
     */
    public static final String EXTRA_RESULTS_UPDATED = "resultsUpdated";

    /**
     * A batch of access point scans has been completed and the results areavailable.
     * Call {@link #getBatchedScanResults()} to obtain the results.
     * @deprecated This API is nolonger supported.
     * Use {@link WifiScanner} API
     * @hide
     */
    @Deprecated
    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    public static final String BATCHED_SCAN_RESULTS_AVAILABLE_ACTION =
            "android.net.wifi.BATCHED_RESULTS";

    /**
     * The RSSI (signal strength) has changed.
     *
     * Receiver Required Permission: android.Manifest.permission.ACCESS_WIFI_STATE
     * @see #EXTRA_NEW_RSSI
     */
    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    public static final String RSSI_CHANGED_ACTION = "android.net.wifi.RSSI_CHANGED";
    /**
     * The lookup key for an {@code int} giving the new RSSI in dBm.
     */
    public static final String EXTRA_NEW_RSSI = "newRssi";

    /**
     * @see #ACTION_LINK_CONFIGURATION_CHANGED
     * @hide
     */
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    public static final String LINK_CONFIGURATION_CHANGED_ACTION =
            "android.net.wifi.LINK_CONFIGURATION_CHANGED";

    /**
     * Broadcast intent action indicating that the link configuration changed on wifi.
     * <br /> No permissions are required to listen to this broadcast.
     * @hide
     */
    @SystemApi
    public static final String ACTION_LINK_CONFIGURATION_CHANGED =
            // should be android.net.wifi.action.LINK_CONFIGURATION_CHANGED, but due to
            // @UnsupportedAppUsage leaving it as android.net.wifi.LINK_CONFIGURATION_CHANGED.
            LINK_CONFIGURATION_CHANGED_ACTION;

    /**
     * The lookup key for a {@link android.net.LinkProperties} object associated with the
     * Wi-Fi network.
     * Included in the {@link #ACTION_LINK_CONFIGURATION_CHANGED} broadcast.
     *
     * Retrieve with {@link android.content.Intent#getParcelableExtra(String)}.
     *
     * @deprecated this extra is no longer populated.
     *
     * @hide
     */
    @Deprecated
    @SystemApi
    public static final String EXTRA_LINK_PROPERTIES = "android.net.wifi.extra.LINK_PROPERTIES";

    /**
     * The lookup key for a {@link android.net.NetworkCapabilities} object associated with the
     * Wi-Fi network. Retrieve with
     * {@link android.content.Intent#getParcelableExtra(String)}.
     * @hide
     */
    public static final String EXTRA_NETWORK_CAPABILITIES = "networkCapabilities";

    /**
     * The network IDs of the configured networks could have changed.
     */
    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    public static final String NETWORK_IDS_CHANGED_ACTION = "android.net.wifi.NETWORK_IDS_CHANGED";

    /**
     * Activity Action: Show a system activity that allows the user to enable
     * scans to be available even with Wi-Fi turned off.
     *
     * <p>Notification of the result of this activity is posted using the
     * {@link android.app.Activity#onActivityResult} callback. The
     * <code>resultCode</code>
     * will be {@link android.app.Activity#RESULT_OK} if scan always mode has
     * been turned on or {@link android.app.Activity#RESULT_CANCELED} if the user
     * has rejected the request or an error has occurred.
     */
    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
    public static final String ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE =
            "android.net.wifi.action.REQUEST_SCAN_ALWAYS_AVAILABLE";

    /**
     * Activity Action: Pick a Wi-Fi network to connect to.
     * <p>Input: Nothing.
     * <p>Output: Nothing.
     */
    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
    public static final String ACTION_PICK_WIFI_NETWORK = "android.net.wifi.PICK_WIFI_NETWORK";

    /**
     * Activity Action: Receiver should show UI to get user approval to enable WiFi.
     * <p>Input: {@link android.content.Intent#EXTRA_PACKAGE_NAME} string extra with
     *           the name of the app requesting the action.
     * <p>Output: Nothing.
     * <p>No permissions are required to send this action.
     * @hide
     */
    @SystemApi
    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
    public static final String ACTION_REQUEST_ENABLE = "android.net.wifi.action.REQUEST_ENABLE";

    /**
     * Activity Action: Receiver should show UI to get user approval to disable WiFi.
     * <p>Input: {@link android.content.Intent#EXTRA_PACKAGE_NAME} string extra with
     *           the name of the app requesting the action.
     * <p>Output: Nothing.
     * <p>No permissions are required to send this action.
     * @hide
     */
    @SystemApi
    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
    public static final String ACTION_REQUEST_DISABLE = "android.net.wifi.action.REQUEST_DISABLE";

    /**
     * Directed broadcast intent action indicating that the device has connected to one of the
     * network suggestions provided by the app. This will be sent post connection to a network
     * which was created with {@link WifiNetworkSuggestion.Builder#setIsAppInteractionRequired(
     * boolean)}
     * flag set.
     * <p>
     * Note: The broadcast is sent to the app only if it holds
     * {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION} permission.
     *
     * @see #EXTRA_NETWORK_SUGGESTION
     */
    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    public static final String ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION =
            "android.net.wifi.action.WIFI_NETWORK_SUGGESTION_POST_CONNECTION";
    /**
     * Sent as as a part of {@link #ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION} that holds
     * an instance of {@link WifiNetworkSuggestion} corresponding to the connected network.
     */
    public static final String EXTRA_NETWORK_SUGGESTION =
            "android.net.wifi.extra.NETWORK_SUGGESTION";

    /**
     * Internally used Wi-Fi lock mode representing the case were no locks are held.
     * @hide
     */
    public static final int WIFI_MODE_NO_LOCKS_HELD = 0;

    /**
     * In this Wi-Fi lock mode, Wi-Fi will be kept active,
     * and will behave normally, i.e., it will attempt to automatically
     * establish a connection to a remembered access point that is
     * within range, and will do periodic scans if there are remembered
     * access points but none are in range.
     *
     * @deprecated This API is non-functional and will have no impact.
     */
    @Deprecated
    public static final int WIFI_MODE_FULL = 1;

    /**
     * In this Wi-Fi lock mode, Wi-Fi will be kept active,
     * but the only operation that will be supported is initiation of
     * scans, and the subsequent reporting of scan results. No attempts
     * will be made to automatically connect to remembered access points,
     * nor will periodic scans be automatically performed looking for
     * remembered access points. Scans must be explicitly requested by
     * an application in this mode.
     *
     * @deprecated This API is non-functional and will have no impact.
     */
    @Deprecated
    public static final int WIFI_MODE_SCAN_ONLY = 2;

    /**
     * In this Wi-Fi lock mode, Wi-Fi will not go to power save.
     * This results in operating with low packet latency.
     * The lock is only active when the device is connected to an access point.
     * The lock is active even when the device screen is off or the acquiring application is
     * running in the background.
     * This mode will consume more power and hence should be used only
     * when there is a need for this tradeoff.
     * <p>
     * An example use case is when a voice connection needs to be
     * kept active even after the device screen goes off.
     * Holding a {@link #WIFI_MODE_FULL_HIGH_PERF} lock for the
     * duration of the voice call may improve the call quality.
     * <p>
     * When there is no support from the hardware, the {@link #WIFI_MODE_FULL_HIGH_PERF}
     * lock will have no impact.
     */
    public static final int WIFI_MODE_FULL_HIGH_PERF = 3;

    /**
     * In this Wi-Fi lock mode, Wi-Fi will operate with a priority to achieve low latency.
     * {@link #WIFI_MODE_FULL_LOW_LATENCY} lock has the following limitations:
     * <ol>
     * <li>The lock is only active when the device is connected to an access point.</li>
     * <li>The lock is only active when the screen is on.</li>
     * <li>The lock is only active when the acquiring app is running in the foreground.</li>
     * </ol>
     * Low latency mode optimizes for reduced packet latency,
     * and as a result other performance measures may suffer when there are trade-offs to make:
     * <ol>
     * <li>Battery life may be reduced.</li>
     * <li>Throughput may be reduced.</li>
     * <li>Frequency of Wi-Fi scanning may be reduced. This may result in: </li>
     * <ul>
     * <li>The device may not roam or switch to the AP with highest signal quality.</li>
     * <li>Location accuracy may be reduced.</li>
     * </ul>
     * </ol>
     * <p>
     * Example use cases are real time gaming or virtual reality applications where
     * low latency is a key factor for user experience.
     * <p>
     * Note: For an app which acquires both {@link #WIFI_MODE_FULL_LOW_LATENCY} and
     * {@link #WIFI_MODE_FULL_HIGH_PERF} locks, {@link #WIFI_MODE_FULL_LOW_LATENCY}
     * lock will be effective when app is running in foreground and screen is on,
     * while the {@link #WIFI_MODE_FULL_HIGH_PERF} lock will take effect otherwise.
     */
    public static final int WIFI_MODE_FULL_LOW_LATENCY = 4;


    /** Anything worse than or equal to this will show 0 bars. */
    @UnsupportedAppUsage
    private static final int MIN_RSSI = -100;

    /** Anything better than or equal to this will show the max bars. */
    @UnsupportedAppUsage
    private static final int MAX_RSSI = -55;

    /**
     * Number of RSSI levels used in the framework to initiate {@link #RSSI_CHANGED_ACTION}
     * broadcast, where each level corresponds to a range of RSSI values.
     * The {@link #RSSI_CHANGED_ACTION} broadcast will only fire if the RSSI
     * change is significant enough to change the RSSI signal level.
     * @hide
     */
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    public static final int RSSI_LEVELS = 5;

    //TODO (b/146346676): This needs to be removed, not used in the code.
    /**
     * Auto settings in the driver. The driver could choose to operate on both
     * 2.4 GHz and 5 GHz or make a dynamic decision on selecting the band.
     * @hide
     */
    @UnsupportedAppUsage
    public static final int WIFI_FREQUENCY_BAND_AUTO = 0;

    /**
     * Operation on 5 GHz alone
     * @hide
     */
    @UnsupportedAppUsage
    public static final int WIFI_FREQUENCY_BAND_5GHZ = 1;

    /**
     * Operation on 2.4 GHz alone
     * @hide
     */
    @UnsupportedAppUsage
    public static final int WIFI_FREQUENCY_BAND_2GHZ = 2;

    /** @hide */
    public static final boolean DEFAULT_POOR_NETWORK_AVOIDANCE_ENABLED = false;

    /**
     * Maximum number of active locks we allow.
     * This limit was added to prevent apps from creating a ridiculous number
     * of locks and crashing the system by overflowing the global ref table.
     */
    private static final int MAX_ACTIVE_LOCKS = 50;

    /** Indicates an invalid SSID. */
    public static final String UNKNOWN_SSID = "<unknown ssid>";

    /** @hide */
    public static final MacAddress ALL_ZEROS_MAC_ADDRESS =
            MacAddress.fromString("00:00:00:00:00:00");

    /* Number of currently active WifiLocks and MulticastLocks */
    @UnsupportedAppUsage
    private int mActiveLockCount;

    private Context mContext;
    @UnsupportedAppUsage
    IWifiManager mService;
    private final int mTargetSdkVersion;

    private Looper mLooper;
    private boolean mVerboseLoggingEnabled = false;

    private final Object mLock = new Object(); // lock guarding access to the following vars
    @GuardedBy("mLock")
    private LocalOnlyHotspotCallbackProxy mLOHSCallbackProxy;
    @GuardedBy("mLock")
    private LocalOnlyHotspotObserverProxy mLOHSObserverProxy;

    private static final SparseArray<IOnWifiUsabilityStatsListener>
            sOnWifiUsabilityStatsListenerMap = new SparseArray();
    private static final SparseArray<ISuggestionConnectionStatusListener>
            sSuggestionConnectionStatusListenerMap = new SparseArray();
    private static final SparseArray<ISuggestionUserApprovalStatusListener>
            sSuggestionUserApprovalStatusListenerMap = new SparseArray();
    private static final SparseArray<IWifiVerboseLoggingStatusChangedListener>
            sWifiVerboseLoggingStatusChangedListenerMap = new SparseArray();
    private static final SparseArray<INetworkRequestMatchCallback>
            sNetworkRequestMatchCallbackMap = new SparseArray();
    private static final SparseArray<ITrafficStateCallback>
            sTrafficStateCallbackMap = new SparseArray();
    private static final SparseArray<ISoftApCallback> sSoftApCallbackMap = new SparseArray();

    /**
     * Create a new WifiManager instance.
     * Applications will almost always want to use
     * {@link android.content.Context#getSystemService Context.getSystemService} to retrieve
     * the standard {@link android.content.Context#WIFI_SERVICE Context.WIFI_SERVICE}.
     *
     * @param context the application context
     * @param service the Binder interface
     * @param looper the Looper used to deliver callbacks
     * @hide - hide this because it takes in a parameter of type IWifiManager, which
     * is a system private class.
     */
    public WifiManager(@NonNull Context context, @NonNull IWifiManager service,
        @NonNull Looper looper) {
        mContext = context;
        mService = service;
        mLooper = looper;
        mTargetSdkVersion = context.getApplicationInfo().targetSdkVersion;
        updateVerboseLoggingEnabledFromService();
    }

    /**
     * Return a list of all the networks configured for the current foreground
     * user.
     *
     * Not all fields of WifiConfiguration are returned. Only the following
     * fields are filled in:
     * <ul>
     * <li>networkId</li>
     * <li>SSID</li>
     * <li>BSSID</li>
     * <li>priority</li>
     * <li>allowedProtocols</li>
     * <li>allowedKeyManagement</li>
     * <li>allowedAuthAlgorithms</li>
     * <li>allowedPairwiseCiphers</li>
     * <li>allowedGroupCiphers</li>
     * <li>status</li>
     * </ul>
     * @return a list of network configurations in the form of a list
     * of {@link WifiConfiguration} objects.
     *
     * @deprecated
     * a) See {@link WifiNetworkSpecifier.Builder#build()} for new
     * mechanism to trigger connection to a Wi-Fi network.
     * b) See {@link #addNetworkSuggestions(List)},
     * {@link #removeNetworkSuggestions(List)} for new API to add Wi-Fi networks for consideration
     * when auto-connecting to wifi.
     * <b>Compatibility Note:</b> For applications targeting
     * {@link android.os.Build.VERSION_CODES#Q} or above, this API will always fail and return an
     * empty list.
     * <p>
     * Deprecation Exemptions:
     * <ul>
     * <li>Device Owner (DO), Profile Owner (PO) and system apps will have access to the full list.
     * <li>Callers with Carrier privilege will receive a restricted list only containing
     * configurations which they created.
     * </ul>
     */
    @Deprecated
    @RequiresPermission(allOf = {ACCESS_FINE_LOCATION, ACCESS_WIFI_STATE})
    public List<WifiConfiguration> getConfiguredNetworks() {
        try {
            ParceledListSlice<WifiConfiguration> parceledList =
                    mService.getConfiguredNetworks(mContext.getOpPackageName(),
                            mContext.getAttributionTag(), false);
            if (parceledList == null) {
                return Collections.emptyList();
            }
            return parceledList.getList();
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Return a list of all the networks previously configured by the calling app. Can
     * be called by Device Owner (DO), Profile Owner (PO), Callers with Carrier privilege and
     * system apps.
     *
     * @return a list of network configurations in the form of a list
     * of {@link WifiConfiguration} objects.
     * @throws {@link java.lang.SecurityException} if the caller is allowed to call this API
     */
    @RequiresPermission(ACCESS_WIFI_STATE)
    @NonNull
    public List<WifiConfiguration> getCallerConfiguredNetworks() {
        try {
            ParceledListSlice<WifiConfiguration> parceledList =
                    mService.getConfiguredNetworks(mContext.getOpPackageName(),
                            mContext.getAttributionTag(), true);
            if (parceledList == null) {
                return Collections.emptyList();
            }
            return parceledList.getList();
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }


    /** @hide */
    @SystemApi
    @RequiresPermission(allOf = {ACCESS_FINE_LOCATION, ACCESS_WIFI_STATE, READ_WIFI_CREDENTIAL})
    public List<WifiConfiguration> getPrivilegedConfiguredNetworks() {
        try {
            ParceledListSlice<WifiConfiguration> parceledList =
                    mService.getPrivilegedConfiguredNetworks(mContext.getOpPackageName(),
                            mContext.getAttributionTag());
            if (parceledList == null) {
                return Collections.emptyList();
            }
            return parceledList.getList();
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Returns a list of all matching WifiConfigurations of PasspointConfiguration for a given list
     * of ScanResult.
     *
     * An empty list will be returned when no PasspointConfiguration are installed or if no
     * PasspointConfiguration match the ScanResult.
     *
     * @param scanResults a list of scanResult that represents the BSSID
     * @return List that consists of {@link WifiConfiguration} and corresponding scanResults per
     * network type({@link #PASSPOINT_HOME_NETWORK} and {@link #PASSPOINT_ROAMING_NETWORK}).
     * @hide
     */
    @SystemApi
    @RequiresPermission(anyOf = {
            android.Manifest.permission.NETWORK_SETTINGS,
            android.Manifest.permission.NETWORK_SETUP_WIZARD
    })
    @NonNull
    public List<Pair<WifiConfiguration, Map<Integer, List<ScanResult>>>> getAllMatchingWifiConfigs(
            @NonNull List<ScanResult> scanResults) {
        List<Pair<WifiConfiguration, Map<Integer, List<ScanResult>>>> configs = new ArrayList<>();
        try {
            Map<String, Map<Integer, List<ScanResult>>> results =
                    mService.getAllMatchingPasspointProfilesForScanResults(scanResults);
            if (results.isEmpty()) {
                return configs;
            }
            List<WifiConfiguration> wifiConfigurations =
                    mService.getWifiConfigsForPasspointProfiles(
                            new ArrayList<>(results.keySet()));
            for (WifiConfiguration configuration : wifiConfigurations) {
                Map<Integer, List<ScanResult>> scanResultsPerNetworkType =
                        results.get(configuration.getProfileKey());
                if (scanResultsPerNetworkType != null) {
                    configs.add(Pair.create(configuration, scanResultsPerNetworkType));
                }
            }
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }

        return configs;
    }

    /**
     * Retrieve a list of {@link WifiConfiguration} for available {@link WifiNetworkSuggestion}
     * matching the given list of {@link ScanResult}.
     *
     * An available {@link WifiNetworkSuggestion} must satisfy:
     * <ul>
     * <li> Matching one of the {@link ScanResult} from the given list.
     * <li> and {@link WifiNetworkSuggestion.Builder#setIsUserAllowedToManuallyConnect(boolean)} set
     * to true.
     * </ul>
     *
     * @param scanResults a list of scanResult.
     * @return a list of @link WifiConfiguration} for available {@link WifiNetworkSuggestion}
     * @hide
     */
    @SystemApi
    @RequiresPermission(anyOf = {
            android.Manifest.permission.NETWORK_SETTINGS,
            android.Manifest.permission.NETWORK_SETUP_WIZARD
    })
    @NonNull
    public List<WifiConfiguration> getWifiConfigForMatchedNetworkSuggestionsSharedWithUser(
            @NonNull List<ScanResult> scanResults) {
        try {
            return mService.getWifiConfigForMatchedNetworkSuggestionsSharedWithUser(scanResults);
        } catch (RemoteException e) {
            throw e.rethrowAsRuntimeException();
        }
    }

    /**
     * Returns a list of unique Hotspot 2.0 OSU (Online Sign-Up) providers associated with a given
     * list of ScanResult.
     *
     * An empty list will be returned if no match is found.
     *
     * @param scanResults a list of ScanResult
     * @return Map that consists {@link OsuProvider} and a list of matching {@link ScanResult}
     * @hide
     */
    @SystemApi
    @RequiresPermission(anyOf = {
            android.Manifest.permission.NETWORK_SETTINGS,
            android.Manifest.permission.NETWORK_SETUP_WIZARD
    })
    @NonNull
    public Map<OsuProvider, List<ScanResult>> getMatchingOsuProviders(
            @Nullable List<ScanResult> scanResults) {
        if (scanResults == null) {
            return new HashMap<>();
        }
        try {
            return mService.getMatchingOsuProviders(scanResults);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Returns the matching Passpoint R2 configurations for given OSU (Online Sign-Up) providers.
     *
     * Given a list of OSU providers, this only returns OSU providers that already have Passpoint R2
     * configurations in the device.
     * An empty map will be returned when there is no matching Passpoint R2 configuration for the
     * given OsuProviders.
     *
     * @param osuProviders a set of {@link OsuProvider}
     * @return Map that consists of {@link OsuProvider} and matching {@link PasspointConfiguration}.
     * @hide
     */
    @SystemApi
    @RequiresPermission(anyOf = {
            android.Manifest.permission.NETWORK_SETTINGS,
            android.Manifest.permission.NETWORK_SETUP_WIZARD
    })
    @NonNull
    public Map<OsuProvider, PasspointConfiguration> getMatchingPasspointConfigsForOsuProviders(
            @NonNull Set<OsuProvider> osuProviders) {
        try {
            return mService.getMatchingPasspointConfigsForOsuProviders(
                    new ArrayList<>(osuProviders));
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Add a new network description to the set of configured networks.
     * The {@code networkId} field of the supplied configuration object
     * is ignored.
     * <p/>
     * The new network will be marked DISABLED by default. To enable it,
     * called {@link #enableNetwork}.
     *
     * @param config the set of variables that describe the configuration,
     *            contained in a {@link WifiConfiguration} object.
     *            If the {@link WifiConfiguration} has an Http Proxy set
     *            the calling app must be System, or be provisioned as the Profile or Device Owner.
     * @return the ID of the newly created network description. This is used in
     *         other operations to specified the network to be acted upon.
     *         Returns {@code -1} on failure.
     *
     * @deprecated
     * a) See {@link WifiNetworkSpecifier.Builder#build()} for new
     * mechanism to trigger connection to a Wi-Fi network.
     * b) See {@link #addNetworkSuggestions(List)},
     * {@link #removeNetworkSuggestions(List)} for new API to add Wi-Fi networks for consideration
     * when auto-connecting to wifi.
     * <b>Compatibility Note:</b> For applications targeting
     * {@link android.os.Build.VERSION_CODES#Q} or above, this API will always fail and return
     * {@code -1}.
     * <p>
     * Deprecation Exemptions:
     * <ul>
     * <li>Device Owner (DO), Profile Owner (PO) and system apps.
     * </ul>
     */
    @Deprecated
    public int addNetwork(WifiConfiguration config) {
        if (config == null) {
            return -1;
        }
        config.networkId = -1;
        return addOrUpdateNetwork(config);
    }

    /**
     * This is a new version of {@link #addNetwork(WifiConfiguration)} which returns more detailed
     * failure codes. The usage of this API is limited to Device Owner (DO), Profile Owner (PO),
     * system app, and privileged apps.
     * <p>
     * Add a new network description to the set of configured networks. The {@code networkId}
     * field of the supplied configuration object is ignored. The new network will be marked
     * DISABLED by default. To enable it, call {@link #enableNetwork}.
     * <p>
     * @param config the set of variables that describe the configuration,
     *            contained in a {@link WifiConfiguration} object.
     *            If the {@link WifiConfiguration} has an Http Proxy set
     *            the calling app must be System, or be provisioned as the Profile or Device Owner.
     * @return A {@link AddNetworkResult} Object.
     * @throws {@link SecurityException} if the calling app is not a Device Owner (DO),
     *                           Profile Owner (PO), system app, or a privileged app that has one of
     *                           the permissions required by this API.
     * @throws {@link IllegalArgumentException} if the input configuration is null.
     */
    @RequiresPermission(anyOf = {
            android.Manifest.permission.NETWORK_SETTINGS,
            android.Manifest.permission.NETWORK_STACK,
            android.Manifest.permission.NETWORK_SETUP_WIZARD,
            android.Manifest.permission.NETWORK_MANAGED_PROVISIONING
    })
    @NonNull
    public AddNetworkResult addNetworkPrivileged(@NonNull WifiConfiguration config) {
        if (config == null) throw new IllegalArgumentException("config cannot be null");
        config.networkId = -1;
        try {
            return mService.addOrUpdateNetworkPrivileged(config, mContext.getOpPackageName());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Provides the results of a call to {@link #addNetworkPrivileged(WifiConfiguration)}
     */
    public static final class AddNetworkResult implements Parcelable {
        /**
         * The operation has completed successfully.
         */
        public static final int STATUS_SUCCESS = 0;
        /**
         * The operation has failed due to an unknown reason.
         */
        public static final int STATUS_FAILURE_UNKNOWN = 1;
        /**
         * The calling app does not have permission to call this API.
         */
        public static final int STATUS_NO_PERMISSION = 2;
        /**
         * Generic failure code for adding a passpoint network.
         */
        public static final int STATUS_ADD_PASSPOINT_FAILURE = 3;
        /**
         * Generic failure code for adding a non-passpoint network.
         */
        public static final int STATUS_ADD_WIFI_CONFIG_FAILURE = 4;
        /**
         * The network configuration is invalid.
         */
        public static final int STATUS_INVALID_CONFIGURATION = 5;
        /**
         * The calling app has no permission to modify the configuration.
         */
        public static final int STATUS_NO_PERMISSION_MODIFY_CONFIG = 6;
        /**
         * The calling app has no permission to modify the proxy setting.
         */
        public static final int STATUS_NO_PERMISSION_MODIFY_PROXY_SETTING = 7;
        /**
         * The calling app has no permission to modify the MAC randomization setting.
         */
        public static final int STATUS_NO_PERMISSION_MODIFY_MAC_RANDOMIZATION = 8;
        /**
         * Internal failure in updating network keys..
         */
        public static final int STATUS_FAILURE_UPDATE_NETWORK_KEYS = 9;
        /**
         * The enterprise network is missing either the root CA or domain name.
         */
        public static final int STATUS_INVALID_CONFIGURATION_ENTERPRISE = 10;

        /** @hide */
        @IntDef(prefix = { "STATUS_" }, value = {
                STATUS_SUCCESS,
                STATUS_FAILURE_UNKNOWN,
                STATUS_NO_PERMISSION,
                STATUS_ADD_PASSPOINT_FAILURE,
                STATUS_ADD_WIFI_CONFIG_FAILURE,
                STATUS_INVALID_CONFIGURATION,
                STATUS_NO_PERMISSION_MODIFY_CONFIG,
                STATUS_NO_PERMISSION_MODIFY_PROXY_SETTING,
                STATUS_NO_PERMISSION_MODIFY_MAC_RANDOMIZATION,
                STATUS_FAILURE_UPDATE_NETWORK_KEYS,
                STATUS_INVALID_CONFIGURATION_ENTERPRISE,
        })
        @Retention(RetentionPolicy.SOURCE)
        public @interface AddNetworkStatusCode {}

        @Override
        public int describeContents() {
            return 0;
        }

        @Override
        public void writeToParcel(@NonNull Parcel dest, int flags) {
            dest.writeInt(statusCode);
            dest.writeInt(networkId);
        }

        /** Implement the Parcelable interface */
        public static final @android.annotation.NonNull Creator<AddNetworkResult> CREATOR =
                new Creator<AddNetworkResult>() {
                    public AddNetworkResult createFromParcel(Parcel in) {
                        return new AddNetworkResult(in.readInt(), in.readInt());
                    }

                    public AddNetworkResult[] newArray(int size) {
                        return new AddNetworkResult[size];
                    }
                };

        /**
         * One of the {@code STATUS_} values. If the operation is successful this field
         * will be set to {@code STATUS_SUCCESS}.
         */
        public final @AddNetworkStatusCode int statusCode;
        /**
         * The identifier of the added network, which could be used in other operations. This field
         * will be set to {@code -1} if the operation failed.
         */
        public final int networkId;

        public AddNetworkResult(@AddNetworkStatusCode int statusCode, int networkId) {
            this.statusCode = statusCode;
            this.networkId = networkId;
        }
    }

    /**
     * Update the network description of an existing configured network.
     *
     * @param config the set of variables that describe the configuration,
     *            contained in a {@link WifiConfiguration} object. It may
     *            be sparse, so that only the items that are being changed
     *            are non-<code>null</code>. The {@code networkId} field
     *            must be set to the ID of the existing network being updated.
     *            If the {@link WifiConfiguration} has an Http Proxy set
     *            the calling app must be System, or be provisioned as the Profile or Device Owner.
     * @return Returns the {@code networkId} of the supplied
     *         {@code WifiConfiguration} on success.
     *         <br/>
     *         Returns {@code -1} on failure, including when the {@code networkId}
     *         field of the {@code WifiConfiguration} does not refer to an
     *         existing network.
     *
     * @deprecated
     * a) See {@link WifiNetworkSpecifier.Builder#build()} for new
     * mechanism to trigger connection to a Wi-Fi network.
     * b) See {@link #addNetworkSuggestions(List)},
     * {@link #removeNetworkSuggestions(List)} for new API to add Wi-Fi networks for consideration
     * when auto-connecting to wifi.
     * <b>Compatibility Note:</b> For applications targeting
     * {@link android.os.Build.VERSION_CODES#Q} or above, this API will always fail and return
     * {@code -1}.
     * <p>
     * Deprecation Exemptions:
     * <ul>
     * <li>Device Owner (DO), Profile Owner (PO) and system apps.
     * </ul>
     */
    @Deprecated
    public int updateNetwork(WifiConfiguration config) {
        if (config == null || config.networkId < 0) {
            return -1;
        }
        return addOrUpdateNetwork(config);
    }

    /**
     * Internal method for doing the RPC that creates a new network description
     * or updates an existing one.
     *
     * @param config The possibly sparse object containing the variables that
     *         are to set or updated in the network description.
     * @return the ID of the network on success, {@code -1} on failure.
     */
    private int addOrUpdateNetwork(WifiConfiguration config) {
        try {
            return mService.addOrUpdateNetwork(config, mContext.getOpPackageName());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Interface for indicating user selection from the list of networks presented in the
     * {@link NetworkRequestMatchCallback#onMatch(List)}.
     *
     * The platform will implement this callback and pass it along with the
     * {@link NetworkRequestMatchCallback#onUserSelectionCallbackRegistration(
     * NetworkRequestUserSelectionCallback)}. The UI component handling
     * {@link NetworkRequestMatchCallback} will invoke {@link #select(WifiConfiguration)} or
     * {@link #reject()} to return the user's selection back to the platform via this callback.
     * @hide
     */
    @SystemApi
    public interface NetworkRequestUserSelectionCallback {
        /**
         * User selected this network to connect to.
         * @param wifiConfiguration WifiConfiguration object corresponding to the network
         *                          user selected.
         */
        @SuppressLint("CallbackMethodName")
        default void select(@NonNull WifiConfiguration wifiConfiguration) {}

        /**
         * User rejected the app's request.
         */
        @SuppressLint("CallbackMethodName")
        default void reject() {}
    }

    /**
     * Interface for network request callback. Should be implemented by applications and passed when
     * calling {@link #registerNetworkRequestMatchCallback(Executor,
     * WifiManager.NetworkRequestMatchCallback)}.
     *
     * This is meant to be implemented by a UI component to present the user with a list of networks
     * matching the app's request. The user is allowed to pick one of these networks to connect to
     * or reject the request by the app.
     * @hide
     */
    @SystemApi
    public interface NetworkRequestMatchCallback {
        /**
         * Invoked to register a callback to be invoked to convey user selection. The callback
         * object passed in this method is to be invoked by the UI component after the service sends
         * a list of matching scan networks using {@link #onMatch(List)} and user picks a network
         * from that list.
         *
         * @param userSelectionCallback Callback object to send back the user selection.
         */
        default void onUserSelectionCallbackRegistration(
                @NonNull NetworkRequestUserSelectionCallback userSelectionCallback) {}

        /**
         * Invoked when the active network request is aborted, either because
         * <li> The app released the request, OR</li>
         * <li> Request was overridden by a new request</li>
         * This signals the end of processing for the current request and should stop the UI
         * component. No subsequent calls from the UI component will be handled by the platform.
         */
        default void onAbort() {}

        /**
         * Invoked when a network request initiated by an app matches some networks in scan results.
         * This may be invoked multiple times for a single network request as the platform finds new
         * matching networks in scan results.
         *
         * @param scanResults List of {@link ScanResult} objects corresponding to the networks
         *                    matching the request.
         */
        default void onMatch(@NonNull List<ScanResult> scanResults) {}

        /**
         * Invoked on a successful connection with the network that the user selected
         * via {@link NetworkRequestUserSelectionCallback}.
         *
         * @param wifiConfiguration WifiConfiguration object corresponding to the network that the
         *                          user selected.
         */
        default void onUserSelectionConnectSuccess(@NonNull WifiConfiguration wifiConfiguration) {}

        /**
         * Invoked on failure to establish connection with the network that the user selected
         * via {@link NetworkRequestUserSelectionCallback}.
         *
         * @param wifiConfiguration WifiConfiguration object corresponding to the network
         *                          user selected.
         */
        default void onUserSelectionConnectFailure(@NonNull WifiConfiguration wifiConfiguration) {}
    }

    /**
     * Callback proxy for NetworkRequestUserSelectionCallback objects.
     * @hide
     */
    private class NetworkRequestUserSelectionCallbackProxy implements
            NetworkRequestUserSelectionCallback {
        private final INetworkRequestUserSelectionCallback mCallback;

        NetworkRequestUserSelectionCallbackProxy(
                INetworkRequestUserSelectionCallback callback) {
            mCallback = callback;
        }

        @Override
        public void select(@NonNull WifiConfiguration wifiConfiguration) {
            if (mVerboseLoggingEnabled) {
                Log.v(TAG, "NetworkRequestUserSelectionCallbackProxy: select "
                        + "wificonfiguration: " + wifiConfiguration);
            }
            try {
                mCallback.select(wifiConfiguration);
            } catch (RemoteException e) {
                Log.e(TAG, "Failed to invoke onSelected", e);
                throw e.rethrowFromSystemServer();
            }
        }

        @Override
        public void reject() {
            if (mVerboseLoggingEnabled) {
                Log.v(TAG, "NetworkRequestUserSelectionCallbackProxy: reject");
            }
            try {
                mCallback.reject();
            } catch (RemoteException e) {
                Log.e(TAG, "Failed to invoke onRejected", e);
                throw e.rethrowFromSystemServer();
            }
        }
    }

    /**
     * Callback proxy for NetworkRequestMatchCallback objects.
     * @hide
     */
    private class NetworkRequestMatchCallbackProxy extends INetworkRequestMatchCallback.Stub {
        private final Executor mExecutor;
        private final NetworkRequestMatchCallback mCallback;

        NetworkRequestMatchCallbackProxy(Executor executor, NetworkRequestMatchCallback callback) {
            mExecutor = executor;
            mCallback = callback;
        }

        @Override
        public void onUserSelectionCallbackRegistration(
                INetworkRequestUserSelectionCallback userSelectionCallback) {
            if (mVerboseLoggingEnabled) {
                Log.v(TAG, "NetworkRequestMatchCallbackProxy: "
                        + "onUserSelectionCallbackRegistration callback: " + userSelectionCallback);
            }
            Binder.clearCallingIdentity();
            mExecutor.execute(() -> {
                mCallback.onUserSelectionCallbackRegistration(
                        new NetworkRequestUserSelectionCallbackProxy(userSelectionCallback));
            });
        }

        @Override
        public void onAbort() {
            if (mVerboseLoggingEnabled) {
                Log.v(TAG, "NetworkRequestMatchCallbackProxy: onAbort");
            }
            Binder.clearCallingIdentity();
            mExecutor.execute(() -> {
                mCallback.onAbort();
            });
        }

        @Override
        public void onMatch(List<ScanResult> scanResults) {
            if (mVerboseLoggingEnabled) {
                Log.v(TAG, "NetworkRequestMatchCallbackProxy: onMatch scanResults: "
                        + scanResults);
            }
            Binder.clearCallingIdentity();
            mExecutor.execute(() -> {
                mCallback.onMatch(scanResults);
            });
        }

        @Override
        public void onUserSelectionConnectSuccess(WifiConfiguration wifiConfiguration) {
            if (mVerboseLoggingEnabled) {
                Log.v(TAG, "NetworkRequestMatchCallbackProxy: onUserSelectionConnectSuccess "
                        + " wificonfiguration: " + wifiConfiguration);
            }
            Binder.clearCallingIdentity();
            mExecutor.execute(() -> {
                mCallback.onUserSelectionConnectSuccess(wifiConfiguration);
            });
        }

        @Override
        public void onUserSelectionConnectFailure(WifiConfiguration wifiConfiguration) {
            if (mVerboseLoggingEnabled) {
                Log.v(TAG, "NetworkRequestMatchCallbackProxy: onUserSelectionConnectFailure"
                        + " wificonfiguration: " + wifiConfiguration);
            }
            Binder.clearCallingIdentity();
            mExecutor.execute(() -> {
                mCallback.onUserSelectionConnectFailure(wifiConfiguration);
            });
        }
    }

    /**
     * Registers a callback for NetworkRequest matches. See {@link NetworkRequestMatchCallback}.
     * Caller can unregister a previously registered callback using
     * {@link #unregisterNetworkRequestMatchCallback(NetworkRequestMatchCallback)}
     * <p>
     * Applications should have the
     * {@link android.Manifest.permission#NETWORK_SETTINGS} permission. Callers
     * without the permission will trigger a {@link java.lang.SecurityException}.
     * <p>
     *
     * @param executor The Executor on whose thread to execute the callbacks of the {@code callback}
     *                 object.
     * @param callback Callback for network match events to register.
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
    public void registerNetworkRequestMatchCallback(@NonNull @CallbackExecutor Executor executor,
            @NonNull NetworkRequestMatchCallback callback) {
        if (executor == null) throw new IllegalArgumentException("executor cannot be null");
        if (callback == null) throw new IllegalArgumentException("callback cannot be null");
        Log.v(TAG, "registerNetworkRequestMatchCallback: callback=" + callback
                + ", executor=" + executor);

        try {
            synchronized (sNetworkRequestMatchCallbackMap) {
                INetworkRequestMatchCallback.Stub binderCallback =
                        new NetworkRequestMatchCallbackProxy(executor, callback);
                sNetworkRequestMatchCallbackMap.put(System.identityHashCode(callback),
                        binderCallback);
                mService.registerNetworkRequestMatchCallback(binderCallback);
            }
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Unregisters a callback for NetworkRequest matches. See {@link NetworkRequestMatchCallback}.
     * <p>
     * Applications should have the
     * {@link android.Manifest.permission#NETWORK_SETTINGS} permission. Callers
     * without the permission will trigger a {@link java.lang.SecurityException}.
     * <p>
     *
     * @param callback Callback for network match events to unregister.
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
    public void unregisterNetworkRequestMatchCallback(
            @NonNull NetworkRequestMatchCallback callback) {
        if (callback == null) throw new IllegalArgumentException("callback cannot be null");
        Log.v(TAG, "unregisterNetworkRequestMatchCallback: callback=" + callback);

        try {
            synchronized (sNetworkRequestMatchCallbackMap) {
                int callbackIdentifier = System.identityHashCode(callback);
                if (!sNetworkRequestMatchCallbackMap.contains(callbackIdentifier)) {
                    Log.w(TAG, "Unknown external callback " + callbackIdentifier);
                    return;
                }
                mService.unregisterNetworkRequestMatchCallback(
                        sNetworkRequestMatchCallbackMap.get(callbackIdentifier));
                sNetworkRequestMatchCallbackMap.remove(callbackIdentifier);
            }
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Privileged API to revoke all app state from wifi stack (equivalent to operations that the
     * wifi stack performs to clear state for an app that was uninstalled.
     * This removes:
     * <li> All saved networks or passpoint profiles added by the app </li>
     * <li> All previously approved peer to peer connection to access points initiated by the app
     * using {@link WifiNetworkSpecifier}</li>
     * <li> All network suggestions and approvals provided using {@link WifiNetworkSuggestion}</li>
     * <p>
     * @param targetAppUid UID of the app.
     * @param targetAppPackageName Package name of the app.
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
    public void removeAppState(int targetAppUid, @NonNull String targetAppPackageName) {
        try {
            mService.removeAppState(targetAppUid, targetAppPackageName);
        } catch (RemoteException e) {
            throw e.rethrowAsRuntimeException();
        }
    }

    /**
     * Provide a list of network suggestions to the device. See {@link WifiNetworkSuggestion}
     * for a detailed explanation of the parameters.
     * When the device decides to connect to one of the provided network suggestions, platform sends
     * a directed broadcast {@link #ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION} to the app if
     * the network was created with
     * {@link WifiNetworkSuggestion.Builder#setIsAppInteractionRequired(boolean)} flag set and the
     * app holds {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION}
     * permission.
     *<p>
     * NOTE:
     * <li> These networks are just a suggestion to the platform. The platform will ultimately
     * decide on which network the device connects to. </li>
     * <li> When an app is uninstalled or disabled, all its suggested networks are discarded.
     * If the device is currently connected to a suggested network which is being removed then the
     * device will disconnect from that network.</li>
     * <li> If user reset network settings, all added suggestions will be discarded. Apps can use
     * {@link #getNetworkSuggestions()} to check if their suggestions are in the device.</li>
     * <li> In-place modification of existing suggestions are allowed.
     * <li> If the provided suggestions include any previously provided suggestions by the app,
     * previous suggestions will be updated.</li>
     * <li>If one of the provided suggestions marks a previously unmetered suggestion as metered and
     * the device is currently connected to that suggested network, then the device will disconnect
     * from that network. The system will immediately re-evaluate all the network candidates
     * and possibly reconnect back to the same suggestion. This disconnect is to make sure that any
     * traffic flowing over unmetered networks isn't accidentally continued over a metered network.
     * </li>
     * </li>
     *
     * @param networkSuggestions List of network suggestions provided by the app.
     * @return Status code for the operation. One of the STATUS_NETWORK_SUGGESTIONS_ values.
     * @throws {@link SecurityException} if the caller is missing required permissions.
     * @see WifiNetworkSuggestion#equals(Object)
     */
    @RequiresPermission(android.Manifest.permission.CHANGE_WIFI_STATE)
    public @NetworkSuggestionsStatusCode int addNetworkSuggestions(
            @NonNull List<WifiNetworkSuggestion> networkSuggestions) {
        try {
            return mService.addNetworkSuggestions(
                    networkSuggestions, mContext.getOpPackageName(), mContext.getAttributionTag());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Remove some or all of the network suggestions that were previously provided by the app.
     * If one of the suggestions being removed was used to establish connection to the current
     * network, then the device will immediately disconnect from that network.
     *
     * See {@link WifiNetworkSuggestion} for a detailed explanation of the parameters.
     * See {@link WifiNetworkSuggestion#equals(Object)} for the equivalence evaluation used.
     *
     * @param networkSuggestions List of network suggestions to be removed. Pass an empty list
     *                           to remove all the previous suggestions provided by the app.
     * @return Status code for the operation. One of the STATUS_NETWORK_SUGGESTIONS_ values.
     * Any matching suggestions are removed from the device and will not be considered for any
     * further connection attempts.
     */
    @RequiresPermission(android.Manifest.permission.CHANGE_WIFI_STATE)
    public @NetworkSuggestionsStatusCode int removeNetworkSuggestions(
            @NonNull List<WifiNetworkSuggestion> networkSuggestions) {
        try {
            return mService.removeNetworkSuggestions(
                    networkSuggestions, mContext.getOpPackageName());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Get all network suggestions provided by the calling app.
     * See {@link #addNetworkSuggestions(List)}
     * See {@link #removeNetworkSuggestions(List)}
     * @return a list of {@link WifiNetworkSuggestion}
     */
    @RequiresPermission(ACCESS_WIFI_STATE)
    public @NonNull List<WifiNetworkSuggestion> getNetworkSuggestions() {
        try {
            return mService.getNetworkSuggestions(mContext.getOpPackageName());
        } catch (RemoteException e) {
            throw e.rethrowAsRuntimeException();
        }
    }

    /**
     * Returns the max number of network suggestions that are allowed per app on the device.
     * @see #addNetworkSuggestions(List)
     * @see #removeNetworkSuggestions(List)
     */
    public int getMaxNumberOfNetworkSuggestionsPerApp() {
        return getMaxNumberOfNetworkSuggestionsPerApp(
                mContext.getSystemService(ActivityManager.class).isLowRamDevice());
    }

    /** @hide */
    public static int getMaxNumberOfNetworkSuggestionsPerApp(boolean isLowRamDevice) {
        return isLowRamDevice
                ? NETWORK_SUGGESTIONS_MAX_PER_APP_LOW_RAM
                : NETWORK_SUGGESTIONS_MAX_PER_APP_HIGH_RAM;
    }

    /**
     * Add or update a Passpoint configuration.  The configuration provides a credential
     * for connecting to Passpoint networks that are operated by the Passpoint
     * service provider specified in the configuration.
     *
     * Each configuration is uniquely identified by a unique key which depends on the contents of
     * the configuration. This allows the caller to install multiple profiles with the same FQDN
     * (Fully qualified domain name). Therefore, in order to update an existing profile, it is
     * first required to remove it using {@link WifiManager#removePasspointConfiguration(String)}.
     * Otherwise, a new profile will be added with both configuration.
     *
     * Deprecated for general app usage - except DO/PO apps.
     * See {@link WifiNetworkSuggestion.Builder#setPasspointConfig(PasspointConfiguration)} to
     * create a passpoint suggestion.
     * See {@link #addNetworkSuggestions(List)}, {@link #removeNetworkSuggestions(List)} for new
     * API to add Wi-Fi networks for consideration when auto-connecting to wifi.
     * <b>Compatibility Note:</b> For applications targeting
     * {@link android.os.Build.VERSION_CODES#R} or above, this API will always fail and throw
     * {@link IllegalArgumentException}.
     * <p>
     * Deprecation Exemptions:
     * <ul>
     * <li>Device Owner (DO), Profile Owner (PO) and system apps.
     * </ul>
     *
     * @param config The Passpoint configuration to be added
     * @throws IllegalArgumentException if configuration is invalid or Passpoint is not enabled on
     *                                  the device.
     */
    public void addOrUpdatePasspointConfiguration(PasspointConfiguration config) {
        try {
            if (!mService.addOrUpdatePasspointConfiguration(config, mContext.getOpPackageName())) {
                throw new IllegalArgumentException();
            }
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Remove the Passpoint configuration identified by its FQDN (Fully Qualified Domain Name) added
     * by the caller.
     *
     * @param fqdn The FQDN of the Passpoint configuration added by the caller to be removed
     * @throws IllegalArgumentException if no configuration is associated with the given FQDN or
     *                                  Passpoint is not enabled on the device.
     * @deprecated This will be non-functional in a future release.
     */
    @Deprecated
    @RequiresPermission(anyOf = {
            android.Manifest.permission.NETWORK_SETTINGS,
            android.Manifest.permission.NETWORK_CARRIER_PROVISIONING
    })
    public void removePasspointConfiguration(String fqdn) {
        try {
            if (!mService.removePasspointConfiguration(fqdn, mContext.getOpPackageName())) {
                throw new IllegalArgumentException();
            }
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Return the list of installed Passpoint configurations added by the caller.
     *
     * An empty list will be returned when no configurations are installed.
     *
     * @return A list of {@link PasspointConfiguration} added by the caller
     * @deprecated This will be non-functional in a future release.
     */
    @Deprecated
    @RequiresPermission(anyOf = {
            android.Manifest.permission.NETWORK_SETTINGS,
            android.Manifest.permission.NETWORK_SETUP_WIZARD
    })
    public List<PasspointConfiguration> getPasspointConfigurations() {
        try {
            return mService.getPasspointConfigurations(mContext.getOpPackageName());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Query for a Hotspot 2.0 release 2 OSU icon file. An {@link #ACTION_PASSPOINT_ICON} intent
     * will be broadcasted once the request is completed.  The presence of the intent extra
     * {@link #EXTRA_ICON} will indicate the result of the request.
     * A missing intent extra {@link #EXTRA_ICON} will indicate a failure.
     *
     * @param bssid The BSSID of the AP
     * @param fileName Name of the icon file (remote file) to query from the AP
     *
     * @throws UnsupportedOperationException if Passpoint is not enabled on the device.
     * @hide
     */
    public void queryPasspointIcon(long bssid, String fileName) {
        try {
            mService.queryPasspointIcon(bssid, fileName);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Match the currently associated network against the SP matching the given FQDN
     * @param fqdn FQDN of the SP
     * @return ordinal [HomeProvider, RoamingProvider, Incomplete, None, Declined]
     * @hide
     */
    public int matchProviderWithCurrentNetwork(String fqdn) {
        try {
            return mService.matchProviderWithCurrentNetwork(fqdn);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Remove the specified network from the list of configured networks.
     * This may result in the asynchronous delivery of state change
     * events.
     *
     * Applications are not allowed to remove networks created by other
     * applications.
     *
     * @param netId the ID of the network as returned by {@link #addNetwork} or {@link
     *        #getConfiguredNetworks}.
     * @return {@code true} if the operation succeeded
     *
     * @deprecated
     * a) See {@link WifiNetworkSpecifier.Builder#build()} for new
     * mechanism to trigger connection to a Wi-Fi network.
     * b) See {@link #addNetworkSuggestions(List)},
     * {@link #removeNetworkSuggestions(List)} for new API to add Wi-Fi networks for consideration
     * when auto-connecting to wifi.
     * <b>Compatibility Note:</b> For applications targeting
     * {@link android.os.Build.VERSION_CODES#Q} or above, this API will always fail and return
     * {@code false}.
     * <p>
     * Deprecation Exemptions:
     * <ul>
     * <li>Device Owner (DO), Profile Owner (PO) and system apps.
     * </ul>
     */
    @Deprecated
    public boolean removeNetwork(int netId) {
        try {
            return mService.removeNetwork(netId, mContext.getOpPackageName());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Remove all configured networks that were not created by the calling app. Can only
     * be called by a Device Owner (DO) app.
     *
     * @return {@code true} if at least one network is removed, {@code false} otherwise
     * @throws {@link java.lang.SecurityException} if the caller is not a Device Owner app
     */
    @RequiresPermission(android.Manifest.permission.CHANGE_WIFI_STATE)
    public boolean removeNonCallerConfiguredNetworks() {
        try {
            return mService.removeNonCallerConfiguredNetworks(mContext.getOpPackageName());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }
    /**
     * Allow a previously configured network to be associated with. If
     * <code>attemptConnect</code> is true, an attempt to connect to the selected
     * network is initiated. This may result in the asynchronous delivery
     * of state change events.
     * <p>
     * <b>Note:</b> Network communication may not use Wi-Fi even if Wi-Fi is connected;
     * traffic may instead be sent through another network, such as cellular data,
     * Bluetooth tethering, or Ethernet. For example, traffic will never use a
     * Wi-Fi network that does not provide Internet access (e.g. a wireless
     * printer), if another network that does offer Internet access (e.g.
     * cellular data) is available. Applications that need to ensure that their
     * network traffic uses Wi-Fi should use APIs such as
     * {@link Network#bindSocket(java.net.Socket)},
     * {@link Network#openConnection(java.net.URL)}, or
     * {@link ConnectivityManager#bindProcessToNetwork} to do so.
     *
     * Applications are not allowed to enable networks created by other
     * applications.
     *
     * @param netId the ID of the network as returned by {@link #addNetwork} or {@link
     *        #getConfiguredNetworks}.
     * @param attemptConnect The way to select a particular network to connect to is specify
     *        {@code true} for this parameter.
     * @return {@code true} if the operation succeeded
     *
     * @deprecated
     * a) See {@link WifiNetworkSpecifier.Builder#build()} for new
     * mechanism to trigger connection to a Wi-Fi network.
     * b) See {@link #addNetworkSuggestions(List)},
     * {@link #removeNetworkSuggestions(List)} for new API to add Wi-Fi networks for consideration
     * when auto-connecting to wifi.
     * <b>Compatibility Note:</b> For applications targeting
     * {@link android.os.Build.VERSION_CODES#Q} or above, this API will always fail and return
     * {@code false}.
     * Deprecation Exemptions:
     * <ul>
     * <li>Device Owner (DO), Profile Owner (PO) and system apps.
     * </ul>
     */
    @Deprecated
    public boolean enableNetwork(int netId, boolean attemptConnect) {
        try {
            return mService.enableNetwork(netId, attemptConnect, mContext.getOpPackageName());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Disable a configured network. The specified network will not be
     * a candidate for associating. This may result in the asynchronous
     * delivery of state change events.
     *
     * Applications are not allowed to disable networks created by other
     * applications.
     *
     * @param netId the ID of the network as returned by {@link #addNetwork} or {@link
     *        #getConfiguredNetworks}.
     * @return {@code true} if the operation succeeded
     *
     * @deprecated
     * a) See {@link WifiNetworkSpecifier.Builder#build()} for new
     * mechanism to trigger connection to a Wi-Fi network.
     * b) See {@link #addNetworkSuggestions(List)},
     * {@link #removeNetworkSuggestions(List)} for new API to add Wi-Fi networks for consideration
     * when auto-connecting to wifi.
     * <b>Compatibility Note:</b> For applications targeting
     * {@link android.os.Build.VERSION_CODES#Q} or above, this API will always fail and return
     * {@code false}.
     * <p>
     * Deprecation Exemptions:
     * <ul>
     * <li>Device Owner (DO), Profile Owner (PO) and system apps.
     * </ul>
     */
    @Deprecated
    public boolean disableNetwork(int netId) {
        try {
            return mService.disableNetwork(netId, mContext.getOpPackageName());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Disassociate from the currently active access point. This may result
     * in the asynchronous delivery of state change events.
     * @return {@code true} if the operation succeeded
     *
     * @deprecated
     * a) See {@link WifiNetworkSpecifier.Builder#build()} for new
     * mechanism to trigger connection to a Wi-Fi network.
     * b) See {@link #addNetworkSuggestions(List)},
     * {@link #removeNetworkSuggestions(List)} for new API to add Wi-Fi networks for consideration
     * when auto-connecting to wifi.
     * <b>Compatibility Note:</b> For applications targeting
     * {@link android.os.Build.VERSION_CODES#Q} or above, this API will always fail and return
     * {@code false}.
     * <p>
     * Deprecation Exemptions:
     * <ul>
     * <li>Device Owner (DO), Profile Owner (PO) and system apps.
     * </ul>
     */
    @Deprecated
    public boolean disconnect() {
        try {
            return mService.disconnect(mContext.getOpPackageName());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Reconnect to the currently active access point, if we are currently
     * disconnected. This may result in the asynchronous delivery of state
     * change events.
     * @return {@code true} if the operation succeeded
     *
     * @deprecated
     * a) See {@link WifiNetworkSpecifier.Builder#build()} for new
     * mechanism to trigger connection to a Wi-Fi network.
     * b) See {@link #addNetworkSuggestions(List)},
     * {@link #removeNetworkSuggestions(List)} for new API to add Wi-Fi networks for consideration
     * when auto-connecting to wifi.
     * <b>Compatibility Note:</b> For applications targeting
     * {@link android.os.Build.VERSION_CODES#Q} or above, this API will always fail and return
     * {@code false}.
     * <p>
     * Deprecation Exemptions:
     * <ul>
     * <li>Device Owner (DO), Profile Owner (PO) and system apps.
     * </ul>
     */
    @Deprecated
    public boolean reconnect() {
        try {
            return mService.reconnect(mContext.getOpPackageName());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Reconnect to the currently active access point, even if we are already
     * connected. This may result in the asynchronous delivery of state
     * change events.
     * @return {@code true} if the operation succeeded
     *
     * @deprecated
     * a) See {@link WifiNetworkSpecifier.Builder#build()} for new
     * mechanism to trigger connection to a Wi-Fi network.
     * b) See {@link #addNetworkSuggestions(List)},
     * {@link #removeNetworkSuggestions(List)} for new API to add Wi-Fi networks for consideration
     * when auto-connecting to wifi.
     * <b>Compatibility Note:</b> For applications targeting
     * {@link android.os.Build.VERSION_CODES#Q} or above, this API will always return false.
     */
    @Deprecated
    public boolean reassociate() {
        try {
            return mService.reassociate(mContext.getOpPackageName());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Check that the supplicant daemon is responding to requests.
     * @return {@code true} if we were able to communicate with the supplicant and
     * it returned the expected response to the PING message.
     * @deprecated Will return the output of {@link #isWifiEnabled()} instead.
     */
    @Deprecated
    public boolean pingSupplicant() {
        return isWifiEnabled();
    }

    /** TODO(b/181364583): Convert all of these to 1 << X form. */
    /** @hide */
    public static final long WIFI_FEATURE_INFRA            = 0x0001L;  // Basic infrastructure mode
    /** @hide */
    public static final long WIFI_FEATURE_PASSPOINT        = 0x0004L;  // Support for GAS/ANQP
    /** @hide */
    public static final long WIFI_FEATURE_P2P              = 0x0008L;  // Wifi-Direct
    /** @hide */
    public static final long WIFI_FEATURE_MOBILE_HOTSPOT   = 0x0010L;  // Soft AP
    /** @hide */
    public static final long WIFI_FEATURE_SCANNER          = 0x0020L;  // WifiScanner APIs
    /** @hide */
    public static final long WIFI_FEATURE_AWARE            = 0x0040L;  // Wi-Fi AWare networking
    /** @hide */
    public static final long WIFI_FEATURE_D2D_RTT          = 0x0080L;  // Device-to-device RTT
    /** @hide */
    public static final long WIFI_FEATURE_D2AP_RTT         = 0x0100L;  // Device-to-AP RTT
    /** @hide */
    public static final long WIFI_FEATURE_BATCH_SCAN       = 0x0200L;  // Batched Scan (deprecated)
    /** @hide */
    public static final long WIFI_FEATURE_PNO              = 0x0400L;  // Preferred network offload
    /** @hide */
    public static final long WIFI_FEATURE_ADDITIONAL_STA   = 0x0800L;  // (unused)
    /** @hide */
    public static final long WIFI_FEATURE_TDLS             = 0x1000L;  // Tunnel directed link setup
    /** @hide */
    public static final long WIFI_FEATURE_TDLS_OFFCHANNEL  = 0x2000L;  // TDLS off channel
    /** @hide */
    public static final long WIFI_FEATURE_EPR              = 0x4000L;  // Enhanced power reporting
    /** @hide */
    public static final long WIFI_FEATURE_AP_STA           = 0x8000L;  // AP STA Concurrency
    /** @hide */
    public static final long WIFI_FEATURE_LINK_LAYER_STATS = 0x10000L; // Link layer stats
    /** @hide */
    public static final long WIFI_FEATURE_LOGGER           = 0x20000L; // WiFi Logger
    /** @hide */
    public static final long WIFI_FEATURE_HAL_EPNO         = 0x40000L; // Enhanced PNO
    /** @hide */
    public static final long WIFI_FEATURE_RSSI_MONITOR     = 0x80000L; // RSSI Monitor
    /** @hide */
    public static final long WIFI_FEATURE_MKEEP_ALIVE      = 0x100000L; // mkeep_alive
    /** @hide */
    public static final long WIFI_FEATURE_CONFIG_NDO       = 0x200000L; // ND offload
    /** @hide */
    public static final long WIFI_FEATURE_TRANSMIT_POWER   = 0x400000L; // Capture transmit power
    /** @hide */
    public static final long WIFI_FEATURE_CONTROL_ROAMING  = 0x800000L; // Control firmware roaming
    /** @hide */
    public static final long WIFI_FEATURE_IE_WHITELIST     = 0x1000000L; // Probe IE white listing
    /** @hide */
    public static final long WIFI_FEATURE_SCAN_RAND        = 0x2000000L; // Random MAC & Probe seq
    /** @hide */
    public static final long WIFI_FEATURE_TX_POWER_LIMIT   = 0x4000000L; // Set Tx power limit
    /** @hide */
    public static final long WIFI_FEATURE_WPA3_SAE         = 0x8000000L; // WPA3-Personal SAE
    /** @hide */
    public static final long WIFI_FEATURE_WPA3_SUITE_B     = 0x10000000L; // WPA3-Enterprise Suite-B
    /** @hide */
    public static final long WIFI_FEATURE_OWE              = 0x20000000L; // Enhanced Open
    /** @hide */
    public static final long WIFI_FEATURE_LOW_LATENCY      = 0x40000000L; // Low Latency modes
    /** @hide */
    public static final long WIFI_FEATURE_DPP              = 0x80000000L; // DPP (Easy-Connect)
    /** @hide */
    public static final long WIFI_FEATURE_P2P_RAND_MAC     = 0x100000000L; // Random P2P MAC
    /** @hide */
    public static final long WIFI_FEATURE_CONNECTED_RAND_MAC    = 0x200000000L; // Random STA MAC
    /** @hide */
    public static final long WIFI_FEATURE_AP_RAND_MAC      = 0x400000000L; // Random AP MAC
    /** @hide */
    public static final long WIFI_FEATURE_MBO              = 0x800000000L; // MBO Support
    /** @hide */
    public static final long WIFI_FEATURE_OCE              = 0x1000000000L; // OCE Support
    /** @hide */
    public static final long WIFI_FEATURE_WAPI             = 0x2000000000L; // WAPI

    /** @hide */
    public static final long WIFI_FEATURE_FILS_SHA256      = 0x4000000000L; // FILS-SHA256

    /** @hide */
    public static final long WIFI_FEATURE_FILS_SHA384      = 0x8000000000L; // FILS-SHA384

    /** @hide */
    public static final long WIFI_FEATURE_SAE_PK           = 0x10000000000L; // SAE-PK

    /** @hide */
    public static final long WIFI_FEATURE_STA_BRIDGED_AP   = 0x20000000000L; // STA + Bridged AP

    /** @hide */
    public static final long WIFI_FEATURE_BRIDGED_AP       = 0x40000000000L; // Bridged AP

    /** @hide */
    public static final long WIFI_FEATURE_INFRA_60G        = 0x80000000000L; // 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 = 0x100000000000L;

    /**
     * Support for 2 STA's for the make before break concurrency.
     * @hide
     */
    public static final long WIFI_FEATURE_ADDITIONAL_STA_MBB = 0x200000000000L;

    /**
     * Support for 2 STA's for the restricted connection + internet connection concurrency.
     * @hide
     */
    public static final long WIFI_FEATURE_ADDITIONAL_STA_RESTRICTED = 0x400000000000L;

    /**
     * DPP (Easy-Connect) Enrollee Responder mode support
     * @hide
     */
    public static final long WIFI_FEATURE_DPP_ENROLLEE_RESPONDER = 0x800000000000L;

    /**
     * Passpoint Terms and Conditions feature support
     * @hide
     */
    public static final long WIFI_FEATURE_PASSPOINT_TERMS_AND_CONDITIONS = 0x1000000000000L;

     /** @hide */
    public static final long WIFI_FEATURE_SAE_H2E          = 0x2000000000000L; // Hash-to-Element

     /** @hide */
    public static final long WIFI_FEATURE_WFD_R2           = 0x4000000000000L; // Wi-Fi Display R2

    /**
     * RFC 7542 decorated identity support
     * @hide */
    public static final long WIFI_FEATURE_DECORATED_IDENTITY = 0x8000000000000L;

    private long getSupportedFeatures() {
        try {
            return mService.getSupportedFeatures();
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    private boolean isFeatureSupported(long feature) {
        return (getSupportedFeatures() & feature) == feature;
    }

    /**
     * @return true if this adapter supports Passpoint
     * @hide
     */
    public boolean isPasspointSupported() {
        return isFeatureSupported(WIFI_FEATURE_PASSPOINT);
    }

    /**
     * @return true if this adapter supports WifiP2pManager (Wi-Fi Direct)
     */
    public boolean isP2pSupported() {
        return isFeatureSupported(WIFI_FEATURE_P2P);
    }

    /**
     * @return true if this adapter supports portable Wi-Fi hotspot
     * @hide
     */
    @SystemApi
    public boolean isPortableHotspotSupported() {
        return isFeatureSupported(WIFI_FEATURE_MOBILE_HOTSPOT);
    }

    /**
     * @return true if this adapter supports WifiScanner APIs
     * @hide
     */
    @SystemApi
    public boolean isWifiScannerSupported() {
        return isFeatureSupported(WIFI_FEATURE_SCANNER);
    }

    /**
     * @return true if this adapter supports Neighbour Awareness Network APIs
     * @hide
     */
    public boolean isWifiAwareSupported() {
        return isFeatureSupported(WIFI_FEATURE_AWARE);
    }

    /**
     * Query whether or not the device supports Station (STA) + Access point (AP) concurrency.
     *
     * @return true if this device supports STA + AP concurrency, false otherwise.
     */
    public boolean isStaApConcurrencySupported() {
        return isFeatureSupported(WIFI_FEATURE_AP_STA);
    }

    /**
     * Query whether or not the device supports concurrent station (STA) connections for local-only
     * connections using {@link WifiNetworkSpecifier}.
     *
     * @return true if this device supports multiple STA concurrency for this use-case, false
     * otherwise.
     */
    public boolean isStaConcurrencyForLocalOnlyConnectionsSupported() {
        return isFeatureSupported(WIFI_FEATURE_ADDITIONAL_STA_LOCAL_ONLY);
    }

    /**
     * Query whether or not the device supports concurrent station (STA) connections for
     * make-before-break wifi to wifi switching.
     *
     * Note: This is an internal feature which is not available to apps.
     *
     * @return true if this device supports multiple STA concurrency for this use-case, false
     * otherwise.
     */
    public boolean isMakeBeforeBreakWifiSwitchingSupported() {
        return isFeatureSupported(WIFI_FEATURE_ADDITIONAL_STA_MBB);
    }

    /**
     * Query whether or not the device supports concurrent station (STA) connections for restricted
     * connections using {@link WifiNetworkSuggestion.Builder#setOemPaid(boolean)} /
     * {@link WifiNetworkSuggestion.Builder#setOemPrivate(boolean)}.
     *
     * @return true if this device supports multiple STA concurrency for this use-case, false
     * otherwise.
     * @hide
     */
    @SystemApi
    public boolean isStaConcurrencyForRestrictedConnectionsSupported() {
        return isFeatureSupported(WIFI_FEATURE_ADDITIONAL_STA_RESTRICTED);
    }

    /**
     * @deprecated Please use {@link android.content.pm.PackageManager#hasSystemFeature(String)}
     * with {@link android.content.pm.PackageManager#FEATURE_WIFI_RTT} and
     * {@link android.content.pm.PackageManager#FEATURE_WIFI_AWARE}.
     *
     * @return true if this adapter supports Device-to-device RTT
     * @hide
     */
    @Deprecated
    @SystemApi
    public boolean isDeviceToDeviceRttSupported() {
        return isFeatureSupported(WIFI_FEATURE_D2D_RTT);
    }

    /**
     * @deprecated Please use {@link android.content.pm.PackageManager#hasSystemFeature(String)}
     * with {@link android.content.pm.PackageManager#FEATURE_WIFI_RTT}.
     *
     * @return true if this adapter supports Device-to-AP RTT
     */
    @Deprecated
    public boolean isDeviceToApRttSupported() {
        return isFeatureSupported(WIFI_FEATURE_D2AP_RTT);
    }

    /**
     * @return true if this adapter supports offloaded connectivity scan
     */
    public boolean isPreferredNetworkOffloadSupported() {
        return isFeatureSupported(WIFI_FEATURE_PNO);
    }

    /**
     * @return true if this adapter supports Tunnel Directed Link Setup
     */
    public boolean isTdlsSupported() {
        return isFeatureSupported(WIFI_FEATURE_TDLS);
    }

    /**
     * @return true if this adapter supports Off Channel Tunnel Directed Link Setup
     * @hide
     */
    public boolean isOffChannelTdlsSupported() {
        return isFeatureSupported(WIFI_FEATURE_TDLS_OFFCHANNEL);
    }

    /**
     * @return true if this adapter supports advanced power/performance counters
     */
    public boolean isEnhancedPowerReportingSupported() {
        return isFeatureSupported(WIFI_FEATURE_LINK_LAYER_STATS);
    }

    /**
     * @return true if this device supports connected MAC randomization.
     * @hide
     */
    @SystemApi
    public boolean isConnectedMacRandomizationSupported() {
        return isFeatureSupported(WIFI_FEATURE_CONNECTED_RAND_MAC);
    }

    /**
     * @return true if this device supports AP MAC randomization.
     * @hide
     */
    @SystemApi
    public boolean isApMacRandomizationSupported() {
        return isFeatureSupported(WIFI_FEATURE_AP_RAND_MAC);
    }

    /**
     * Check if the chipset supports 2.4GHz band.
     * @return {@code true} if supported, {@code false} otherwise.
     */
    public boolean is24GHzBandSupported() {
        try {
            return mService.is24GHzBandSupported();
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Check if the chipset supports 5GHz band.
     * @return {@code true} if supported, {@code false} otherwise.
     */
    public boolean is5GHzBandSupported() {
        try {
            return mService.is5GHzBandSupported();
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Check if the chipset supports the 60GHz frequency band.
     *
     * @return {@code true} if supported, {@code false} otherwise.
     */
    @RequiresApi(Build.VERSION_CODES.S)
    public boolean is60GHzBandSupported() {
        try {
            return mService.is60GHzBandSupported();
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Check if the chipset supports 6GHz band.
     * @return {@code true} if supported, {@code false} otherwise.
     */
    public boolean is6GHzBandSupported() {
        try {
            return mService.is6GHzBandSupported();
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Check if the chipset supports a certain Wi-Fi standard.
     * @param standard the IEEE 802.11 standard to check on.
     *        valid values from {@link ScanResult}'s {@code WIFI_STANDARD_}
     * @return {@code true} if supported, {@code false} otherwise.
     */
    public boolean isWifiStandardSupported(@WifiAnnotations.WifiStandard int standard) {
        try {
            return mService.isWifiStandardSupported(standard);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Query whether or not the device supports concurrency of Station (STA) + multiple access
     * points (AP) (where the APs bridged together).
     *
     * See {@link SoftApConfiguration.Builder#setBands(int[])}
     * or {@link SoftApConfiguration.Builder#setChannels(android.util.SparseIntArray)} to configure
     * bridged AP when the bridged AP supported.
     *
     * @return true if this device supports concurrency of STA + multiple APs which are bridged
     *         together, false otherwise.
     */
    public boolean isStaBridgedApConcurrencySupported() {
        return isFeatureSupported(WIFI_FEATURE_STA_BRIDGED_AP);
    }

    /**
     * Query whether or not the device supports multiple Access point (AP) which are bridged
     * together.
     *
     * See {@link SoftApConfiguration.Builder#setBands(int[])}
     * or {@link SoftApConfiguration.Builder#setChannels(android.util.SparseIntArray)} to configure
     * bridged AP when the bridged AP supported.
     *
     * @return true if this device supports concurrency of multiple AP which bridged together,
     *         false otherwise.
     */
    public boolean isBridgedApConcurrencySupported() {
        return isFeatureSupported(WIFI_FEATURE_BRIDGED_AP);
    }

    /**
     * Interface for Wi-Fi activity energy info listener. Should be implemented by applications and
     * set when calling {@link WifiManager#getWifiActivityEnergyInfoAsync}.
     *
     * @hide
     */
    @SystemApi
    public interface OnWifiActivityEnergyInfoListener {
        /**
         * Called when Wi-Fi activity energy info is available.
         * Note: this listener is triggered at most once for each call to
         * {@link #getWifiActivityEnergyInfoAsync}.
         *
         * @param info the latest {@link WifiActivityEnergyInfo}, or null if unavailable.
         */
        void onWifiActivityEnergyInfo(@Nullable WifiActivityEnergyInfo info);
    }

    private static class OnWifiActivityEnergyInfoProxy
            extends IOnWifiActivityEnergyInfoListener.Stub {
        private final Object mLock = new Object();
        @Nullable @GuardedBy("mLock") private Executor mExecutor;
        @Nullable @GuardedBy("mLock") private OnWifiActivityEnergyInfoListener mListener;

        OnWifiActivityEnergyInfoProxy(Executor executor,
                OnWifiActivityEnergyInfoListener listener) {
            mExecutor = executor;
            mListener = listener;
        }

        @Override
        public void onWifiActivityEnergyInfo(WifiActivityEnergyInfo info) {
            Executor executor;
            OnWifiActivityEnergyInfoListener listener;
            synchronized (mLock) {
                if (mExecutor == null || mListener == null) {
                    return;
                }
                executor = mExecutor;
                listener = mListener;
                // null out to allow garbage collection, prevent triggering listener more than once
                mExecutor = null;
                mListener = null;
            }
            Binder.clearCallingIdentity();
            executor.execute(() -> listener.onWifiActivityEnergyInfo(info));
        }
    }

    /**
     * Request to get the current {@link WifiActivityEnergyInfo} asynchronously.
     * Note: This method will return null if {@link #isEnhancedPowerReportingSupported()} returns
     * false.
     *
     * @param executor the executor that the listener will be invoked on
     * @param listener the listener that will receive the {@link WifiActivityEnergyInfo} object
     *                 when it becomes available. The listener will be triggered at most once for
     *                 each call to this method.
     *
     * @hide
     */
    @SystemApi
    @RequiresPermission(ACCESS_WIFI_STATE)
    public void getWifiActivityEnergyInfoAsync(
            @NonNull @CallbackExecutor Executor executor,
            @NonNull OnWifiActivityEnergyInfoListener listener) {
        Objects.requireNonNull(executor, "executor cannot be null");
        Objects.requireNonNull(listener, "listener cannot be null");
        try {
            mService.getWifiActivityEnergyInfoAsync(
                    new OnWifiActivityEnergyInfoProxy(executor, listener));
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Request a scan for access points. Returns immediately. The availability
     * of the results is made known later by means of an asynchronous event sent
     * on completion of the scan.
     * <p>
     * To initiate a Wi-Fi scan, declare the
     * {@link android.Manifest.permission#CHANGE_WIFI_STATE}
     * permission in the manifest, and perform these steps:
     * </p>
     * <ol style="1">
     * <li>Invoke the following method:
     * {@code ((WifiManager) getSystemService(WIFI_SERVICE)).startScan()}</li>
     * <li>
     * Register a BroadcastReceiver to listen to
     * {@code SCAN_RESULTS_AVAILABLE_ACTION}.</li>
     * <li>When a broadcast is received, call:
     * {@code ((WifiManager) getSystemService(WIFI_SERVICE)).getScanResults()}</li>
     * </ol>
     * @return {@code true} if the operation succeeded, i.e., the scan was initiated.
     * @deprecated The ability for apps to trigger scan requests will be removed in a future
     * release.
     */
    @Deprecated
    public boolean startScan() {
        return startScan(null);
    }

    /** @hide */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS)
    public boolean startScan(WorkSource workSource) {
        try {
            String packageName = mContext.getOpPackageName();
            String attributionTag = mContext.getAttributionTag();
            return mService.startScan(packageName, attributionTag);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * WPS has been deprecated from Client mode operation.
     *
     * @return null
     * @hide
     * @deprecated This API is deprecated
     */
    public String getCurrentNetworkWpsNfcConfigurationToken() {
        return null;
    }

    /**
     * Return dynamic information about the current Wi-Fi connection, if any is active.
     * <p>
     *
     * @return the Wi-Fi information, contained in {@link WifiInfo}.
     *
     * @deprecated Starting with {@link Build.VERSION_CODES#S}, WifiInfo retrieval is moved to
     * {@link ConnectivityManager} API surface. WifiInfo is attached in
     * {@link NetworkCapabilities#getTransportInfo()} which is available via callback in
     * {@link NetworkCallback#onCapabilitiesChanged(Network, NetworkCapabilities)} or on-demand from
     * {@link ConnectivityManager#getNetworkCapabilities(Network)}.
     *
     *</p>
     * Usage example:
     * <pre>{@code
     * final NetworkRequest request =
     *      new NetworkRequest.Builder()
     *      .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
     *      .build();
     * final ConnectivityManager connectivityManager =
     *      context.getSystemService(ConnectivityManager.class);
     * final NetworkCallback networkCallback = new NetworkCallback() {
     *      ...
     *      {@literal @}Override
     *      void onAvailable(Network network) {}
     *
     *      {@literal @}Override
     *      void onCapabilitiesChanged(Network network, NetworkCapabilities networkCapabilities) {
     *          WifiInfo wifiInfo = (WifiInfo) networkCapabilities.getTransportInfo();
     *      }
     *      // etc.
     * };
     * connectivityManager.requestNetwork(request, networkCallback); // For request
     * connectivityManager.registerNetworkCallback(request, networkCallback); // For listen
     * }</pre>
     * <p>
     * <b>Compatibility Notes:</b>
     * <li>Apps can continue using this API, however newer features
     * such as ability to mask out location sensitive data in WifiInfo will not be supported
     * via this API. </li>
     * <li>On devices supporting concurrent connections (indicated via
     * {@link #isStaConcurrencyForLocalOnlyConnectionsSupported()}, etc) this API will return
     * the details of the internet providing connection (if any) to all apps, except for the apps
     * that triggered the creation of the concurrent connection. For such apps, this API will return
     * the details of the connection they created. e.g. apps using {@link WifiNetworkSpecifier} will
     * trigger a concurrent connection on supported devices and hence this API will provide
     * details of their peer to peer connection (not the internet providing connection). This
     * is to maintain backwards compatibility with behavior on single STA devices.</li>
     * </p>
     */
    @Deprecated
    public WifiInfo getConnectionInfo() {
        try {
            return mService.getConnectionInfo(mContext.getOpPackageName(),
                    mContext.getAttributionTag());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Return the results of the latest access point scan.
     * @return the list of access points found in the most recent scan. An app must hold
     * {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION} permission
     * in order to get valid results.
     */
    public List<ScanResult> getScanResults() {
        try {
            return mService.getScanResults(mContext.getOpPackageName(),
                    mContext.getAttributionTag());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Get the filtered ScanResults which match the network configurations specified by the
     * {@code networkSuggestionsToMatch}. Suggestions which use {@link WifiConfiguration} use
     * SSID and the security type to match. Suggestions which use {@link PasspointConfigration}
     * use the matching rules of Hotspot 2.0.
     * @param networkSuggestionsToMatch The list of {@link WifiNetworkSuggestion} to match against.
     * These may or may not be suggestions which are installed on the device.
     * @param scanResults The scan results to be filtered. Optional - if not provided(empty list),
     * the Wi-Fi service will use the most recent scan results which the system has.
     * @return The map of {@link WifiNetworkSuggestion} to the list of {@link ScanResult}
     * corresponding to networks which match them.
     * @hide
     */
    @SystemApi
    @RequiresPermission(allOf = {ACCESS_FINE_LOCATION, ACCESS_WIFI_STATE})
    @NonNull
    public Map<WifiNetworkSuggestion, List<ScanResult>> getMatchingScanResults(
            @NonNull List<WifiNetworkSuggestion> networkSuggestionsToMatch,
            @Nullable List<ScanResult> scanResults) {
        if (networkSuggestionsToMatch == null) {
            throw new IllegalArgumentException("networkSuggestions must not be null.");
        }
        try {
            return mService.getMatchingScanResults(
                    networkSuggestionsToMatch, scanResults,
                    mContext.getOpPackageName(), mContext.getAttributionTag());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Set if scanning is always available.
     *
     * If set to {@code true}, apps can issue {@link #startScan} and fetch scan results
     * even when Wi-Fi is turned off.
     *
     * @param isAvailable true to enable, false to disable.
     * @hide
     * @see #isScanAlwaysAvailable()
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
    public void setScanAlwaysAvailable(boolean isAvailable) {
        try {
            mService.setScanAlwaysAvailable(isAvailable, mContext.getOpPackageName());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Check if scanning is always available.
     *
     * If this return {@code true}, apps can issue {@link #startScan} and fetch scan results
     * even when Wi-Fi is turned off.
     *
     * To change this setting, see {@link #ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE}.
     * @deprecated The ability for apps to trigger scan requests will be removed in a future
     * release.
     */
    @Deprecated
    public boolean isScanAlwaysAvailable() {
        try {
            return mService.isScanAlwaysAvailable();
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Tell the device to persist the current list of configured networks.
     * <p>
     * Note: It is possible for this method to change the network IDs of
     * existing networks. You should assume the network IDs can be different
     * after calling this method.
     *
     * @return {@code false}.
     * @deprecated There is no need to call this method -
     * {@link #addNetwork(WifiConfiguration)}, {@link #updateNetwork(WifiConfiguration)}
     * and {@link #removeNetwork(int)} already persist the configurations automatically.
     */
    @Deprecated
    public boolean saveConfiguration() {
        return false;
    }

    /**
     * Get the country code as resolved by the Wi-Fi framework.
     * The Wi-Fi framework uses multiple sources to resolve a country code
     * - in order of priority (high to low):
     * 1. Override country code set by {@link WifiManager#setOverrideCountryCode(String)}
     * and cleared by {@link WifiManager#clearOverrideCountryCode()}. Typically only used
     * for testing.
     * 2. Country code supplied by the telephony module. Typically provided from the
     * current network or from emergency cell information.
     * 3. Default country code set either via {@code ro.boot.wificountrycode}
     * or the {@link WifiManager#setDefaultCountryCode(String)}.
     *
     * @return the country code in ISO 3166 alpha-2 (2-letter) upper format,
     * or null if there is no country code configured.
     *
     * @hide
     */
    @Nullable
    @SystemApi
    @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
    public String getCountryCode() {
        try {
            return mService.getCountryCode();
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Set the override country code - may be used for testing. See the country code resolution
     * order and format in {@link #getCountryCode()}.
     * @param country A 2-Character alphanumeric country code.
     * @see #getCountryCode().
     *
     * @hide
     */
    @RequiresApi(Build.VERSION_CODES.S)
    @SystemApi
    @RequiresPermission(android.Manifest.permission.MANAGE_WIFI_COUNTRY_CODE)
    public void setOverrideCountryCode(@NonNull String country) {
        try {
            mService.setOverrideCountryCode(country);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * This clears the override country code which was previously set by
     * {@link WifiManager#setOverrideCountryCode(String)} method.
     * @see #getCountryCode().
     *
     * @hide
     */
    @RequiresApi(Build.VERSION_CODES.S)
    @SystemApi
    @RequiresPermission(android.Manifest.permission.MANAGE_WIFI_COUNTRY_CODE)
    public void clearOverrideCountryCode() {
        try {
            mService.clearOverrideCountryCode();
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }
    /**
     * Used to configure the default country code. See {@link #getCountryCode()} for resolution
     * method of the country code.
     * @param country A 2-character alphanumeric country code.
     * @see #getCountryCode().
     *
     * @hide
     */
    @RequiresApi(Build.VERSION_CODES.S)
    @SystemApi
    @RequiresPermission(android.Manifest.permission.MANAGE_WIFI_COUNTRY_CODE)
    public void setDefaultCountryCode(@NonNull String country) {
        try {
            mService.setDefaultCountryCode(country);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Return the DHCP-assigned addresses from the last successful DHCP request,
     * if any.
     *
     * @return the DHCP information
     *
     * @deprecated Use the methods on {@link android.net.LinkProperties} which can be obtained
     * either via {@link NetworkCallback#onLinkPropertiesChanged(Network, LinkProperties)} or
     * {@link ConnectivityManager#getLinkProperties(Network)}.
     *
     * <p>
     * <b>Compatibility Notes:</b>
     * <li>On devices supporting concurrent connections (indicated via
     * {@link #isStaConcurrencyForLocalOnlyConnectionsSupported()}, etc), this API will return
     * the details of the internet providing connection (if any) to all apps, except for the apps
     * that triggered the creation of the concurrent connection. For such apps, this API will return
     * the details of the connection they created. e.g. apps using {@link WifiNetworkSpecifier} will
     * trigger a concurrent connection on supported devices and hence this API will provide
     * details of their peer to peer connection (not the internet providing connection). This
     * is to maintain backwards compatibility with behavior on single STA devices.</li>
     * </p>
     */
    @Deprecated
    public DhcpInfo getDhcpInfo() {
        try {
            return mService.getDhcpInfo(mContext.getOpPackageName());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Enable or disable Wi-Fi.
     * <p>
     * Applications must have the {@link android.Manifest.permission#CHANGE_WIFI_STATE}
     * permission to toggle wifi.
     *
     * @param enabled {@code true} to enable, {@code false} to disable.
     * @return {@code false} if the request cannot be satisfied; {@code true} indicates that wifi is
     *         either already in the requested state, or in progress toward the requested state.
     * @throws  {@link java.lang.SecurityException} if the caller is missing required permissions.
     *
     * @deprecated Starting with Build.VERSION_CODES#Q, applications are not allowed to
     * enable/disable Wi-Fi.
     * <b>Compatibility Note:</b> For applications targeting
     * {@link android.os.Build.VERSION_CODES#Q} or above, this API will always fail and return
     * {@code false}. If apps are targeting an older SDK ({@link android.os.Build.VERSION_CODES#P}
     * or below), they can continue to use this API.
     * <p>
     * Deprecation Exemptions:
     * <ul>
     * <li>Device Owner (DO), Profile Owner (PO) and system apps.
     * </ul>
     */
    @Deprecated
    public boolean setWifiEnabled(boolean enabled) {
        try {
            return mService.setWifiEnabled(mContext.getOpPackageName(), enabled);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Abstract callback class for applications to receive updates about the Wi-Fi subsystem
     * restarting. The Wi-Fi subsystem can restart due to internal recovery mechanisms or via user
     * action.
     */
    @RequiresApi(Build.VERSION_CODES.S)
    public abstract static class SubsystemRestartTrackingCallback {
        private final SubsystemRestartTrackingCallback.SubsystemRestartCallbackProxy mProxy;

        public SubsystemRestartTrackingCallback() {
            mProxy = new SubsystemRestartTrackingCallback.SubsystemRestartCallbackProxy();
        }

        /*package*/ @NonNull
        SubsystemRestartTrackingCallback.SubsystemRestartCallbackProxy getProxy() {
            return mProxy;
        }

        /**
         * Indicates that the Wi-Fi subsystem is about to restart.
         */
        public abstract void onSubsystemRestarting();

        /**
         * Indicates that the Wi-Fi subsystem has restarted.
         */
        public abstract void onSubsystemRestarted();

        private static class SubsystemRestartCallbackProxy extends ISubsystemRestartCallback.Stub {
            private final Object mLock = new Object();
            @Nullable
            @GuardedBy("mLock")
            private Executor mExecutor;
            @Nullable
            @GuardedBy("mLock")
            private SubsystemRestartTrackingCallback mCallback;

            SubsystemRestartCallbackProxy() {
                mExecutor = null;
                mCallback = null;
            }

            /*package*/ void initProxy(@NonNull Executor executor,
                    @NonNull SubsystemRestartTrackingCallback callback) {
                synchronized (mLock) {
                    mExecutor = executor;
                    mCallback = callback;
                }
            }

            /*package*/ void cleanUpProxy() {
                synchronized (mLock) {
                    mExecutor = null;
                    mCallback = null;
                }
            }

            @Override
            public void onSubsystemRestarting() {
                Executor executor;
                SubsystemRestartTrackingCallback callback;
                synchronized (mLock) {
                    executor = mExecutor;
                    callback = mCallback;
                }
                if (executor == null || callback == null) {
                    return;
                }
                Binder.clearCallingIdentity();
                executor.execute(callback::onSubsystemRestarting);
            }

            @Override
            public void onSubsystemRestarted() {
                Executor executor;
                SubsystemRestartTrackingCallback callback;
                synchronized (mLock) {
                    executor = mExecutor;
                    callback = mCallback;
                }
                if (executor == null || callback == null) {
                    return;
                }
                Binder.clearCallingIdentity();
                executor.execute(callback::onSubsystemRestarted);
            }
        }
    }

    /**
     * Registers a {@link SubsystemRestartTrackingCallback} to listen to Wi-Fi subsystem restarts.
     * The subsystem may restart due to internal recovery mechanisms or via user action.
     *
     * @see #unregisterSubsystemRestartTrackingCallback(SubsystemRestartTrackingCallback)
     *
     * @param executor Executor to execute callback on
     * @param callback {@link SubsystemRestartTrackingCallback} to register
     */
    @RequiresApi(Build.VERSION_CODES.S)
    @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE)
    public void registerSubsystemRestartTrackingCallback(
            @NonNull @CallbackExecutor Executor executor,
            @NonNull SubsystemRestartTrackingCallback callback) {
        if (executor == null) throw new IllegalArgumentException("executor must not be null");
        if (callback == null) throw new IllegalArgumentException("callback must not be null");
        SubsystemRestartTrackingCallback.SubsystemRestartCallbackProxy proxy = callback.getProxy();
        proxy.initProxy(executor, callback);
        try {
            mService.registerSubsystemRestartCallback(proxy);
        } catch (RemoteException e) {
            proxy.cleanUpProxy();
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Unregisters a {@link SubsystemRestartTrackingCallback} registered with
     * {@link #registerSubsystemRestartTrackingCallback(Executor, SubsystemRestartTrackingCallback)}
     *
     * @param callback {@link SubsystemRestartTrackingCallback} to unregister
     */
    @RequiresApi(Build.VERSION_CODES.S)
    @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE)
    public void unregisterSubsystemRestartTrackingCallback(
            @NonNull SubsystemRestartTrackingCallback callback) {
        if (callback == null) throw new IllegalArgumentException("callback must not be null");
        SubsystemRestartTrackingCallback.SubsystemRestartCallbackProxy proxy = callback.getProxy();
        try {
            mService.unregisterSubsystemRestartCallback(proxy);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        } finally {
            proxy.cleanUpProxy();
        }
    }

    /**
     * Restart the Wi-Fi subsystem.
     *
     * Restarts the Wi-Fi subsystem - effectively disabling it and re-enabling it. All existing
     * Access Point (AP) associations are torn down, all Soft APs are disabled, Wi-Fi Direct and
     * Wi-Fi Aware are disabled.
     *
     * The state of the system after restart is not guaranteed to match its state before the API is
     * called - for instance the device may associate to a different Access Point (AP), and tethered
     * hotspots may or may not be restored.
     *
     * Use the
     * {@link #registerSubsystemRestartTrackingCallback(Executor, SubsystemRestartTrackingCallback)}
     * to track the operation.
     *
     * @hide
     */
    @RequiresApi(Build.VERSION_CODES.S)
    @SystemApi
    @RequiresPermission(android.Manifest.permission.RESTART_WIFI_SUBSYSTEM)
    public void restartWifiSubsystem() {
        try {
            mService.restartWifiSubsystem();
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Gets the Wi-Fi enabled state.
     * @return One of {@link #WIFI_STATE_DISABLED},
     *         {@link #WIFI_STATE_DISABLING}, {@link #WIFI_STATE_ENABLED},
     *         {@link #WIFI_STATE_ENABLING}, {@link #WIFI_STATE_UNKNOWN}
     * @see #isWifiEnabled()
     */
    public int getWifiState() {
        try {
            return mService.getWifiEnabledState();
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Return whether Wi-Fi is enabled or disabled.
     * @return {@code true} if Wi-Fi is enabled
     * @see #getWifiState()
     */
    public boolean isWifiEnabled() {
        return getWifiState() == WIFI_STATE_ENABLED;
    }

    /**
     * Calculates the level of the signal. This should be used any time a signal
     * is being shown.
     *
     * @param rssi The power of the signal measured in RSSI.
     * @param numLevels The number of levels to consider in the calculated level.
     * @return A level of the signal, given in the range of 0 to numLevels-1 (both inclusive).
     * @deprecated Callers should use {@link #calculateSignalLevel(int)} instead to get the
     * signal level using the system default RSSI thresholds, or otherwise compute the RSSI level
     * themselves using their own formula.
     */
    @Deprecated
    public static int calculateSignalLevel(int rssi, int numLevels) {
        if (rssi <= MIN_RSSI) {
            return 0;
        } else if (rssi >= MAX_RSSI) {
            return numLevels - 1;
        } else {
            float inputRange = (MAX_RSSI - MIN_RSSI);
            float outputRange = (numLevels - 1);
            return (int)((float)(rssi - MIN_RSSI) * outputRange / inputRange);
        }
    }

    /**
     * Given a raw RSSI, return the RSSI signal quality rating using the system default RSSI
     * quality rating thresholds.
     * @param rssi a raw RSSI value, in dBm, usually between -55 and -90
     * @return the RSSI signal quality rating, in the range
     * [0, {@link #getMaxSignalLevel()}], where 0 is the lowest (worst signal) RSSI
     * rating and {@link #getMaxSignalLevel()} is the highest (best signal) RSSI rating.
     */
    @IntRange(from = 0)
    public int calculateSignalLevel(int rssi) {
        try {
            return mService.calculateSignalLevel(rssi);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Get the system default maximum signal level.
     * This is the maximum RSSI level returned by {@link #calculateSignalLevel(int)}.
     */
    @IntRange(from = 0)
    public int getMaxSignalLevel() {
        return calculateSignalLevel(Integer.MAX_VALUE);
    }

    /**
     * Compares two signal strengths.
     *
     * @param rssiA The power of the first signal measured in RSSI.
     * @param rssiB The power of the second signal measured in RSSI.
     * @return Returns <0 if the first signal is weaker than the second signal,
     *         0 if the two signals have the same strength, and >0 if the first
     *         signal is stronger than the second signal.
     */
    public static int compareSignalLevel(int rssiA, int rssiB) {
        return rssiA - rssiB;
    }

    /**
     * Call allowing ConnectivityService to update WifiService with interface mode changes.
     *
     * @param ifaceName String name of the updated interface, or null to represent all interfaces
     * @param mode int representing the new mode, one of:
     *             {@link #IFACE_IP_MODE_TETHERED},
     *             {@link #IFACE_IP_MODE_LOCAL_ONLY},
     *             {@link #IFACE_IP_MODE_CONFIGURATION_ERROR},
     *             {@link #IFACE_IP_MODE_UNSPECIFIED}
     *
     * @hide
     */
    @SystemApi
    @RequiresPermission(anyOf = {
            android.Manifest.permission.NETWORK_STACK,
            NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK
    })
    public void updateInterfaceIpState(@Nullable String ifaceName, @IfaceIpMode int mode) {
        try {
            mService.updateInterfaceIpState(ifaceName, mode);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /* Wi-Fi/Cellular Coex */

    /**
     * Mandatory coex restriction flag for Wi-Fi Direct.
     *
     * @see #setCoexUnsafeChannels(List, int)
     *
     * @hide
     */
    @SystemApi
    @RequiresApi(Build.VERSION_CODES.S)
    public static final int COEX_RESTRICTION_WIFI_DIRECT = 0x1 << 0;

    /**
     * Mandatory coex restriction flag for SoftAP
     *
     * @see #setCoexUnsafeChannels(List, int)
     *
     * @hide
     */
    @SystemApi
    @RequiresApi(Build.VERSION_CODES.S)
    public static final int COEX_RESTRICTION_SOFTAP = 0x1 << 1;

    /**
     * Mandatory coex restriction flag for Wi-Fi Aware.
     *
     * @see #setCoexUnsafeChannels(List, int)
     *
     * @hide
     */
    @SystemApi
    @RequiresApi(Build.VERSION_CODES.S)
    public static final int COEX_RESTRICTION_WIFI_AWARE = 0x1 << 2;

    /** @hide */
    @RequiresApi(Build.VERSION_CODES.S)
    @Retention(RetentionPolicy.SOURCE)
    @IntDef(flag = true, prefix = {"COEX_RESTRICTION_"}, value = {
            COEX_RESTRICTION_WIFI_DIRECT,
            COEX_RESTRICTION_SOFTAP,
            COEX_RESTRICTION_WIFI_AWARE
    })
    public @interface CoexRestriction {}

    /**
     * @return {@code true} if the default coex algorithm is enabled. {@code false} otherwise.
     *
     * @hide
     */
    public boolean isDefaultCoexAlgorithmEnabled() {
        try {
            return mService.isDefaultCoexAlgorithmEnabled();
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Specify the list of {@link CoexUnsafeChannel} to propagate through the framework for
     * Wi-Fi/Cellular coex channel avoidance if the default algorithm is disabled via overlay
     * (i.e. config_wifiCoexDefaultAlgorithmEnabled = false). Otherwise do nothing.
     *
     * @param unsafeChannels List of {@link CoexUnsafeChannel} to avoid.
     * @param restrictions Bitmap of {@code COEX_RESTRICTION_*} constants specifying the mode
     *                     restrictions on the specified channels. If any restrictions are set,
     *                     then the supplied CoexUnsafeChannels should be completely avoided for
     *                     the specified modes, rather than be avoided with best effort.
     *
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.WIFI_UPDATE_COEX_UNSAFE_CHANNELS)
    @RequiresApi(Build.VERSION_CODES.S)
    public void setCoexUnsafeChannels(
            @NonNull List<CoexUnsafeChannel> unsafeChannels, @CoexRestriction int restrictions) {
        if (unsafeChannels == null) {
            throw new IllegalArgumentException("unsafeChannels must not be null");
        }
        try {
            mService.setCoexUnsafeChannels(unsafeChannels, restrictions);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Registers a CoexCallback to listen on the current CoexUnsafeChannels and restrictions being
     * used for Wi-Fi/cellular coex channel avoidance. The callback method
     * {@link CoexCallback#onCoexUnsafeChannelsChanged(List, int)} will be called immediately after
     * registration to return the current values.
     *
     * @param executor Executor to execute listener callback on
     * @param callback CoexCallback to register
     *
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.WIFI_ACCESS_COEX_UNSAFE_CHANNELS)
    @RequiresApi(Build.VERSION_CODES.S)
    public void registerCoexCallback(
            @NonNull @CallbackExecutor Executor executor, @NonNull CoexCallback callback) {
        if (executor == null) throw new IllegalArgumentException("executor must not be null");
        if (callback == null) throw new IllegalArgumentException("callback must not be null");
        CoexCallback.CoexCallbackProxy proxy = callback.getProxy();
        proxy.initProxy(executor, callback);
        try {
            mService.registerCoexCallback(proxy);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Unregisters a CoexCallback from listening on the current CoexUnsafeChannels and restrictions
     * being used for Wi-Fi/cellular coex channel avoidance.
     * @param callback CoexCallback to unregister
     *
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.WIFI_ACCESS_COEX_UNSAFE_CHANNELS)
    @RequiresApi(Build.VERSION_CODES.S)
    public void unregisterCoexCallback(@NonNull CoexCallback callback) {
        if (callback == null) throw new IllegalArgumentException("callback must not be null");
        CoexCallback.CoexCallbackProxy proxy = callback.getProxy();
        try {
            mService.unregisterCoexCallback(proxy);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        } finally {
            proxy.cleanUpProxy();
        }
    }

    /**
     * Abstract callback class for applications to receive updates about current CoexUnsafeChannels
     * for Wi-Fi/Cellular coex channel avoidance.
     *
     * @hide
     */
    @SystemApi
    @RequiresApi(Build.VERSION_CODES.S)
    public abstract static class CoexCallback {
        private final CoexCallbackProxy mCoexCallbackProxy;

        public CoexCallback() {
            if (!SdkLevel.isAtLeastS()) {
                throw new UnsupportedOperationException();
            }
            mCoexCallbackProxy = new CoexCallbackProxy();
        }

        /*package*/ @NonNull
        CoexCallbackProxy getProxy() {
            return mCoexCallbackProxy;
        }

        /**
         * This indicates the current CoexUnsafeChannels and restrictions calculated by the default
         * coex algorithm if config_wifiCoexDefaultAlgorithmEnabled is {@code true}. Otherwise, the
         * values will match the ones supplied to {@link #setCoexUnsafeChannels(List, int)}.
         *
         * @param unsafeChannels List of {@link CoexUnsafeChannel} to avoid.
         * @param restrictions Bitmap of {@code COEX_RESTRICTION_*} constants specifying the mode
         *                     restrictions on the specified channels. If any restrictions are set,
         *                     then the supplied CoexUnsafeChannels should be completely avoided for
         *                     the specified modes, rather than be avoided with best effort.
         */
        public abstract void onCoexUnsafeChannelsChanged(
                @NonNull List<CoexUnsafeChannel> unsafeChannels, @CoexRestriction int restrictions);

        /**
         * Callback proxy for CoexCallback objects.
         */
        private static class CoexCallbackProxy extends ICoexCallback.Stub {
            private final Object mLock = new Object();
            @Nullable @GuardedBy("mLock") private Executor mExecutor;
            @Nullable @GuardedBy("mLock") private CoexCallback mCallback;

            CoexCallbackProxy() {
                mExecutor = null;
                mCallback = null;
            }

            /*package*/ void initProxy(@NonNull Executor executor,
                    @NonNull CoexCallback callback) {
                synchronized (mLock) {
                    mExecutor = executor;
                    mCallback = callback;
                }
            }

            /*package*/ void cleanUpProxy() {
                synchronized (mLock) {
                    mExecutor = null;
                    mCallback = null;
                }
            }

            @Override
            public void onCoexUnsafeChannelsChanged(
                    @NonNull List<CoexUnsafeChannel> unsafeChannels,
                    @CoexRestriction int restrictions) {
                Executor executor;
                CoexCallback callback;
                synchronized (mLock) {
                    executor = mExecutor;
                    callback = mCallback;
                }
                if (executor == null || callback == null) {
                    return;
                }
                Binder.clearCallingIdentity();
                executor.execute(() ->
                        callback.onCoexUnsafeChannelsChanged(unsafeChannels, restrictions));
            }
        }
    }

    /**
     * Start Soft AP (hotspot) mode for tethering purposes with the specified configuration.
     * Note that starting Soft AP mode may disable station mode operation if the device does not
     * support concurrency.
     * @param wifiConfig SSID, security and channel details as part of WifiConfiguration, or null to
     *                   use the persisted Soft AP configuration that was previously set using
     *                   {@link #setWifiApConfiguration(WifiConfiguration)}.
     * @return {@code true} if the operation succeeded, {@code false} otherwise
     *
     * @hide
     */
    @RequiresPermission(anyOf = {
            android.Manifest.permission.NETWORK_STACK,
            NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK
    })
    public boolean startSoftAp(@Nullable WifiConfiguration wifiConfig) {
        try {
            return mService.startSoftAp(wifiConfig, mContext.getOpPackageName());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Start Soft AP (hotspot) mode for tethering purposes with the specified configuration.
     * Note that starting Soft AP mode may disable station mode operation if the device does not
     * support concurrency.
     * @param softApConfig A valid SoftApConfiguration specifying the configuration of the SAP,
     *                     or null to use the persisted Soft AP configuration that was previously
     *                     set using {@link #setSoftApConfiguration(softApConfiguration)}.
     * @return {@code true} if the operation succeeded, {@code false} otherwise
     *
     * @hide
     */
    @SystemApi
    @RequiresPermission(anyOf = {
            android.Manifest.permission.NETWORK_STACK,
            NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK
    })
    public boolean startTetheredHotspot(@Nullable SoftApConfiguration softApConfig) {
        try {
            return mService.startTetheredHotspot(softApConfig, mContext.getOpPackageName());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }


    /**
     * Stop SoftAp mode.
     * Note that stopping softap mode will restore the previous wifi mode.
     * @return {@code true} if the operation succeeds, {@code false} otherwise
     *
     * @hide
     */
    @SystemApi
    @RequiresPermission(anyOf = {
            android.Manifest.permission.NETWORK_STACK,
            NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK
    })
    public boolean stopSoftAp() {
        try {
            return mService.stopSoftAp();
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Request a local only hotspot that an application can use to communicate between co-located
     * devices connected to the created WiFi hotspot.  The network created by this method will not
     * have Internet access.  Each application can make a single request for the hotspot, but
     * multiple applications could be requesting the hotspot at the same time.  When multiple
     * applications have successfully registered concurrently, they will be sharing the underlying
     * hotspot. {@link LocalOnlyHotspotCallback#onStarted(LocalOnlyHotspotReservation)} is called
     * when the hotspot is ready for use by the application.
     * <p>
     * Each application can make a single active call to this method. The {@link
     * LocalOnlyHotspotCallback#onStarted(LocalOnlyHotspotReservation)} callback supplies the
     * requestor with a {@link LocalOnlyHotspotReservation} that contains a
     * {@link SoftApConfiguration} with the SSID, security type and credentials needed to connect
     * to the hotspot.  Communicating this information is up to the application.
     * <p>
     * If the LocalOnlyHotspot cannot be created, the {@link LocalOnlyHotspotCallback#onFailed(int)}
     * method will be called. Example failures include errors bringing up the network or if
     * there is an incompatible operating mode.  For example, if the user is currently using Wifi
     * Tethering to provide an upstream to another device, LocalOnlyHotspot will not start due to
     * an incompatible mode. The possible error codes include:
     * {@link LocalOnlyHotspotCallback#ERROR_NO_CHANNEL},
     * {@link LocalOnlyHotspotCallback#ERROR_GENERIC},
     * {@link LocalOnlyHotspotCallback#ERROR_INCOMPATIBLE_MODE} and
     * {@link LocalOnlyHotspotCallback#ERROR_TETHERING_DISALLOWED}.
     * <p>
     * Internally, requests will be tracked to prevent the hotspot from being torn down while apps
     * are still using it.  The {@link LocalOnlyHotspotReservation} object passed in the  {@link
     * LocalOnlyHotspotCallback#onStarted(LocalOnlyHotspotReservation)} call should be closed when
     * the LocalOnlyHotspot is no longer needed using {@link LocalOnlyHotspotReservation#close()}.
     * Since the hotspot may be shared among multiple applications, removing the final registered
     * application request will trigger the hotspot teardown.  This means that applications should
     * not listen to broadcasts containing wifi state to determine if the hotspot was stopped after
     * they are done using it. Additionally, once {@link LocalOnlyHotspotReservation#close()} is
     * called, applications will not receive callbacks of any kind.
     * <p>
     * Applications should be aware that the user may also stop the LocalOnlyHotspot through the
     * Settings UI; it is not guaranteed to stay up as long as there is a requesting application.
     * The requestors will be notified of this case via
     * {@link LocalOnlyHotspotCallback#onStopped()}.  Other cases may arise where the hotspot is
     * torn down (Emergency mode, etc).  Application developers should be aware that it can stop
     * unexpectedly, but they will receive a notification if they have properly registered.
     * <p>
     * Applications should also be aware that this network will be shared with other applications.
     * Applications are responsible for protecting their data on this network (e.g. TLS).
     * <p>
     * Applications need to have the following permissions to start LocalOnlyHotspot: {@link
     * android.Manifest.permission#CHANGE_WIFI_STATE} and {@link
     * android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION}.  Callers without
     * the permissions will trigger a {@link java.lang.SecurityException}.
     * <p>
     * @param callback LocalOnlyHotspotCallback for the application to receive updates about
     * operating status.
     * @param handler Handler to be used for callbacks.  If the caller passes a null Handler, the
     * main thread will be used.
     */
    @RequiresPermission(allOf = {
            android.Manifest.permission.CHANGE_WIFI_STATE,
            android.Manifest.permission.ACCESS_FINE_LOCATION})
    public void startLocalOnlyHotspot(LocalOnlyHotspotCallback callback,
            @Nullable Handler handler) {
        Executor executor = handler == null ? null : new HandlerExecutor(handler);
        startLocalOnlyHotspotInternal(null, executor, callback);
    }

    /**
     * Starts a local-only hotspot with a specific configuration applied. See
     * {@link #startLocalOnlyHotspot(LocalOnlyHotspotCallback, Handler)}.
     *
     * Applications need either {@link android.Manifest.permission#NETWORK_SETUP_WIZARD} or
     * {@link android.Manifest.permission#NETWORK_SETTINGS} to call this method.
     *
     * Since custom configuration settings may be incompatible with each other, the hotspot started
     * through this method cannot coexist with another hotspot created through
     * startLocalOnlyHotspot. 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, or null to use the main thread.
     * @param callback Callback object for updates about hotspot status, or null for no updates.
     * @hide
     */
    @SystemApi
    @RequiresPermission(anyOf = {
            android.Manifest.permission.NETWORK_SETTINGS,
            android.Manifest.permission.NETWORK_SETUP_WIZARD})
    public void startLocalOnlyHotspot(@NonNull SoftApConfiguration config,
            @Nullable Executor executor,
            @Nullable LocalOnlyHotspotCallback callback) {
        Objects.requireNonNull(config);
        startLocalOnlyHotspotInternal(config, executor, callback);
    }

    /**
     * Common implementation of both configurable and non-configurable LOHS.
     *
     * @param config App-specified configuration, or null. When present, additional privileges are
     *               required, and the hotspot cannot be shared with other clients.
     * @param executor Executor to run callback methods on, or null to use the main thread.
     * @param callback Callback object for updates about hotspot status, or null for no updates.
     */
    private void startLocalOnlyHotspotInternal(
            @Nullable SoftApConfiguration config,
            @Nullable Executor executor,
            @Nullable LocalOnlyHotspotCallback callback) {
        if (executor == null) {
            executor = mContext.getMainExecutor();
        }
        synchronized (mLock) {
            LocalOnlyHotspotCallbackProxy proxy =
                    new LocalOnlyHotspotCallbackProxy(this, executor, callback);
            try {
                String packageName = mContext.getOpPackageName();
                String featureId = mContext.getAttributionTag();
                int returnCode = mService.startLocalOnlyHotspot(proxy, packageName, featureId,
                        config);
                if (returnCode != LocalOnlyHotspotCallback.REQUEST_REGISTERED) {
                    // Send message to the proxy to make sure we call back on the correct thread
                    proxy.onHotspotFailed(returnCode);
                    return;
                }
                mLOHSCallbackProxy = proxy;
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
    }

    /**
     * Cancels a pending local only hotspot request.  This can be used by the calling application to
     * cancel the existing request if the provided callback has not been triggered.  Calling this
     * method will be equivalent to closing the returned LocalOnlyHotspotReservation, but it is not
     * explicitly required.
     * <p>
     * When cancelling this request, application developers should be aware that there may still be
     * outstanding local only hotspot requests and the hotspot may still start, or continue running.
     * Additionally, if a callback was registered, it will no longer be triggered after calling
     * cancel.
     *
     * @hide
     */
    @UnsupportedAppUsage
    public void cancelLocalOnlyHotspotRequest() {
        synchronized (mLock) {
            stopLocalOnlyHotspot();
        }
    }

    /**
     *  Method used to inform WifiService that the LocalOnlyHotspot is no longer needed.  This
     *  method is used by WifiManager to release LocalOnlyHotspotReservations held by calling
     *  applications and removes the internal tracking for the hotspot request.  When all requesting
     *  applications are finished using the hotspot, it will be stopped and WiFi will return to the
     *  previous operational mode.
     *
     *  This method should not be called by applications.  Instead, they should call the close()
     *  method on their LocalOnlyHotspotReservation.
     */
    private void stopLocalOnlyHotspot() {
        synchronized (mLock) {
            if (mLOHSCallbackProxy == null) {
                // nothing to do, the callback was already cleaned up.
                return;
            }
            mLOHSCallbackProxy = null;
            try {
                mService.stopLocalOnlyHotspot();
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
    }

    /**
     * Allow callers (Settings UI) to watch LocalOnlyHotspot state changes.  Callers will
     * receive a {@link LocalOnlyHotspotSubscription} object as a parameter of the
     * {@link LocalOnlyHotspotObserver#onRegistered(LocalOnlyHotspotSubscription)}. The registered
     * callers will receive the {@link LocalOnlyHotspotObserver#onStarted(SoftApConfiguration)} and
     * {@link LocalOnlyHotspotObserver#onStopped()} callbacks.
     * <p>
     * Applications should have the
     * {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION}
     * permission.  Callers without the permission will trigger a
     * {@link java.lang.SecurityException}.
     * <p>
     * @param observer LocalOnlyHotspotObserver callback.
     * @param handler Handler to use for callbacks
     *
     * @hide
     */
    public void watchLocalOnlyHotspot(LocalOnlyHotspotObserver observer,
            @Nullable Handler handler) {
        Executor executor = handler == null ? mContext.getMainExecutor()
                : new HandlerExecutor(handler);
        synchronized (mLock) {
            mLOHSObserverProxy =
                    new LocalOnlyHotspotObserverProxy(this, executor, observer);
            try {
                mService.startWatchLocalOnlyHotspot(mLOHSObserverProxy);
                mLOHSObserverProxy.registered();
            } catch (RemoteException e) {
                mLOHSObserverProxy = null;
                throw e.rethrowFromSystemServer();
            }
        }
    }

    /**
     * Allow callers to stop watching LocalOnlyHotspot state changes.  After calling this method,
     * applications will no longer receive callbacks.
     *
     * @hide
     */
    public void unregisterLocalOnlyHotspotObserver() {
        synchronized (mLock) {
            if (mLOHSObserverProxy == null) {
                // nothing to do, the callback was already cleaned up
                return;
            }
            mLOHSObserverProxy = null;
            try {
                mService.stopWatchLocalOnlyHotspot();
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
    }

    /**
     * Gets the tethered Wi-Fi hotspot enabled state.
     * @return One of {@link #WIFI_AP_STATE_DISABLED},
     *         {@link #WIFI_AP_STATE_DISABLING}, {@link #WIFI_AP_STATE_ENABLED},
     *         {@link #WIFI_AP_STATE_ENABLING}, {@link #WIFI_AP_STATE_FAILED}
     * @see #isWifiApEnabled()
     *
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE)
    public int getWifiApState() {
        try {
            return mService.getWifiApEnabledState();
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Return whether tethered Wi-Fi AP is enabled or disabled.
     * @return {@code true} if tethered  Wi-Fi AP is enabled
     * @see #getWifiApState()
     *
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE)
    public boolean isWifiApEnabled() {
        return getWifiApState() == WIFI_AP_STATE_ENABLED;
    }

    /**
     * Gets the tethered Wi-Fi AP Configuration.
     * @return AP details in WifiConfiguration
     *
     * Note that AP detail may contain configuration which is cannot be represented
     * by the legacy WifiConfiguration, in such cases a null will be returned.
     *
     * @deprecated This API is deprecated. Use {@link #getSoftApConfiguration()} instead.
     * @hide
     */
    @Nullable
    @SystemApi
    @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE)
    @Deprecated
    public WifiConfiguration getWifiApConfiguration() {
        try {
            return mService.getWifiApConfiguration();
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Gets the Wi-Fi tethered AP Configuration.
     * @return AP details in {@link SoftApConfiguration}
     *
     * @hide
     */
    @NonNull
    @SystemApi
    @RequiresPermission(anyOf = {
            android.Manifest.permission.NETWORK_SETTINGS,
            android.Manifest.permission.OVERRIDE_WIFI_CONFIG
    })
    public SoftApConfiguration getSoftApConfiguration() {
        try {
            return mService.getSoftApConfiguration();
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Sets the tethered Wi-Fi AP Configuration.
     * @return {@code true} if the operation succeeded, {@code false} otherwise
     *
     * @deprecated This API is deprecated. Use {@link #setSoftApConfiguration(SoftApConfiguration)}
     * instead.
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.CHANGE_WIFI_STATE)
    @Deprecated
    public boolean setWifiApConfiguration(WifiConfiguration wifiConfig) {
        try {
            return mService.setWifiApConfiguration(wifiConfig, mContext.getOpPackageName());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Sets the tethered Wi-Fi AP Configuration.
     *
     * If the API is called while the tethered soft AP is enabled, the configuration will apply to
     * the current soft AP if the new configuration only includes
     * {@link SoftApConfiguration.Builder#setMaxNumberOfClients(int)}
     * or {@link SoftApConfiguration.Builder#setShutdownTimeoutMillis(long)}
     * or {@link SoftApConfiguration.Builder#setClientControlByUserEnabled(boolean)}
     * or {@link SoftApConfiguration.Builder#setBlockedClientList(List)}
     * or {@link SoftApConfiguration.Builder#setAllowedClientList(List)}
     * or {@link SoftApConfiguration.Builder#setAutoShutdownEnabled(boolean)}
     * or {@link SoftApConfiguration.Builder#setBridgedModeOpportunisticShutdownEnabled(boolean)}
     *
     * Otherwise, the configuration changes will be applied when the Soft AP is next started
     * (the framework will not stop/start the AP).
     *
     * @param softApConfig  A valid SoftApConfiguration specifying the configuration of the SAP.
     * @return {@code true} if the operation succeeded, {@code false} otherwise
     *
     * @hide
     */
    @SystemApi
    @RequiresPermission(anyOf = {
            android.Manifest.permission.NETWORK_SETTINGS,
            android.Manifest.permission.OVERRIDE_WIFI_CONFIG
    })
    public boolean setSoftApConfiguration(@NonNull SoftApConfiguration softApConfig) {
        try {
            return mService.setSoftApConfiguration(
                    softApConfig, mContext.getOpPackageName());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Enable/Disable TDLS on a specific local route.
     *
     * <p>
     * TDLS enables two wireless endpoints to talk to each other directly
     * without going through the access point that is managing the local
     * network. It saves bandwidth and improves quality of the link.
     * </p>
     * <p>
     * This API enables/disables the option of using TDLS. If enabled, the
     * underlying hardware is free to use TDLS or a hop through the access
     * point. If disabled, existing TDLS session is torn down and
     * hardware is restricted to use access point for transferring wireless
     * packets. Default value for all routes is 'disabled', meaning restricted
     * to use access point for transferring packets.
     * </p>
     *
     * @param remoteIPAddress IP address of the endpoint to setup TDLS with
     * @param enable true = setup and false = tear down TDLS
     */
    public void setTdlsEnabled(InetAddress remoteIPAddress, boolean enable) {
        try {
            mService.enableTdls(remoteIPAddress.getHostAddress(), enable);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Similar to {@link #setTdlsEnabled(InetAddress, boolean) }, except
     * this version allows you to specify remote endpoint with a MAC address.
     * @param remoteMacAddress MAC address of the remote endpoint such as 00:00:0c:9f:f2:ab
     * @param enable true = setup and false = tear down TDLS
     */
    public void setTdlsEnabledWithMacAddress(String remoteMacAddress, boolean enable) {
        try {
            mService.enableTdlsWithMacAddress(remoteMacAddress, enable);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Passed with {@link ActionListener#onFailure}.
     * Indicates that the operation failed due to an internal error.
     * @hide
     */
    public static final int ERROR                       = 0;

    /**
     * Passed with {@link ActionListener#onFailure}.
     * Indicates that the operation is already in progress
     * @hide
     */
    public static final int IN_PROGRESS                 = 1;

    /**
     * Passed with {@link ActionListener#onFailure}.
     * Indicates that the operation failed because the framework is busy and
     * unable to service the request
     * @hide
     */
    public static final int BUSY                        = 2;

    /** @hide */
    @Retention(RetentionPolicy.SOURCE)
    @IntDef({ERROR, IN_PROGRESS, BUSY})
    public @interface ActionListenerFailureReason {}

    /* WPS specific errors */
    /** WPS overlap detected
     * @deprecated This is deprecated
     */
    public static final int WPS_OVERLAP_ERROR           = 3;
    /** WEP on WPS is prohibited
     * @deprecated This is deprecated
     */
    public static final int WPS_WEP_PROHIBITED          = 4;
    /** TKIP only prohibited
     * @deprecated This is deprecated
     */
    public static final int WPS_TKIP_ONLY_PROHIBITED    = 5;
    /** Authentication failure on WPS
     * @deprecated This is deprecated
     */
    public static final int WPS_AUTH_FAILURE            = 6;
    /** WPS timed out
     * @deprecated This is deprecated
     */
    public static final int WPS_TIMED_OUT               = 7;

    /**
     * Passed with {@link ActionListener#onFailure}.
     * Indicates that the operation failed due to invalid inputs
     * @hide
     */
    public static final int INVALID_ARGS                = 8;

    /**
     * Passed with {@link ActionListener#onFailure}.
     * Indicates that the operation failed due to user permissions.
     * @hide
     */
    public static final int NOT_AUTHORIZED              = 9;

    /**
     * Interface for callback invocation on an application action
     * @hide
     */
    @SystemApi
    public interface ActionListener {
        /**
         * The operation succeeded.
         */
        void onSuccess();
        /**
         * The operation failed.
         * @param reason The reason for failure depends on the operation.
         */
        void onFailure(@ActionListenerFailureReason int reason);
    }

    /** Interface for callback invocation on a start WPS action
     * @deprecated This is deprecated
     */
    public static abstract class WpsCallback {

        /** WPS start succeeded
         * @deprecated This API is deprecated
         */
        public abstract void onStarted(String pin);

        /** WPS operation completed successfully
         * @deprecated This API is deprecated
         */
        public abstract void onSucceeded();

        /**
         * WPS operation failed
         * @param reason The reason for failure could be one of
         * {@link #WPS_TKIP_ONLY_PROHIBITED}, {@link #WPS_OVERLAP_ERROR},
         * {@link #WPS_WEP_PROHIBITED}, {@link #WPS_TIMED_OUT} or {@link #WPS_AUTH_FAILURE}
         * and some generic errors.
         * @deprecated This API is deprecated
         */
        public abstract void onFailed(int reason);
    }

    /**
     * Base class for soft AP callback. Should be extended by applications and set when calling
     * {@link WifiManager#registerSoftApCallback(Executor, SoftApCallback)}.
     *
     * @hide
     */
    @SystemApi
    public interface SoftApCallback {
        /**
         * Called when soft AP state changes.
         *
         * @param state         the new AP state. One of {@link #WIFI_AP_STATE_DISABLED},
         *                      {@link #WIFI_AP_STATE_DISABLING}, {@link #WIFI_AP_STATE_ENABLED},
         *                      {@link #WIFI_AP_STATE_ENABLING}, {@link #WIFI_AP_STATE_FAILED}
         * @param failureReason reason when in failed state. One of
         *                      {@link #SAP_START_FAILURE_GENERAL},
         *                      {@link #SAP_START_FAILURE_NO_CHANNEL},
         *                      {@link #SAP_START_FAILURE_UNSUPPORTED_CONFIGURATION}
         */
        default void onStateChanged(@WifiApState int state, @SapStartFailure int failureReason) {}

        /**
         * Called when the connected clients to soft AP changes.
         *
         * @param clients the currently connected clients
         *
         * @deprecated This API is deprecated.
         * Use {@link #onConnectedClientsChanged(SoftApInfo, List<WifiClient>)} instead.
         */
        @Deprecated
        default void onConnectedClientsChanged(@NonNull List<WifiClient> clients) {}


        /**
         * Called when the connected clients for a soft AP instance change.
         *
         * When the Soft AP is configured in single AP mode, this callback is invoked
         * with the same {@link SoftApInfo} for all connected clients changes.
         * When the Soft AP is configured as multiple Soft AP instances (using
         * {@link SoftApConfiguration.Builder#setBands(int[])} or
         * {@link SoftApConfiguration.Builder#setChannels(android.util.SparseIntArray)}), this
         * callback is invoked with the corresponding {@link SoftApInfo} for the instance in which
         * the connected clients changed.
         *
         * @param info The {@link SoftApInfo} of the AP.
         * @param clients The currently connected clients on the AP instance specified by
         *                {@code info}.
         */
        default void onConnectedClientsChanged(@NonNull SoftApInfo info,
                @NonNull List<WifiClient> clients) {}

        /**
         * Called when the Soft AP information changes.
         *
         * Note: this API remains valid only when the Soft AP is configured as a single AP -
         * not as multiple Soft APs (which are bridged to each other). When multiple Soft APs are
         * configured (using {@link SoftApConfiguration.Builder#setBands(int[])} or
         * {@link SoftApConfiguration.Builder#setChannels(android.util.SparseIntArray)})
         * this callback will not be triggered -  use the
         * {@link #onInfoChanged(List<SoftApInfo>)} callback in that case.
         *
         * @param softApInfo is the Soft AP information. {@link SoftApInfo}
         *
         * @deprecated This API is deprecated. Use {@link #onInfoChanged(List<SoftApInfo>)}
         * instead.
         */
        @Deprecated
        default void onInfoChanged(@NonNull SoftApInfo softApInfo) {
            // Do nothing: can be updated to add SoftApInfo details (e.g. channel) to the UI.
        }

        /**
         * Called when the Soft AP information changes.
         *
         * Returns information on all configured Soft AP instances. The number of the elements in
         * the list depends on Soft AP configuration and state:
         * <ul>
         * <li>An empty list will be returned when the Soft AP is disabled.
         * <li>One information element will be returned in the list when the Soft AP is configured
         *     as a single AP or when a single Soft AP remains active.
         * <li>Two information elements will be returned in the list when the multiple Soft APs are
         *     configured and are active.
         *     (configured using {@link SoftApConfiguration.Builder#setBands(int[])} or
         *     {@link SoftApConfiguration.Builder#setChannels(android.util.SparseIntArray)}).
         * </ul>
         *
         * Note: When multiple Soft AP instances are configured, one of the Soft APs may
         * be shut down independently of the other by the framework. This can happen if no devices
         * are connected to it for some duration. In that case, one information element will be
         * returned.
         *
         * See {@link #isBridgedApConcurrencySupported()} for support info of multiple (bridged) AP.
         *
         * @param softApInfoList is the list of the Soft AP information elements -
         *        {@link SoftApInfo}.
         */
        default void onInfoChanged(@NonNull List<SoftApInfo> softApInfoList) {
            // Do nothing: can be updated to add SoftApInfo details (e.g. channel) to the UI.
        }

        /**
         * Called when capability of Soft AP changes.
         *
         * @param softApCapability is the Soft AP capability. {@link SoftApCapability}
         */
        default void onCapabilityChanged(@NonNull SoftApCapability softApCapability) {
            // Do nothing: can be updated to add SoftApCapability details (e.g. meximum supported
            // client number) to the UI.
        }

        /**
         * Called when client trying to connect but device blocked the client with specific reason.
         *
         * Can be used to ask user to update client to allowed list or blocked list
         * when reason is {@link SAP_CLIENT_BLOCK_REASON_CODE_BLOCKED_BY_USER}, or
         * indicate the block due to maximum supported client number limitation when reason is
         * {@link SAP_CLIENT_BLOCK_REASON_CODE_NO_MORE_STAS}.
         *
         * @param client the currently blocked client.
         * @param blockedReason one of blocked reason from {@link SapClientBlockedReason}
         */
        default void onBlockedClientConnecting(@NonNull WifiClient client,
                @SapClientBlockedReason int blockedReason) {
            // Do nothing: can be used to ask user to update client to allowed list or blocked list.
        }
    }

    /**
     * Callback proxy for SoftApCallback objects.
     *
     * @hide
     */
    private class SoftApCallbackProxy extends ISoftApCallback.Stub {
        private final Executor mExecutor;
        private final SoftApCallback mCallback;
        private Map<String, List<WifiClient>> mCurrentClients = new HashMap<>();
        private Map<String, SoftApInfo> mCurrentInfos = new HashMap<>();

        private List<WifiClient> getConnectedClientList(Map<String, List<WifiClient>> clientsMap) {
            List<WifiClient> connectedClientList = new ArrayList<>();
            for (List<WifiClient> it : clientsMap.values()) {
                connectedClientList.addAll(it);
            }
            return connectedClientList;
        }

        SoftApCallbackProxy(Executor executor, SoftApCallback callback) {
            mExecutor = executor;
            mCallback = callback;
        }

        @Override
        public void onStateChanged(int state, int failureReason) {
            if (mVerboseLoggingEnabled) {
                Log.v(TAG, "SoftApCallbackProxy: onStateChanged: state=" + state
                        + ", failureReason=" + failureReason);
            }

            Binder.clearCallingIdentity();
            mExecutor.execute(() -> {
                mCallback.onStateChanged(state, failureReason);
            });
        }

        @Override
        public void onConnectedClientsOrInfoChanged(Map<String, SoftApInfo> infos,
                Map<String, List<WifiClient>> clients, boolean isBridged, boolean isRegistration) {
            if (mVerboseLoggingEnabled) {
                Log.v(TAG, "SoftApCallbackProxy: onConnectedClientsOrInfoChanged: clients: "
                        + clients + ", infos: " + infos + ", isBridged is " + isBridged
                        + ", isRegistration is " + isRegistration);
            }

            List<SoftApInfo> changedInfoList = new ArrayList<>(infos.values());
            Map<SoftApInfo, List<WifiClient>> changedInfoClients = new HashMap<>();
            // Some devices may not support infos callback, allow them to support client
            // connection changed callback.
            boolean areClientsChangedWithoutInfosChanged =
                    infos.size() == 0 && getConnectedClientList(clients).size()
                    != getConnectedClientList(mCurrentClients).size();
            boolean isInfoChanged = infos.size() != mCurrentInfos.size();

            if (isRegistration) {
                // Check if there are clients connected, put it to changedInfoClients
                for (SoftApInfo currentInfo : infos.values()) {
                    String instance = currentInfo.getApInstanceIdentifier();
                    if (clients.getOrDefault(instance, Collections.emptyList()).size() > 0) {
                        changedInfoClients.put(currentInfo, clients.get(instance));
                    }
                }
            }

            // Check if old info removed or not (client changed case)
            for (SoftApInfo info : mCurrentInfos.values()) {
                String changedInstance = info.getApInstanceIdentifier();
                if (!changedInfoList.contains(info)) {
                    isInfoChanged = true;
                    if (mCurrentClients.getOrDefault(changedInstance,
                              Collections.emptyList()).size() > 0) {
                        Log.d(TAG, "SoftApCallbackProxy: info changed on client connected"
                                + " instance(Shut Down case)");
                        //Here should notify client changed on old info
                        changedInfoClients.put(info, Collections.emptyList());
                    }
                } else {
                    // info doesn't change, check client list
                    List<WifiClient> changedClientList = clients.getOrDefault(
                            changedInstance, Collections.emptyList());
                    if (changedClientList.size()
                            != mCurrentClients
                            .getOrDefault(changedInstance, Collections.emptyList()).size()) {
                        // Here should notify client changed on new info(same as old info)
                        changedInfoClients.put(info, changedClientList);
                    }
                }
            }

            mCurrentClients = clients;
            mCurrentInfos = infos;
            if (!isInfoChanged && changedInfoClients.isEmpty()
                    && !isRegistration && !areClientsChangedWithoutInfosChanged) {
                Log.v(TAG, "SoftApCallbackProxy: No changed & Not Registration,"
                        + " don't need to notify the client");
                return;
            }
            Binder.clearCallingIdentity();
            // Notify the clients changed first for old info shutdown case
            for (SoftApInfo changedInfo : changedInfoClients.keySet()) {
                Log.v(TAG, "SoftApCallbackProxy: send onConnectedClientsChanged, changedInfo is "
                        + changedInfo + " and clients are " + changedInfoClients.get(changedInfo));
                mExecutor.execute(() -> {
                    mCallback.onConnectedClientsChanged(
                            changedInfo, changedInfoClients.get(changedInfo));
                });
            }

            if (isInfoChanged || isRegistration) {
                if (!isBridged) {
                    SoftApInfo newInfo = changedInfoList.isEmpty()
                            ? new SoftApInfo() : changedInfoList.get(0);
                    Log.v(TAG, "SoftApCallbackProxy: send InfoChanged, newInfo: " + newInfo);
                    mExecutor.execute(() -> {
                        mCallback.onInfoChanged(newInfo);
                    });
                }
                Log.v(TAG, "SoftApCallbackProxy: send InfoChanged, changedInfoList: "
                        + changedInfoList);
                mExecutor.execute(() -> {
                    mCallback.onInfoChanged(changedInfoList);
                });
            }

            if (isRegistration || !changedInfoClients.isEmpty()
                    || areClientsChangedWithoutInfosChanged) {
                Log.v(TAG, "SoftApCallbackProxy: send onConnectedClientsChanged(clients): "
                        + getConnectedClientList(clients));
                mExecutor.execute(() -> {
                    mCallback.onConnectedClientsChanged(getConnectedClientList(clients));
                });
            }
        }

        @Override
        public void onCapabilityChanged(SoftApCapability capability) {
            if (mVerboseLoggingEnabled) {
                Log.v(TAG, "SoftApCallbackProxy: onCapabilityChanged: SoftApCapability="
                        + capability);
            }

            Binder.clearCallingIdentity();
            mExecutor.execute(() -> {
                mCallback.onCapabilityChanged(capability);
            });
        }

        @Override
        public void onBlockedClientConnecting(@NonNull WifiClient client, int blockedReason) {
            if (mVerboseLoggingEnabled) {
                Log.v(TAG, "SoftApCallbackProxy: onBlockedClientConnecting: client=" + client
                        + " with reason = " + blockedReason);
            }

            Binder.clearCallingIdentity();
            mExecutor.execute(() -> {
                mCallback.onBlockedClientConnecting(client, blockedReason);
            });
        }
    }

    /**
     * Registers a callback for Soft AP. See {@link SoftApCallback}. Caller will receive the
     * following callbacks on registration:
     * <ul>
     * <li> {@link SoftApCallback#onStateChanged(int, int)}</li>
     * <li> {@link SoftApCallback#onConnectedClientsChanged(List<WifiClient>)}</li>
     * <li> {@link SoftApCallback#onInfoChanged(SoftApInfo)}</li>
     * <li> {@link SoftApCallback#onInfoChanged(List<SoftApInfo>)}</li>
     * <li> {@link SoftApCallback#onCapabilityChanged(SoftApCapability)}</li>
     * </ul>
     *
     * Use {@link SoftApCallback#onConnectedClientsChanged(SoftApInfo, List<WifiClient>)} to know
     * if there are any clients connected to a specific bridged instance of this AP
     * (if bridged AP is enabled).
     *
     * Note: Caller will receive the callback
     * {@link SoftApCallback#onConnectedClientsChanged(SoftApInfo, List<WifiClient>)}
     * on registration when there are clients connected to AP.
     *
     * These will be dispatched on registration to provide the caller with the current state
     * (and are not an indication of any current change). Note that receiving an immediate
     * WIFI_AP_STATE_FAILED value for soft AP state indicates that the latest attempt to start
     * soft AP has failed. Caller can unregister a previously registered callback using
     * {@link #unregisterSoftApCallback}
     * <p>
     * Applications should have the
     * {@link android.Manifest.permission#NETWORK_SETTINGS NETWORK_SETTINGS} permission. Callers
     * without the permission will trigger a {@link java.lang.SecurityException}.
     * <p>
     *
     * @param executor The Executor on whose thread to execute the callbacks of the {@code callback}
     *                 object.
     * @param callback Callback for soft AP events
     * @hide
     */
    @SystemApi
    @RequiresPermission(anyOf = {
            android.Manifest.permission.NETWORK_SETTINGS,
            NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
            android.Manifest.permission.OVERRIDE_WIFI_CONFIG
    })
    public void registerSoftApCallback(@NonNull @CallbackExecutor Executor executor,
            @NonNull SoftApCallback callback) {
        if (executor == null) throw new IllegalArgumentException("executor cannot be null");
        if (callback == null) throw new IllegalArgumentException("callback cannot be null");
        Log.v(TAG, "registerSoftApCallback: callback=" + callback + ", executor=" + executor);

        try {
            synchronized (sSoftApCallbackMap) {
                ISoftApCallback.Stub binderCallback = new SoftApCallbackProxy(executor, callback);
                sSoftApCallbackMap.put(System.identityHashCode(callback), binderCallback);
                mService.registerSoftApCallback(binderCallback);
            }
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Allow callers to unregister a previously registered callback. After calling this method,
     * applications will no longer receive soft AP events.
     *
     * @param callback Callback to unregister for soft AP events
     *
     * @hide
     */
    @SystemApi
    @RequiresPermission(anyOf = {
            android.Manifest.permission.NETWORK_SETTINGS,
            NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
            android.Manifest.permission.OVERRIDE_WIFI_CONFIG
    })
    public void unregisterSoftApCallback(@NonNull SoftApCallback callback) {
        if (callback == null) throw new IllegalArgumentException("callback cannot be null");
        Log.v(TAG, "unregisterSoftApCallback: callback=" + callback);

        try {
            synchronized (sSoftApCallbackMap) {
                int callbackIdentifier = System.identityHashCode(callback);
                if (!sSoftApCallbackMap.contains(callbackIdentifier)) {
                    Log.w(TAG, "Unknown external callback " + callbackIdentifier);
                    return;
                }
                mService.unregisterSoftApCallback(sSoftApCallbackMap.get(callbackIdentifier));
                sSoftApCallbackMap.remove(callbackIdentifier);
            }
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * LocalOnlyHotspotReservation that contains the {@link SoftApConfiguration} for the active
     * LocalOnlyHotspot request.
     * <p>
     * Applications requesting LocalOnlyHotspot for sharing will receive an instance of the
     * LocalOnlyHotspotReservation in the
     * {@link LocalOnlyHotspotCallback#onStarted(LocalOnlyHotspotReservation)} call.  This
     * reservation contains the relevant {@link SoftApConfiguration}.
     * When an application is done with the LocalOnlyHotspot, they should call {@link
     * LocalOnlyHotspotReservation#close()}.  Once this happens, the application will not receive
     * any further callbacks. If the LocalOnlyHotspot is stopped due to a
     * user triggered mode change, applications will be notified via the {@link
     * LocalOnlyHotspotCallback#onStopped()} callback.
     */
    public class LocalOnlyHotspotReservation implements AutoCloseable {

        private final CloseGuard mCloseGuard = new CloseGuard();
        private final SoftApConfiguration mSoftApConfig;
        private final WifiConfiguration mWifiConfig;
        private boolean mClosed = false;

        /** @hide */
        @VisibleForTesting
        public LocalOnlyHotspotReservation(SoftApConfiguration config) {
            mSoftApConfig = config;
            mWifiConfig = config.toWifiConfiguration();
            mCloseGuard.open("close");
        }

        /**
         * Returns the {@link WifiConfiguration} of the current Local Only Hotspot (LOHS).
         * May be null if hotspot enabled and security type is not
         * {@code WifiConfiguration.KeyMgmt.None} or {@code WifiConfiguration.KeyMgmt.WPA2_PSK}.
         *
         * @deprecated Use {@code WifiManager#getSoftApConfiguration()} to get the
         * LOHS configuration.
         */
        @Deprecated
        @Nullable
        public WifiConfiguration getWifiConfiguration() {
            return mWifiConfig;
        }

        /**
         * Returns the {@link SoftApConfiguration} of the current Local Only Hotspot (LOHS).
         */
        @NonNull
        public SoftApConfiguration getSoftApConfiguration() {
            return mSoftApConfig;
        }

        @Override
        public void close() {
            try {
                synchronized (mLock) {
                    if (!mClosed) {
                        mClosed = true;
                        stopLocalOnlyHotspot();
                        mCloseGuard.close();
                    }
                }
            } catch (Exception e) {
                Log.e(TAG, "Failed to stop Local Only Hotspot.");
            } finally {
                Reference.reachabilityFence(this);
            }
        }

        @Override
        protected void finalize() throws Throwable {
            try {
                if (mCloseGuard != null) {
                    mCloseGuard.warnIfOpen();
                }
                close();
            } finally {
                super.finalize();
            }
        }
    }

    /**
     * Callback class for applications to receive updates about the LocalOnlyHotspot status.
     */
    public static class LocalOnlyHotspotCallback {
        /** @hide */
        public static final int REQUEST_REGISTERED = 0;

        public static final int ERROR_NO_CHANNEL = 1;
        public static final int ERROR_GENERIC = 2;
        public static final int ERROR_INCOMPATIBLE_MODE = 3;
        public static final int ERROR_TETHERING_DISALLOWED = 4;

        /** LocalOnlyHotspot start succeeded. */
        public void onStarted(LocalOnlyHotspotReservation reservation) {};

        /**
         * LocalOnlyHotspot stopped.
         * <p>
         * The LocalOnlyHotspot can be disabled at any time by the user.  When this happens,
         * applications will be notified that it was stopped. This will not be invoked when an
         * application calls {@link LocalOnlyHotspotReservation#close()}.
         */
        public void onStopped() {};

        /**
         * LocalOnlyHotspot failed to start.
         * <p>
         * Applications can attempt to call
         * {@link WifiManager#startLocalOnlyHotspot(LocalOnlyHotspotCallback, Handler)} again at
         * a later time.
         * <p>
         * @param reason The reason for failure could be one of: {@link
         * #ERROR_TETHERING_DISALLOWED}, {@link #ERROR_INCOMPATIBLE_MODE},
         * {@link #ERROR_NO_CHANNEL}, or {@link #ERROR_GENERIC}.
         */
        public void onFailed(int reason) { };
    }

    /**
     * Callback proxy for LocalOnlyHotspotCallback objects.
     */
    private static class LocalOnlyHotspotCallbackProxy extends ILocalOnlyHotspotCallback.Stub {
        private final WeakReference<WifiManager> mWifiManager;
        private final Executor mExecutor;
        private final LocalOnlyHotspotCallback mCallback;

        /**
         * Constructs a {@link LocalOnlyHotspotCallbackProxy} using the specified executor.  All
         * callbacks will run using the given executor.
         *
         * @param manager WifiManager
         * @param executor Executor for delivering callbacks.
         * @param callback LocalOnlyHotspotCallback to notify the calling application, or null.
         */
        LocalOnlyHotspotCallbackProxy(
                @NonNull WifiManager manager,
                @NonNull Executor executor,
                @Nullable LocalOnlyHotspotCallback callback) {
            mWifiManager = new WeakReference<>(manager);
            mExecutor = executor;
            mCallback = callback;
        }

        @Override
        public void onHotspotStarted(SoftApConfiguration config) {
            WifiManager manager = mWifiManager.get();
            if (manager == null) return;

            if (config == null) {
                Log.e(TAG, "LocalOnlyHotspotCallbackProxy: config cannot be null.");
                onHotspotFailed(LocalOnlyHotspotCallback.ERROR_GENERIC);
                return;
            }
            final LocalOnlyHotspotReservation reservation =
                    manager.new LocalOnlyHotspotReservation(config);
            if (mCallback == null) return;
            mExecutor.execute(() -> mCallback.onStarted(reservation));
        }

        @Override
        public void onHotspotStopped() {
            WifiManager manager = mWifiManager.get();
            if (manager == null) return;

            Log.w(TAG, "LocalOnlyHotspotCallbackProxy: hotspot stopped");
            if (mCallback == null) return;
            mExecutor.execute(() -> mCallback.onStopped());
        }

        @Override
        public void onHotspotFailed(int reason) {
            WifiManager manager = mWifiManager.get();
            if (manager == null) return;

            Log.w(TAG, "LocalOnlyHotspotCallbackProxy: failed to start.  reason: "
                    + reason);
            if (mCallback == null) return;
            mExecutor.execute(() -> mCallback.onFailed(reason));
        }
    }

    /**
     * LocalOnlyHotspotSubscription that is an AutoCloseable object for tracking applications
     * watching for LocalOnlyHotspot changes.
     *
     * @hide
     */
    public class LocalOnlyHotspotSubscription implements AutoCloseable {
        private final CloseGuard mCloseGuard = new CloseGuard();

        /** @hide */
        @VisibleForTesting
        public LocalOnlyHotspotSubscription() {
            mCloseGuard.open("close");
        }

        @Override
        public void close() {
            try {
                unregisterLocalOnlyHotspotObserver();
                mCloseGuard.close();
            } catch (Exception e) {
                Log.e(TAG, "Failed to unregister LocalOnlyHotspotObserver.");
            } finally {
                Reference.reachabilityFence(this);
            }
        }

        @Override
        protected void finalize() throws Throwable {
            try {
                if (mCloseGuard != null) {
                    mCloseGuard.warnIfOpen();
                }
                close();
            } finally {
                super.finalize();
            }
        }
    }

    /**
     * Class to notify calling applications that watch for changes in LocalOnlyHotspot of updates.
     *
     * @hide
     */
    public static class LocalOnlyHotspotObserver {
        /**
         * Confirm registration for LocalOnlyHotspotChanges by returning a
         * LocalOnlyHotspotSubscription.
         */
        public void onRegistered(LocalOnlyHotspotSubscription subscription) {};

        /**
         * LocalOnlyHotspot started with the supplied config.
         */
        public void onStarted(SoftApConfiguration config) {};

        /**
         * LocalOnlyHotspot stopped.
         */
        public void onStopped() {};
    }

    /**
     * Callback proxy for LocalOnlyHotspotObserver objects.
     */
    private static class LocalOnlyHotspotObserverProxy extends ILocalOnlyHotspotCallback.Stub {
        private final WeakReference<WifiManager> mWifiManager;
        private final Executor mExecutor;
        private final LocalOnlyHotspotObserver mObserver;

        /**
         * Constructs a {@link LocalOnlyHotspotObserverProxy} using the specified looper.
         * All callbacks will be delivered on the thread of the specified looper.
         *
         * @param manager WifiManager
         * @param executor Executor for delivering callbacks
         * @param observer LocalOnlyHotspotObserver to notify the calling application.
         */
        LocalOnlyHotspotObserverProxy(WifiManager manager, Executor executor,
                final LocalOnlyHotspotObserver observer) {
            mWifiManager = new WeakReference<>(manager);
            mExecutor = executor;
            mObserver = observer;
        }

        public void registered() throws RemoteException {
            WifiManager manager = mWifiManager.get();
            if (manager == null) return;

            mExecutor.execute(() ->
                    mObserver.onRegistered(manager.new LocalOnlyHotspotSubscription()));
        }

        @Override
        public void onHotspotStarted(SoftApConfiguration config) {
            WifiManager manager = mWifiManager.get();
            if (manager == null) return;

            if (config == null) {
                Log.e(TAG, "LocalOnlyHotspotObserverProxy: config cannot be null.");
                return;
            }
            mExecutor.execute(() -> mObserver.onStarted(config));
        }

        @Override
        public void onHotspotStopped() {
            WifiManager manager = mWifiManager.get();
            if (manager == null) return;

            mExecutor.execute(() -> mObserver.onStopped());
        }

        @Override
        public void onHotspotFailed(int reason) {
            // do nothing
        }
    }

    /**
     * Callback proxy for ActionListener objects.
     */
    private class ActionListenerProxy extends IActionListener.Stub {
        private final String mActionTag;
        private final Handler mHandler;
        private final ActionListener mCallback;

        ActionListenerProxy(String actionTag, Looper looper, ActionListener callback) {
            mActionTag = actionTag;
            mHandler = new Handler(looper);
            mCallback = callback;
        }

        @Override
        public void onSuccess() {
            if (mVerboseLoggingEnabled) {
                Log.v(TAG, "ActionListenerProxy:" + mActionTag + ": onSuccess");
            }
            mHandler.post(() -> {
                mCallback.onSuccess();
            });
        }

        @Override
        public void onFailure(@ActionListenerFailureReason int reason) {
            if (mVerboseLoggingEnabled) {
                Log.v(TAG, "ActionListenerProxy:" + mActionTag + ": onFailure=" + reason);
            }
            mHandler.post(() -> {
                mCallback.onFailure(reason);
            });
        }
    }

    private void connectInternal(@Nullable WifiConfiguration config, int networkId,
            @Nullable ActionListener listener) {
        ActionListenerProxy listenerProxy = null;
        if (listener != null) {
            listenerProxy = new ActionListenerProxy("connect", mLooper, listener);
        }
        try {
            mService.connect(config, networkId, listenerProxy);
        } catch (RemoteException e) {
            if (listenerProxy != null) listenerProxy.onFailure(ERROR);
        } catch (SecurityException e) {
            if (listenerProxy != null) listenerProxy.onFailure(NOT_AUTHORIZED);
        }
    }

    /**
     * Connect to a network with the given configuration. The network also
     * gets added to the list of configured networks for the foreground user.
     *
     * For a new network, this function is used instead of a
     * sequence of addNetwork(), enableNetwork(), and reconnect()
     *
     * @param config the set of variables that describe the configuration,
     *            contained in a {@link WifiConfiguration} object.
     * @param listener for callbacks on success or failure. Can be null.
     * @throws IllegalStateException if the WifiManager instance needs to be
     * initialized again
     *
     * @hide
     */
    @SystemApi
    @RequiresPermission(anyOf = {
            android.Manifest.permission.NETWORK_SETTINGS,
            android.Manifest.permission.NETWORK_SETUP_WIZARD,
            android.Manifest.permission.NETWORK_STACK
    })
    public void connect(@NonNull WifiConfiguration config, @Nullable ActionListener listener) {
        if (config == null) throw new IllegalArgumentException("config cannot be null");
        connectInternal(config, WifiConfiguration.INVALID_NETWORK_ID, listener);
    }

    /**
     * Connect to a network with the given networkId.
     *
     * This function is used instead of a enableNetwork() and reconnect()
     *
     * <li> This API will cause reconnect if the credentials of the current active
     * connection has been changed.</li>
     * <li> This API will cause reconnect if the current active connection is marked metered.</li>
     *
     * @param networkId the ID of the network as returned by {@link #addNetwork} or {@link
     *        getConfiguredNetworks}.
     * @param listener for callbacks on success or failure. Can be null.
     * @throws IllegalStateException if the WifiManager instance needs to be
     * initialized again
     * @hide
     */
    @SystemApi
    @RequiresPermission(anyOf = {
            android.Manifest.permission.NETWORK_SETTINGS,
            android.Manifest.permission.NETWORK_SETUP_WIZARD,
            android.Manifest.permission.NETWORK_STACK
    })
    public void connect(int networkId, @Nullable ActionListener listener) {
        if (networkId < 0) throw new IllegalArgumentException("Network id cannot be negative");
        connectInternal(null, networkId, listener);
    }

    /**
     * Temporarily disable autojoin for all currently visible and provisioned (saved, suggested)
     * wifi networks except merged carrier networks from the provided subscription ID.
     *
     * Disabled networks will get automatically re-enabled when they are out of range for a period
     * of time, or after the maximum disable duration specified in the framework.
     *
     * Calling {@link #stopRestrictingAutoJoinToSubscriptionId()} will immediately re-enable
     * autojoin on all disabled networks.
     *
     * @param subscriptionId the subscription ID of the carrier whose merged wifi networks won't be
     *                       disabled {@link android.telephony.SubscriptionInfo#getSubscriptionId()}
     * @hide
     */
    @SystemApi
    @RequiresPermission(anyOf = {
            android.Manifest.permission.NETWORK_SETTINGS,
            android.Manifest.permission.NETWORK_SETUP_WIZARD})
    @RequiresApi(Build.VERSION_CODES.S)
    public void startRestrictingAutoJoinToSubscriptionId(int subscriptionId) {
        try {
            mService.startRestrictingAutoJoinToSubscriptionId(subscriptionId);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Re-enable autojoin for all non carrier merged wifi networks temporarily disconnected by
     * {@link #startRestrictingAutoJoinToSubscriptionId(int)}.
     * @hide
     */
    @SystemApi
    @RequiresPermission(anyOf = {
            android.Manifest.permission.NETWORK_SETTINGS,
            android.Manifest.permission.NETWORK_SETUP_WIZARD})
    @RequiresApi(Build.VERSION_CODES.S)
    public void stopRestrictingAutoJoinToSubscriptionId() {
        try {
            mService.stopRestrictingAutoJoinToSubscriptionId();
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Save the given network to the list of configured networks for the
     * foreground user. If the network already exists, the configuration
     * is updated. Any new network is enabled by default.
     *
     * For a new network, this function is used instead of a
     * sequence of addNetwork() and enableNetwork().
     *
     * For an existing network, it accomplishes the task of updateNetwork()
     *
     * <li> This API will cause reconnect if the credentials of the current active
     * connection has been changed.</li>
     * <li> This API will cause disconnect if the current active connection is marked metered.</li>
     *
     * @param config the set of variables that describe the configuration,
     *            contained in a {@link WifiConfiguration} object.
     * @param listener for callbacks on success or failure. Can be null.
     * @throws IllegalStateException if the WifiManager instance needs to be
     * initialized again
     * @hide
     */
    @SystemApi
    @RequiresPermission(anyOf = {
            android.Manifest.permission.NETWORK_SETTINGS,
            android.Manifest.permission.NETWORK_SETUP_WIZARD,
            android.Manifest.permission.NETWORK_STACK
    })
    public void save(@NonNull WifiConfiguration config, @Nullable ActionListener listener) {
        if (config == null) throw new IllegalArgumentException("config cannot be null");
        ActionListenerProxy listenerProxy = null;
        if (listener != null) {
            listenerProxy = new ActionListenerProxy("save", mLooper, listener);
        }
        try {
            mService.save(config, listenerProxy);
        } catch (RemoteException e) {
            if (listenerProxy != null) listenerProxy.onFailure(ERROR);
        } catch (SecurityException e) {
            if (listenerProxy != null) listenerProxy.onFailure(NOT_AUTHORIZED);
        }
    }

    /**
     * Delete the network from the list of configured networks for the
     * foreground user.
     *
     * This function is used instead of a sequence of removeNetwork()
     *
     * @param config the set of variables that describe the configuration,
     *            contained in a {@link WifiConfiguration} object.
     * @param listener for callbacks on success or failure. Can be null.
     * @throws IllegalStateException if the WifiManager instance needs to be
     * initialized again
     * @hide
     */
    @SystemApi
    @RequiresPermission(anyOf = {
            android.Manifest.permission.NETWORK_SETTINGS,
            android.Manifest.permission.NETWORK_SETUP_WIZARD,
            android.Manifest.permission.NETWORK_STACK
    })
    public void forget(int netId, @Nullable ActionListener listener) {
        if (netId < 0) throw new IllegalArgumentException("Network id cannot be negative");
        ActionListenerProxy listenerProxy = null;
        if (listener != null) {
            listenerProxy = new ActionListenerProxy("forget", mLooper, listener);
        }
        try {
            mService.forget(netId, listenerProxy);
        } catch (RemoteException e) {
            if (listenerProxy != null) listenerProxy.onFailure(ERROR);
        } catch (SecurityException e) {
            if (listenerProxy != null) listenerProxy.onFailure(NOT_AUTHORIZED);
        }
    }

    /**
     * Disable network
     *
     * @param netId is the network Id
     * @param listener for callbacks on success or failure. Can be null.
     * @throws IllegalStateException if the WifiManager instance needs to be
     * initialized again
     * @deprecated This API is deprecated. Use {@link #disableNetwork(int)} instead.
     * @hide
     */
    @SystemApi
    @RequiresPermission(anyOf = {
            android.Manifest.permission.NETWORK_SETTINGS,
            android.Manifest.permission.NETWORK_SETUP_WIZARD,
            android.Manifest.permission.NETWORK_STACK
    })
    @Deprecated
    public void disable(int netId, @Nullable ActionListener listener) {
        if (netId < 0) throw new IllegalArgumentException("Network id cannot be negative");
        // Simple wrapper which forwards the call to disableNetwork. This is a temporary
        // implementation until we can remove this API completely.
        boolean status = disableNetwork(netId);
        if (listener != null) {
            if (status) {
                listener.onSuccess();
            } else {
                listener.onFailure(ERROR);
            }
        }
    }

    /**
     * Enable/disable auto-join globally.
     *
     * @param allowAutojoin true to allow auto-join, false to disallow auto-join
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
    public void allowAutojoinGlobal(boolean allowAutojoin) {
        try {
            mService.allowAutojoinGlobal(allowAutojoin);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }


    /**
     * Sets the user choice for allowing auto-join to a network.
     * The updated choice will be made available through the updated config supplied by the
     * CONFIGURED_NETWORKS_CHANGED broadcast.
     *
     * @param netId the id of the network to allow/disallow auto-join for.
     * @param allowAutojoin true to allow auto-join, false to disallow auto-join
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
    public void allowAutojoin(int netId, boolean allowAutojoin) {
        try {
            mService.allowAutojoin(netId, allowAutojoin);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Configure auto-join settings for a Passpoint profile.
     *
     * @param fqdn the FQDN (fully qualified domain name) of the passpoint profile.
     * @param allowAutojoin true to enable auto-join, false to disable auto-join.
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
    public void allowAutojoinPasspoint(@NonNull String fqdn, boolean allowAutojoin) {
        try {
            mService.allowAutojoinPasspoint(fqdn, allowAutojoin);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Configure MAC randomization setting for a Passpoint profile.
     * MAC randomization is enabled by default.
     *
     * @param fqdn the FQDN (fully qualified domain name) of the passpoint profile.
     * @param enable true to enable MAC randomization, false to disable MAC randomization.
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
    public void setMacRandomizationSettingPasspointEnabled(@NonNull String fqdn, boolean enable) {
        try {
            mService.setMacRandomizationSettingPasspointEnabled(fqdn, enable);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Sets the user's choice of metered override for a Passpoint profile.
     *
     * @param fqdn the FQDN (fully qualified domain name) of the passpoint profile.
     * @param meteredOverride One of three values: {@link WifiConfiguration#METERED_OVERRIDE_NONE},
     *                        {@link WifiConfiguration#METERED_OVERRIDE_METERED},
     *                        {@link WifiConfiguration#METERED_OVERRIDE_NOT_METERED}
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
    public void setPasspointMeteredOverride(@NonNull String fqdn,
            @WifiConfiguration.MeteredOverride int meteredOverride) {
        try {
            mService.setPasspointMeteredOverride(fqdn, meteredOverride);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Temporarily disable a network. Should always trigger with user disconnect network.
     *
     * @param network Input can be SSID or FQDN. And caller must ensure that the SSID passed thru
     *                this API matched the WifiConfiguration.SSID rules, and thus be surrounded by
     *                quotes.
     * @hide
     */
    @SystemApi
    @RequiresPermission(anyOf = {
            android.Manifest.permission.NETWORK_SETTINGS,
            android.Manifest.permission.NETWORK_STACK
    })
    public void disableEphemeralNetwork(@NonNull String network) {
        if (TextUtils.isEmpty(network)) {
            throw new IllegalArgumentException("SSID cannot be null or empty!");
        }
        try {
            mService.disableEphemeralNetwork(network, mContext.getOpPackageName());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * WPS suport has been deprecated from Client mode and this method will immediately trigger
     * {@link WpsCallback#onFailed(int)} with a generic error.
     *
     * @param config WPS configuration (does not support {@link WpsInfo#LABEL})
     * @param listener for callbacks on success or failure. Can be null.
     * @throws IllegalStateException if the WifiManager instance needs to be initialized again
     * @deprecated This API is deprecated
     */
    public void startWps(WpsInfo config, WpsCallback listener) {
        if (listener != null ) {
            listener.onFailed(ERROR);
        }
    }

    /**
     * WPS support has been deprecated from Client mode and this method will immediately trigger
     * {@link WpsCallback#onFailed(int)} with a generic error.
     *
     * @param listener for callbacks on success or failure. Can be null.
     * @throws IllegalStateException if the WifiManager instance needs to be initialized again
     * @deprecated This API is deprecated
     */
    public void cancelWps(WpsCallback listener) {
        if (listener != null) {
            listener.onFailed(ERROR);
        }
    }

    /**
     * Allows an application to keep the Wi-Fi radio awake.
     * Normally the Wi-Fi radio may turn off when the user has not used the device in a while.
     * Acquiring a WifiLock will keep the radio on until the lock is released.  Multiple
     * applications may hold WifiLocks, and the radio will only be allowed to turn off when no
     * WifiLocks are held in any application.
     * <p>
     * Before using a WifiLock, consider carefully if your application requires Wi-Fi access, or
     * could function over a mobile network, if available.  A program that needs to download large
     * files should hold a WifiLock to ensure that the download will complete, but a program whose
     * network usage is occasional or low-bandwidth should not hold a WifiLock to avoid adversely
     * affecting battery life.
     * <p>
     * Note that WifiLocks cannot override the user-level "Wi-Fi Enabled" setting, nor Airplane
     * Mode.  They simply keep the radio from turning off when Wi-Fi is already on but the device
     * is idle.
     * <p>
     * Any application using a WifiLock must request the {@code android.permission.WAKE_LOCK}
     * permission in an {@code <uses-permission>} element of the application's manifest.
     */
    public class WifiLock {
        private String mTag;
        private final IBinder mBinder;
        private int mRefCount;
        int mLockType;
        private boolean mRefCounted;
        private boolean mHeld;
        private WorkSource mWorkSource;

        private WifiLock(int lockType, String tag) {
            mTag = tag;
            mLockType = lockType;
            mBinder = new Binder();
            mRefCount = 0;
            mRefCounted = true;
            mHeld = false;
        }

        /**
         * Locks the Wi-Fi radio on until {@link #release} is called.
         *
         * If this WifiLock is reference-counted, each call to {@code acquire} will increment the
         * reference count, and the radio will remain locked as long as the reference count is
         * above zero.
         *
         * If this WifiLock is not reference-counted, the first call to {@code acquire} will lock
         * the radio, but subsequent calls will be ignored.  Only one call to {@link #release}
         * will be required, regardless of the number of times that {@code acquire} is called.
         */
        public void acquire() {
            synchronized (mBinder) {
                if (mRefCounted ? (++mRefCount == 1) : (!mHeld)) {
                    try {
                        mService.acquireWifiLock(mBinder, mLockType, mTag, mWorkSource);
                        synchronized (WifiManager.this) {
                            if (mActiveLockCount >= MAX_ACTIVE_LOCKS) {
                                mService.releaseWifiLock(mBinder);
                                throw new UnsupportedOperationException(
                                            "Exceeded maximum number of wifi locks");
                            }
                            mActiveLockCount++;
                        }
                    } catch (RemoteException e) {
                        throw e.rethrowFromSystemServer();
                    }
                    mHeld = true;
                }
            }
        }

        /**
         * Unlocks the Wi-Fi radio, allowing it to turn off when the device is idle.
         *
         * If this WifiLock is reference-counted, each call to {@code release} will decrement the
         * reference count, and the radio will be unlocked only when the reference count reaches
         * zero.  If the reference count goes below zero (that is, if {@code release} is called
         * a greater number of times than {@link #acquire}), an exception is thrown.
         *
         * If this WifiLock is not reference-counted, the first call to {@code release} (after
         * the radio was locked using {@link #acquire}) will unlock the radio, and subsequent
         * calls will be ignored.
         */
        public void release() {
            synchronized (mBinder) {
                if (mRefCounted ? (--mRefCount == 0) : (mHeld)) {
                    try {
                        mService.releaseWifiLock(mBinder);
                        synchronized (WifiManager.this) {
                            mActiveLockCount--;
                        }
                    } catch (RemoteException e) {
                        throw e.rethrowFromSystemServer();
                    }
                    mHeld = false;
                }
                if (mRefCount < 0) {
                    throw new RuntimeException("WifiLock under-locked " + mTag);
                }
            }
        }

        /**
         * Controls whether this is a reference-counted or non-reference-counted WifiLock.
         *
         * Reference-counted WifiLocks keep track of the number of calls to {@link #acquire} and
         * {@link #release}, and only allow the radio to sleep when every call to {@link #acquire}
         * has been balanced with a call to {@link #release}.  Non-reference-counted WifiLocks
         * lock the radio whenever {@link #acquire} is called and it is unlocked, and unlock the
         * radio whenever {@link #release} is called and it is locked.
         *
         * @param refCounted true if this WifiLock should keep a reference count
         */
        public void setReferenceCounted(boolean refCounted) {
            mRefCounted = refCounted;
        }

        /**
         * Checks whether this WifiLock is currently held.
         *
         * @return true if this WifiLock is held, false otherwise
         */
        public boolean isHeld() {
            synchronized (mBinder) {
                return mHeld;
            }
        }

        public void setWorkSource(WorkSource ws) {
            synchronized (mBinder) {
                if (ws != null && ws.isEmpty()) {
                    ws = null;
                }
                boolean changed = true;
                if (ws == null) {
                    mWorkSource = null;
                } else {
                    ws = ws.withoutNames();
                    if (mWorkSource == null) {
                        changed = mWorkSource != null;
                        mWorkSource = new WorkSource(ws);
                    } else {
                        changed = !mWorkSource.equals(ws);
                        if (changed) {
                            mWorkSource.set(ws);
                        }
                    }
                }
                if (changed && mHeld) {
                    try {
                        mService.updateWifiLockWorkSource(mBinder, mWorkSource);
                    } catch (RemoteException e) {
                        throw e.rethrowFromSystemServer();
                    }
                }
            }
        }

        public String toString() {
            String s1, s2, s3;
            synchronized (mBinder) {
                s1 = Integer.toHexString(System.identityHashCode(this));
                s2 = mHeld ? "held; " : "";
                if (mRefCounted) {
                    s3 = "refcounted: refcount = " + mRefCount;
                } else {
                    s3 = "not refcounted";
                }
                return "WifiLock{ " + s1 + "; " + s2 + s3 + " }";
            }
        }

        @Override
        protected void finalize() throws Throwable {
            super.finalize();
            synchronized (mBinder) {
                if (mHeld) {
                    try {
                        mService.releaseWifiLock(mBinder);
                        synchronized (WifiManager.this) {
                            mActiveLockCount--;
                        }
                    } catch (RemoteException e) {
                        throw e.rethrowFromSystemServer();
                    }
                }
            }
        }
    }

    /**
     * Creates a new WifiLock.
     *
     * @param lockType the type of lock to create. See {@link #WIFI_MODE_FULL_HIGH_PERF}
     * and {@link #WIFI_MODE_FULL_LOW_LATENCY} for descriptions of the types of Wi-Fi locks.
     * @param tag a tag for the WifiLock to identify it in debugging messages.  This string is
     *            never shown to the user under normal conditions, but should be descriptive
     *            enough to identify your application and the specific WifiLock within it, if it
     *            holds multiple WifiLocks.
     *
     * @return a new, unacquired WifiLock with the given tag.
     *
     * @see WifiLock
     */
    public WifiLock createWifiLock(int lockType, String tag) {
        return new WifiLock(lockType, tag);
    }

    /**
     * Creates a new WifiLock.
     *
     * @param tag a tag for the WifiLock to identify it in debugging messages.  This string is
     *            never shown to the user under normal conditions, but should be descriptive
     *            enough to identify your application and the specific WifiLock within it, if it
     *            holds multiple WifiLocks.
     *
     * @return a new, unacquired WifiLock with the given tag.
     *
     * @see WifiLock
     *
     * @deprecated This API is non-functional.
     */
    @Deprecated
    public WifiLock createWifiLock(String tag) {
        return new WifiLock(WIFI_MODE_FULL, tag);
    }

    /**
     * Create a new MulticastLock
     *
     * @param tag a tag for the MulticastLock to identify it in debugging
     *            messages.  This string is never shown to the user under
     *            normal conditions, but should be descriptive enough to
     *            identify your application and the specific MulticastLock
     *            within it, if it holds multiple MulticastLocks.
     *
     * @return a new, unacquired MulticastLock with the given tag.
     *
     * @see MulticastLock
     */
    public MulticastLock createMulticastLock(String tag) {
        return new MulticastLock(tag);
    }

    /**
     * Allows an application to receive Wifi Multicast packets.
     * Normally the Wifi stack filters out packets not explicitly
     * addressed to this device.  Acquring a MulticastLock will
     * cause the stack to receive packets addressed to multicast
     * addresses.  Processing these extra packets can cause a noticeable
     * battery drain and should be disabled when not needed.
     */
    public class MulticastLock {
        private String mTag;
        private final IBinder mBinder;
        private int mRefCount;
        private boolean mRefCounted;
        private boolean mHeld;

        private MulticastLock(String tag) {
            mTag = tag;
            mBinder = new Binder();
            mRefCount = 0;
            mRefCounted = true;
            mHeld = false;
        }

        /**
         * Locks Wifi Multicast on until {@link #release} is called.
         *
         * If this MulticastLock is reference-counted each call to
         * {@code acquire} will increment the reference count, and the
         * wifi interface will receive multicast packets as long as the
         * reference count is above zero.
         *
         * If this MulticastLock is not reference-counted, the first call to
         * {@code acquire} will turn on the multicast packets, but subsequent
         * calls will be ignored.  Only one call to {@link #release} will
         * be required, regardless of the number of times that {@code acquire}
         * is called.
         *
         * Note that other applications may also lock Wifi Multicast on.
         * Only they can relinquish their lock.
         *
         * Also note that applications cannot leave Multicast locked on.
         * When an app exits or crashes, any Multicast locks will be released.
         */
        public void acquire() {
            synchronized (mBinder) {
                if (mRefCounted ? (++mRefCount == 1) : (!mHeld)) {
                    try {
                        mService.acquireMulticastLock(mBinder, mTag);
                        synchronized (WifiManager.this) {
                            if (mActiveLockCount >= MAX_ACTIVE_LOCKS) {
                                mService.releaseMulticastLock(mTag);
                                throw new UnsupportedOperationException(
                                        "Exceeded maximum number of wifi locks");
                            }
                            mActiveLockCount++;
                        }
                    } catch (RemoteException e) {
                        throw e.rethrowFromSystemServer();
                    }
                    mHeld = true;
                }
            }
        }

        /**
         * Unlocks Wifi Multicast, restoring the filter of packets
         * not addressed specifically to this device and saving power.
         *
         * If this MulticastLock is reference-counted, each call to
         * {@code release} will decrement the reference count, and the
         * multicast packets will only stop being received when the reference
         * count reaches zero.  If the reference count goes below zero (that
         * is, if {@code release} is called a greater number of times than
         * {@link #acquire}), an exception is thrown.
         *
         * If this MulticastLock is not reference-counted, the first call to
         * {@code release} (after the radio was multicast locked using
         * {@link #acquire}) will unlock the multicast, and subsequent calls
         * will be ignored.
         *
         * Note that if any other Wifi Multicast Locks are still outstanding
         * this {@code release} call will not have an immediate effect.  Only
         * when all applications have released all their Multicast Locks will
         * the Multicast filter be turned back on.
         *
         * Also note that when an app exits or crashes all of its Multicast
         * Locks will be automatically released.
         */
        public void release() {
            synchronized (mBinder) {
                if (mRefCounted ? (--mRefCount == 0) : (mHeld)) {
                    try {
                        mService.releaseMulticastLock(mTag);
                        synchronized (WifiManager.this) {
                            mActiveLockCount--;
                        }
                    } catch (RemoteException e) {
                        throw e.rethrowFromSystemServer();
                    }
                    mHeld = false;
                }
                if (mRefCount < 0) {
                    throw new RuntimeException("MulticastLock under-locked "
                            + mTag);
                }
            }
        }

        /**
         * Controls whether this is a reference-counted or non-reference-
         * counted MulticastLock.
         *
         * Reference-counted MulticastLocks keep track of the number of calls
         * to {@link #acquire} and {@link #release}, and only stop the
         * reception of multicast packets when every call to {@link #acquire}
         * has been balanced with a call to {@link #release}.  Non-reference-
         * counted MulticastLocks allow the reception of multicast packets
         * whenever {@link #acquire} is called and stop accepting multicast
         * packets whenever {@link #release} is called.
         *
         * @param refCounted true if this MulticastLock should keep a reference
         * count
         */
        public void setReferenceCounted(boolean refCounted) {
            mRefCounted = refCounted;
        }

        /**
         * Checks whether this MulticastLock is currently held.
         *
         * @return true if this MulticastLock is held, false otherwise
         */
        public boolean isHeld() {
            synchronized (mBinder) {
                return mHeld;
            }
        }

        public String toString() {
            String s1, s2, s3;
            synchronized (mBinder) {
                s1 = Integer.toHexString(System.identityHashCode(this));
                s2 = mHeld ? "held; " : "";
                if (mRefCounted) {
                    s3 = "refcounted: refcount = " + mRefCount;
                } else {
                    s3 = "not refcounted";
                }
                return "MulticastLock{ " + s1 + "; " + s2 + s3 + " }";
            }
        }

        @Override
        protected void finalize() throws Throwable {
            super.finalize();
            setReferenceCounted(false);
            release();
        }
    }

    /**
     * Check multicast filter status.
     *
     * @return true if multicast packets are allowed.
     *
     * @hide pending API council approval
     */
    public boolean isMulticastEnabled() {
        try {
            return mService.isMulticastEnabled();
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Initialize the multicast filtering to 'on'
     * @hide no intent to publish
     */
    @UnsupportedAppUsage
    public boolean initializeMulticastFiltering() {
        try {
            mService.initializeMulticastFiltering();
            return true;
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Set Wi-Fi verbose logging level from developer settings.
     *
     * @param enable true to enable verbose logging, false to disable.
     *
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
    public void setVerboseLoggingEnabled(boolean enable) {
        enableVerboseLogging(enable ? VERBOSE_LOGGING_LEVEL_ENABLED
                : VERBOSE_LOGGING_LEVEL_DISABLED);
    }

    /**
     * Set Wi-Fi verbose logging level from developer settings.
     *
     * @param verbose the verbose logging mode which could be
     * {@link #VERBOSE_LOGGING_LEVEL_DISABLED}, {@link #VERBOSE_LOGGING_LEVEL_ENABLED}, or
     * {@link #VERBOSE_LOGGING_LEVEL_ENABLED_SHOW_KEY}.
     *
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
    public void setVerboseLoggingLevel(@VerboseLoggingLevel int verbose) {
        enableVerboseLogging(verbose);
    }

    /** @hide */
    @UnsupportedAppUsage(
            maxTargetSdk = Build.VERSION_CODES.Q,
            publicAlternatives = "Use {@code #setVerboseLoggingEnabled(boolean)} instead."
    )
    @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
    public void enableVerboseLogging(@VerboseLoggingLevel int verbose) {
        try {
            mService.enableVerboseLogging(verbose);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Get the persisted Wi-Fi verbose logging level, set by
     * {@link #setVerboseLoggingEnabled(boolean)} or {@link #setVerboseLoggingLevel(int)}.
     * No permissions are required to call this method.
     *
     * @return true to indicate that verbose logging is enabled, false to indicate that verbose
     * logging is disabled.
     *
     * @hide
     */
    @SystemApi
    public boolean isVerboseLoggingEnabled() {
        return getVerboseLoggingLevel() > 0;
    }

    /**
     * Get the persisted Wi-Fi verbose logging level, set by
     * {@link #setVerboseLoggingEnabled(boolean)} or {@link #setVerboseLoggingLevel(int)}.
     * No permissions are required to call this method.
     *
     * @return one of {@link #VERBOSE_LOGGING_LEVEL_DISABLED},
     *         {@link #VERBOSE_LOGGING_LEVEL_ENABLED},
     *         or {@link #VERBOSE_LOGGING_LEVEL_ENABLED_SHOW_KEY}.
     *
     * @hide
     */
    @SystemApi
    public @VerboseLoggingLevel int getVerboseLoggingLevel() {
        try {
            return mService.getVerboseLoggingLevel();
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Removes all saved Wi-Fi networks, Passpoint configurations, ephemeral networks, Network
     * Requests, and Network Suggestions.
     *
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
    public void factoryReset() {
        try {
            mService.factoryReset(mContext.getOpPackageName());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Get {@link Network} object of current wifi network, or null if not connected.
     * @hide
     */
    @Nullable
    @SystemApi
    @RequiresPermission(anyOf = {
            android.Manifest.permission.NETWORK_SETTINGS,
            android.Manifest.permission.NETWORK_SETUP_WIZARD
    })
    public Network getCurrentNetwork() {
        try {
            return mService.getCurrentNetwork();
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Deprecated
     * returns false
     * @hide
     * @deprecated
     */
    public boolean setEnableAutoJoinWhenAssociated(boolean enabled) {
        return false;
    }

    /**
     * Deprecated
     * returns false
     * @hide
     * @deprecated
     */
    public boolean getEnableAutoJoinWhenAssociated() {
        return false;
    }

    /**
     * Returns a byte stream representing the data that needs to be backed up to save the
     * current Wifi state.
     * This Wifi state can be restored by calling {@link #restoreBackupData(byte[])}.
     * @hide
     */
    @NonNull
    @SystemApi
    @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
    public byte[] retrieveBackupData() {
        try {
            return mService.retrieveBackupData();
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Restore state from the backed up data.
     * @param data byte stream in the same format produced by {@link #retrieveBackupData()}
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
    public void restoreBackupData(@NonNull byte[] data) {
        try {
            mService.restoreBackupData(data);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Returns a byte stream representing the data that needs to be backed up to save the
     * current soft ap config data.
     *
     * This soft ap config can be restored by calling {@link #restoreSoftApBackupData(byte[])}
     * @hide
     */
    @NonNull
    @SystemApi
    @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
    public byte[] retrieveSoftApBackupData() {
        try {
            return mService.retrieveSoftApBackupData();
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Returns soft ap config from the backed up data or null if data is invalid.
     * @param data byte stream in the same format produced by {@link #retrieveSoftApBackupData()}
     *
     * @hide
     */
    @Nullable
    @SystemApi
    @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
    public SoftApConfiguration restoreSoftApBackupData(@NonNull byte[] data) {
        try {
            return mService.restoreSoftApBackupData(data);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Restore state from the older version of back up data.
     * The old backup data was essentially a backup of wpa_supplicant.conf
     * and ipconfig.txt file.
     * @param supplicantData bytes representing wpa_supplicant.conf
     * @param ipConfigData bytes representing ipconfig.txt
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
    public void restoreSupplicantBackupData(
            @NonNull byte[] supplicantData, @NonNull byte[] ipConfigData) {
        try {
            mService.restoreSupplicantBackupData(supplicantData, ipConfigData);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Start subscription provisioning flow
     *
     * @param provider {@link OsuProvider} to provision with
     * @param executor the Executor on which to run the callback.
     * @param callback {@link ProvisioningCallback} for updates regarding provisioning flow
     * @hide
     */
    @SystemApi
    @RequiresPermission(anyOf = {
            android.Manifest.permission.NETWORK_SETTINGS,
            android.Manifest.permission.NETWORK_SETUP_WIZARD
    })
    public void startSubscriptionProvisioning(@NonNull OsuProvider provider,
            @NonNull @CallbackExecutor Executor executor, @NonNull ProvisioningCallback callback) {
        // Verify arguments
        if (executor == null) {
            throw new IllegalArgumentException("executor must not be null");
        }
        if (callback == null) {
            throw new IllegalArgumentException("callback must not be null");
        }
        try {
            mService.startSubscriptionProvisioning(provider,
                    new ProvisioningCallbackProxy(executor, callback));
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Helper class to support OSU Provisioning callbacks
     */
    private static class ProvisioningCallbackProxy extends IProvisioningCallback.Stub {
        private final Executor mExecutor;
        private final ProvisioningCallback mCallback;

        ProvisioningCallbackProxy(Executor executor, ProvisioningCallback callback) {
            mExecutor = executor;
            mCallback = callback;
        }

        @Override
        public void onProvisioningStatus(int status) {
            mExecutor.execute(() -> mCallback.onProvisioningStatus(status));
        }

        @Override
        public void onProvisioningFailure(int status) {
            mExecutor.execute(() -> mCallback.onProvisioningFailure(status));
        }

        @Override
        public void onProvisioningComplete() {
            mExecutor.execute(() -> mCallback.onProvisioningComplete());
        }
    }

    /**
     * Interface for Traffic state callback. Should be extended by applications and set when
     * calling {@link #registerTrafficStateCallback(Executor, WifiManager.TrafficStateCallback)}.
     * @hide
     */
    @SystemApi
    public interface TrafficStateCallback {
        /** @hide */
        @Retention(RetentionPolicy.SOURCE)
        @IntDef(prefix = {"DATA_ACTIVITY_"}, value = {
                DATA_ACTIVITY_NONE,
                DATA_ACTIVITY_IN,
                DATA_ACTIVITY_OUT,
                DATA_ACTIVITY_INOUT})
        @interface DataActivity {}

        // Lowest bit indicates data reception and the second lowest bit indicates data transmitted
        /** No data in or out */
        int DATA_ACTIVITY_NONE         = 0x00;
        /** Data in, no data out */
        int DATA_ACTIVITY_IN           = 0x01;
        /** Data out, no data in */
        int DATA_ACTIVITY_OUT          = 0x02;
        /** Data in and out */
        int DATA_ACTIVITY_INOUT        = 0x03;

        /**
         * Callback invoked to inform clients about the current traffic state.
         *
         * @param state One of the values: {@link #DATA_ACTIVITY_NONE}, {@link #DATA_ACTIVITY_IN},
         * {@link #DATA_ACTIVITY_OUT} & {@link #DATA_ACTIVITY_INOUT}.
         */
        void onStateChanged(@DataActivity int state);
    }

    /**
     * Callback proxy for TrafficStateCallback objects.
     *
     * @hide
     */
    private class TrafficStateCallbackProxy extends ITrafficStateCallback.Stub {
        private final Executor mExecutor;
        private final TrafficStateCallback mCallback;

        TrafficStateCallbackProxy(Executor executor, TrafficStateCallback callback) {
            mExecutor = executor;
            mCallback = callback;
        }

        @Override
        public void onStateChanged(int state) {
            if (mVerboseLoggingEnabled) {
                Log.v(TAG, "TrafficStateCallbackProxy: onStateChanged state=" + state);
            }
            Binder.clearCallingIdentity();
            mExecutor.execute(() -> {
                mCallback.onStateChanged(state);
            });
        }
    }

    /**
     * Registers a callback for monitoring traffic state. See {@link TrafficStateCallback}. These
     * callbacks will be invoked periodically by platform to inform clients about the current
     * traffic state. Caller can unregister a previously registered callback using
     * {@link #unregisterTrafficStateCallback(TrafficStateCallback)}
     * <p>
     * Applications should have the
     * {@link android.Manifest.permission#NETWORK_SETTINGS NETWORK_SETTINGS} permission. Callers
     * without the permission will trigger a {@link java.lang.SecurityException}.
     * <p>
     *
     * @param executor The Executor on whose thread to execute the callbacks of the {@code callback}
     *                 object.
     * @param callback Callback for traffic state events
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
    public void registerTrafficStateCallback(@NonNull @CallbackExecutor Executor executor,
                                             @NonNull TrafficStateCallback callback) {
        if (executor == null) throw new IllegalArgumentException("executor cannot be null");
        if (callback == null) throw new IllegalArgumentException("callback cannot be null");
        Log.v(TAG, "registerTrafficStateCallback: callback=" + callback + ", executor=" + executor);

        try {
            synchronized (sTrafficStateCallbackMap) {
                ITrafficStateCallback.Stub binderCallback = new TrafficStateCallbackProxy(executor,
                        callback);
                sTrafficStateCallbackMap.put(System.identityHashCode(callback), binderCallback);
                mService.registerTrafficStateCallback(binderCallback);
            }
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Allow callers to unregister a previously registered callback. After calling this method,
     * applications will no longer receive traffic state notifications.
     *
     * @param callback Callback to unregister for traffic state events
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
    public void unregisterTrafficStateCallback(@NonNull TrafficStateCallback callback) {
        if (callback == null) throw new IllegalArgumentException("callback cannot be null");
        Log.v(TAG, "unregisterTrafficStateCallback: callback=" + callback);

        try {
            synchronized (sTrafficStateCallbackMap) {
                int callbackIdentifier = System.identityHashCode(callback);
                if (!sTrafficStateCallbackMap.contains(callbackIdentifier)) {
                    Log.w(TAG, "Unknown external callback " + callbackIdentifier);
                    return;
                }
                mService.unregisterTrafficStateCallback(
                        sTrafficStateCallbackMap.get(callbackIdentifier));
                sTrafficStateCallbackMap.remove(callbackIdentifier);
            }
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Helper method to update the local verbose logging flag based on the verbose logging
     * level from wifi service.
     */
    private void updateVerboseLoggingEnabledFromService() {
        mVerboseLoggingEnabled = isVerboseLoggingEnabled();
    }

    /**
     * @return true if this device supports WPA3-Personal SAE
     */
    public boolean isWpa3SaeSupported() {
        return isFeatureSupported(WIFI_FEATURE_WPA3_SAE);
    }

    /**
     * @return true if this device supports WPA3-Enterprise Suite-B-192
     */
    public boolean isWpa3SuiteBSupported() {
        return isFeatureSupported(WIFI_FEATURE_WPA3_SUITE_B);
    }

    /**
     * @return true if this device supports Wi-Fi Enhanced Open (OWE)
     */
    public boolean isEnhancedOpenSupported() {
        return isFeatureSupported(WIFI_FEATURE_OWE);
    }

    /**
     * Wi-Fi Easy Connect (DPP) introduces standardized mechanisms to simplify the provisioning and
     * configuration of Wi-Fi devices.
     * For more details, visit <a href="https://www.wi-fi.org/">https://www.wi-fi.org/</a> and
     * search for "Easy Connect" or "Device Provisioning Protocol specification".
     *
     * @return true if this device supports Wi-Fi Easy-connect (Device Provisioning Protocol)
     */
    public boolean isEasyConnectSupported() {
        return isFeatureSupported(WIFI_FEATURE_DPP);
    }

    /**
     * @return true if this device supports Wi-Fi Easy Connect (DPP) Enrollee Responder mode.
     */
    public boolean isEasyConnectEnrolleeResponderModeSupported() {
        return isFeatureSupported(WIFI_FEATURE_DPP_ENROLLEE_RESPONDER);
    }

    /**
     * @return true if this device supports WAPI.
     */
    public boolean isWapiSupported() {
        return isFeatureSupported(WIFI_FEATURE_WAPI);
    }

    /**
     * @return true if this device supports WPA3 SAE Public Key.
     */
    public boolean isWpa3SaePublicKeySupported() {
        // This feature is not fully implemented in the framework yet.
        // After the feature complete, it returns whether WIFI_FEATURE_SAE_PK
        // is supported or not directly.
        return false;
    }

    /**
     * @return true if this device supports Wi-Fi Passpoint Terms and Conditions feature.
     */
    public boolean isPasspointTermsAndConditionsSupported() {
        return isFeatureSupported(WIFI_FEATURE_PASSPOINT_TERMS_AND_CONDITIONS);
    }

    /**
     * @return true if this device supports WPA3 SAE Hash-to-Element.
     */
    public boolean isWpa3SaeH2eSupported() {
        return isFeatureSupported(WIFI_FEATURE_SAE_H2E);
    }

    /**
     * @return true if this device supports Wi-Fi Display R2.
     */
    public boolean isWifiDisplayR2Supported() {
        return isFeatureSupported(WIFI_FEATURE_WFD_R2);
    }

    /**
     * @return true if this device supports RFC 7542 decorated identity.
     */
    public boolean isDecoratedIdentitySupported() {
        return isFeatureSupported(WIFI_FEATURE_DECORATED_IDENTITY);
    }

    /**
     * Gets the factory Wi-Fi MAC addresses.
     * @return Array of String representing Wi-Fi MAC addresses sorted lexically or an empty Array
     * if failed.
     * @hide
     */
    @NonNull
    @SystemApi
    @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
    public String[] getFactoryMacAddresses() {
        try {
            return mService.getFactoryMacAddresses();
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /** @hide */
    @Retention(RetentionPolicy.SOURCE)
    @IntDef(prefix = {"DEVICE_MOBILITY_STATE_"}, value = {
            DEVICE_MOBILITY_STATE_UNKNOWN,
            DEVICE_MOBILITY_STATE_HIGH_MVMT,
            DEVICE_MOBILITY_STATE_LOW_MVMT,
            DEVICE_MOBILITY_STATE_STATIONARY})
    public @interface DeviceMobilityState {}

    /**
     * Unknown device mobility state
     *
     * @see #setDeviceMobilityState(int)
     *
     * @hide
     */
    @SystemApi
    public static final int DEVICE_MOBILITY_STATE_UNKNOWN = 0;

    /**
     * High movement device mobility state.
     * e.g. on a bike, in a motor vehicle
     *
     * @see #setDeviceMobilityState(int)
     *
     * @hide
     */
    @SystemApi
    public static final int DEVICE_MOBILITY_STATE_HIGH_MVMT = 1;

    /**
     * Low movement device mobility state.
     * e.g. walking, running
     *
     * @see #setDeviceMobilityState(int)
     *
     * @hide
     */
    @SystemApi
    public static final int DEVICE_MOBILITY_STATE_LOW_MVMT = 2;

    /**
     * Stationary device mobility state
     *
     * @see #setDeviceMobilityState(int)
     *
     * @hide
     */
    @SystemApi
    public static final int DEVICE_MOBILITY_STATE_STATIONARY = 3;

    /**
     * Updates the device mobility state. Wifi uses this information to adjust the interval between
     * Wifi scans in order to balance power consumption with scan accuracy.
     * The default mobility state when the device boots is {@link #DEVICE_MOBILITY_STATE_UNKNOWN}.
     * This API should be called whenever there is a change in the mobility state.
     * @param state the updated device mobility state
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.WIFI_SET_DEVICE_MOBILITY_STATE)
    public void setDeviceMobilityState(@DeviceMobilityState int state) {
        try {
            mService.setDeviceMobilityState(state);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /* Easy Connect - AKA Device Provisioning Protocol (DPP) */

    /**
     * Easy Connect Network role: Station.
     *
     * @hide
     */
    @SystemApi
    public static final int EASY_CONNECT_NETWORK_ROLE_STA = 0;

    /**
     * Easy Connect Network role: Access Point.
     *
     * @hide
     */
    @SystemApi
    public static final int EASY_CONNECT_NETWORK_ROLE_AP = 1;

    /** @hide */
    @IntDef(prefix = {"EASY_CONNECT_NETWORK_ROLE_"}, value = {
            EASY_CONNECT_NETWORK_ROLE_STA,
            EASY_CONNECT_NETWORK_ROLE_AP,
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface EasyConnectNetworkRole {
    }

    /** Easy Connect Device information maximum allowed length */
    private static final int EASY_CONNECT_DEVICE_INFO_MAXIMUM_LENGTH = 40;

    /**
     * Easy Connect Cryptography Curve name: prime256v1
     *
     * @hide
     */
    @SystemApi
    public static final int EASY_CONNECT_CRYPTOGRAPHY_CURVE_PRIME256V1 = 0;

    /**
     * Easy Connect Cryptography Curve name: secp384r1
     *
     * @hide
     */
    @SystemApi
    public static final int EASY_CONNECT_CRYPTOGRAPHY_CURVE_SECP384R1 = 1;

    /**
     * Easy Connect Cryptography Curve name: secp521r1
     *
     * @hide
     */
    @SystemApi
    public static final int EASY_CONNECT_CRYPTOGRAPHY_CURVE_SECP521R1 = 2;


    /**
     * Easy Connect Cryptography Curve name: brainpoolP256r1
     *
     * @hide
     */
    @SystemApi
    public static final int EASY_CONNECT_CRYPTOGRAPHY_CURVE_BRAINPOOLP256R1 = 3;


    /**
     * Easy Connect Cryptography Curve name: brainpoolP384r1
     *
     * @hide
     */
    @SystemApi
    public static final int EASY_CONNECT_CRYPTOGRAPHY_CURVE_BRAINPOOLP384R1 = 4;


    /**
     * Easy Connect Cryptography Curve name: brainpoolP512r1
     *
     * @hide
     */
    @SystemApi
    public static final int EASY_CONNECT_CRYPTOGRAPHY_CURVE_BRAINPOOLP512R1 = 5;

    /** @hide */
    @IntDef(prefix = {"EASY_CONNECT_CRYPTOGRAPHY_CURVE_"}, value = {
            EASY_CONNECT_CRYPTOGRAPHY_CURVE_PRIME256V1,
            EASY_CONNECT_CRYPTOGRAPHY_CURVE_SECP384R1,
            EASY_CONNECT_CRYPTOGRAPHY_CURVE_SECP521R1,
            EASY_CONNECT_CRYPTOGRAPHY_CURVE_BRAINPOOLP256R1,
            EASY_CONNECT_CRYPTOGRAPHY_CURVE_BRAINPOOLP384R1,
            EASY_CONNECT_CRYPTOGRAPHY_CURVE_BRAINPOOLP512R1,
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface EasyConnectCryptographyCurve {
    }

    /**
     * Verbose logging mode: DISABLED.
     * @hide
     */
    @SystemApi
    public static final int VERBOSE_LOGGING_LEVEL_DISABLED = 0;

    /**
     * Verbose logging mode: ENABLED.
     * @hide
     */
    @SystemApi
    public static final int VERBOSE_LOGGING_LEVEL_ENABLED = 1;

    /**
     * Verbose logging mode: ENABLED_SHOW_KEY.
     * This mode causes the Wi-Fi password and encryption keys to be output to the logcat.
     * This is security sensitive information useful for debugging.
     * This configuration is enabled for 30 seconds and then falls back to
     * the regular verbose mode (i.e. to {@link VERBOSE_LOGGING_LEVEL_ENABLED}).
     * Show key mode is not persistent, i.e. rebooting the device would fallback to
     * the regular verbose mode.
     * @hide
     */
    @SystemApi
    public static final int VERBOSE_LOGGING_LEVEL_ENABLED_SHOW_KEY = 2;

    /** @hide */
    @IntDef(prefix = {"VERBOSE_LOGGING_LEVEL_"}, value = {
            VERBOSE_LOGGING_LEVEL_DISABLED,
            VERBOSE_LOGGING_LEVEL_ENABLED,
            VERBOSE_LOGGING_LEVEL_ENABLED_SHOW_KEY,
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface VerboseLoggingLevel {
    }

    /**
     * Start Easy Connect (DPP) in Configurator-Initiator role. The current device will initiate
     * Easy Connect bootstrapping with a peer, and configure the peer with the SSID and password of
     * the specified network using the Easy Connect protocol on an encrypted link.
     *
     * @param enrolleeUri         URI of the Enrollee obtained separately (e.g. QR code scanning)
     * @param selectedNetworkId   Selected network ID to be sent to the peer
     * @param enrolleeNetworkRole The network role of the enrollee
     * @param callback            Callback for status updates
     * @param executor            The Executor on which to run the callback.
     * @hide
     */
    @SystemApi
    @RequiresPermission(anyOf = {
            android.Manifest.permission.NETWORK_SETTINGS,
            android.Manifest.permission.NETWORK_SETUP_WIZARD})
    public void startEasyConnectAsConfiguratorInitiator(@NonNull String enrolleeUri,
            int selectedNetworkId, @EasyConnectNetworkRole int enrolleeNetworkRole,
            @NonNull @CallbackExecutor Executor executor,
            @NonNull EasyConnectStatusCallback callback) {
        Binder binder = new Binder();
        try {
            mService.startDppAsConfiguratorInitiator(binder, mContext.getOpPackageName(),
                    enrolleeUri, selectedNetworkId, enrolleeNetworkRole,
                    new EasyConnectCallbackProxy(executor, callback));
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Start Easy Connect (DPP) in Enrollee-Initiator role. The current device will initiate Easy
     * Connect bootstrapping with a peer, and receive the SSID and password from the peer
     * configurator.
     *
     * @param configuratorUri URI of the Configurator obtained separately (e.g. QR code scanning)
     * @param callback        Callback for status updates
     * @param executor        The Executor on which to run the callback.
     * @hide
     */
    @SystemApi
    @RequiresPermission(anyOf = {
            android.Manifest.permission.NETWORK_SETTINGS,
            android.Manifest.permission.NETWORK_SETUP_WIZARD})
    public void startEasyConnectAsEnrolleeInitiator(@NonNull String configuratorUri,
            @NonNull @CallbackExecutor Executor executor,
            @NonNull EasyConnectStatusCallback callback) {
        Binder binder = new Binder();
        try {
            mService.startDppAsEnrolleeInitiator(binder, configuratorUri,
                    new EasyConnectCallbackProxy(executor, callback));
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Start Easy Connect (DPP) in Enrollee-Responder role.
     * The device will:
     * 1. Generate a DPP bootstrap URI and return it using the
     * {@link EasyConnectStatusCallback#onBootstrapUriGenerated(Uri)} method.
     * 2. Start DPP as a Responder, waiting for an Initiator device to start the DPP
     * authentication process.
     * The caller should use the URI provided in step #1, for instance display it as a QR code
     * or communicate it in some other way to the initiator device.
     *
     * @param deviceInfo      Device specific information to add to the DPP URI. This field allows
     *                        the users of the configurators to identify the device.
     *                        Optional - if not provided or in case of an empty string,
     *                        Info field (I:) will be skipped in the generated DPP URI.
     *                        Allowed Range of ASCII characters in deviceInfo - %x20-7E.
     *                        semicolon and space are not allowed. Due to the limitation of maximum
     *                        allowed characters in QR code, framework adds a limit to maximum
     *                        characters in deviceInfo. Users must call
     *                        {@link WifiManager#getEasyConnectMaxAllowedResponderDeviceInfoLength()
     *                        } method to know max allowed length. Violation of these rules will
     *                        result in an exception.
     * @param curve           Elliptic curve cryptography used to generate DPP
     *                        public/private key pair. If application is not interested in a
     *                        specific curve, use specification mandated NIST P-256 elliptic curve,
     *                        {@link WifiManager#EASY_CONNECT_CRYPTOGRAPHY_CURVE_PRIME256V1}.
     * @param callback        Callback for status updates
     * @param executor        The Executor on which to run the callback.
     * @hide
     */
    @SystemApi
    @RequiresPermission(anyOf = {
            android.Manifest.permission.NETWORK_SETTINGS,
            android.Manifest.permission.NETWORK_SETUP_WIZARD})
    @RequiresApi(Build.VERSION_CODES.S)
    public void startEasyConnectAsEnrolleeResponder(@Nullable String deviceInfo,
            @EasyConnectCryptographyCurve int curve,
            @NonNull @CallbackExecutor Executor executor,
            @NonNull EasyConnectStatusCallback callback) {
        Binder binder = new Binder();
        try {
            mService.startDppAsEnrolleeResponder(binder, deviceInfo, curve,
                    new EasyConnectCallbackProxy(executor, callback));
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Maximum allowed length of Device specific information that can be added to the URI of
     * Easy Connect responder device.
     * @see #startEasyConnectAsEnrolleeResponder(String, int, Executor, EasyConnectStatusCallback)}
     *
     * @hide
     */
    @SystemApi
    public static int getEasyConnectMaxAllowedResponderDeviceInfoLength() {
        return EASY_CONNECT_DEVICE_INFO_MAXIMUM_LENGTH;
    }

    /**
     * Stop or abort a current Easy Connect (DPP) session. This call, once processed, will
     * terminate any ongoing transaction, and clean up all associated resources. Caller should not
     * expect any callbacks once this call is made. However, due to the asynchronous nature of
     * this call, a callback may be fired if it was already pending in the queue.
     *
     * @hide
     */
    @SystemApi
    @RequiresPermission(anyOf = {
            android.Manifest.permission.NETWORK_SETTINGS,
            android.Manifest.permission.NETWORK_SETUP_WIZARD})
    public void stopEasyConnectSession() {
        try {
            /* Request lower layers to stop/abort and clear resources */
            mService.stopDppSession();
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Helper class to support Easy Connect (DPP) callbacks
     *
     * @hide
     */
    private static class EasyConnectCallbackProxy extends IDppCallback.Stub {
        private final Executor mExecutor;
        private final EasyConnectStatusCallback mEasyConnectStatusCallback;

        EasyConnectCallbackProxy(Executor executor,
                EasyConnectStatusCallback easyConnectStatusCallback) {
            mExecutor = executor;
            mEasyConnectStatusCallback = easyConnectStatusCallback;
        }

        @Override
        public void onSuccessConfigReceived(int newNetworkId) {
            Log.d(TAG, "Easy Connect onSuccessConfigReceived callback");
            Binder.clearCallingIdentity();
            mExecutor.execute(() -> {
                mEasyConnectStatusCallback.onEnrolleeSuccess(newNetworkId);
            });
        }

        @Override
        public void onSuccess(int status) {
            Log.d(TAG, "Easy Connect onSuccess callback");
            Binder.clearCallingIdentity();
            mExecutor.execute(() -> {
                mEasyConnectStatusCallback.onConfiguratorSuccess(status);
            });
        }

        @Override
        public void onFailure(int status, String ssid, String channelList,
                int[] operatingClassArray) {
            Log.d(TAG, "Easy Connect onFailure callback");
            Binder.clearCallingIdentity();
            mExecutor.execute(() -> {
                SparseArray<int[]> channelListArray = parseDppChannelList(channelList);
                mEasyConnectStatusCallback.onFailure(status, ssid, channelListArray,
                        operatingClassArray);
            });
        }

        @Override
        public void onProgress(int status) {
            Log.d(TAG, "Easy Connect onProgress callback");
            Binder.clearCallingIdentity();
            mExecutor.execute(() -> {
                mEasyConnectStatusCallback.onProgress(status);
            });
        }

        @Override
        public void onBootstrapUriGenerated(@NonNull String uri) {
            Log.d(TAG, "Easy Connect onBootstrapUriGenerated callback");
            if (!SdkLevel.isAtLeastS()) {
                Log.e(TAG, "Easy Connect bootstrap URI callback supported only on S+");
                return;
            }
            Binder.clearCallingIdentity();
            mExecutor.execute(() -> {
                mEasyConnectStatusCallback.onBootstrapUriGenerated(Uri.parse(uri));
            });
        }
    }

    /**
     * Interface for Wi-Fi usability statistics listener. Should be implemented by applications and
     * set when calling {@link WifiManager#addOnWifiUsabilityStatsListener(Executor,
     * OnWifiUsabilityStatsListener)}.
     *
     * @hide
     */
    @SystemApi
    public interface OnWifiUsabilityStatsListener {
        /**
         * Called when Wi-Fi usability statistics is updated.
         *
         * @param seqNum The sequence number of statistics, used to derive the timing of updated
         *               Wi-Fi usability statistics, set by framework and incremented by one after
         *               each update.
         * @param isSameBssidAndFreq The flag to indicate whether the BSSID and the frequency of
         *                           network stays the same or not relative to the last update of
         *                           Wi-Fi usability stats.
         * @param stats The updated Wi-Fi usability statistics.
         */
        void onWifiUsabilityStats(int seqNum, boolean isSameBssidAndFreq,
                @NonNull WifiUsabilityStatsEntry stats);
    }

    /**
     * Interface for Wi-Fi verbose logging status listener. Should be implemented by applications
     * and set when calling {@link WifiManager#addWifiVerboseLoggingStatusListener(Executor,
     * WifiVerboseLoggingStatusListener)}.
     *
     * @hide
     */
    @SystemApi
    public interface WifiVerboseLoggingStatusChangedListener {
        /**
         * Called when Wi-Fi verbose logging setting is updated.
         *
         * @param enabled true if verbose logging is enabled, false if verbose logging is disabled.
         */
        void onWifiVerboseLoggingStatusChanged(boolean enabled);
    }

    /**
     * Adds a listener for Wi-Fi usability statistics. See {@link OnWifiUsabilityStatsListener}.
     * Multiple listeners can be added. Callers will be invoked periodically by framework to
     * inform clients about the current Wi-Fi usability statistics. Callers can remove a previously
     * added listener using
     * {@link #removeOnWifiUsabilityStatsListener(OnWifiUsabilityStatsListener)}.
     *
     * @param executor The executor on which callback will be invoked.
     * @param listener Listener for Wifi usability statistics.
     *
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE)
    public void addOnWifiUsabilityStatsListener(@NonNull @CallbackExecutor Executor executor,
            @NonNull OnWifiUsabilityStatsListener listener) {
        if (executor == null) throw new IllegalArgumentException("executor cannot be null");
        if (listener == null) throw new IllegalArgumentException("listener cannot be null");
        if (mVerboseLoggingEnabled) {
            Log.v(TAG, "addOnWifiUsabilityStatsListener: listener=" + listener);
        }
        try {
            synchronized (sOnWifiUsabilityStatsListenerMap) {
                IOnWifiUsabilityStatsListener.Stub binderCallback =
                        new IOnWifiUsabilityStatsListener.Stub() {
                            @Override
                            public void onWifiUsabilityStats(int seqNum, boolean isSameBssidAndFreq,
                                    WifiUsabilityStatsEntry stats) {
                                if (mVerboseLoggingEnabled) {
                                    Log.v(TAG, "OnWifiUsabilityStatsListener: "
                                            + "onWifiUsabilityStats: seqNum=" + seqNum);
                                }
                                Binder.clearCallingIdentity();
                                executor.execute(() -> listener.onWifiUsabilityStats(
                                        seqNum, isSameBssidAndFreq, stats));
                            }
                        };
                sOnWifiUsabilityStatsListenerMap.put(System.identityHashCode(listener),
                        binderCallback);
                mService.addOnWifiUsabilityStatsListener(binderCallback);
            }
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Allow callers to remove a previously registered listener. After calling this method,
     * applications will no longer receive Wi-Fi usability statistics.
     *
     * @param listener Listener to remove the Wi-Fi usability statistics.
     *
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE)
    public void removeOnWifiUsabilityStatsListener(@NonNull OnWifiUsabilityStatsListener listener) {
        if (listener == null) throw new IllegalArgumentException("listener cannot be null");
        if (mVerboseLoggingEnabled) {
            Log.v(TAG, "removeOnWifiUsabilityStatsListener: listener=" + listener);
        }
        try {
            synchronized (sOnWifiUsabilityStatsListenerMap) {
                int listenerIdentifier = System.identityHashCode(listener);
                if (!sOnWifiUsabilityStatsListenerMap.contains(listenerIdentifier)) {
                    Log.w(TAG, "Unknown external callback " + listenerIdentifier);
                    return;
                }
                mService.removeOnWifiUsabilityStatsListener(
                        sOnWifiUsabilityStatsListenerMap.get(listenerIdentifier));
                sOnWifiUsabilityStatsListenerMap.remove(listenerIdentifier);
            }
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Provide a Wi-Fi usability score information to be recorded (but not acted upon) by the
     * framework. The Wi-Fi usability score is derived from {@link OnWifiUsabilityStatsListener}
     * where a score is matched to Wi-Fi usability statistics using the sequence number. The score
     * is used to quantify whether Wi-Fi is usable in a future time.
     *
     * @param seqNum Sequence number of the Wi-Fi usability score.
     * @param score The Wi-Fi usability score, expected range: [0, 100].
     * @param predictionHorizonSec Prediction horizon of the Wi-Fi usability score in second,
     *                             expected range: [0, 30].
     *
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE)
    public void updateWifiUsabilityScore(int seqNum, int score, int predictionHorizonSec) {
        try {
            mService.updateWifiUsabilityScore(seqNum, score, predictionHorizonSec);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Abstract class for scan results callback. Should be extended by applications and set when
     * calling {@link WifiManager#registerScanResultsCallback(Executor, ScanResultsCallback)}.
     */
    public abstract static class ScanResultsCallback {
        private final ScanResultsCallbackProxy mScanResultsCallbackProxy;

        public ScanResultsCallback() {
            mScanResultsCallbackProxy = new ScanResultsCallbackProxy();
        }

        /**
         * Called when new scan results are available.
         * Clients should use {@link WifiManager#getScanResults()} to get the scan results.
         */
        public abstract void onScanResultsAvailable();

        /*package*/ @NonNull ScanResultsCallbackProxy getProxy() {
            return mScanResultsCallbackProxy;
        }

        private static class ScanResultsCallbackProxy extends IScanResultsCallback.Stub {
            private final Object mLock = new Object();
            @Nullable @GuardedBy("mLock") private Executor mExecutor;
            @Nullable @GuardedBy("mLock") private ScanResultsCallback mCallback;

            ScanResultsCallbackProxy() {
                mCallback = null;
                mExecutor = null;
            }

            /*package*/ void initProxy(@NonNull Executor executor,
                    @NonNull ScanResultsCallback callback) {
                synchronized (mLock) {
                    mExecutor = executor;
                    mCallback = callback;
                }
            }

            /*package*/ void cleanUpProxy() {
                synchronized (mLock) {
                    mExecutor = null;
                    mCallback = null;
                }
            }

            @Override
            public void onScanResultsAvailable() {
                ScanResultsCallback callback;
                Executor executor;
                synchronized (mLock) {
                    executor = mExecutor;
                    callback = mCallback;
                }
                if (callback == null || executor == null) {
                    return;
                }
                Binder.clearCallingIdentity();
                executor.execute(callback::onScanResultsAvailable);
            }
        }
    }

    /**
     * Register a callback for Scan Results. See {@link ScanResultsCallback}.
     * Caller will receive the event when scan results are available.
     * Caller should use {@link WifiManager#getScanResults()} requires
     * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} to get the scan results.
     * Caller can remove a previously registered callback using
     * {@link WifiManager#unregisterScanResultsCallback(ScanResultsCallback)}
     * Same caller can add multiple listeners.
     * <p>
     * Applications should have the
     * {@link android.Manifest.permission#ACCESS_WIFI_STATE} permission. Callers
     * without the permission will trigger a {@link java.lang.SecurityException}.
     * <p>
     *
     * @param executor The executor to execute the callback of the {@code callback} object.
     * @param callback callback for Scan Results events
     */

    @RequiresPermission(ACCESS_WIFI_STATE)
    public void registerScanResultsCallback(@NonNull @CallbackExecutor Executor executor,
            @NonNull ScanResultsCallback callback) {
        if (executor == null) throw new IllegalArgumentException("executor cannot be null");
        if (callback == null) throw new IllegalArgumentException("callback cannot be null");

        Log.v(TAG, "registerScanResultsCallback: callback=" + callback
                + ", executor=" + executor);
        ScanResultsCallback.ScanResultsCallbackProxy proxy = callback.getProxy();
        proxy.initProxy(executor, callback);
        try {
            mService.registerScanResultsCallback(proxy);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Allow callers to unregister a previously registered callback. After calling this method,
     * applications will no longer receive Scan Results events.
     *
     * @param callback callback to unregister for Scan Results events
     */
    @RequiresPermission(ACCESS_WIFI_STATE)
    public void unregisterScanResultsCallback(@NonNull ScanResultsCallback callback) {
        if (callback == null) throw new IllegalArgumentException("callback cannot be null");
        Log.v(TAG, "unregisterScanResultsCallback: Callback=" + callback);
        ScanResultsCallback.ScanResultsCallbackProxy proxy = callback.getProxy();
        try {
            mService.unregisterScanResultsCallback(proxy);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        } finally {
            proxy.cleanUpProxy();
        }
    }

    /**
     * Interface for suggestion connection status listener.
     * Should be implemented by applications and set when calling
     * {@link WifiManager#addSuggestionConnectionStatusListener(
     * Executor, SuggestionConnectionStatusListener)}.
     */
    public interface SuggestionConnectionStatusListener {

        /**
         * Called when the framework attempted to connect to a suggestion provided by the
         * registering app, but the connection to the suggestion failed.
         * @param wifiNetworkSuggestion The suggestion which failed to connect.
         * @param failureReason the connection failure reason code. One of
         * {@link #STATUS_SUGGESTION_CONNECTION_FAILURE_ASSOCIATION},
         * {@link #STATUS_SUGGESTION_CONNECTION_FAILURE_AUTHENTICATION},
         * {@link #STATUS_SUGGESTION_CONNECTION_FAILURE_IP_PROVISIONING}
         * {@link #STATUS_SUGGESTION_CONNECTION_FAILURE_UNKNOWN}
         */
        void onConnectionStatus(
                @NonNull WifiNetworkSuggestion wifiNetworkSuggestion,
                @SuggestionConnectionStatusCode int failureReason);
    }

    private class SuggestionConnectionStatusListenerProxy extends
            ISuggestionConnectionStatusListener.Stub {
        private final Executor mExecutor;
        private final SuggestionConnectionStatusListener mListener;

        SuggestionConnectionStatusListenerProxy(@NonNull Executor executor,
                @NonNull SuggestionConnectionStatusListener listener) {
            mExecutor = executor;
            mListener = listener;
        }

        @Override
        public void onConnectionStatus(@NonNull WifiNetworkSuggestion wifiNetworkSuggestion,
                int failureReason) {
            mExecutor.execute(() ->
                    mListener.onConnectionStatus(wifiNetworkSuggestion, failureReason));
        }

    }

    /**
     * Add a listener listening to wifi verbose logging changes.
     * See {@link WifiVerboseLoggingStatusChangedListener}.
     * Caller can remove a previously registered listener using
     * {@link WifiManager#removeWifiVerboseLoggingStatusChangedListener(
     * WifiVerboseLoggingStatusChangedListener)}
     * Same caller can add multiple listeners to monitor the event.
     * <p>
     * Applications should have the
     * {@link android.Manifest.permission#ACCESS_WIFI_STATE}.
     * Callers without the permission will trigger a {@link java.lang.SecurityException}.
     * <p>
     * @param executor The executor to execute the listener of the {@code listener} object.
     * @param listener listener for changes in wifi verbose logging.
     *
     * @hide
     */
    @SystemApi
    @RequiresPermission(ACCESS_WIFI_STATE)
    public void addWifiVerboseLoggingStatusChangedListener(
            @NonNull @CallbackExecutor Executor executor,
            @NonNull WifiVerboseLoggingStatusChangedListener listener) {
        if (listener == null) throw new IllegalArgumentException("Listener cannot be null");
        if (executor == null) throw new IllegalArgumentException("Executor cannot be null");
        if (mVerboseLoggingEnabled) {
            Log.v(TAG, "addWifiVerboseLoggingStatusChangedListener listener=" + listener
                    + ", executor=" + executor);
        }
        try {
            synchronized (sWifiVerboseLoggingStatusChangedListenerMap) {
                IWifiVerboseLoggingStatusChangedListener.Stub binderCallback =
                        new IWifiVerboseLoggingStatusChangedListener.Stub() {
                            @Override
                            public void onStatusChanged(boolean enabled) {
                                if (mVerboseLoggingEnabled) {
                                    Log.v(TAG, "WifiVerboseLoggingStatusListener: "
                                            + "onVerboseLoggingStatusChanged: enabled=" + enabled);
                                }
                                Binder.clearCallingIdentity();
                                executor.execute(() -> listener.onWifiVerboseLoggingStatusChanged(
                                        enabled));
                            }
                        };
                sWifiVerboseLoggingStatusChangedListenerMap.put(System.identityHashCode(listener),
                        binderCallback);
                mService.addWifiVerboseLoggingStatusChangedListener(binderCallback);
            }
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Allow callers to remove a previously registered listener.
     * <p>
     * Applications should have the
     * {@link android.Manifest.permission#ACCESS_WIFI_STATE}.
     * Callers without the permission will trigger a {@link java.lang.SecurityException}.
     * <p>
     * @param listener listener to remove.
     *
     * @hide
     */
    @SystemApi
    @RequiresPermission(ACCESS_WIFI_STATE)
    public void removeWifiVerboseLoggingStatusChangedListener(
            @NonNull WifiVerboseLoggingStatusChangedListener listener) {
        if (listener == null) throw new IllegalArgumentException("Listener cannot be null");
        Log.v(TAG, "removeWifiVerboseLoggingStatusChangedListener: listener=" + listener);
        try {
            synchronized (sWifiVerboseLoggingStatusChangedListenerMap) {
                int listenerIdentifier = System.identityHashCode(listener);
                if (!sWifiVerboseLoggingStatusChangedListenerMap.contains(listenerIdentifier)) {
                    Log.w(TAG, "Unknown external callback " + listenerIdentifier);
                    return;
                }
                mService.removeWifiVerboseLoggingStatusChangedListener(
                        sWifiVerboseLoggingStatusChangedListenerMap.get(listenerIdentifier));
                sWifiVerboseLoggingStatusChangedListenerMap.remove(listenerIdentifier);
            }
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Add a listener for suggestion networks. See {@link SuggestionConnectionStatusListener}.
     * Caller will receive the event when suggested network have connection failure.
     * Caller can remove a previously registered listener using
     * {@link WifiManager#removeSuggestionConnectionStatusListener(
     * SuggestionConnectionStatusListener)}
     * Same caller can add multiple listeners to monitor the event.
     * <p>
     * Applications should have the
     * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} and
     * {@link android.Manifest.permission#ACCESS_WIFI_STATE} permissions.
     * Callers without the permission will trigger a {@link java.lang.SecurityException}.
     * <p>
     *
     * @param executor The executor to execute the listener of the {@code listener} object.
     * @param listener listener for suggestion network connection failure.
     */
    @RequiresPermission(allOf = {ACCESS_FINE_LOCATION, ACCESS_WIFI_STATE})
    public void addSuggestionConnectionStatusListener(@NonNull @CallbackExecutor Executor executor,
            @NonNull SuggestionConnectionStatusListener listener) {
        if (listener == null) throw new IllegalArgumentException("Listener cannot be null");
        if (executor == null) throw new IllegalArgumentException("Executor cannot be null");
        Log.v(TAG, "addSuggestionConnectionStatusListener listener=" + listener
                + ", executor=" + executor);
        try {
            synchronized (sSuggestionConnectionStatusListenerMap) {
                ISuggestionConnectionStatusListener.Stub binderCallback =
                        new SuggestionConnectionStatusListenerProxy(executor, listener);
                sSuggestionConnectionStatusListenerMap.put(System.identityHashCode(listener),
                        binderCallback);
                mService.registerSuggestionConnectionStatusListener(binderCallback,
                        mContext.getOpPackageName(), mContext.getAttributionTag());
            }
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }

    }

    /**
     * Allow callers to remove a previously registered listener. After calling this method,
     * applications will no longer receive suggestion connection events through that listener.
     *
     * @param listener listener to remove.
     */
    @RequiresPermission(ACCESS_WIFI_STATE)
    public void removeSuggestionConnectionStatusListener(
            @NonNull SuggestionConnectionStatusListener listener) {
        if (listener == null) throw new IllegalArgumentException("Listener cannot be null");
        Log.v(TAG, "removeSuggestionConnectionStatusListener: listener=" + listener);
        try {
            synchronized (sSuggestionConnectionStatusListenerMap) {
                int listenerIdentifier = System.identityHashCode(listener);
                if (!sSuggestionConnectionStatusListenerMap.contains(listenerIdentifier)) {
                    Log.w(TAG, "Unknown external callback " + listenerIdentifier);
                    return;
                }
                mService.unregisterSuggestionConnectionStatusListener(
                        sSuggestionConnectionStatusListenerMap.get(listenerIdentifier),
                        mContext.getOpPackageName());
                sSuggestionConnectionStatusListenerMap.remove(listenerIdentifier);
            }
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Parse the list of channels the DPP enrollee reports when it fails to find an AP.
     *
     * @param channelList List of channels in the format defined in the DPP specification.
     * @return A parsed sparse array, where the operating class is the key.
     * @hide
     */
    @VisibleForTesting
    public static SparseArray<int[]> parseDppChannelList(String channelList) {
        SparseArray<int[]> channelListArray = new SparseArray<>();

        if (TextUtils.isEmpty(channelList)) {
            return channelListArray;
        }
        StringTokenizer str = new StringTokenizer(channelList, ",");
        String classStr = null;
        List<Integer> channelsInClass = new ArrayList<>();

        try {
            while (str.hasMoreElements()) {
                String cur = str.nextToken();

                /**
                 * Example for a channel list:
                 *
                 * 81/1,2,3,4,5,6,7,8,9,10,11,115/36,40,44,48,118/52,56,60,64,121/100,104,108,112,
                 * 116,120,124,128,132,136,140,0/144,124/149,153,157,161,125/165
                 *
                 * Detect operating class by the delimiter of '/' and use a string tokenizer with
                 * ',' as a delimiter.
                 */
                int classDelim = cur.indexOf('/');
                if (classDelim != -1) {
                    if (classStr != null) {
                        // Store the last channel array in the sparse array, where the operating
                        // class is the key (as an integer).
                        int[] channelsArray = new int[channelsInClass.size()];
                        for (int i = 0; i < channelsInClass.size(); i++) {
                            channelsArray[i] = channelsInClass.get(i);
                        }
                        channelListArray.append(Integer.parseInt(classStr), channelsArray);
                        channelsInClass = new ArrayList<>();
                    }

                    // Init a new operating class and store the first channel
                    classStr = cur.substring(0, classDelim);
                    String channelStr = cur.substring(classDelim + 1);
                    channelsInClass.add(Integer.parseInt(channelStr));
                } else {
                    if (classStr == null) {
                        // Invalid format
                        Log.e(TAG, "Cannot parse DPP channel list");
                        return new SparseArray<>();
                    }
                    channelsInClass.add(Integer.parseInt(cur));
                }
            }

            // Store the last array
            if (classStr != null) {
                int[] channelsArray = new int[channelsInClass.size()];
                for (int i = 0; i < channelsInClass.size(); i++) {
                    channelsArray[i] = channelsInClass.get(i);
                }
                channelListArray.append(Integer.parseInt(classStr), channelsArray);
            }
            return channelListArray;
        } catch (NumberFormatException e) {
            Log.e(TAG, "Cannot parse DPP channel list");
            return new SparseArray<>();
        }
    }

    /**
     * Callback interface for framework to receive network status updates and trigger of updating
     * {@link WifiUsabilityStatsEntry}.
     *
     * @hide
     */
    @SystemApi
    public interface ScoreUpdateObserver {
        /**
         * Called by applications to indicate network status. For applications targeting
         * {@link android.os.Build.VERSION_CODES#S} or above: The score is not used to take action
         * on network selection but for the purpose of Wifi metric collection only; Network
         * selection is influenced by inputs from
         * {@link ScoreUpdateObserver#notifyStatusUpdate(int, boolean)},
         * {@link ScoreUpdateObserver#requestNudOperation(int, boolean)}, and
         * {@link ScoreUpdateObserver#blocklistCurrentBssid(int)}.
         *
         * @param sessionId The ID to indicate current Wi-Fi network connection obtained from
         *                  {@link WifiConnectedNetworkScorer#onStart(int)}.
         * @param score The score representing link quality of current Wi-Fi network connection.
         *              Populated by connected network scorer in applications..
         */
        void notifyScoreUpdate(int sessionId, int score);

        /**
         * Called by applications to trigger an update of {@link WifiUsabilityStatsEntry}.
         * To receive update applications need to add WifiUsabilityStatsEntry listener. See
         * {@link addOnWifiUsabilityStatsListener(Executor, OnWifiUsabilityStatsListener)}.
         *
         * @param sessionId The ID to indicate current Wi-Fi network connection obtained from
         *                  {@link WifiConnectedNetworkScorer#onStart(int)}.
         */
        void triggerUpdateOfWifiUsabilityStats(int sessionId);

        /**
         * Called by applications to indicate whether current Wi-Fi network is usable or not.
         *
         * @param sessionId The ID to indicate current Wi-Fi network connection obtained from
         *                  {@link WifiConnectedNetworkScorer#onStart(int)}.
         * @param isUsable The boolean representing whether current Wi-Fi network is usable, and it
         *                 may be sent to ConnectivityService and used for setting default network.
         *                 Populated by connected network scorer in applications.
         */
        @RequiresApi(Build.VERSION_CODES.S)
        default void notifyStatusUpdate(int sessionId, boolean isUsable) {}

        /**
         * Called by applications to start a NUD (Neighbor Unreachability Detection) operation. The
         * framework throttles NUD operations to no more frequently than every five seconds
         * (see {@link WifiScoreReport#NUD_THROTTLE_MILLIS}). The framework keeps track of requests
         * and executes them as soon as possible based on the throttling criteria.
         *
         * @param sessionId The ID to indicate current Wi-Fi network connection obtained from
         *                  {@link WifiConnectedNetworkScorer#onStart(int)}.
         */
        @RequiresApi(Build.VERSION_CODES.S)
        default void requestNudOperation(int sessionId) {}

        /**
         * Called by applications to blocklist currently connected BSSID. No blocklisting operation
         * if called after disconnection.
         *
         * @param sessionId The ID to indicate current Wi-Fi network connection obtained from
         *                  {@link WifiConnectedNetworkScorer#onStart(int)}.
         */
        @RequiresApi(Build.VERSION_CODES.S)
        default void blocklistCurrentBssid(int sessionId) {}
    }

    /**
     * Callback proxy for {@link ScoreUpdateObserver} objects.
     *
     * @hide
     */
    private class ScoreUpdateObserverProxy implements ScoreUpdateObserver {
        private final IScoreUpdateObserver mScoreUpdateObserver;

        private ScoreUpdateObserverProxy(IScoreUpdateObserver observer) {
            mScoreUpdateObserver = observer;
        }

        @Override
        public void notifyScoreUpdate(int sessionId, int score) {
            try {
                mScoreUpdateObserver.notifyScoreUpdate(sessionId, score);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }

        @Override
        public void triggerUpdateOfWifiUsabilityStats(int sessionId) {
            try {
                mScoreUpdateObserver.triggerUpdateOfWifiUsabilityStats(sessionId);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }

        @Override
        public void notifyStatusUpdate(int sessionId, boolean isUsable) {
            if (!SdkLevel.isAtLeastS()) {
                throw new UnsupportedOperationException();
            }
            try {
                mScoreUpdateObserver.notifyStatusUpdate(sessionId, isUsable);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }

        @Override
        public void requestNudOperation(int sessionId) {
            if (!SdkLevel.isAtLeastS()) {
                throw new UnsupportedOperationException();
            }
            try {
                mScoreUpdateObserver.requestNudOperation(sessionId);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }

        @Override
        public void blocklistCurrentBssid(int sessionId) {
            if (!SdkLevel.isAtLeastS()) {
                throw new UnsupportedOperationException();
            }
            try {
                mScoreUpdateObserver.blocklistCurrentBssid(sessionId);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
    }

    /**
     * Interface for Wi-Fi connected network scorer. Should be implemented by applications and set
     * when calling
     * {@link WifiManager#setWifiConnectedNetworkScorer(Executor, WifiConnectedNetworkScorer)}.
     *
     * @hide
     */
    @SystemApi
    public interface WifiConnectedNetworkScorer {
        /**
         * Called by framework to indicate the start of a network connection.
         * @param sessionId The ID to indicate current Wi-Fi network connection.
         * @deprecated This API is deprecated.  Please use
         *             {@link WifiConnectedNetworkScorer#onStart(WifiConnectedSessionInfo)}.
         */
        @Deprecated
        default void onStart(int sessionId) {}

        /**
         * Called by framework to indicate the start of a network connection.
         * @param sessionInfo The session information to indicate current Wi-Fi network connection.
         *                    See {@link WifiConnectedSessionInfo}.
         */
        default void onStart(@NonNull WifiConnectedSessionInfo sessionInfo) {
            onStart(sessionInfo.getSessionId());
        }

        /**
         * Called by framework to indicate the end of a network connection.
         * @param sessionId The ID to indicate current Wi-Fi network connection obtained from
         *                  {@link WifiConnectedNetworkScorer#onStart(int)}.
         */
        void onStop(int sessionId);

        /**
         * Framework sets callback for score change events after application sets its scorer.
         * @param observerImpl The instance for {@link WifiManager#ScoreUpdateObserver}. Should be
         * implemented and instantiated by framework.
         */
        void onSetScoreUpdateObserver(@NonNull ScoreUpdateObserver observerImpl);
    }

    /**
     * Callback proxy for {@link WifiConnectedNetworkScorer} objects.
     *
     * @hide
     */
    private class WifiConnectedNetworkScorerProxy extends IWifiConnectedNetworkScorer.Stub {
        private Executor mExecutor;
        private WifiConnectedNetworkScorer mScorer;

        WifiConnectedNetworkScorerProxy(Executor executor, WifiConnectedNetworkScorer scorer) {
            mExecutor = executor;
            mScorer = scorer;
        }

        @Override
        public void onStart(@NonNull WifiConnectedSessionInfo sessionInfo) {
            if (mVerboseLoggingEnabled) {
                Log.v(TAG, "WifiConnectedNetworkScorer: " + "onStart: sessionInfo=" + sessionInfo);
            }
            Binder.clearCallingIdentity();
            mExecutor.execute(() -> mScorer.onStart(sessionInfo));
        }

        @Override
        public void onStop(int sessionId) {
            if (mVerboseLoggingEnabled) {
                Log.v(TAG, "WifiConnectedNetworkScorer: " + "onStop: sessionId=" + sessionId);
            }
            Binder.clearCallingIdentity();
            mExecutor.execute(() -> mScorer.onStop(sessionId));
        }

        @Override
        public void onSetScoreUpdateObserver(IScoreUpdateObserver observerImpl) {
            if (mVerboseLoggingEnabled) {
                Log.v(TAG, "WifiConnectedNetworkScorer: "
                        + "onSetScoreUpdateObserver: observerImpl=" + observerImpl);
            }
            Binder.clearCallingIdentity();
            mExecutor.execute(() -> mScorer.onSetScoreUpdateObserver(
                    new ScoreUpdateObserverProxy(observerImpl)));
        }
    }

    /**
     * Set a callback for Wi-Fi connected network scorer.  See {@link WifiConnectedNetworkScorer}.
     * Only a single scorer can be set. Caller will be invoked periodically by framework to inform
     * client about start and stop of Wi-Fi connection. Caller can clear a previously set scorer
     * using {@link clearWifiConnectedNetworkScorer()}.
     *
     * @param executor The executor on which callback will be invoked.
     * @param scorer Scorer for Wi-Fi network implemented by application.
     * @return true Scorer is set successfully.
     *
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE)
    public boolean setWifiConnectedNetworkScorer(@NonNull @CallbackExecutor Executor executor,
            @NonNull WifiConnectedNetworkScorer scorer) {
        if (executor == null) throw new IllegalArgumentException("executor cannot be null");
        if (scorer == null) throw new IllegalArgumentException("scorer cannot be null");
        if (mVerboseLoggingEnabled) {
            Log.v(TAG, "setWifiConnectedNetworkScorer: scorer=" + scorer);
        }
        try {
            return mService.setWifiConnectedNetworkScorer(new Binder(),
                    new WifiConnectedNetworkScorerProxy(executor, scorer));
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Allow caller to clear a previously set scorer. After calling this method,
     * client will no longer receive information about start and stop of Wi-Fi connection.
     *
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE)
    public void clearWifiConnectedNetworkScorer() {
        if (mVerboseLoggingEnabled) {
            Log.v(TAG, "clearWifiConnectedNetworkScorer");
        }
        try {
            mService.clearWifiConnectedNetworkScorer();
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Enable/disable wifi scan throttling from 3rd party apps.
     *
     * <p>
     * The throttling limits for apps are described in
     * <a href="Wi-Fi Scan Throttling">
     * https://developer.android.com/guide/topics/connectivity/wifi-scan#wifi-scan-throttling</a>
     * </p>
     *
     * @param enable true to allow scan throttling, false to disallow scan throttling.
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
    public void setScanThrottleEnabled(boolean enable) {
        try {
            mService.setScanThrottleEnabled(enable);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Get the persisted Wi-Fi scan throttle state. Defaults to true, unless changed by the user via
     * Developer options.
     *
     * <p>
     * The throttling limits for apps are described in
     * <a href="Wi-Fi Scan Throttling">
     * https://developer.android.com/guide/topics/connectivity/wifi-scan#wifi-scan-throttling</a>
     * </p>
     *
     * @return true to indicate that scan throttling is enabled, false to indicate that scan
     * throttling is disabled.
     */
    @RequiresPermission(ACCESS_WIFI_STATE)
    public boolean isScanThrottleEnabled() {
        try {
            return mService.isScanThrottleEnabled();
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Enable/disable wifi auto wakeup feature.
     *
     * <p>
     * The feature is described in
     * <a href="Wi-Fi Turn on automatically">
     * https://source.android.com/devices/tech/connect/wifi-infrastructure
     * #turn_on_wi-fi_automatically
     * </a>
     *
     * @param enable true to enable, false to disable.
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
    public void setAutoWakeupEnabled(boolean enable) {
        try {
            mService.setAutoWakeupEnabled(enable);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Get the persisted Wi-Fi auto wakeup feature state. Defaults to false, unless changed by the
     * user via Settings.
     *
     * <p>
     * The feature is described in
     * <a href="Wi-Fi Turn on automatically">
     * https://source.android.com/devices/tech/connect/wifi-infrastructure
     * #turn_on_wi-fi_automatically
     * </a>
     *
     * @return true to indicate that wakeup feature is enabled, false to indicate that wakeup
     * feature is disabled.
     */
    @RequiresPermission(ACCESS_WIFI_STATE)
    public boolean isAutoWakeupEnabled() {
        try {
            return mService.isAutoWakeupEnabled();
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Sets the state of carrier offload on merged or unmerged networks for specified subscription.
     *
     * <p>
     * When a subscription's carrier network offload is disabled, all network suggestions related to
     * this subscription will not be considered for auto join.
     * <p>
     * If calling app want disable all carrier network offload from a specified subscription, should
     * call this API twice to disable both merged and unmerged carrier network suggestions.
     *
     * @param subscriptionId See {@link SubscriptionInfo#getSubscriptionId()}.
     * @param merged True for carrier merged network, false otherwise.
     *               See {@link WifiNetworkSuggestion.Builder#setCarrierMerged(boolean)}
     * @param enabled True for enable carrier network offload, false otherwise.
     * @see #isCarrierNetworkOffloadEnabled(int, boolean)
     * @hide
     */
    @SystemApi
    @RequiresPermission(anyOf = {
            android.Manifest.permission.NETWORK_SETTINGS,
            android.Manifest.permission.NETWORK_SETUP_WIZARD})
    public void setCarrierNetworkOffloadEnabled(int subscriptionId, boolean merged,
            boolean enabled) {
        try {
            mService.setCarrierNetworkOffloadEnabled(subscriptionId, merged, enabled);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Get the carrier network offload state for merged or unmerged networks for specified
     * subscription.
     * @param subscriptionId subscription ID see {@link SubscriptionInfo#getSubscriptionId()}
     * @param merged True for carrier merged network, false otherwise.
     *               See {@link WifiNetworkSuggestion.Builder#setCarrierMerged(boolean)}
     * @return True to indicate that carrier network offload is enabled, false otherwise.
     */
    @RequiresPermission(ACCESS_WIFI_STATE)
    public boolean isCarrierNetworkOffloadEnabled(int subscriptionId, boolean merged) {
        try {
            return mService.isCarrierNetworkOffloadEnabled(subscriptionId, merged);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Interface for network suggestion user approval status change listener.
     * Should be implemented by applications and registered using
     * {@link #addSuggestionUserApprovalStatusListener(Executor,
     * SuggestionUserApprovalStatusListener)} (
     */
    public interface SuggestionUserApprovalStatusListener {

        /**
         * Called when the user approval status of the App has changed.
         * @param status The current status code for the user approval. One of the
         *               {@code STATUS_SUGGESTION_APPROVAL_} values.
         */
        void onUserApprovalStatusChange(@SuggestionUserApprovalStatus int status);
    }

    private class SuggestionUserApprovalStatusListenerProxy extends
            ISuggestionUserApprovalStatusListener.Stub {
        private final Executor mExecutor;
        private final SuggestionUserApprovalStatusListener mListener;

        SuggestionUserApprovalStatusListenerProxy(@NonNull Executor executor,
                @NonNull SuggestionUserApprovalStatusListener listener) {
            mExecutor = executor;
            mListener = listener;
        }

        @Override
        public void onUserApprovalStatusChange(int status) {
            mExecutor.execute(() -> mListener.onUserApprovalStatusChange(status));
        }

    }

    /**
     * Add a listener for Wi-Fi network suggestion user approval status.
     * See {@link SuggestionUserApprovalStatusListener}.
     * Caller will receive a callback immediately after adding a listener and when the user approval
     * status of the caller has changed.
     * Caller can remove a previously registered listener using
     * {@link WifiManager#removeSuggestionUserApprovalStatusListener(
     * SuggestionUserApprovalStatusListener)}
     * A caller can add multiple listeners to monitor the event.
     * @param executor The executor to execute the listener of the {@code listener} object.
     * @param listener listener for suggestion user approval status changes.
     */
    @RequiresPermission(ACCESS_WIFI_STATE)
    public void addSuggestionUserApprovalStatusListener(
            @NonNull @CallbackExecutor Executor executor,
            @NonNull SuggestionUserApprovalStatusListener listener) {
        if (listener == null) throw new NullPointerException("Listener cannot be null");
        if (executor == null) throw new NullPointerException("Executor cannot be null");
        Log.v(TAG, "addSuggestionUserApprovalStatusListener listener=" + listener
                + ", executor=" + executor);
        try {
            synchronized (sSuggestionUserApprovalStatusListenerMap) {
                ISuggestionUserApprovalStatusListener.Stub binderCallback =
                        new SuggestionUserApprovalStatusListenerProxy(executor, listener);
                sSuggestionUserApprovalStatusListenerMap.put(System.identityHashCode(listener),
                        binderCallback);
                mService.addSuggestionUserApprovalStatusListener(binderCallback,
                        mContext.getOpPackageName());
            }
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }

    }

    /**
     * Allow callers to remove a previously registered listener using
     * {@link #addSuggestionUserApprovalStatusListener(Executor,
     * SuggestionUserApprovalStatusListener)}. After calling this method,
     * applications will no longer receive network suggestion user approval status change through
     * that listener.
     */
    @RequiresPermission(ACCESS_WIFI_STATE)
    public void removeSuggestionUserApprovalStatusListener(
            @NonNull SuggestionUserApprovalStatusListener listener) {
        if (listener == null) throw new IllegalArgumentException("Listener cannot be null");
        Log.v(TAG, "removeSuggestionUserApprovalStatusListener: listener=" + listener);
        try {
            synchronized (sSuggestionUserApprovalStatusListenerMap) {
                int listenerIdentifier = System.identityHashCode(listener);
                if (!sSuggestionUserApprovalStatusListenerMap.contains(listenerIdentifier)) {
                    Log.w(TAG, "Unknown external callback " + listenerIdentifier);
                    return;
                }
                mService.removeSuggestionUserApprovalStatusListener(
                        sSuggestionUserApprovalStatusListenerMap.get(listenerIdentifier),
                        mContext.getOpPackageName());
                sSuggestionUserApprovalStatusListenerMap.remove(listenerIdentifier);
            }
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Indicates the start/end of an emergency scan request being processed by {@link WifiScanner}.
     * The wifi stack should ensure that the wifi chip remains on for the duration of the scan.
     * WifiScanner detects emergency scan requests via
     * {@link WifiScanner.ScanSettings#ignoreLocationSettings} flag.
     *
     * If the wifi stack is off (because location & wifi toggles are off) when this indication is
     * received, the wifi stack will temporarily move to a scan only mode. Since location toggle
     * is off, only scan with
     * {@link WifiScanner.ScanSettings#ignoreLocationSettings} flag set will be
     * allowed to be processed for this duration.
     *
     * @hide
     */
    @RequiresPermission(android.Manifest.permission.NETWORK_STACK)
    public void setEmergencyScanRequestInProgress(boolean inProgress) {
        try {
            mService.setEmergencyScanRequestInProgress(inProgress);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Enable or disable Wi-Fi scoring.  Wi-Fi network status is evaluated by Wi-Fi scoring
     * {@link WifiScoreReport}. This API enables/disables Wi-Fi scoring to take action on network
     * selection.
     *
     * @param enabled {@code true} to enable, {@code false} to disable.
     * @return true The status of Wifi scoring is set successfully.
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
    public boolean setWifiScoringEnabled(boolean enabled) {
        if (mVerboseLoggingEnabled) {
            Log.v(TAG, "setWifiScoringEnabled: " + enabled);
        }
        try {
            return mService.setWifiScoringEnabled(enabled);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Flush Passpoint ANQP cache, and clear pending ANQP requests. Allows the caller to reset the
     * Passpoint ANQP state, if required.
     *
     * Notes:
     * 1. Flushing the ANQP cache may cause delays in discovering and connecting to Passpoint
     * networks.
     * 2. Intended to be used by Device Owner (DO), Profile Owner (PO), Settings and provisioning
     * apps.
     */
    @RequiresPermission(anyOf = {
            android.Manifest.permission.NETWORK_SETTINGS,
            android.Manifest.permission.NETWORK_MANAGED_PROVISIONING,
            android.Manifest.permission.NETWORK_CARRIER_PROVISIONING
            })
    public void flushPasspointAnqpCache() {
        try {
            mService.flushPasspointAnqpCache(mContext.getOpPackageName());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Returns a list of {@link WifiAvailableChannel} for the specified band and operational
     * mode(s), that is allowed for the current regulatory domain. An empty list implies that there
     * are no available channels for use.
     *
     * @param band one of the following band constants defined in {@code WifiScanner#WIFI_BAND_*}
     *             constants.
     *             1. {@code WifiScanner#WIFI_BAND_UNSPECIFIED} - no band specified; Looks for the
     *                channels in all the available bands - 2.4 GHz, 5 GHz, 6 GHz and 60 GHz
     *             2. {@code WifiScanner#WIFI_BAND_24_GHZ}
     *             3. {@code WifiScanner#WIFI_BAND_5_GHZ_WITH_DFS}
     *             4. {@code WifiScanner#WIFI_BAND_BOTH_WITH_DFS}
     *             5. {@code WifiScanner#WIFI_BAND_6_GHZ}
     *             6. {@code WifiScanner#WIFI_BAND_24_5_WITH_DFS_6_GHZ}
     *             7. {@code WifiScanner#WIFI_BAND_60_GHZ}
     *             8. {@code WifiScanner#WIFI_BAND_24_5_WITH_DFS_6_60_GHZ}
     * @param mode Bitwise OR of {@code WifiAvailableChannel#OP_MODE_*} constants
     *        e.g. {@link WifiAvailableChannel#OP_MODE_WIFI_AWARE}
     * @return a list of {@link WifiAvailableChannel}
     *
     * @throws UnsupportedOperationException - if this API is not supported on this device
     *         or IllegalArgumentException - if the band specified is not one among the list
     *         of bands mentioned above.
     * @hide
     */
    @RequiresApi(Build.VERSION_CODES.S)
    @SystemApi
    @NonNull
    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
    public List<WifiAvailableChannel> getAllowedChannels(
            @WifiScanner.WifiBand int band,
            @WifiAvailableChannel.OpMode int mode) {
        if (!SdkLevel.isAtLeastS()) {
            throw new UnsupportedOperationException();
        }
        try {
            return mService.getUsableChannels(band, mode,
                    WifiAvailableChannel.FILTER_REGULATORY);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Returns a list of {@link WifiAvailableChannel} for the specified band and operational
     * mode(s) per the current regulatory domain and device-specific constraints such as concurrency
     * state and interference due to other radios. An empty list implies that there are no available
     * channels for use.
     *
     * @param band one of the following band constants defined in {@code WifiScanner#WIFI_BAND_*}
     *             constants.
     *             1. {@code WifiScanner#WIFI_BAND_UNSPECIFIED} - no band specified; Looks for the
     *                channels in all the available bands - 2.4 GHz, 5 GHz, 6 GHz and 60 GHz
     *             2. {@code WifiScanner#WIFI_BAND_24_GHZ}
     *             3. {@code WifiScanner#WIFI_BAND_5_GHZ_WITH_DFS}
     *             4. {@code WifiScanner#WIFI_BAND_BOTH_WITH_DFS}
     *             5. {@code WifiScanner#WIFI_BAND_6_GHZ}
     *             6. {@code WifiScanner#WIFI_BAND_24_5_WITH_DFS_6_GHZ}
     *             7. {@code WifiScanner#WIFI_BAND_60_GHZ}
     *             8. {@code WifiScanner#WIFI_BAND_24_5_WITH_DFS_6_60_GHZ}
     * @param mode Bitwise OR of {@code WifiAvailableChannel#OP_MODE_*} constants
     *        e.g. {@link WifiAvailableChannel#OP_MODE_WIFI_AWARE}
     * @return a list of {@link WifiAvailableChannel}
     *
     * @throws UnsupportedOperationException - if this API is not supported on this device
     *         or IllegalArgumentException - if the band specified is not one among the list
     *         of bands mentioned above.
     * @hide
     */
    @RequiresApi(Build.VERSION_CODES.S)
    @SystemApi
    @NonNull
    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
    public List<WifiAvailableChannel> getUsableChannels(
            @WifiScanner.WifiBand int band,
            @WifiAvailableChannel.OpMode int mode) {
        if (!SdkLevel.isAtLeastS()) {
            throw new UnsupportedOperationException();
        }
        try {
            return mService.getUsableChannels(band, mode,
                    WifiAvailableChannel.getUsableFilter());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }
}
