1 /* 2 * Copyright (C) 2024 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.net.wifi; 18 19 import android.annotation.FlaggedApi; 20 import android.annotation.NonNull; 21 import android.annotation.Nullable; 22 import android.annotation.SystemApi; 23 import android.net.TetheringManager; 24 import android.os.Parcel; 25 import android.os.Parcelable; 26 27 import com.android.modules.utils.build.SdkLevel; 28 import com.android.wifi.flags.Flags; 29 30 import java.util.Objects; 31 32 /** 33 * A class representing the current state of SoftAp. 34 * @see WifiManager.SoftApCallback#onStateChanged(SoftApState) 35 * 36 * @hide 37 */ 38 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 39 @SystemApi 40 public final class SoftApState implements Parcelable { 41 42 @WifiManager.WifiApState 43 final int mState; 44 @WifiManager.SapStartFailure 45 final int mFailureReason; 46 @Nullable 47 final TetheringManager.TetheringRequest mTetheringRequest; 48 @Nullable 49 final String mIface; 50 51 /** 52 * SoftApState constructor. 53 * 54 * @param state Current state of the Soft AP. 55 * @param failureReason Failure reason if the current state is 56 * {@link WifiManager#WIFI_AP_STATE_FAILED}. 57 * @param tetheringRequest TetheringRequest if one was specified when Soft AP was requested, 58 * else {@code null}. 59 * @param iface Interface name if an interface was created, else {@code null}. 60 * @hide 61 */ SoftApState(@ifiManager.WifiApState int state, @WifiManager.SapStartFailure int failureReason, @Nullable TetheringManager.TetheringRequest tetheringRequest, @Nullable String iface)62 public SoftApState(@WifiManager.WifiApState int state, 63 @WifiManager.SapStartFailure int failureReason, 64 @Nullable TetheringManager.TetheringRequest tetheringRequest, 65 @Nullable String iface) { 66 mState = state; 67 mFailureReason = failureReason; 68 mTetheringRequest = tetheringRequest; 69 mIface = iface; 70 } 71 SoftApState(@onNull Parcel in)72 private SoftApState(@NonNull Parcel in) { 73 mState = in.readInt(); 74 mFailureReason = in.readInt(); 75 if (SdkLevel.isAtLeastV()) { 76 // TetheringRequest is parcelable starting in V. 77 mTetheringRequest = in.readParcelable( 78 TetheringManager.TetheringRequest.class.getClassLoader()); 79 } else { 80 mTetheringRequest = null; 81 } 82 mIface = in.readString(); 83 } 84 85 @Override writeToParcel(@onNull Parcel dest, int flags)86 public void writeToParcel(@NonNull Parcel dest, int flags) { 87 dest.writeInt(mState); 88 dest.writeInt(mFailureReason); 89 if (SdkLevel.isAtLeastV()) { 90 // TetheringRequest is parcelable starting in V. 91 dest.writeParcelable(mTetheringRequest, flags); 92 } 93 dest.writeString(mIface); 94 } 95 96 @Override describeContents()97 public int describeContents() { 98 return 0; 99 } 100 101 @NonNull 102 public static final Creator<SoftApState> CREATOR = new Creator<SoftApState>() { 103 @Override 104 @NonNull 105 public SoftApState createFromParcel(Parcel in) { 106 return new SoftApState(in); 107 } 108 109 @Override 110 @NonNull 111 public SoftApState[] newArray(int size) { 112 return new SoftApState[size]; 113 } 114 }; 115 116 /** 117 * Get the AP state. 118 * 119 * @return One of {@link WifiManager#WIFI_AP_STATE_DISABLED}, 120 * {@link WifiManager#WIFI_AP_STATE_DISABLING}, 121 * {@link WifiManager#WIFI_AP_STATE_ENABLED}, 122 * {@link WifiManager#WIFI_AP_STATE_ENABLING}, 123 * {@link WifiManager#WIFI_AP_STATE_FAILED} 124 */ 125 @WifiManager.WifiApState getState()126 public int getState() { 127 return mState; 128 } 129 130 /** 131 * Get the failure reason if the state is {@link WifiManager#WIFI_AP_STATE_FAILED}. 132 * 133 * @return One of {@link WifiManager#SAP_START_FAILURE_GENERAL}, 134 * {@link WifiManager#SAP_START_FAILURE_NO_CHANNEL}, 135 * {@link WifiManager#SAP_START_FAILURE_UNSUPPORTED_CONFIGURATION}, 136 * {@link WifiManager#SAP_START_FAILURE_USER_REJECTED} 137 * @throws IllegalStateException if the state is not {@link WifiManager#WIFI_AP_STATE_FAILED}. 138 */ 139 @WifiManager.SapStartFailure getFailureReason()140 public int getFailureReason() { 141 if (mState != WifiManager.WIFI_AP_STATE_FAILED) { 142 throw new IllegalStateException("Called getFailureReason() when state is not" 143 + " WIFI_AP_STATE_FAILED. Actual state is " + mState); 144 } 145 return getFailureReasonInternal(); 146 } 147 148 /** 149 * @hide 150 */ 151 @WifiManager.SapStartFailure getFailureReasonInternal()152 public int getFailureReasonInternal() { 153 return mFailureReason; 154 } 155 156 /** 157 * Gets the TetheringRequest of the Soft AP, if one was specified via 158 * {@link WifiManager#startTetheredHotspotRequest(TetheringManager.TetheringRequest)}. 159 * Otherwise, returns {@code null}. 160 */ 161 @Nullable getTetheringRequest()162 public TetheringManager.TetheringRequest getTetheringRequest() { 163 return mTetheringRequest; 164 } 165 166 /** 167 * Gets the interface name of the Soft AP (e.g. "wlan0") once the Soft AP starts enabling, i.e. 168 * {@link #getState()} returns {@link WifiManager#WIFI_AP_STATE_ENABLING}). Returns {@code null} 169 * if the Soft AP hasn't started enabling yet, or if it failed with 170 * {@link WifiManager#WIFI_AP_STATE_FAILED} without starting enabling. 171 */ 172 @Nullable getIface()173 public String getIface() { 174 return mIface; 175 } 176 177 @Override toString()178 public String toString() { 179 return "SoftApState{" 180 + "mState=" + mState 181 + ", mFailureReason=" + mFailureReason 182 + ", mTetheringRequest=" + mTetheringRequest 183 + ", mIface='" + mIface + '\'' 184 + '}'; 185 } 186 187 @Override equals(Object o)188 public boolean equals(Object o) { 189 if (this == o) return true; 190 if (!(o instanceof SoftApState stateInfo)) return false; 191 return mState == stateInfo.mState && mFailureReason == stateInfo.mFailureReason 192 && Objects.equals(mTetheringRequest, stateInfo.mTetheringRequest) 193 && Objects.equals(mIface, stateInfo.mIface); 194 } 195 196 @Override hashCode()197 public int hashCode() { 198 return Objects.hash(mState, mFailureReason, mTetheringRequest, mIface); 199 } 200 } 201