blob: f0dd943e93f3ea1362dbce7a4c6b7a3b4bcca47d [file] [log] [blame]
Jason Monk3d5f5512014-07-25 11:17:28 -04001/*
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 */
16package com.android.systemui.statusbar.policy;
17
Selim Cinek24ac55e2014-08-27 12:51:45 +020018import android.app.ActivityManager;
Jason Monk3d5f5512014-07-25 11:17:28 -040019import android.app.admin.DevicePolicyManager;
20import android.content.Context;
Jason Monk3d5f5512014-07-25 11:17:28 -040021import android.content.pm.PackageManager.NameNotFoundException;
22import android.net.ConnectivityManager;
23import android.net.ConnectivityManager.NetworkCallback;
24import android.net.IConnectivityManager;
Jason Monk92b5c812014-08-21 13:44:18 -040025import android.net.Network;
Jason Monk3d5f5512014-07-25 11:17:28 -040026import android.net.NetworkCapabilities;
27import android.net.NetworkRequest;
28import android.os.RemoteException;
29import android.os.ServiceManager;
30import android.text.TextUtils;
31import android.util.Log;
32
33import com.android.internal.net.VpnConfig;
34
35import java.io.FileDescriptor;
36import java.io.PrintWriter;
37import java.util.ArrayList;
38
39public 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();
Jason Monk92b5c812014-08-21 13:44:18 -040049 private static final int NO_NETWORK = -1;
50
Jason Monk3d5f5512014-07-25 11:17:28 -040051 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;
Selim Cinek24ac55e2014-08-27 12:51:45 +020056 private final ArrayList<SecurityControllerCallback> mCallbacks
57 = new ArrayList<SecurityControllerCallback>();
Jason Monk3d5f5512014-07-25 11:17:28 -040058
Jason Monk3d5f5512014-07-25 11:17:28 -040059 private VpnConfig mVpnConfig;
60 private String mVpnName;
Jason Monk92b5c812014-08-21 13:44:18 -040061 private int mCurrentVpnNetworkId = NO_NETWORK;
Selim Cinek24ac55e2014-08-27 12:51:45 +020062 private int mCurrentUserId;
Jason Monk3d5f5512014-07-25 11:17:28 -040063
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);
Selim Cinek24ac55e2014-08-27 12:51:45 +020073 mCurrentUserId = ActivityManager.getCurrentUser();
Jason Monk3d5f5512014-07-25 11:17:28 -040074 }
75
76 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
77 pw.println("SecurityController state:");
Jason Monk92b5c812014-08-21 13:44:18 -040078 pw.print(" mCurrentVpnNetworkId="); pw.println(mCurrentVpnNetworkId);
Jason Monk3d5f5512014-07-25 11:17:28 -040079 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
Selim Cinek24ac55e2014-08-27 12:51:45 +020089 public boolean hasProfileOwner() {
90 return !TextUtils.isEmpty(mDevicePolicyManager.getProfileOwnerNameAsUser(mCurrentUserId));
91 }
92
93 @Override
Jason Monk3d5f5512014-07-25 11:17:28 -040094 public String getDeviceOwnerName() {
95 return mDevicePolicyManager.getDeviceOwnerName();
96 }
97
98 @Override
Selim Cinek24ac55e2014-08-27 12:51:45 +020099 public String getProfileOwnerName() {
100 return mDevicePolicyManager.getProfileOwnerNameAsUser(mCurrentUserId);
101 }
102
103
104 @Override
Jason Monk3d5f5512014-07-25 11:17:28 -0400105 public boolean isVpnEnabled() {
Jason Monk92b5c812014-08-21 13:44:18 -0400106 return mCurrentVpnNetworkId != NO_NETWORK;
Jason Monk3d5f5512014-07-25 11:17:28 -0400107 }
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
Jeff Davidson05542602014-08-11 14:07:27 -0700125 public void disconnectFromVpn() {
Jason Monk3d5f5512014-07-25 11:17:28 -0400126 try {
Jeff Davidson05542602014-08-11 14:07:27 -0700127 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 }
Jason Monk3d5f5512014-07-25 11:17:28 -0400136 } catch (Exception e) {
137 Log.e(TAG, "Unable to disconnect from VPN", e);
138 }
139 }
140
141 @Override
Jason Monk3128f122014-09-03 13:18:57 -0400142 public void removeCallback(SecurityControllerCallback callback) {
Jason Monk3d5f5512014-07-25 11:17:28 -0400143 if (callback == null) return;
144 if (DEBUG) Log.d(TAG, "removeCallback " + callback);
145 mCallbacks.remove(callback);
146 }
147
148 @Override
Jason Monk3128f122014-09-03 13:18:57 -0400149 public void addCallback(SecurityControllerCallback callback) {
Jason Monk3d5f5512014-07-25 11:17:28 -0400150 if (callback == null || mCallbacks.contains(callback)) return;
151 if (DEBUG) Log.d(TAG, "addCallback " + callback);
152 mCallbacks.add(callback);
153 }
154
Selim Cinek24ac55e2014-08-27 12:51:45 +0200155 @Override
156 public void onUserSwitched(int newUserId) {
157 mCurrentUserId = newUserId;
158 fireCallbacks();
159 }
160
Jason Monk92b5c812014-08-21 13:44:18 -0400161 private void setCurrentNetid(int netId) {
162 if (netId != mCurrentVpnNetworkId) {
163 mCurrentVpnNetworkId = netId;
164 updateState();
165 fireCallbacks();
166 }
167 }
168
Jason Monk3d5f5512014-07-25 11:17:28 -0400169 private void fireCallbacks() {
Selim Cinek24ac55e2014-08-27 12:51:45 +0200170 for (SecurityControllerCallback callback : mCallbacks) {
171 callback.onStateChanged();
Jason Monk3d5f5512014-07-25 11:17:28 -0400172 }
173 }
174
175 private void updateState() {
176 try {
177 mVpnConfig = mConnectivityService.getVpnConfig();
178
Jason Monk3d5f5512014-07-25 11:17:28 -0400179 if (mVpnConfig != null && !mVpnConfig.legacy) {
Jeff Davidson05542602014-08-11 14:07:27 -0700180 mVpnName = VpnConfig.getVpnLabel(mContext, mVpnConfig.user).toString();
Jason Monk3d5f5512014-07-25 11:17:28 -0400181 }
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() {
Jason Monk92b5c812014-08-21 13:44:18 -0400188 @Override
189 public void onAvailable(Network network) {
190 NetworkCapabilities networkCapabilities =
191 mConnectivityManager.getNetworkCapabilities(network);
192 if (DEBUG) Log.d(TAG, "onAvailable " + network.netId + " : " + networkCapabilities);
Raju Yadavaedae722014-12-22 14:54:13 +0100193 if (networkCapabilities != null &&
194 networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN)) {
Jason Monk92b5c812014-08-21 13:44:18 -0400195 setCurrentNetid(network.netId);
196 }
197 };
198
199 // TODO Find another way to receive VPN lost. This may be delayed depending on
200 // how long the VPN connection is held on to.
201 @Override
202 public void onLost(Network network) {
203 if (DEBUG) Log.d(TAG, "onLost " + network.netId);
204 if (mCurrentVpnNetworkId == network.netId) {
205 setCurrentNetid(NO_NETWORK);
206 }
207 };
Jason Monk3d5f5512014-07-25 11:17:28 -0400208 };
209
210}