1 /* 2 * Copyright (C) 2022 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; 18 19 import android.annotation.IntDef; 20 import android.annotation.NonNull; 21 import android.annotation.Nullable; 22 import android.os.Parcel; 23 import android.os.Parcelable; 24 25 import java.lang.annotation.Retention; 26 import java.lang.annotation.RetentionPolicy; 27 import java.util.Objects; 28 import java.util.StringJoiner; 29 30 /** 31 * Describe the state of VPN. 32 */ 33 public final class VpnProfileState implements Parcelable { 34 /** The VPN has not been started, or some other VPN is active. */ 35 public static final int STATE_DISCONNECTED = 0; 36 /** The VPN is attempting to connect, potentially after a failure. */ 37 public static final int STATE_CONNECTING = 1; 38 /** The VPN was established successfully. */ 39 public static final int STATE_CONNECTED = 2; 40 /** A non-recoverable error has occurred, and will not be retried. */ 41 public static final int STATE_FAILED = 3; 42 /** @hide */ 43 @Retention(RetentionPolicy.SOURCE) 44 @IntDef(prefix = {"STATE_"}, value = { 45 STATE_CONNECTED, 46 STATE_CONNECTING, 47 STATE_DISCONNECTED, 48 STATE_FAILED, 49 }) 50 public @interface State {} 51 52 @State private final int mState; 53 private final String mSessionKey; 54 private final boolean mAlwaysOn; 55 private final boolean mLockdown; 56 VpnProfileState(@tate int state, @Nullable String sessionKey, boolean alwaysOn, boolean lockdown)57 public VpnProfileState(@State int state, @Nullable String sessionKey, boolean alwaysOn, 58 boolean lockdown) { 59 mState = state; 60 mSessionKey = sessionKey; 61 mAlwaysOn = alwaysOn; 62 mLockdown = lockdown; 63 } 64 65 /** 66 * Returns the state of the Platform VPN 67 * 68 * <p>This state represents the internal connection state of the VPN. This state may diverge 69 * from the VPN Network's state during error and recovery handling. 70 */ getState()71 @State public int getState() { 72 return mState; 73 } 74 75 /** 76 * Retrieves the Session Key 77 * 78 * <p>The session key is an ephemeral key uniquely identifying the session for a Platform VPN. 79 * The lifetime of this key is tied to the lifetime of the VPN session. In other words, 80 * reprovisioning of the VPN profile, restarting of the device, or manually restarting the 81 * platform VPN session will result in a new VPN session, and a new key. 82 * 83 * @return the unique key for the platform VPN session, or null if it is not running. 84 */ 85 @Nullable getSessionId()86 public String getSessionId() { 87 return mSessionKey; 88 } 89 90 /** 91 * Returns the always-on status of the PlatformVpnProfile. 92 * 93 * <p>If the PlatformVpnProfile is set to be running in always-on mode, the system will ensure 94 * that the profile is always started, and restarting it when necessary (e.g. after reboot). 95 * 96 * <p>Always-on can be set by an appropriately privileged user via the Settings VPN menus, or by 97 * the Device Policy Manager app programmatically. 98 * 99 * See DevicePolicyManager#setAlwaysOnVpnPackage(ComponentName, String, boolean, Set) 100 */ isAlwaysOn()101 public boolean isAlwaysOn() { 102 return mAlwaysOn; 103 } 104 105 /** 106 * Returns the lockdown mode status of the PlatformVpnProfile. 107 * 108 * <p>In lockdown mode, the system will ensure that apps are not allowed to bypass the VPN, 109 * including during startup or failure of the VPN. 110 * 111 * <p>Lockdown mode can be set by an appropriately privileged user via the Settings VPN menus, 112 * or by the Device Policy Manager app programmatically. 113 * 114 * See DevicePolicyManager#setAlwaysOnVpnPackage(ComponentName, String, boolean, Set) 115 */ isLockdownEnabled()116 public boolean isLockdownEnabled() { 117 return mLockdown; 118 } 119 120 /** 121 * Implement the Parcelable interface 122 */ describeContents()123 public int describeContents() { 124 return 0; 125 } 126 127 /** 128 * Implement the Parcelable interface 129 */ writeToParcel(@onNull Parcel out, int flags)130 public void writeToParcel(@NonNull Parcel out, int flags) { 131 out.writeInt(mState); 132 out.writeString(mSessionKey); 133 out.writeBoolean(mAlwaysOn); 134 out.writeBoolean(mLockdown); 135 } 136 137 @NonNull 138 public static final Parcelable.Creator<VpnProfileState> CREATOR = 139 new Parcelable.Creator<VpnProfileState>() { 140 public VpnProfileState createFromParcel(Parcel in) { 141 return new VpnProfileState(in); 142 } 143 144 public VpnProfileState[] newArray(int size) { 145 return new VpnProfileState[size]; 146 } 147 }; 148 VpnProfileState(Parcel in)149 private VpnProfileState(Parcel in) { 150 mState = in.readInt(); 151 mSessionKey = in.readString(); 152 mAlwaysOn = in.readBoolean(); 153 mLockdown = in.readBoolean(); 154 } 155 convertStateToString(@tate int state)156 private String convertStateToString(@State int state) { 157 switch (state) { 158 case STATE_CONNECTED: 159 return "CONNECTED"; 160 case STATE_CONNECTING: 161 return "CONNECTING"; 162 case STATE_DISCONNECTED: 163 return "DISCONNECTED"; 164 case STATE_FAILED: 165 return "FAILED"; 166 default: 167 return "UNKNOWN"; 168 } 169 } 170 171 @Override toString()172 public String toString() { 173 final StringJoiner resultJoiner = new StringJoiner(", ", "{", "}"); 174 resultJoiner.add("State: " + convertStateToString(getState())); 175 resultJoiner.add("SessionId: " + getSessionId()); 176 resultJoiner.add("Always-on: " + isAlwaysOn()); 177 resultJoiner.add("Lockdown: " + isLockdownEnabled()); 178 return resultJoiner.toString(); 179 } 180 181 @Override equals(@ullable Object obj)182 public boolean equals(@Nullable Object obj) { 183 if (!(obj instanceof VpnProfileState)) return false; 184 final VpnProfileState that = (VpnProfileState) obj; 185 return (getState() == that.getState() 186 && Objects.equals(getSessionId(), that.getSessionId()) 187 && isAlwaysOn() == that.isAlwaysOn() 188 && isLockdownEnabled() == that.isLockdownEnabled()); 189 } 190 191 @Override hashCode()192 public int hashCode() { 193 return Objects.hash(getState(), getSessionId(), isAlwaysOn(), isLockdownEnabled()); 194 } 195 } 196