SecurityControllerImpl.java revision 05542603dd4f1e0ea47a3dca01de3999a9a329a9
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 */
16package com.android.systemui.statusbar.policy;
17
18import android.app.admin.DevicePolicyManager;
19import android.content.Context;
20import android.content.Intent;
21import android.content.pm.PackageManager.NameNotFoundException;
22import android.net.ConnectivityManager;
23import android.net.ConnectivityManager.NetworkCallback;
24import android.net.IConnectivityManager;
25import android.net.NetworkCapabilities;
26import android.net.NetworkRequest;
27import android.os.RemoteException;
28import android.os.ServiceManager;
29import android.text.TextUtils;
30import android.util.Log;
31
32import com.android.internal.net.VpnConfig;
33
34import java.io.FileDescriptor;
35import java.io.PrintWriter;
36import java.util.ArrayList;
37
38public class SecurityControllerImpl implements SecurityController {
39
40    private static final String TAG = "SecurityController";
41    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
42
43    private static final NetworkRequest REQUEST = new NetworkRequest.Builder()
44            .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
45            .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
46            .removeCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED)
47            .build();
48    private final Context mContext;
49    private final ConnectivityManager mConnectivityManager;
50    private final IConnectivityManager mConnectivityService = IConnectivityManager.Stub.asInterface(
51                ServiceManager.getService(Context.CONNECTIVITY_SERVICE));
52    private final DevicePolicyManager mDevicePolicyManager;
53    private final ArrayList<VpnCallback> mCallbacks = new ArrayList<VpnCallback>();
54
55    private boolean mIsVpnEnabled;
56    private VpnConfig mVpnConfig;
57    private String mVpnName;
58
59    public SecurityControllerImpl(Context context) {
60        mContext = context;
61        mDevicePolicyManager = (DevicePolicyManager)
62                context.getSystemService(Context.DEVICE_POLICY_SERVICE);
63        mConnectivityManager = (ConnectivityManager)
64                context.getSystemService(Context.CONNECTIVITY_SERVICE);
65
66        // TODO: re-register network callback on user change.
67        mConnectivityManager.registerNetworkCallback(REQUEST, mNetworkCallback);
68    }
69
70    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
71        pw.println("SecurityController state:");
72        pw.print("  mIsVpnEnabled="); pw.println(mIsVpnEnabled);
73        pw.print("  mVpnConfig="); pw.println(mVpnConfig);
74        pw.print("  mVpnName="); pw.println(mVpnName);
75    }
76
77    @Override
78    public boolean hasDeviceOwner() {
79        return !TextUtils.isEmpty(mDevicePolicyManager.getDeviceOwner());
80    }
81
82    @Override
83    public String getDeviceOwnerName() {
84        return mDevicePolicyManager.getDeviceOwnerName();
85    }
86
87    @Override
88    public boolean isVpnEnabled() {
89        // TODO: Remove once using NetworkCallback for updates.
90        updateState();
91
92        return mIsVpnEnabled;
93    }
94
95    @Override
96    public boolean isLegacyVpn() {
97        return mVpnConfig.legacy;
98    }
99
100    @Override
101    public String getVpnApp() {
102        return mVpnName;
103    }
104
105    @Override
106    public String getLegacyVpnName() {
107        return mVpnConfig.session;
108    }
109
110    @Override
111    public void disconnectFromVpn() {
112        try {
113            if (isLegacyVpn()) {
114                mConnectivityService.prepareVpn(VpnConfig.LEGACY_VPN, VpnConfig.LEGACY_VPN);
115            } else {
116                // Prevent this app from initiating VPN connections in the future without user
117                // intervention.
118                mConnectivityService.setVpnPackageAuthorization(false);
119
120                mConnectivityService.prepareVpn(mVpnConfig.user, VpnConfig.LEGACY_VPN);
121            }
122        } catch (Exception e) {
123            Log.e(TAG, "Unable to disconnect from VPN", e);
124        }
125    }
126
127    @Override
128    public void addCallback(VpnCallback callback) {
129        if (callback == null) return;
130        if (DEBUG) Log.d(TAG, "removeCallback " + callback);
131        mCallbacks.remove(callback);
132    }
133
134    @Override
135    public void removeCallback(VpnCallback callback) {
136        if (callback == null || mCallbacks.contains(callback)) return;
137        if (DEBUG) Log.d(TAG, "addCallback " + callback);
138        mCallbacks.add(callback);
139    }
140
141    private void fireCallbacks() {
142        for (VpnCallback callback : mCallbacks) {
143            callback.onVpnStateChanged();
144        }
145    }
146
147    private void updateState() {
148        try {
149            mVpnConfig = mConnectivityService.getVpnConfig();
150
151            // TODO: Remove once using NetworkCallback for updates.
152            mIsVpnEnabled = mVpnConfig != null;
153
154            if (mVpnConfig != null && !mVpnConfig.legacy) {
155                mVpnName = VpnConfig.getVpnLabel(mContext, mVpnConfig.user).toString();
156            }
157        } catch (RemoteException | NameNotFoundException e) {
158            Log.w(TAG, "Unable to get current VPN", e);
159        }
160    }
161
162    private final NetworkCallback mNetworkCallback = new NetworkCallback() {
163        public void onCapabilitiesChanged(android.net.Network network,
164                android.net.NetworkCapabilities networkCapabilities) {
165            if (DEBUG) Log.d(TAG, "onCapabilitiesChanged " + networkCapabilities);
166            mIsVpnEnabled = networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN);
167            updateState();
168            fireCallbacks();
169        }
170    };
171
172}
173