169ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey/* 269ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey * Copyright (C) 2012 The Android Open Source Project 369ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey * 469ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License"); 569ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey * you may not use this file except in compliance with the License. 669ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey * You may obtain a copy of the License at 769ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey * 869ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey * http://www.apache.org/licenses/LICENSE-2.0 969ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey * 1069ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey * Unless required by applicable law or agreed to in writing, software 1169ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS, 1269ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1369ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey * See the License for the specific language governing permissions and 1469ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey * limitations under the License. 1569ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey */ 1669ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 1769ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkeypackage com.android.server.net; 1869ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 1969ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkeyimport static android.Manifest.permission.CONNECTIVITY_INTERNAL; 20b41c9f7f39939cee8d226eb5e506c3f0573f44f5Xiaohui Chenimport static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NONE; 2115e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasaniimport static android.net.NetworkPolicyManager.FIREWALL_RULE_ALLOW; 2215e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasaniimport static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT; 23a249aee10b621a94c986f4823d840e33c2a7d480Robin Leeimport static android.provider.Settings.ACTION_VPN_SETTINGS; 2469ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 2569ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkeyimport android.app.Notification; 2669ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkeyimport android.app.NotificationManager; 2769ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkeyimport android.app.PendingIntent; 2869ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkeyimport android.content.BroadcastReceiver; 2969ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkeyimport android.content.Context; 3069ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkeyimport android.content.Intent; 3169ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkeyimport android.content.IntentFilter; 320cb7903ddedbbb8a8171926e4460b74af589369dLorenzo Colittiimport android.net.ConnectivityManager; 3369ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkeyimport android.net.LinkProperties; 344ca19e8377f33e8a80684fb4ee67f5a4bdc9ea76Chad Brubakerimport android.net.LinkAddress; 3569ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkeyimport android.net.NetworkInfo; 3669ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkeyimport android.net.NetworkInfo.DetailedState; 3769ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkeyimport android.net.NetworkInfo.State; 3815e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasaniimport android.net.NetworkPolicyManager; 3969ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkeyimport android.os.INetworkManagementService; 4069ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkeyimport android.os.RemoteException; 4169ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkeyimport android.security.Credentials; 4269ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkeyimport android.security.KeyStore; 43ad4cd0c01966017e2f51ec3d23d06de3874f100cLorenzo Colittiimport android.system.Os; 4469ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkeyimport android.text.TextUtils; 4569ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkeyimport android.util.Slog; 4669ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 4769ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkeyimport com.android.internal.R; 48282cfefea0fbbd299839e353e6d30affdcd4a55cChris Wrenimport com.android.internal.messages.nano.SystemMessageProto.SystemMessage; 4969ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkeyimport com.android.internal.net.VpnConfig; 5069ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkeyimport com.android.internal.net.VpnProfile; 51af759c52ce01fe6b5144957e38da956af01a217bGeoffrey Pitschimport com.android.internal.notification.SystemNotificationChannels; 5269ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkeyimport com.android.internal.util.Preconditions; 5369ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkeyimport com.android.server.ConnectivityService; 5491c6a64a04c2d8b27b886d96a56800ae24efb7a9Jeff Sharkeyimport com.android.server.EventLogTags; 5569ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkeyimport com.android.server.connectivity.Vpn; 5669ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 574ca19e8377f33e8a80684fb4ee67f5a4bdc9ea76Chad Brubakerimport java.util.List; 584ca19e8377f33e8a80684fb4ee67f5a4bdc9ea76Chad Brubaker 5969ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey/** 6069ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey * State tracker for lockdown mode. Watches for normal {@link NetworkInfo} to be 6169ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey * connected and kicks off VPN connection, managing any required {@code netd} 6269ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey * firewall rules. 6369ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey */ 6469ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkeypublic class LockdownVpnTracker { 6569ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey private static final String TAG = "LockdownVpnTracker"; 6669ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 6769ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey /** Number of VPN attempts before waiting for user intervention. */ 6869ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey private static final int MAX_ERROR_COUNT = 4; 6969ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 7069ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey private static final String ACTION_LOCKDOWN_RESET = "com.android.server.action.LOCKDOWN_RESET"; 714fa63b2d5e3b2e2a85bf17a9bf056cbdfb7046f0Jeff Sharkey 72ad4cd0c01966017e2f51ec3d23d06de3874f100cLorenzo Colitti private static final int ROOT_UID = 0; 73ad4cd0c01966017e2f51ec3d23d06de3874f100cLorenzo Colitti 7469ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey private final Context mContext; 7569ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey private final INetworkManagementService mNetService; 7669ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey private final ConnectivityService mConnService; 7769ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey private final Vpn mVpn; 7869ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey private final VpnProfile mProfile; 7969ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 8069ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey private final Object mStateLock = new Object(); 8169ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 824fa63b2d5e3b2e2a85bf17a9bf056cbdfb7046f0Jeff Sharkey private final PendingIntent mConfigIntent; 834fa63b2d5e3b2e2a85bf17a9bf056cbdfb7046f0Jeff Sharkey private final PendingIntent mResetIntent; 8469ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 8569ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey private String mAcceptedEgressIface; 8669ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey private String mAcceptedIface; 874ca19e8377f33e8a80684fb4ee67f5a4bdc9ea76Chad Brubaker private List<LinkAddress> mAcceptedSourceAddr; 8869ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 8969ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey private int mErrorCount; 9069ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 9169ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey public static boolean isEnabled() { 9269ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey return KeyStore.getInstance().contains(Credentials.LOCKDOWN_VPN); 9369ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey } 9469ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 9569ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey public LockdownVpnTracker(Context context, INetworkManagementService netService, 9669ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey ConnectivityService connService, Vpn vpn, VpnProfile profile) { 9769ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey mContext = Preconditions.checkNotNull(context); 9869ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey mNetService = Preconditions.checkNotNull(netService); 9969ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey mConnService = Preconditions.checkNotNull(connService); 10069ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey mVpn = Preconditions.checkNotNull(vpn); 10169ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey mProfile = Preconditions.checkNotNull(profile); 10269ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 1034fa63b2d5e3b2e2a85bf17a9bf056cbdfb7046f0Jeff Sharkey final Intent configIntent = new Intent(ACTION_VPN_SETTINGS); 1044fa63b2d5e3b2e2a85bf17a9bf056cbdfb7046f0Jeff Sharkey mConfigIntent = PendingIntent.getActivity(mContext, 0, configIntent, 0); 1054fa63b2d5e3b2e2a85bf17a9bf056cbdfb7046f0Jeff Sharkey 106580dd31a68c65b4af68147d52d57f60e0bd52dbeJeff Sharkey final Intent resetIntent = new Intent(ACTION_LOCKDOWN_RESET); 107580dd31a68c65b4af68147d52d57f60e0bd52dbeJeff Sharkey resetIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); 108580dd31a68c65b4af68147d52d57f60e0bd52dbeJeff Sharkey mResetIntent = PendingIntent.getBroadcast(mContext, 0, resetIntent, 0); 10969ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey } 11069ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 11169ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey private BroadcastReceiver mResetReceiver = new BroadcastReceiver() { 11269ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey @Override 11369ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey public void onReceive(Context context, Intent intent) { 11469ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey reset(); 11569ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey } 11669ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey }; 11769ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 11869ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey /** 11969ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey * Watch for state changes to both active egress network, kicking off a VPN 12069ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey * connection when ready, or setting firewall rules once VPN is connected. 12169ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey */ 12269ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey private void handleStateChangedLocked() { 12369ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 12469ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey final NetworkInfo egressInfo = mConnService.getActiveNetworkInfoUnfiltered(); 12569ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey final LinkProperties egressProp = mConnService.getActiveLinkProperties(); 12669ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 12769ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey final NetworkInfo vpnInfo = mVpn.getNetworkInfo(); 12869ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey final VpnConfig vpnConfig = mVpn.getLegacyVpnConfig(); 12969ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 13069ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey // Restart VPN when egress network disconnected or changed 13169ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey final boolean egressDisconnected = egressInfo == null 13269ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey || State.DISCONNECTED.equals(egressInfo.getState()); 13369ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey final boolean egressChanged = egressProp == null 13469ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey || !TextUtils.equals(mAcceptedEgressIface, egressProp.getInterfaceName()); 1350cb7903ddedbbb8a8171926e4460b74af589369dLorenzo Colitti 1360cb7903ddedbbb8a8171926e4460b74af589369dLorenzo Colitti final String egressTypeName = (egressInfo == null) ? 1370cb7903ddedbbb8a8171926e4460b74af589369dLorenzo Colitti null : ConnectivityManager.getNetworkTypeName(egressInfo.getType()); 1380cb7903ddedbbb8a8171926e4460b74af589369dLorenzo Colitti final String egressIface = (egressProp == null) ? 1390cb7903ddedbbb8a8171926e4460b74af589369dLorenzo Colitti null : egressProp.getInterfaceName(); 1400cb7903ddedbbb8a8171926e4460b74af589369dLorenzo Colitti Slog.d(TAG, "handleStateChanged: egress=" + egressTypeName + 1410cb7903ddedbbb8a8171926e4460b74af589369dLorenzo Colitti " " + mAcceptedEgressIface + "->" + egressIface); 1420cb7903ddedbbb8a8171926e4460b74af589369dLorenzo Colitti 14369ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey if (egressDisconnected || egressChanged) { 14469ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey mAcceptedEgressIface = null; 145b21298a686b04d55ff97223dd317497845713f4bJeff Davidson mVpn.stopLegacyVpnPrivileged(); 14669ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey } 14757666934b4a161cc2fb77eef15d0b894aaf8f173Jeff Sharkey if (egressDisconnected) { 14857666934b4a161cc2fb77eef15d0b894aaf8f173Jeff Sharkey hideNotification(); 14957666934b4a161cc2fb77eef15d0b894aaf8f173Jeff Sharkey return; 15057666934b4a161cc2fb77eef15d0b894aaf8f173Jeff Sharkey } 15169ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 15291c6a64a04c2d8b27b886d96a56800ae24efb7a9Jeff Sharkey final int egressType = egressInfo.getType(); 15391c6a64a04c2d8b27b886d96a56800ae24efb7a9Jeff Sharkey if (vpnInfo.getDetailedState() == DetailedState.FAILED) { 15491c6a64a04c2d8b27b886d96a56800ae24efb7a9Jeff Sharkey EventLogTags.writeLockdownVpnError(egressType); 15591c6a64a04c2d8b27b886d96a56800ae24efb7a9Jeff Sharkey } 15691c6a64a04c2d8b27b886d96a56800ae24efb7a9Jeff Sharkey 15769ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey if (mErrorCount > MAX_ERROR_COUNT) { 15869ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey showNotification(R.string.vpn_lockdown_error, R.drawable.vpn_disconnected); 15969ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 16069ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey } else if (egressInfo.isConnected() && !vpnInfo.isConnectedOrConnecting()) { 16169ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey if (mProfile.isValidLockdownProfile()) { 16269ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey Slog.d(TAG, "Active network connected; starting VPN"); 16391c6a64a04c2d8b27b886d96a56800ae24efb7a9Jeff Sharkey EventLogTags.writeLockdownVpnConnecting(egressType); 16469ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey showNotification(R.string.vpn_lockdown_connecting, R.drawable.vpn_disconnected); 16569ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 16669ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey mAcceptedEgressIface = egressProp.getInterfaceName(); 167421fab8a7b429073512967e54a469ce440772e15Jeff Sharkey try { 168b21298a686b04d55ff97223dd317497845713f4bJeff Davidson // Use the privileged method because Lockdown VPN is initiated by the system, so 169b21298a686b04d55ff97223dd317497845713f4bJeff Davidson // no additional permission checks are necessary. 170b21298a686b04d55ff97223dd317497845713f4bJeff Davidson mVpn.startLegacyVpnPrivileged(mProfile, KeyStore.getInstance(), egressProp); 171421fab8a7b429073512967e54a469ce440772e15Jeff Sharkey } catch (IllegalStateException e) { 172421fab8a7b429073512967e54a469ce440772e15Jeff Sharkey mAcceptedEgressIface = null; 173421fab8a7b429073512967e54a469ce440772e15Jeff Sharkey Slog.e(TAG, "Failed to start VPN", e); 174421fab8a7b429073512967e54a469ce440772e15Jeff Sharkey showNotification(R.string.vpn_lockdown_error, R.drawable.vpn_disconnected); 175421fab8a7b429073512967e54a469ce440772e15Jeff Sharkey } 17669ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey } else { 17769ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey Slog.e(TAG, "Invalid VPN profile; requires IP-based server and DNS"); 17869ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey showNotification(R.string.vpn_lockdown_error, R.drawable.vpn_disconnected); 17969ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey } 18069ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 18169ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey } else if (vpnInfo.isConnected() && vpnConfig != null) { 18269ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey final String iface = vpnConfig.interfaze; 1834ca19e8377f33e8a80684fb4ee67f5a4bdc9ea76Chad Brubaker final List<LinkAddress> sourceAddrs = vpnConfig.addresses; 18469ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 18569ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey if (TextUtils.equals(iface, mAcceptedIface) 1864ca19e8377f33e8a80684fb4ee67f5a4bdc9ea76Chad Brubaker && sourceAddrs.equals(mAcceptedSourceAddr)) { 18769ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey return; 18869ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey } 18969ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 1904ca19e8377f33e8a80684fb4ee67f5a4bdc9ea76Chad Brubaker Slog.d(TAG, "VPN connected using iface=" + iface + 1914ca19e8377f33e8a80684fb4ee67f5a4bdc9ea76Chad Brubaker ", sourceAddr=" + sourceAddrs.toString()); 19291c6a64a04c2d8b27b886d96a56800ae24efb7a9Jeff Sharkey EventLogTags.writeLockdownVpnConnected(egressType); 19369ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey showNotification(R.string.vpn_lockdown_connected, R.drawable.vpn_connected); 19469ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 195f07c7b9fd0a640bff4bf7690373613da217fe69bJeff Sharkey final NetworkInfo clone = new NetworkInfo(egressInfo); 196f07c7b9fd0a640bff4bf7690373613da217fe69bJeff Sharkey augmentNetworkInfo(clone); 197f07c7b9fd0a640bff4bf7690373613da217fe69bJeff Sharkey mConnService.sendConnectedBroadcast(clone); 19869ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey } 19969ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey } 20069ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 20169ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey public void init() { 202580dd31a68c65b4af68147d52d57f60e0bd52dbeJeff Sharkey synchronized (mStateLock) { 203580dd31a68c65b4af68147d52d57f60e0bd52dbeJeff Sharkey initLocked(); 204580dd31a68c65b4af68147d52d57f60e0bd52dbeJeff Sharkey } 205580dd31a68c65b4af68147d52d57f60e0bd52dbeJeff Sharkey } 206580dd31a68c65b4af68147d52d57f60e0bd52dbeJeff Sharkey 207580dd31a68c65b4af68147d52d57f60e0bd52dbeJeff Sharkey private void initLocked() { 208580dd31a68c65b4af68147d52d57f60e0bd52dbeJeff Sharkey Slog.d(TAG, "initLocked()"); 20969ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 21057666934b4a161cc2fb77eef15d0b894aaf8f173Jeff Sharkey mVpn.setEnableTeardown(false); 211c3736bc10da63d6a351d3f8e7781ff1d67ecc9a6Robin Lee mVpn.setLockdown(true); 21269ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 21369ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey final IntentFilter resetFilter = new IntentFilter(ACTION_LOCKDOWN_RESET); 21469ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey mContext.registerReceiver(mResetReceiver, resetFilter, CONNECTIVITY_INTERNAL, null); 21569ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 216aca5e7e3dc369923a8655f1de84bba903b3b1143Robin Lee handleStateChangedLocked(); 21769ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey } 21869ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 21969ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey public void shutdown() { 220580dd31a68c65b4af68147d52d57f60e0bd52dbeJeff Sharkey synchronized (mStateLock) { 221580dd31a68c65b4af68147d52d57f60e0bd52dbeJeff Sharkey shutdownLocked(); 222580dd31a68c65b4af68147d52d57f60e0bd52dbeJeff Sharkey } 223580dd31a68c65b4af68147d52d57f60e0bd52dbeJeff Sharkey } 224580dd31a68c65b4af68147d52d57f60e0bd52dbeJeff Sharkey 225580dd31a68c65b4af68147d52d57f60e0bd52dbeJeff Sharkey private void shutdownLocked() { 226580dd31a68c65b4af68147d52d57f60e0bd52dbeJeff Sharkey Slog.d(TAG, "shutdownLocked()"); 22769ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 22869ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey mAcceptedEgressIface = null; 22969ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey mErrorCount = 0; 23069ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 231b21298a686b04d55ff97223dd317497845713f4bJeff Davidson mVpn.stopLegacyVpnPrivileged(); 232c3736bc10da63d6a351d3f8e7781ff1d67ecc9a6Robin Lee mVpn.setLockdown(false); 23369ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey hideNotification(); 23469ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 23569ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey mContext.unregisterReceiver(mResetReceiver); 23657666934b4a161cc2fb77eef15d0b894aaf8f173Jeff Sharkey mVpn.setEnableTeardown(true); 23769ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey } 23869ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 23969ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey public void reset() { 2400cb7903ddedbbb8a8171926e4460b74af589369dLorenzo Colitti Slog.d(TAG, "reset()"); 24169ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey synchronized (mStateLock) { 242580dd31a68c65b4af68147d52d57f60e0bd52dbeJeff Sharkey // cycle tracker, reset error count, and trigger retry 243580dd31a68c65b4af68147d52d57f60e0bd52dbeJeff Sharkey shutdownLocked(); 244580dd31a68c65b4af68147d52d57f60e0bd52dbeJeff Sharkey initLocked(); 24569ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey handleStateChangedLocked(); 24669ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey } 24769ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey } 24869ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 2490cb7903ddedbbb8a8171926e4460b74af589369dLorenzo Colitti public void onNetworkInfoChanged() { 25069ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey synchronized (mStateLock) { 25169ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey handleStateChangedLocked(); 25269ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey } 25369ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey } 25469ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 25569ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey public void onVpnStateChanged(NetworkInfo info) { 25669ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey if (info.getDetailedState() == DetailedState.FAILED) { 25769ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey mErrorCount++; 25869ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey } 25969ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey synchronized (mStateLock) { 26069ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey handleStateChangedLocked(); 26169ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey } 26269ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey } 26369ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 264f07c7b9fd0a640bff4bf7690373613da217fe69bJeff Sharkey public void augmentNetworkInfo(NetworkInfo info) { 2650b81be6f79ec3d1b9441c21a3cefc629be1450c8Jeff Sharkey if (info.isConnected()) { 2660b81be6f79ec3d1b9441c21a3cefc629be1450c8Jeff Sharkey final NetworkInfo vpnInfo = mVpn.getNetworkInfo(); 2670b81be6f79ec3d1b9441c21a3cefc629be1450c8Jeff Sharkey info.setDetailedState(vpnInfo.getDetailedState(), vpnInfo.getReason(), null); 2680b81be6f79ec3d1b9441c21a3cefc629be1450c8Jeff Sharkey } 26969ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey } 27069ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 27169ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey private void showNotification(int titleRes, int iconRes) { 272af759c52ce01fe6b5144957e38da956af01a217bGeoffrey Pitsch final Notification.Builder builder = 273af759c52ce01fe6b5144957e38da956af01a217bGeoffrey Pitsch new Notification.Builder(mContext, SystemNotificationChannels.VPN) 274af759c52ce01fe6b5144957e38da956af01a217bGeoffrey Pitsch .setWhen(0) 275af759c52ce01fe6b5144957e38da956af01a217bGeoffrey Pitsch .setSmallIcon(iconRes) 276af759c52ce01fe6b5144957e38da956af01a217bGeoffrey Pitsch .setContentTitle(mContext.getString(titleRes)) 277af759c52ce01fe6b5144957e38da956af01a217bGeoffrey Pitsch .setContentText(mContext.getString(R.string.vpn_lockdown_config)) 278af759c52ce01fe6b5144957e38da956af01a217bGeoffrey Pitsch .setContentIntent(mConfigIntent) 279af759c52ce01fe6b5144957e38da956af01a217bGeoffrey Pitsch .setOngoing(true) 280af759c52ce01fe6b5144957e38da956af01a217bGeoffrey Pitsch .addAction(R.drawable.ic_menu_refresh, mContext.getString(R.string.reset), 281af759c52ce01fe6b5144957e38da956af01a217bGeoffrey Pitsch mResetIntent) 282af759c52ce01fe6b5144957e38da956af01a217bGeoffrey Pitsch .setColor(mContext.getColor( 283af759c52ce01fe6b5144957e38da956af01a217bGeoffrey Pitsch com.android.internal.R.color.system_notification_accent_color)); 2844fa63b2d5e3b2e2a85bf17a9bf056cbdfb7046f0Jeff Sharkey 285282cfefea0fbbd299839e353e6d30affdcd4a55cChris Wren NotificationManager.from(mContext).notify(null, SystemMessage.NOTE_VPN_STATUS, 286282cfefea0fbbd299839e353e6d30affdcd4a55cChris Wren builder.build()); 28769ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey } 28869ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey 28969ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey private void hideNotification() { 290282cfefea0fbbd299839e353e6d30affdcd4a55cChris Wren NotificationManager.from(mContext).cancel(null, SystemMessage.NOTE_VPN_STATUS); 29169ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey } 29269ddab4575ff684c533c995e07ca15fe18543fc0Jeff Sharkey} 293