1310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh/* 2310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh * Copyright (C) 2011 The Android Open Source Project 3310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh * 4310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh * Licensed under the Apache License, Version 2.0 (the "License"); 5310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh * you may not use this file except in compliance with the License. 6310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh * You may obtain a copy of the License at 7310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh * 8310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh * http://www.apache.org/licenses/LICENSE-2.0 9310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh * 10310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh * Unless required by applicable law or agreed to in writing, software 11310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh * distributed under the License is distributed on an "AS IS" BASIS, 12310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh * See the License for the specific language governing permissions and 14310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh * limitations under the License. 15310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh */ 16310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh 17310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yehpackage com.android.settings.vpn2; 18310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh 197bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Leeimport android.annotation.UiThread; 207bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Leeimport android.annotation.WorkerThread; 212bd92d5d0685144aad566b9d29454fb519ff0371Robin Leeimport android.app.AppOpsManager; 22310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yehimport android.content.Context; 232bd92d5d0685144aad566b9d29454fb519ff0371Robin Leeimport android.content.Intent; 242bd92d5d0685144aad566b9d29454fb519ff0371Robin Leeimport android.content.pm.PackageInfo; 252bd92d5d0685144aad566b9d29454fb519ff0371Robin Leeimport android.content.pm.PackageManager; 262bd92d5d0685144aad566b9d29454fb519ff0371Robin Leeimport android.net.ConnectivityManager.NetworkCallback; 277bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Leeimport android.net.ConnectivityManager; 28bbb5094be6673929bcb808cdeaf748a73be4dbf0Chia-chi Yehimport android.net.IConnectivityManager; 292bd92d5d0685144aad566b9d29454fb519ff0371Robin Leeimport android.net.Network; 302bd92d5d0685144aad566b9d29454fb519ff0371Robin Leeimport android.net.NetworkCapabilities; 312bd92d5d0685144aad566b9d29454fb519ff0371Robin Leeimport android.net.NetworkRequest; 32310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yehimport android.os.Bundle; 33310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yehimport android.os.Handler; 34310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yehimport android.os.Message; 352bd92d5d0685144aad566b9d29454fb519ff0371Robin Leeimport android.os.RemoteException; 36bbb5094be6673929bcb808cdeaf748a73be4dbf0Chia-chi Yehimport android.os.ServiceManager; 372bd92d5d0685144aad566b9d29454fb519ff0371Robin Leeimport android.os.UserHandle; 38ee27b9de8f2ab17d50b90dd8c13546aebb4e9fc1Julia Reynoldsimport android.os.UserManager; 39310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yehimport android.security.Credentials; 40310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yehimport android.security.KeyStore; 4139b467482d1bf256a111c757e9b7621c6f523271Jason Monkimport android.support.v7.preference.Preference; 4239b467482d1bf256a111c757e9b7621c6f523271Jason Monkimport android.support.v7.preference.PreferenceGroup; 4339b467482d1bf256a111c757e9b7621c6f523271Jason Monkimport android.support.v7.preference.PreferenceScreen; 447bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Leeimport android.util.ArrayMap; 457bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Leeimport android.util.ArraySet; 467bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Leeimport android.util.Log; 47310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yehimport android.view.Menu; 489fd7ac1ec7c0c3984f225a237bd6e3dbafc7f831Jeff Sharkeyimport android.view.MenuInflater; 49310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yehimport android.view.MenuItem; 50310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh 519d1bfd1e8de6e46137a9571507c03526880d6a46Chris Wrenimport com.android.internal.logging.MetricsProto.MetricsEvent; 5297fd85fd9776f3fb5c35217e82bcbcb5aea8416dChia-chi Yehimport com.android.internal.net.LegacyVpnInfo; 53d95ec871138ebb367cfd8b67b4814438ac30c628Chia-chi Yehimport com.android.internal.net.VpnConfig; 54c6e84c09590ec5e4da287fba32dd53775156ae76Jeff Sharkeyimport com.android.internal.net.VpnProfile; 55f5de1db28a61d159e62ef42f64a2cdcb316d0c2cJeff Sharkeyimport com.android.internal.util.ArrayUtils; 5614c2ac4dcb17c27e065384e69c9f2e24dcbf22aaVictor Changimport com.android.settings.GearPreference; 5714c2ac4dcb17c27e065384e69c9f2e24dcbf22aaVictor Changimport com.android.settings.GearPreference.OnGearClickListener; 58745e6212e71f6fe9da863c9c9f7b092542929449Jeff Sharkeyimport com.android.settings.R; 597dbbe131683c231f6820bca4d67853649a4836f8Sudheer Shankaimport com.android.settings.RestrictedSettingsFragment; 607dbbe131683c231f6820bca4d67853649a4836f8Sudheer Shankaimport com.android.settingslib.RestrictedLockUtils; 619fd7ac1ec7c0c3984f225a237bd6e3dbafc7f831Jeff Sharkeyimport com.google.android.collect.Lists; 62310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh 639fd7ac1ec7c0c3984f225a237bd6e3dbafc7f831Jeff Sharkeyimport java.util.ArrayList; 647bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Leeimport java.util.Collections; 659fd7ac1ec7c0c3984f225a237bd6e3dbafc7f831Jeff Sharkeyimport java.util.List; 667bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Leeimport java.util.Map; 677bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Leeimport java.util.Set; 68310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh 692bd92d5d0685144aad566b9d29454fb519ff0371Robin Leeimport static android.app.AppOpsManager.OP_ACTIVATE_VPN; 70310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh 712bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee/** 722bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee * Settings screen listing VPNs. Configured VPNs and networks managed by apps 732bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee * are shown in the same list. 742bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee */ 757dbbe131683c231f6820bca4d67853649a4836f8Sudheer Shankapublic class VpnSettings extends RestrictedSettingsFragment implements 762bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee Handler.Callback, Preference.OnPreferenceClickListener { 772bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee private static final String LOG_TAG = "VpnSettings"; 789fd7ac1ec7c0c3984f225a237bd6e3dbafc7f831Jeff Sharkey 7901b35bcae307907bd8aaaa9cf23fa50f70e5f491Robin Lee private static final int RESCAN_MESSAGE = 0; 8001b35bcae307907bd8aaaa9cf23fa50f70e5f491Robin Lee private static final int RESCAN_INTERVAL_MS = 1000; 8101b35bcae307907bd8aaaa9cf23fa50f70e5f491Robin Lee 822bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee private static final NetworkRequest VPN_REQUEST = new NetworkRequest.Builder() 832bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN) 842bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED) 852bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee .removeCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED) 862bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee .build(); 878b78299d94ebb09fb9bf2bc7fb0015d2f1950839Jeff Sharkey 882bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee private final IConnectivityManager mConnectivityService = IConnectivityManager.Stub 8997fd85fd9776f3fb5c35217e82bcbcb5aea8416dChia-chi Yeh .asInterface(ServiceManager.getService(Context.CONNECTIVITY_SERVICE)); 902bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee private ConnectivityManager mConnectivityManager; 912bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee private UserManager mUserManager; 922bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee 93310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh private final KeyStore mKeyStore = KeyStore.getInstance(); 94310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh 9514c2ac4dcb17c27e065384e69c9f2e24dcbf22aaVictor Chang private Map<String, LegacyVpnPreference> mLegacyVpnPreferences = new ArrayMap<>(); 967bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee private Map<AppVpnInfo, AppPreference> mAppPreferences = new ArrayMap<>(); 97bbb5094be6673929bcb808cdeaf748a73be4dbf0Chia-chi Yeh 98bbb5094be6673929bcb808cdeaf748a73be4dbf0Chia-chi Yeh private Handler mUpdater; 992bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee private LegacyVpnInfo mConnectedLegacyVpn; 100310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh 101ee27b9de8f2ab17d50b90dd8c13546aebb4e9fc1Julia Reynolds private boolean mUnavailable; 102ee27b9de8f2ab17d50b90dd8c13546aebb4e9fc1Julia Reynolds 1037dbbe131683c231f6820bca4d67853649a4836f8Sudheer Shanka public VpnSettings() { 1047dbbe131683c231f6820bca4d67853649a4836f8Sudheer Shanka super(UserManager.DISALLOW_CONFIG_VPN); 1057dbbe131683c231f6820bca4d67853649a4836f8Sudheer Shanka } 1067dbbe131683c231f6820bca4d67853649a4836f8Sudheer Shanka 107310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh @Override 1088a963babe2e36b7a41f77b8d2598c97658196e58Chris Wren protected int getMetricsCategory() { 1099d1bfd1e8de6e46137a9571507c03526880d6a46Chris Wren return MetricsEvent.VPN; 1108a963babe2e36b7a41f77b8d2598c97658196e58Chris Wren } 1118a963babe2e36b7a41f77b8d2598c97658196e58Chris Wren 1128a963babe2e36b7a41f77b8d2598c97658196e58Chris Wren @Override 113eb034eb65e99e3abee7e9951bfd02456a9fcf7deRobin Lee public void onActivityCreated(Bundle savedInstanceState) { 114eb034eb65e99e3abee7e9951bfd02456a9fcf7deRobin Lee super.onActivityCreated(savedInstanceState); 1159fd7ac1ec7c0c3984f225a237bd6e3dbafc7f831Jeff Sharkey 1162bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee mUserManager = (UserManager) getSystemService(Context.USER_SERVICE); 1172bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee mConnectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); 1182bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee 119eb034eb65e99e3abee7e9951bfd02456a9fcf7deRobin Lee mUnavailable = isUiRestricted(); 120eb034eb65e99e3abee7e9951bfd02456a9fcf7deRobin Lee setHasOptionsMenu(!mUnavailable); 121eb034eb65e99e3abee7e9951bfd02456a9fcf7deRobin Lee 122310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh addPreferencesFromResource(R.xml.vpn_settings2); 1232bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee } 124310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh 1252bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee @Override 1269fd7ac1ec7c0c3984f225a237bd6e3dbafc7f831Jeff Sharkey public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { 1279fd7ac1ec7c0c3984f225a237bd6e3dbafc7f831Jeff Sharkey super.onCreateOptionsMenu(menu, inflater); 1289fd7ac1ec7c0c3984f225a237bd6e3dbafc7f831Jeff Sharkey inflater.inflate(R.menu.vpn, menu); 1299fd7ac1ec7c0c3984f225a237bd6e3dbafc7f831Jeff Sharkey } 1309fd7ac1ec7c0c3984f225a237bd6e3dbafc7f831Jeff Sharkey 1319fd7ac1ec7c0c3984f225a237bd6e3dbafc7f831Jeff Sharkey @Override 13207d465ddb8629f128dde193d22de28cfd56663caJeff Sharkey public void onPrepareOptionsMenu(Menu menu) { 13307d465ddb8629f128dde193d22de28cfd56663caJeff Sharkey super.onPrepareOptionsMenu(menu); 13407d465ddb8629f128dde193d22de28cfd56663caJeff Sharkey 1354198607ee274ffc9749ac069f7047d9e3a4da43eRobin Lee // Disable all actions if VPN configuration has been disallowed 1364198607ee274ffc9749ac069f7047d9e3a4da43eRobin Lee for (int i = 0; i < menu.size(); i++) { 1377dbbe131683c231f6820bca4d67853649a4836f8Sudheer Shanka if (isUiRestrictedByOnlyAdmin()) { 1387dbbe131683c231f6820bca4d67853649a4836f8Sudheer Shanka RestrictedLockUtils.setMenuItemAsDisabledByAdmin(getPrefContext(), 1397dbbe131683c231f6820bca4d67853649a4836f8Sudheer Shanka menu.getItem(i), getRestrictionEnforcedAdmin()); 1407dbbe131683c231f6820bca4d67853649a4836f8Sudheer Shanka } else { 1417dbbe131683c231f6820bca4d67853649a4836f8Sudheer Shanka menu.getItem(i).setEnabled(!mUnavailable); 1427dbbe131683c231f6820bca4d67853649a4836f8Sudheer Shanka } 1434198607ee274ffc9749ac069f7047d9e3a4da43eRobin Lee } 14407d465ddb8629f128dde193d22de28cfd56663caJeff Sharkey } 14507d465ddb8629f128dde193d22de28cfd56663caJeff Sharkey 14607d465ddb8629f128dde193d22de28cfd56663caJeff Sharkey @Override 1479fd7ac1ec7c0c3984f225a237bd6e3dbafc7f831Jeff Sharkey public boolean onOptionsItemSelected(MenuItem item) { 1489fd7ac1ec7c0c3984f225a237bd6e3dbafc7f831Jeff Sharkey switch (item.getItemId()) { 1499fd7ac1ec7c0c3984f225a237bd6e3dbafc7f831Jeff Sharkey case R.id.vpn_create: { 1509fd7ac1ec7c0c3984f225a237bd6e3dbafc7f831Jeff Sharkey // Generate a new key. Here we just use the current time. 1519fd7ac1ec7c0c3984f225a237bd6e3dbafc7f831Jeff Sharkey long millis = System.currentTimeMillis(); 15214c2ac4dcb17c27e065384e69c9f2e24dcbf22aaVictor Chang while (mLegacyVpnPreferences.containsKey(Long.toHexString(millis))) { 1539fd7ac1ec7c0c3984f225a237bd6e3dbafc7f831Jeff Sharkey ++millis; 1549fd7ac1ec7c0c3984f225a237bd6e3dbafc7f831Jeff Sharkey } 1552bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee VpnProfile profile = new VpnProfile(Long.toHexString(millis)); 1562bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee ConfigDialogFragment.show(this, profile, true /* editing */, false /* exists */); 1579fd7ac1ec7c0c3984f225a237bd6e3dbafc7f831Jeff Sharkey return true; 1589fd7ac1ec7c0c3984f225a237bd6e3dbafc7f831Jeff Sharkey } 1599fd7ac1ec7c0c3984f225a237bd6e3dbafc7f831Jeff Sharkey } 1609fd7ac1ec7c0c3984f225a237bd6e3dbafc7f831Jeff Sharkey return super.onOptionsItemSelected(item); 1619fd7ac1ec7c0c3984f225a237bd6e3dbafc7f831Jeff Sharkey } 1629fd7ac1ec7c0c3984f225a237bd6e3dbafc7f831Jeff Sharkey 1639fd7ac1ec7c0c3984f225a237bd6e3dbafc7f831Jeff Sharkey @Override 164310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh public void onResume() { 165310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh super.onResume(); 166310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh 167ee27b9de8f2ab17d50b90dd8c13546aebb4e9fc1Julia Reynolds if (mUnavailable) { 168dd142295da8912c1f2d972341abb2e5b761075e9Robin Lee // Show a message to explain that VPN settings have been disabled 1697dbbe131683c231f6820bca4d67853649a4836f8Sudheer Shanka if (!isUiRestrictedByOnlyAdmin()) { 1707dbbe131683c231f6820bca4d67853649a4836f8Sudheer Shanka getEmptyTextView().setText(R.string.vpn_settings_not_available); 171ee27b9de8f2ab17d50b90dd8c13546aebb4e9fc1Julia Reynolds } 1727dbbe131683c231f6820bca4d67853649a4836f8Sudheer Shanka getPreferenceScreen().removeAll(); 173ee27b9de8f2ab17d50b90dd8c13546aebb4e9fc1Julia Reynolds return; 174eb034eb65e99e3abee7e9951bfd02456a9fcf7deRobin Lee } else { 175eb034eb65e99e3abee7e9951bfd02456a9fcf7deRobin Lee getEmptyTextView().setText(R.string.vpn_no_vpns_added); 176ee27b9de8f2ab17d50b90dd8c13546aebb4e9fc1Julia Reynolds } 177ee27b9de8f2ab17d50b90dd8c13546aebb4e9fc1Julia Reynolds 17801b35bcae307907bd8aaaa9cf23fa50f70e5f491Robin Lee // Start monitoring 17901b35bcae307907bd8aaaa9cf23fa50f70e5f491Robin Lee mConnectivityManager.registerNetworkCallback(VPN_REQUEST, mNetworkCallback); 18001b35bcae307907bd8aaaa9cf23fa50f70e5f491Robin Lee 18101b35bcae307907bd8aaaa9cf23fa50f70e5f491Robin Lee // Trigger a refresh 18201b35bcae307907bd8aaaa9cf23fa50f70e5f491Robin Lee if (mUpdater == null) { 18301b35bcae307907bd8aaaa9cf23fa50f70e5f491Robin Lee mUpdater = new Handler(this); 18401b35bcae307907bd8aaaa9cf23fa50f70e5f491Robin Lee } 18501b35bcae307907bd8aaaa9cf23fa50f70e5f491Robin Lee mUpdater.sendEmptyMessage(RESCAN_MESSAGE); 18601b35bcae307907bd8aaaa9cf23fa50f70e5f491Robin Lee } 18701b35bcae307907bd8aaaa9cf23fa50f70e5f491Robin Lee 18801b35bcae307907bd8aaaa9cf23fa50f70e5f491Robin Lee @Override 18901b35bcae307907bd8aaaa9cf23fa50f70e5f491Robin Lee public void onPause() { 190614fc178bf028ef66bea24a70ae476a91833a7f1Robin Lee if (mUnavailable) { 191dd142295da8912c1f2d972341abb2e5b761075e9Robin Lee super.onPause(); 192dd142295da8912c1f2d972341abb2e5b761075e9Robin Lee return; 193dd142295da8912c1f2d972341abb2e5b761075e9Robin Lee } 194dd142295da8912c1f2d972341abb2e5b761075e9Robin Lee 1955f6f4cc572589674196e836904c4b27f84f21934Robin Lee // Stop monitoring 19601b35bcae307907bd8aaaa9cf23fa50f70e5f491Robin Lee mConnectivityManager.unregisterNetworkCallback(mNetworkCallback); 19701b35bcae307907bd8aaaa9cf23fa50f70e5f491Robin Lee 19801b35bcae307907bd8aaaa9cf23fa50f70e5f491Robin Lee if (mUpdater != null) { 19901b35bcae307907bd8aaaa9cf23fa50f70e5f491Robin Lee mUpdater.removeCallbacksAndMessages(null); 20001b35bcae307907bd8aaaa9cf23fa50f70e5f491Robin Lee } 20101b35bcae307907bd8aaaa9cf23fa50f70e5f491Robin Lee 20201b35bcae307907bd8aaaa9cf23fa50f70e5f491Robin Lee super.onPause(); 2032bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee } 204310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh 20501b35bcae307907bd8aaaa9cf23fa50f70e5f491Robin Lee @Override 20601b35bcae307907bd8aaaa9cf23fa50f70e5f491Robin Lee public boolean handleMessage(Message message) { 20701b35bcae307907bd8aaaa9cf23fa50f70e5f491Robin Lee mUpdater.removeMessages(RESCAN_MESSAGE); 20801b35bcae307907bd8aaaa9cf23fa50f70e5f491Robin Lee 20937b179fa8cdde8e00a745cbf030bcb1836e921c4Robin Lee // Run heavy RPCs before switching to UI thread 2107bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee final List<VpnProfile> vpnProfiles = loadVpnProfiles(mKeyStore); 211003a4b563a61144513688f6508101c7d2ee48f6fRobin Lee final List<AppVpnInfo> vpnApps = getVpnApps(getActivity(), /* includeProfiles */ true); 2122bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee 213b166ea26687f7b72cbc544438436ae85167ca2f1Robin Lee final Map<String, LegacyVpnInfo> connectedLegacyVpns = getConnectedLegacyVpns(); 214b166ea26687f7b72cbc544438436ae85167ca2f1Robin Lee final Set<AppVpnInfo> connectedAppVpns = getConnectedAppVpns(); 215310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh 21614c2ac4dcb17c27e065384e69c9f2e24dcbf22aaVictor Chang final Set<AppVpnInfo> alwaysOnAppVpnInfos = getAlwaysOnAppVpnInfos(); 21714c2ac4dcb17c27e065384e69c9f2e24dcbf22aaVictor Chang final String lockdownVpnKey = VpnUtils.getLockdownVpn(); 218cac0dddd2ad4ca44c4dd5c0f57cca9439edbf773Robin Lee 21937b179fa8cdde8e00a745cbf030bcb1836e921c4Robin Lee // Refresh list of VPNs 2207bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee getActivity().runOnUiThread(new Runnable() { 2217bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee @Override 2227bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee public void run() { 22337b179fa8cdde8e00a745cbf030bcb1836e921c4Robin Lee // Can't do anything useful if the context has gone away 22437b179fa8cdde8e00a745cbf030bcb1836e921c4Robin Lee if (!isAdded()) { 22537b179fa8cdde8e00a745cbf030bcb1836e921c4Robin Lee return; 22637b179fa8cdde8e00a745cbf030bcb1836e921c4Robin Lee } 22737b179fa8cdde8e00a745cbf030bcb1836e921c4Robin Lee 2287bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee // Find new VPNs by subtracting existing ones from the full set 2297bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee final Set<Preference> updates = new ArraySet<>(); 230310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh 2317bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee for (VpnProfile profile : vpnProfiles) { 23214c2ac4dcb17c27e065384e69c9f2e24dcbf22aaVictor Chang LegacyVpnPreference p = findOrCreatePreference(profile); 233b166ea26687f7b72cbc544438436ae85167ca2f1Robin Lee if (connectedLegacyVpns.containsKey(profile.key)) { 234b166ea26687f7b72cbc544438436ae85167ca2f1Robin Lee p.setState(connectedLegacyVpns.get(profile.key).state); 235b166ea26687f7b72cbc544438436ae85167ca2f1Robin Lee } else { 236b166ea26687f7b72cbc544438436ae85167ca2f1Robin Lee p.setState(LegacyVpnPreference.STATE_NONE); 237b166ea26687f7b72cbc544438436ae85167ca2f1Robin Lee } 23814c2ac4dcb17c27e065384e69c9f2e24dcbf22aaVictor Chang p.setAlwaysOn(lockdownVpnKey != null && lockdownVpnKey.equals(profile.key)); 2397bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee updates.add(p); 2407bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee } 2417bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee for (AppVpnInfo app : vpnApps) { 2427bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee AppPreference p = findOrCreatePreference(app); 243b166ea26687f7b72cbc544438436ae85167ca2f1Robin Lee if (connectedAppVpns.contains(app)) { 244b166ea26687f7b72cbc544438436ae85167ca2f1Robin Lee p.setState(AppPreference.STATE_CONNECTED); 245b166ea26687f7b72cbc544438436ae85167ca2f1Robin Lee } else { 246b166ea26687f7b72cbc544438436ae85167ca2f1Robin Lee p.setState(AppPreference.STATE_DISCONNECTED); 247b166ea26687f7b72cbc544438436ae85167ca2f1Robin Lee } 24814c2ac4dcb17c27e065384e69c9f2e24dcbf22aaVictor Chang p.setAlwaysOn(alwaysOnAppVpnInfos.contains(app)); 2497bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee updates.add(p); 25001b35bcae307907bd8aaaa9cf23fa50f70e5f491Robin Lee } 25101b35bcae307907bd8aaaa9cf23fa50f70e5f491Robin Lee 252b166ea26687f7b72cbc544438436ae85167ca2f1Robin Lee // Trim out deleted VPN preferences 25314c2ac4dcb17c27e065384e69c9f2e24dcbf22aaVictor Chang mLegacyVpnPreferences.values().retainAll(updates); 2547bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee mAppPreferences.values().retainAll(updates); 2557bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee 2567bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee final PreferenceGroup vpnGroup = getPreferenceScreen(); 2577bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee for (int i = vpnGroup.getPreferenceCount() - 1; i >= 0; i--) { 2587bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee Preference p = vpnGroup.getPreference(i); 2597bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee if (updates.contains(p)) { 2607bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee updates.remove(p); 2617bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee } else { 2627bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee vpnGroup.removePreference(p); 2637bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee } 2647bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee } 2657bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee 2667bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee // Show any new preferences on the screen 2677bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee for (Preference pref : updates) { 2687bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee vpnGroup.addPreference(pref); 2697bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee } 27001b35bcae307907bd8aaaa9cf23fa50f70e5f491Robin Lee } 2717bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee }); 27201b35bcae307907bd8aaaa9cf23fa50f70e5f491Robin Lee 27301b35bcae307907bd8aaaa9cf23fa50f70e5f491Robin Lee mUpdater.sendEmptyMessageDelayed(RESCAN_MESSAGE, RESCAN_INTERVAL_MS); 27401b35bcae307907bd8aaaa9cf23fa50f70e5f491Robin Lee return true; 275310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh } 276310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh 277310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh @Override 2782bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee public boolean onPreferenceClick(Preference preference) { 27914c2ac4dcb17c27e065384e69c9f2e24dcbf22aaVictor Chang if (preference instanceof LegacyVpnPreference) { 28014c2ac4dcb17c27e065384e69c9f2e24dcbf22aaVictor Chang LegacyVpnPreference pref = (LegacyVpnPreference) preference; 28114c2ac4dcb17c27e065384e69c9f2e24dcbf22aaVictor Chang VpnProfile profile = pref.getProfile(); 2822bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee if (mConnectedLegacyVpn != null && profile.key.equals(mConnectedLegacyVpn.key) && 2832bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee mConnectedLegacyVpn.state == LegacyVpnInfo.STATE_CONNECTED) { 284413b171159cec5ad1e7b3cf4f1f842b5f2debc05Chia-chi Yeh try { 2852bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee mConnectedLegacyVpn.intent.send(); 2862bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee return true; 287413b171159cec5ad1e7b3cf4f1f842b5f2debc05Chia-chi Yeh } catch (Exception e) { 2887bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee Log.w(LOG_TAG, "Starting config intent failed", e); 289413b171159cec5ad1e7b3cf4f1f842b5f2debc05Chia-chi Yeh } 290310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh } 2912bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee ConfigDialogFragment.show(this, profile, false /* editing */, true /* exists */); 2922bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee return true; 2932bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee } else if (preference instanceof AppPreference) { 2942bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee AppPreference pref = (AppPreference) preference; 2952bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee boolean connected = (pref.getState() == AppPreference.STATE_CONNECTED); 296310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh 2972bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee if (!connected) { 2982bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee try { 2997bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee UserHandle user = UserHandle.of(pref.getUserId()); 3002bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee Context userContext = getActivity().createPackageContextAsUser( 3012bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee getActivity().getPackageName(), 0 /* flags */, user); 3022bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee PackageManager pm = userContext.getPackageManager(); 3032bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee Intent appIntent = pm.getLaunchIntentForPackage(pref.getPackageName()); 3042bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee if (appIntent != null) { 3052bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee userContext.startActivityAsUser(appIntent, user); 3062bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee return true; 3072bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee } 3082bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee } catch (PackageManager.NameNotFoundException nnfe) { 3097bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee Log.w(LOG_TAG, "VPN provider does not exist: " + pref.getPackageName(), nnfe); 3102bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee } 311310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh } 312310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh 3137bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee // Already connected or no launch intent available - show an info dialog 3142bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee PackageInfo pkgInfo = pref.getPackageInfo(); 315ab6a65c03b2505ed2cce0226e11ef2d566699cf4Robin Lee AppDialogFragment.show(this, pkgInfo, pref.getLabel(), false /* editing */, connected); 3162bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee return true; 317310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh } 318310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh return false; 319310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh } 320310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh 3217bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee @Override 3227bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee protected int getHelpResource() { 3237bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee return R.string.help_url_vpn; 3247bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee } 3257bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee 32614c2ac4dcb17c27e065384e69c9f2e24dcbf22aaVictor Chang private OnGearClickListener mGearListener = new OnGearClickListener() { 3272bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee @Override 32814c2ac4dcb17c27e065384e69c9f2e24dcbf22aaVictor Chang public void onGearClick(GearPreference p) { 32914c2ac4dcb17c27e065384e69c9f2e24dcbf22aaVictor Chang if (p instanceof LegacyVpnPreference) { 33014c2ac4dcb17c27e065384e69c9f2e24dcbf22aaVictor Chang LegacyVpnPreference pref = (LegacyVpnPreference) p; 3312bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee ConfigDialogFragment.show(VpnSettings.this, pref.getProfile(), true /* editing */, 3322bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee true /* exists */); 33314c2ac4dcb17c27e065384e69c9f2e24dcbf22aaVictor Chang } else if (p instanceof AppPreference) { 33414c2ac4dcb17c27e065384e69c9f2e24dcbf22aaVictor Chang AppPreference pref = (AppPreference) p;; 33516da2aa45000dd32213a3d84baacc82cd2b16e5fVictor Chang AppManagementFragment.show(getPrefContext(), pref); 336310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh } 337310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh } 3382bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee }; 339310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh 3402bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee private NetworkCallback mNetworkCallback = new NetworkCallback() { 3412bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee @Override 3422bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee public void onAvailable(Network network) { 3432bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee if (mUpdater != null) { 34401b35bcae307907bd8aaaa9cf23fa50f70e5f491Robin Lee mUpdater.sendEmptyMessage(RESCAN_MESSAGE); 3452bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee } 346d95ec871138ebb367cfd8b67b4814438ac30c628Chia-chi Yeh } 347310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh 3482bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee @Override 3492bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee public void onLost(Network network) { 3502bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee if (mUpdater != null) { 35101b35bcae307907bd8aaaa9cf23fa50f70e5f491Robin Lee mUpdater.sendEmptyMessage(RESCAN_MESSAGE); 35297fd85fd9776f3fb5c35217e82bcbcb5aea8416dChia-chi Yeh } 35397fd85fd9776f3fb5c35217e82bcbcb5aea8416dChia-chi Yeh } 3542bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee }; 355310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh 3567bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee @UiThread 35714c2ac4dcb17c27e065384e69c9f2e24dcbf22aaVictor Chang private LegacyVpnPreference findOrCreatePreference(VpnProfile profile) { 35814c2ac4dcb17c27e065384e69c9f2e24dcbf22aaVictor Chang LegacyVpnPreference pref = mLegacyVpnPreferences.get(profile.key); 3597bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee if (pref == null) { 36014c2ac4dcb17c27e065384e69c9f2e24dcbf22aaVictor Chang pref = new LegacyVpnPreference(getPrefContext()); 36114c2ac4dcb17c27e065384e69c9f2e24dcbf22aaVictor Chang pref.setOnGearClickListener(mGearListener); 3627bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee pref.setOnPreferenceClickListener(this); 36314c2ac4dcb17c27e065384e69c9f2e24dcbf22aaVictor Chang mLegacyVpnPreferences.put(profile.key, pref); 3647bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee } 365b166ea26687f7b72cbc544438436ae85167ca2f1Robin Lee // This may change as the profile can update and keep the same key. 3667bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee pref.setProfile(profile); 3677bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee return pref; 3687bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee } 3697bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee 3707bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee @UiThread 3717bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee private AppPreference findOrCreatePreference(AppVpnInfo app) { 3727bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee AppPreference pref = mAppPreferences.get(app); 3737bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee if (pref == null) { 374b166ea26687f7b72cbc544438436ae85167ca2f1Robin Lee pref = new AppPreference(getPrefContext(), app.userId, app.packageName); 37514c2ac4dcb17c27e065384e69c9f2e24dcbf22aaVictor Chang pref.setOnGearClickListener(mGearListener); 3767bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee pref.setOnPreferenceClickListener(this); 3777bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee mAppPreferences.put(app, pref); 3787bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee } 3797bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee return pref; 380b0b37ae21c172491bc170659b5f429601858ddc1Amith Yamasani } 381b0b37ae21c172491bc170659b5f429601858ddc1Amith Yamasani 3827bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee @WorkerThread 383b166ea26687f7b72cbc544438436ae85167ca2f1Robin Lee private Map<String, LegacyVpnInfo> getConnectedLegacyVpns() { 3847bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee try { 3857bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee mConnectedLegacyVpn = mConnectivityService.getLegacyVpnInfo(UserHandle.myUserId()); 3867bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee if (mConnectedLegacyVpn != null) { 387b166ea26687f7b72cbc544438436ae85167ca2f1Robin Lee return Collections.singletonMap(mConnectedLegacyVpn.key, mConnectedLegacyVpn); 3887bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee } 3897bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee } catch (RemoteException e) { 3907bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee Log.e(LOG_TAG, "Failure updating VPN list with connected legacy VPNs", e); 3917bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee } 392b166ea26687f7b72cbc544438436ae85167ca2f1Robin Lee return Collections.emptyMap(); 3937bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee } 3947bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee 3957bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee @WorkerThread 396b166ea26687f7b72cbc544438436ae85167ca2f1Robin Lee private Set<AppVpnInfo> getConnectedAppVpns() { 3977bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee // Mark connected third-party services 398b166ea26687f7b72cbc544438436ae85167ca2f1Robin Lee Set<AppVpnInfo> connections = new ArraySet<>(); 3997bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee try { 4007bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee for (UserHandle profile : mUserManager.getUserProfiles()) { 4017bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee VpnConfig config = mConnectivityService.getVpnConfig(profile.getIdentifier()); 4027bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee if (config != null && !config.legacy) { 4037bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee connections.add(new AppVpnInfo(profile.getIdentifier(), config.user)); 4047bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee } 4057bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee } 4067bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee } catch (RemoteException e) { 4077bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee Log.e(LOG_TAG, "Failure updating VPN list with connected app VPNs", e); 4087bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee } 4097bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee return connections; 4107bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee } 4117bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee 412cac0dddd2ad4ca44c4dd5c0f57cca9439edbf773Robin Lee @WorkerThread 41314c2ac4dcb17c27e065384e69c9f2e24dcbf22aaVictor Chang private Set<AppVpnInfo> getAlwaysOnAppVpnInfos() { 41414c2ac4dcb17c27e065384e69c9f2e24dcbf22aaVictor Chang Set<AppVpnInfo> result = new ArraySet<>(); 415cac0dddd2ad4ca44c4dd5c0f57cca9439edbf773Robin Lee for (UserHandle profile : mUserManager.getUserProfiles()) { 416cac0dddd2ad4ca44c4dd5c0f57cca9439edbf773Robin Lee final int profileId = profile.getIdentifier(); 41714c2ac4dcb17c27e065384e69c9f2e24dcbf22aaVictor Chang final String packageName = mConnectivityManager.getAlwaysOnVpnPackageForUser(profileId); 41814c2ac4dcb17c27e065384e69c9f2e24dcbf22aaVictor Chang if (packageName != null) { 41914c2ac4dcb17c27e065384e69c9f2e24dcbf22aaVictor Chang result.add(new AppVpnInfo(profileId, packageName)); 420cac0dddd2ad4ca44c4dd5c0f57cca9439edbf773Robin Lee } 421cac0dddd2ad4ca44c4dd5c0f57cca9439edbf773Robin Lee } 422cac0dddd2ad4ca44c4dd5c0f57cca9439edbf773Robin Lee return result; 423cac0dddd2ad4ca44c4dd5c0f57cca9439edbf773Robin Lee } 424cac0dddd2ad4ca44c4dd5c0f57cca9439edbf773Robin Lee 425003a4b563a61144513688f6508101c7d2ee48f6fRobin Lee static List<AppVpnInfo> getVpnApps(Context context, boolean includeProfiles) { 4267bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee List<AppVpnInfo> result = Lists.newArrayList(); 427310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh 428003a4b563a61144513688f6508101c7d2ee48f6fRobin Lee final Set<Integer> profileIds; 429003a4b563a61144513688f6508101c7d2ee48f6fRobin Lee if (includeProfiles) { 430003a4b563a61144513688f6508101c7d2ee48f6fRobin Lee profileIds = new ArraySet<>(); 431003a4b563a61144513688f6508101c7d2ee48f6fRobin Lee for (UserHandle profile : UserManager.get(context).getUserProfiles()) { 432003a4b563a61144513688f6508101c7d2ee48f6fRobin Lee profileIds.add(profile.getIdentifier()); 433003a4b563a61144513688f6508101c7d2ee48f6fRobin Lee } 434003a4b563a61144513688f6508101c7d2ee48f6fRobin Lee } else { 435003a4b563a61144513688f6508101c7d2ee48f6fRobin Lee profileIds = Collections.singleton(UserHandle.myUserId()); 43697fd85fd9776f3fb5c35217e82bcbcb5aea8416dChia-chi Yeh } 43797fd85fd9776f3fb5c35217e82bcbcb5aea8416dChia-chi Yeh 4382bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee // Fetch VPN-enabled apps from AppOps. 439003a4b563a61144513688f6508101c7d2ee48f6fRobin Lee AppOpsManager aom = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); 4402bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee List<AppOpsManager.PackageOps> apps = aom.getPackagesForOps(new int[] {OP_ACTIVATE_VPN}); 4412bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee if (apps != null) { 4422bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee for (AppOpsManager.PackageOps pkg : apps) { 4432bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee int userId = UserHandle.getUserId(pkg.getUid()); 444003a4b563a61144513688f6508101c7d2ee48f6fRobin Lee if (!profileIds.contains(userId)) { 4452bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee // Skip packages for users outside of our profile group. 4462bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee continue; 447310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh } 4482bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee // Look for a MODE_ALLOWED permission to activate VPN. 4492bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee boolean allowed = false; 4502bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee for (AppOpsManager.OpEntry op : pkg.getOps()) { 4512bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee if (op.getOp() == OP_ACTIVATE_VPN && 4522bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee op.getMode() == AppOpsManager.MODE_ALLOWED) { 4532bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee allowed = true; 4542bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee } 4552bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee } 4562bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee if (allowed) { 4577bf8654a5c1dfca8552aa635e552ded374e6fd46Robin Lee result.add(new AppVpnInfo(userId, pkg.getPackageName())); 4589fd7ac1ec7c0c3984f225a237bd6e3dbafc7f831Jeff Sharkey } 4599fd7ac1ec7c0c3984f225a237bd6e3dbafc7f831Jeff Sharkey } 4609fd7ac1ec7c0c3984f225a237bd6e3dbafc7f831Jeff Sharkey } 461003a4b563a61144513688f6508101c7d2ee48f6fRobin Lee 462003a4b563a61144513688f6508101c7d2ee48f6fRobin Lee Collections.sort(result); 4632bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee return result; 4642bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee } 4659fd7ac1ec7c0c3984f225a237bd6e3dbafc7f831Jeff Sharkey 466003a4b563a61144513688f6508101c7d2ee48f6fRobin Lee static List<VpnProfile> loadVpnProfiles(KeyStore keyStore, int... excludeTypes) { 4672bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee final ArrayList<VpnProfile> result = Lists.newArrayList(); 4689fd7ac1ec7c0c3984f225a237bd6e3dbafc7f831Jeff Sharkey 4693848407d0c2fad920419d6b925e0c8e374502680Alex Klyubin for (String key : keyStore.list(Credentials.VPN)) { 4702bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee final VpnProfile profile = VpnProfile.decode(key, keyStore.get(Credentials.VPN + key)); 4712bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee if (profile != null && !ArrayUtils.contains(excludeTypes, profile.type)) { 4722bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee result.add(profile); 4739fd7ac1ec7c0c3984f225a237bd6e3dbafc7f831Jeff Sharkey } 4749fd7ac1ec7c0c3984f225a237bd6e3dbafc7f831Jeff Sharkey } 4759fd7ac1ec7c0c3984f225a237bd6e3dbafc7f831Jeff Sharkey return result; 4769fd7ac1ec7c0c3984f225a237bd6e3dbafc7f831Jeff Sharkey } 477310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh} 478