blob: a467965bdf02e1b2013ecaa2da141f80aac7e7b4 [file] [log] [blame]
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/
package com.android.libraries.tv.tvsystem.wifi;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.net.MacAddress;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
import android.os.Parcel;
import android.os.Parcelable;
import com.android.internal.util.Preconditions;
import java.nio.charset.StandardCharsets;
import java.util.Objects;
import java.util.concurrent.Executor;
/**
* WiFi configuration for a soft access point (a.k.a. Soft AP, SAP, Hotspot).
*
* This is input for the framework provided by a client app, i.e. it exposes knobs to instruct the
* framework how it should open a hotspot. It is not meant to describe the network as it will be
* seen by clients; this role is currently served by {@link WifiConfiguration} (see
* {@link WifiManager.LocalOnlyHotspotReservation#getWifiConfiguration()}).
*
* Apps can use this to configure a local-only hotspot using
* {@link TvWifiManager#startLocalOnlyHotspot(SoftApConfiguration, Executor,
* WifiManager.LocalOnlyHotspotCallback)}.
*
* Instances of this class are immutable; use {@link SoftApConfiguration.Builder} and its methods to
* create a new instance.
*
* @hide
*/
@SystemApi
public final class SoftApConfiguration implements Parcelable {
/**
* SSID for the AP, or null for a framework-determined SSID.
*/
private final @Nullable
String mSsid;
/**
* BSSID for the AP, or null to use a framework-determined BSSID.
*/
private final @Nullable
MacAddress mBssid;
/**
* Pre-shared key for WPA2-PSK encryption (non-null enables WPA2-PSK).
*/
private final @Nullable
String mWpa2Passphrase;
/** Private constructor for Builder and Parcelable implementation. */
private SoftApConfiguration(
@Nullable String ssid, @Nullable MacAddress bssid, String wpa2Passphrase) {
mSsid = ssid;
mBssid = bssid;
mWpa2Passphrase = wpa2Passphrase;
}
@Override
public boolean equals(Object otherObj) {
if (this == otherObj) {
return true;
}
if (!(otherObj instanceof SoftApConfiguration)) {
return false;
}
SoftApConfiguration other = (SoftApConfiguration) otherObj;
return Objects.equals(mSsid, other.mSsid)
&& Objects.equals(mBssid, other.mBssid)
&& Objects.equals(mWpa2Passphrase, other.mWpa2Passphrase);
}
@Override
public int hashCode() {
return Objects.hash(mSsid, mBssid, mWpa2Passphrase);
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeString(mSsid);
dest.writeParcelable(mBssid, flags);
dest.writeString(mWpa2Passphrase);
}
@Override
public int describeContents() {
return 0;
}
@NonNull
public static final Creator<SoftApConfiguration> CREATOR = new Creator<SoftApConfiguration>() {
@Override
public SoftApConfiguration createFromParcel(Parcel in) {
return new SoftApConfiguration(
in.readString(),
in.readParcelable(MacAddress.class.getClassLoader()),
in.readString());
}
@Override
public SoftApConfiguration[] newArray(int size) {
return new SoftApConfiguration[size];
}
};
@Nullable
public String getSsid() {
return mSsid;
}
@Nullable
public MacAddress getBssid() {
return mBssid;
}
@Nullable
public String getWpa2Passphrase() {
return mWpa2Passphrase;
}
/**
* Builds a {@link SoftApConfiguration}, which allows an app to configure various aspects of a
* Soft AP.
*
* All fields are optional. By default, SSID and BSSID are automatically chosen by the
* framework, and an open network is created.
*/
public static final class Builder {
private String mSsid;
private MacAddress mBssid;
private String mWpa2Passphrase;
/**
* Constructs a Builder with default values (see {@link Builder}).
*/
public Builder() {
mSsid = null;
mBssid = null;
mWpa2Passphrase = null;
}
/**
* Constructs a Builder initialized from an existing {@link SoftApConfiguration} instance.
*/
public Builder(@NonNull SoftApConfiguration other) {
Objects.requireNonNull(other);
mSsid = other.mSsid;
mBssid = other.mBssid;
mWpa2Passphrase = other.mWpa2Passphrase;
}
/**
* Builds the {@link SoftApConfiguration}.
*
* @return A new {@link SoftApConfiguration}, as configured by previous method calls.
*/
@NonNull
public SoftApConfiguration build() {
return new SoftApConfiguration(mSsid, mBssid, mWpa2Passphrase);
}
/**
* Specifies an SSID for the AP.
*
* @param ssid SSID of valid Unicode characters, or null to have the SSID automatically
* chosen by the framework.
* @return Builder for chaining.
* @throws IllegalArgumentException when the SSID is empty or not valid Unicode.
*/
@NonNull
public Builder setSsid(@Nullable String ssid) {
if (ssid != null) {
Preconditions.checkStringNotEmpty(ssid);
Preconditions.checkArgument(StandardCharsets.UTF_8.newEncoder().canEncode(ssid));
}
mSsid = ssid;
return this;
}
/**
* Specifies a BSSID for the AP.
*
* @param bssid BSSID, or null to have the BSSID chosen by the framework. The caller is
* responsible for avoiding collisions.
* @return Builder for chaining.
* @throws IllegalArgumentException when the given BSSID is the all-zero or broadcast MAC
* address.
*/
@NonNull
public Builder setBssid(@Nullable MacAddress bssid) {
if (bssid != null) {
Preconditions.checkArgument(!bssid.equals(MacAddress.ALL_ZEROS_ADDRESS));
Preconditions.checkArgument(!bssid.equals(MacAddress.BROADCAST_ADDRESS));
}
mBssid = bssid;
return this;
}
/**
* Specifies that this AP should use WPA2-PSK with the given passphrase. When set to null
* and no other encryption method is configured, an open network is created.
*
* @param passphrase The passphrase to use, or null to unset a previously-set WPA2-PSK
* configuration.
* @return Builder for chaining.
* @throws IllegalArgumentException when the passphrase is the empty string
*/
@NonNull
public Builder setWpa2Passphrase(@Nullable String passphrase) {
if (passphrase != null) {
Preconditions.checkStringNotEmpty(passphrase);
}
mWpa2Passphrase = passphrase;
return this;
}
}
}