diff options
-rw-r--r-- | core/java/android/net/VpnBuilder.java | 413 | ||||
-rw-r--r-- | core/java/com/android/internal/net/VpnConfig.java | 8 | ||||
-rw-r--r-- | core/res/AndroidManifest.xml | 8 | ||||
-rwxr-xr-x | core/res/res/values/strings.xml | 8 | ||||
-rw-r--r-- | packages/VpnDialogs/AndroidManifest.xml | 1 | ||||
-rw-r--r-- | packages/VpnDialogs/src/com/android/vpndialogs/ManageDialog.java | 6 | ||||
-rw-r--r-- | services/java/com/android/server/connectivity/Vpn.java | 86 |
7 files changed, 49 insertions, 481 deletions
diff --git a/core/java/android/net/VpnBuilder.java b/core/java/android/net/VpnBuilder.java deleted file mode 100644 index 4582523..0000000 --- a/core/java/android/net/VpnBuilder.java +++ /dev/null @@ -1,413 +0,0 @@ -/* - * Copyright (C) 2011 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; - -import android.app.Activity; -import android.app.PendingIntent; -import android.content.Context; -import android.content.Intent; -import android.os.ParcelFileDescriptor; -import android.os.RemoteException; -import android.os.ServiceManager; - -import com.android.internal.net.VpnConfig; - -import java.net.InetAddress; -import java.net.Inet4Address; -import java.net.Inet6Address; -import java.net.DatagramSocket; -import java.net.Socket; -import java.util.ArrayList; - -/** - * VpnBuilder is a framework which enables applications to build their - * own VPN solutions. In general, it creates a virtual network interface, - * configures addresses and routing rules, and returns a file descriptor - * to the application. Each read from the descriptor retrieves an outgoing - * packet which was routed to the interface. Each write to the descriptor - * injects an incoming packet just like it was received from the interface. - * The framework is running on Internet Protocol (IP), so packets are - * always started with IP headers. The application then completes a VPN - * connection by processing and exchanging packets with a remote server - * over a secured tunnel. - * - * <p>Letting applications intercept packets raises huge security concerns. - * Besides, a VPN application can easily break the network, and two of them - * may conflict with each other. The framework takes several actions to - * address these issues. Here are some key points: - * <ul> - * <li>User action is required to create a VPN connection.</li> - * <li>There can be only one VPN connection running at the same time. The - * existing interface is deactivated when a new one is created.</li> - * <li>A system-managed notification is shown during the lifetime of a - * VPN connection.</li> - * <li>A system-managed dialog gives the information of the current VPN - * connection. It also provides a button to disconnect.</li> - * <li>The network is restored automatically when the file descriptor is - * closed. It also covers the cases when a VPN application is crashed - * or killed by the system.</li> - * </ul> - * - * <p>There are two primary methods in this class: {@link #prepare} and - * {@link #establish}. The former deals with the user action and stops - * the existing VPN connection created by another application. The latter - * creates a VPN interface using the parameters supplied to this builder. - * An application must call {@link #prepare} to grant the right to create - * an interface, and it can be revoked at any time by another application. - * The application got revoked is notified by an {@link #ACTION_VPN_REVOKED} - * broadcast. Here are the general steps to create a VPN connection: - * <ol> - * <li>When the user press the button to connect, call {@link #prepare} - * and launch the intent if necessary.</li> - * <li>Register a receiver for {@link #ACTION_VPN_REVOKED} broadcasts. - * <li>Connect to the remote server and negotiate the network parameters - * of the VPN connection.</li> - * <li>Use those parameters to configure a VpnBuilder and create a VPN - * interface by calling {@link #establish}.</li> - * <li>Start processing packets between the returned file descriptor and - * the VPN tunnel.</li> - * <li>When an {@link #ACTION_VPN_REVOKED} broadcast is received, the - * interface is already deactivated by the framework. Close the file - * descriptor and shut down the VPN tunnel gracefully. - * </ol> - * Methods in this class can be used in activities and services. However, - * the intent returned from {@link #prepare} must be launched from an - * activity. The broadcast receiver can be registered at any time, but doing - * it before calling {@link #establish} effectively avoids race conditions. - * - * <p class="note">Using this class requires - * {@link android.Manifest.permission#VPN} permission. - * @hide - */ -public class VpnBuilder { - - /** - * Broadcast intent action indicating that the VPN application has been - * revoked. This can be only received by the target application on the - * receiver explicitly registered using {@link Context#registerReceiver}. - * - * <p>This is a protected intent that can only be sent by the system. - */ - public static final String ACTION_VPN_REVOKED = VpnConfig.ACTION_VPN_REVOKED; - - /** - * Use IConnectivityManager instead since those methods are hidden and - * not available in ConnectivityManager. - */ - private static IConnectivityManager getService() { - return IConnectivityManager.Stub.asInterface( - ServiceManager.getService(Context.CONNECTIVITY_SERVICE)); - } - - /** - * Prepare to establish a VPN connection. This method returns {@code null} - * if the VPN application is already prepared. Otherwise, it returns an - * {@link Intent} to a system activity. The application should launch the - * activity using {@link Activity#startActivityForResult} to get itself - * prepared. The activity may pop up a dialog to require user action, and - * the result will come back to the application through its - * {@link Activity#onActivityResult}. The application becomes prepared if - * the result is {@link Activity#RESULT_OK}, and it is granted to create a - * VPN interface by calling {@link #establish}. - * - * <p>Only one application can be granted at the same time. The right - * is revoked when another application is granted. The application - * losing the right will be notified by an {@link #ACTION_VPN_REVOKED} - * broadcast, and its VPN interface will be deactivated by the system. - * The application should then notify the remote server and disconnect - * gracefully. Unless the application becomes prepared again, subsequent - * calls to {@link #establish} will return {@code null}. - * - * @see #establish - * @see #ACTION_VPN_REVOKED - */ - public static Intent prepare(Context context) { - try { - if (getService().prepareVpn(context.getPackageName(), null)) { - return null; - } - } catch (RemoteException e) { - // ignore - } - return VpnConfig.getIntentForConfirmation(); - } - - private VpnConfig mConfig = new VpnConfig(); - private StringBuilder mAddresses = new StringBuilder(); - private StringBuilder mRoutes = new StringBuilder(); - - /** - * Set the name of this session. It will be displayed in system-managed - * dialogs and notifications. This is recommended not required. - */ - public VpnBuilder setSession(String session) { - mConfig.session = session; - return this; - } - - /** - * Set the {@link PendingIntent} to an activity for users to configure - * the VPN connection. If it is not set, the button to configure will - * not be shown in system-managed dialogs. - */ - public VpnBuilder setConfigureIntent(PendingIntent intent) { - mConfig.configureIntent = intent; - return this; - } - - /** - * Set the maximum transmission unit (MTU) of the VPN interface. If it - * is not set, the default value in the operating system will be used. - * - * @throws IllegalArgumentException if the value is not positive. - */ - public VpnBuilder setMtu(int mtu) { - if (mtu <= 0) { - throw new IllegalArgumentException("Bad mtu"); - } - mConfig.mtu = mtu; - return this; - } - - /** - * Private method to validate address and prefixLength. - */ - private static void check(InetAddress address, int prefixLength) { - if (address.isLoopbackAddress()) { - throw new IllegalArgumentException("Bad address"); - } - if (address instanceof Inet4Address) { - if (prefixLength < 0 || prefixLength > 32) { - throw new IllegalArgumentException("Bad prefixLength"); - } - } else if (address instanceof Inet6Address) { - if (prefixLength < 0 || prefixLength > 128) { - throw new IllegalArgumentException("Bad prefixLength"); - } - } else { - throw new IllegalArgumentException("Unsupported family"); - } - } - - /** - * Convenience method to add a network address to the VPN interface - * using a numeric address string. See {@link InetAddress} for the - * definitions of numeric address formats. - * - * @throws IllegalArgumentException if the address is invalid. - * @see #addAddress(InetAddress, int) - */ - public VpnBuilder addAddress(String address, int prefixLength) { - return addAddress(InetAddress.parseNumericAddress(address), prefixLength); - } - - /** - * Add a network address to the VPN interface. Both IPv4 and IPv6 - * addresses are supported. At least one address must be set before - * calling {@link #establish}. - * - * @throws IllegalArgumentException if the address is invalid. - */ - public VpnBuilder addAddress(InetAddress address, int prefixLength) { - check(address, prefixLength); - - if (address.isAnyLocalAddress()) { - throw new IllegalArgumentException("Bad address"); - } - - mAddresses.append(String.format(" %s/%d", address.getHostAddress(), prefixLength)); - return this; - } - - /** - * Convenience method to add a network route to the VPN interface - * using a numeric address string. See {@link InetAddress} for the - * definitions of numeric address formats. - * - * @see #addRoute(InetAddress, int) - * @throws IllegalArgumentException if the route is invalid. - */ - public VpnBuilder addRoute(String address, int prefixLength) { - return addRoute(InetAddress.parseNumericAddress(address), prefixLength); - } - - /** - * Add a network route to the VPN interface. Both IPv4 and IPv6 - * routes are supported. - * - * @throws IllegalArgumentException if the route is invalid. - */ - public VpnBuilder addRoute(InetAddress address, int prefixLength) { - check(address, prefixLength); - - int offset = prefixLength / 8; - byte[] bytes = address.getAddress(); - if (offset < bytes.length) { - if ((byte)(bytes[offset] << (prefixLength % 8)) != 0) { - throw new IllegalArgumentException("Bad address"); - } - while (++offset < bytes.length) { - if (bytes[offset] != 0) { - throw new IllegalArgumentException("Bad address"); - } - } - } - - mRoutes.append(String.format(" %s/%d", address.getHostAddress(), prefixLength)); - return this; - } - - /** - * Convenience method to add a DNS server to the VPN connection - * using a numeric address string. See {@link InetAddress} for the - * definitions of numeric address formats. - * - * @throws IllegalArgumentException if the address is invalid. - * @see #addDnsServer(InetAddress) - */ - public VpnBuilder addDnsServer(String address) { - return addDnsServer(InetAddress.parseNumericAddress(address)); - } - - /** - * Add a DNS server to the VPN connection. Both IPv4 and IPv6 - * addresses are supported. If none is set, the DNS servers of - * the default network will be used. - * - * @throws IllegalArgumentException if the address is invalid. - */ - public VpnBuilder addDnsServer(InetAddress address) { - if (address.isLoopbackAddress() || address.isAnyLocalAddress()) { - throw new IllegalArgumentException("Bad address"); - } - if (mConfig.dnsServers == null) { - mConfig.dnsServers = new ArrayList<String>(); - } - mConfig.dnsServers.add(address.getHostAddress()); - return this; - } - - /** - * Add a search domain to the DNS resolver. - */ - public VpnBuilder addSearchDomain(String domain) { - if (mConfig.searchDomains == null) { - mConfig.searchDomains = new ArrayList<String>(); - } - mConfig.searchDomains.add(domain); - return this; - } - - /** - * Create a VPN interface using the parameters supplied to this builder. - * The interface works on IP packets, and a file descriptor is returned - * for the application to access them. Each read retrieves an outgoing - * packet which was routed to the interface. Each write injects an - * incoming packet just like it was received from the interface. The file - * descriptor is put into non-blocking mode by default to avoid blocking - * Java threads. To use the file descriptor completely in native space, - * see {@link ParcelFileDescriptor#detachFd()}. The application MUST - * close the file descriptor when the VPN connection is terminated. The - * VPN interface will be removed and the network will be restored by the - * framework automatically. - * - * <p>To avoid conflicts, there can be only one active VPN interface at - * the same time. Usually network parameters are never changed during the - * lifetime of a VPN connection. It is also common for an application to - * create a new file descriptor after closing the previous one. However, - * it is rare but not impossible to have two interfaces while performing a - * seamless handover. In this case, the old interface will be deactivated - * when the new one is configured successfully. Both file descriptors are - * valid but now outgoing packets will be routed to the new interface. - * Therefore, after draining the old file descriptor, the application MUST - * close it and start using the new file descriptor. If the new interface - * cannot be created, the existing interface and its file descriptor remain - * untouched. - * - * <p>An exception will be thrown if the interface cannot be created for - * any reason. However, this method returns {@code null} if the application - * is not prepared or is revoked by another application. This helps solve - * possible race conditions while handling {@link #ACTION_VPN_REVOKED} - * broadcasts. - * - * @return {@link ParcelFileDescriptor} of the VPN interface, or - * {@code null} if the application is not prepared. - * @throws IllegalArgumentException if a parameter is not accepted by the - * operating system. - * @throws IllegalStateException if a parameter cannot be applied by the - * operating system. - * @see #prepare - */ - public ParcelFileDescriptor establish() { - mConfig.addresses = mAddresses.toString(); - mConfig.routes = mRoutes.toString(); - - try { - return getService().establishVpn(mConfig); - } catch (RemoteException e) { - throw new IllegalStateException(e); - } - } - - /** - * Protect a socket from VPN connections. The socket will be bound to the - * current default network interface, so its traffic will not be forwarded - * through VPN. This method is useful if some connections need to be kept - * outside of VPN. For example, a VPN tunnel should protect itself if its - * destination is covered by VPN routes. Otherwise its outgoing packets - * will be sent back to the VPN interface and cause an infinite loop. - * - * <p>The socket is NOT closed by this method. - * - * @return {@code true} on success. - */ - public static boolean protect(int socket) { - ParcelFileDescriptor dup = null; - try { - dup = ParcelFileDescriptor.fromFd(socket); - return getService().protectVpn(dup); - } catch (Exception e) { - return false; - } finally { - try { - dup.close(); - } catch (Exception e) { - // ignore - } - } - } - - /** - * Protect a {@link Socket} from VPN connections. - * - * @return {@code true} on success. - * @see #protect(int) - */ - public static boolean protect(Socket socket) { - return protect(socket.getFileDescriptor$().getInt$()); - } - - /** - * Protect a {@link DatagramSocket} from VPN connections. - * - * @return {@code true} on success. - * @see #protect(int) - */ - public static boolean protect(DatagramSocket socket) { - return protect(socket.getFileDescriptor$().getInt$()); - } -} diff --git a/core/java/com/android/internal/net/VpnConfig.java b/core/java/com/android/internal/net/VpnConfig.java index d36be10..d61a579 100644 --- a/core/java/com/android/internal/net/VpnConfig.java +++ b/core/java/com/android/internal/net/VpnConfig.java @@ -32,7 +32,7 @@ import java.util.List; */ public class VpnConfig implements Parcelable { - public static final String ACTION_VPN_REVOKED = "android.net.vpn.action.REVOKED"; + public static final String SERVICE_INTERFACE = "android.net.VpnService"; public static final String LEGACY_VPN = "[Legacy VPN]"; @@ -52,7 +52,7 @@ public class VpnConfig implements Parcelable { PendingIntent.FLAG_NO_CREATE : PendingIntent.FLAG_CANCEL_CURRENT); } - public String packagz; + public String user; public String interfaze; public String session; public int mtu = -1; @@ -70,7 +70,7 @@ public class VpnConfig implements Parcelable { @Override public void writeToParcel(Parcel out, int flags) { - out.writeString(packagz); + out.writeString(user); out.writeString(interfaze); out.writeString(session); out.writeInt(mtu); @@ -87,7 +87,7 @@ public class VpnConfig implements Parcelable { @Override public VpnConfig createFromParcel(Parcel in) { VpnConfig config = new VpnConfig(); - config.packagz = in.readString(); + config.user = in.readString(); config.interfaze = in.readString(); config.session = in.readString(); config.mtu = in.readInt(); diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index f99a94c..19a25cc 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -393,14 +393,6 @@ android:description="@string/permdesc_nfc" android:label="@string/permlab_nfc" /> - <!-- Allows applications to provide VPN functionality. - @hide Pending API council approval --> - <permission android:name="android.permission.VPN" - android:permissionGroup="android.permission-group.NETWORK" - android:protectionLevel="dangerous" - android:description="@string/permdesc_vpn" - android:label="@string/permlab_vpn" /> - <!-- Allows an application to use SIP service --> <permission android:name="android.permission.USE_SIP" android:permissionGroup="android.permission-group.NETWORK" diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index c5aa4b2..ae14dc8 100755 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -1358,14 +1358,6 @@ with Near Field Communication (NFC) tags, cards, and readers.</string> <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. --> - <string name="permlab_vpn">intercept and modify all network traffic</string> - <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. --> - <string name="permdesc_vpn">Allows an application to intercept and - inspect all network traffic to establish a VPN connection. - Malicious applications may monitor, redirect, or modify network packets - without your knowledge.</string> - - <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. --> <string name="permlab_disableKeyguard">disable keylock</string> <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. --> <string name="permdesc_disableKeyguard">Allows an application to disable diff --git a/packages/VpnDialogs/AndroidManifest.xml b/packages/VpnDialogs/AndroidManifest.xml index bd5f739..8e062b7 100644 --- a/packages/VpnDialogs/AndroidManifest.xml +++ b/packages/VpnDialogs/AndroidManifest.xml @@ -5,7 +5,6 @@ <application android:label="VpnDialogs" android:allowBackup="false" > <activity android:name=".ConfirmDialog" - android:permission="android.permission.VPN" android:theme="@style/transparent"> <intent-filter> <action android:name="android.intent.action.MAIN"/> diff --git a/packages/VpnDialogs/src/com/android/vpndialogs/ManageDialog.java b/packages/VpnDialogs/src/com/android/vpndialogs/ManageDialog.java index 40c0a02..d668e98 100644 --- a/packages/VpnDialogs/src/com/android/vpndialogs/ManageDialog.java +++ b/packages/VpnDialogs/src/com/android/vpndialogs/ManageDialog.java @@ -79,7 +79,7 @@ public class ManageDialog extends Activity implements Handler.Callback, mDataTransmitted = (TextView) view.findViewById(R.id.data_transmitted); mDataReceived = (TextView) view.findViewById(R.id.data_received); - if (mConfig.packagz.equals(VpnConfig.LEGACY_VPN)) { + if (mConfig.user.equals(VpnConfig.LEGACY_VPN)) { mDialog = new AlertDialog.Builder(this) .setIcon(android.R.drawable.ic_dialog_info) .setTitle(R.string.legacy_title) @@ -89,7 +89,7 @@ public class ManageDialog extends Activity implements Handler.Callback, .create(); } else { PackageManager pm = getPackageManager(); - ApplicationInfo app = pm.getApplicationInfo(mConfig.packagz, 0); + ApplicationInfo app = pm.getApplicationInfo(mConfig.user, 0); mDialog = new AlertDialog.Builder(this) .setIcon(app.loadIcon(pm)) .setTitle(app.loadLabel(pm)) @@ -131,7 +131,7 @@ public class ManageDialog extends Activity implements Handler.Callback, if (which == AlertDialog.BUTTON_POSITIVE) { mConfig.configureIntent.send(); } else if (which == AlertDialog.BUTTON_NEUTRAL) { - mService.prepareVpn(mConfig.packagz, VpnConfig.LEGACY_VPN); + mService.prepareVpn(mConfig.user, VpnConfig.LEGACY_VPN); } } catch (Exception e) { Log.e(TAG, "onClick", e); diff --git a/services/java/com/android/server/connectivity/Vpn.java b/services/java/com/android/server/connectivity/Vpn.java index ecbad09..b69cc31 100644 --- a/services/java/com/android/server/connectivity/Vpn.java +++ b/services/java/com/android/server/connectivity/Vpn.java @@ -54,7 +54,6 @@ import java.util.Arrays; public class Vpn extends INetworkManagementEventObserver.Stub { private final static String TAG = "Vpn"; - private final static String VPN = android.Manifest.permission.VPN; private final Context mContext; private final VpnCallback mCallback; @@ -69,18 +68,6 @@ public class Vpn extends INetworkManagementEventObserver.Stub { } /** - * Protect a socket from routing changes by binding it to the given - * interface. The socket is NOT closed by this method. - * - * @param socket The socket to be bound. - * @param name The name of the interface. - */ - public void protect(ParcelFileDescriptor socket, String interfaze) { - mContext.enforceCallingPermission(VPN, "protect"); - jniProtect(socket.getFd(), interfaze); - } - - /** * Prepare for a VPN application. This method is designed to solve * race conditions. It first compares the current prepared package * with {@code oldPackage}. If they are the same, the prepared @@ -115,13 +102,6 @@ public class Vpn extends INetworkManagementEventObserver.Stub { throw new SecurityException("Unauthorized Caller"); } - // Check the permission of the given package. - PackageManager pm = mContext.getPackageManager(); - if (!newPackage.equals(VpnConfig.LEGACY_VPN) && - pm.checkPermission(VPN, newPackage) != PackageManager.PERMISSION_GRANTED) { - throw new SecurityException(newPackage + " does not have " + VPN); - } - // Reset the interface and hide the notification. if (mInterface != null) { jniReset(mInterface); @@ -130,12 +110,9 @@ public class Vpn extends INetworkManagementEventObserver.Stub { mInterface = null; } - // Send out the broadcast or stop LegacyVpnRunner. + // Revoke the connection or stop LegacyVpnRunner. if (!mPackage.equals(VpnConfig.LEGACY_VPN)) { - Intent intent = new Intent(VpnConfig.ACTION_VPN_REVOKED); - intent.setPackage(mPackage); - intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); - mContext.sendBroadcast(intent); + // TODO } else if (mLegacyVpnRunner != null) { mLegacyVpnRunner.exit(); mLegacyVpnRunner = null; @@ -147,6 +124,22 @@ public class Vpn extends INetworkManagementEventObserver.Stub { } /** + * Protect a socket from routing changes by binding it to the given + * interface. The socket is NOT closed by this method. + * + * @param socket The socket to be bound. + * @param name The name of the interface. + */ + public void protect(ParcelFileDescriptor socket, String interfaze) throws Exception { + PackageManager pm = mContext.getPackageManager(); + ApplicationInfo app = pm.getApplicationInfo(mPackage, 0); + if (Binder.getCallingUid() != app.uid) { + throw new SecurityException("Unauthorized Caller"); + } + jniProtect(socket.getFd(), interfaze); + } + + /** * Establish a VPN network and return the file descriptor of the VPN * interface. This methods returns {@code null} if the application is * revoked or not prepared. @@ -155,9 +148,6 @@ public class Vpn extends INetworkManagementEventObserver.Stub { * @return The file descriptor of the VPN interface. */ public synchronized ParcelFileDescriptor establish(VpnConfig config) { - // Check the permission of the caller. - mContext.enforceCallingPermission(VPN, "establish"); - // Check if the caller is already prepared. PackageManager pm = mContext.getPackageManager(); ApplicationInfo app = null; @@ -170,6 +160,9 @@ public class Vpn extends INetworkManagementEventObserver.Stub { return null; } + // Check if the service is properly declared. + // TODO + // Load the label. String label = app.loadLabel(pm).toString(); @@ -198,6 +191,7 @@ public class Vpn extends INetworkManagementEventObserver.Stub { if (config.routes != null) { jniSetRoutes(interfaze, config.routes); } + // TODO: bind the service if (mInterface != null && !mInterface.equals(interfaze)) { jniReset(mInterface); } @@ -211,23 +205,25 @@ public class Vpn extends INetworkManagementEventObserver.Stub { throw e; } - // Override DNS servers and search domains. - mCallback.override(config.dnsServers, config.searchDomains); - // Fill more values. - config.packagz = mPackage; + config.user = mPackage; config.interfaze = mInterface; - // Show the notification! + // Override DNS servers and show the notification. + long identity = Binder.clearCallingIdentity(); + mCallback.override(config.dnsServers, config.searchDomains); showNotification(config, label, bitmap); + Binder.restoreCallingIdentity(identity); return tun; } // INetworkManagementEventObserver.Stub + @Override public void interfaceAdded(String interfaze) { } // INetworkManagementEventObserver.Stub + @Override public synchronized void interfaceStatusChanged(String interfaze, boolean up) { if (!up && mLegacyVpnRunner != null) { mLegacyVpnRunner.check(interfaze); @@ -235,22 +231,28 @@ public class Vpn extends INetworkManagementEventObserver.Stub { } // INetworkManagementEventObserver.Stub - public synchronized void interfaceLinkStateChanged(String interfaze, boolean up) { - if (!up && mLegacyVpnRunner != null) { - mLegacyVpnRunner.check(interfaze); - } + @Override + public void interfaceLinkStateChanged(String interfaze, boolean up) { + interfaceStatusChanged(interfaze, up); } // INetworkManagementEventObserver.Stub + @Override public synchronized void interfaceRemoved(String interfaze) { if (interfaze.equals(mInterface) && jniCheck(interfaze) == 0) { + long identity = Binder.clearCallingIdentity(); mCallback.restore(); hideNotification(); + Binder.restoreCallingIdentity(identity); mInterface = null; + // TODO: unbind the service } } - public void limitReached(String limitName, String iface) {} + // INetworkManagementEventObserver.Stub + @Override + public void limitReached(String limit, String interfaze) { + } private void showNotification(VpnConfig config, String label, Bitmap icon) { NotificationManager nm = (NotificationManager) @@ -263,7 +265,6 @@ public class Vpn extends INetworkManagementEventObserver.Stub { mContext.getString(R.string.vpn_text_long, config.session); config.startTime = SystemClock.elapsedRealtime(); - long identity = Binder.clearCallingIdentity(); Notification notification = new Notification.Builder(mContext) .setSmallIcon(R.drawable.vpn_connected) .setLargeIcon(icon) @@ -274,7 +275,6 @@ public class Vpn extends INetworkManagementEventObserver.Stub { .setOngoing(true) .getNotification(); nm.notify(R.drawable.vpn_connected, notification); - Binder.restoreCallingIdentity(identity); } } @@ -283,9 +283,7 @@ public class Vpn extends INetworkManagementEventObserver.Stub { mContext.getSystemService(Context.NOTIFICATION_SERVICE); if (nm != null) { - long identity = Binder.clearCallingIdentity(); nm.cancel(R.drawable.vpn_connected); - Binder.restoreCallingIdentity(identity); } } @@ -355,8 +353,8 @@ public class Vpn extends INetworkManagementEventObserver.Stub { mOuterInterface = mConfig.interfaze; // Legacy VPN is not a real package, so we use it to carry the key. - mInfo.key = mConfig.packagz; - mConfig.packagz = VpnConfig.LEGACY_VPN; + mInfo.key = mConfig.user; + mConfig.user = VpnConfig.LEGACY_VPN; } public void check(String interfaze) { |