Move to Android N-MR1 SDK.
[android_tools.git] / sdk / sources / android-25 / com / android / systemui / statusbar / policy / SecurityControllerImpl.java
blob07d3b596bc056005978cf5d49f32ecb4b73f7a32
1 /*
2 * Copyright (C) 2014 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 package com.android.systemui.statusbar.policy;
18 import android.app.ActivityManager;
19 import android.app.admin.DevicePolicyManager;
20 import android.content.Context;
21 import android.content.pm.ApplicationInfo;
22 import android.content.pm.PackageManager;
23 import android.content.pm.PackageManager.NameNotFoundException;
24 import android.content.pm.UserInfo;
25 import android.net.ConnectivityManager;
26 import android.net.ConnectivityManager.NetworkCallback;
27 import android.net.IConnectivityManager;
28 import android.net.Network;
29 import android.net.NetworkCapabilities;
30 import android.net.NetworkRequest;
31 import android.os.RemoteException;
32 import android.os.ServiceManager;
33 import android.os.UserHandle;
34 import android.os.UserManager;
35 import android.util.Log;
36 import android.util.SparseArray;
38 import com.android.internal.annotations.GuardedBy;
39 import com.android.internal.net.LegacyVpnInfo;
40 import com.android.internal.net.VpnConfig;
41 import com.android.systemui.R;
43 import java.io.FileDescriptor;
44 import java.io.PrintWriter;
45 import java.util.ArrayList;
47 public class SecurityControllerImpl implements SecurityController {
49 private static final String TAG = "SecurityController";
50 private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
52 private static final NetworkRequest REQUEST = new NetworkRequest.Builder()
53 .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
54 .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
55 .removeCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED)
56 .build();
57 private static final int NO_NETWORK = -1;
59 private static final String VPN_BRANDED_META_DATA = "com.android.systemui.IS_BRANDED";
61 private final Context mContext;
62 private final ConnectivityManager mConnectivityManager;
63 private final IConnectivityManager mConnectivityManagerService;
64 private final DevicePolicyManager mDevicePolicyManager;
65 private final PackageManager mPackageManager;
66 private final UserManager mUserManager;
68 @GuardedBy("mCallbacks")
69 private final ArrayList<SecurityControllerCallback> mCallbacks = new ArrayList<>();
71 private SparseArray<VpnConfig> mCurrentVpns = new SparseArray<>();
72 private int mCurrentUserId;
73 private int mVpnUserId;
75 public SecurityControllerImpl(Context context) {
76 mContext = context;
77 mDevicePolicyManager = (DevicePolicyManager)
78 context.getSystemService(Context.DEVICE_POLICY_SERVICE);
79 mConnectivityManager = (ConnectivityManager)
80 context.getSystemService(Context.CONNECTIVITY_SERVICE);
81 mConnectivityManagerService = IConnectivityManager.Stub.asInterface(
82 ServiceManager.getService(Context.CONNECTIVITY_SERVICE));
83 mPackageManager = context.getPackageManager();
84 mUserManager = (UserManager)
85 context.getSystemService(Context.USER_SERVICE);
87 // TODO: re-register network callback on user change.
88 mConnectivityManager.registerNetworkCallback(REQUEST, mNetworkCallback);
89 onUserSwitched(ActivityManager.getCurrentUser());
92 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
93 pw.println("SecurityController state:");
94 pw.print(" mCurrentVpns={");
95 for (int i = 0 ; i < mCurrentVpns.size(); i++) {
96 if (i > 0) {
97 pw.print(", ");
99 pw.print(mCurrentVpns.keyAt(i));
100 pw.print('=');
101 pw.print(mCurrentVpns.valueAt(i).user);
103 pw.println("}");
106 @Override
107 public boolean isDeviceManaged() {
108 return mDevicePolicyManager.isDeviceManaged();
111 @Override
112 public String getDeviceOwnerName() {
113 return mDevicePolicyManager.getDeviceOwnerNameOnAnyUser();
116 @Override
117 public boolean hasProfileOwner() {
118 return mDevicePolicyManager.getProfileOwnerAsUser(mCurrentUserId) != null;
121 @Override
122 public String getProfileOwnerName() {
123 for (int profileId : mUserManager.getProfileIdsWithDisabled(mCurrentUserId)) {
124 String name = mDevicePolicyManager.getProfileOwnerNameAsUser(profileId);
125 if (name != null) {
126 return name;
129 return null;
132 @Override
133 public String getPrimaryVpnName() {
134 VpnConfig cfg = mCurrentVpns.get(mVpnUserId);
135 if (cfg != null) {
136 return getNameForVpnConfig(cfg, new UserHandle(mVpnUserId));
137 } else {
138 return null;
142 @Override
143 public String getProfileVpnName() {
144 for (int profileId : mUserManager.getProfileIdsWithDisabled(mVpnUserId)) {
145 if (profileId == mVpnUserId) {
146 continue;
148 VpnConfig cfg = mCurrentVpns.get(profileId);
149 if (cfg != null) {
150 return getNameForVpnConfig(cfg, UserHandle.of(profileId));
153 return null;
156 @Override
157 public boolean isVpnEnabled() {
158 for (int profileId : mUserManager.getProfileIdsWithDisabled(mVpnUserId)) {
159 if (mCurrentVpns.get(profileId) != null) {
160 return true;
163 return false;
166 @Override
167 public boolean isVpnRestricted() {
168 UserHandle currentUser = new UserHandle(mCurrentUserId);
169 return mUserManager.getUserInfo(mCurrentUserId).isRestricted()
170 || mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_VPN, currentUser);
173 @Override
174 public boolean isVpnBranded() {
175 VpnConfig cfg = mCurrentVpns.get(mVpnUserId);
176 if (cfg == null) {
177 return false;
180 String packageName = getPackageNameForVpnConfig(cfg);
181 if (packageName == null) {
182 return false;
185 return isVpnPackageBranded(packageName);
188 @Override
189 public void removeCallback(SecurityControllerCallback callback) {
190 synchronized (mCallbacks) {
191 if (callback == null) return;
192 if (DEBUG) Log.d(TAG, "removeCallback " + callback);
193 mCallbacks.remove(callback);
197 @Override
198 public void addCallback(SecurityControllerCallback callback) {
199 synchronized (mCallbacks) {
200 if (callback == null || mCallbacks.contains(callback)) return;
201 if (DEBUG) Log.d(TAG, "addCallback " + callback);
202 mCallbacks.add(callback);
206 @Override
207 public void onUserSwitched(int newUserId) {
208 mCurrentUserId = newUserId;
209 final UserInfo newUserInfo = mUserManager.getUserInfo(newUserId);
210 if (newUserInfo.isRestricted()) {
211 // VPN for a restricted profile is routed through its owner user
212 mVpnUserId = newUserInfo.restrictedProfileParentId;
213 } else {
214 mVpnUserId = mCurrentUserId;
216 fireCallbacks();
219 private String getNameForVpnConfig(VpnConfig cfg, UserHandle user) {
220 if (cfg.legacy) {
221 return mContext.getString(R.string.legacy_vpn_name);
223 // The package name for an active VPN is stored in the 'user' field of its VpnConfig
224 final String vpnPackage = cfg.user;
225 try {
226 Context userContext = mContext.createPackageContextAsUser(mContext.getPackageName(),
227 0 /* flags */, user);
228 return VpnConfig.getVpnLabel(userContext, vpnPackage).toString();
229 } catch (NameNotFoundException nnfe) {
230 Log.e(TAG, "Package " + vpnPackage + " is not present", nnfe);
231 return null;
235 private void fireCallbacks() {
236 synchronized (mCallbacks) {
237 for (SecurityControllerCallback callback : mCallbacks) {
238 callback.onStateChanged();
243 private void updateState() {
244 // Find all users with an active VPN
245 SparseArray<VpnConfig> vpns = new SparseArray<>();
246 try {
247 for (UserInfo user : mUserManager.getUsers()) {
248 VpnConfig cfg = mConnectivityManagerService.getVpnConfig(user.id);
249 if (cfg == null) {
250 continue;
251 } else if (cfg.legacy) {
252 // Legacy VPNs should do nothing if the network is disconnected. Third-party
253 // VPN warnings need to continue as traffic can still go to the app.
254 LegacyVpnInfo legacyVpn = mConnectivityManagerService.getLegacyVpnInfo(user.id);
255 if (legacyVpn == null || legacyVpn.state != LegacyVpnInfo.STATE_CONNECTED) {
256 continue;
259 vpns.put(user.id, cfg);
261 } catch (RemoteException rme) {
262 // Roll back to previous state
263 Log.e(TAG, "Unable to list active VPNs", rme);
264 return;
266 mCurrentVpns = vpns;
269 private String getPackageNameForVpnConfig(VpnConfig cfg) {
270 if (cfg.legacy) {
271 return null;
273 return cfg.user;
276 private boolean isVpnPackageBranded(String packageName) {
277 boolean isBranded;
278 try {
279 ApplicationInfo info = mPackageManager.getApplicationInfo(packageName,
280 PackageManager.GET_META_DATA);
281 if (info == null || info.metaData == null || !info.isSystemApp()) {
282 return false;
284 isBranded = info.metaData.getBoolean(VPN_BRANDED_META_DATA, false);
285 } catch (NameNotFoundException e) {
286 return false;
288 return isBranded;
291 private final NetworkCallback mNetworkCallback = new NetworkCallback() {
292 @Override
293 public void onAvailable(Network network) {
294 if (DEBUG) Log.d(TAG, "onAvailable " + network.netId);
295 updateState();
296 fireCallbacks();
299 // TODO Find another way to receive VPN lost. This may be delayed depending on
300 // how long the VPN connection is held on to.
301 @Override
302 public void onLost(Network network) {
303 if (DEBUG) Log.d(TAG, "onLost " + network.netId);
304 updateState();
305 fireCallbacks();