12830 lines
516 KiB
Java
12830 lines
516 KiB
Java
![]() |
/*
|
|||
|
* 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.CHANGE_WIFI_STATE;
|
|||
|
import static android.Manifest.permission.MANAGE_WIFI_NETWORK_SELECTION;
|
|||
|
import static android.Manifest.permission.NEARBY_WIFI_DEVICES;
|
|||
|
import static android.Manifest.permission.NETWORK_SETTINGS;
|
|||
|
import static android.Manifest.permission.NETWORK_SETUP_WIZARD;
|
|||
|
import static android.Manifest.permission.READ_WIFI_CREDENTIAL;
|
|||
|
import static android.Manifest.permission.REQUEST_COMPANION_PROFILE_AUTOMOTIVE_PROJECTION;
|
|||
|
|
|||
|
import android.Manifest;
|
|||
|
import android.annotation.CallbackExecutor;
|
|||
|
import android.annotation.FlaggedApi;
|
|||
|
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.StringDef;
|
|||
|
import android.annotation.SuppressLint;
|
|||
|
import android.annotation.SystemApi;
|
|||
|
import android.annotation.SystemService;
|
|||
|
import android.app.ActivityManager;
|
|||
|
import android.app.admin.WifiSsidPolicy;
|
|||
|
import android.compat.annotation.ChangeId;
|
|||
|
import android.compat.annotation.EnabledAfter;
|
|||
|
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.DhcpOption;
|
|||
|
import android.net.LinkProperties;
|
|||
|
import android.net.MacAddress;
|
|||
|
import android.net.Network;
|
|||
|
import android.net.NetworkCapabilities;
|
|||
|
import android.net.NetworkRequest;
|
|||
|
import android.net.NetworkStack;
|
|||
|
import android.net.TetheringManager;
|
|||
|
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.net.wifi.p2p.WifiP2pConfig;
|
|||
|
import android.net.wifi.p2p.WifiP2pDiscoveryConfig;
|
|||
|
import android.net.wifi.p2p.WifiP2pManager;
|
|||
|
import android.net.wifi.twt.TwtRequest;
|
|||
|
import android.net.wifi.twt.TwtSession;
|
|||
|
import android.net.wifi.twt.TwtSessionCallback;
|
|||
|
import android.os.Binder;
|
|||
|
import android.os.Build;
|
|||
|
import android.os.Bundle;
|
|||
|
import android.os.Handler;
|
|||
|
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.text.TextUtils;
|
|||
|
import android.util.ArraySet;
|
|||
|
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.HandlerExecutor;
|
|||
|
import com.android.modules.utils.ParceledListSlice;
|
|||
|
import com.android.modules.utils.build.SdkLevel;
|
|||
|
import com.android.wifi.flags.Flags;
|
|||
|
|
|||
|
import java.lang.annotation.Retention;
|
|||
|
import java.lang.annotation.RetentionPolicy;
|
|||
|
import java.lang.ref.Reference;
|
|||
|
import java.lang.ref.WeakReference;
|
|||
|
import java.net.InetAddress;
|
|||
|
import java.time.Duration;
|
|||
|
import java.util.ArrayList;
|
|||
|
import java.util.Arrays;
|
|||
|
import java.util.Collections;
|
|||
|
import java.util.HashMap;
|
|||
|
import java.util.List;
|
|||
|
import java.util.Map;
|
|||
|
import java.util.Objects;
|
|||
|
import java.util.Set;
|
|||
|
import java.util.StringTokenizer;
|
|||
|
import java.util.concurrent.Executor;
|
|||
|
import java.util.function.BiConsumer;
|
|||
|
import java.util.function.Consumer;
|
|||
|
import java.util.function.IntConsumer;
|
|||
|
|
|||
|
/**
|
|||
|
* 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";
|
|||
|
|
|||
|
/**
|
|||
|
* Local networks should not be modified by B&R since the user may have
|
|||
|
* updated it with the latest configurations.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@ChangeId
|
|||
|
@EnabledAfter(targetSdkVersion = Build.VERSION_CODES.S_V2)
|
|||
|
public static final long NOT_OVERRIDE_EXISTING_NETWORKS_ON_RESTORE = 234793325L;
|
|||
|
|
|||
|
// 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;
|
|||
|
|
|||
|
/**
|
|||
|
* Reason code if {@link android.os.UserManager#DISALLOW_ADD_WIFI_CONFIG} user restriction
|
|||
|
* is set and calling app is restricted by device admin.
|
|||
|
*/
|
|||
|
public static final int STATUS_NETWORK_SUGGESTIONS_ERROR_RESTRICTED_BY_ADMIN = 8;
|
|||
|
|
|||
|
/** @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,
|
|||
|
STATUS_NETWORK_SUGGESTIONS_ERROR_RESTRICTED_BY_ADMIN,
|
|||
|
})
|
|||
|
@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 {}
|
|||
|
|
|||
|
/**
|
|||
|
* Reason code if local-only network connection attempt failed with an unknown failure.
|
|||
|
*/
|
|||
|
public static final int STATUS_LOCAL_ONLY_CONNECTION_FAILURE_UNKNOWN = 0;
|
|||
|
/**
|
|||
|
* Reason code if local-only network connection attempt failed with association failure.
|
|||
|
*/
|
|||
|
public static final int STATUS_LOCAL_ONLY_CONNECTION_FAILURE_ASSOCIATION = 1;
|
|||
|
/**
|
|||
|
* Reason code if local-only network connection attempt failed with an authentication failure.
|
|||
|
*/
|
|||
|
public static final int STATUS_LOCAL_ONLY_CONNECTION_FAILURE_AUTHENTICATION = 2;
|
|||
|
/**
|
|||
|
* Reason code if local-only network connection attempt failed with an IP provisioning failure.
|
|||
|
*/
|
|||
|
public static final int STATUS_LOCAL_ONLY_CONNECTION_FAILURE_IP_PROVISIONING = 3;
|
|||
|
/**
|
|||
|
* Reason code if local-only network connection attempt failed with AP not in range.
|
|||
|
*/
|
|||
|
public static final int STATUS_LOCAL_ONLY_CONNECTION_FAILURE_NOT_FOUND = 4;
|
|||
|
/**
|
|||
|
* Reason code if local-only network connection attempt failed with AP not responding
|
|||
|
*/
|
|||
|
public static final int STATUS_LOCAL_ONLY_CONNECTION_FAILURE_NO_RESPONSE = 5;
|
|||
|
|
|||
|
/** @hide */
|
|||
|
@IntDef(prefix = {"STATUS_LOCAL_ONLY_CONNECTION_FAILURE_"},
|
|||
|
value = {STATUS_LOCAL_ONLY_CONNECTION_FAILURE_UNKNOWN,
|
|||
|
STATUS_LOCAL_ONLY_CONNECTION_FAILURE_ASSOCIATION,
|
|||
|
STATUS_LOCAL_ONLY_CONNECTION_FAILURE_AUTHENTICATION,
|
|||
|
STATUS_LOCAL_ONLY_CONNECTION_FAILURE_IP_PROVISIONING,
|
|||
|
STATUS_LOCAL_ONLY_CONNECTION_FAILURE_NOT_FOUND,
|
|||
|
STATUS_LOCAL_ONLY_CONNECTION_FAILURE_NO_RESPONSE
|
|||
|
})
|
|||
|
@Retention(RetentionPolicy.SOURCE)
|
|||
|
public @interface LocalOnlyConnectionStatusCode {}
|
|||
|
|
|||
|
/**
|
|||
|
* 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 android.telephony.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 {}
|
|||
|
|
|||
|
/**
|
|||
|
* Disable PNO scan until device reboot.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|||
|
@SystemApi
|
|||
|
public static final int PNO_SCAN_STATE_DISABLED_UNTIL_REBOOT = 0;
|
|||
|
|
|||
|
/**
|
|||
|
* Disable PNO scan until device reboot or Wi-Fi is toggled.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|||
|
@SystemApi
|
|||
|
public static final int PNO_SCAN_STATE_DISABLED_UNTIL_WIFI_TOGGLE = 1;
|
|||
|
|
|||
|
/**
|
|||
|
* Enable PNO scan.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|||
|
@SystemApi
|
|||
|
public static final int PNO_SCAN_STATE_ENABLED = 2;
|
|||
|
|
|||
|
/** @hide */
|
|||
|
@IntDef(prefix = {"PNO_SCAN_STATE_"},
|
|||
|
value = {PNO_SCAN_STATE_DISABLED_UNTIL_REBOOT,
|
|||
|
PNO_SCAN_STATE_DISABLED_UNTIL_WIFI_TOGGLE,
|
|||
|
PNO_SCAN_STATE_ENABLED
|
|||
|
})
|
|||
|
@Retention(RetentionPolicy.SOURCE)
|
|||
|
public @interface PnoScanState {}
|
|||
|
|
|||
|
/**
|
|||
|
* If one of the removed suggestions is currently connected, that network will be disconnected
|
|||
|
* after a short delay as opposed to immediately (which will be done by
|
|||
|
* {@link #ACTION_REMOVE_SUGGESTION_DISCONNECT}). The {@link ConnectivityManager} may call the
|
|||
|
* {@link NetworkCallback#onLosing(Network, int)} on such networks.
|
|||
|
*/
|
|||
|
public static final int ACTION_REMOVE_SUGGESTION_LINGER = 1;
|
|||
|
|
|||
|
/**
|
|||
|
* If one of the removed suggestions is currently connected, trigger an immediate disconnect
|
|||
|
* after suggestions removal
|
|||
|
*/
|
|||
|
public static final int ACTION_REMOVE_SUGGESTION_DISCONNECT = 2;
|
|||
|
|
|||
|
/** @hide */
|
|||
|
@IntDef(prefix = {"ACTION_REMOVE_SUGGESTION_"},
|
|||
|
value = {ACTION_REMOVE_SUGGESTION_LINGER,
|
|||
|
ACTION_REMOVE_SUGGESTION_DISCONNECT
|
|||
|
})
|
|||
|
@Retention(RetentionPolicy.SOURCE)
|
|||
|
public @interface ActionAfterRemovingSuggestion {}
|
|||
|
|
|||
|
/**
|
|||
|
* Only available on Android S or later.
|
|||
|
* @hide
|
|||
|
**/
|
|||
|
public static final String EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE =
|
|||
|
"EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE";
|
|||
|
|
|||
|
/**
|
|||
|
* 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;
|
|||
|
|
|||
|
/** @hide */
|
|||
|
@Retention(RetentionPolicy.SOURCE)
|
|||
|
@IntDef(value = {
|
|||
|
API_SCANNING_ENABLED,
|
|||
|
API_WIFI_ENABLED,
|
|||
|
API_SOFT_AP,
|
|||
|
API_TETHERED_HOTSPOT,
|
|||
|
API_AUTOJOIN_GLOBAL,
|
|||
|
API_SET_SCAN_SCHEDULE,
|
|||
|
API_SET_ONE_SHOT_SCREEN_ON_CONNECTIVITY_SCAN_DELAY,
|
|||
|
API_SET_NETWORK_SELECTION_CONFIG,
|
|||
|
API_SET_THIRD_PARTY_APPS_ENABLING_WIFI_CONFIRMATION_DIALOG,
|
|||
|
API_ADD_NETWORK,
|
|||
|
API_UPDATE_NETWORK,
|
|||
|
API_ALLOW_AUTOJOIN,
|
|||
|
API_CONNECT_CONFIG,
|
|||
|
API_CONNECT_NETWORK_ID,
|
|||
|
API_DISABLE_NETWORK,
|
|||
|
API_ENABLE_NETWORK,
|
|||
|
API_FORGET,
|
|||
|
API_SAVE,
|
|||
|
API_START_SCAN,
|
|||
|
API_START_LOCAL_ONLY_HOTSPOT,
|
|||
|
API_P2P_DISCOVER_PEERS,
|
|||
|
API_P2P_DISCOVER_PEERS_ON_SOCIAL_CHANNELS,
|
|||
|
API_P2P_DISCOVER_PEERS_ON_SPECIFIC_FREQUENCY,
|
|||
|
API_P2P_STOP_PEER_DISCOVERY,
|
|||
|
API_P2P_CONNECT,
|
|||
|
API_P2P_CANCEL_CONNECT,
|
|||
|
API_P2P_CREATE_GROUP,
|
|||
|
API_P2P_CREATE_GROUP_P2P_CONFIG,
|
|||
|
API_P2P_REMOVE_GROUP,
|
|||
|
API_P2P_START_LISTENING,
|
|||
|
API_P2P_STOP_LISTENING,
|
|||
|
API_P2P_SET_CHANNELS,
|
|||
|
API_WIFI_SCANNER_START_SCAN,
|
|||
|
API_SET_TDLS_ENABLED,
|
|||
|
API_SET_TDLS_ENABLED_WITH_MAC_ADDRESS,
|
|||
|
API_P2P_DISCOVER_PEERS_WITH_CONFIG_PARAMS
|
|||
|
})
|
|||
|
public @interface ApiType {}
|
|||
|
|
|||
|
/**
|
|||
|
* A constant used in
|
|||
|
* {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)}
|
|||
|
* Tracks usage of {@link WifiScanner#setScanningEnabled(boolean)}
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
public static final int API_SCANNING_ENABLED = 1;
|
|||
|
/**
|
|||
|
* A constant used in
|
|||
|
* {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)}
|
|||
|
* Tracks usage of {@link WifiManager#setWifiEnabled(boolean)} .
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
public static final int API_WIFI_ENABLED = 2;
|
|||
|
/**
|
|||
|
* A constant used in
|
|||
|
* {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)}
|
|||
|
* Tracks usage of {@link WifiManager#startSoftAp(WifiConfiguration)} and
|
|||
|
* {@link WifiManager#stopSoftAp()}.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
public static final int API_SOFT_AP = 3;
|
|||
|
/**
|
|||
|
* A constant used in
|
|||
|
* {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)}
|
|||
|
* Tracks usage of {@link WifiManager#startTetheredHotspot(SoftApConfiguration)}.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
public static final int API_TETHERED_HOTSPOT = 4;
|
|||
|
/**
|
|||
|
* A constant used in
|
|||
|
* {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)}
|
|||
|
* Tracks usage of {@link WifiManager#allowAutojoinGlobal(boolean)}.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
public static final int API_AUTOJOIN_GLOBAL = 5;
|
|||
|
/**
|
|||
|
* A constant used in
|
|||
|
* {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)}
|
|||
|
* Tracks usage of {@link WifiManager#setScreenOnScanSchedule(List)}.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
public static final int API_SET_SCAN_SCHEDULE = 6;
|
|||
|
|
|||
|
/**
|
|||
|
* A constant used in
|
|||
|
* {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)}
|
|||
|
* Tracks usage of {@link WifiManager#setOneShotScreenOnConnectivityScanDelayMillis(int)}.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
public static final int API_SET_ONE_SHOT_SCREEN_ON_CONNECTIVITY_SCAN_DELAY = 7;
|
|||
|
|
|||
|
/**
|
|||
|
* A constant used in
|
|||
|
* {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)}
|
|||
|
* Tracks usage of
|
|||
|
* {@link WifiManager#setNetworkSelectionConfig(WifiNetworkSelectionConfig)}
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
public static final int API_SET_NETWORK_SELECTION_CONFIG = 8;
|
|||
|
|
|||
|
/**
|
|||
|
* A constant used in
|
|||
|
* {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)}
|
|||
|
* Tracks usage of
|
|||
|
* {@link WifiManager#setThirdPartyAppEnablingWifiConfirmationDialogEnabled(boolean)}
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
public static final int API_SET_THIRD_PARTY_APPS_ENABLING_WIFI_CONFIRMATION_DIALOG = 9;
|
|||
|
|
|||
|
/**
|
|||
|
* A constant used in
|
|||
|
* {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)}
|
|||
|
* Tracks usage of
|
|||
|
* {@link WifiManager#addNetwork(WifiConfiguration)}
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
public static final int API_ADD_NETWORK = 10;
|
|||
|
|
|||
|
/**
|
|||
|
* A constant used in
|
|||
|
* {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)}
|
|||
|
* Tracks usage of
|
|||
|
* {@link WifiManager#updateNetwork(WifiConfiguration)}
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
public static final int API_UPDATE_NETWORK = 11;
|
|||
|
|
|||
|
/**
|
|||
|
* A constant used in
|
|||
|
* {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)}
|
|||
|
* Tracks usage of
|
|||
|
* {@link WifiManager#allowAutojoin(int, boolean)}
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
public static final int API_ALLOW_AUTOJOIN = 12;
|
|||
|
|
|||
|
/**
|
|||
|
* A constant used in
|
|||
|
* {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)}
|
|||
|
* Tracks usage of
|
|||
|
* {@link WifiManager#connect(WifiConfiguration, ActionListener)}
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
public static final int API_CONNECT_CONFIG = 13;
|
|||
|
|
|||
|
/**
|
|||
|
* A constant used in
|
|||
|
* {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)}
|
|||
|
* Tracks usage of
|
|||
|
* {@link WifiManager#connect(int, ActionListener)}
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
public static final int API_CONNECT_NETWORK_ID = 14;
|
|||
|
|
|||
|
/**
|
|||
|
* A constant used in
|
|||
|
* {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)}
|
|||
|
* Tracks usage of
|
|||
|
* {@link WifiManager#disableNetwork(int)}
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
public static final int API_DISABLE_NETWORK = 15;
|
|||
|
|
|||
|
/**
|
|||
|
* A constant used in
|
|||
|
* {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)}
|
|||
|
* Tracks usage of
|
|||
|
* {@link WifiManager#enableNetwork(int, boolean)}
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
public static final int API_ENABLE_NETWORK = 16;
|
|||
|
|
|||
|
/**
|
|||
|
* A constant used in
|
|||
|
* {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)}
|
|||
|
* Tracks usage of
|
|||
|
* {@link WifiManager#forget(int, ActionListener)}
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
public static final int API_FORGET = 17;
|
|||
|
|
|||
|
/**
|
|||
|
* A constant used in
|
|||
|
* {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)}
|
|||
|
* Tracks usage of
|
|||
|
* {@link WifiManager#save(WifiConfiguration, ActionListener)}
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
public static final int API_SAVE = 18;
|
|||
|
|
|||
|
/**
|
|||
|
* A constant used in
|
|||
|
* {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)}
|
|||
|
* Tracks usage of
|
|||
|
* {@link WifiManager#startScan()}
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
public static final int API_START_SCAN = 19;
|
|||
|
|
|||
|
/**
|
|||
|
* A constant used in
|
|||
|
* {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)}
|
|||
|
* Tracks usage of
|
|||
|
* {@link WifiManager#startLocalOnlyHotspot(LocalOnlyHotspotCallback, Handler)}
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
public static final int API_START_LOCAL_ONLY_HOTSPOT = 20;
|
|||
|
|
|||
|
/**
|
|||
|
* A constant used in
|
|||
|
* {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)}
|
|||
|
* Tracks usage of
|
|||
|
* {@link WifiP2pManager#discoverPeers(WifiP2pManager.Channel, WifiP2pManager.ActionListener)}
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
public static final int API_P2P_DISCOVER_PEERS = 21;
|
|||
|
|
|||
|
/**
|
|||
|
* A constant used in
|
|||
|
* {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)}
|
|||
|
* Tracks usage of
|
|||
|
* {@link WifiP2pManager#discoverPeersOnSocialChannels(WifiP2pManager.Channel,
|
|||
|
* WifiP2pManager.ActionListener)}
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
public static final int API_P2P_DISCOVER_PEERS_ON_SOCIAL_CHANNELS = 22;
|
|||
|
|
|||
|
/**
|
|||
|
* A constant used in
|
|||
|
* {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)}
|
|||
|
* Tracks usage of
|
|||
|
* {@link WifiP2pManager#discoverPeersOnSpecificFrequency(WifiP2pManager.Channel, int,
|
|||
|
* WifiP2pManager.ActionListener)}
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
public static final int API_P2P_DISCOVER_PEERS_ON_SPECIFIC_FREQUENCY = 23;
|
|||
|
|
|||
|
/**
|
|||
|
* A constant used in
|
|||
|
* {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)}
|
|||
|
* Tracks usage of
|
|||
|
* {@link WifiP2pManager#stopPeerDiscovery(WifiP2pManager.Channel,
|
|||
|
* WifiP2pManager.ActionListener)}
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
public static final int API_P2P_STOP_PEER_DISCOVERY = 24;
|
|||
|
|
|||
|
/**
|
|||
|
* A constant used in
|
|||
|
* {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)}
|
|||
|
* Tracks usage of
|
|||
|
* {@link WifiP2pManager#connect(WifiP2pManager.Channel, WifiP2pConfig,
|
|||
|
* WifiP2pManager.ActionListener)}
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
public static final int API_P2P_CONNECT = 25;
|
|||
|
|
|||
|
/**
|
|||
|
* A constant used in
|
|||
|
* {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)}
|
|||
|
* Tracks usage of
|
|||
|
* {@link WifiP2pManager#cancelConnect(WifiP2pManager.Channel, WifiP2pManager.ActionListener)}
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
public static final int API_P2P_CANCEL_CONNECT = 26;
|
|||
|
|
|||
|
/**
|
|||
|
* A constant used in
|
|||
|
* {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)}
|
|||
|
* Tracks usage of
|
|||
|
* {@link WifiP2pManager#createGroup(WifiP2pManager.Channel, WifiP2pManager.ActionListener)}
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
public static final int API_P2P_CREATE_GROUP = 27;
|
|||
|
|
|||
|
/**
|
|||
|
* A constant used in
|
|||
|
* {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)}
|
|||
|
* Tracks usage of
|
|||
|
* {@link WifiP2pManager#createGroup(WifiP2pManager.Channel, WifiP2pConfig,
|
|||
|
* WifiP2pManager.ActionListener)}
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
public static final int API_P2P_CREATE_GROUP_P2P_CONFIG = 28;
|
|||
|
|
|||
|
/**
|
|||
|
* A constant used in
|
|||
|
* {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)}
|
|||
|
* Tracks usage of
|
|||
|
* {@link WifiP2pManager#removeGroup(WifiP2pManager.Channel, WifiP2pManager.ActionListener)}
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
public static final int API_P2P_REMOVE_GROUP = 29;
|
|||
|
|
|||
|
/**
|
|||
|
* A constant used in
|
|||
|
* {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)}
|
|||
|
* Tracks usage of
|
|||
|
* {@link WifiP2pManager#startListening(WifiP2pManager.Channel, WifiP2pManager.ActionListener)}
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
public static final int API_P2P_START_LISTENING = 30;
|
|||
|
|
|||
|
/**
|
|||
|
* A constant used in
|
|||
|
* {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)}
|
|||
|
* Tracks usage of
|
|||
|
* {@link WifiP2pManager#stopListening(WifiP2pManager.Channel, WifiP2pManager.ActionListener)}
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
public static final int API_P2P_STOP_LISTENING = 31;
|
|||
|
|
|||
|
/**
|
|||
|
* A constant used in
|
|||
|
* {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)}
|
|||
|
* Tracks usage of
|
|||
|
* {@link WifiP2pManager#setWifiP2pChannels(WifiP2pManager.Channel, int, int,
|
|||
|
* WifiP2pManager.ActionListener)}
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
public static final int API_P2P_SET_CHANNELS = 32;
|
|||
|
|
|||
|
/**
|
|||
|
* A constant used in
|
|||
|
* {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)}
|
|||
|
* Tracks usage of
|
|||
|
* {@link WifiScanner#startScan(WifiScanner.ScanSettings, WifiScanner.ScanListener)}
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
public static final int API_WIFI_SCANNER_START_SCAN = 33;
|
|||
|
|
|||
|
/**
|
|||
|
* A constant used in
|
|||
|
* {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)}
|
|||
|
* Tracks usage of
|
|||
|
* {@link WifiManager#setTdlsEnabled(InetAddress, boolean)} and
|
|||
|
* {@link WifiManager#setTdlsEnabled(InetAddress, boolean, Executor, Consumer)}
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
public static final int API_SET_TDLS_ENABLED = 34;
|
|||
|
|
|||
|
/**
|
|||
|
* A constant used in
|
|||
|
* {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)}
|
|||
|
* Tracks usage of
|
|||
|
* {@link WifiManager#setTdlsEnabledWithMacAddress(String, boolean)} and
|
|||
|
* {@link WifiManager#setTdlsEnabledWithMacAddress(String, boolean, Executor, Consumer)}
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
public static final int API_SET_TDLS_ENABLED_WITH_MAC_ADDRESS = 35;
|
|||
|
|
|||
|
/**
|
|||
|
* A constant used in {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)}
|
|||
|
* Tracks usage of {@link WifiManager#setPnoScanState(int)}
|
|||
|
*
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|||
|
@SystemApi
|
|||
|
public static final int API_SET_PNO_SCAN_ENABLED = 36;
|
|||
|
|
|||
|
/**
|
|||
|
* A constant used in {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)}
|
|||
|
* Tracks usage of {@link WifiP2pManager#discoverPeersWithConfigParams(
|
|||
|
* WifiP2pManager.Channel, WifiP2pDiscoveryConfig, WifiP2pManager.ActionListener)}
|
|||
|
*
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|||
|
@SystemApi
|
|||
|
public static final int API_P2P_DISCOVER_PEERS_WITH_CONFIG_PARAMS = 37;
|
|||
|
|
|||
|
/**
|
|||
|
* Used internally to keep track of boundary.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
public static final int API_MAX = 38;
|
|||
|
|
|||
|
/**
|
|||
|
* 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
|
|||
|
@RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE)
|
|||
|
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}
|
|||
|
* {@link #SAP_START_FAILURE_USER_REJECTED}
|
|||
|
*
|
|||
|
* @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,
|
|||
|
SAP_START_FAILURE_USER_REJECTED,
|
|||
|
})
|
|||
|
@Retention(RetentionPolicy.SOURCE)
|
|||
|
public @interface SapStartFailure {}
|
|||
|
|
|||
|
/**
|
|||
|
* All other reasons for AP start failure besides {@link #SAP_START_FAILURE_NO_CHANNEL},
|
|||
|
* {@link #SAP_START_FAILURE_UNSUPPORTED_CONFIGURATION}, and
|
|||
|
* {@link #SAP_START_FAILURE_USER_REJECTED}.
|
|||
|
*
|
|||
|
* @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;
|
|||
|
|
|||
|
/**
|
|||
|
* If Wi-Fi AP start failed, this reason code means that the user was asked for confirmation to
|
|||
|
* create the AP and the user declined.
|
|||
|
*
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
public static final int SAP_START_FAILURE_USER_REJECTED = 3;
|
|||
|
|
|||
|
/** @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.
|
|||
|
*
|
|||
|
* @deprecated The {@code WIFI_MODE_FULL_HIGH_PERF} is deprecated and is automatically replaced
|
|||
|
* with {@link #WIFI_MODE_FULL_LOW_LATENCY} with all the restrictions documented on that lock.
|
|||
|
* I.e. any request to the {@code WIFI_MODE_FULL_HIGH_PERF} will now obtain a
|
|||
|
* {@link #WIFI_MODE_FULL_LOW_LATENCY} lock instead.
|
|||
|
* Deprecation is due to the impact of {@code WIFI_MODE_FULL_HIGH_PERF} on power dissipation.
|
|||
|
* The {@link #WIFI_MODE_FULL_LOW_LATENCY} provides much of the same desired functionality with
|
|||
|
* less impact on power dissipation.
|
|||
|
*/
|
|||
|
@Deprecated
|
|||
|
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");
|
|||
|
|
|||
|
/** @hide */
|
|||
|
@IntDef(flag = false, prefix = { "WIFI_MULTI_INTERNET_MODE_" }, value = {
|
|||
|
WIFI_MULTI_INTERNET_MODE_DISABLED,
|
|||
|
WIFI_MULTI_INTERNET_MODE_DBS_AP,
|
|||
|
WIFI_MULTI_INTERNET_MODE_MULTI_AP,
|
|||
|
})
|
|||
|
@Retention(RetentionPolicy.SOURCE)
|
|||
|
public @interface WifiMultiInternetMode {}
|
|||
|
|
|||
|
/**
|
|||
|
* Wi-Fi simultaneous connection to multiple internet-providing Wi-Fi networks (APs) is
|
|||
|
* disabled.
|
|||
|
*
|
|||
|
* @see #getStaConcurrencyForMultiInternetMode()
|
|||
|
*
|
|||
|
*/
|
|||
|
public static final int WIFI_MULTI_INTERNET_MODE_DISABLED = 0;
|
|||
|
/**
|
|||
|
* Wi-Fi simultaneous connection to multiple internet-providing Wi-FI networks (APs) is enabled
|
|||
|
* and restricted to a single network on different bands (e.g. a DBS AP).
|
|||
|
*
|
|||
|
* @see #getStaConcurrencyForMultiInternetMode()
|
|||
|
*
|
|||
|
*/
|
|||
|
public static final int WIFI_MULTI_INTERNET_MODE_DBS_AP = 1;
|
|||
|
/**
|
|||
|
* Wi-Fi simultaneous connection to multiple internet-providing Wi-Fi networks (APs) is enabled.
|
|||
|
* The device can connect to any networks/APs - it is just restricted to using different bands
|
|||
|
* for individual connections.
|
|||
|
*
|
|||
|
* @see #getStaConcurrencyForMultiInternetMode()
|
|||
|
*
|
|||
|
*/
|
|||
|
public static final int WIFI_MULTI_INTERNET_MODE_MULTI_AP = 2;
|
|||
|
|
|||
|
/**
|
|||
|
* The bundle key string for the channel frequency in MHz.
|
|||
|
* See {@link #getChannelData(Executor, Consumer)}
|
|||
|
*/
|
|||
|
public static final String CHANNEL_DATA_KEY_FREQUENCY_MHZ = "CHANNEL_DATA_KEY_FREQUENCY_MHZ";
|
|||
|
/**
|
|||
|
* The bundle key for the number of APs found on the corresponding channel specified by
|
|||
|
* {@link WifiManager#CHANNEL_DATA_KEY_FREQUENCY_MHZ}.
|
|||
|
* See {@link #getChannelData(Executor, Consumer)}
|
|||
|
*/
|
|||
|
public static final String CHANNEL_DATA_KEY_NUM_AP = "CHANNEL_DATA_KEY_NUM_AP";
|
|||
|
|
|||
|
/**
|
|||
|
* This policy is being tracked by the Wifi service.
|
|||
|
* Indicates success for {@link #addQosPolicies(List, Executor, Consumer)}.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
public static final int QOS_REQUEST_STATUS_TRACKING = 0;
|
|||
|
|
|||
|
/**
|
|||
|
* A policy with the same policy ID is already being tracked.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
public static final int QOS_REQUEST_STATUS_ALREADY_ACTIVE = 1;
|
|||
|
|
|||
|
/**
|
|||
|
* There are insufficient resources to handle this request at this time.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
public static final int QOS_REQUEST_STATUS_INSUFFICIENT_RESOURCES = 2;
|
|||
|
|
|||
|
/**
|
|||
|
* The parameters in the policy request are invalid.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
public static final int QOS_REQUEST_STATUS_INVALID_PARAMETERS = 3;
|
|||
|
|
|||
|
/**
|
|||
|
* An unspecified failure occurred while processing this request.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
public static final int QOS_REQUEST_STATUS_FAILURE_UNKNOWN = 4;
|
|||
|
|
|||
|
/** @hide */
|
|||
|
@Retention(RetentionPolicy.SOURCE)
|
|||
|
@IntDef(prefix = {"QOS_REQUEST_STATUS_"}, value = {
|
|||
|
QOS_REQUEST_STATUS_TRACKING,
|
|||
|
QOS_REQUEST_STATUS_ALREADY_ACTIVE,
|
|||
|
QOS_REQUEST_STATUS_INSUFFICIENT_RESOURCES,
|
|||
|
QOS_REQUEST_STATUS_INVALID_PARAMETERS,
|
|||
|
QOS_REQUEST_STATUS_FAILURE_UNKNOWN})
|
|||
|
public @interface QosRequestStatus {}
|
|||
|
|
|||
|
/**
|
|||
|
* Maximum number of policies that can be included in a QoS add/remove request.
|
|||
|
*/
|
|||
|
private static final int MAX_POLICIES_PER_QOS_REQUEST = 16;
|
|||
|
|
|||
|
/**
|
|||
|
* Get the maximum number of policies that can be included in a request to
|
|||
|
* {@link #addQosPolicies(List, Executor, Consumer)} or {@link #removeQosPolicies(int[])}.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
public static int getMaxNumberOfPoliciesPerQosRequest() {
|
|||
|
return MAX_POLICIES_PER_QOS_REQUEST;
|
|||
|
}
|
|||
|
|
|||
|
/* 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();
|
|||
|
private static final SparseArray<IOnWifiDriverCountryCodeChangedListener>
|
|||
|
sActiveCountryCodeChangedCallbackMap = new SparseArray();
|
|||
|
private static final SparseArray<ISoftApCallback>
|
|||
|
sLocalOnlyHotspotSoftApCallbackMap = new SparseArray();
|
|||
|
private static final SparseArray<ILocalOnlyConnectionStatusListener>
|
|||
|
sLocalOnlyConnectionStatusListenerMap = new SparseArray();
|
|||
|
private static final SparseArray<IWifiNetworkStateChangedListener>
|
|||
|
sOnWifiNetworkStateChangedListenerMap = new SparseArray<>();
|
|||
|
private static final SparseArray<IWifiLowLatencyLockListener>
|
|||
|
sWifiLowLatencyLockListenerMap = new SparseArray<>();
|
|||
|
|
|||
|
/**
|
|||
|
* Multi-link operation (MLO) will allow Wi-Fi devices to operate on multiple links at the same
|
|||
|
* time through a single connection, aiming to support applications that require lower latency,
|
|||
|
* and higher capacity. Chip vendors have algorithms that run on the chip to use available links
|
|||
|
* based on incoming traffic and various inputs. Below is a list of Multi-Link Operation modes
|
|||
|
* that applications can suggest to be accommodated in the algorithm.
|
|||
|
*
|
|||
|
* The default MLO mode is for chip vendors to use algorithms to select the optimum links to
|
|||
|
* operate on, without any guidance from the calling app.
|
|||
|
*
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
public static final int MLO_MODE_DEFAULT = 0;
|
|||
|
|
|||
|
/**
|
|||
|
* Low latency mode for Multi-link operation. In this mode, the chip vendor's algorithm
|
|||
|
* should select MLO links that will achieve low latency.
|
|||
|
*
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
public static final int MLO_MODE_LOW_LATENCY = 1;
|
|||
|
|
|||
|
/**
|
|||
|
* High throughput mode for Multi-link operation. In this mode, the chip vendor's algorithm
|
|||
|
* should select MLO links that will achieve higher throughput.
|
|||
|
*
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
public static final int MLO_MODE_HIGH_THROUGHPUT = 2;
|
|||
|
|
|||
|
/**
|
|||
|
* Low power mode for Multi-link operation. In this mode, the chip vendor's algorithm
|
|||
|
* should select MLO links that will achieve low power.
|
|||
|
*
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
public static final int MLO_MODE_LOW_POWER = 3;
|
|||
|
|
|||
|
/** @hide */
|
|||
|
@Retention(RetentionPolicy.SOURCE)
|
|||
|
@IntDef(prefix = {"MLO_MODE_"}, value = {
|
|||
|
MLO_MODE_DEFAULT,
|
|||
|
MLO_MODE_LOW_LATENCY,
|
|||
|
MLO_MODE_HIGH_THROUGHPUT,
|
|||
|
MLO_MODE_LOW_POWER})
|
|||
|
public @interface MloMode {
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Roaming is disabled.
|
|||
|
*/
|
|||
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|||
|
public static final int ROAMING_MODE_NONE = 0;
|
|||
|
|
|||
|
/**
|
|||
|
* Chipset has roaming trigger capability based on the score calculated
|
|||
|
* using multiple parameters. If device is configured to this mode then it
|
|||
|
* will be using chipset's normal (default) roaming.
|
|||
|
*/
|
|||
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|||
|
public static final int ROAMING_MODE_NORMAL = 1;
|
|||
|
|
|||
|
/**
|
|||
|
* Allows the device to roam more quickly than the normal roaming mode.
|
|||
|
* Used in cases such as where APs are installed in a high density.
|
|||
|
*/
|
|||
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|||
|
public static final int ROAMING_MODE_AGGRESSIVE = 2;
|
|||
|
|
|||
|
/**
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@Retention(RetentionPolicy.SOURCE)
|
|||
|
@IntDef(prefix = {"ROAMING_MODE_"}, value = {
|
|||
|
ROAMING_MODE_NONE,
|
|||
|
ROAMING_MODE_NORMAL,
|
|||
|
ROAMING_MODE_AGGRESSIVE})
|
|||
|
public @interface RoamingMode {
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 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 SecurityException if the caller is not 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();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* Applications targeting {@link android.os.Build.VERSION_CODES#TIRAMISU} or later need to have
|
|||
|
* the following permissions: {@link android.Manifest.permission#NEARBY_WIFI_DEVICES},
|
|||
|
* {@link android.Manifest.permission#ACCESS_WIFI_STATE} and
|
|||
|
* {@link android.Manifest.permission#READ_WIFI_CREDENTIAL}.
|
|||
|
* Applications targeting {@link Build.VERSION_CODES#S} or prior SDK levels need to have the
|
|||
|
* following permissions: {@link android.Manifest.permission#ACCESS_FINE_LOCATION},
|
|||
|
* {@link android.Manifest.permission#CHANGE_WIFI_STATE} and
|
|||
|
* {@link android.Manifest.permission#READ_WIFI_CREDENTIAL}.
|
|||
|
* <p> See {@link #getPrivilegedConnectedNetwork()} to get the WifiConfiguration for only the
|
|||
|
* connected network that's providing internet by default.
|
|||
|
*
|
|||
|
* @hide
|
|||
|
**/
|
|||
|
@SystemApi
|
|||
|
@RequiresPermission(allOf = {ACCESS_FINE_LOCATION, NEARBY_WIFI_DEVICES, ACCESS_WIFI_STATE,
|
|||
|
READ_WIFI_CREDENTIAL},
|
|||
|
conditional = true)
|
|||
|
public List<WifiConfiguration> getPrivilegedConfiguredNetworks() {
|
|||
|
try {
|
|||
|
Bundle extras = new Bundle();
|
|||
|
if (SdkLevel.isAtLeastS()) {
|
|||
|
extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE,
|
|||
|
mContext.getAttributionSource());
|
|||
|
}
|
|||
|
ParceledListSlice<WifiConfiguration> parceledList =
|
|||
|
mService.getPrivilegedConfiguredNetworks(mContext.getOpPackageName(),
|
|||
|
mContext.getAttributionTag(), extras);
|
|||
|
if (parceledList == null) {
|
|||
|
return Collections.emptyList();
|
|||
|
}
|
|||
|
return parceledList.getList();
|
|||
|
} catch (RemoteException e) {
|
|||
|
throw e.rethrowFromSystemServer();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Gets the {@link WifiConfiguration} with credentials of the connected wifi network
|
|||
|
* that's providing internet by default.
|
|||
|
* <p>
|
|||
|
* On {@link android.os.Build.VERSION_CODES#TIRAMISU} or later SDKs, the caller need to have
|
|||
|
* the following permissions: {@link android.Manifest.permission#NEARBY_WIFI_DEVICES} with
|
|||
|
* android:usesPermissionFlags="neverForLocation",
|
|||
|
* {@link android.Manifest.permission#ACCESS_WIFI_STATE} and
|
|||
|
* {@link android.Manifest.permission#READ_WIFI_CREDENTIAL}. If the app does not have
|
|||
|
* android:usesPermissionFlags="neverForLocation", then it must also have
|
|||
|
* {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
|
|||
|
* <p>
|
|||
|
* On {@link Build.VERSION_CODES#S} or prior SDKs, the caller need to have the
|
|||
|
* following permissions: {@link android.Manifest.permission#ACCESS_FINE_LOCATION},
|
|||
|
* {@link android.Manifest.permission#CHANGE_WIFI_STATE} and
|
|||
|
* {@link android.Manifest.permission#READ_WIFI_CREDENTIAL}.
|
|||
|
*
|
|||
|
* @return The WifiConfiguration representation of the connected wifi network providing
|
|||
|
* internet, or null if wifi is not connected.
|
|||
|
*
|
|||
|
* @throws SecurityException if caller does not have the required permissions
|
|||
|
* @hide
|
|||
|
**/
|
|||
|
@SystemApi
|
|||
|
@RequiresPermission(allOf = {NEARBY_WIFI_DEVICES, ACCESS_WIFI_STATE, READ_WIFI_CREDENTIAL},
|
|||
|
conditional = true)
|
|||
|
@Nullable
|
|||
|
public WifiConfiguration getPrivilegedConnectedNetwork() {
|
|||
|
try {
|
|||
|
Bundle extras = new Bundle();
|
|||
|
if (SdkLevel.isAtLeastS()) {
|
|||
|
extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE,
|
|||
|
mContext.getAttributionSource());
|
|||
|
}
|
|||
|
return mService.getPrivilegedConnectedNetwork(mContext.getOpPackageName(),
|
|||
|
mContext.getAttributionTag(), extras);
|
|||
|
} 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;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* To be used with setScreenOnScanSchedule.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
public static class ScreenOnScanSchedule {
|
|||
|
private final Duration mScanInterval;
|
|||
|
private final int mScanType;
|
|||
|
|
|||
|
/**
|
|||
|
* Creates a ScreenOnScanSchedule.
|
|||
|
* @param scanInterval Interval between framework-initiated connectivity scans.
|
|||
|
* @param scanType One of the {@code WifiScanner.SCAN_TYPE_} values.
|
|||
|
*/
|
|||
|
public ScreenOnScanSchedule(@NonNull Duration scanInterval,
|
|||
|
@WifiAnnotations.ScanType int scanType) {
|
|||
|
if (scanInterval == null) {
|
|||
|
throw new IllegalArgumentException("scanInterval can't be null");
|
|||
|
}
|
|||
|
mScanInterval = scanInterval;
|
|||
|
mScanType = scanType;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Gets the interval between framework-initiated connectivity scans.
|
|||
|
*/
|
|||
|
public @NonNull Duration getScanInterval() {
|
|||
|
return mScanInterval;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Gets the type of scan to be used. One of the {@code WifiScanner.SCAN_TYPE_} values.
|
|||
|
*/
|
|||
|
public @WifiAnnotations.ScanType int getScanType() {
|
|||
|
return mScanType;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* This API allows a privileged app to customize the wifi framework's network selection logic.
|
|||
|
* To revert to default behavior, call this API with a {@link WifiNetworkSelectionConfig}
|
|||
|
* created from a default {@link WifiNetworkSelectionConfig.Builder}.
|
|||
|
*
|
|||
|
* Use {@link WifiManager#getNetworkSelectionConfig(Executor, Consumer)} to get the current
|
|||
|
* network selection configuration.
|
|||
|
* <P>
|
|||
|
* @param nsConfig an Object representing the network selection configuration being programmed.
|
|||
|
* This should be created with a {@link WifiNetworkSelectionConfig.Builder}.
|
|||
|
*
|
|||
|
* @throws UnsupportedOperationException if the API is not supported on this SDK version.
|
|||
|
* @throws IllegalArgumentException if input is invalid.
|
|||
|
* @throws SecurityException if the caller does not have permission.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
|
|||
|
@RequiresPermission(anyOf = {
|
|||
|
android.Manifest.permission.NETWORK_SETTINGS,
|
|||
|
MANAGE_WIFI_NETWORK_SELECTION
|
|||
|
})
|
|||
|
@SystemApi
|
|||
|
public void setNetworkSelectionConfig(@NonNull WifiNetworkSelectionConfig nsConfig) {
|
|||
|
try {
|
|||
|
if (nsConfig == null) {
|
|||
|
throw new IllegalArgumentException("nsConfig can not be null");
|
|||
|
}
|
|||
|
mService.setNetworkSelectionConfig(nsConfig);
|
|||
|
} catch (RemoteException e) {
|
|||
|
throw e.rethrowFromSystemServer();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* This API allows a privileged app to retrieve the {@link WifiNetworkSelectionConfig}
|
|||
|
* currently being used by the network selector.
|
|||
|
*
|
|||
|
* Use {@link WifiManager#setNetworkSelectionConfig(WifiNetworkSelectionConfig)} to set a
|
|||
|
* new network selection configuration.
|
|||
|
* <P>
|
|||
|
* @param executor The executor on which callback will be invoked.
|
|||
|
* @param resultsCallback An asynchronous callback that will return
|
|||
|
* {@link WifiNetworkSelectionConfig}
|
|||
|
*
|
|||
|
* @throws UnsupportedOperationException if the API is not supported on this SDK version.
|
|||
|
* @throws SecurityException if the caller does not have permission.
|
|||
|
* @throws NullPointerException if the caller provided invalid inputs.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
|
|||
|
@RequiresPermission(anyOf = {
|
|||
|
android.Manifest.permission.NETWORK_SETTINGS,
|
|||
|
MANAGE_WIFI_NETWORK_SELECTION
|
|||
|
})
|
|||
|
@SystemApi
|
|||
|
public void getNetworkSelectionConfig(@NonNull @CallbackExecutor Executor executor,
|
|||
|
@NonNull Consumer<WifiNetworkSelectionConfig> resultsCallback) {
|
|||
|
Objects.requireNonNull(executor, "executor cannot be null");
|
|||
|
Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null");
|
|||
|
try {
|
|||
|
mService.getNetworkSelectionConfig(
|
|||
|
new IWifiNetworkSelectionConfigListener.Stub() {
|
|||
|
@Override
|
|||
|
public void onResult(WifiNetworkSelectionConfig value) {
|
|||
|
Binder.clearCallingIdentity();
|
|||
|
executor.execute(() -> {
|
|||
|
resultsCallback.accept(value);
|
|||
|
});
|
|||
|
}
|
|||
|
});
|
|||
|
} catch (RemoteException e) {
|
|||
|
throw e.rethrowFromSystemServer();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Allows a privileged app to enable/disable whether a confirmation dialog should be displayed
|
|||
|
* when third-party apps attempt to turn on WiFi.
|
|||
|
*
|
|||
|
* Use {@link #isThirdPartyAppEnablingWifiConfirmationDialogEnabled()} to get the
|
|||
|
* currently configured value.
|
|||
|
*
|
|||
|
* Note: Only affects behavior for apps with targetSDK < Q, since third party apps are not
|
|||
|
* allowed to enable wifi on targetSDK >= Q.
|
|||
|
*
|
|||
|
* This overrides the overlay value |config_showConfirmationDialogForThirdPartyAppsEnablingWifi|
|
|||
|
* <P>
|
|||
|
* @param enable true to enable the confirmation dialog, false otherwise
|
|||
|
*
|
|||
|
* @throws UnsupportedOperationException if the API is not supported on this SDK version.
|
|||
|
* @throws SecurityException if the caller does not have permission.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@RequiresPermission(anyOf = {
|
|||
|
android.Manifest.permission.NETWORK_SETTINGS,
|
|||
|
android.Manifest.permission.NETWORK_SETUP_WIZARD
|
|||
|
})
|
|||
|
@SystemApi
|
|||
|
public void setThirdPartyAppEnablingWifiConfirmationDialogEnabled(boolean enable) {
|
|||
|
try {
|
|||
|
mService.setThirdPartyAppEnablingWifiConfirmationDialogEnabled(enable);
|
|||
|
} catch (RemoteException e) {
|
|||
|
throw e.rethrowFromSystemServer();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Check whether the wifi configuration indicates that a confirmation dialog should be displayed
|
|||
|
* when third-party apps attempt to turn on WiFi.
|
|||
|
*
|
|||
|
* Use {@link #setThirdPartyAppEnablingWifiConfirmationDialogEnabled(boolean)} to set this
|
|||
|
* value.
|
|||
|
*
|
|||
|
* Note: This setting only affects behavior for apps with targetSDK < Q, since third party apps
|
|||
|
* are not allowed to enable wifi on targetSDK >= Q.
|
|||
|
*
|
|||
|
* <P>
|
|||
|
* @throws UnsupportedOperationException if the API is not supported on this SDK version.
|
|||
|
* @throws SecurityException if the caller does not have permission.
|
|||
|
* @return true if dialog should be displayed, false otherwise.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@RequiresPermission(anyOf = {
|
|||
|
android.Manifest.permission.NETWORK_SETTINGS,
|
|||
|
android.Manifest.permission.NETWORK_SETUP_WIZARD
|
|||
|
})
|
|||
|
@SystemApi
|
|||
|
public boolean isThirdPartyAppEnablingWifiConfirmationDialogEnabled() {
|
|||
|
try {
|
|||
|
return mService.isThirdPartyAppEnablingWifiConfirmationDialogEnabled();
|
|||
|
} catch (RemoteException e) {
|
|||
|
throw e.rethrowFromSystemServer();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Allows a privileged app to customize the screen-on scan behavior. When a non-null schedule
|
|||
|
* is set via this API, it will always get used instead of the scan schedules defined in the
|
|||
|
* overlay. When a null schedule is set via this API, the wifi subsystem will go back to using
|
|||
|
* the scan schedules defined in the overlay. Also note, the scan schedule will be truncated
|
|||
|
* (rounded down) to the nearest whole second.
|
|||
|
* <p>
|
|||
|
* Example usage:
|
|||
|
* The following call specifies that first scheduled scan should be in 20 seconds using
|
|||
|
* {@link WifiScanner#SCAN_TYPE_HIGH_ACCURACY}, and all
|
|||
|
* scheduled scans later should happen every 40 seconds using
|
|||
|
* {@link WifiScanner#SCAN_TYPE_LOW_POWER}.
|
|||
|
* <pre>
|
|||
|
* List<ScreenOnScanSchedule> schedule = new ArrayList<>();
|
|||
|
* schedule.add(new ScreenOnScanSchedule(Duration.ofSeconds(20),
|
|||
|
* WifiScanner.SCAN_TYPE_HIGH_ACCURACY));
|
|||
|
* schedule.add(new ScreenOnScanSchedule(Duration.ofSeconds(40),
|
|||
|
* WifiScanner.SCAN_TYPE_LOW_POWER));
|
|||
|
* wifiManager.setScreenOnScanSchedule(schedule);
|
|||
|
* </pre>
|
|||
|
* @param screenOnScanSchedule defines the screen-on scan schedule and the corresponding
|
|||
|
* scan type. Set to null to clear any previously set value.
|
|||
|
*
|
|||
|
* @throws IllegalStateException if input is invalid
|
|||
|
* @throws UnsupportedOperationException if the API is not supported on this SDK version.
|
|||
|
* @throws SecurityException if the caller does not have permission.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
|
|||
|
@RequiresPermission(anyOf = {
|
|||
|
android.Manifest.permission.NETWORK_SETTINGS,
|
|||
|
MANAGE_WIFI_NETWORK_SELECTION
|
|||
|
})
|
|||
|
@SystemApi
|
|||
|
public void setScreenOnScanSchedule(@Nullable List<ScreenOnScanSchedule> screenOnScanSchedule) {
|
|||
|
try {
|
|||
|
if (screenOnScanSchedule == null) {
|
|||
|
mService.setScreenOnScanSchedule(null, null);
|
|||
|
return;
|
|||
|
}
|
|||
|
if (screenOnScanSchedule.isEmpty()) {
|
|||
|
throw new IllegalArgumentException("The input should either be null or a non-empty"
|
|||
|
+ " list");
|
|||
|
}
|
|||
|
int[] scanSchedule = new int[screenOnScanSchedule.size()];
|
|||
|
int[] scanType = new int[screenOnScanSchedule.size()];
|
|||
|
for (int i = 0; i < screenOnScanSchedule.size(); i++) {
|
|||
|
scanSchedule[i] = (int) screenOnScanSchedule.get(i).getScanInterval().toSeconds();
|
|||
|
scanType[i] = screenOnScanSchedule.get(i).getScanType();
|
|||
|
}
|
|||
|
mService.setScreenOnScanSchedule(scanSchedule, scanType);
|
|||
|
} catch (RemoteException e) {
|
|||
|
throw e.rethrowFromSystemServer();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* The Wi-Fi framework may trigger connectivity scans in response to the screen turning on for
|
|||
|
* network selection purposes. This API allows a privileged app to set a delay to the next
|
|||
|
* connectivity scan triggered by the Wi-Fi framework in response to the next screen-on event.
|
|||
|
* This gives a window for the privileged app to issue their own custom scans to influence Wi-Fi
|
|||
|
* network selection. The expected usage is the privileged app monitor for the screen turning
|
|||
|
* off, and then call this API if it believes delaying the next screen-on connectivity scan is
|
|||
|
* needed.
|
|||
|
* <p>
|
|||
|
* Note that this API will only delay screen-on connectivity scans once. This API will need to
|
|||
|
* be called again if further screen-on scan delays are needed after it resolves.
|
|||
|
* @param delayMs defines the time in milliseconds to delay the next screen-on connectivity
|
|||
|
* scan. Setting this to 0 will remove the delay.
|
|||
|
*
|
|||
|
* @throws IllegalStateException if input is invalid
|
|||
|
* @throws UnsupportedOperationException if the API is not supported on this SDK version.
|
|||
|
* @throws SecurityException if the caller does not have permission.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
|
|||
|
@RequiresPermission(anyOf = {
|
|||
|
android.Manifest.permission.NETWORK_SETTINGS,
|
|||
|
MANAGE_WIFI_NETWORK_SELECTION
|
|||
|
})
|
|||
|
@SystemApi
|
|||
|
public void setOneShotScreenOnConnectivityScanDelayMillis(@IntRange(from = 0) int delayMs) {
|
|||
|
try {
|
|||
|
mService.setOneShotScreenOnConnectivityScanDelayMillis(delayMs);
|
|||
|
} catch (RemoteException e) {
|
|||
|
throw e.rethrowFromSystemServer();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 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();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Specify a set of SSIDs that will not get disabled internally by the Wi-Fi subsystem when
|
|||
|
* connection issues occur. To clear the list, call this API with an empty Set.
|
|||
|
* <p>
|
|||
|
* {@link #getSsidsAllowlist()} can be used to check the SSIDs that have been set.
|
|||
|
* @param ssids - list of WifiSsid that will not get disabled internally
|
|||
|
* @throws SecurityException if the calling app is not a Device Owner (DO), Profile Owner (PO),
|
|||
|
* or a privileged app that has one of the permissions required by
|
|||
|
* this API.
|
|||
|
* @throws IllegalArgumentException if the input is null.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
@RequiresPermission(anyOf = {
|
|||
|
android.Manifest.permission.NETWORK_SETTINGS,
|
|||
|
android.Manifest.permission.MANAGE_WIFI_NETWORK_SELECTION}, conditional = true)
|
|||
|
public void setSsidsAllowlist(@NonNull Set<WifiSsid> ssids) {
|
|||
|
if (ssids == null) {
|
|||
|
throw new IllegalArgumentException(TAG + ": ssids can not be null");
|
|||
|
}
|
|||
|
try {
|
|||
|
mService.setSsidsAllowlist(mContext.getOpPackageName(), new ArrayList<>(ssids));
|
|||
|
} catch (RemoteException e) {
|
|||
|
throw e.rethrowFromSystemServer();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Get the Set of SSIDs that will not get disabled internally by the Wi-Fi subsystem when
|
|||
|
* connection issues occur.
|
|||
|
* @throws SecurityException if the calling app is not a Device Owner (DO), Profile Owner (PO),
|
|||
|
* or a privileged app that has one of the permissions required by
|
|||
|
* this API.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
@RequiresPermission(anyOf = {
|
|||
|
android.Manifest.permission.NETWORK_SETTINGS,
|
|||
|
android.Manifest.permission.MANAGE_WIFI_NETWORK_SELECTION}, conditional = true)
|
|||
|
public @NonNull Set<WifiSsid> getSsidsAllowlist() {
|
|||
|
try {
|
|||
|
return new ArraySet<WifiSsid>(
|
|||
|
mService.getSsidsAllowlist(mContext.getOpPackageName()));
|
|||
|
} catch (RemoteException e) {
|
|||
|
throw e.rethrowFromSystemServer();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 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 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 IllegalArgumentException if the input configuration is null or if the
|
|||
|
* security type in input configuration is not supported.
|
|||
|
*/
|
|||
|
@RequiresPermission(anyOf = {
|
|||
|
android.Manifest.permission.NETWORK_SETTINGS,
|
|||
|
android.Manifest.permission.NETWORK_STACK,
|
|||
|
android.Manifest.permission.NETWORK_SETUP_WIZARD,
|
|||
|
android.Manifest.permission.NETWORK_MANAGED_PROVISIONING
|
|||
|
}, conditional = true)
|
|||
|
@NonNull
|
|||
|
public AddNetworkResult addNetworkPrivileged(@NonNull WifiConfiguration config) {
|
|||
|
if (config == null) throw new IllegalArgumentException("config cannot be null");
|
|||
|
if (config.isSecurityType(WifiInfo.SECURITY_TYPE_DPP)
|
|||
|
&& !isFeatureSupported(WIFI_FEATURE_DPP_AKM)) {
|
|||
|
throw new IllegalArgumentException("dpp akm is not supported");
|
|||
|
}
|
|||
|
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) {
|
|||
|
Bundle extras = new Bundle();
|
|||
|
if (SdkLevel.isAtLeastS()) {
|
|||
|
extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE,
|
|||
|
mContext.getAttributionSource());
|
|||
|
}
|
|||
|
|
|||
|
try {
|
|||
|
return mService.addOrUpdateNetwork(config, mContext.getOpPackageName(), extras);
|
|||
|
} 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:
|
|||
|
* <ul>
|
|||
|
* <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>
|
|||
|
* <ul>
|
|||
|
* <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>
|
|||
|
* On {@link android.os.Build.VERSION_CODES#TIRAMISU} or above If one of the provided
|
|||
|
* suggestions marks a previously trusted suggestion as untrusted 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. This disconnect is to make
|
|||
|
* sure device will not remain connected to an untrusted network without a related
|
|||
|
* {@link android.net.NetworkRequest}.
|
|||
|
* </li>
|
|||
|
* </ul>
|
|||
|
* </ul>
|
|||
|
*
|
|||
|
* @param networkSuggestions List of network suggestions provided by the app.
|
|||
|
* @return Status code for the operation. One of the STATUS_NETWORK_SUGGESTIONS_ values.
|
|||
|
* @throws SecurityException if the caller is missing required permissions.
|
|||
|
* @see WifiNetworkSuggestion#equals(Object)
|
|||
|
*/
|
|||
|
@RequiresPermission(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. This method is same
|
|||
|
* as {@link #removeNetworkSuggestions(List, int)} with
|
|||
|
* {@link #ACTION_REMOVE_SUGGESTION_DISCONNECT}
|
|||
|
*
|
|||
|
* See {@link WifiNetworkSuggestion} for a detailed explanation of the parameters.
|
|||
|
* See {@link WifiNetworkSuggestion#equals(Object)} for the equivalence evaluation used.
|
|||
|
* <p></
|
|||
|
* Note: Use {@link #removeNetworkSuggestions(List, int)}. An {@code action} of
|
|||
|
* {@link #ACTION_REMOVE_SUGGESTION_DISCONNECT} is equivalent to the current behavior.
|
|||
|
*
|
|||
|
* @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 {@code STATUS_NETWORK_SUGGESTIONS_*}
|
|||
|
* values. Any matching suggestions are removed from the device and will not be considered for
|
|||
|
* any further connection attempts.
|
|||
|
*/
|
|||
|
@RequiresPermission(CHANGE_WIFI_STATE)
|
|||
|
public @NetworkSuggestionsStatusCode int removeNetworkSuggestions(
|
|||
|
@NonNull List<WifiNetworkSuggestion> networkSuggestions) {
|
|||
|
return removeNetworkSuggestions(networkSuggestions, ACTION_REMOVE_SUGGESTION_DISCONNECT);
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 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 specified action will be executed.
|
|||
|
*
|
|||
|
* 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.
|
|||
|
* @param action Desired action to execute after removing the suggestion. One of
|
|||
|
* {@code ACTION_REMOVE_SUGGESTION_*}
|
|||
|
* @return Status code for the operation. One of the {@code STATUS_NETWORK_SUGGESTIONS_*}
|
|||
|
* values. Any matching suggestions are removed from the device and will not be considered for
|
|||
|
* further connection attempts.
|
|||
|
*/
|
|||
|
@RequiresPermission(CHANGE_WIFI_STATE)
|
|||
|
public @NetworkSuggestionsStatusCode int removeNetworkSuggestions(
|
|||
|
@NonNull List<WifiNetworkSuggestion> networkSuggestions,
|
|||
|
@ActionAfterRemovingSuggestion int action) {
|
|||
|
try {
|
|||
|
return mService.removeNetworkSuggestions(networkSuggestions,
|
|||
|
mContext.getOpPackageName(), action);
|
|||
|
} 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.
|
|||
|
* <br>
|
|||
|
* Requires {@code android.Manifest.permission.NETWORK_SETTINGS} or
|
|||
|
* {@code android.Manifest.permission.NETWORK_CARRIER_PROVISIONING}.
|
|||
|
*/
|
|||
|
@Deprecated
|
|||
|
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.
|
|||
|
* <br>
|
|||
|
* Requires {@code android.Manifest.permission.NETWORK_SETTINGS} or
|
|||
|
* {@code android.Manifest.permission.NETWORK_SETUP_WIZARD}.
|
|||
|
*/
|
|||
|
@Deprecated
|
|||
|
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 SecurityException if the caller is not a Device Owner app
|
|||
|
*/
|
|||
|
@RequiresPermission(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();
|
|||
|
}
|
|||
|
|
|||
|
/** @hide */
|
|||
|
public static final long WIFI_FEATURE_INFRA = 1L << 0; // Basic infrastructure mode
|
|||
|
/** @hide */
|
|||
|
public static final long WIFI_FEATURE_PASSPOINT = 1L << 2; // Support for GAS/ANQP
|
|||
|
/** @hide */
|
|||
|
public static final long WIFI_FEATURE_P2P = 1L << 3; // Wifi-Direct
|
|||
|
/** @hide */
|
|||
|
public static final long WIFI_FEATURE_MOBILE_HOTSPOT = 1L << 4; // Soft AP
|
|||
|
/** @hide */
|
|||
|
public static final long WIFI_FEATURE_SCANNER = 1L << 5; // WifiScanner APIs
|
|||
|
/** @hide */
|
|||
|
public static final long WIFI_FEATURE_AWARE = 1L << 6; // Wi-Fi Aware networking
|
|||
|
/** @hide */
|
|||
|
public static final long WIFI_FEATURE_D2D_RTT = 1L << 7; // Device-to-device RTT
|
|||
|
/** @hide */
|
|||
|
public static final long WIFI_FEATURE_D2AP_RTT = 1L << 8; // Device-to-AP RTT
|
|||
|
/** @hide */
|
|||
|
public static final long WIFI_FEATURE_PNO = 1L << 10; // Preferred network offload
|
|||
|
/** @hide */
|
|||
|
public static final long WIFI_FEATURE_TDLS = 1L << 12; // Tunnel directed link setup
|
|||
|
/** @hide */
|
|||
|
public static final long WIFI_FEATURE_TDLS_OFFCHANNEL = 1L << 13; // TDLS off channel
|
|||
|
/** @hide */
|
|||
|
public static final long WIFI_FEATURE_AP_STA = 1L << 15; // AP STA Concurrency
|
|||
|
/** @hide */
|
|||
|
public static final long WIFI_FEATURE_LINK_LAYER_STATS = 1L << 16; // Link layer stats
|
|||
|
/** @hide */
|
|||
|
public static final long WIFI_FEATURE_LOGGER = 1L << 17; // WiFi Logger
|
|||
|
/** @hide */
|
|||
|
public static final long WIFI_FEATURE_RSSI_MONITOR = 1L << 19; // RSSI Monitor
|
|||
|
/** @hide */
|
|||
|
public static final long WIFI_FEATURE_MKEEP_ALIVE = 1L << 20; // mkeep_alive
|
|||
|
/** @hide */
|
|||
|
public static final long WIFI_FEATURE_CONFIG_NDO = 1L << 21; // ND offload
|
|||
|
/** @hide */
|
|||
|
public static final long WIFI_FEATURE_CONTROL_ROAMING = 1L << 23; // Control firmware roaming
|
|||
|
/** @hide */
|
|||
|
public static final long WIFI_FEATURE_IE_WHITELIST = 1L << 24; // Probe IE white listing
|
|||
|
/** @hide */
|
|||
|
public static final long WIFI_FEATURE_SCAN_RAND = 1L << 25; // Random MAC & Probe seq
|
|||
|
/** @hide */
|
|||
|
public static final long WIFI_FEATURE_TX_POWER_LIMIT = 1L << 26; // Set Tx power limit
|
|||
|
/** @hide */
|
|||
|
public static final long WIFI_FEATURE_WPA3_SAE = 1L << 27; // WPA3-Personal SAE
|
|||
|
/** @hide */
|
|||
|
public static final long WIFI_FEATURE_WPA3_SUITE_B = 1L << 28; // WPA3-Enterprise Suite-B
|
|||
|
/** @hide */
|
|||
|
public static final long WIFI_FEATURE_OWE = 1L << 29; // Enhanced Open
|
|||
|
/** @hide */
|
|||
|
public static final long WIFI_FEATURE_LOW_LATENCY = 1L << 30; // Low Latency modes
|
|||
|
/** @hide */
|
|||
|
public static final long WIFI_FEATURE_DPP = 1L << 31; // DPP (Easy-Connect)
|
|||
|
/** @hide */
|
|||
|
public static final long WIFI_FEATURE_P2P_RAND_MAC = 1L << 32; // Random P2P MAC
|
|||
|
/** @hide */
|
|||
|
public static final long WIFI_FEATURE_CONNECTED_RAND_MAC = 1L << 33; // Random STA MAC
|
|||
|
/** @hide */
|
|||
|
public static final long WIFI_FEATURE_AP_RAND_MAC = 1L << 34; // Random AP MAC
|
|||
|
/** @hide */
|
|||
|
public static final long WIFI_FEATURE_MBO = 1L << 35; // MBO Support
|
|||
|
/** @hide */
|
|||
|
public static final long WIFI_FEATURE_OCE = 1L << 36; // OCE Support
|
|||
|
/** @hide */
|
|||
|
public static final long WIFI_FEATURE_WAPI = 1L << 37; // WAPI
|
|||
|
|
|||
|
/** @hide */
|
|||
|
public static final long WIFI_FEATURE_FILS_SHA256 = 1L << 38; // FILS-SHA256
|
|||
|
|
|||
|
/** @hide */
|
|||
|
public static final long WIFI_FEATURE_FILS_SHA384 = 1L << 39; // FILS-SHA384
|
|||
|
|
|||
|
/** @hide */
|
|||
|
public static final long WIFI_FEATURE_SAE_PK = 1L << 40; // SAE-PK
|
|||
|
|
|||
|
/** @hide */
|
|||
|
public static final long WIFI_FEATURE_STA_BRIDGED_AP = 1L << 41; // STA + Bridged AP
|
|||
|
|
|||
|
/** @hide */
|
|||
|
public static final long WIFI_FEATURE_BRIDGED_AP = 1L << 42; // Bridged AP
|
|||
|
|
|||
|
/** @hide */
|
|||
|
public static final long WIFI_FEATURE_INFRA_60G = 1L << 43; // 60 GHz Band Support
|
|||
|
|
|||
|
/**
|
|||
|
* Support for 2 STA's for the local-only (peer to peer) connection + internet connection
|
|||
|
* concurrency.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
public static final long WIFI_FEATURE_ADDITIONAL_STA_LOCAL_ONLY = 1L << 44;
|
|||
|
|
|||
|
/**
|
|||
|
* Support for 2 STA's for the make before break concurrency.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
public static final long WIFI_FEATURE_ADDITIONAL_STA_MBB = 1L << 45;
|
|||
|
|
|||
|
/**
|
|||
|
* Support for 2 STA's for the restricted connection + internet connection concurrency.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
public static final long WIFI_FEATURE_ADDITIONAL_STA_RESTRICTED = 1L << 46;
|
|||
|
|
|||
|
/**
|
|||
|
* DPP (Easy-Connect) Enrollee Responder mode support
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
public static final long WIFI_FEATURE_DPP_ENROLLEE_RESPONDER = 1L << 47;
|
|||
|
|
|||
|
/**
|
|||
|
* Passpoint Terms and Conditions feature support
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
public static final long WIFI_FEATURE_PASSPOINT_TERMS_AND_CONDITIONS = 1L << 48;
|
|||
|
|
|||
|
/** @hide */
|
|||
|
public static final long WIFI_FEATURE_SAE_H2E = 1L << 49; // Hash-to-Element
|
|||
|
|
|||
|
/** @hide */
|
|||
|
public static final long WIFI_FEATURE_WFD_R2 = 1L << 50; // Wi-Fi Display R2
|
|||
|
|
|||
|
/**
|
|||
|
* RFC 7542 decorated identity support
|
|||
|
* @hide */
|
|||
|
public static final long WIFI_FEATURE_DECORATED_IDENTITY = 1L << 51;
|
|||
|
|
|||
|
/**
|
|||
|
* Trust On First Use support for WPA Enterprise network
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
public static final long WIFI_FEATURE_TRUST_ON_FIRST_USE = 1L << 52;
|
|||
|
|
|||
|
/**
|
|||
|
* Support for 2 STA's multi internet concurrency.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
public static final long WIFI_FEATURE_ADDITIONAL_STA_MULTI_INTERNET = 1L << 53;
|
|||
|
|
|||
|
/**
|
|||
|
* Support for DPP (Easy-Connect) AKM.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
public static final long WIFI_FEATURE_DPP_AKM = 1L << 54;
|
|||
|
|
|||
|
/**
|
|||
|
* Support for setting TLS minimum version.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
public static final long WIFI_FEATURE_SET_TLS_MINIMUM_VERSION = 1L << 55;
|
|||
|
|
|||
|
/**
|
|||
|
* Support for TLS v.13.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
public static final long WIFI_FEATURE_TLS_V1_3 = 1L << 56;
|
|||
|
|
|||
|
/**
|
|||
|
* Support for Dual Band Simultaneous (DBS) operation.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
public static final long WIFI_FEATURE_DUAL_BAND_SIMULTANEOUS = 1L << 57;
|
|||
|
|
|||
|
/**
|
|||
|
* Support for TID-To-Link Mapping negotiation.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
public static final long WIFI_FEATURE_T2LM_NEGOTIATION = 1L << 58;
|
|||
|
|
|||
|
/**
|
|||
|
* Support for WEP Wi-Fi Network
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
public static final long WIFI_FEATURE_WEP = 1L << 59;
|
|||
|
|
|||
|
/**
|
|||
|
* Support for WPA PERSONAL Wi-Fi Network
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
public static final long WIFI_FEATURE_WPA_PERSONAL = 1L << 60;
|
|||
|
|
|||
|
/**
|
|||
|
* Support for Roaming Mode
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
public static final long WIFI_FEATURE_AGGRESSIVE_ROAMING_MODE_SUPPORT = 1L << 61;
|
|||
|
|
|||
|
/**
|
|||
|
* Supports device-to-device connections when infra STA is disabled.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
public static final long WIFI_FEATURE_D2D_WHEN_INFRA_STA_DISABLED = 1L << 62;
|
|||
|
|
|||
|
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 multi
|
|||
|
* internet connections.
|
|||
|
*
|
|||
|
* @return true if this device supports multiple STA concurrency for this use-case, false
|
|||
|
* otherwise.
|
|||
|
*/
|
|||
|
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
|
|||
|
public boolean isStaConcurrencyForMultiInternetSupported() {
|
|||
|
return isFeatureSupported(WIFI_FEATURE_ADDITIONAL_STA_MULTI_INTERNET);
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 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() {
|
|||
|
try {
|
|||
|
return mService.isPnoSupported();
|
|||
|
} catch (RemoteException e) {
|
|||
|
throw e.rethrowFromSystemServer();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* @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);
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* @return true if this device supports Low latency mode.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|||
|
@SystemApi
|
|||
|
public boolean isLowLatencyModeSupported() {
|
|||
|
return isFeatureSupported(WIFI_FEATURE_LOW_LATENCY);
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 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).
|
|||
|
*
|
|||
|
* @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.
|
|||
|
*
|
|||
|
* @return true if this device supports concurrency of multiple AP which bridged together,
|
|||
|
* false otherwise.
|
|||
|
*/
|
|||
|
public boolean isBridgedApConcurrencySupported() {
|
|||
|
return isFeatureSupported(WIFI_FEATURE_BRIDGED_AP);
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* @return true if this devices supports device-to-device (D2d) Wi-Fi use-cases
|
|||
|
* such as Wi-Fi Direct when infra station (STA) is disabled.
|
|||
|
*/
|
|||
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|||
|
public boolean isD2dSupportedWhenInfraStaDisabled() {
|
|||
|
return isFeatureSupported(WIFI_FEATURE_D2D_WHEN_INFRA_STA_DISABLED);
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 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>
|
|||
|
* final NetworkRequest request =
|
|||
|
* new NetworkRequest.Builder()
|
|||
|
* .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
|
|||
|
* .build();
|
|||
|
* final ConnectivityManager connectivityManager =
|
|||
|
* context.getSystemService(ConnectivityManager.class);
|
|||
|
* final NetworkCallback networkCallback = new NetworkCallback() {
|
|||
|
* ...
|
|||
|
* @Override
|
|||
|
* void onAvailable(Network network) {}
|
|||
|
*
|
|||
|
* @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
|
|||
|
@RequiresPermission(allOf = {ACCESS_WIFI_STATE, ACCESS_FINE_LOCATION}, conditional = true)
|
|||
|
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
|
|||
|
* and {@link android.Manifest.permission#ACCESS_WIFI_STATE} permission
|
|||
|
* in order to get valid results.
|
|||
|
*
|
|||
|
* <p>
|
|||
|
* When an Access Point’s beacon or probe response includes a Multi-BSSID Element, the
|
|||
|
* returned scan results should include separate scan result for each BSSID within the
|
|||
|
* Multi-BSSID Information Element. This includes both transmitted and non-transmitted BSSIDs.
|
|||
|
* Original Multi-BSSID Element will be included in the Information Elements attached to
|
|||
|
* each of the scan results.
|
|||
|
* Note: This is the expected behavior for devices supporting 11ax (WiFi-6) and above, and an
|
|||
|
* optional requirement for devices running with older WiFi generations.
|
|||
|
* </p>
|
|||
|
*/
|
|||
|
@RequiresPermission(allOf = {ACCESS_WIFI_STATE, ACCESS_FINE_LOCATION})
|
|||
|
public List<ScanResult> getScanResults() {
|
|||
|
try {
|
|||
|
ParceledListSlice<ScanResult> parceledList = mService
|
|||
|
.getScanResults(mContext.getOpPackageName(), mContext.getAttributionTag());
|
|||
|
if (parceledList == null) {
|
|||
|
return Collections.emptyList();
|
|||
|
}
|
|||
|
return parceledList.getList();
|
|||
|
} 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();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Get channel data such as the number of APs found on each channel from the most recent scan.
|
|||
|
* App requires {@link android.Manifest.permission#NEARBY_WIFI_DEVICES}
|
|||
|
*
|
|||
|
* @param executor The executor on which callback will be invoked.
|
|||
|
* @param resultsCallback A callback that will return {@code List<Bundle>} containing channel
|
|||
|
* data such as the number of APs found on each channel.
|
|||
|
* {@link WifiManager#CHANNEL_DATA_KEY_FREQUENCY_MHZ} and
|
|||
|
* {@link WifiManager#CHANNEL_DATA_KEY_NUM_AP} are used to get
|
|||
|
* the frequency (Mhz) and number of APs.
|
|||
|
* @throws UnsupportedOperationException if the API is not supported on this SDK version.
|
|||
|
* @throws SecurityException if the caller does not have permission.
|
|||
|
* @throws NullPointerException if the caller provided invalid inputs.
|
|||
|
*/
|
|||
|
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
|
|||
|
@RequiresPermission(NEARBY_WIFI_DEVICES)
|
|||
|
public void getChannelData(@NonNull @CallbackExecutor Executor executor,
|
|||
|
@NonNull Consumer<List<Bundle>> resultsCallback) {
|
|||
|
Objects.requireNonNull(executor, "executor cannot be null");
|
|||
|
Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null");
|
|||
|
try {
|
|||
|
Bundle extras = new Bundle();
|
|||
|
extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE,
|
|||
|
mContext.getAttributionSource());
|
|||
|
mService.getChannelData(new IListListener.Stub() {
|
|||
|
@Override
|
|||
|
public void onResult(List value) {
|
|||
|
Binder.clearCallingIdentity();
|
|||
|
executor.execute(() -> {
|
|||
|
resultsCallback.accept(value);
|
|||
|
});
|
|||
|
}
|
|||
|
}, mContext.getOpPackageName(), extras);
|
|||
|
} 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;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Helper class to support driver country code changed listener.
|
|||
|
*/
|
|||
|
private static class OnDriverCountryCodeChangedProxy
|
|||
|
extends IOnWifiDriverCountryCodeChangedListener.Stub {
|
|||
|
|
|||
|
@NonNull private Executor mExecutor;
|
|||
|
@NonNull private ActiveCountryCodeChangedCallback mCallback;
|
|||
|
|
|||
|
OnDriverCountryCodeChangedProxy(@NonNull Executor executor,
|
|||
|
@NonNull ActiveCountryCodeChangedCallback callback) {
|
|||
|
Objects.requireNonNull(executor);
|
|||
|
Objects.requireNonNull(callback);
|
|||
|
mExecutor = executor;
|
|||
|
mCallback = callback;
|
|||
|
}
|
|||
|
|
|||
|
@Override
|
|||
|
public void onDriverCountryCodeChanged(String countryCode) {
|
|||
|
Log.i(TAG, "OnDriverCountryCodeChangedProxy: receive onDriverCountryCodeChanged: "
|
|||
|
+ countryCode);
|
|||
|
Binder.clearCallingIdentity();
|
|||
|
if (countryCode != null) {
|
|||
|
mExecutor.execute(() -> mCallback.onActiveCountryCodeChanged(countryCode));
|
|||
|
} else {
|
|||
|
mExecutor.execute(() -> mCallback.onCountryCodeInactive());
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Interface used to listen the active country code changed event.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
public interface ActiveCountryCodeChangedCallback {
|
|||
|
/**
|
|||
|
* Called when the country code used by the Wi-Fi subsystem has changed.
|
|||
|
*
|
|||
|
* @param countryCode An ISO-3166-alpha2 country code which is 2-Character alphanumeric.
|
|||
|
*/
|
|||
|
void onActiveCountryCodeChanged(@NonNull String countryCode);
|
|||
|
|
|||
|
/**
|
|||
|
* Called when the Wi-Fi subsystem does not have an active country code.
|
|||
|
* This can happen when Wi-Fi is disabled.
|
|||
|
*/
|
|||
|
void onCountryCodeInactive();
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Add the provided callback for the active country code changed event.
|
|||
|
* Caller will receive either
|
|||
|
* {@link WifiManager.ActiveCountryCodeChangedCallback#onActiveCountryCodeChanged(String)}
|
|||
|
* or {@link WifiManager.ActiveCountryCodeChangedCallback#onCountryCodeInactive()}
|
|||
|
* on registration.
|
|||
|
*
|
|||
|
* Note: When the global location setting is off or the caller does not have runtime location
|
|||
|
* permission, caller will not receive the callback even if caller register callback succeeded.
|
|||
|
*
|
|||
|
*
|
|||
|
* Caller can remove a previously registered callback using
|
|||
|
* {@link WifiManager#unregisterActiveCountryCodeChangedCallback(
|
|||
|
* ActiveCountryCodeChangedCallback)}.
|
|||
|
*
|
|||
|
* <p>
|
|||
|
* Note:
|
|||
|
* The value provided by
|
|||
|
* {@link WifiManager.ActiveCountryCodeChangedCallback#onActiveCountryCodeChanged(String)}
|
|||
|
* may be different from the returned value from {@link WifiManager#getCountryCode()} even if
|
|||
|
* the Wi-Fi subsystem is active. See: {@link WifiManager#getCountryCode()} for details.
|
|||
|
* </p>
|
|||
|
*
|
|||
|
* @param executor The Executor on which to execute the callbacks.
|
|||
|
* @param callback callback for the driver country code changed events.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
|
|||
|
@RequiresPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION)
|
|||
|
public void registerActiveCountryCodeChangedCallback(
|
|||
|
@NonNull @CallbackExecutor Executor executor,
|
|||
|
@NonNull ActiveCountryCodeChangedCallback callback) {
|
|||
|
if (!SdkLevel.isAtLeastT()) {
|
|||
|
throw new UnsupportedOperationException();
|
|||
|
}
|
|||
|
if (executor == null) throw new IllegalArgumentException("executor cannot be null");
|
|||
|
if (callback == null) throw new IllegalArgumentException("callback cannot be null");
|
|||
|
if (mVerboseLoggingEnabled) {
|
|||
|
Log.d(TAG, "registerActiveCountryCodeChangedCallback: callback=" + callback
|
|||
|
+ ", executor=" + executor);
|
|||
|
}
|
|||
|
final int callbackIdentifier = System.identityHashCode(callback);
|
|||
|
synchronized (sActiveCountryCodeChangedCallbackMap) {
|
|||
|
try {
|
|||
|
IOnWifiDriverCountryCodeChangedListener.Stub binderListener =
|
|||
|
new OnDriverCountryCodeChangedProxy(executor, callback);
|
|||
|
sActiveCountryCodeChangedCallbackMap.put(callbackIdentifier,
|
|||
|
binderListener);
|
|||
|
mService.registerDriverCountryCodeChangedListener(binderListener,
|
|||
|
mContext.getOpPackageName(), mContext.getAttributionTag());
|
|||
|
} catch (RemoteException e) {
|
|||
|
sActiveCountryCodeChangedCallbackMap.remove(callbackIdentifier);
|
|||
|
throw e.rethrowFromSystemServer();
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Allow callers to remove a previously registered listener. After calling this method,
|
|||
|
* applications will no longer receive the active country code changed events through that
|
|||
|
* callback.
|
|||
|
*
|
|||
|
* @param callback Callback to remove the active country code changed events.
|
|||
|
*
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
|
|||
|
@SystemApi
|
|||
|
public void unregisterActiveCountryCodeChangedCallback(
|
|||
|
@NonNull ActiveCountryCodeChangedCallback callback) {
|
|||
|
if (!SdkLevel.isAtLeastT()) {
|
|||
|
throw new UnsupportedOperationException();
|
|||
|
}
|
|||
|
if (callback == null) throw new IllegalArgumentException("Callback cannot be null");
|
|||
|
if (mVerboseLoggingEnabled) {
|
|||
|
Log.d(TAG, "unregisterActiveCountryCodeChangedCallback: callback=" + callback);
|
|||
|
}
|
|||
|
final int callbackIdentifier = System.identityHashCode(callback);
|
|||
|
synchronized (sActiveCountryCodeChangedCallbackMap) {
|
|||
|
try {
|
|||
|
if (!sActiveCountryCodeChangedCallbackMap.contains(callbackIdentifier)) {
|
|||
|
Log.w(TAG, "Unknown external listener " + callbackIdentifier);
|
|||
|
return;
|
|||
|
}
|
|||
|
mService.unregisterDriverCountryCodeChangedListener(
|
|||
|
sActiveCountryCodeChangedCallbackMap.get(callbackIdentifier));
|
|||
|
} catch (RemoteException e) {
|
|||
|
throw e.rethrowFromSystemServer();
|
|||
|
} finally {
|
|||
|
sActiveCountryCodeChangedCallbackMap.remove(callbackIdentifier);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Interface used to listen to changes in current network state.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
public interface WifiNetworkStateChangedListener {
|
|||
|
/** @hide */
|
|||
|
@Retention(RetentionPolicy.SOURCE)
|
|||
|
@IntDef(prefix = {"WIFI_ROLE_CLIENT_"}, value = {
|
|||
|
WIFI_ROLE_CLIENT_PRIMARY,
|
|||
|
WIFI_ROLE_CLIENT_SECONDARY_INTERNET,
|
|||
|
WIFI_ROLE_CLIENT_SECONDARY_LOCAL_ONLY
|
|||
|
})
|
|||
|
@interface WifiClientModeRole {}
|
|||
|
|
|||
|
/**
|
|||
|
* A client mode role returned by {@link #onWifiNetworkStateChanged(int, int)}.
|
|||
|
* Represents the primary Client Mode Manager which is mostly used for internet, but could
|
|||
|
* also be used for other use-cases such as local only connections.
|
|||
|
**/
|
|||
|
int WIFI_ROLE_CLIENT_PRIMARY = 1;
|
|||
|
/**
|
|||
|
* A client mode role returned by {@link #onWifiNetworkStateChanged(int, int)}.
|
|||
|
* Represents a Client Mode Manager dedicated for the secondary internet use-case.
|
|||
|
**/
|
|||
|
int WIFI_ROLE_CLIENT_SECONDARY_INTERNET = 2;
|
|||
|
/**
|
|||
|
* A client mode role returned by {@link #onWifiNetworkStateChanged(int, int)}.
|
|||
|
* Represents a Client Mode Manager dedicated for the local only connection use-case.
|
|||
|
**/
|
|||
|
int WIFI_ROLE_CLIENT_SECONDARY_LOCAL_ONLY = 3;
|
|||
|
|
|||
|
/** @hide */
|
|||
|
@Retention(RetentionPolicy.SOURCE)
|
|||
|
@IntDef(prefix = {"WIFI_NETWORK_STATUS_"}, value = {
|
|||
|
WIFI_NETWORK_STATUS_IDLE,
|
|||
|
WIFI_NETWORK_STATUS_SCANNING,
|
|||
|
WIFI_NETWORK_STATUS_CONNECTING,
|
|||
|
WIFI_NETWORK_STATUS_AUTHENTICATING,
|
|||
|
WIFI_NETWORK_STATUS_OBTAINING_IPADDR,
|
|||
|
WIFI_NETWORK_STATUS_CONNECTED,
|
|||
|
WIFI_NETWORK_STATUS_DISCONNECTED,
|
|||
|
WIFI_NETWORK_STATUS_FAILED
|
|||
|
})
|
|||
|
@interface WifiNetworkState {}
|
|||
|
|
|||
|
/**
|
|||
|
* A state returned by {@link #onWifiNetworkStateChanged(int, int)}.
|
|||
|
* Supplicant is in uninitialized state.
|
|||
|
**/
|
|||
|
int WIFI_NETWORK_STATUS_IDLE = 1;
|
|||
|
/**
|
|||
|
* A state returned by {@link #onWifiNetworkStateChanged(int, int)}.
|
|||
|
* Supplicant is scanning.
|
|||
|
**/
|
|||
|
int WIFI_NETWORK_STATUS_SCANNING = 2;
|
|||
|
/**
|
|||
|
* A state returned by {@link #onWifiNetworkStateChanged(int, int)}.
|
|||
|
* L2 connection is in progress.
|
|||
|
**/
|
|||
|
int WIFI_NETWORK_STATUS_CONNECTING = 3;
|
|||
|
/**
|
|||
|
* A state returned by {@link #onWifiNetworkStateChanged(int, int)}.
|
|||
|
* L2 connection 4 way handshake.
|
|||
|
**/
|
|||
|
int WIFI_NETWORK_STATUS_AUTHENTICATING = 4;
|
|||
|
/**
|
|||
|
* A state returned by {@link #onWifiNetworkStateChanged(int, int)}.
|
|||
|
* L2 connection complete. Obtaining IP address.
|
|||
|
**/
|
|||
|
int WIFI_NETWORK_STATUS_OBTAINING_IPADDR = 5;
|
|||
|
/**
|
|||
|
* A state returned by {@link #onWifiNetworkStateChanged(int, int)}.
|
|||
|
* L3 connection is complete.
|
|||
|
**/
|
|||
|
int WIFI_NETWORK_STATUS_CONNECTED = 6;
|
|||
|
/**
|
|||
|
* A state returned by {@link #onWifiNetworkStateChanged(int, int)}.
|
|||
|
* Network disconnected.
|
|||
|
**/
|
|||
|
int WIFI_NETWORK_STATUS_DISCONNECTED = 7;
|
|||
|
/**
|
|||
|
* A state returned by {@link #onWifiNetworkStateChanged(int, int)}.
|
|||
|
* A pseudo-state that should normally never be seen.
|
|||
|
**/
|
|||
|
int WIFI_NETWORK_STATUS_FAILED = 8;
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* Provides network state changes per client mode role.
|
|||
|
* @param cmmRole the role of the wifi client mode manager having the state change.
|
|||
|
* One of {@link WifiClientModeRole}.
|
|||
|
* @param state the wifi network state specified by one of {@link WifiNetworkState}.
|
|||
|
*/
|
|||
|
void onWifiNetworkStateChanged(@WifiClientModeRole int cmmRole,
|
|||
|
@WifiNetworkState int state);
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Helper class to support wifi network state changed listener.
|
|||
|
*/
|
|||
|
private static class OnWifiNetworkStateChangedProxy
|
|||
|
extends IWifiNetworkStateChangedListener.Stub {
|
|||
|
|
|||
|
@NonNull private Executor mExecutor;
|
|||
|
@NonNull private WifiNetworkStateChangedListener mListener;
|
|||
|
|
|||
|
OnWifiNetworkStateChangedProxy(@NonNull Executor executor,
|
|||
|
@NonNull WifiNetworkStateChangedListener listener) {
|
|||
|
Objects.requireNonNull(executor);
|
|||
|
Objects.requireNonNull(listener);
|
|||
|
mExecutor = executor;
|
|||
|
mListener = listener;
|
|||
|
}
|
|||
|
|
|||
|
@Override
|
|||
|
public void onWifiNetworkStateChanged(int cmmRole, int state) {
|
|||
|
Log.i(TAG, "OnWifiNetworkStateChangedProxy: onWifiNetworkStateChanged: "
|
|||
|
+ cmmRole + ", " + state);
|
|||
|
Binder.clearCallingIdentity();
|
|||
|
mExecutor.execute(() -> mListener.onWifiNetworkStateChanged(cmmRole, state));
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Add a listener to listen to Wi-Fi network state changes on available client mode roles
|
|||
|
* specified in {@link WifiNetworkStateChangedListener.WifiClientModeRole}.
|
|||
|
* When wifi state changes such as connected/disconnect happens, results will be delivered via
|
|||
|
* {@link WifiNetworkStateChangedListener#onWifiNetworkStateChanged(int, int)}.
|
|||
|
*
|
|||
|
* @param executor The Executor on which to execute the callbacks.
|
|||
|
* @param listener listener for the network status updates.
|
|||
|
* @throws SecurityException if the caller is missing required permissions.
|
|||
|
* @throws IllegalArgumentException if incorrect input arguments are provided.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
@RequiresPermission(Manifest.permission.NETWORK_SETTINGS)
|
|||
|
public void addWifiNetworkStateChangedListener(@NonNull @CallbackExecutor Executor executor,
|
|||
|
@NonNull WifiNetworkStateChangedListener listener) {
|
|||
|
if (executor == null) throw new IllegalArgumentException("executor cannot be null");
|
|||
|
if (listener == null) throw new IllegalArgumentException("listener cannot be null");
|
|||
|
if (mVerboseLoggingEnabled) {
|
|||
|
Log.d(TAG, "addWifiNetworkStateChangedListener: listener=" + listener
|
|||
|
+ ", executor=" + executor);
|
|||
|
}
|
|||
|
final int listenerIdentifier = System.identityHashCode(listener);
|
|||
|
synchronized (sOnWifiNetworkStateChangedListenerMap) {
|
|||
|
try {
|
|||
|
IWifiNetworkStateChangedListener.Stub listenerProxy =
|
|||
|
new OnWifiNetworkStateChangedProxy(executor, listener);
|
|||
|
sOnWifiNetworkStateChangedListenerMap.put(listenerIdentifier,
|
|||
|
listenerProxy);
|
|||
|
mService.addWifiNetworkStateChangedListener(listenerProxy);
|
|||
|
} catch (RemoteException e) {
|
|||
|
sOnWifiNetworkStateChangedListenerMap.remove(listenerIdentifier);
|
|||
|
throw e.rethrowFromSystemServer();
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Remove a listener added using
|
|||
|
* {@link #addWifiNetworkStateChangedListener(Executor, WifiNetworkStateChangedListener)}.
|
|||
|
* @param listener the listener to be removed.
|
|||
|
* @throws IllegalArgumentException if incorrect input arguments are provided.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
|
|||
|
public void removeWifiNetworkStateChangedListener(
|
|||
|
@NonNull WifiNetworkStateChangedListener listener) {
|
|||
|
if (listener == null) throw new IllegalArgumentException("listener cannot be null");
|
|||
|
if (mVerboseLoggingEnabled) {
|
|||
|
Log.d(TAG, "removeWifiNetworkStateChangedListener: listener=" + listener);
|
|||
|
}
|
|||
|
final int listenerIdentifier = System.identityHashCode(listener);
|
|||
|
synchronized (sOnWifiNetworkStateChangedListenerMap) {
|
|||
|
try {
|
|||
|
if (!sOnWifiNetworkStateChangedListenerMap.contains(listenerIdentifier)) {
|
|||
|
Log.w(TAG, "Unknown external listener " + listenerIdentifier);
|
|||
|
return;
|
|||
|
}
|
|||
|
mService.removeWifiNetworkStateChangedListener(
|
|||
|
sOnWifiNetworkStateChangedListenerMap.get(listenerIdentifier));
|
|||
|
} catch (RemoteException e) {
|
|||
|
throw e.rethrowFromSystemServer();
|
|||
|
} finally {
|
|||
|
sOnWifiNetworkStateChangedListenerMap.remove(listenerIdentifier);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 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. Country code supplied by the wifi driver module. (802.11d)
|
|||
|
* 4. Default country code set either via {@code ro.boot.wificountrycode}
|
|||
|
* or the {@link WifiManager#setDefaultCountryCode(String)}.
|
|||
|
*
|
|||
|
* <p>
|
|||
|
* Note:
|
|||
|
* This method returns the Country Code value used by the framework - even if not currently
|
|||
|
* used by the Wi-Fi subsystem. I.e. the returned value from this API may be different from the
|
|||
|
* value provided by
|
|||
|
* {@link WifiManager.ActiveCountryCodeChangedCallback#onActiveCountryCodeChanged(String)}.
|
|||
|
* Such a difference may happen when there is an ongoing network connection (STA, AP, Direct,
|
|||
|
* or Aware) and the Wi-Fi subsystem does not support dynamic updates - at that point the
|
|||
|
* framework may defer setting the Country Code to the Wi-Fi subsystem.
|
|||
|
* </p>
|
|||
|
* @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(anyOf = {
|
|||
|
android.Manifest.permission.NETWORK_SETTINGS,
|
|||
|
android.Manifest.permission.ACCESS_COARSE_LOCATION
|
|||
|
})
|
|||
|
public String getCountryCode() {
|
|||
|
try {
|
|||
|
return mService.getCountryCode(mContext.getOpPackageName(),
|
|||
|
mContext.getAttributionTag());
|
|||
|
} 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 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>
|
|||
|
*
|
|||
|
* Starting with {@link android.os.Build.VERSION_CODES#TIRAMISU}, DO/COPE may set
|
|||
|
* a user restriction (DISALLOW_CHANGE_WIFI_STATE) to only allow DO/PO to use this API.
|
|||
|
*/
|
|||
|
@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.
|
|||
|
*
|
|||
|
* Note: Call {@link WifiManager#validateSoftApConfiguration(SoftApConfiguration)} to avoid
|
|||
|
* unexpected error due to invalid configuration.
|
|||
|
*
|
|||
|
* @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 WifiManager#setSoftApConfiguration(SoftApConfiguration)}.
|
|||
|
* @return {@code true} if the operation succeeded, {@code false} otherwise
|
|||
|
*
|
|||
|
* @deprecated Use {@link #startTetheredHotspot(TetheringManager.TetheringRequest)}
|
|||
|
* instead.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
@RequiresPermission(anyOf = {
|
|||
|
android.Manifest.permission.NETWORK_STACK,
|
|||
|
NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK
|
|||
|
})
|
|||
|
@Deprecated
|
|||
|
public boolean startTetheredHotspot(@Nullable SoftApConfiguration softApConfig) {
|
|||
|
try {
|
|||
|
return mService.startTetheredHotspot(softApConfig, mContext.getOpPackageName());
|
|||
|
} catch (RemoteException e) {
|
|||
|
throw e.rethrowFromSystemServer();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Start Soft AP (hotspot) mode for tethering purposes with the specified TetheringRequest.
|
|||
|
* Note that starting Soft AP mode may disable station mode operation if the device does not
|
|||
|
* support concurrency.
|
|||
|
*
|
|||
|
* @param request A valid TetheringRequest specifying the configuration of the SAP.
|
|||
|
* @param executor Executor to run the callback on.
|
|||
|
* @param callback Callback to listen on state changes for this specific request.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|||
|
@SystemApi
|
|||
|
@RequiresPermission(anyOf = {
|
|||
|
android.Manifest.permission.NETWORK_STACK,
|
|||
|
NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK
|
|||
|
})
|
|||
|
public void startTetheredHotspot(@NonNull TetheringManager.TetheringRequest request,
|
|||
|
@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");
|
|||
|
ISoftApCallback.Stub binderCallback = new SoftApCallbackProxy(executor, callback,
|
|||
|
IFACE_IP_MODE_TETHERED);
|
|||
|
try {
|
|||
|
mService.startTetheredHotspotRequest(request, binderCallback,
|
|||
|
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();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Check if input configuration is valid.
|
|||
|
*
|
|||
|
* @param config a configuration would like to be checked.
|
|||
|
* @return true if config is valid, otherwise false.
|
|||
|
*/
|
|||
|
public boolean validateSoftApConfiguration(@NonNull SoftApConfiguration config) {
|
|||
|
if (config == null) {
|
|||
|
throw new IllegalArgumentException(TAG + ": config can not be null");
|
|||
|
}
|
|||
|
try {
|
|||
|
return mService.validateSoftApConfiguration(config);
|
|||
|
} 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 may 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 targeting {@link android.os.Build.VERSION_CODES#TIRAMISU} or later need to have
|
|||
|
* the following permissions: {@link android.Manifest.permission#CHANGE_WIFI_STATE} and
|
|||
|
* {@link android.Manifest.permission#NEARBY_WIFI_DEVICES}.
|
|||
|
* Applications targeting {@link Build.VERSION_CODES#S} or prior SDK levels need to have the
|
|||
|
* following permissions: {@link android.Manifest.permission#CHANGE_WIFI_STATE} and
|
|||
|
* {@link android.Manifest.permission#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 = {CHANGE_WIFI_STATE, ACCESS_FINE_LOCATION, NEARBY_WIFI_DEVICES},
|
|||
|
conditional = true)
|
|||
|
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},
|
|||
|
* {@link android.Manifest.permission#NETWORK_SETTINGS} or
|
|||
|
* {@link android.Manifest.permission#NEARBY_WIFI_DEVICES} 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,
|
|||
|
NEARBY_WIFI_DEVICES})
|
|||
|
public void startLocalOnlyHotspot(@NonNull SoftApConfiguration config,
|
|||
|
@Nullable @CallbackExecutor 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 @CallbackExecutor 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();
|
|||
|
Bundle extras = new Bundle();
|
|||
|
if (SdkLevel.isAtLeastS()) {
|
|||
|
extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE,
|
|||
|
mContext.getAttributionSource());
|
|||
|
}
|
|||
|
int returnCode = mService.startLocalOnlyHotspot(proxy, packageName, featureId,
|
|||
|
config, extras);
|
|||
|
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();
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Registers a callback for local only hotspot. 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(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 #unregisterLocalOnlyHotspotSoftApCallback}
|
|||
|
* <p>
|
|||
|
*
|
|||
|
* @param executor The Executor on whose thread to execute the callbacks of the {@code callback}
|
|||
|
* object.
|
|||
|
* @param callback Callback for local only hotspot events
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
|
|||
|
@RequiresPermission(NEARBY_WIFI_DEVICES)
|
|||
|
public void registerLocalOnlyHotspotSoftApCallback(@NonNull @CallbackExecutor Executor executor,
|
|||
|
@NonNull SoftApCallback callback) {
|
|||
|
if (!SdkLevel.isAtLeastT()) {
|
|||
|
throw new UnsupportedOperationException();
|
|||
|
}
|
|||
|
if (executor == null) throw new IllegalArgumentException("executor cannot be null");
|
|||
|
if (callback == null) throw new IllegalArgumentException("callback cannot be null");
|
|||
|
Log.v(TAG, "registerLocalOnlyHotspotSoftApCallback: callback=" + callback + ", executor="
|
|||
|
+ executor);
|
|||
|
try {
|
|||
|
synchronized (sLocalOnlyHotspotSoftApCallbackMap) {
|
|||
|
ISoftApCallback.Stub binderCallback = new SoftApCallbackProxy(executor, callback,
|
|||
|
IFACE_IP_MODE_LOCAL_ONLY);
|
|||
|
sLocalOnlyHotspotSoftApCallbackMap.put(System.identityHashCode(callback),
|
|||
|
binderCallback);
|
|||
|
Bundle extras = new Bundle();
|
|||
|
extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE,
|
|||
|
mContext.getAttributionSource());
|
|||
|
mService.registerLocalOnlyHotspotSoftApCallback(binderCallback, extras);
|
|||
|
}
|
|||
|
} catch (RemoteException e) {
|
|||
|
throw e.rethrowFromSystemServer();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Allow callers to unregister a previously registered callback. After calling this method,
|
|||
|
* applications will no longer receive local only hotspot events.
|
|||
|
*
|
|||
|
* <p>
|
|||
|
*
|
|||
|
* @param callback Callback to unregister for soft AP events
|
|||
|
*
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
|
|||
|
@RequiresPermission(NEARBY_WIFI_DEVICES)
|
|||
|
public void unregisterLocalOnlyHotspotSoftApCallback(@NonNull SoftApCallback callback) {
|
|||
|
if (!SdkLevel.isAtLeastT()) {
|
|||
|
throw new UnsupportedOperationException();
|
|||
|
}
|
|||
|
if (callback == null) throw new IllegalArgumentException("callback cannot be null");
|
|||
|
Log.v(TAG, "unregisterLocalOnlyHotspotSoftApCallback: callback=" + callback);
|
|||
|
|
|||
|
try {
|
|||
|
synchronized (sLocalOnlyHotspotSoftApCallbackMap) {
|
|||
|
int callbackIdentifier = System.identityHashCode(callback);
|
|||
|
if (!sLocalOnlyHotspotSoftApCallbackMap.contains(callbackIdentifier)) {
|
|||
|
Log.w(TAG, "Unknown external callback " + callbackIdentifier);
|
|||
|
return;
|
|||
|
}
|
|||
|
Bundle extras = new Bundle();
|
|||
|
extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE,
|
|||
|
mContext.getAttributionSource());
|
|||
|
mService.unregisterLocalOnlyHotspotSoftApCallback(
|
|||
|
sLocalOnlyHotspotSoftApCallbackMap.get(callbackIdentifier), extras);
|
|||
|
sLocalOnlyHotspotSoftApCallbackMap.remove(callbackIdentifier);
|
|||
|
}
|
|||
|
} 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();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Gets the last configured Wi-Fi tethered AP passphrase.
|
|||
|
*
|
|||
|
* Note: It may be null when there is no passphrase changed since
|
|||
|
* device boot.
|
|||
|
*
|
|||
|
* @param executor The executor on which callback will be invoked.
|
|||
|
* @param resultCallback An asynchronous callback that will return the last configured
|
|||
|
* Wi-Fi tethered AP passphrase.
|
|||
|
*
|
|||
|
* @throws SecurityException if the caller does not have permission.
|
|||
|
* @throws NullPointerException if the caller provided invalid inputs.
|
|||
|
*
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@Nullable
|
|||
|
@SystemApi
|
|||
|
@RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
|
|||
|
public void queryLastConfiguredTetheredApPassphraseSinceBoot(
|
|||
|
@NonNull @CallbackExecutor Executor executor,
|
|||
|
@NonNull Consumer<String> resultCallback) {
|
|||
|
Objects.requireNonNull(executor, "executor cannot be null");
|
|||
|
Objects.requireNonNull(resultCallback, "resultsCallback cannot be null");
|
|||
|
try {
|
|||
|
mService.queryLastConfiguredTetheredApPassphraseSinceBoot(
|
|||
|
new IStringListener.Stub() {
|
|||
|
@Override
|
|||
|
public void onResult(String value) {
|
|||
|
Binder.clearCallingIdentity();
|
|||
|
executor.execute(() -> {
|
|||
|
resultCallback.accept(value);
|
|||
|
});
|
|||
|
}
|
|||
|
});
|
|||
|
} 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(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).
|
|||
|
*
|
|||
|
* Note: Call {@link WifiManager#validateSoftApConfiguration(SoftApConfiguration)} to avoid
|
|||
|
* unexpected error due to invalid configuration.
|
|||
|
*
|
|||
|
* @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();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Enable/Disable TDLS on a specific local route.
|
|||
|
*
|
|||
|
* Similar to {@link #setTdlsEnabled(InetAddress, boolean)}, except
|
|||
|
* this version sends the result of the Enable/Disable request.
|
|||
|
*
|
|||
|
* @param remoteIPAddress IP address of the endpoint to setup TDLS with
|
|||
|
* @param enable true = setup and false = tear down TDLS
|
|||
|
* @param executor The executor on which callback will be invoked.
|
|||
|
* @param resultsCallback An asynchronous callback that will return {@code Boolean} indicating
|
|||
|
* whether TDLS was successfully enabled or disabled.
|
|||
|
* {@code true} for success, {@code false} for failure.
|
|||
|
*
|
|||
|
* @throws NullPointerException if the caller provided invalid inputs.
|
|||
|
*/
|
|||
|
public void setTdlsEnabled(@NonNull InetAddress remoteIPAddress, boolean enable,
|
|||
|
@NonNull @CallbackExecutor Executor executor,
|
|||
|
@NonNull Consumer<Boolean> resultsCallback) {
|
|||
|
Objects.requireNonNull(executor, "executor cannot be null");
|
|||
|
Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null");
|
|||
|
Objects.requireNonNull(remoteIPAddress, "remote IP address cannot be null");
|
|||
|
try {
|
|||
|
mService.enableTdlsWithRemoteIpAddress(remoteIPAddress.getHostAddress(), enable,
|
|||
|
new IBooleanListener.Stub() {
|
|||
|
@Override
|
|||
|
public void onResult(boolean value) {
|
|||
|
Binder.clearCallingIdentity();
|
|||
|
executor.execute(() -> {
|
|||
|
resultsCallback.accept(value);
|
|||
|
});
|
|||
|
}
|
|||
|
});
|
|||
|
} 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();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Enable/Disable TDLS with a specific peer Mac Address.
|
|||
|
*
|
|||
|
* Similar to {@link #setTdlsEnabledWithMacAddress(String, boolean)}, except
|
|||
|
* this version sends the result of the Enable/Disable request.
|
|||
|
*
|
|||
|
* @param remoteMacAddress Mac address of the endpoint to setup TDLS with
|
|||
|
* @param enable true = setup and false = tear down TDLS
|
|||
|
* @param executor The executor on which callback will be invoked.
|
|||
|
* @param resultsCallback An asynchronous callback that will return {@code Boolean} indicating
|
|||
|
* whether TDLS was successfully enabled or disabled.
|
|||
|
* {@code true} for success, {@code false} for failure.
|
|||
|
*
|
|||
|
* @throws NullPointerException if the caller provided invalid inputs.
|
|||
|
*/
|
|||
|
public void setTdlsEnabledWithMacAddress(@NonNull String remoteMacAddress, boolean enable,
|
|||
|
@NonNull @CallbackExecutor Executor executor,
|
|||
|
@NonNull Consumer<Boolean> resultsCallback) {
|
|||
|
Objects.requireNonNull(executor, "executor cannot be null");
|
|||
|
Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null");
|
|||
|
Objects.requireNonNull(remoteMacAddress, "remote Mac address cannot be null");
|
|||
|
try {
|
|||
|
mService.enableTdlsWithRemoteMacAddress(remoteMacAddress, enable,
|
|||
|
new IBooleanListener.Stub() {
|
|||
|
@Override
|
|||
|
public void onResult(boolean value) {
|
|||
|
Binder.clearCallingIdentity();
|
|||
|
executor.execute(() -> {
|
|||
|
resultsCallback.accept(value);
|
|||
|
});
|
|||
|
}
|
|||
|
});
|
|||
|
} catch (RemoteException e) {
|
|||
|
throw e.rethrowFromSystemServer();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Check if a TDLS session can be established at this time via
|
|||
|
* {@link #setTdlsEnabled(InetAddress, boolean)} or
|
|||
|
* {@link #setTdlsEnabledWithMacAddress(String, boolean)} or
|
|||
|
* {@link #setTdlsEnabled(InetAddress, boolean, Executor, Consumer)} or
|
|||
|
* {@link #setTdlsEnabledWithMacAddress(String, boolean, Executor, Consumer)}
|
|||
|
*
|
|||
|
* Internally framework checks the STA connected state, device support for TDLS and
|
|||
|
* the number of TDLS sessions available in driver/firmware.
|
|||
|
*
|
|||
|
* @param executor The executor on which callback will be invoked.
|
|||
|
* @param resultsCallback An asynchronous callback that will return {@code Boolean} indicating
|
|||
|
* whether a TDLS session can be established at this time.
|
|||
|
* {@code true} for available, {@code false} for not available.
|
|||
|
*
|
|||
|
* @throws NullPointerException if the caller provided invalid inputs.
|
|||
|
*/
|
|||
|
public void isTdlsOperationCurrentlyAvailable(@NonNull @CallbackExecutor Executor executor,
|
|||
|
@NonNull Consumer<Boolean> resultsCallback) {
|
|||
|
Objects.requireNonNull(executor, "executor cannot be null");
|
|||
|
Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null");
|
|||
|
try {
|
|||
|
mService.isTdlsOperationCurrentlyAvailable(
|
|||
|
new IBooleanListener.Stub() {
|
|||
|
@Override
|
|||
|
public void onResult(boolean value) {
|
|||
|
Binder.clearCallingIdentity();
|
|||
|
executor.execute(() -> {
|
|||
|
resultsCallback.accept(value);
|
|||
|
});
|
|||
|
}
|
|||
|
});
|
|||
|
} catch (RemoteException e) {
|
|||
|
throw e.rethrowFromSystemServer();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Return the maximum number of concurrent TDLS sessions supported by the device.
|
|||
|
*
|
|||
|
* @param executor The executor on which callback will be invoked.
|
|||
|
* @param resultsCallback An asynchronous callback that will return the maximum number of
|
|||
|
* concurrent TDLS sessions supported by the device. Returns
|
|||
|
* {@code -1} if information is not available,
|
|||
|
* e.g. if the driver/firmware doesn't provide this information.
|
|||
|
*
|
|||
|
* @throws NullPointerException if the caller provided invalid inputs.
|
|||
|
* @throws UnsupportedOperationException if the feature is not available.
|
|||
|
*/
|
|||
|
@RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
|
|||
|
public void getMaxSupportedConcurrentTdlsSessions(@NonNull @CallbackExecutor Executor executor,
|
|||
|
@NonNull Consumer<Integer> resultsCallback) {
|
|||
|
Objects.requireNonNull(executor, "executor cannot be null");
|
|||
|
Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null");
|
|||
|
try {
|
|||
|
mService.getMaxSupportedConcurrentTdlsSessions(
|
|||
|
new IIntegerListener.Stub() {
|
|||
|
@Override
|
|||
|
public void onResult(int value) {
|
|||
|
Binder.clearCallingIdentity();
|
|||
|
executor.execute(() -> {
|
|||
|
resultsCallback.accept(value);
|
|||
|
});
|
|||
|
}
|
|||
|
});
|
|||
|
} catch (RemoteException e) {
|
|||
|
throw e.rethrowFromSystemServer();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Return the number of currently enabled TDLS sessions.
|
|||
|
*
|
|||
|
* Tracks the number of peers enabled for TDLS session via
|
|||
|
* {@link #setTdlsEnabled(InetAddress, boolean) },
|
|||
|
* {@link #setTdlsEnabledWithMacAddress(String, boolean) },
|
|||
|
* {@link #setTdlsEnabled(InetAddress, boolean, Executor, Consumer) } and
|
|||
|
* {@link #setTdlsEnabledWithMacAddress(String, boolean, Executor, Consumer) }
|
|||
|
*
|
|||
|
* @param executor The executor on which callback will be invoked.
|
|||
|
* @param resultsCallback An asynchronous callback that will return the number of Peer
|
|||
|
* Mac addresses configured in the driver for TDLS session.
|
|||
|
*
|
|||
|
* @throws NullPointerException if the caller provided invalid inputs.
|
|||
|
*/
|
|||
|
public void getNumberOfEnabledTdlsSessions(@NonNull @CallbackExecutor Executor executor,
|
|||
|
@NonNull Consumer<Integer> resultsCallback) {
|
|||
|
Objects.requireNonNull(executor, "executor cannot be null");
|
|||
|
Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null");
|
|||
|
try {
|
|||
|
mService.getNumberOfEnabledTdlsSessions(
|
|||
|
new IIntegerListener.Stub() {
|
|||
|
@Override
|
|||
|
public void onResult(int value) {
|
|||
|
Binder.clearCallingIdentity();
|
|||
|
executor.execute(() -> {
|
|||
|
resultsCallback.accept(value);
|
|||
|
});
|
|||
|
}
|
|||
|
});
|
|||
|
} catch (RemoteException e) {
|
|||
|
throw e.rethrowFromSystemServer();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/** @hide */
|
|||
|
@Retention(RetentionPolicy.SOURCE)
|
|||
|
@IntDef({ActionListener.FAILURE_INTERNAL_ERROR,
|
|||
|
ActionListener.FAILURE_IN_PROGRESS,
|
|||
|
ActionListener.FAILURE_BUSY,
|
|||
|
ActionListener.FAILURE_INVALID_ARGS,
|
|||
|
ActionListener.FAILURE_NOT_AUTHORIZED})
|
|||
|
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;
|
|||
|
|
|||
|
/**
|
|||
|
* Interface for callback invocation on an application action.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
public interface ActionListener {
|
|||
|
/**
|
|||
|
* Passed with {@link #onFailure}.
|
|||
|
* Indicates that the operation failed due to an internal error.
|
|||
|
*/
|
|||
|
int FAILURE_INTERNAL_ERROR = 0;
|
|||
|
|
|||
|
/**
|
|||
|
* Passed with {@link #onFailure}.
|
|||
|
* Indicates that the operation is already in progress.
|
|||
|
*/
|
|||
|
int FAILURE_IN_PROGRESS = 1;
|
|||
|
|
|||
|
/**
|
|||
|
* Passed with {@link #onFailure}.
|
|||
|
* Indicates that the operation failed because the framework is busy and is unable to
|
|||
|
* service the request.
|
|||
|
*/
|
|||
|
int FAILURE_BUSY = 2;
|
|||
|
|
|||
|
/**
|
|||
|
* Passed with {@link #onFailure}.
|
|||
|
* Indicates that the operation failed due to invalid inputs.
|
|||
|
*/
|
|||
|
int FAILURE_INVALID_ARGS = 3;
|
|||
|
|
|||
|
/**
|
|||
|
* Passed with {@link #onFailure}.
|
|||
|
* Indicates that the operation failed due to insufficient user permissions.
|
|||
|
*/
|
|||
|
int FAILURE_NOT_AUTHORIZED = 4;
|
|||
|
|
|||
|
/**
|
|||
|
* 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},
|
|||
|
* {@link #SAP_START_FAILURE_USER_REJECTED}
|
|||
|
*/
|
|||
|
default void onStateChanged(@WifiApState int state, @SapStartFailure int failureReason) {}
|
|||
|
|
|||
|
/**
|
|||
|
* Called when soft AP state changes.
|
|||
|
* <p>
|
|||
|
* This provides the same state and failure reason as {@link #onStateChanged(int, int)}, but
|
|||
|
* also provides extra information such as interface name and TetheringRequest in order to
|
|||
|
* replace usage of the WIFI_AP_STATE_CHANGED_ACTION broadcast. If this method is overridden
|
|||
|
* then {@link #onStateChanged(int, int)} will no longer be called.
|
|||
|
*
|
|||
|
* @param state the new state.
|
|||
|
*/
|
|||
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|||
|
default void onStateChanged(@NonNull SoftApState state) {
|
|||
|
onStateChanged(state.mState, state.mFailureReason);
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 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;
|
|||
|
// Either {@link #IFACE_IP_MODE_TETHERED} or {@link #IFACE_IP_MODE_LOCAL_ONLY}.
|
|||
|
private final int mIpMode;
|
|||
|
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, int mode) {
|
|||
|
mExecutor = executor;
|
|||
|
mCallback = callback;
|
|||
|
mIpMode = mode;
|
|||
|
}
|
|||
|
|
|||
|
@Override
|
|||
|
public void onStateChanged(SoftApState state) {
|
|||
|
if (mVerboseLoggingEnabled) {
|
|||
|
Log.v(TAG, "SoftApCallbackProxy on mode " + mIpMode
|
|||
|
+ ", onStateChanged: " + state);
|
|||
|
}
|
|||
|
|
|||
|
Binder.clearCallingIdentity();
|
|||
|
mExecutor.execute(() -> {
|
|||
|
mCallback.onStateChanged(state);
|
|||
|
});
|
|||
|
}
|
|||
|
|
|||
|
@Override
|
|||
|
public void onConnectedClientsOrInfoChanged(Map<String, SoftApInfo> infos,
|
|||
|
Map<String, List<WifiClient>> clients, boolean isBridged, boolean isRegistration) {
|
|||
|
if (mVerboseLoggingEnabled) {
|
|||
|
Log.v(TAG, "SoftApCallbackProxy on mode " + mIpMode
|
|||
|
+ ", 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();
|
|||
|
List<WifiClient> changedClientList = clients.getOrDefault(
|
|||
|
changedInstance, Collections.emptyList());
|
|||
|
if (!changedInfoList.contains(info)) {
|
|||
|
isInfoChanged = true;
|
|||
|
if (mCurrentClients.getOrDefault(changedInstance,
|
|||
|
Collections.emptyList()).size() > 0) {
|
|||
|
SoftApInfo changedInfo = infos.get(changedInstance);
|
|||
|
if (changedInfo == null || changedInfo.getFrequency() == 0) {
|
|||
|
Log.d(TAG, "SoftApCallbackProxy on mode " + mIpMode
|
|||
|
+ ", info changed on client connected instance(AP disabled)");
|
|||
|
// Send old info with empty client list for shutdown case
|
|||
|
changedInfoClients.put(info, Collections.emptyList());
|
|||
|
} else {
|
|||
|
Log.d(TAG, "SoftApCallbackProxy on mode " + mIpMode
|
|||
|
+ ", info changed on client connected instance");
|
|||
|
changedInfoClients.put(changedInfo, changedClientList);
|
|||
|
}
|
|||
|
}
|
|||
|
} else {
|
|||
|
// info doesn't change, check client list
|
|||
|
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 on mode " + mIpMode
|
|||
|
+ ", 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 on mode " + mIpMode
|
|||
|
+ ", 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 on mode " + mIpMode
|
|||
|
+ ", send InfoChanged, newInfo: " + newInfo);
|
|||
|
mExecutor.execute(() -> {
|
|||
|
mCallback.onInfoChanged(newInfo);
|
|||
|
});
|
|||
|
}
|
|||
|
Log.v(TAG, "SoftApCallbackProxy on mode " + mIpMode
|
|||
|
+ ", send InfoChanged, changedInfoList: " + changedInfoList);
|
|||
|
mExecutor.execute(() -> {
|
|||
|
mCallback.onInfoChanged(changedInfoList);
|
|||
|
});
|
|||
|
}
|
|||
|
|
|||
|
if (isRegistration || !changedInfoClients.isEmpty()
|
|||
|
|| areClientsChangedWithoutInfosChanged) {
|
|||
|
Log.v(TAG, "SoftApCallbackProxy on mode " + mIpMode
|
|||
|
+ ", send onConnectedClientsChanged(clients): "
|
|||
|
+ getConnectedClientList(clients));
|
|||
|
mExecutor.execute(() -> {
|
|||
|
mCallback.onConnectedClientsChanged(getConnectedClientList(clients));
|
|||
|
});
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
@Override
|
|||
|
public void onCapabilityChanged(SoftApCapability capability) {
|
|||
|
if (mVerboseLoggingEnabled) {
|
|||
|
Log.v(TAG, "SoftApCallbackProxy on mode " + mIpMode
|
|||
|
+ ", 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 on mode " + mIpMode
|
|||
|
+ ", 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,
|
|||
|
IFACE_IP_MODE_TETHERED);
|
|||
|
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 @CallbackExecutor 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 {
|
|||
|
Bundle extras = new Bundle();
|
|||
|
if (SdkLevel.isAtLeastS()) {
|
|||
|
extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE,
|
|||
|
mContext.getAttributionSource());
|
|||
|
}
|
|||
|
mService.connect(config, networkId, listenerProxy, mContext.getOpPackageName(), extras);
|
|||
|
} catch (RemoteException e) {
|
|||
|
if (listenerProxy != null) {
|
|||
|
listenerProxy.onFailure(ActionListener.FAILURE_INTERNAL_ERROR);
|
|||
|
}
|
|||
|
} catch (SecurityException e) {
|
|||
|
if (listenerProxy != null) {
|
|||
|
listenerProxy.onFailure(ActionListener.FAILURE_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, mContext.getOpPackageName());
|
|||
|
} catch (RemoteException e) {
|
|||
|
if (listenerProxy != null) {
|
|||
|
listenerProxy.onFailure(ActionListener.FAILURE_INTERNAL_ERROR);
|
|||
|
}
|
|||
|
} catch (SecurityException e) {
|
|||
|
if (listenerProxy != null) {
|
|||
|
listenerProxy.onFailure(ActionListener.FAILURE_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(ActionListener.FAILURE_INTERNAL_ERROR);
|
|||
|
}
|
|||
|
} catch (SecurityException e) {
|
|||
|
if (listenerProxy != null) {
|
|||
|
listenerProxy.onFailure(ActionListener.FAILURE_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(ActionListener.FAILURE_INTERNAL_ERROR);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Control whether the device will automatically search for and connect to Wi-Fi networks -
|
|||
|
* auto-join Wi-Fi networks. Disabling this option will not impact manual connections - i.e.
|
|||
|
* the user will still be able to manually select and connect to a Wi-Fi network. Disabling
|
|||
|
* this option significantly impacts the device connectivity and is a restricted operation
|
|||
|
* (see below for permissions). Note that disabling this operation will also disable
|
|||
|
* connectivity initiated scanning operations.
|
|||
|
* <p>
|
|||
|
* Disabling the auto-join configuration is a temporary operation (with the exception of a
|
|||
|
* DO/PO caller): it will be reset (to enabled) when the device reboots or the user toggles
|
|||
|
* Wi-Fi off/on. When the caller is a DO/PO then toggling Wi-Fi will not reset the
|
|||
|
* configuration. Additionally, if a DO/PO disables auto-join then it cannot be (re)enabled by
|
|||
|
* a non-DO/PO caller.
|
|||
|
*
|
|||
|
* @param allowAutojoin true to allow auto-join, false to disallow auto-join
|
|||
|
*
|
|||
|
* Available for DO/PO apps.
|
|||
|
* Other apps require {@code android.Manifest.permission#NETWORK_SETTINGS} or
|
|||
|
* {@code android.Manifest.permission#MANAGE_WIFI_NETWORK_SELECTION} permission.
|
|||
|
*/
|
|||
|
public void allowAutojoinGlobal(boolean allowAutojoin) {
|
|||
|
try {
|
|||
|
Bundle extras = new Bundle();
|
|||
|
if (SdkLevel.isAtLeastS()) {
|
|||
|
extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE,
|
|||
|
mContext.getAttributionSource());
|
|||
|
}
|
|||
|
mService.allowAutojoinGlobal(allowAutojoin, mContext.getOpPackageName(), extras);
|
|||
|
} catch (RemoteException e) {
|
|||
|
throw e.rethrowFromSystemServer();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Query whether or not auto-join global is enabled/disabled
|
|||
|
* @see #allowAutojoinGlobal(boolean)
|
|||
|
*
|
|||
|
* Available for DO/PO apps.
|
|||
|
* Other apps require {@code android.Manifest.permission#NETWORK_SETTINGS} or
|
|||
|
* {@code android.Manifest.permission#MANAGE_WIFI_NETWORK_SELECTION} permission.
|
|||
|
*
|
|||
|
* @param executor The executor on which callback will be invoked.
|
|||
|
* @param resultsCallback An asynchronous callback that will return {@code Boolean} indicating
|
|||
|
* whether auto-join global is enabled/disabled.
|
|||
|
*
|
|||
|
* @throws SecurityException if the caller does not have permission.
|
|||
|
* @throws NullPointerException if the caller provided invalid inputs.
|
|||
|
*/
|
|||
|
public void queryAutojoinGlobal(@NonNull @CallbackExecutor Executor executor,
|
|||
|
@NonNull Consumer<Boolean> resultsCallback) {
|
|||
|
Objects.requireNonNull(executor, "executor cannot be null");
|
|||
|
Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null");
|
|||
|
try {
|
|||
|
mService.queryAutojoinGlobal(
|
|||
|
new IBooleanListener.Stub() {
|
|||
|
@Override
|
|||
|
public void onResult(boolean value) {
|
|||
|
Binder.clearCallingIdentity();
|
|||
|
executor.execute(() -> {
|
|||
|
resultsCallback.accept(value);
|
|||
|
});
|
|||
|
}
|
|||
|
});
|
|||
|
} 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(ActionListener.FAILURE_INTERNAL_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(ActionListener.FAILURE_INTERNAL_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 {
|
|||
|
Bundle extras = new Bundle();
|
|||
|
if (SdkLevel.isAtLeastS()) {
|
|||
|
extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE,
|
|||
|
mContext.getAttributionSource());
|
|||
|
}
|
|||
|
mService.acquireWifiLock(mBinder, mLockType, mTag, mWorkSource,
|
|||
|
mContext.getOpPackageName(), extras);
|
|||
|
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 {
|
|||
|
Bundle extras = new Bundle();
|
|||
|
if (SdkLevel.isAtLeastS()) {
|
|||
|
extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE,
|
|||
|
mContext.getAttributionSource());
|
|||
|
}
|
|||
|
mService.updateWifiLockWorkSource(mBinder, mWorkSource,
|
|||
|
mContext.getOpPackageName(), extras);
|
|||
|
} 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);
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Interface for low latency lock listener. Should be extended by application and set when
|
|||
|
* calling {@link WifiManager#addWifiLowLatencyLockListener(Executor,
|
|||
|
* WifiLowLatencyLockListener)}.
|
|||
|
*
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|||
|
@SystemApi
|
|||
|
public interface WifiLowLatencyLockListener {
|
|||
|
/**
|
|||
|
* Provides low latency mode is activated or not. Triggered when Wi-Fi chip enters into low
|
|||
|
* latency mode.
|
|||
|
*
|
|||
|
* <p>Note: Always called with current state when a new listener gets registered.
|
|||
|
*/
|
|||
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|||
|
void onActivatedStateChanged(boolean activated);
|
|||
|
|
|||
|
/**
|
|||
|
* Provides UIDs (lock owners) of the applications which currently acquired low latency
|
|||
|
* lock. Triggered when an application acquires or releases a lock.
|
|||
|
*
|
|||
|
* <p>Note: Always called with UIDs of the current acquired locks when a new listener gets
|
|||
|
* registered.
|
|||
|
*
|
|||
|
* @param ownerUids An array of UIDs.
|
|||
|
*/
|
|||
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|||
|
default void onOwnershipChanged(@NonNull int[] ownerUids) {}
|
|||
|
|
|||
|
/**
|
|||
|
* Provides UIDs of the applications which acquired the low latency lock and is currently
|
|||
|
* active. See {@link WifiManager#WIFI_MODE_FULL_LOW_LATENCY} for the conditions to be met
|
|||
|
* for low latency lock to be active. Triggered when application acquiring the lock
|
|||
|
* satisfies or does not satisfy low latency conditions when the low latency mode is
|
|||
|
* activated. Also gets triggered when the lock becomes active, immediately after the {@link
|
|||
|
* WifiLowLatencyLockListener#onActivatedStateChanged(boolean)} callback is triggered.
|
|||
|
*
|
|||
|
* <p>Note: Always called with UIDs of the current active locks when a new listener gets
|
|||
|
* registered if the Wi-Fi chip is in low latency mode.
|
|||
|
*
|
|||
|
* @param activeUids An array of UIDs.
|
|||
|
*/
|
|||
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|||
|
default void onActiveUsersChanged(@NonNull int[] activeUids) {}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Helper class to support wifi low latency lock listener.
|
|||
|
*/
|
|||
|
private static class OnWifiLowLatencyLockProxy extends IWifiLowLatencyLockListener.Stub {
|
|||
|
@NonNull
|
|||
|
private Executor mExecutor;
|
|||
|
@NonNull
|
|||
|
private WifiLowLatencyLockListener mListener;
|
|||
|
|
|||
|
OnWifiLowLatencyLockProxy(@NonNull Executor executor,
|
|||
|
@NonNull WifiLowLatencyLockListener listener) {
|
|||
|
Objects.requireNonNull(executor);
|
|||
|
Objects.requireNonNull(listener);
|
|||
|
mExecutor = executor;
|
|||
|
mListener = listener;
|
|||
|
}
|
|||
|
|
|||
|
@Override
|
|||
|
public void onActivatedStateChanged(boolean activated) {
|
|||
|
Binder.clearCallingIdentity();
|
|||
|
mExecutor.execute(() -> mListener.onActivatedStateChanged(activated));
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
@Override
|
|||
|
public void onOwnershipChanged(@NonNull int[] ownerUids) {
|
|||
|
Binder.clearCallingIdentity();
|
|||
|
mExecutor.execute(() -> mListener.onOwnershipChanged(ownerUids));
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
@Override
|
|||
|
public void onActiveUsersChanged(@NonNull int[] activeUids) {
|
|||
|
Binder.clearCallingIdentity();
|
|||
|
mExecutor.execute(() -> mListener.onActiveUsersChanged(activeUids));
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Add a listener for monitoring the low latency lock. The caller can unregister a previously
|
|||
|
* registered listener using {@link WifiManager#removeWifiLowLatencyLockListener(
|
|||
|
* WifiLowLatencyLockListener)}.
|
|||
|
*
|
|||
|
* <p>Applications should have the {@link android.Manifest.permission#NETWORK_SETTINGS} and
|
|||
|
* {@link android.Manifest.permission#MANAGE_WIFI_NETWORK_SELECTION} permission. Callers without
|
|||
|
* the permission will trigger a {@link java.lang.SecurityException}.
|
|||
|
*
|
|||
|
* @param executor The Executor on which to execute the callbacks.
|
|||
|
* @param listener The listener for the latency mode change.
|
|||
|
* @throws IllegalArgumentException if incorrect input arguments are provided.
|
|||
|
* @throws SecurityException if the caller is not allowed to call this API
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|||
|
@SystemApi
|
|||
|
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
|
|||
|
@RequiresPermission(
|
|||
|
anyOf = {android.Manifest.permission.NETWORK_SETTINGS, MANAGE_WIFI_NETWORK_SELECTION})
|
|||
|
public void addWifiLowLatencyLockListener(
|
|||
|
@NonNull @CallbackExecutor Executor executor,
|
|||
|
@NonNull WifiLowLatencyLockListener listener) {
|
|||
|
if (executor == null) throw new IllegalArgumentException("executor cannot be null");
|
|||
|
if (listener == null) throw new IllegalArgumentException("listener cannot be null");
|
|||
|
if (mVerboseLoggingEnabled) {
|
|||
|
Log.d(TAG, "addWifiLowLatencyLockListener: listener=" + listener + ", executor="
|
|||
|
+ executor);
|
|||
|
}
|
|||
|
final int listenerIdentifier = System.identityHashCode(listener);
|
|||
|
try {
|
|||
|
synchronized (sWifiLowLatencyLockListenerMap) {
|
|||
|
IWifiLowLatencyLockListener.Stub listenerProxy = new OnWifiLowLatencyLockProxy(
|
|||
|
executor,
|
|||
|
listener);
|
|||
|
sWifiLowLatencyLockListenerMap.put(listenerIdentifier, listenerProxy);
|
|||
|
mService.addWifiLowLatencyLockListener(listenerProxy);
|
|||
|
}
|
|||
|
} catch (RemoteException e) {
|
|||
|
sWifiLowLatencyLockListenerMap.remove(listenerIdentifier);
|
|||
|
throw e.rethrowFromSystemServer();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Removes a listener added using {@link WifiManager#addWifiLowLatencyLockListener(Executor,
|
|||
|
* WifiLowLatencyLockListener)}. After calling this method, applications will no longer receive
|
|||
|
* low latency mode notifications.
|
|||
|
*
|
|||
|
* @param listener the listener to be removed.
|
|||
|
* @throws IllegalArgumentException if incorrect input arguments are provided.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|||
|
@SystemApi
|
|||
|
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
|
|||
|
public void removeWifiLowLatencyLockListener(@NonNull WifiLowLatencyLockListener listener) {
|
|||
|
if (listener == null) throw new IllegalArgumentException("listener cannot be null");
|
|||
|
if (mVerboseLoggingEnabled) {
|
|||
|
Log.d(TAG, "removeWifiLowLatencyLockListener: listener=" + listener);
|
|||
|
}
|
|||
|
final int listenerIdentifier = System.identityHashCode(listener);
|
|||
|
synchronized (sWifiLowLatencyLockListenerMap) {
|
|||
|
try {
|
|||
|
if (!sWifiLowLatencyLockListenerMap.contains(listenerIdentifier)) {
|
|||
|
Log.w(TAG, "Unknown external listener " + listenerIdentifier);
|
|||
|
return;
|
|||
|
}
|
|||
|
mService.removeWifiLowLatencyLockListener(
|
|||
|
sWifiLowLatencyLockListenerMap.get(listenerIdentifier));
|
|||
|
|
|||
|
} catch (RemoteException e) {
|
|||
|
throw e.rethrowFromSystemServer();
|
|||
|
} finally {
|
|||
|
sWifiLowLatencyLockListenerMap.remove(listenerIdentifier);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 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(anyOf = {
|
|||
|
android.Manifest.permission.NETWORK_SETTINGS,
|
|||
|
android.Manifest.permission.DUMP
|
|||
|
})
|
|||
|
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(anyOf = {
|
|||
|
android.Manifest.permission.NETWORK_SETTINGS,
|
|||
|
android.Manifest.permission.DUMP
|
|||
|
})
|
|||
|
public void setVerboseLoggingLevel(@VerboseLoggingLevel int verbose) {
|
|||
|
enableVerboseLogging(verbose);
|
|||
|
}
|
|||
|
|
|||
|
/** @hide */
|
|||
|
@UnsupportedAppUsage(
|
|||
|
maxTargetSdk = Build.VERSION_CODES.Q,
|
|||
|
publicAlternatives = "Use {@code #setVerboseLoggingEnabled(boolean)} instead."
|
|||
|
)
|
|||
|
@RequiresPermission(anyOf = {
|
|||
|
android.Manifest.permission.NETWORK_SETTINGS,
|
|||
|
android.Manifest.permission.DUMP
|
|||
|
})
|
|||
|
public void enableVerboseLogging(@VerboseLoggingLevel int verbose) {
|
|||
|
try {
|
|||
|
mService.enableVerboseLogging(verbose);
|
|||
|
mVerboseLoggingEnabled =
|
|||
|
verbose == VERBOSE_LOGGING_LEVEL_ENABLED_SHOW_KEY
|
|||
|
|| verbose == VERBOSE_LOGGING_LEVEL_ENABLED;
|
|||
|
} 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() {
|
|||
|
int verboseLoggingLevel = getVerboseLoggingLevel();
|
|||
|
return verboseLoggingLevel == VERBOSE_LOGGING_LEVEL_ENABLED_SHOW_KEY
|
|||
|
|| verboseLoggingLevel == VERBOSE_LOGGING_LEVEL_ENABLED;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 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 #restoreWifiBackupData(byte[])}.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
@RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
|
|||
|
@RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
|
|||
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|||
|
public void retrieveWifiBackupData(@NonNull @CallbackExecutor Executor executor,
|
|||
|
@NonNull Consumer<byte[]> resultsCallback) {
|
|||
|
if (!SdkLevel.isAtLeastV()) {
|
|||
|
throw new UnsupportedOperationException();
|
|||
|
}
|
|||
|
|
|||
|
Objects.requireNonNull(executor, "executor cannot be null");
|
|||
|
Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null");
|
|||
|
try {
|
|||
|
mService.retrieveWifiBackupData(
|
|||
|
new IByteArrayListener.Stub() {
|
|||
|
@Override
|
|||
|
public void onResult(byte[] value) {
|
|||
|
Binder.clearCallingIdentity();
|
|||
|
executor.execute(() -> {
|
|||
|
resultsCallback.accept(value);
|
|||
|
});
|
|||
|
}
|
|||
|
});
|
|||
|
} catch (RemoteException e) {
|
|||
|
throw e.rethrowFromSystemServer();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Restore state from the backed up data.
|
|||
|
* @param data byte stream in the same format produced by {@link #retrieveWifiBackupData()}
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
@RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
|
|||
|
@RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
|
|||
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|||
|
public void restoreWifiBackupData(@NonNull byte[] data) {
|
|||
|
if (!SdkLevel.isAtLeastV()) {
|
|||
|
throw new UnsupportedOperationException();
|
|||
|
}
|
|||
|
try {
|
|||
|
mService.restoreWifiBackupData(data);
|
|||
|
} catch (RemoteException e) {
|
|||
|
throw e.rethrowFromSystemServer();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 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);
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* @return true if this device supports Trust On First Use (TOFU).
|
|||
|
*/
|
|||
|
public boolean isTrustOnFirstUseSupported() {
|
|||
|
return isFeatureSupported(WIFI_FEATURE_TRUST_ON_FIRST_USE);
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Wi-Fi Easy Connect DPP AKM enables provisioning and configuration of Wi-Fi devices without
|
|||
|
* the need of using the device PSK passphrase.
|
|||
|
* 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 DPP (Device Provisioning Protocol)
|
|||
|
* AKM, false otherwise.
|
|||
|
*/
|
|||
|
public boolean isEasyConnectDppAkmSupported() {
|
|||
|
return isFeatureSupported(WIFI_FEATURE_DPP_AKM);
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Indicate that whether or not settings required TLS minimum version is supported.
|
|||
|
*
|
|||
|
* If the device doesn't support this capability, the minimum accepted TLS version is 1.0.
|
|||
|
*
|
|||
|
* @return true if this device supports setting TLS minimum version.
|
|||
|
*/
|
|||
|
public boolean isTlsMinimumVersionSupported() {
|
|||
|
return isFeatureSupported(WIFI_FEATURE_SET_TLS_MINIMUM_VERSION);
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Indicate that whether or not TLS v1.3 is supported.
|
|||
|
*
|
|||
|
* If requested minimum is not supported, it will default to the maximum supported version.
|
|||
|
*
|
|||
|
* @return true if this device supports TLS v1.3.
|
|||
|
*/
|
|||
|
public boolean isTlsV13Supported() {
|
|||
|
return isFeatureSupported(WIFI_FEATURE_TLS_V1_3);
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* @return true if this device supports Dual Band Simultaneous (DBS) operation.
|
|||
|
*/
|
|||
|
public boolean isDualBandSimultaneousSupported() {
|
|||
|
return isFeatureSupported(WIFI_FEATURE_DUAL_BAND_SIMULTANEOUS);
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* @return true if this device supports TID-To-Link Mapping Negotiation.
|
|||
|
*/
|
|||
|
public boolean isTidToLinkMappingNegotiationSupported() {
|
|||
|
return isFeatureSupported(WIFI_FEATURE_T2LM_NEGOTIATION);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* @return true if this device supports connections to Wi-Fi WEP networks.
|
|||
|
*/
|
|||
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|||
|
public boolean isWepSupported() {
|
|||
|
return isFeatureSupported(WIFI_FEATURE_WEP);
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* @return true if this device supports connections to Wi-Fi WPA-Personal networks.
|
|||
|
*
|
|||
|
* Note that this is the older and less secure WPA-Personal protocol, not WPA2-Personal
|
|||
|
* or later protocols.
|
|||
|
*/
|
|||
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|||
|
public boolean isWpaPersonalSupported() {
|
|||
|
return isFeatureSupported(WIFI_FEATURE_WPA_PERSONAL);
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 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;
|
|||
|
|
|||
|
/**
|
|||
|
* Verbose logging mode: only enable for Wi-Fi Aware feature.
|
|||
|
*
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|||
|
@SystemApi
|
|||
|
public static final int VERBOSE_LOGGING_LEVEL_WIFI_AWARE_ENABLED_ONLY = 3;
|
|||
|
|
|||
|
/** @hide */
|
|||
|
@IntDef(prefix = {"VERBOSE_LOGGING_LEVEL_"}, value = {
|
|||
|
VERBOSE_LOGGING_LEVEL_DISABLED,
|
|||
|
VERBOSE_LOGGING_LEVEL_ENABLED,
|
|||
|
VERBOSE_LOGGING_LEVEL_ENABLED_SHOW_KEY,
|
|||
|
VERBOSE_LOGGING_LEVEL_WIFI_AWARE_ENABLED_ONLY,
|
|||
|
})
|
|||
|
@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.
|
|||
|
*/
|
|||
|
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) {
|
|||
|
Binder.clearCallingIdentity();
|
|||
|
mExecutor.execute(() ->
|
|||
|
mListener.onConnectionStatus(wifiNetworkSuggestion, failureReason));
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Interface for local-only connection failure listener.
|
|||
|
* Should be implemented by applications and set when calling
|
|||
|
* {@link WifiManager#addLocalOnlyConnectionFailureListener(Executor, LocalOnlyConnectionFailureListener)}
|
|||
|
*/
|
|||
|
public interface LocalOnlyConnectionFailureListener {
|
|||
|
|
|||
|
/**
|
|||
|
* Called when the framework attempted to connect to a local-only network requested by the
|
|||
|
* registering app, but the connection to the network failed.
|
|||
|
* @param wifiNetworkSpecifier The {@link WifiNetworkSpecifier} which failed to connect.
|
|||
|
* @param failureReason the connection failure reason code.
|
|||
|
*/
|
|||
|
void onConnectionFailed(
|
|||
|
@NonNull WifiNetworkSpecifier wifiNetworkSpecifier,
|
|||
|
@LocalOnlyConnectionStatusCode int failureReason);
|
|||
|
}
|
|||
|
|
|||
|
private static class LocalOnlyConnectionStatusListenerProxy extends
|
|||
|
ILocalOnlyConnectionStatusListener.Stub {
|
|||
|
private final Executor mExecutor;
|
|||
|
private final LocalOnlyConnectionFailureListener mListener;
|
|||
|
|
|||
|
LocalOnlyConnectionStatusListenerProxy(@NonNull Executor executor,
|
|||
|
@NonNull LocalOnlyConnectionFailureListener listener) {
|
|||
|
mExecutor = executor;
|
|||
|
mListener = listener;
|
|||
|
}
|
|||
|
|
|||
|
@Override
|
|||
|
public void onConnectionStatus(@NonNull WifiNetworkSpecifier networkSpecifier,
|
|||
|
int failureReason) {
|
|||
|
Binder.clearCallingIdentity();
|
|||
|
mExecutor.execute(() ->
|
|||
|
mListener.onConnectionFailed(networkSpecifier, 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();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Add a listener for local-only networks. See {@link WifiNetworkSpecifier}.
|
|||
|
* Specify the caller will only get connection failures for networks they requested.
|
|||
|
* Caller can remove a previously registered listener using
|
|||
|
* {@link WifiManager#removeLocalOnlyConnectionFailureListener(LocalOnlyConnectionFailureListener)}
|
|||
|
* Same caller can add multiple listeners to monitor the event.
|
|||
|
* <p>
|
|||
|
* Applications should have the {@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 local-only network connection failure.
|
|||
|
*/
|
|||
|
@RequiresPermission(ACCESS_WIFI_STATE)
|
|||
|
public void addLocalOnlyConnectionFailureListener(@NonNull @CallbackExecutor Executor executor,
|
|||
|
@NonNull LocalOnlyConnectionFailureListener listener) {
|
|||
|
if (listener == null) throw new IllegalArgumentException("Listener cannot be null");
|
|||
|
if (executor == null) throw new IllegalArgumentException("Executor cannot be null");
|
|||
|
try {
|
|||
|
synchronized (sLocalOnlyConnectionStatusListenerMap) {
|
|||
|
if (sLocalOnlyConnectionStatusListenerMap
|
|||
|
.contains(System.identityHashCode(listener))) {
|
|||
|
Log.w(TAG, "Same listener already registered");
|
|||
|
return;
|
|||
|
}
|
|||
|
ILocalOnlyConnectionStatusListener.Stub binderCallback =
|
|||
|
new LocalOnlyConnectionStatusListenerProxy(executor, listener);
|
|||
|
sLocalOnlyConnectionStatusListenerMap.put(System.identityHashCode(listener),
|
|||
|
binderCallback);
|
|||
|
mService.addLocalOnlyConnectionStatusListener(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 local-only connection events through that listener.
|
|||
|
*
|
|||
|
* @param listener listener to remove.
|
|||
|
*/
|
|||
|
@RequiresPermission(ACCESS_WIFI_STATE)
|
|||
|
public void removeLocalOnlyConnectionFailureListener(
|
|||
|
@NonNull LocalOnlyConnectionFailureListener listener) {
|
|||
|
if (listener == null) throw new IllegalArgumentException("Listener cannot be null");
|
|||
|
try {
|
|||
|
synchronized (sLocalOnlyConnectionStatusListenerMap) {
|
|||
|
int listenerIdentifier = System.identityHashCode(listener);
|
|||
|
if (!sLocalOnlyConnectionStatusListenerMap.contains(listenerIdentifier)) {
|
|||
|
Log.w(TAG, "Unknown external callback " + listenerIdentifier);
|
|||
|
return;
|
|||
|
}
|
|||
|
mService.removeLocalOnlyConnectionStatusListener(
|
|||
|
sLocalOnlyConnectionStatusListenerMap.get(listenerIdentifier),
|
|||
|
mContext.getOpPackageName());
|
|||
|
sLocalOnlyConnectionStatusListenerMap.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);
|
|||
|
|
|||
|
/**
|
|||
|
* Called by framework to indicate the user accepted a dialog to switch to a new network.
|
|||
|
* @param sessionId The ID to indicate current Wi-Fi network connection obtained from
|
|||
|
* {@link WifiConnectedNetworkScorer#onStart(int)}.
|
|||
|
* @param targetNetworkId Network ID of the target network.
|
|||
|
* @param targetBssid BSSID of the target network.
|
|||
|
*/
|
|||
|
default void onNetworkSwitchAccepted(
|
|||
|
int sessionId, int targetNetworkId, @NonNull String targetBssid) {
|
|||
|
// No-op.
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Called by framework to indicate the user rejected a dialog to switch to new network.
|
|||
|
* @param sessionId The ID to indicate current Wi-Fi network connection obtained from
|
|||
|
* {@link WifiConnectedNetworkScorer#onStart(int)}.
|
|||
|
* @param targetNetworkId Network ID of the target network.
|
|||
|
* @param targetBssid BSSID of the target network.
|
|||
|
*/
|
|||
|
default void onNetworkSwitchRejected(
|
|||
|
int sessionId, int targetNetworkId, @NonNull String targetBssid) {
|
|||
|
// No-op.
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* Callback registered with {@link WifiManager#setExternalPnoScanRequest(List, int[], Executor,
|
|||
|
* PnoScanResultsCallback)}. Returns status and result information on offloaded external PNO
|
|||
|
* requests.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
public interface PnoScanResultsCallback {
|
|||
|
/**
|
|||
|
* A status code returned by {@link #onRegisterFailed(int)}.
|
|||
|
* Unknown failure.
|
|||
|
*/
|
|||
|
int REGISTER_PNO_CALLBACK_UNKNOWN = 0;
|
|||
|
|
|||
|
/**
|
|||
|
* A status code returned by {@link #onRegisterFailed(int)}.
|
|||
|
* A callback has already been registered by the caller.
|
|||
|
*/
|
|||
|
int REGISTER_PNO_CALLBACK_ALREADY_REGISTERED = 1;
|
|||
|
|
|||
|
/**
|
|||
|
* A status code returned by {@link #onRegisterFailed(int)}.
|
|||
|
* The platform is unable to serve this request because another app has a PNO scan request
|
|||
|
* active.
|
|||
|
*/
|
|||
|
int REGISTER_PNO_CALLBACK_RESOURCE_BUSY = 2;
|
|||
|
|
|||
|
/**
|
|||
|
* A status code returned by {@link #onRegisterFailed(int)}.
|
|||
|
* PNO scans are not supported on this device.
|
|||
|
*/
|
|||
|
int REGISTER_PNO_CALLBACK_PNO_NOT_SUPPORTED = 3;
|
|||
|
|
|||
|
/** @hide */
|
|||
|
@IntDef(prefix = { "REGISTER_PNO_CALLBACK_" }, value = {
|
|||
|
REGISTER_PNO_CALLBACK_UNKNOWN,
|
|||
|
REGISTER_PNO_CALLBACK_ALREADY_REGISTERED,
|
|||
|
REGISTER_PNO_CALLBACK_RESOURCE_BUSY,
|
|||
|
REGISTER_PNO_CALLBACK_PNO_NOT_SUPPORTED
|
|||
|
})
|
|||
|
@Retention(RetentionPolicy.SOURCE)
|
|||
|
public @interface RegisterFailureReason {}
|
|||
|
|
|||
|
/**
|
|||
|
* A status code returned by {@link #onRemoved(int)}.
|
|||
|
* Unknown reason.
|
|||
|
*/
|
|||
|
int REMOVE_PNO_CALLBACK_UNKNOWN = 0;
|
|||
|
|
|||
|
/**
|
|||
|
* A status code returned by {@link #onRemoved(int)}.
|
|||
|
* This Callback is automatically removed after results ScanResults are delivered.
|
|||
|
*/
|
|||
|
int REMOVE_PNO_CALLBACK_RESULTS_DELIVERED = 1;
|
|||
|
|
|||
|
/**
|
|||
|
* A status code returned by {@link #onRemoved(int)}.
|
|||
|
* This callback has been unregistered via {@link WifiManager#clearExternalPnoScanRequest()}
|
|||
|
*/
|
|||
|
int REMOVE_PNO_CALLBACK_UNREGISTERED = 2;
|
|||
|
|
|||
|
/** @hide */
|
|||
|
@IntDef(prefix = { "REMOVE_PNO_CALLBACK_" }, value = {
|
|||
|
REMOVE_PNO_CALLBACK_UNKNOWN,
|
|||
|
REMOVE_PNO_CALLBACK_RESULTS_DELIVERED,
|
|||
|
REMOVE_PNO_CALLBACK_UNREGISTERED
|
|||
|
})
|
|||
|
@Retention(RetentionPolicy.SOURCE)
|
|||
|
public @interface RemovalReason {}
|
|||
|
|
|||
|
/**
|
|||
|
* Called when PNO scan finds one of the requested SSIDs. This is a one time callback.
|
|||
|
* After results are reported the callback will be automatically unregistered.
|
|||
|
*/
|
|||
|
void onScanResultsAvailable(@NonNull List<ScanResult> scanResults);
|
|||
|
|
|||
|
/**
|
|||
|
* Called when this callback has been successfully registered.
|
|||
|
*/
|
|||
|
void onRegisterSuccess();
|
|||
|
|
|||
|
/**
|
|||
|
* Called when this callback failed to register with the failure reason.
|
|||
|
* See {@link RegisterFailureReason} for details.
|
|||
|
*/
|
|||
|
void onRegisterFailed(@RegisterFailureReason int reason);
|
|||
|
|
|||
|
/**
|
|||
|
* Called when this callback has been unregistered from the Wi-Fi subsystem.
|
|||
|
* See {@link RemovalReason} for details.
|
|||
|
*/
|
|||
|
void onRemoved(@RemovalReason int reason);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
private class PnoScanResultsCallbackProxy extends IPnoScanResultsCallback.Stub {
|
|||
|
private Executor mExecutor;
|
|||
|
private PnoScanResultsCallback mCallback;
|
|||
|
|
|||
|
PnoScanResultsCallbackProxy(@NonNull Executor executor,
|
|||
|
@NonNull PnoScanResultsCallback callback) {
|
|||
|
mExecutor = executor;
|
|||
|
mCallback = callback;
|
|||
|
}
|
|||
|
|
|||
|
@Override
|
|||
|
public void onScanResultsAvailable(List<ScanResult> scanResults) {
|
|||
|
if (mVerboseLoggingEnabled) {
|
|||
|
Log.v(TAG, "PnoScanResultsCallback: " + "onScanResultsAvailable");
|
|||
|
}
|
|||
|
Binder.clearCallingIdentity();
|
|||
|
mExecutor.execute(() -> mCallback.onScanResultsAvailable(scanResults));
|
|||
|
}
|
|||
|
|
|||
|
@Override
|
|||
|
public void onRegisterSuccess() {
|
|||
|
if (mVerboseLoggingEnabled) {
|
|||
|
Log.v(TAG, "PnoScanResultsCallback: " + "onRegisterSuccess");
|
|||
|
}
|
|||
|
Binder.clearCallingIdentity();
|
|||
|
mExecutor.execute(() -> mCallback.onRegisterSuccess());
|
|||
|
}
|
|||
|
|
|||
|
@Override
|
|||
|
public void onRegisterFailed(int reason) {
|
|||
|
if (mVerboseLoggingEnabled) {
|
|||
|
Log.v(TAG, "PnoScanResultsCallback: " + "onRegisterFailed " + reason);
|
|||
|
}
|
|||
|
Binder.clearCallingIdentity();
|
|||
|
mExecutor.execute(() -> mCallback.onRegisterFailed(reason));
|
|||
|
}
|
|||
|
|
|||
|
@Override
|
|||
|
public void onRemoved(int reason) {
|
|||
|
if (mVerboseLoggingEnabled) {
|
|||
|
Log.v(TAG, "PnoScanResultsCallback: " + "onRemoved");
|
|||
|
}
|
|||
|
Binder.clearCallingIdentity();
|
|||
|
mExecutor.execute(() -> mCallback.onRemoved(reason));
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 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)));
|
|||
|
}
|
|||
|
|
|||
|
@Override
|
|||
|
public void onNetworkSwitchAccepted(
|
|||
|
int sessionId, int targetNetworkId, @NonNull String targetBssid) {
|
|||
|
if (mVerboseLoggingEnabled) {
|
|||
|
Log.v(TAG, "WifiConnectedNetworkScorer: onNetworkSwitchAccepted:"
|
|||
|
+ " sessionId=" + sessionId
|
|||
|
+ " targetNetworkId=" + targetNetworkId
|
|||
|
+ " targetBssid=" + targetBssid);
|
|||
|
}
|
|||
|
Binder.clearCallingIdentity();
|
|||
|
mExecutor.execute(() -> mScorer.onNetworkSwitchAccepted(
|
|||
|
sessionId, targetNetworkId, targetBssid));
|
|||
|
}
|
|||
|
@Override
|
|||
|
public void onNetworkSwitchRejected(
|
|||
|
int sessionId, int targetNetworkId, @NonNull String targetBssid) {
|
|||
|
if (mVerboseLoggingEnabled) {
|
|||
|
Log.v(TAG, "WifiConnectedNetworkScorer: onNetworkSwitchRejected:"
|
|||
|
+ " sessionId=" + sessionId
|
|||
|
+ " targetNetworkId=" + targetNetworkId
|
|||
|
+ " targetBssid=" + targetBssid);
|
|||
|
}
|
|||
|
Binder.clearCallingIdentity();
|
|||
|
mExecutor.execute(() -> mScorer.onNetworkSwitchRejected(
|
|||
|
sessionId, targetNetworkId, targetBssid));
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* This API allows the caller to program up to 2 SSIDs for PNO scans. PNO scans are offloaded
|
|||
|
* to the Wi-Fi chip when the device is inactive (typically screen-off).
|
|||
|
* If the screen is currently off when this API is called, then a PNO scan including the
|
|||
|
* requested SSIDs will immediately get started. If the screen is on when this API is called,
|
|||
|
* the requested SSIDs will get included for PNO scans the next time the screen turns off.
|
|||
|
* <p>
|
|||
|
* Note, due to PNO being a limited resource, only one external PNO request is supported, and
|
|||
|
* calling this API will fail if an external PNO scan request is already registered by another
|
|||
|
* caller. If the caller that has already registered a callback calls this API again, the new
|
|||
|
* callback will override the previous one.
|
|||
|
* <p>
|
|||
|
* After this API is called, {@link PnoScanResultsCallback#onRegisterSuccess()} will be invoked
|
|||
|
* if the operation is successful, or {@link PnoScanResultsCallback#onRegisterFailed(int)} will
|
|||
|
* be invoked if the operation failed.
|
|||
|
* <p>
|
|||
|
* {@link PnoScanResultsCallback#onRemoved(int)} will be invoked to notify the caller when the
|
|||
|
* external PNO scan request is removed, which will happen when one of the following events
|
|||
|
* happen:
|
|||
|
* </p>
|
|||
|
* <ul>
|
|||
|
* <li>Upon finding any of the requested SSIDs through either a connectivity scan or PNO scan,
|
|||
|
* the matching ScanResults will be returned
|
|||
|
* via {@link PnoScanResultsCallback#onScanResultsAvailable(List)}, and the registered PNO
|
|||
|
* scan request will get automatically removed.</li>
|
|||
|
* <li>The external PNO scan request is removed by a call to
|
|||
|
* {@link #clearExternalPnoScanRequest()}</li>
|
|||
|
* </ul>
|
|||
|
*
|
|||
|
* @param ssids The list of SSIDs to request for PNO scan.
|
|||
|
* @param frequencies Provide as hint a list of up to 10 frequencies to be used for PNO scan.
|
|||
|
* Each frequency should be in MHz. For example 2412 and 5180 are valid
|
|||
|
* frequencies. {@link WifiInfo#getFrequency()} is a location where this
|
|||
|
* information could be obtained. If a null or empty array is provided, the
|
|||
|
* Wi-Fi framework will automatically decide the list of frequencies to scan.
|
|||
|
* @param executor The executor on which callback will be invoked.
|
|||
|
* @param callback For the calling application to receive results and status updates.
|
|||
|
*
|
|||
|
* @throws SecurityException if the caller does not have permission.
|
|||
|
* @throws IllegalArgumentException if the caller provided invalid inputs.
|
|||
|
* @throws UnsupportedOperationException if this API is not supported on this SDK version.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
@RequiresPermission(allOf = {ACCESS_FINE_LOCATION,
|
|||
|
REQUEST_COMPANION_PROFILE_AUTOMOTIVE_PROJECTION})
|
|||
|
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
|
|||
|
public void setExternalPnoScanRequest(@NonNull List<WifiSsid> ssids,
|
|||
|
@Nullable int[] frequencies, @NonNull @CallbackExecutor Executor executor,
|
|||
|
@NonNull PnoScanResultsCallback callback) {
|
|||
|
if (executor == null) throw new IllegalArgumentException("executor cannot be null");
|
|||
|
if (callback == null) throw new IllegalArgumentException("callback cannot be null");
|
|||
|
try {
|
|||
|
mService.setExternalPnoScanRequest(new Binder(),
|
|||
|
new PnoScanResultsCallbackProxy(executor, callback),
|
|||
|
ssids, frequencies == null ? new int[0] : frequencies,
|
|||
|
mContext.getOpPackageName(), mContext.getAttributionTag());
|
|||
|
} catch (RemoteException e) {
|
|||
|
throw e.rethrowFromSystemServer();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Wi-Fi Preferred Network Offload (PNO) scanning offloads scanning to the chip to save power
|
|||
|
* when Wi-Fi is disconnected and the screen is off. See
|
|||
|
* {@link https://source.android.com/docs/core/connect/wifi-scan} for more details.
|
|||
|
* <p>
|
|||
|
* This API can be used to enable or disable PNO scanning. After boot, PNO scanning is enabled
|
|||
|
* by default. When PNO scanning is disabled, the Wi-Fi framework will not trigger scans at all
|
|||
|
* when the screen is off. This can be used to save power on devices with small batteries.
|
|||
|
*
|
|||
|
* @param enabled True - enable PNO scanning
|
|||
|
* False - disable PNO scanning
|
|||
|
* @param enablePnoScanAfterWifiToggle True - Wifi being enabled by
|
|||
|
* {@link #setWifiEnabled(boolean)} will re-enable PNO
|
|||
|
* scanning.
|
|||
|
* False - Wifi being enabled by
|
|||
|
* {@link #setWifiEnabled(boolean)} will not re-enable PNO
|
|||
|
* scanning.
|
|||
|
*
|
|||
|
* @throws SecurityException if the caller does not have permission.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|||
|
@SystemApi
|
|||
|
@RequiresPermission(
|
|||
|
anyOf = {MANAGE_WIFI_NETWORK_SELECTION, NETWORK_SETTINGS, NETWORK_SETUP_WIZARD})
|
|||
|
public void setPnoScanState(@PnoScanState int pnoScanState) {
|
|||
|
try {
|
|||
|
boolean enabled = false;
|
|||
|
boolean enablePnoScanAfterWifiToggle = false;
|
|||
|
switch (pnoScanState) {
|
|||
|
case PNO_SCAN_STATE_DISABLED_UNTIL_REBOOT:
|
|||
|
break;
|
|||
|
case PNO_SCAN_STATE_DISABLED_UNTIL_WIFI_TOGGLE:
|
|||
|
enablePnoScanAfterWifiToggle = true;
|
|||
|
break;
|
|||
|
case PNO_SCAN_STATE_ENABLED:
|
|||
|
enabled = true;
|
|||
|
break;
|
|||
|
default:
|
|||
|
throw new IllegalArgumentException("Invalid PnoScanState");
|
|||
|
}
|
|||
|
mService.setPnoScanEnabled(enabled, enablePnoScanAfterWifiToggle,
|
|||
|
mContext.getOpPackageName());
|
|||
|
} catch (RemoteException e) {
|
|||
|
throw e.rethrowFromSystemServer();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Wi-Fi Preferred Network Offload (PNO) scanning offloads scanning to the chip to save power
|
|||
|
* when Wi-Fi is disconnected and the screen is off. See
|
|||
|
* {@link https://source.android.com/docs/core/connect/wifi-scan} for more details.
|
|||
|
* <p>
|
|||
|
* This API can be used to enable or disable PNO scanning. After boot, PNO scanning is enabled
|
|||
|
* by default. When PNO scanning is disabled, the Wi-Fi framework will not trigger scans at all
|
|||
|
* when the screen is off. This can be used to save power on devices with small batteries.
|
|||
|
*
|
|||
|
* @param enabled True - enable PNO scanning
|
|||
|
* False - disable PNO scanning
|
|||
|
* @param enablePnoScanAfterWifiToggle True - Wifi being enabled by
|
|||
|
* {@link #setWifiEnabled(boolean)} will re-enable PNO
|
|||
|
* scanning.
|
|||
|
* False - Wifi being enabled by
|
|||
|
* {@link #setWifiEnabled(boolean)} will not re-enable PNO
|
|||
|
* scanning.
|
|||
|
*
|
|||
|
* @throws SecurityException if the caller does not have permission.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@RequiresPermission(
|
|||
|
anyOf = {MANAGE_WIFI_NETWORK_SELECTION, NETWORK_SETTINGS, NETWORK_SETUP_WIZARD})
|
|||
|
public void setPnoScanEnabled(boolean enabled, boolean enablePnoScanAfterWifiToggle) {
|
|||
|
try {
|
|||
|
mService.setPnoScanEnabled(enabled, enablePnoScanAfterWifiToggle,
|
|||
|
mContext.getOpPackageName());
|
|||
|
} catch (RemoteException e) {
|
|||
|
throw e.rethrowFromSystemServer();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Clear the current PNO scan request that's been set by the calling UID. Note, the call will
|
|||
|
* be no-op if the current PNO scan request is set by a different UID.
|
|||
|
*
|
|||
|
* @throws UnsupportedOperationException if the API is not supported on this SDK version.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
|
|||
|
public void clearExternalPnoScanRequest() {
|
|||
|
try {
|
|||
|
mService.clearExternalPnoScanRequest();
|
|||
|
} catch (RemoteException e) {
|
|||
|
throw e.rethrowFromSystemServer();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Returns information about the last caller of an API.
|
|||
|
*
|
|||
|
* @param apiType The type of API to request information for the last caller.
|
|||
|
* @param executor The executor on which callback will be invoked.
|
|||
|
* @param resultsCallback An asynchronous callback that will return 2 arguments.
|
|||
|
* {@code String} the name of the package that performed the last API
|
|||
|
* call. {@code Boolean} the value associated with the last API call.
|
|||
|
*
|
|||
|
* @throws SecurityException if the caller does not have permission.
|
|||
|
* @throws IllegalArgumentException if the caller provided invalid inputs.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
@RequiresPermission(anyOf = {
|
|||
|
android.Manifest.permission.NETWORK_SETTINGS,
|
|||
|
android.Manifest.permission.NETWORK_STACK,
|
|||
|
NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK})
|
|||
|
public void getLastCallerInfoForApi(@ApiType int apiType,
|
|||
|
@NonNull @CallbackExecutor Executor executor,
|
|||
|
@NonNull BiConsumer<String, Boolean> resultsCallback) {
|
|||
|
if (executor == null) {
|
|||
|
throw new IllegalArgumentException("executor can't be null");
|
|||
|
}
|
|||
|
if (resultsCallback == null) {
|
|||
|
throw new IllegalArgumentException("resultsCallback can't be null");
|
|||
|
}
|
|||
|
try {
|
|||
|
mService.getLastCallerInfoForApi(apiType,
|
|||
|
new ILastCallerListener.Stub() {
|
|||
|
@Override
|
|||
|
public void onResult(String packageName, boolean enabled) {
|
|||
|
Binder.clearCallingIdentity();
|
|||
|
executor.execute(() -> {
|
|||
|
resultsCallback.accept(packageName, enabled);
|
|||
|
});
|
|||
|
}
|
|||
|
});
|
|||
|
} catch (RemoteException e) {
|
|||
|
throw e.rethrowFromSystemServer();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 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
|
|||
|
}, conditional = true)
|
|||
|
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.
|
|||
|
*
|
|||
|
* Note: the {@code band} parameter which is specified as a {@code WifiScanner#WIFI_BAND_*}
|
|||
|
* constant is limited to one of the band values specified below. Specifically, if the 5GHz
|
|||
|
* band is included then it must include the DFS channels - an exception will be thrown
|
|||
|
* otherwise. The caller should not make any assumptions about whether DFS channels are allowed.
|
|||
|
* This API will indicate whether DFS channels are allowed for the specified operation mode(s)
|
|||
|
* per device policy.
|
|||
|
*
|
|||
|
* @param band one of the following band constants defined in {@code WifiScanner#WIFI_BAND_*}
|
|||
|
* constants.
|
|||
|
* 1. {@code WifiScanner#WIFI_BAND_UNSPECIFIED}=0 - 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}=1
|
|||
|
* 3. {@code WifiScanner#WIFI_BAND_5_GHZ_WITH_DFS}=6
|
|||
|
* 4. {@code WifiScanner#WIFI_BAND_BOTH_WITH_DFS}=7
|
|||
|
* 5. {@code WifiScanner#WIFI_BAND_6_GHZ}=8
|
|||
|
* 6. {@code WifiScanner#WIFI_BAND_24_5_WITH_DFS_6_GHZ}=15
|
|||
|
* 7. {@code WifiScanner#WIFI_BAND_60_GHZ}=16
|
|||
|
* 8. {@code WifiScanner#WIFI_BAND_24_5_WITH_DFS_6_60_GHZ}=31
|
|||
|
* @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.
|
|||
|
*/
|
|||
|
@RequiresApi(Build.VERSION_CODES.S)
|
|||
|
@NonNull
|
|||
|
@RequiresPermission(NEARBY_WIFI_DEVICES)
|
|||
|
public List<WifiAvailableChannel> getAllowedChannels(
|
|||
|
int band,
|
|||
|
@WifiAvailableChannel.OpMode int mode) {
|
|||
|
if (!SdkLevel.isAtLeastS()) {
|
|||
|
throw new UnsupportedOperationException();
|
|||
|
}
|
|||
|
try {
|
|||
|
Bundle extras = new Bundle();
|
|||
|
if (SdkLevel.isAtLeastS()) {
|
|||
|
extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE,
|
|||
|
mContext.getAttributionSource());
|
|||
|
}
|
|||
|
return mService.getUsableChannels(band, mode,
|
|||
|
WifiAvailableChannel.FILTER_REGULATORY, mContext.getOpPackageName(), extras);
|
|||
|
} 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.
|
|||
|
*
|
|||
|
* Note: the {@code band} parameter which is specified as a {@code WifiScanner#WIFI_BAND_*}
|
|||
|
* constant is limited to one of the band values specified below. Specifically, if the 5GHz
|
|||
|
* band is included then it must include the DFS channels - an exception will be thrown
|
|||
|
* otherwise. The caller should not make any assumptions about whether DFS channels are allowed.
|
|||
|
* This API will indicate whether DFS channels are allowed for the specified operation mode(s)
|
|||
|
* per device policy.
|
|||
|
*
|
|||
|
* @param band one of the following band constants defined in {@code WifiScanner#WIFI_BAND_*}
|
|||
|
* constants.
|
|||
|
* 1. {@code WifiScanner#WIFI_BAND_UNSPECIFIED}=0 - 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}=1
|
|||
|
* 3. {@code WifiScanner#WIFI_BAND_5_GHZ_WITH_DFS}=6
|
|||
|
* 4. {@code WifiScanner#WIFI_BAND_BOTH_WITH_DFS}=7
|
|||
|
* 5. {@code WifiScanner#WIFI_BAND_6_GHZ}=8
|
|||
|
* 6. {@code WifiScanner#WIFI_BAND_24_5_WITH_DFS_6_GHZ}=15
|
|||
|
* 7. {@code WifiScanner#WIFI_BAND_60_GHZ}=16
|
|||
|
* 8. {@code WifiScanner#WIFI_BAND_24_5_WITH_DFS_6_60_GHZ}=31
|
|||
|
* @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.
|
|||
|
*/
|
|||
|
@RequiresApi(Build.VERSION_CODES.S)
|
|||
|
@NonNull
|
|||
|
@RequiresPermission(NEARBY_WIFI_DEVICES)
|
|||
|
public List<WifiAvailableChannel> getUsableChannels(
|
|||
|
int band,
|
|||
|
@WifiAvailableChannel.OpMode int mode) {
|
|||
|
if (!SdkLevel.isAtLeastS()) {
|
|||
|
throw new UnsupportedOperationException();
|
|||
|
}
|
|||
|
try {
|
|||
|
Bundle extras = new Bundle();
|
|||
|
if (SdkLevel.isAtLeastS()) {
|
|||
|
extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE,
|
|||
|
mContext.getAttributionSource());
|
|||
|
}
|
|||
|
return mService.getUsableChannels(band, mode,
|
|||
|
WifiAvailableChannel.getUsableFilter(), mContext.getOpPackageName(), extras);
|
|||
|
} catch (RemoteException e) {
|
|||
|
throw e.rethrowFromSystemServer();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* If the device supports Wi-Fi Passpoint, the user can explicitly enable or disable it.
|
|||
|
* That status can be queried using this method.
|
|||
|
* @return {@code true} if Wi-Fi Passpoint is enabled
|
|||
|
*
|
|||
|
*/
|
|||
|
@RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE)
|
|||
|
public boolean isWifiPasspointEnabled() {
|
|||
|
try {
|
|||
|
return mService.isWifiPasspointEnabled();
|
|||
|
} catch (RemoteException e) {
|
|||
|
throw e.rethrowFromSystemServer();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Explicitly enable or disable Wi-Fi Passpoint as a global switch.
|
|||
|
* The global Passpoint enabling/disabling overrides individual configuration
|
|||
|
* enabling/disabling.
|
|||
|
* Passpoint global status can be queried by {@link WifiManager#isWifiPasspointEnabled }.
|
|||
|
*
|
|||
|
* @param enabled {@code true} to enable, {@code false} to disable.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
@RequiresPermission(anyOf = {
|
|||
|
android.Manifest.permission.NETWORK_SETTINGS,
|
|||
|
android.Manifest.permission.NETWORK_SETUP_WIZARD
|
|||
|
})
|
|||
|
public void setWifiPasspointEnabled(boolean enabled) {
|
|||
|
if (mVerboseLoggingEnabled) {
|
|||
|
Log.v(TAG, "setWifiPasspointEnabled: " + enabled);
|
|||
|
}
|
|||
|
try {
|
|||
|
mService.setWifiPasspointEnabled(enabled);
|
|||
|
} catch (RemoteException e) {
|
|||
|
throw e.rethrowFromSystemServer();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* The device may support concurrent connections to multiple internet-providing Wi-Fi
|
|||
|
* networks (APs) - that is indicated by
|
|||
|
* {@link WifiManager#isStaConcurrencyForMultiInternetSupported()}.
|
|||
|
* This method indicates whether or not the feature is currently enabled.
|
|||
|
* A value of {@link WifiManager#WIFI_MULTI_INTERNET_MODE_DISABLED} indicates that the feature
|
|||
|
* is disabled, a value of {@link WifiManager#WIFI_MULTI_INTERNET_MODE_DBS_AP} or
|
|||
|
* {@link WifiManager#WIFI_MULTI_INTERNET_MODE_MULTI_AP} indicates that the feature is enabled.
|
|||
|
*
|
|||
|
* The app can register to receive the corresponding Wi-Fi networks using the
|
|||
|
* {@link ConnectivityManager#registerNetworkCallback(NetworkRequest, NetworkCallback)} API with
|
|||
|
* a {@link WifiNetworkSpecifier} configured using the
|
|||
|
* {@link WifiNetworkSpecifier.Builder#setBand(int)} method.
|
|||
|
*/
|
|||
|
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
|
|||
|
@RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE)
|
|||
|
public @WifiMultiInternetMode int getStaConcurrencyForMultiInternetMode() {
|
|||
|
try {
|
|||
|
return mService.getStaConcurrencyForMultiInternetMode();
|
|||
|
} catch (RemoteException e) {
|
|||
|
throw e.rethrowFromSystemServer();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Check if the currently connected network meets the minimum required Wi-Fi security level set.
|
|||
|
* If not, the current network will be disconnected.
|
|||
|
*
|
|||
|
* @throws SecurityException if the caller does not have permission.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
|
|||
|
@SystemApi
|
|||
|
@RequiresPermission(android.Manifest.permission.MANAGE_DEVICE_ADMINS)
|
|||
|
public void notifyMinimumRequiredWifiSecurityLevelChanged(int level) {
|
|||
|
if (mVerboseLoggingEnabled) {
|
|||
|
Log.v(TAG, "notifyMinimumRequiredWifiSecurityLevelChanged");
|
|||
|
}
|
|||
|
try {
|
|||
|
mService.notifyMinimumRequiredWifiSecurityLevelChanged(level);
|
|||
|
} catch (RemoteException e) {
|
|||
|
throw e.rethrowFromSystemServer();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Check if the currently connected network meets the Wi-Fi SSID policy set.
|
|||
|
* If not, the current network will be disconnected.
|
|||
|
*
|
|||
|
* @throws SecurityException if the caller does not have permission.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
|
|||
|
@SystemApi
|
|||
|
@RequiresPermission(android.Manifest.permission.MANAGE_DEVICE_ADMINS)
|
|||
|
public void notifyWifiSsidPolicyChanged(@NonNull WifiSsidPolicy policy) {
|
|||
|
if (mVerboseLoggingEnabled) {
|
|||
|
Log.v(TAG, "notifyWifiSsidPolicyChanged");
|
|||
|
}
|
|||
|
try {
|
|||
|
if (policy != null) {
|
|||
|
mService.notifyWifiSsidPolicyChanged(
|
|||
|
policy.getPolicyType(), new ArrayList<>(policy.getSsids()));
|
|||
|
}
|
|||
|
} catch (RemoteException e) {
|
|||
|
throw e.rethrowFromSystemServer();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Configure whether or not concurrent multiple connections to internet-providing Wi-Fi
|
|||
|
* networks (AP) is enabled.
|
|||
|
* Use {@link WifiManager#WIFI_MULTI_INTERNET_MODE_DISABLED} to disable, and either
|
|||
|
* {@link WifiManager#WIFI_MULTI_INTERNET_MODE_DBS_AP} or
|
|||
|
* {@link WifiManager#WIFI_MULTI_INTERNET_MODE_MULTI_AP} to enable in different modes.
|
|||
|
* The {@link WifiManager#getStaConcurrencyForMultiInternetMode() } can be used to retrieve
|
|||
|
* the current mode.
|
|||
|
*
|
|||
|
* @param mode Multi internet mode.
|
|||
|
* @return true when the mode is set successfully, false when failed.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
|
|||
|
@RequiresPermission(anyOf = {
|
|||
|
android.Manifest.permission.NETWORK_SETTINGS,
|
|||
|
android.Manifest.permission.NETWORK_SETUP_WIZARD
|
|||
|
})
|
|||
|
public boolean setStaConcurrencyForMultiInternetMode(@WifiMultiInternetMode int mode) {
|
|||
|
if (mVerboseLoggingEnabled) {
|
|||
|
Log.v(TAG, "setStaConcurrencyForMultiInternetMode: " + mode);
|
|||
|
}
|
|||
|
try {
|
|||
|
return mService.setStaConcurrencyForMultiInternetMode(mode);
|
|||
|
} catch (RemoteException e) {
|
|||
|
throw e.rethrowFromSystemServer();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Intent action to launch a dialog from the WifiDialog app.
|
|||
|
* Must include EXTRA_DIALOG_ID, EXTRA_DIALOG_TYPE, and appropriate extras for the dialog type.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
public static final String ACTION_LAUNCH_DIALOG =
|
|||
|
"android.net.wifi.action.LAUNCH_DIALOG";
|
|||
|
|
|||
|
/**
|
|||
|
* Intent action to dismiss an existing dialog from the WifiDialog app.
|
|||
|
* Must include EXTRA_DIALOG_ID.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
public static final String ACTION_DISMISS_DIALOG =
|
|||
|
"android.net.wifi.action.DISMISS_DIALOG";
|
|||
|
|
|||
|
/**
|
|||
|
* Unknown DialogType.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
public static final int DIALOG_TYPE_UNKNOWN = 0;
|
|||
|
|
|||
|
/**
|
|||
|
* DialogType for a simple dialog.
|
|||
|
* @see {@link com.android.server.wifi.WifiDialogManager#createSimpleDialog}
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
public static final int DIALOG_TYPE_SIMPLE = 1;
|
|||
|
|
|||
|
/**
|
|||
|
* DialogType for a P2P Invitation Sent dialog.
|
|||
|
* @see {@link com.android.server.wifi.WifiDialogManager#createP2pInvitationSentDialog}
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
public static final int DIALOG_TYPE_P2P_INVITATION_SENT = 2;
|
|||
|
|
|||
|
/**
|
|||
|
* DialogType for a P2P Invitation Received dialog.
|
|||
|
* @see {@link com.android.server.wifi.WifiDialogManager#createP2pInvitationReceivedDialog}
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
public static final int DIALOG_TYPE_P2P_INVITATION_RECEIVED = 3;
|
|||
|
|
|||
|
/** @hide */
|
|||
|
@IntDef(prefix = { "DIALOG_TYPE_" }, value = {
|
|||
|
DIALOG_TYPE_UNKNOWN,
|
|||
|
DIALOG_TYPE_SIMPLE,
|
|||
|
DIALOG_TYPE_P2P_INVITATION_SENT,
|
|||
|
DIALOG_TYPE_P2P_INVITATION_RECEIVED,
|
|||
|
})
|
|||
|
@Retention(RetentionPolicy.SOURCE)
|
|||
|
public @interface DialogType {}
|
|||
|
|
|||
|
/**
|
|||
|
* Dialog positive button was clicked.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
public static final int DIALOG_REPLY_POSITIVE = 0;
|
|||
|
|
|||
|
/**
|
|||
|
* Dialog negative button was clicked.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
public static final int DIALOG_REPLY_NEGATIVE = 1;
|
|||
|
|
|||
|
/**
|
|||
|
* Dialog neutral button was clicked.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
public static final int DIALOG_REPLY_NEUTRAL = 2;
|
|||
|
|
|||
|
/**
|
|||
|
* Dialog was cancelled.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
public static final int DIALOG_REPLY_CANCELLED = 3;
|
|||
|
|
|||
|
/**
|
|||
|
* Indication of a reply to a dialog.
|
|||
|
* See {@link WifiManager#replyToSimpleDialog(int, int)}
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@IntDef(prefix = { "DIALOG_TYPE_" }, value = {
|
|||
|
DIALOG_REPLY_POSITIVE,
|
|||
|
DIALOG_REPLY_NEGATIVE,
|
|||
|
DIALOG_REPLY_NEUTRAL,
|
|||
|
DIALOG_REPLY_CANCELLED,
|
|||
|
})
|
|||
|
@Retention(RetentionPolicy.SOURCE)
|
|||
|
public @interface DialogReply {}
|
|||
|
|
|||
|
/**
|
|||
|
* Invalid dialog id for dialogs that are not currently active.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
public static final int INVALID_DIALOG_ID = -1;
|
|||
|
|
|||
|
/**
|
|||
|
* Extra int indicating the type of dialog to display.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
public static final String EXTRA_DIALOG_TYPE = "android.net.wifi.extra.DIALOG_TYPE";
|
|||
|
|
|||
|
/**
|
|||
|
* Extra int indicating the ID of a dialog. The value must not be {@link #INVALID_DIALOG_ID}.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
public static final String EXTRA_DIALOG_ID = "android.net.wifi.extra.DIALOG_ID";
|
|||
|
|
|||
|
/**
|
|||
|
* Extra String indicating the title of a simple dialog.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
public static final String EXTRA_DIALOG_TITLE = "android.net.wifi.extra.DIALOG_TITLE";
|
|||
|
|
|||
|
/**
|
|||
|
* Extra String indicating the message of a simple dialog.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
public static final String EXTRA_DIALOG_MESSAGE = "android.net.wifi.extra.DIALOG_MESSAGE";
|
|||
|
|
|||
|
/**
|
|||
|
* Extra String indicating the message URL of a simple dialog.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
public static final String EXTRA_DIALOG_MESSAGE_URL =
|
|||
|
"android.net.wifi.extra.DIALOG_MESSAGE_URL";
|
|||
|
|
|||
|
/**
|
|||
|
* Extra String indicating the start index of a message URL span of a simple dialog.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
public static final String EXTRA_DIALOG_MESSAGE_URL_START =
|
|||
|
"android.net.wifi.extra.DIALOG_MESSAGE_URL_START";
|
|||
|
|
|||
|
/**
|
|||
|
* Extra String indicating the end index of a message URL span of a simple dialog.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
public static final String EXTRA_DIALOG_MESSAGE_URL_END =
|
|||
|
"android.net.wifi.extra.DIALOG_MESSAGE_URL_END";
|
|||
|
|
|||
|
/**
|
|||
|
* Extra String indicating the positive button text of a simple dialog.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
public static final String EXTRA_DIALOG_POSITIVE_BUTTON_TEXT =
|
|||
|
"android.net.wifi.extra.DIALOG_POSITIVE_BUTTON_TEXT";
|
|||
|
|
|||
|
/**
|
|||
|
* Extra String indicating the negative button text of a simple dialog.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
public static final String EXTRA_DIALOG_NEGATIVE_BUTTON_TEXT =
|
|||
|
"android.net.wifi.extra.DIALOG_NEGATIVE_BUTTON_TEXT";
|
|||
|
|
|||
|
/**
|
|||
|
* Extra String indicating the neutral button text of a simple dialog.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
public static final String EXTRA_DIALOG_NEUTRAL_BUTTON_TEXT =
|
|||
|
"android.net.wifi.extra.DIALOG_NEUTRAL_BUTTON_TEXT";
|
|||
|
|
|||
|
/**
|
|||
|
* Extra long indicating the timeout in milliseconds of a dialog.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
public static final String EXTRA_DIALOG_TIMEOUT_MS = "android.net.wifi.extra.DIALOG_TIMEOUT_MS";
|
|||
|
|
|||
|
/**
|
|||
|
* Extra String indicating a P2P device name for a P2P Invitation Sent/Received dialog.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
public static final String EXTRA_P2P_DEVICE_NAME = "android.net.wifi.extra.P2P_DEVICE_NAME";
|
|||
|
|
|||
|
/**
|
|||
|
* Extra boolean indicating that a PIN is requested for a P2P Invitation Received dialog.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
public static final String EXTRA_P2P_PIN_REQUESTED = "android.net.wifi.extra.P2P_PIN_REQUESTED";
|
|||
|
|
|||
|
/**
|
|||
|
* Extra String indicating the PIN to be displayed for a P2P Invitation Sent/Received dialog.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
public static final String EXTRA_P2P_DISPLAY_PIN = "android.net.wifi.extra.P2P_DISPLAY_PIN";
|
|||
|
|
|||
|
/**
|
|||
|
* Extra boolean indicating ACTION_CLOSE_SYSTEM_DIALOGS should not close the Wi-Fi dialogs.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
public static final String EXTRA_CLOSE_SYSTEM_DIALOGS_EXCEPT_WIFI =
|
|||
|
"android.net.wifi.extra.CLOSE_SYSTEM_DIALOGS_EXCEPT_WIFI";
|
|||
|
|
|||
|
/**
|
|||
|
* Returns a set of packages that aren't DO or PO but should be able to manage WiFi networks.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
@RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
|
|||
|
@NonNull
|
|||
|
public Set<String> getOemPrivilegedWifiAdminPackages() {
|
|||
|
try {
|
|||
|
return new ArraySet<>(mService.getOemPrivilegedWifiAdminPackages());
|
|||
|
} catch (RemoteException e) {
|
|||
|
throw e.rethrowFromSystemServer();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Method for WifiDialog to notify the framework of a reply to a simple dialog.
|
|||
|
* @param dialogId id of the replying dialog.
|
|||
|
* @param reply reply of the dialog.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
public void replyToSimpleDialog(int dialogId, @DialogReply int reply) {
|
|||
|
if (mVerboseLoggingEnabled) {
|
|||
|
Log.v(TAG, "replyToWifiEnableRequestDialog: dialogId=" + dialogId
|
|||
|
+ " reply=" + reply);
|
|||
|
}
|
|||
|
try {
|
|||
|
mService.replyToSimpleDialog(dialogId, reply);
|
|||
|
} catch (RemoteException e) {
|
|||
|
throw e.rethrowFromSystemServer();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Method for WifiDialog to notify the framework of a reply to a P2P Invitation Received dialog.
|
|||
|
* @param dialogId id of the replying dialog.
|
|||
|
* @param accepted Whether the invitation was accepted.
|
|||
|
* @param optionalPin PIN of the reply, or {@code null} if none was supplied.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
public void replyToP2pInvitationReceivedDialog(
|
|||
|
int dialogId, boolean accepted, @Nullable String optionalPin) {
|
|||
|
if (mVerboseLoggingEnabled) {
|
|||
|
Log.v(TAG, "replyToP2pInvitationReceivedDialog: "
|
|||
|
+ "dialogId=" + dialogId
|
|||
|
+ ", accepted=" + accepted
|
|||
|
+ ", pin=" + optionalPin);
|
|||
|
}
|
|||
|
try {
|
|||
|
mService.replyToP2pInvitationReceivedDialog(dialogId, accepted, optionalPin);
|
|||
|
} catch (RemoteException e) {
|
|||
|
throw e.rethrowFromSystemServer();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Specify a list of DHCP options to use for any network whose SSID is specified and which
|
|||
|
* transmits vendor-specific information elements (VSIEs) using the specified Organizationally
|
|||
|
* Unique Identifier (OUI). If the AP transmits VSIEs for multiple specified OUIs then all
|
|||
|
* matching DHCP options will be used. The allowlist for DHCP options in
|
|||
|
* {@link android.net.ip.IpClient} gates whether the DHCP options will actually be used.
|
|||
|
* When DHCP options are used: if the option value {@link android.net.DhcpOption#getValue()}
|
|||
|
* is null, the option type {@link android.net.DhcpOption#getType()} will be put in the
|
|||
|
* Parameter Request List in the DHCP packets; otherwise, the option will be included in the
|
|||
|
* options section in the DHCP packets. Use {@link #removeCustomDhcpOptions(Object, Object)}
|
|||
|
* to remove the specified DHCP options.
|
|||
|
*
|
|||
|
* @param ssid the network SSID.
|
|||
|
* @param oui the 3-byte OUI.
|
|||
|
* @param options the list of {@link android.net.DhcpOption}.
|
|||
|
*
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
|
|||
|
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
|
|||
|
@RequiresPermission(anyOf = {
|
|||
|
android.Manifest.permission.NETWORK_SETTINGS,
|
|||
|
android.Manifest.permission.OVERRIDE_WIFI_CONFIG
|
|||
|
})
|
|||
|
public void addCustomDhcpOptions(@NonNull WifiSsid ssid, @NonNull byte[] oui,
|
|||
|
@NonNull List<DhcpOption> options) {
|
|||
|
if (mVerboseLoggingEnabled) {
|
|||
|
Log.v(TAG, "addCustomDhcpOptions: ssid="
|
|||
|
+ ssid + ", oui=" + Arrays.toString(oui) + ", options=" + options);
|
|||
|
}
|
|||
|
try {
|
|||
|
mService.addCustomDhcpOptions(ssid, oui, options);
|
|||
|
} catch (RemoteException e) {
|
|||
|
throw e.rethrowFromSystemServer();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Remove custom DHCP options specified by {@link #addCustomDhcpOptions(Object, Object, List)}.
|
|||
|
*
|
|||
|
* @param ssid the network SSID.
|
|||
|
* @param oui the 3-byte OUI.
|
|||
|
*
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
|
|||
|
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
|
|||
|
@RequiresPermission(anyOf = {
|
|||
|
android.Manifest.permission.NETWORK_SETTINGS,
|
|||
|
android.Manifest.permission.OVERRIDE_WIFI_CONFIG
|
|||
|
})
|
|||
|
public void removeCustomDhcpOptions(@NonNull WifiSsid ssid, @NonNull byte[] oui) {
|
|||
|
if (mVerboseLoggingEnabled) {
|
|||
|
Log.v(TAG, "removeCustomDhcpOptions: ssid=" + ssid + ", oui=" + Arrays.toString(oui));
|
|||
|
}
|
|||
|
try {
|
|||
|
mService.removeCustomDhcpOptions(ssid, oui);
|
|||
|
} catch (RemoteException e) {
|
|||
|
throw e.rethrowFromSystemServer();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Wi-Fi interface of type STA (station/client Wi-Fi infrastructure device).
|
|||
|
*/
|
|||
|
public static final int WIFI_INTERFACE_TYPE_STA = 0;
|
|||
|
|
|||
|
/**
|
|||
|
* Wi-Fi interface of type AP (access point Wi-Fi infrastructure device).
|
|||
|
*/
|
|||
|
public static final int WIFI_INTERFACE_TYPE_AP = 1;
|
|||
|
|
|||
|
/**
|
|||
|
* Wi-Fi interface of type Wi-Fi Aware (aka NAN).
|
|||
|
*/
|
|||
|
public static final int WIFI_INTERFACE_TYPE_AWARE = 2;
|
|||
|
|
|||
|
/**
|
|||
|
* Wi-Fi interface of type Wi-Fi Direct (aka P2P).
|
|||
|
*/
|
|||
|
public static final int WIFI_INTERFACE_TYPE_DIRECT = 3;
|
|||
|
|
|||
|
/** @hide */
|
|||
|
@IntDef(prefix = { "WIFI_INTERFACE_TYPE_" }, value = {
|
|||
|
WIFI_INTERFACE_TYPE_STA,
|
|||
|
WIFI_INTERFACE_TYPE_AP,
|
|||
|
WIFI_INTERFACE_TYPE_AWARE,
|
|||
|
WIFI_INTERFACE_TYPE_DIRECT,
|
|||
|
})
|
|||
|
@Retention(RetentionPolicy.SOURCE)
|
|||
|
public @interface WifiInterfaceType {}
|
|||
|
|
|||
|
/**
|
|||
|
* Class describing an impact of interface creation - returned by
|
|||
|
* {@link #reportCreateInterfaceImpact(int, boolean, Executor, BiConsumer)}. Due to Wi-Fi
|
|||
|
* concurrency limitations certain interfaces may have to be torn down. Each of these
|
|||
|
* interfaces was requested by a set of applications who could potentially be impacted.
|
|||
|
*
|
|||
|
* This class contain the information for a single interface: the interface type with
|
|||
|
* {@link InterfaceCreationImpact#getInterfaceType()} and the set of impacted packages
|
|||
|
* with {@link InterfaceCreationImpact#getPackages()}.
|
|||
|
*/
|
|||
|
public static class InterfaceCreationImpact {
|
|||
|
private final int mInterfaceType;
|
|||
|
private final Set<String> mPackages;
|
|||
|
|
|||
|
public InterfaceCreationImpact(@WifiInterfaceType int interfaceType,
|
|||
|
@NonNull Set<String> packages) {
|
|||
|
mInterfaceType = interfaceType;
|
|||
|
mPackages = packages;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* @return The interface type which will be torn down to make room for the interface
|
|||
|
* requested in {@link #reportCreateInterfaceImpact(int, boolean, Executor, BiConsumer)}.
|
|||
|
*/
|
|||
|
public @WifiInterfaceType int getInterfaceType() {
|
|||
|
return mInterfaceType;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* @return The list of potentially impacted packages due to tearing down the interface
|
|||
|
* specified in {@link #getInterfaceType()}.
|
|||
|
*/
|
|||
|
public @NonNull Set<String> getPackages() {
|
|||
|
return mPackages;
|
|||
|
}
|
|||
|
|
|||
|
@Override
|
|||
|
public int hashCode() {
|
|||
|
return Objects.hash(mInterfaceType, mPackages);
|
|||
|
}
|
|||
|
|
|||
|
@Override
|
|||
|
public boolean equals(Object that) {
|
|||
|
if (this == that) return true;
|
|||
|
if (!(that instanceof InterfaceCreationImpact)) return false;
|
|||
|
InterfaceCreationImpact thatInterfaceCreationImpact = (InterfaceCreationImpact) that;
|
|||
|
|
|||
|
return this.mInterfaceType == thatInterfaceCreationImpact.mInterfaceType
|
|||
|
&& Objects.equals(this.mPackages, thatInterfaceCreationImpact.mPackages);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Queries the framework to determine whether the specified interface can be created, and if
|
|||
|
* so - what other interfaces would be torn down by the framework to allow this creation if
|
|||
|
* it were requested. The result is returned via the specified {@link BiConsumer} callback
|
|||
|
* which returns two arguments:
|
|||
|
* <li>First argument: a {@code boolean} - indicating whether or not the interface can be
|
|||
|
* created.</li>
|
|||
|
* <li>Second argument: a {@code Set<InterfaceCreationImpact>} - if the interface can be
|
|||
|
* created (first argument is {@code true} then this is the set of interface types which
|
|||
|
* will be removed and the packages which requested them. Possibly an empty set. If the
|
|||
|
* first argument is {@code false}, then an empty set will be returned here.</li>
|
|||
|
* <p>
|
|||
|
* Interfaces, input and output, are specified using the {@code WIFI_INTERFACE_*} constants:
|
|||
|
* {@link #WIFI_INTERFACE_TYPE_STA}, {@link #WIFI_INTERFACE_TYPE_AP},
|
|||
|
* {@link #WIFI_INTERFACE_TYPE_AWARE}, or {@link #WIFI_INTERFACE_TYPE_DIRECT}.
|
|||
|
* <p>
|
|||
|
* This method does not actually create the interface. That operation is handled by the
|
|||
|
* framework when a particular service method is called. E.g. a Wi-Fi Direct interface may be
|
|||
|
* created when various methods of {@link android.net.wifi.p2p.WifiP2pManager} are called,
|
|||
|
* similarly for Wi-Fi Aware and {@link android.net.wifi.aware.WifiAwareManager}.
|
|||
|
* <p>
|
|||
|
* Note: the information returned via this method is the current snapshot of the system. It may
|
|||
|
* change due to actions of the framework or other apps.
|
|||
|
*
|
|||
|
* @param interfaceType The interface type whose possible creation is being queried.
|
|||
|
* @param requireNewInterface Indicates that the query is for a new interface of the specified
|
|||
|
* type - an existing interface won't meet the query. Some
|
|||
|
* operations (such as Wi-Fi Direct and Wi-Fi Aware are a shared
|
|||
|
* resource and so may not need a new interface).
|
|||
|
* @param executor An {@link Executor} on which to return the result.
|
|||
|
* @param resultCallback The asynchronous callback which will return two argument: a
|
|||
|
* {@code boolean} (whether the interface can be created), and a
|
|||
|
* {@code Set<InterfaceCreationImpact>} (a set of {@link InterfaceCreationImpact}:
|
|||
|
* interfaces which will be destroyed when the interface is created
|
|||
|
* and the packages which requested them and thus may be impacted).
|
|||
|
*/
|
|||
|
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
|
|||
|
@RequiresPermission(allOf = {android.Manifest.permission.MANAGE_WIFI_INTERFACES,
|
|||
|
ACCESS_WIFI_STATE})
|
|||
|
public void reportCreateInterfaceImpact(@WifiInterfaceType int interfaceType,
|
|||
|
boolean requireNewInterface,
|
|||
|
@NonNull @CallbackExecutor Executor executor,
|
|||
|
@NonNull BiConsumer<Boolean, Set<InterfaceCreationImpact>> resultCallback) {
|
|||
|
Objects.requireNonNull(executor, "Non-null executor required");
|
|||
|
Objects.requireNonNull(resultCallback, "Non-null resultCallback required");
|
|||
|
try {
|
|||
|
mService.reportCreateInterfaceImpact(mContext.getOpPackageName(), interfaceType,
|
|||
|
requireNewInterface, new IInterfaceCreationInfoCallback.Stub() {
|
|||
|
@Override
|
|||
|
public void onResults(boolean canCreate, int[] interfacesToDelete,
|
|||
|
String[] packagesForInterfaces) {
|
|||
|
Binder.clearCallingIdentity();
|
|||
|
if ((interfacesToDelete == null && packagesForInterfaces != null)
|
|||
|
|| (interfacesToDelete != null
|
|||
|
&& packagesForInterfaces == null) || (canCreate && (
|
|||
|
interfacesToDelete == null || interfacesToDelete.length
|
|||
|
!= packagesForInterfaces.length))) {
|
|||
|
Log.e(TAG,
|
|||
|
"reportImpactToCreateIfaceRequest: Invalid callback "
|
|||
|
+ "parameters - canCreate="
|
|||
|
+ canCreate + ", interfacesToDelete="
|
|||
|
+ Arrays.toString(interfacesToDelete)
|
|||
|
+ ", worksourcesForInterfaces="
|
|||
|
+ Arrays.toString(packagesForInterfaces));
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
final Set<InterfaceCreationImpact> finalSet =
|
|||
|
(canCreate && interfacesToDelete.length > 0) ? new ArraySet<>()
|
|||
|
: Collections.emptySet();
|
|||
|
if (canCreate) {
|
|||
|
for (int i = 0; i < interfacesToDelete.length; ++i) {
|
|||
|
finalSet.add(
|
|||
|
new InterfaceCreationImpact(interfacesToDelete[i],
|
|||
|
packagesForInterfaces[i] == null
|
|||
|
? Collections.emptySet()
|
|||
|
: new ArraySet<>(
|
|||
|
packagesForInterfaces[i]
|
|||
|
.split(","))));
|
|||
|
}
|
|||
|
}
|
|||
|
executor.execute(() -> resultCallback.accept(canCreate, finalSet));
|
|||
|
}
|
|||
|
});
|
|||
|
} catch (RemoteException e) {
|
|||
|
throw e.rethrowFromSystemServer();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Returns the max number of channels that is allowed to be set on a
|
|||
|
* {@link WifiNetworkSpecifier}.
|
|||
|
* @see WifiNetworkSpecifier.Builder#setPreferredChannelsFrequenciesMhz(int[])
|
|||
|
*
|
|||
|
* @return The max number of channels can be set on a request.
|
|||
|
*/
|
|||
|
|
|||
|
public int getMaxNumberOfChannelsPerNetworkSpecifierRequest() {
|
|||
|
try {
|
|||
|
return mService.getMaxNumberOfChannelsPerRequest();
|
|||
|
} catch (RemoteException e) {
|
|||
|
throw e.rethrowFromSystemServer();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Add a list of new application-initiated QoS policies.
|
|||
|
*
|
|||
|
* Note: Policies are managed using a policy ID, which can be retrieved using
|
|||
|
* {@link QosPolicyParams#getPolicyId()}. This ID can be used when removing a policy via
|
|||
|
* {@link #removeQosPolicies(int[])}. The caller is in charge of assigning and managing
|
|||
|
* the policy IDs for any requested policies.
|
|||
|
*
|
|||
|
* Note: Policies with duplicate IDs are not allowed. To update an existing policy, first
|
|||
|
* remove it using {@link #removeQosPolicies(int[])}, and then re-add it using this API.
|
|||
|
*
|
|||
|
* Note: All policies in a single request must have the same {@link QosPolicyParams.Direction}.
|
|||
|
*
|
|||
|
* Note: Support for the {@link QosPolicyParams#DIRECTION_UPLINK} direction is added in
|
|||
|
* {@link android.os.Build.VERSION_CODES#VANILLA_ICE_CREAM}. For earlier releases,
|
|||
|
* only the {@link QosPolicyParams#DIRECTION_DOWNLINK} direction is supported.
|
|||
|
*
|
|||
|
* @param policyParamsList List of {@link QosPolicyParams} objects describing the requested
|
|||
|
* policies. Must have a maximum length of
|
|||
|
* {@link #getMaxNumberOfPoliciesPerQosRequest()}.
|
|||
|
* @param executor The executor on which callback will be invoked.
|
|||
|
* @param resultsCallback An asynchronous callback that will return a list of integer status
|
|||
|
* codes from {@link QosRequestStatus}. Result list will be the same
|
|||
|
* length as the input list, and each status code will correspond to
|
|||
|
* the policy at that index in the input list.
|
|||
|
*
|
|||
|
* @throws SecurityException if caller does not have the required permissions.
|
|||
|
* @throws NullPointerException if the caller provided a null input.
|
|||
|
* @throws UnsupportedOperationException if the feature is not enabled.
|
|||
|
* @throws IllegalArgumentException if the input list is invalid.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
@RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
|
|||
|
@RequiresPermission(anyOf = {
|
|||
|
android.Manifest.permission.NETWORK_SETTINGS,
|
|||
|
MANAGE_WIFI_NETWORK_SELECTION
|
|||
|
})
|
|||
|
public void addQosPolicies(@NonNull List<QosPolicyParams> policyParamsList,
|
|||
|
@NonNull @CallbackExecutor Executor executor,
|
|||
|
@NonNull Consumer<List<Integer>> resultsCallback) {
|
|||
|
Objects.requireNonNull(policyParamsList, "policyParamsList cannot be null");
|
|||
|
Objects.requireNonNull(executor, "executor cannot be null");
|
|||
|
Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null");
|
|||
|
try {
|
|||
|
mService.addQosPolicies(policyParamsList, new Binder(), mContext.getOpPackageName(),
|
|||
|
new IListListener.Stub() {
|
|||
|
@Override
|
|||
|
public void onResult(List value) {
|
|||
|
Binder.clearCallingIdentity();
|
|||
|
executor.execute(() -> {
|
|||
|
resultsCallback.accept(value);
|
|||
|
});
|
|||
|
}
|
|||
|
});
|
|||
|
} catch (RemoteException e) {
|
|||
|
throw e.rethrowFromSystemServer();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Remove a list of existing application-initiated QoS policies, previously added via
|
|||
|
* {@link #addQosPolicies(List, Executor, Consumer)}.
|
|||
|
*
|
|||
|
* Note: Policies are identified by their policy IDs, which are assigned by the caller. The ID
|
|||
|
* for a given policy can be retrieved using {@link QosPolicyParams#getPolicyId()}.
|
|||
|
*
|
|||
|
* @param policyIdList List of policy IDs corresponding to the policies to remove. Must have
|
|||
|
* a maximum length of {@link #getMaxNumberOfPoliciesPerQosRequest()}.
|
|||
|
* @throws SecurityException if caller does not have the required permissions.
|
|||
|
* @throws NullPointerException if the caller provided a null input.
|
|||
|
* @throws IllegalArgumentException if the input list is invalid.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
@RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
|
|||
|
@RequiresPermission(anyOf = {
|
|||
|
android.Manifest.permission.NETWORK_SETTINGS,
|
|||
|
MANAGE_WIFI_NETWORK_SELECTION
|
|||
|
})
|
|||
|
public void removeQosPolicies(@NonNull int[] policyIdList) {
|
|||
|
Objects.requireNonNull(policyIdList, "policyIdList cannot be null");
|
|||
|
try {
|
|||
|
mService.removeQosPolicies(policyIdList, mContext.getOpPackageName());
|
|||
|
} catch (RemoteException e) {
|
|||
|
throw e.rethrowFromSystemServer();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Remove all application-initiated QoS policies requested by this caller,
|
|||
|
* previously added via {@link #addQosPolicies(List, Executor, Consumer)}.
|
|||
|
*
|
|||
|
* @throws SecurityException if caller does not have the required permissions.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
@RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
|
|||
|
@RequiresPermission(anyOf = {
|
|||
|
android.Manifest.permission.NETWORK_SETTINGS,
|
|||
|
MANAGE_WIFI_NETWORK_SELECTION
|
|||
|
})
|
|||
|
public void removeAllQosPolicies() {
|
|||
|
try {
|
|||
|
mService.removeAllQosPolicies(mContext.getOpPackageName());
|
|||
|
} catch (RemoteException e) {
|
|||
|
throw e.rethrowFromSystemServer();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Set the link layer stats polling interval, in milliseconds.
|
|||
|
*
|
|||
|
* @param intervalMs a non-negative integer, for the link layer stats polling interval
|
|||
|
* in milliseconds.
|
|||
|
* To set a fixed interval, use a positive value.
|
|||
|
* For automatic handling of the interval, use value 0
|
|||
|
* @throws UnsupportedOperationException if the API is not supported on this SDK version.
|
|||
|
* @throws SecurityException if the caller does not have permission.
|
|||
|
* @throws IllegalArgumentException if input is invalid.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
|
|||
|
@RequiresPermission(android.Manifest.permission.MANAGE_WIFI_NETWORK_SELECTION)
|
|||
|
public void setLinkLayerStatsPollingInterval(@IntRange (from = 0) int intervalMs) {
|
|||
|
try {
|
|||
|
mService.setLinkLayerStatsPollingInterval(intervalMs);
|
|||
|
} catch (RemoteException e) {
|
|||
|
throw e.rethrowFromSystemServer();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Get the link layer stats polling interval, in milliseconds.
|
|||
|
*
|
|||
|
* @param executor The executor on which callback will be invoked.
|
|||
|
* @param resultsCallback An asynchronous callback that will return current
|
|||
|
* link layer stats polling interval in milliseconds.
|
|||
|
*
|
|||
|
* @throws UnsupportedOperationException if the API is not supported on this SDK version.
|
|||
|
* @throws SecurityException if the caller does not have permission.
|
|||
|
* @throws NullPointerException if the caller provided invalid inputs.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
|
|||
|
@RequiresPermission(android.Manifest.permission.MANAGE_WIFI_NETWORK_SELECTION)
|
|||
|
public void getLinkLayerStatsPollingInterval(@NonNull @CallbackExecutor Executor executor,
|
|||
|
@NonNull Consumer<Integer> resultsCallback) {
|
|||
|
Objects.requireNonNull(executor, "executor cannot be null");
|
|||
|
Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null");
|
|||
|
try {
|
|||
|
mService.getLinkLayerStatsPollingInterval(
|
|||
|
new IIntegerListener.Stub() {
|
|||
|
@Override
|
|||
|
public void onResult(int value) {
|
|||
|
Binder.clearCallingIdentity();
|
|||
|
executor.execute(() -> {
|
|||
|
resultsCallback.accept(value);
|
|||
|
});
|
|||
|
}
|
|||
|
});
|
|||
|
} catch (RemoteException e) {
|
|||
|
throw e.rethrowFromSystemServer();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* This API allows a privileged application to set Multi-Link Operation mode.
|
|||
|
*
|
|||
|
* Multi-link operation (MLO) will allow Wi-Fi devices to operate on multiple links at the same
|
|||
|
* time through a single connection, aiming to support applications that require lower latency,
|
|||
|
* and higher capacity. Chip vendors have algorithms that run on the chip to use available links
|
|||
|
* based on incoming traffic and various inputs. This API allows system application to give a
|
|||
|
* suggestion to such algorithms on its preference using {@link MloMode}.
|
|||
|
*
|
|||
|
*
|
|||
|
* @param mode Refer {@link MloMode} for supported modes.
|
|||
|
* @param executor The executor on which callback will be invoked.
|
|||
|
* @param resultsCallback An asynchronous callback that will return {@code Boolean} indicating
|
|||
|
* whether the MLO mode is successfully set or not.
|
|||
|
* @throws IllegalArgumentException if mode value is not in {@link MloMode}.
|
|||
|
* @throws NullPointerException if the caller provided a null input.
|
|||
|
* @throws SecurityException if caller does not have the required permissions.
|
|||
|
* @throws UnsupportedOperationException if the set operation is not supported on this SDK.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
@RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
|
|||
|
@RequiresPermission(MANAGE_WIFI_NETWORK_SELECTION)
|
|||
|
public void setMloMode(@MloMode int mode, @NonNull @CallbackExecutor Executor executor,
|
|||
|
@NonNull Consumer<Boolean> resultsCallback) {
|
|||
|
|
|||
|
if (mode < MLO_MODE_DEFAULT || mode > MLO_MODE_LOW_POWER) {
|
|||
|
throw new IllegalArgumentException("invalid mode: " + mode);
|
|||
|
}
|
|||
|
Objects.requireNonNull(executor, "executor cannot be null");
|
|||
|
Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null");
|
|||
|
try {
|
|||
|
mService.setMloMode(mode, new IBooleanListener.Stub() {
|
|||
|
@Override
|
|||
|
public void onResult(boolean value) {
|
|||
|
Binder.clearCallingIdentity();
|
|||
|
executor.execute(() -> {
|
|||
|
resultsCallback.accept(value);
|
|||
|
});
|
|||
|
}
|
|||
|
});
|
|||
|
} catch (RemoteException e) {
|
|||
|
throw e.rethrowFromSystemServer();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* This API allows a privileged application to get Multi-Link Operation mode. Refer
|
|||
|
* {@link WifiManager#setMloMode(int, Executor, Consumer)} for more details.
|
|||
|
*
|
|||
|
* @param executor The executor on which callback will be invoked.
|
|||
|
* @param resultsCallback An asynchronous callback that will return current MLO mode. Returns
|
|||
|
* {@link MloMode#MLO_MODE_DEFAULT} if information is not available,
|
|||
|
* e.g. if the driver/firmware doesn't provide this information.
|
|||
|
* @throws NullPointerException if the caller provided a null input.
|
|||
|
* @throws SecurityException if caller does not have the required permissions.
|
|||
|
* @throws UnsupportedOperationException if the get operation is not supported on this SDK.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
@RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
|
|||
|
@RequiresPermission(MANAGE_WIFI_NETWORK_SELECTION)
|
|||
|
public void getMloMode(@NonNull @CallbackExecutor Executor executor,
|
|||
|
@NonNull Consumer<Integer> resultsCallback) {
|
|||
|
Objects.requireNonNull(executor, "executor cannot be null");
|
|||
|
Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null");
|
|||
|
try {
|
|||
|
mService.getMloMode(new IIntegerListener.Stub() {
|
|||
|
@Override
|
|||
|
public void onResult(int value) {
|
|||
|
Binder.clearCallingIdentity();
|
|||
|
executor.execute(() -> {
|
|||
|
resultsCallback.accept(value);
|
|||
|
});
|
|||
|
}
|
|||
|
});
|
|||
|
} catch (RemoteException e) {
|
|||
|
throw e.rethrowFromSystemServer();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Get the maximum number of links supported by the chip for MLO association. e.g. if the Wi-Fi
|
|||
|
* chip supports eMLSR (Enhanced Multi-Link Single Radio) and STR (Simultaneous Transmit and
|
|||
|
* Receive) with following capabilities,
|
|||
|
* - Max MLO assoc link count = 3.
|
|||
|
* - Max MLO STR link count = 2. See
|
|||
|
* {@link WifiManager#getMaxMloStrLinkCount(Executor, Consumer)}
|
|||
|
* One of the possible configuration is - STR (2.4 GHz , eMLSR(5 GHz, 6 GHz)), provided the
|
|||
|
* radio combination of the chip supports it.
|
|||
|
*
|
|||
|
* @param executor The executor on which callback will be invoked.
|
|||
|
* @param resultsCallback An asynchronous callback that will return maximum MLO association link
|
|||
|
* count supported by the chip or -1 if error or not available.
|
|||
|
* @throws NullPointerException if the caller provided a null input.
|
|||
|
* @throws SecurityException if caller does not have the required permissions.
|
|||
|
* @throws UnsupportedOperationException if the get operation is not supported on this SDK.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|||
|
@RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
|
|||
|
@RequiresPermission(MANAGE_WIFI_NETWORK_SELECTION)
|
|||
|
public void getMaxMloAssociationLinkCount(@NonNull @CallbackExecutor Executor executor,
|
|||
|
@NonNull Consumer<Integer> resultsCallback) {
|
|||
|
Objects.requireNonNull(executor, "executor cannot be null");
|
|||
|
Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null");
|
|||
|
try {
|
|||
|
Bundle extras = new Bundle();
|
|||
|
if (SdkLevel.isAtLeastS()) {
|
|||
|
extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE,
|
|||
|
mContext.getAttributionSource());
|
|||
|
}
|
|||
|
mService.getMaxMloAssociationLinkCount(new IIntegerListener.Stub() {
|
|||
|
@Override
|
|||
|
public void onResult(int value) {
|
|||
|
Binder.clearCallingIdentity();
|
|||
|
executor.execute(() -> {
|
|||
|
resultsCallback.accept(value);
|
|||
|
});
|
|||
|
}
|
|||
|
}, extras);
|
|||
|
} catch (RemoteException e) {
|
|||
|
throw e.rethrowFromSystemServer();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Get the maximum number of STR links used in Multi-Link Operation. The maximum number of STR
|
|||
|
* links used for MLO can be different from the number of radios supported by the chip. e.g. if
|
|||
|
* the Wi-Fi chip supports eMLSR (Enhanced Multi-Link Single Radio) and STR (Simultaneous
|
|||
|
* Transmit and Receive) with following capabilities,
|
|||
|
* - Max MLO assoc link count = 3. See
|
|||
|
* {@link WifiManager#getMaxMloAssociationLinkCount(Executor, Consumer)}.
|
|||
|
* - Max MLO STR link count = 2.
|
|||
|
* One of the possible configuration is - STR (2.4 GHz, eMLSR(5 GHz, 6 GHz)), provided the radio
|
|||
|
* combination of the chip supports it.
|
|||
|
*
|
|||
|
* @param executor The executor on which callback will be invoked.
|
|||
|
* @param resultsCallback An asynchronous callback that will return maximum STR link count
|
|||
|
* supported by the chip in MLO mode or -1 if error or not available.
|
|||
|
* @throws NullPointerException if the caller provided a null input.
|
|||
|
* @throws SecurityException if caller does not have the required permissions.
|
|||
|
* @throws UnsupportedOperationException if the get operation is not supported on this SDK
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|||
|
@RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
|
|||
|
@RequiresPermission(MANAGE_WIFI_NETWORK_SELECTION)
|
|||
|
public void getMaxMloStrLinkCount(@NonNull @CallbackExecutor Executor executor,
|
|||
|
@NonNull Consumer<Integer> resultsCallback) {
|
|||
|
Objects.requireNonNull(executor, "executor cannot be null");
|
|||
|
Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null");
|
|||
|
try {
|
|||
|
Bundle extras = new Bundle();
|
|||
|
if (SdkLevel.isAtLeastS()) {
|
|||
|
extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE,
|
|||
|
mContext.getAttributionSource());
|
|||
|
}
|
|||
|
mService.getMaxMloStrLinkCount(new IIntegerListener.Stub() {
|
|||
|
@Override
|
|||
|
public void onResult(int value) {
|
|||
|
Binder.clearCallingIdentity();
|
|||
|
executor.execute(() -> {
|
|||
|
resultsCallback.accept(value);
|
|||
|
});
|
|||
|
}
|
|||
|
}, extras);
|
|||
|
} catch (RemoteException e) {
|
|||
|
throw e.rethrowFromSystemServer();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Get the set of band combinations supported simultaneously by the Wi-Fi Chip.
|
|||
|
*
|
|||
|
* Note: This method returns simultaneous band operation combination and not multichannel
|
|||
|
* concurrent operation (MCC) combination.
|
|||
|
*
|
|||
|
* @param executor The executor on which callback will be invoked.
|
|||
|
* @param resultsCallback An asynchronous callback that will return a list of possible
|
|||
|
* simultaneous band combinations supported by the chip or empty list if
|
|||
|
* not available. Band value is defined in {@link WifiScanner.WifiBand}.
|
|||
|
* @throws NullPointerException if the caller provided a null input.
|
|||
|
* @throws SecurityException if caller does not have the required permissions.
|
|||
|
* @throws UnsupportedOperationException if the get operation is not supported on this SDK.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|||
|
@RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
|
|||
|
@RequiresPermission(MANAGE_WIFI_NETWORK_SELECTION)
|
|||
|
public void getSupportedSimultaneousBandCombinations(
|
|||
|
@NonNull @CallbackExecutor Executor executor,
|
|||
|
@NonNull Consumer<List<int[]>> resultsCallback) {
|
|||
|
Objects.requireNonNull(executor, "executor cannot be null");
|
|||
|
Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null");
|
|||
|
try {
|
|||
|
Bundle extras = new Bundle();
|
|||
|
if (SdkLevel.isAtLeastS()) {
|
|||
|
extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE,
|
|||
|
mContext.getAttributionSource());
|
|||
|
}
|
|||
|
mService.getSupportedSimultaneousBandCombinations(new IWifiBandsListener.Stub() {
|
|||
|
@Override
|
|||
|
public void onResult(WifiBands[] supportedBands) {
|
|||
|
Binder.clearCallingIdentity();
|
|||
|
List<int[]> bandCombinations = new ArrayList<>();
|
|||
|
for (WifiBands wifiBands : supportedBands) {
|
|||
|
bandCombinations.add(wifiBands.bands);
|
|||
|
}
|
|||
|
executor.execute(() -> {
|
|||
|
resultsCallback.accept(bandCombinations);
|
|||
|
});
|
|||
|
}
|
|||
|
}, extras);
|
|||
|
} catch (RemoteException e) {
|
|||
|
throw e.rethrowFromSystemServer();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* This API allows a privileged application to set whether or not this device allows
|
|||
|
* connections to Wi-Fi WEP networks.
|
|||
|
*
|
|||
|
* Note: The WEP connections may not work even if caller invokes this method with {@code true}
|
|||
|
* because device may NOT support connections to Wi-Fi WEP networks.
|
|||
|
* See: {@link #isWepSupported()}.
|
|||
|
*
|
|||
|
* @param isAllowed whether or not the user allow connections to Wi-Fi WEP networks.
|
|||
|
* @throws SecurityException if the caller does not have permission.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|||
|
@SystemApi
|
|||
|
@RequiresPermission(anyOf = {
|
|||
|
android.Manifest.permission.NETWORK_SETTINGS,
|
|||
|
android.Manifest.permission.NETWORK_SETUP_WIZARD
|
|||
|
})
|
|||
|
public void setWepAllowed(boolean isAllowed) {
|
|||
|
try {
|
|||
|
mService.setWepAllowed(isAllowed);
|
|||
|
} catch (RemoteException e) {
|
|||
|
throw e.rethrowFromSystemServer();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Query whether or not this device is configured to allow connections to Wi-Fi WEP networks.
|
|||
|
* @see #setWepAllowed(boolean)
|
|||
|
*
|
|||
|
* Note: The WEP connections may not work even if this method returns {@code true} in the
|
|||
|
* result callback because device may NOT support connections to Wi-Fi WEP networks.
|
|||
|
* See: {@link #isWepSupported()}.
|
|||
|
*
|
|||
|
* @param executor The executor on which callback will be invoked.
|
|||
|
* @param resultsCallback An asynchronous callback that will return {@code Boolean} indicating
|
|||
|
* whether wep network support is enabled/disabled.
|
|||
|
*
|
|||
|
* @throws SecurityException if the caller does not have permission.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|||
|
@SystemApi
|
|||
|
@RequiresPermission(anyOf = {
|
|||
|
android.Manifest.permission.NETWORK_SETTINGS,
|
|||
|
android.Manifest.permission.NETWORK_SETUP_WIZARD
|
|||
|
})
|
|||
|
public void queryWepAllowed(@NonNull @CallbackExecutor Executor executor,
|
|||
|
@NonNull Consumer<Boolean> resultsCallback) {
|
|||
|
Objects.requireNonNull(executor, "executor cannot be null");
|
|||
|
Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null");
|
|||
|
try {
|
|||
|
mService.queryWepAllowed(
|
|||
|
new IBooleanListener.Stub() {
|
|||
|
@Override
|
|||
|
public void onResult(boolean value) {
|
|||
|
Binder.clearCallingIdentity();
|
|||
|
executor.execute(() -> {
|
|||
|
resultsCallback.accept(value);
|
|||
|
});
|
|||
|
}
|
|||
|
});
|
|||
|
} catch (RemoteException e) {
|
|||
|
throw e.rethrowFromSystemServer();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Enable Mirrored Stream Classification Service (MSCS) and configure using
|
|||
|
* the provided configuration values.
|
|||
|
*
|
|||
|
* If MSCS has already been enabled/configured, this will override the
|
|||
|
* existing configuration.
|
|||
|
*
|
|||
|
* Refer to Section 11.25.3 of the IEEE 802.11-2020 standard for more information.
|
|||
|
*
|
|||
|
* @param mscsParams {@link MscsParams} object containing the configuration parameters.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
@RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
|
|||
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|||
|
@RequiresPermission(anyOf = {MANAGE_WIFI_NETWORK_SELECTION})
|
|||
|
public void enableMscs(@NonNull MscsParams mscsParams) {
|
|||
|
Objects.requireNonNull(mscsParams);
|
|||
|
try {
|
|||
|
mService.enableMscs(mscsParams);
|
|||
|
} catch (RemoteException e) {
|
|||
|
throw e.rethrowFromSystemServer();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Disable Mirrored Stream Classification Service (MSCS).
|
|||
|
*
|
|||
|
* If MSCS is enabled/configured, this will send a remove request to the AP.
|
|||
|
*
|
|||
|
* Refer to Section 11.25.3 of the IEEE 802.11-2020 standard for more information.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
@RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
|
|||
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|||
|
@RequiresPermission(anyOf = {MANAGE_WIFI_NETWORK_SELECTION})
|
|||
|
public void disableMscs() {
|
|||
|
try {
|
|||
|
mService.disableMscs();
|
|||
|
} catch (RemoteException e) {
|
|||
|
throw e.rethrowFromSystemServer();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Do not send the DHCP hostname to open networks.
|
|||
|
*/
|
|||
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|||
|
public static final int FLAG_SEND_DHCP_HOSTNAME_RESTRICTION_OPEN = 1 << 0;
|
|||
|
|
|||
|
/**
|
|||
|
* Do not send the DHCP hostname to secure network.
|
|||
|
*/
|
|||
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|||
|
public static final int FLAG_SEND_DHCP_HOSTNAME_RESTRICTION_SECURE = 1 << 1;
|
|||
|
|
|||
|
/** @hide */
|
|||
|
@IntDef(flag = true, prefix = { "FLAG_SEND_DHCP_HOSTNAME_RESTRICTION_" }, value = {
|
|||
|
FLAG_SEND_DHCP_HOSTNAME_RESTRICTION_OPEN,
|
|||
|
FLAG_SEND_DHCP_HOSTNAME_RESTRICTION_SECURE,
|
|||
|
})
|
|||
|
@Retention(RetentionPolicy.SOURCE)
|
|||
|
public @interface SendDhcpHostnameRestriction {}
|
|||
|
|
|||
|
/**
|
|||
|
* Sets the global restrictions on which networks to send the device hostname to during DHCP.
|
|||
|
*
|
|||
|
* @param restriction Bitmask of {@link SendDhcpHostnameRestriction}, or none to indicate no
|
|||
|
* restriction.
|
|||
|
* @throws IllegalArgumentException if input is invalid
|
|||
|
* @throws SecurityException if the calling app is not a Device Owner (DO), or a privileged app
|
|||
|
* that has one of the permissions required by this API.
|
|||
|
*/
|
|||
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|||
|
@RequiresPermission(anyOf = {
|
|||
|
android.Manifest.permission.NETWORK_SETTINGS,
|
|||
|
android.Manifest.permission.NETWORK_SETUP_WIZARD
|
|||
|
})
|
|||
|
public void setSendDhcpHostnameRestriction(@SendDhcpHostnameRestriction int restriction) {
|
|||
|
try {
|
|||
|
mService.setSendDhcpHostnameRestriction(mContext.getOpPackageName(), restriction);
|
|||
|
} catch (RemoteException e) {
|
|||
|
throw e.rethrowFromSystemServer();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Query the global restriction on which networks to send the device hostname to during DHCP.
|
|||
|
* @see #setSendDhcpHostnameRestriction(int)
|
|||
|
*
|
|||
|
* @param executor The executor on which callback will be invoked.
|
|||
|
* @param resultsCallback An asynchronous callback that will return a bitmask of
|
|||
|
* {@link SendDhcpHostnameRestriction}.
|
|||
|
*
|
|||
|
* @throws SecurityException if the calling app is not a Device Owner (DO), or a privileged app
|
|||
|
* that has one of the permissions required by this API.
|
|||
|
*/
|
|||
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|||
|
@RequiresPermission(anyOf = {
|
|||
|
android.Manifest.permission.NETWORK_SETTINGS,
|
|||
|
android.Manifest.permission.NETWORK_SETUP_WIZARD
|
|||
|
})
|
|||
|
public void querySendDhcpHostnameRestriction(@NonNull @CallbackExecutor Executor executor,
|
|||
|
@NonNull IntConsumer resultsCallback) {
|
|||
|
Objects.requireNonNull(executor, "executor cannot be null");
|
|||
|
Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null");
|
|||
|
try {
|
|||
|
mService.querySendDhcpHostnameRestriction(mContext.getOpPackageName(),
|
|||
|
new IIntegerListener.Stub() {
|
|||
|
@Override
|
|||
|
public void onResult(int value) {
|
|||
|
Binder.clearCallingIdentity();
|
|||
|
executor.execute(() -> {
|
|||
|
resultsCallback.accept(value);
|
|||
|
});
|
|||
|
}
|
|||
|
});
|
|||
|
} catch (RemoteException e) {
|
|||
|
throw e.rethrowFromSystemServer();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* @return true if this device supports Aggressive roaming mode
|
|||
|
* {@link #setPerSsidRoamingMode(WifiSsid, int)}
|
|||
|
*/
|
|||
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|||
|
public boolean isAggressiveRoamingModeSupported() {
|
|||
|
return isFeatureSupported(WIFI_FEATURE_AGGRESSIVE_ROAMING_MODE_SUPPORT);
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* This API allows a privileged application to set roaming mode per SSID.
|
|||
|
*
|
|||
|
* Available for DO/COPE apps.
|
|||
|
* Other apps require {@code android.Manifest.permission#NETWORK_SETTINGS} or
|
|||
|
* {@code android.Manifest.permission#MANAGE_WIFI_NETWORK_SELECTION} permission.
|
|||
|
*
|
|||
|
* @param ssid SSID to be mapped to apply roaming policy
|
|||
|
* @param roamingMode refer {@link RoamingMode} for supported modes.
|
|||
|
* @throws IllegalArgumentException if mode value is not in {@link RoamingMode}.
|
|||
|
* @throws NullPointerException if the caller provided a null input.
|
|||
|
* @throws SecurityException if caller does not have the required permission.
|
|||
|
* @throws UnsupportedOperationException if the set operation is not supported on this SDK or
|
|||
|
* if the feature is not available
|
|||
|
* {@link #isAggressiveRoamingModeSupported()}.
|
|||
|
*/
|
|||
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|||
|
@RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
|
|||
|
@SuppressLint("RequiresPermission")
|
|||
|
public void setPerSsidRoamingMode(@NonNull WifiSsid ssid, @RoamingMode int roamingMode) {
|
|||
|
if (roamingMode < ROAMING_MODE_NONE || roamingMode > ROAMING_MODE_AGGRESSIVE) {
|
|||
|
throw new IllegalArgumentException("invalid roaming mode: " + roamingMode);
|
|||
|
}
|
|||
|
Objects.requireNonNull(ssid, "ssid cannot be null");
|
|||
|
try {
|
|||
|
mService.setPerSsidRoamingMode(ssid, roamingMode, mContext.getOpPackageName());
|
|||
|
} catch (RemoteException e) {
|
|||
|
throw e.rethrowFromSystemServer();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* This API allows a privileged application to remove roaming mode policy
|
|||
|
* configured using the {@link #setPerSsidRoamingMode(WifiSsid, int)}.
|
|||
|
*
|
|||
|
* Available for DO/COPE apps.
|
|||
|
* Other apps require {@code android.Manifest.permission#NETWORK_SETTINGS} or
|
|||
|
* {@code android.Manifest.permission#MANAGE_WIFI_NETWORK_SELECTION} permission.
|
|||
|
*
|
|||
|
* @param ssid SSID to be removed from the roaming mode policy.
|
|||
|
* @throws NullPointerException if the caller provided a null input.
|
|||
|
* @throws SecurityException if caller does not have the required permission.
|
|||
|
* @throws UnsupportedOperationException if the set operation is not supported on this SDK or
|
|||
|
* if the feature is not available
|
|||
|
* {@link #isAggressiveRoamingModeSupported()}.
|
|||
|
*/
|
|||
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|||
|
@RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
|
|||
|
@SuppressLint("RequiresPermission")
|
|||
|
public void removePerSsidRoamingMode(@NonNull WifiSsid ssid) {
|
|||
|
Objects.requireNonNull(ssid, "ssid cannot be null");
|
|||
|
try {
|
|||
|
mService.removePerSsidRoamingMode(ssid, mContext.getOpPackageName());
|
|||
|
} catch (RemoteException e) {
|
|||
|
throw e.rethrowFromSystemServer();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* This API allows a privileged application to get roaming mode policies
|
|||
|
* configured using the {@link #setPerSsidRoamingMode(WifiSsid, int)}.
|
|||
|
*
|
|||
|
* Available for DO/COPE apps.
|
|||
|
* Other apps require {@code android.Manifest.permission#NETWORK_SETTINGS} or
|
|||
|
* {@code android.Manifest.permission#MANAGE_WIFI_NETWORK_SELECTION} permission.
|
|||
|
*
|
|||
|
* @param executor The executor on which callback will be invoked.
|
|||
|
* @param resultsCallback An asynchronous callback that will return the corresponding
|
|||
|
* roaming policies for the API caller.
|
|||
|
* @throws SecurityException if caller does not have the required permission.
|
|||
|
* @throws UnsupportedOperationException if the get operation is not supported on this SDK or
|
|||
|
* if the feature is not available
|
|||
|
* {@link #isAggressiveRoamingModeSupported()}.
|
|||
|
*/
|
|||
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|||
|
@RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
|
|||
|
@SuppressLint("RequiresPermission")
|
|||
|
public void getPerSsidRoamingModes(@NonNull @CallbackExecutor Executor executor,
|
|||
|
@NonNull Consumer<Map<String, Integer>> resultsCallback) {
|
|||
|
Objects.requireNonNull(executor, "executor cannot be null");
|
|||
|
Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null");
|
|||
|
try {
|
|||
|
mService.getPerSsidRoamingModes(mContext.getOpPackageName(), new IMapListener.Stub() {
|
|||
|
@Override
|
|||
|
public void onResult(Map roamingPolicies) {
|
|||
|
Binder.clearCallingIdentity();
|
|||
|
executor.execute(() -> {
|
|||
|
resultsCallback.accept(roamingPolicies);
|
|||
|
});
|
|||
|
}
|
|||
|
});
|
|||
|
} catch (RemoteException e) {
|
|||
|
throw e.rethrowFromSystemServer();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Bundle key to check target wake time requester mode supported or not
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|||
|
public static final String TWT_CAPABILITIES_KEY_BOOLEAN_TWT_REQUESTER =
|
|||
|
"key_requester";
|
|||
|
|
|||
|
/**
|
|||
|
* Bundle key to get minimum wake duration supported in microseconds
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|||
|
public static final String TWT_CAPABILITIES_KEY_INT_MIN_WAKE_DURATION_MICROS =
|
|||
|
"key_min_wake_duration";
|
|||
|
/**
|
|||
|
* Bundle key to get maximum wake duration supported in microseconds
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|||
|
public static final String TWT_CAPABILITIES_KEY_INT_MAX_WAKE_DURATION_MICROS =
|
|||
|
"key_max_wake_duration";
|
|||
|
/**
|
|||
|
* Bundle key to get minimum wake interval supported in microseconds
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|||
|
public static final String TWT_CAPABILITIES_KEY_LONG_MIN_WAKE_INTERVAL_MICROS =
|
|||
|
"key_min_wake_interval";
|
|||
|
/**
|
|||
|
* Bundle key to get maximum wake interval supported in microseconds
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|||
|
public static final String TWT_CAPABILITIES_KEY_LONG_MAX_WAKE_INTERVAL_MICROS =
|
|||
|
"key_max_wake_interval";
|
|||
|
|
|||
|
/** @hide */
|
|||
|
@StringDef(prefix = { "TWT_CAPABILITIES_KEY_"}, value = {
|
|||
|
TWT_CAPABILITIES_KEY_BOOLEAN_TWT_REQUESTER,
|
|||
|
TWT_CAPABILITIES_KEY_INT_MIN_WAKE_DURATION_MICROS,
|
|||
|
TWT_CAPABILITIES_KEY_INT_MAX_WAKE_DURATION_MICROS,
|
|||
|
TWT_CAPABILITIES_KEY_LONG_MIN_WAKE_INTERVAL_MICROS,
|
|||
|
TWT_CAPABILITIES_KEY_LONG_MAX_WAKE_INTERVAL_MICROS,
|
|||
|
})
|
|||
|
@Retention(RetentionPolicy.SOURCE)
|
|||
|
public @interface TwtCapabilities {}
|
|||
|
|
|||
|
/**
|
|||
|
* Get target wake time (TWT) capabilities of the primary station interface.
|
|||
|
*
|
|||
|
* Note: Target wake time feature is only supported for primary station. If Wi-Fi is off or the
|
|||
|
* capability is not available the asynchronous callback will be called with the bundle
|
|||
|
* with values { false, -1, -1, -1, -1 }.
|
|||
|
*
|
|||
|
* @param executor Executor to execute listener callback
|
|||
|
* @param resultCallback An asynchronous callback that will return a bundle for target wake time
|
|||
|
* capabilities. See {@link TwtCapabilities} for the string keys for
|
|||
|
* the bundle.
|
|||
|
* @throws SecurityException if the caller does not have permission.
|
|||
|
* @throws NullPointerException if the caller provided null inputs.
|
|||
|
* @throws UnsupportedOperationException if the API is not supported.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
@RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
|
|||
|
@RequiresPermission(MANAGE_WIFI_NETWORK_SELECTION)
|
|||
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|||
|
public void getTwtCapabilities(@NonNull @CallbackExecutor Executor executor,
|
|||
|
@NonNull Consumer<Bundle> resultCallback) {
|
|||
|
Objects.requireNonNull(executor, "executor cannot be null");
|
|||
|
Objects.requireNonNull(resultCallback, "resultCallback cannot be null");
|
|||
|
if (!SdkLevel.isAtLeastV()) {
|
|||
|
throw new UnsupportedOperationException();
|
|||
|
}
|
|||
|
try {
|
|||
|
Bundle extras = new Bundle();
|
|||
|
extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE,
|
|||
|
mContext.getAttributionSource());
|
|||
|
mService.getTwtCapabilities(
|
|||
|
new ITwtCapabilitiesListener.Stub() {
|
|||
|
@Override
|
|||
|
public void onResult(Bundle value) {
|
|||
|
Binder.clearCallingIdentity();
|
|||
|
executor.execute(() -> {
|
|||
|
resultCallback.accept(value);
|
|||
|
});
|
|||
|
}
|
|||
|
}, extras);
|
|||
|
} catch (RemoteException e) {
|
|||
|
throw e.rethrowFromSystemServer();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private class TwtCallbackProxy extends ITwtCallback.Stub {
|
|||
|
private final Executor mExecutor;
|
|||
|
private final TwtSessionCallback mCallback;
|
|||
|
|
|||
|
private TwtCallbackProxy(Executor executor, TwtSessionCallback callback) {
|
|||
|
mExecutor = executor;
|
|||
|
mCallback = callback;
|
|||
|
}
|
|||
|
|
|||
|
@Override
|
|||
|
public void onFailure(@TwtSessionCallback.TwtErrorCode int errorCode)
|
|||
|
throws RemoteException {
|
|||
|
if (mVerboseLoggingEnabled) {
|
|||
|
Log.v(TAG, "TwtCallbackProxy: onFailure(errorCode = " + errorCode + " )");
|
|||
|
}
|
|||
|
Binder.clearCallingIdentity();
|
|||
|
mExecutor.execute(() -> mCallback.onFailure(errorCode));
|
|||
|
}
|
|||
|
|
|||
|
@Override
|
|||
|
public void onTeardown(@TwtSessionCallback.TwtReasonCode int reasonCode)
|
|||
|
throws RemoteException {
|
|||
|
if (mVerboseLoggingEnabled) {
|
|||
|
Log.v(TAG, "TwtCallbackProxy: onTeardown(errorCode = " + reasonCode + " )");
|
|||
|
}
|
|||
|
Binder.clearCallingIdentity();
|
|||
|
mExecutor.execute(() -> mCallback.onTeardown(reasonCode));
|
|||
|
}
|
|||
|
|
|||
|
@Override
|
|||
|
public void onCreate(int wakeDuration, long wakeInterval, int mloLinkId, int owner,
|
|||
|
int sessionId) throws RemoteException {
|
|||
|
if (mVerboseLoggingEnabled) {
|
|||
|
Log.v(TAG, "TwtCallbackProxy: onCreate " + sessionId);
|
|||
|
}
|
|||
|
|
|||
|
WifiTwtSession wifiTwtSession = new WifiTwtSession(WifiManager.this, wakeDuration,
|
|||
|
wakeInterval, mloLinkId, owner, sessionId);
|
|||
|
Binder.clearCallingIdentity();
|
|||
|
mExecutor.execute(() -> mCallback.onCreate(wifiTwtSession));
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Set up a TWT session with a TWT responder capable AP. Only supported for primary connected
|
|||
|
* station which is a TWT requester. See {@link #getTwtCapabilities(Executor, Consumer)} and
|
|||
|
* {@link ScanResult#isTwtResponder()} to check station and AP support.
|
|||
|
*
|
|||
|
* Following callbacks are invoked,
|
|||
|
* - {@link TwtSessionCallback#onFailure(int)} upon error with error code.
|
|||
|
* - {@link TwtSessionCallback#onCreate(TwtSession)} upon TWT session creation.
|
|||
|
* - {@link TwtSessionCallback#onTeardown(int)} upon TWT session teardown.
|
|||
|
*
|
|||
|
* Note: {@link #getTwtCapabilities(Executor, Consumer)} gives {@link TwtCapabilities} which can
|
|||
|
* be used to fill in the valid TWT wake interval and duration ranges for {@link TwtRequest}.
|
|||
|
*
|
|||
|
* @param twtRequest TWT request
|
|||
|
* @param executor Executor to execute listener callback on
|
|||
|
* @param callback Callback to register
|
|||
|
* @throws SecurityException if the caller does not have permission.
|
|||
|
* @throws NullPointerException if the caller provided null inputs.
|
|||
|
* @throws UnsupportedOperationException if the API is not supported.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@SystemApi
|
|||
|
@RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
|
|||
|
@RequiresPermission(MANAGE_WIFI_NETWORK_SELECTION)
|
|||
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|||
|
public void setupTwtSession(@NonNull TwtRequest twtRequest,
|
|||
|
@NonNull @CallbackExecutor Executor executor, @NonNull TwtSessionCallback callback) {
|
|||
|
Objects.requireNonNull(executor, "executor cannot be null");
|
|||
|
Objects.requireNonNull(callback, "callback cannot be null");
|
|||
|
Objects.requireNonNull(twtRequest, "twtRequest cannot be null");
|
|||
|
if (!SdkLevel.isAtLeastV()) {
|
|||
|
throw new UnsupportedOperationException();
|
|||
|
}
|
|||
|
try {
|
|||
|
ITwtCallback.Stub binderCallback = new TwtCallbackProxy(executor, callback);
|
|||
|
Bundle extras = new Bundle();
|
|||
|
extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE,
|
|||
|
mContext.getAttributionSource());
|
|||
|
mService.setupTwtSession(twtRequest, binderCallback, extras);
|
|||
|
} catch (RemoteException e) {
|
|||
|
throw e.rethrowFromSystemServer();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Get stats of the target wake time session.
|
|||
|
*
|
|||
|
* Note: For Internal use only. Expected to be called through
|
|||
|
* {@link TwtSession#getStats(Executor, Consumer)}. If the command fails, -1 will be returned
|
|||
|
* for all stats values.
|
|||
|
*
|
|||
|
* @param sessionId TWT session id
|
|||
|
* @param executor The executor on which callback will be invoked.
|
|||
|
* @param resultCallback The asynchronous callback that will return bundle with key string
|
|||
|
* {@link TwtSession.TwtStats}.
|
|||
|
*
|
|||
|
* @throws SecurityException if the caller does not have permission.
|
|||
|
* @throws NullPointerException if the caller provided null inputs.
|
|||
|
* @throws UnsupportedOperationException if the API is not supported or primary station is
|
|||
|
* not connected.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
public void getStatsTwtSession(@NonNull int sessionId, @NonNull Executor executor,
|
|||
|
@NonNull Consumer<Bundle> resultCallback) {
|
|||
|
Objects.requireNonNull(executor, "executor cannot be null");
|
|||
|
Objects.requireNonNull(resultCallback, "resultsCallback cannot be null");
|
|||
|
if (!SdkLevel.isAtLeastV()) {
|
|||
|
throw new UnsupportedOperationException();
|
|||
|
}
|
|||
|
try {
|
|||
|
Bundle extras = new Bundle();
|
|||
|
if (SdkLevel.isAtLeastS()) {
|
|||
|
extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE,
|
|||
|
mContext.getAttributionSource());
|
|||
|
}
|
|||
|
mService.getStatsTwtSession(sessionId,
|
|||
|
new ITwtStatsListener.Stub() {
|
|||
|
@Override
|
|||
|
public void onResult(Bundle value) {
|
|||
|
Binder.clearCallingIdentity();
|
|||
|
executor.execute(() -> {
|
|||
|
resultCallback.accept(value);
|
|||
|
});
|
|||
|
}
|
|||
|
}, extras);
|
|||
|
} catch (RemoteException e) {
|
|||
|
throw e.rethrowFromSystemServer();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Teardown the target wake time session. Only owner can teardown the session.
|
|||
|
*
|
|||
|
* Note: For internal use only. Expected to be called through
|
|||
|
* {@link TwtSessionCallback#onTeardown(int)}.
|
|||
|
*
|
|||
|
* @param sessionId TWT session id
|
|||
|
* @throws SecurityException if the caller does not have permission.
|
|||
|
* @throws UnsupportedOperationException if the API is not supported or primary station is not
|
|||
|
* connected.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
public void teardownTwtSession(int sessionId) {
|
|||
|
if (!SdkLevel.isAtLeastV()) {
|
|||
|
throw new UnsupportedOperationException();
|
|||
|
}
|
|||
|
try {
|
|||
|
Bundle extras = new Bundle();
|
|||
|
if (SdkLevel.isAtLeastS()) {
|
|||
|
extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE,
|
|||
|
mContext.getAttributionSource());
|
|||
|
}
|
|||
|
mService.teardownTwtSession(sessionId, extras);
|
|||
|
} catch (RemoteException e) {
|
|||
|
throw e.rethrowFromSystemServer();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Allows a privileged application to set whether or not this device allows
|
|||
|
* device-to-device connections when infra STA is disabled. Callers can use
|
|||
|
* {@link #queryD2dAllowedWhenInfraStaDisabled(Executor, Consumer)} to check the currently
|
|||
|
* set value.
|
|||
|
*
|
|||
|
* Note: This functionality is supported only when the device support device-to-device
|
|||
|
* when infra STA is disabled. Use {@link #isD2dSupportedWhenInfraStaDisabled()} to
|
|||
|
* know if device supported device-to-device when infra STA is disabled.
|
|||
|
*
|
|||
|
* @param isAllowed whether or not the device allows to device-to-device connectivity when
|
|||
|
* infra STA is disabled.
|
|||
|
* @throws SecurityException if the caller does not have permission.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|||
|
@SystemApi
|
|||
|
@RequiresPermission(anyOf = {
|
|||
|
android.Manifest.permission.NETWORK_SETTINGS,
|
|||
|
android.Manifest.permission.NETWORK_SETUP_WIZARD
|
|||
|
})
|
|||
|
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
|
|||
|
public void setD2dAllowedWhenInfraStaDisabled(boolean isAllowed) {
|
|||
|
try {
|
|||
|
mService.setD2dAllowedWhenInfraStaDisabled(isAllowed);
|
|||
|
} catch (RemoteException e) {
|
|||
|
throw e.rethrowFromSystemServer();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Query whether or not this device is configured to allow D2d connection when
|
|||
|
* infra STA is disabled.
|
|||
|
* see: {@link #setD2dAllowedWhenInfraStaDisabled(boolean)}.
|
|||
|
*
|
|||
|
*
|
|||
|
* @param executor The executor on which callback will be invoked.
|
|||
|
* @param resultsCallback An asynchronous callback that will return {@code Boolean} indicating
|
|||
|
* whether device-to-device connection is allowed or disallowed
|
|||
|
* when infra STA is disabled.
|
|||
|
* @hide
|
|||
|
*/
|
|||
|
@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
|
|||
|
@SystemApi
|
|||
|
public void queryD2dAllowedWhenInfraStaDisabled(@NonNull @CallbackExecutor Executor executor,
|
|||
|
@NonNull Consumer<Boolean> resultsCallback) {
|
|||
|
Objects.requireNonNull(executor, "executor cannot be null");
|
|||
|
Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null");
|
|||
|
try {
|
|||
|
mService.queryD2dAllowedWhenInfraStaDisabled(
|
|||
|
new IBooleanListener.Stub() {
|
|||
|
@Override
|
|||
|
public void onResult(boolean value) {
|
|||
|
Binder.clearCallingIdentity();
|
|||
|
executor.execute(() -> {
|
|||
|
resultsCallback.accept(value);
|
|||
|
});
|
|||
|
}
|
|||
|
});
|
|||
|
} catch (RemoteException e) {
|
|||
|
throw e.rethrowFromSystemServer();
|
|||
|
}
|
|||
|
}
|
|||
|
}
|