diff --git a/src/com/android/settings/vpn2/AppPreference.java b/src/com/android/settings/vpn2/AppPreference.java index fa9daf6187a..3369970baf2 100644 --- a/src/com/android/settings/vpn2/AppPreference.java +++ b/src/com/android/settings/vpn2/AppPreference.java @@ -34,17 +34,43 @@ public class AppPreference extends ManageablePreference { public static final int STATE_CONNECTED = LegacyVpnInfo.STATE_CONNECTED; public static final int STATE_DISCONNECTED = STATE_NONE; - private String mPackageName; - private String mName; + private final String mPackageName; + private final String mName; - public AppPreference(Context context) { + public AppPreference(Context context, int userId, String packageName) { super(context, null /* attrs */); - } - - @Override - public void setUserId(int userId) { super.setUserId(userId); - update(); + + mPackageName = packageName; + + // Fetch icon and VPN label + String label = packageName; + Drawable icon = null; + try { + // Make all calls to the package manager as the appropriate user. + Context userContext = getUserContext(); + PackageManager pm = userContext.getPackageManager(); + // The nested catch block is for the case that the app doesn't exist, so we can fall + // back to the default activity icon. + try { + PackageInfo pkgInfo = pm.getPackageInfo(mPackageName, 0 /* flags */); + if (pkgInfo != null) { + icon = pkgInfo.applicationInfo.loadIcon(pm); + label = VpnConfig.getVpnLabel(userContext, mPackageName).toString(); + } + } catch (PackageManager.NameNotFoundException pkgNotFound) { + // Use default app label and icon as fallback + } + if (icon == null) { + icon = pm.getDefaultActivityIcon(); + } + } catch (PackageManager.NameNotFoundException userNotFound) { + // No user, no useful information to obtain. Quietly fail. + } + mName = label; + + setTitle(mName); + setIcon(icon); } public PackageInfo getPackageInfo() { @@ -64,48 +90,6 @@ public class AppPreference extends ManageablePreference { return mPackageName; } - public void setPackageName(String name) { - mPackageName = name; - update(); - } - - private void update() { - if (mPackageName == null || mUserId == UserHandle.USER_NULL) { - return; - } - - mName = mPackageName; - Drawable icon = null; - - try { - // Make all calls to the package manager as the appropriate user. - Context userContext = getUserContext(); - PackageManager pm = userContext.getPackageManager(); - // Fetch icon and VPN label- the nested catch block is for the case that the app doesn't - // exist, in which case we can fall back to the default activity icon for an activity in - // that user. - try { - PackageInfo pkgInfo = pm.getPackageInfo(mPackageName, 0 /* flags */); - if (pkgInfo != null) { - icon = pkgInfo.applicationInfo.loadIcon(pm); - mName = VpnConfig.getVpnLabel(userContext, mPackageName).toString(); - } - } catch (PackageManager.NameNotFoundException pkgNotFound) { - // Use default app label and icon as fallback - } - if (icon == null) { - icon = pm.getDefaultActivityIcon(); - } - } catch (PackageManager.NameNotFoundException userNotFound) { - // No user, no useful information to obtain. Quietly fail. - } - setTitle(mName); - setIcon(icon); - updateSummary(); - - notifyHierarchyChanged(); - } - private Context getUserContext() throws PackageManager.NameNotFoundException { UserHandle user = UserHandle.of(mUserId); return getContext().createPackageContextAsUser( diff --git a/src/com/android/settings/vpn2/LegacyVpnPreference.java b/src/com/android/settings/vpn2/LegacyVpnPreference.java index 2ce22d487c5..c1550e242ca 100644 --- a/src/com/android/settings/vpn2/LegacyVpnPreference.java +++ b/src/com/android/settings/vpn2/LegacyVpnPreference.java @@ -18,6 +18,7 @@ package com.android.settings.vpn2; import android.content.Context; import android.support.v7.preference.Preference; +import android.text.TextUtils; import android.view.View; import com.android.internal.net.VpnProfile; @@ -33,6 +34,7 @@ public class LegacyVpnPreference extends ManageablePreference { LegacyVpnPreference(Context context) { super(context, null /* attrs */); + setIcon(R.mipmap.ic_launcher_settings); } public VpnProfile getProfile() { @@ -40,12 +42,13 @@ public class LegacyVpnPreference extends ManageablePreference { } public void setProfile(VpnProfile profile) { - mProfile = profile; - if (mProfile != null) { - setIcon(R.mipmap.ic_launcher_settings); - setTitle(mProfile.name); + final String oldLabel = (mProfile != null ? mProfile.name : null); + final String newLabel = (profile != null ? profile.name : null); + if (!TextUtils.equals(oldLabel, newLabel)) { + setTitle(newLabel); + notifyHierarchyChanged(); } - notifyHierarchyChanged(); + mProfile = profile; } @Override diff --git a/src/com/android/settings/vpn2/ManageablePreference.java b/src/com/android/settings/vpn2/ManageablePreference.java index 7c07e2018bc..e31a396f7ec 100644 --- a/src/com/android/settings/vpn2/ManageablePreference.java +++ b/src/com/android/settings/vpn2/ManageablePreference.java @@ -62,13 +62,18 @@ public abstract class ManageablePreference extends GearPreference { } public void setState(int state) { - mState = state; - updateSummary(); + if (mState != state) { + mState = state; + updateSummary(); + notifyHierarchyChanged(); + } } public void setAlwaysOn(boolean isEnabled) { - mIsAlwaysOn = isEnabled; - updateSummary(); + if (mIsAlwaysOn != isEnabled) { + mIsAlwaysOn = isEnabled; + updateSummary(); + } } /** diff --git a/src/com/android/settings/vpn2/VpnSettings.java b/src/com/android/settings/vpn2/VpnSettings.java index 6c47b438f0f..a675779bf99 100644 --- a/src/com/android/settings/vpn2/VpnSettings.java +++ b/src/com/android/settings/vpn2/VpnSettings.java @@ -34,7 +34,6 @@ import android.os.Handler; import android.os.Message; import android.os.RemoteException; import android.os.ServiceManager; -import android.os.SystemProperties; import android.os.UserHandle; import android.os.UserManager; import android.security.Credentials; @@ -211,8 +210,8 @@ public class VpnSettings extends RestrictedSettingsFragment implements final List vpnProfiles = loadVpnProfiles(mKeyStore); final List vpnApps = getVpnApps(getActivity(), /* includeProfiles */ true); - final List connectedLegacyVpns = getConnectedLegacyVpns(); - final List connectedAppVpns = getConnectedAppVpns(); + final Map connectedLegacyVpns = getConnectedLegacyVpns(); + final Set connectedAppVpns = getConnectedAppVpns(); final Set alwaysOnAppVpnInfos = getAlwaysOnAppVpnInfos(); final String lockdownVpnKey = VpnUtils.getLockdownVpn(); @@ -231,18 +230,26 @@ public class VpnSettings extends RestrictedSettingsFragment implements for (VpnProfile profile : vpnProfiles) { LegacyVpnPreference p = findOrCreatePreference(profile); - p.setState(LegacyVpnPreference.STATE_NONE); + if (connectedLegacyVpns.containsKey(profile.key)) { + p.setState(connectedLegacyVpns.get(profile.key).state); + } else { + p.setState(LegacyVpnPreference.STATE_NONE); + } p.setAlwaysOn(lockdownVpnKey != null && lockdownVpnKey.equals(profile.key)); updates.add(p); } for (AppVpnInfo app : vpnApps) { AppPreference p = findOrCreatePreference(app); - p.setState(AppPreference.STATE_DISCONNECTED); + if (connectedAppVpns.contains(app)) { + p.setState(AppPreference.STATE_CONNECTED); + } else { + p.setState(AppPreference.STATE_DISCONNECTED); + } p.setAlwaysOn(alwaysOnAppVpnInfos.contains(app)); updates.add(p); } - // Trim preferences for deleted VPNs + // Trim out deleted VPN preferences mLegacyVpnPreferences.values().retainAll(updates); mAppPreferences.values().retainAll(updates); @@ -260,20 +267,6 @@ public class VpnSettings extends RestrictedSettingsFragment implements for (Preference pref : updates) { vpnGroup.addPreference(pref); } - - // Mark connected VPNs - for (LegacyVpnInfo info : connectedLegacyVpns) { - final LegacyVpnPreference preference = mLegacyVpnPreferences.get(info.key); - if (preference != null) { - preference.setState(info.state); - } - } - for (AppVpnInfo app : connectedAppVpns) { - final AppPreference preference = mAppPreferences.get(app); - if (preference != null) { - preference.setState(AppPreference.STATE_CONNECTED); - } - } } }); @@ -369,6 +362,7 @@ public class VpnSettings extends RestrictedSettingsFragment implements pref.setOnPreferenceClickListener(this); mLegacyVpnPreferences.put(profile.key, pref); } + // This may change as the profile can update and keep the same key. pref.setProfile(profile); return pref; } @@ -377,33 +371,31 @@ public class VpnSettings extends RestrictedSettingsFragment implements private AppPreference findOrCreatePreference(AppVpnInfo app) { AppPreference pref = mAppPreferences.get(app); if (pref == null) { - pref = new AppPreference(getPrefContext()); + pref = new AppPreference(getPrefContext(), app.userId, app.packageName); pref.setOnGearClickListener(mGearListener); pref.setOnPreferenceClickListener(this); mAppPreferences.put(app, pref); } - pref.setUserId(app.userId); - pref.setPackageName(app.packageName); return pref; } @WorkerThread - private List getConnectedLegacyVpns() { + private Map getConnectedLegacyVpns() { try { mConnectedLegacyVpn = mConnectivityService.getLegacyVpnInfo(UserHandle.myUserId()); if (mConnectedLegacyVpn != null) { - return Collections.singletonList(mConnectedLegacyVpn); + return Collections.singletonMap(mConnectedLegacyVpn.key, mConnectedLegacyVpn); } } catch (RemoteException e) { Log.e(LOG_TAG, "Failure updating VPN list with connected legacy VPNs", e); } - return Collections.emptyList(); + return Collections.emptyMap(); } @WorkerThread - private List getConnectedAppVpns() { + private Set getConnectedAppVpns() { // Mark connected third-party services - List connections = new ArrayList<>(); + Set connections = new ArraySet<>(); try { for (UserHandle profile : mUserManager.getUserProfiles()) { VpnConfig config = mConnectivityService.getVpnConfig(profile.getIdentifier());