From 3a978c1a988b00c111f6540998700e1f3b441178 Mon Sep 17 00:00:00 2001 From: Hung-ying Tyan Date: Wed, 3 Jun 2009 23:56:34 +0800 Subject: First-time check-in of the VPN APIs. Patch Set 2: - Fixed style issues raised by cywang. Patch Set 3: - Hide everything - Make VpnProfile parcelable Patch Set 4: - Add license notice --- vpn/java/android/net/vpn/IVpnService.aidl | 43 +++++ vpn/java/android/net/vpn/L2tpIpsecProfile.java | 74 ++++++++ vpn/java/android/net/vpn/L2tpProfile.java | 28 +++ vpn/java/android/net/vpn/SingleServerProfile.java | 47 +++++ vpn/java/android/net/vpn/VpnManager.java | 216 ++++++++++++++++++++++ vpn/java/android/net/vpn/VpnProfile.aidl | 19 ++ vpn/java/android/net/vpn/VpnProfile.java | 155 ++++++++++++++++ vpn/java/android/net/vpn/VpnState.java | 31 ++++ vpn/java/android/net/vpn/VpnType.java | 46 +++++ 9 files changed, 659 insertions(+) create mode 100644 vpn/java/android/net/vpn/IVpnService.aidl create mode 100644 vpn/java/android/net/vpn/L2tpIpsecProfile.java create mode 100644 vpn/java/android/net/vpn/L2tpProfile.java create mode 100644 vpn/java/android/net/vpn/SingleServerProfile.java create mode 100644 vpn/java/android/net/vpn/VpnManager.java create mode 100644 vpn/java/android/net/vpn/VpnProfile.aidl create mode 100644 vpn/java/android/net/vpn/VpnProfile.java create mode 100644 vpn/java/android/net/vpn/VpnState.java create mode 100644 vpn/java/android/net/vpn/VpnType.java (limited to 'vpn') diff --git a/vpn/java/android/net/vpn/IVpnService.aidl b/vpn/java/android/net/vpn/IVpnService.aidl new file mode 100644 index 0000000..0e658df --- /dev/null +++ b/vpn/java/android/net/vpn/IVpnService.aidl @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2007, 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.vpn; + +import android.net.vpn.VpnProfile; + +/** + * Interface to access a VPN service. + * {@hide} + */ +interface IVpnService { + /** + * Sets up the VPN connection. + * @param profile the profile object + * @param username the username for authentication + * @param password the corresponding password for authentication + */ + boolean connect(in VpnProfile profile, String username, String password); + + /** + * Tears down the VPN connection. + */ + void disconnect(); + + /** + * Makes the service broadcast the connectivity state. + */ + void checkStatus(in VpnProfile profile); +} diff --git a/vpn/java/android/net/vpn/L2tpIpsecProfile.java b/vpn/java/android/net/vpn/L2tpIpsecProfile.java new file mode 100644 index 0000000..a7e53d1 --- /dev/null +++ b/vpn/java/android/net/vpn/L2tpIpsecProfile.java @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2007, 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.vpn; + +import android.os.Parcel; + +/** + * The profile for L2TP-over-IPSec type of VPN. + * {@hide} + */ +public class L2tpIpsecProfile extends SingleServerProfile { + private String mUserCertificate; + private String mCaCertificate; + private String mUserkey; + + @Override + public VpnType getType() { + return VpnType.L2TP_IPSEC; + } + + public void setCaCertificate(String name) { + mCaCertificate = name; + } + + public String getCaCertificate() { + return mCaCertificate; + } + + public void setUserCertificate(String name) { + mUserCertificate = name; + } + + public String getUserCertificate() { + return mUserCertificate; + } + + public void setUserkey(String name) { + mUserkey = name; + } + + public String getUserkey() { + return mUserkey; + } + + @Override + protected void readFromParcel(Parcel in) { + super.readFromParcel(in); + mCaCertificate = in.readString(); + mUserCertificate = in.readString(); + mUserkey = in.readString(); + } + + @Override + public void writeToParcel(Parcel parcel, int flags) { + super.writeToParcel(parcel, flags); + parcel.writeString(mCaCertificate); + parcel.writeString(mUserCertificate); + parcel.writeString(mUserkey); + } +} diff --git a/vpn/java/android/net/vpn/L2tpProfile.java b/vpn/java/android/net/vpn/L2tpProfile.java new file mode 100644 index 0000000..ca4ef75 --- /dev/null +++ b/vpn/java/android/net/vpn/L2tpProfile.java @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2007, 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.vpn; + +/** + * The profile for L2TP type of VPN. + * {@hide} + */ +public class L2tpProfile extends SingleServerProfile { + @Override + public VpnType getType() { + return VpnType.L2TP; + } +} diff --git a/vpn/java/android/net/vpn/SingleServerProfile.java b/vpn/java/android/net/vpn/SingleServerProfile.java new file mode 100644 index 0000000..59b5a7b --- /dev/null +++ b/vpn/java/android/net/vpn/SingleServerProfile.java @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2007, 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.vpn; + +import android.os.Parcel; + +/** + * The profile for single-server type of VPN. + * {@hide} + */ +public abstract class SingleServerProfile extends VpnProfile { + private String mServerName; + + public void setServerName(String name) { + mServerName = name; + } + + public String getServerName() { + return mServerName; + } + + @Override + protected void readFromParcel(Parcel in) { + super.readFromParcel(in); + mServerName = in.readString(); + } + + @Override + public void writeToParcel(Parcel parcel, int flags) { + super.writeToParcel(parcel, flags); + parcel.writeString(mServerName); + } +} diff --git a/vpn/java/android/net/vpn/VpnManager.java b/vpn/java/android/net/vpn/VpnManager.java new file mode 100644 index 0000000..6c6e52a --- /dev/null +++ b/vpn/java/android/net/vpn/VpnManager.java @@ -0,0 +1,216 @@ +/* + * Copyright (C) 2007, 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.vpn; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.ServiceConnection; +import android.util.Log; + +/** + * The class provides interface to manage all VPN-related tasks, including: + * + * {@hide} + */ +public class VpnManager { + // Action for broadcasting a connectivity state. + private static final String ACTION_VPN_CONNECTIVITY = "vpn.connectivity"; + /** Key to the profile name of a connectivity broadcast event. */ + public static final String BROADCAST_PROFILE_NAME = "profile_name"; + /** Key to the connectivity state of a connectivity broadcast event. */ + public static final String BROADCAST_CONNECTION_STATE = "connection_state"; + + public static final String PROFILES_PATH = "/data/misc/vpn/profiles"; + + private static final String PACKAGE_PREFIX = + VpnManager.class.getPackage().getName() + "."; + + /** Action to start the activity of installing a new profile. */ + public static final String ACTION_VPN_INSTALL_PROFILE = + PACKAGE_PREFIX + "INSTALL_PROFILE"; + /** + * Key to the installation path in the intent of installing a new profile. + */ + public static final String KEY_INSTALLATION_PATH = "install_path"; + public static final String DEFAULT_INSTALLATION_PATH = + "/data/local/tmp/vpn"; + + // Action to start VPN installation monitor service + private static final String SERVICE_VPN_INSTALL_MONITOR = + PACKAGE_PREFIX + "INSTALLATION_MONITOR"; + + // Action to start VPN settings + private static final String ACTION_VPN_SETTINGS = PACKAGE_PREFIX + "SETTINGS"; + + private static final String TAG = VpnManager.class.getSimpleName(); + + /** + * Returns all supported VPN types. + */ + public static VpnType[] getSupportedVpnTypes() { + return VpnType.values(); + } + + private Context mContext; + + /** + * Creates a manager object with the specified context. + */ + public VpnManager(Context c) { + mContext = c; + } + + /** + * Creates a VPN profile of the specified type. + * + * @param type the VPN type + * @return the profile object + */ + public VpnProfile createVpnProfile(VpnType type) { + return createVpnProfile(type, false); + } + + /** + * Creates a VPN profile of the specified type. + * + * @param type the VPN type + * @param customized true if the profile is custom made + * @return the profile object + */ + public VpnProfile createVpnProfile(VpnType type, boolean customized) { + try { + VpnProfile p = (VpnProfile) type.getProfileClass().newInstance(); + p.setCustomized(customized); + return p; + } catch (InstantiationException e) { + return null; + } catch (IllegalAccessException e) { + return null; + } + } + + private String getServiceActionName(VpnType type) { + return PACKAGE_PREFIX + type.getServiceName(); + } + + /** + * Starts the VPN service of the specified type. + */ + public boolean startService(VpnType type) { + String serviceAction = getServiceActionName(type); + if (serviceAction != null) { + Log.i(TAG, "start service: " + serviceAction); + mContext.startService(new Intent(serviceAction)); + return true; + } else { + Log.w(TAG, "unknown vpn type to start service for: " + type); + return false; + } + } + + /** + * Stops the VPN service of the specified type. + */ + public void stopService(VpnType type) { + String serviceAction = getServiceActionName(type); + if (serviceAction != null) { + Log.i(TAG, "stop service for: " + type); + mContext.stopService(new Intent(serviceAction)); + } else { + Log.w(TAG, "unknown vpn type to stop service for: " + type); + } + } + + /** + * Binds the specified ServiceConnection with the VPN service of the + * specified type. + */ + public boolean bindService(VpnType type, ServiceConnection c) { + String serviceAction = getServiceActionName(type); + if (serviceAction == null) { + Log.w(TAG, "unknown vpn type to bind service for: " + type); + return false; + } + if (!mContext.bindService(new Intent(serviceAction), c, 0)) { + Log.w(TAG, "failed to connect to service: " + type); + return false; + } else { + Log.v(TAG, "succeeded to connect to service: " + type); + return true; + } + } + + /** Broadcasts the connectivity state of the specified profile. */ + public void broadcastConnectivity(String profileName, VpnState s) { + Intent intent = new Intent(ACTION_VPN_CONNECTIVITY); + intent.putExtra(BROADCAST_PROFILE_NAME, profileName); + intent.putExtra(BROADCAST_CONNECTION_STATE, s); + mContext.sendBroadcast(intent); + } + + public void registerConnectivityReceiver(BroadcastReceiver r) { + IntentFilter filter = new IntentFilter(); + filter.addAction(VpnManager.ACTION_VPN_CONNECTIVITY); + mContext.registerReceiver(r, filter); + } + + public void unregisterConnectivityReceiver(BroadcastReceiver r) { + mContext.unregisterReceiver(r); + } + + /** + * Starts the installation monitor service. + * The service monitors the default installtion path (under /data/local/tmp) + * and automatically starts the activity to create a new profile when new + * configuration files appear in that path. + */ + public void startInstallationMonitorService() { + mContext.startService(new Intent(SERVICE_VPN_INSTALL_MONITOR)); + } + + /** Stops the installation monitor service. */ + public void stopInstallationMonitorService() { + mContext.stopService(new Intent(SERVICE_VPN_INSTALL_MONITOR)); + } + + /** Starts the VPN settings activity. */ + public void startSettingsActivity() { + Intent intent = new Intent(ACTION_VPN_SETTINGS); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + mContext.startActivity(intent); + } + + /** + * Starts the activity to install a customized profile. + * @param installPath the path where all the configuration files are located + */ + public void startInstallProfileActivity(String installPath) { + Intent intent = new Intent(ACTION_VPN_INSTALL_PROFILE); + intent.putExtra(KEY_INSTALLATION_PATH, installPath); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + mContext.startActivity(intent); + } +} diff --git a/vpn/java/android/net/vpn/VpnProfile.aidl b/vpn/java/android/net/vpn/VpnProfile.aidl new file mode 100644 index 0000000..ad34bfc --- /dev/null +++ b/vpn/java/android/net/vpn/VpnProfile.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2007, 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.vpn; + +parcelable VpnProfile; diff --git a/vpn/java/android/net/vpn/VpnProfile.java b/vpn/java/android/net/vpn/VpnProfile.java new file mode 100644 index 0000000..cbb3b10 --- /dev/null +++ b/vpn/java/android/net/vpn/VpnProfile.java @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2007, 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.vpn; + +import android.content.Context; +import android.os.Parcel; +import android.os.Parcelable; + +import java.io.IOException; +import java.io.Serializable; + +/** + * A VPN profile. + * {@hide} + */ +public abstract class VpnProfile implements Parcelable { + private String mName; // unique display name + private String mId; // unique identifier + private String mDomainSuffices; // space separated list + private String mRouteList; // space separated list + private boolean mIsCustomized; + private transient VpnState mState = VpnState.IDLE; + + /** Sets a user-friendly name for this profile. */ + public void setName(String name) { + mName = name; + } + + public String getName() { + return mName; + } + + /** + * Sets an ID for this profile. The caller should make sure the + * uniqueness of the ID. + */ + public void setId(String id) { + mId = id; + } + + public String getId() { + return mId; + } + + /** + * Sets the domain suffices for DNS resolution. + * + * @param entries a comma-separated list of domain suffices + */ + public void setDomainSuffices(String entries) { + mDomainSuffices = entries; + } + + public String getDomainSuffices() { + return mDomainSuffices; + } + + /** + * Sets the routing info for this VPN connection. + * + * @param entries a comma-separated list of routes; each entry is in the + * format of "(network address)/(network mask)" + */ + public void setRouteList(String entries) { + mRouteList = entries; + } + + public String getRouteList() { + return mRouteList; + } + + public void setState(VpnState state) { + mState = state; + } + + public VpnState getState() { + return ((mState == null) ? VpnState.IDLE : mState); + } + + public boolean isIdle() { + return (mState == VpnState.IDLE); + } + + /** + * Returns whether this profile is custom made (as opposed to being + * created by provided user interface). + */ + public boolean isCustomized() { + return mIsCustomized; + } + + /** + * Returns the VPN type of the profile. + */ + public abstract VpnType getType(); + + void setCustomized(boolean customized) { + mIsCustomized = customized; + } + + protected void readFromParcel(Parcel in) { + mName = in.readString(); + mId = in.readString(); + mDomainSuffices = in.readString(); + mRouteList = in.readString(); + } + + public static final Parcelable.Creator CREATOR = + new Parcelable.Creator() { + @Override + public VpnProfile createFromParcel(Parcel in) { + VpnType type = Enum.valueOf(VpnType.class, in.readString()); + boolean customized = in.readInt() > 0; + VpnProfile p = new VpnManager(null).createVpnProfile(type, + customized); + if (p == null) return null; + p.readFromParcel(in); + return p; + } + + @Override + public VpnProfile[] newArray(int size) { + return new VpnProfile[size]; + } + }; + + @Override + public void writeToParcel(Parcel parcel, int flags) { + parcel.writeString(getType().toString()); + parcel.writeInt(mIsCustomized ? 1 : 0); + parcel.writeString(mName); + parcel.writeString(mId); + parcel.writeString(mDomainSuffices); + parcel.writeString(mRouteList); + } + + @Override + public int describeContents() { + return 0; + } +} diff --git a/vpn/java/android/net/vpn/VpnState.java b/vpn/java/android/net/vpn/VpnState.java new file mode 100644 index 0000000..78117e0 --- /dev/null +++ b/vpn/java/android/net/vpn/VpnState.java @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2007, 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.vpn; + +/** + * Enumeration of all VPN states. + * + * A normal VPN connection lifetime starts in {@link IDLE}. When a new + * connection is about to be set up, it goes to {@link CONNECTING} and then + * {@link CONNECTED} if successful; back to {@link IDLE} if failed. + * When the connection is about to be torn down, it goes to + * {@link DISCONNECTING} and then {@link IDLE}. + * {@hide} + */ +public enum VpnState { + CONNECTING, DISCONNECTING, CONNECTED, IDLE +} diff --git a/vpn/java/android/net/vpn/VpnType.java b/vpn/java/android/net/vpn/VpnType.java new file mode 100644 index 0000000..dcf2078 --- /dev/null +++ b/vpn/java/android/net/vpn/VpnType.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2007, 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.vpn; + +/** + * Enumeration of all supported VPN types. + * {@hide} + */ +public enum VpnType { + L2TP_IPSEC("L2TP/IPSec", L2tpIpsecProfile.class), + L2TP("L2TP", L2tpProfile.class); + + private String mDisplayName; + private Class mClass; + + VpnType(String displayName, Class klass) { + mDisplayName = displayName; + mClass = klass; + } + + public String getDisplayName() { + return mDisplayName; + } + + public Class getProfileClass() { + return mClass; + } + + public String getServiceName() { + return this.toString(); + } +} -- cgit v1.1