Home | History | Annotate | Download | only in policy
      1 /*
      2  * Copyright (C) 2014 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 package com.android.systemui.statusbar.policy;
     17 
     18 import android.app.ActivityManager;
     19 import android.app.admin.DevicePolicyManager;
     20 import android.content.Context;
     21 import android.content.pm.PackageManager.NameNotFoundException;
     22 import android.net.ConnectivityManager;
     23 import android.net.ConnectivityManager.NetworkCallback;
     24 import android.net.IConnectivityManager;
     25 import android.net.Network;
     26 import android.net.NetworkCapabilities;
     27 import android.net.NetworkRequest;
     28 import android.os.RemoteException;
     29 import android.os.ServiceManager;
     30 import android.text.TextUtils;
     31 import android.util.Log;
     32 
     33 import com.android.internal.net.VpnConfig;
     34 
     35 import java.io.FileDescriptor;
     36 import java.io.PrintWriter;
     37 import java.util.ArrayList;
     38 
     39 public class SecurityControllerImpl implements SecurityController {
     40 
     41     private static final String TAG = "SecurityController";
     42     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
     43 
     44     private static final NetworkRequest REQUEST = new NetworkRequest.Builder()
     45             .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
     46             .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
     47             .removeCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED)
     48             .build();
     49     private static final int NO_NETWORK = -1;
     50 
     51     private final Context mContext;
     52     private final ConnectivityManager mConnectivityManager;
     53     private final IConnectivityManager mConnectivityService = IConnectivityManager.Stub.asInterface(
     54                 ServiceManager.getService(Context.CONNECTIVITY_SERVICE));
     55     private final DevicePolicyManager mDevicePolicyManager;
     56     private final ArrayList<SecurityControllerCallback> mCallbacks
     57             = new ArrayList<SecurityControllerCallback>();
     58 
     59     private VpnConfig mVpnConfig;
     60     private String mVpnName;
     61     private int mCurrentVpnNetworkId = NO_NETWORK;
     62     private int mCurrentUserId;
     63 
     64     public SecurityControllerImpl(Context context) {
     65         mContext = context;
     66         mDevicePolicyManager = (DevicePolicyManager)
     67                 context.getSystemService(Context.DEVICE_POLICY_SERVICE);
     68         mConnectivityManager = (ConnectivityManager)
     69                 context.getSystemService(Context.CONNECTIVITY_SERVICE);
     70 
     71         // TODO: re-register network callback on user change.
     72         mConnectivityManager.registerNetworkCallback(REQUEST, mNetworkCallback);
     73         mCurrentUserId = ActivityManager.getCurrentUser();
     74     }
     75 
     76     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
     77         pw.println("SecurityController state:");
     78         pw.print("  mCurrentVpnNetworkId="); pw.println(mCurrentVpnNetworkId);
     79         pw.print("  mVpnConfig="); pw.println(mVpnConfig);
     80         pw.print("  mVpnName="); pw.println(mVpnName);
     81     }
     82 
     83     @Override
     84     public boolean hasDeviceOwner() {
     85         return !TextUtils.isEmpty(mDevicePolicyManager.getDeviceOwner());
     86     }
     87 
     88     @Override
     89     public boolean hasProfileOwner() {
     90         return !TextUtils.isEmpty(mDevicePolicyManager.getProfileOwnerNameAsUser(mCurrentUserId));
     91     }
     92 
     93     @Override
     94     public String getDeviceOwnerName() {
     95         return mDevicePolicyManager.getDeviceOwnerName();
     96     }
     97 
     98     @Override
     99     public String getProfileOwnerName() {
    100         return mDevicePolicyManager.getProfileOwnerNameAsUser(mCurrentUserId);
    101     }
    102 
    103 
    104     @Override
    105     public boolean isVpnEnabled() {
    106         return mCurrentVpnNetworkId != NO_NETWORK;
    107     }
    108 
    109     @Override
    110     public boolean isLegacyVpn() {
    111         return mVpnConfig.legacy;
    112     }
    113 
    114     @Override
    115     public String getVpnApp() {
    116         return mVpnName;
    117     }
    118 
    119     @Override
    120     public String getLegacyVpnName() {
    121         return mVpnConfig.session;
    122     }
    123 
    124     @Override
    125     public void disconnectFromVpn() {
    126         try {
    127             if (isLegacyVpn()) {
    128                 mConnectivityService.prepareVpn(VpnConfig.LEGACY_VPN, VpnConfig.LEGACY_VPN);
    129             } else {
    130                 // Prevent this app from initiating VPN connections in the future without user
    131                 // intervention.
    132                 mConnectivityService.setVpnPackageAuthorization(false);
    133 
    134                 mConnectivityService.prepareVpn(mVpnConfig.user, VpnConfig.LEGACY_VPN);
    135             }
    136         } catch (Exception e) {
    137             Log.e(TAG, "Unable to disconnect from VPN", e);
    138         }
    139     }
    140 
    141     @Override
    142     public void removeCallback(SecurityControllerCallback callback) {
    143         if (callback == null) return;
    144         if (DEBUG) Log.d(TAG, "removeCallback " + callback);
    145         mCallbacks.remove(callback);
    146     }
    147 
    148     @Override
    149     public void addCallback(SecurityControllerCallback callback) {
    150         if (callback == null || mCallbacks.contains(callback)) return;
    151         if (DEBUG) Log.d(TAG, "addCallback " + callback);
    152         mCallbacks.add(callback);
    153     }
    154 
    155     @Override
    156     public void onUserSwitched(int newUserId) {
    157         mCurrentUserId = newUserId;
    158         fireCallbacks();
    159     }
    160 
    161     private void setCurrentNetid(int netId) {
    162         if (netId != mCurrentVpnNetworkId) {
    163             mCurrentVpnNetworkId = netId;
    164             updateState();
    165             fireCallbacks();
    166         }
    167     }
    168 
    169     private void fireCallbacks() {
    170         for (SecurityControllerCallback callback : mCallbacks) {
    171             callback.onStateChanged();
    172         }
    173     }
    174 
    175     private void updateState() {
    176         try {
    177             mVpnConfig = mConnectivityService.getVpnConfig();
    178 
    179             if (mVpnConfig != null && !mVpnConfig.legacy) {
    180                 mVpnName = VpnConfig.getVpnLabel(mContext, mVpnConfig.user).toString();
    181             }
    182         } catch (RemoteException | NameNotFoundException e) {
    183             Log.w(TAG, "Unable to get current VPN", e);
    184         }
    185     }
    186 
    187     private final NetworkCallback mNetworkCallback = new NetworkCallback() {
    188         @Override
    189         public void onAvailable(Network network) {
    190             NetworkCapabilities networkCapabilities =
    191                     mConnectivityManager.getNetworkCapabilities(network);
    192             if (DEBUG) Log.d(TAG, "onAvailable " + network.netId + " : " + networkCapabilities);
    193             if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN)) {
    194                 setCurrentNetid(network.netId);
    195             }
    196         };
    197 
    198         // TODO Find another way to receive VPN lost.  This may be delayed depending on
    199         // how long the VPN connection is held on to.
    200         @Override
    201         public void onLost(Network network) {
    202             if (DEBUG) Log.d(TAG, "onLost " + network.netId);
    203             if (mCurrentVpnNetworkId == network.netId) {
    204                 setCurrentNetid(NO_NETWORK);
    205             }
    206         };
    207     };
    208 
    209 }
    210