From 3956639122f96e5e7cfde007f0675496474c47fc Mon Sep 17 00:00:00 2001 From: Daniel Nishi Date: Thu, 24 Mar 2016 15:06:57 -0700 Subject: [PATCH] Add a branded VPN icon for quick settings and status bar. If a system VPN app specifies in its meta-data that it should use the system's branded VPN icon instead of the standard one, the Quick Settings footer and status bar show it instead. Bug 27146125 Change-Id: I3cfe4dda156d9147bdb339ba6bce82c72ca7393d --- .../res/drawable/ic_qs_branded_vpn.xml | 24 +++++++++++ .../res/drawable/stat_sys_branded_vpn.xml | 28 ++++++++++++ .../src/com/android/systemui/qs/QSFooter.java | 11 +++++ .../systemui/statusbar/SignalClusterView.java | 18 +++++++- .../statusbar/policy/SecurityController.java | 2 + .../policy/SecurityControllerImpl.java | 43 +++++++++++++++++++ 6 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 packages/SystemUI/res/drawable/ic_qs_branded_vpn.xml create mode 100644 packages/SystemUI/res/drawable/stat_sys_branded_vpn.xml diff --git a/packages/SystemUI/res/drawable/ic_qs_branded_vpn.xml b/packages/SystemUI/res/drawable/ic_qs_branded_vpn.xml new file mode 100644 index 0000000000000..736a04a1da441 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_qs_branded_vpn.xml @@ -0,0 +1,24 @@ + + + + + diff --git a/packages/SystemUI/res/drawable/stat_sys_branded_vpn.xml b/packages/SystemUI/res/drawable/stat_sys_branded_vpn.xml new file mode 100644 index 0000000000000..cac4fa790683a --- /dev/null +++ b/packages/SystemUI/res/drawable/stat_sys_branded_vpn.xml @@ -0,0 +1,28 @@ + + + + + + + + diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java index 51efbf06739f3..0549afa0a30e1 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java @@ -19,6 +19,7 @@ import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; +import android.graphics.drawable.Drawable; import android.os.Handler; import android.os.Looper; import android.os.Message; @@ -57,6 +58,7 @@ public class QSFooter implements OnClickListener, DialogInterface.OnClickListene private boolean mIsVisible; private boolean mIsIconVisible; private int mFooterTextId; + private int mFooterIconId; public QSFooter(QSPanel qsPanel, Context context) { mRootView = LayoutInflater.from(context) @@ -64,6 +66,7 @@ public class QSFooter implements OnClickListener, DialogInterface.OnClickListene mRootView.setOnClickListener(this); mFooterText = (TextView) mRootView.findViewById(R.id.footer_text); mFooterIcon = (ImageView) mRootView.findViewById(R.id.footer_icon); + mFooterIconId = R.drawable.ic_qs_vpn; mContext = context; mMainHandler = new Handler(); } @@ -118,6 +121,14 @@ public class QSFooter implements OnClickListener, DialogInterface.OnClickListene mIsVisible = true; } else { mFooterTextId = R.string.vpn_footer; + // Update the VPN footer icon, if needed. + int footerIconId = (mSecurityController.isVpnBranded() + ? R.drawable.ic_qs_branded_vpn + : R.drawable.ic_qs_vpn); + if (mFooterIconId != footerIconId) { + mFooterIcon.setImageResource(footerIconId); + mFooterIconId = footerIconId; + } mIsVisible = mIsIconVisible; } mMainHandler.post(mUpdateDisplayState); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java index 988d537f6c2cb..1810526ac3d84 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java @@ -67,6 +67,8 @@ public class SignalClusterView private boolean mNoSimsVisible = false; private boolean mVpnVisible = false; + private int mVpnIconId = 0; + private int mLastVpnIconId = -1; private boolean mEthernetVisible = false; private int mEthernetIconId = 0; private int mLastEthernetIconId = -1; @@ -164,6 +166,7 @@ public class SignalClusterView mSC = sc; mSC.addCallback(this); mVpnVisible = mSC.isVpnEnabled(); + mVpnIconId = currentVpnIconId(mSC.isVpnBranded()); } @Override @@ -241,6 +244,7 @@ public class SignalClusterView @Override public void run() { mVpnVisible = mSC.isVpnEnabled(); + mVpnIconId = currentVpnIconId(mSC.isVpnBranded()); apply(); } }); @@ -415,6 +419,15 @@ public class SignalClusterView if (mWifiGroup == null) return; mVpn.setVisibility(mVpnVisible ? View.VISIBLE : View.GONE); + if (mVpnVisible) { + if (mLastVpnIconId != mVpnIconId) { + setIconForView(mVpn, mVpnIconId); + mLastVpnIconId = mVpnIconId; + } + mVpn.setVisibility(View.VISIBLE); + } else { + mVpn.setVisibility(View.GONE); + } if (DEBUG) Log.d(TAG, String.format("vpn: %s", mVpnVisible ? "VISIBLE" : "GONE")); if (mEthernetVisible) { @@ -543,6 +556,10 @@ public class SignalClusterView v.setImageTintList(ColorStateList.valueOf(tint)); } + private int currentVpnIconId(boolean isBranded) { + return isBranded ? R.drawable.stat_sys_branded_vpn : R.drawable.stat_sys_vpn_ic; + } + private class PhoneState { private final int mSubId; private boolean mMobileVisible = false; @@ -664,4 +681,3 @@ public class SignalClusterView } } } - diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityController.java index a22f9884e101b..014afae7bf5a6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityController.java @@ -23,6 +23,8 @@ public interface SecurityController { String getProfileOwnerName(); boolean isVpnEnabled(); boolean isVpnRestricted(); + /** Whether the VPN app should use branded VPN iconography. */ + boolean isVpnBranded(); String getPrimaryVpnName(); String getProfileVpnName(); void onUserSwitched(int newUserId); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java index a85fe0d367696..d8facf01a48f9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java @@ -18,6 +18,8 @@ package com.android.systemui.statusbar.policy; import android.app.ActivityManager; import android.app.admin.DevicePolicyManager; import android.content.Context; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.UserInfo; import android.net.ConnectivityManager; @@ -54,10 +56,13 @@ public class SecurityControllerImpl implements SecurityController { .build(); private static final int NO_NETWORK = -1; + private static final String VPN_BRANDED_META_DATA = "com.android.systemui.IS_BRANDED"; + private final Context mContext; private final ConnectivityManager mConnectivityManager; private final IConnectivityManager mConnectivityManagerService; private final DevicePolicyManager mDevicePolicyManager; + private final PackageManager mPackageManager; private final UserManager mUserManager; @GuardedBy("mCallbacks") @@ -75,6 +80,7 @@ public class SecurityControllerImpl implements SecurityController { context.getSystemService(Context.CONNECTIVITY_SERVICE); mConnectivityManagerService = IConnectivityManager.Stub.asInterface( ServiceManager.getService(Context.CONNECTIVITY_SERVICE)); + mPackageManager = context.getPackageManager(); mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE); @@ -164,6 +170,21 @@ public class SecurityControllerImpl implements SecurityController { || mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_VPN, currentUser); } + @Override + public boolean isVpnBranded() { + VpnConfig cfg = mCurrentVpns.get(mVpnUserId); + if (cfg == null) { + return false; + } + + String packageName = getPackageNameForVpnConfig(cfg); + if (packageName == null) { + return false; + } + + return isVpnPackageBranded(packageName); + } + @Override public void removeCallback(SecurityControllerCallback callback) { synchronized (mCallbacks) { @@ -245,6 +266,28 @@ public class SecurityControllerImpl implements SecurityController { mCurrentVpns = vpns; } + private String getPackageNameForVpnConfig(VpnConfig cfg) { + if (cfg.legacy) { + return null; + } + return cfg.user; + } + + private boolean isVpnPackageBranded(String packageName) { + boolean isBranded; + try { + ApplicationInfo info = mPackageManager.getApplicationInfo(packageName, + PackageManager.GET_META_DATA); + if (info == null || info.metaData == null || !info.isSystemApp()) { + return false; + } + isBranded = info.metaData.getBoolean(VPN_BRANDED_META_DATA, false); + } catch (NameNotFoundException e) { + return false; + } + return isBranded; + } + private final NetworkCallback mNetworkCallback = new NetworkCallback() { @Override public void onAvailable(Network network) {