1 /* 2 * Copyright (C) 2009, 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.vpn; 18 19 import java.io.File; 20 21 import android.content.BroadcastReceiver; 22 import android.content.Context; 23 import android.content.Intent; 24 import android.content.IntentFilter; 25 import android.content.ServiceConnection; 26 import android.os.Environment; 27 import android.os.SystemProperties; 28 import android.util.Log; 29 30 /** 31 * The class provides interface to manage all VPN-related tasks, including: 32 * <ul> 33 * <li>The list of supported VPN types. 34 * <li>API's to start/stop the service of a particular type. 35 * <li>API's to start the settings activity. 36 * <li>API's to create a profile. 37 * <li>API's to register/unregister a connectivity receiver and the keys to 38 * access the fields in a connectivity broadcast event. 39 * </ul> 40 * {@hide} 41 */ 42 public class VpnManager { 43 // Action for broadcasting a connectivity state. 44 private static final String ACTION_VPN_CONNECTIVITY = "vpn.connectivity"; 45 /** Key to the profile name of a connectivity broadcast event. */ 46 public static final String BROADCAST_PROFILE_NAME = "profile_name"; 47 /** Key to the connectivity state of a connectivity broadcast event. */ 48 public static final String BROADCAST_CONNECTION_STATE = "connection_state"; 49 /** Key to the error code of a connectivity broadcast event. */ 50 public static final String BROADCAST_ERROR_CODE = "err"; 51 /** Error code to indicate an error from authentication. */ 52 public static final int VPN_ERROR_AUTH = 51; 53 /** Error code to indicate the connection attempt failed. */ 54 public static final int VPN_ERROR_CONNECTION_FAILED = 101; 55 /** Error code to indicate the server is not known. */ 56 public static final int VPN_ERROR_UNKNOWN_SERVER = 102; 57 /** Error code to indicate an error from challenge response. */ 58 public static final int VPN_ERROR_CHALLENGE = 5; 59 /** Error code to indicate an error of remote server hanging up. */ 60 public static final int VPN_ERROR_REMOTE_HUNG_UP = 7; 61 /** Error code to indicate an error of remote PPP server hanging up. */ 62 public static final int VPN_ERROR_REMOTE_PPP_HUNG_UP = 48; 63 /** Error code to indicate a PPP negotiation error. */ 64 public static final int VPN_ERROR_PPP_NEGOTIATION_FAILED = 42; 65 /** Error code to indicate an error of losing connectivity. */ 66 public static final int VPN_ERROR_CONNECTION_LOST = 103; 67 /** Largest error code used by VPN. */ 68 public static final int VPN_ERROR_LARGEST = 200; 69 /** Error code to indicate a successful connection. */ 70 public static final int VPN_ERROR_NO_ERROR = 0; 71 72 public static final String PROFILES_PATH = "/misc/vpn/profiles"; 73 74 private static final String PACKAGE_PREFIX = 75 VpnManager.class.getPackage().getName() + "."; 76 77 // Action to start VPN service 78 private static final String ACTION_VPN_SERVICE = PACKAGE_PREFIX + "SERVICE"; 79 80 // Action to start VPN settings 81 private static final String ACTION_VPN_SETTINGS = 82 PACKAGE_PREFIX + "SETTINGS"; 83 84 public static final String TAG = VpnManager.class.getSimpleName(); 85 86 // TODO(oam): Test VPN when EFS is enabled (will do later)... 87 public static String getProfilePath() { 88 // This call will return the correct path if Encrypted FS is enabled or not. 89 return Environment.getSecureDataDirectory().getPath() + PROFILES_PATH; 90 } 91 92 /** 93 * Returns all supported VPN types. 94 */ 95 public static VpnType[] getSupportedVpnTypes() { 96 return VpnType.values(); 97 } 98 99 private Context mContext; 100 101 /** 102 * Creates a manager object with the specified context. 103 */ 104 public VpnManager(Context c) { 105 mContext = c; 106 } 107 108 /** 109 * Creates a VPN profile of the specified type. 110 * 111 * @param type the VPN type 112 * @return the profile object 113 */ 114 public VpnProfile createVpnProfile(VpnType type) { 115 return createVpnProfile(type, false); 116 } 117 118 /** 119 * Creates a VPN profile of the specified type. 120 * 121 * @param type the VPN type 122 * @param customized true if the profile is custom made 123 * @return the profile object 124 */ 125 public VpnProfile createVpnProfile(VpnType type, boolean customized) { 126 try { 127 VpnProfile p = (VpnProfile) type.getProfileClass().newInstance(); 128 p.setCustomized(customized); 129 return p; 130 } catch (InstantiationException e) { 131 return null; 132 } catch (IllegalAccessException e) { 133 return null; 134 } 135 } 136 137 /** 138 * Starts the VPN service to establish VPN connection. 139 */ 140 public void startVpnService() { 141 mContext.startService(new Intent(ACTION_VPN_SERVICE)); 142 } 143 144 /** 145 * Stops the VPN service. 146 */ 147 public void stopVpnService() { 148 mContext.stopService(new Intent(ACTION_VPN_SERVICE)); 149 } 150 151 /** 152 * Binds the specified ServiceConnection with the VPN service. 153 */ 154 public boolean bindVpnService(ServiceConnection c) { 155 if (!mContext.bindService(new Intent(ACTION_VPN_SERVICE), c, 0)) { 156 Log.w(TAG, "failed to connect to VPN service"); 157 return false; 158 } else { 159 Log.d(TAG, "succeeded to connect to VPN service"); 160 return true; 161 } 162 } 163 164 /** Broadcasts the connectivity state of the specified profile. */ 165 public void broadcastConnectivity(String profileName, VpnState s) { 166 broadcastConnectivity(profileName, s, VPN_ERROR_NO_ERROR); 167 } 168 169 /** Broadcasts the connectivity state with an error code. */ 170 public void broadcastConnectivity(String profileName, VpnState s, 171 int error) { 172 Intent intent = new Intent(ACTION_VPN_CONNECTIVITY); 173 intent.putExtra(BROADCAST_PROFILE_NAME, profileName); 174 intent.putExtra(BROADCAST_CONNECTION_STATE, s); 175 if (error != VPN_ERROR_NO_ERROR) { 176 intent.putExtra(BROADCAST_ERROR_CODE, error); 177 } 178 mContext.sendBroadcast(intent); 179 } 180 181 public void registerConnectivityReceiver(BroadcastReceiver r) { 182 IntentFilter filter = new IntentFilter(); 183 filter.addAction(VpnManager.ACTION_VPN_CONNECTIVITY); 184 mContext.registerReceiver(r, filter); 185 } 186 187 public void unregisterConnectivityReceiver(BroadcastReceiver r) { 188 mContext.unregisterReceiver(r); 189 } 190 191 /** Starts the VPN settings activity. */ 192 public void startSettingsActivity() { 193 Intent intent = new Intent(ACTION_VPN_SETTINGS); 194 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 195 mContext.startActivity(intent); 196 } 197 198 /** Creates an intent to start the VPN settings activity. */ 199 public Intent createSettingsActivityIntent() { 200 Intent intent = new Intent(ACTION_VPN_SETTINGS); 201 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 202 return intent; 203 } 204 } 205