diff options
5 files changed, 216 insertions, 29 deletions
diff --git a/packages/SystemUI/res/drawable/ic_qs_network_logging.xml b/packages/SystemUI/res/drawable/ic_qs_network_logging.xml index 8200fcb2ca10..2cce5325a48c 100644 --- a/packages/SystemUI/res/drawable/ic_qs_network_logging.xml +++ b/packages/SystemUI/res/drawable/ic_qs_network_logging.xml @@ -24,6 +24,6 @@ Copyright (C) 2016 The Android Open Source Project android:tint="#4DFFFFFF" > <path android:fillColor="#FFFFFFFF" - android:pathData="M7,18v-2h6v2H7z M7,14v-2h10v2H7z M8.5,9 12,5.5 15.5,9 13,9 13,13 11,13 11,9z"/> + android:pathData="M2,24v-4h12v4H2z M2,16v-4h20v4H2z M5,7 12,0 19,7 14,7 14,15 10,15 10,7z"/> </vector> diff --git a/packages/SystemUI/res/layout/quick_settings_footer_dialog.xml b/packages/SystemUI/res/layout/quick_settings_footer_dialog.xml new file mode 100644 index 000000000000..2ba04fd31c0f --- /dev/null +++ b/packages/SystemUI/res/layout/quick_settings_footer_dialog.xml @@ -0,0 +1,117 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2016 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/scrollView" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:clipToPadding="false"> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:paddingTop="?android:attr/dialogPreferredPadding" + android:paddingRight="?android:attr/dialogPreferredPadding" + android:paddingLeft="?android:attr/dialogPreferredPadding" + android:paddingBottom="?android:attr/dialogPreferredPadding" + android:orientation="vertical"> + <TextView + android:id="@+id/device_owner_warning" + android:layout_width="match_parent" + android:layout_height="wrap_content" + style="@android:style/TextAppearance.Material.Subhead" + android:textColor="?android:attr/textColorPrimaryInverse" + /> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal"> + <ImageView + android:id="@+id/vpn_icon" + android:layout_width="@dimen/qs_footer_dialog_icon_size" + android:layout_height="wrap_content" + android:paddingTop="?android:attr/dialogPreferredPadding" + android:layout_marginStart="@dimen/qs_footer_dialog_icon_margin" + android:layout_marginEnd="@dimen/qs_footer_dialog_icon_margin" + android:scaleType="fitCenter" + android:src="@drawable/ic_qs_vpn" + android:tint="?android:attr/textColorPrimaryInverse" + android:adjustViewBounds="true"/> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical"> + <TextView + android:id="@+id/vpn_subtitle" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:paddingTop="?android:attr/dialogPreferredPadding" + android:text="@string/monitoring_subtitle_vpn" + style="@android:style/TextAppearance.Material.Title" + android:textColor="?android:attr/textColorPrimaryInverse" + /> + <TextView + android:id="@+id/vpn_warning" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@null" + style="@android:style/TextAppearance.Material.Subhead" + android:textColor="?android:attr/textColorPrimaryInverse" + /> + </LinearLayout> + </LinearLayout> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal"> + <ImageView + android:id="@+id/network_logging_icon" + android:layout_width="@dimen/qs_footer_dialog_icon_size" + android:layout_height="wrap_content" + android:paddingTop="?android:attr/dialogPreferredPadding" + android:layout_marginStart="@dimen/qs_footer_dialog_icon_margin" + android:layout_marginEnd="@dimen/qs_footer_dialog_icon_margin" + android:scaleType="fitCenter" + android:src="@drawable/ic_qs_network_logging" + android:tint="?android:attr/textColorPrimaryInverse" + android:alpha="@dimen/qs_footer_dialog_network_logging_icon_alpha" + android:adjustViewBounds="true"/> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical"> + <TextView + android:id="@+id/network_logging_subtitle" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:paddingTop="?android:attr/dialogPreferredPadding" + android:text="@string/monitoring_subtitle_network_logging" + style="@android:style/TextAppearance.Material.Title" + android:textColor="?android:attr/textColorPrimaryInverse" + /> + <TextView + android:id="@+id/network_logging_warning" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/monitoring_description_network_logging" + style="@android:style/TextAppearance.Material.Subhead" + android:textColor="?android:attr/textColorPrimaryInverse" + /> + </LinearLayout> + </LinearLayout> + </LinearLayout> +</ScrollView> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index dca9767fabed..e6194a9cca98 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -212,6 +212,13 @@ <!-- How far the expanded QS panel peeks from the header in collapsed state. --> <dimen name="qs_peek_height">0dp</dimen> + <!-- How large the icons in the quick settings footer dialog are --> + <dimen name="qs_footer_dialog_icon_size">24sp</dimen> + <!-- Left and right margin of the icons --> + <dimen name="qs_footer_dialog_icon_margin">8sp</dimen> + <!-- Alpha value of network logging icon --> + <item name="qs_footer_dialog_network_logging_icon_alpha" format="float" type="dimen">0.3</item> + <!-- Zen mode panel: condition item button padding --> <dimen name="zen_mode_condition_detail_button_padding">8dp</dimen> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index 2ea475a1166b..0bb58e37a71e 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -1013,6 +1013,13 @@ <!-- Monitoring dialog title for normal devices [CHAR LIMIT=35]--> <string name="monitoring_title">Network monitoring</string> + <!-- STOPSHIP(b/33655277) Monitoring strings still need to be finalized and approved --> + <!-- Monitoring dialog subtitle for the section describing VPN [CHAR LIMIT=TODO]--> + <string name="monitoring_subtitle_vpn">VPN</string> + + <!-- Monitoring dialog subtitle for the section describing network logging [CHAR LIMIT=TODO]--> + <string name="monitoring_subtitle_network_logging">Network Logging</string> + <!-- Monitoring dialog disable vpn button [CHAR LIMIT=30] --> <string name="disable_vpn">Disable VPN</string> @@ -1022,6 +1029,19 @@ <!-- Monitoring dialog device owner body text [CHAR LIMIT=400] --> <string name="monitoring_description_device_owned">Your device is managed by <xliff:g id="organization">%1$s</xliff:g>.\n\nYour administrator can monitor and manage settings, corporate access, apps, data associated with your device, and your device\'s location information. For more information, contact your administrator.</string> + <!-- Monitoring dialog: Part of text body explaining that a VPN is connected and what it can do, for devices managed by a Device Owner app [CHAR LIMIT=130] --> + <string name="monitoring_description_do_body_vpn">You\'re connected to <xliff:g id="vpn_app">%1$s</xliff:g>, which can monitor your network activity, including emails, apps, and websites.</string> + + <!-- Monitoring dialog: Space that separates the VPN body text and the "Open VPN Settings" link that follows it. [CHAR LIMIT=5] --> + <string name="monitoring_description_vpn_settings_separator">" "</string> + + <!-- Monitoring dialog: Link to open the VPN settings page [CHAR LIMIT=TODO] --> + <string name="monitoring_description_vpn_settings">Open VPN Settings</string> + + <!-- Monitoring dialog: Network logging text [CHAR LIMIT=TODO] --> + <string name="monitoring_description_network_logging">Your admin has turned on network logging, which monitors traffic on your device.\n\nFor more information contact your admin.</string> + + <!-- Monitoring dialog VPN text [CHAR LIMIT=400] --> <string name="monitoring_description_vpn">You gave an app permission to set up a VPN connection.\n\nThis app can monitor your device and network activity, including emails, apps, and websites.</string> diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java index 756513b61c45..92654b29cfba 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java @@ -24,9 +24,14 @@ import android.os.Handler; import android.os.Looper; import android.os.Message; import android.os.UserHandle; +import android.provider.Settings; +import android.text.SpannableStringBuilder; +import android.text.method.LinkMovementMethod; +import android.text.style.ClickableSpan; import android.util.Log; import android.view.LayoutInflater; import android.view.View; +import android.view.ViewGroup; import android.view.View.OnClickListener; import android.widget.ImageView; import android.widget.TextView; @@ -159,24 +164,60 @@ public class QSFooter implements OnClickListener, DialogInterface.OnClickListene } private void createDialog() { - String deviceOwner = mSecurityController.getDeviceOwnerName(); - String profileOwner = mSecurityController.getProfileOwnerName(); - String primaryVpn = mSecurityController.getPrimaryVpnName(); - String profileVpn = mSecurityController.getProfileVpnName(); - boolean managed = mSecurityController.hasProfileOwner(); - boolean isBranded = deviceOwner == null && mSecurityController.isVpnBranded(); + final String deviceOwnerPackage = mSecurityController.getDeviceOwnerName(); + final String profileOwnerPackage = mSecurityController.getProfileOwnerName(); + final boolean isNetworkLoggingEnabled = mSecurityController.isNetworkLoggingEnabled(); + final String primaryVpn = mSecurityController.getPrimaryVpnName(); + final String profileVpn = mSecurityController.getProfileVpnName(); + boolean hasProfileOwner = mSecurityController.hasProfileOwner(); + boolean isBranded = deviceOwnerPackage == null && mSecurityController.isVpnBranded(); mDialog = new SystemUIDialog(mContext); if (!isBranded) { - mDialog.setTitle(getTitle(deviceOwner)); + mDialog.setTitle(getTitle(deviceOwnerPackage)); } - mDialog.setMessage(getMessage(deviceOwner, profileOwner, primaryVpn, profileVpn, managed, - isBranded)); - mDialog.setButton(DialogInterface.BUTTON_POSITIVE, getPositiveButton(isBranded), this); - if (mSecurityController.isVpnEnabled() && !mSecurityController.isVpnRestricted()) { - mDialog.setButton(DialogInterface.BUTTON_NEGATIVE, getSettingsButton(), this); + CharSequence msg = getMessage(deviceOwnerPackage, profileOwnerPackage, primaryVpn, + profileVpn, hasProfileOwner, isBranded); + if (deviceOwnerPackage == null) { + mDialog.setMessage(msg); + } else { + View dialogView = LayoutInflater.from(mContext) + .inflate(R.layout.quick_settings_footer_dialog, null, false); + mDialog.setView(dialogView); + TextView deviceOwnerWarning = + (TextView) dialogView.findViewById(R.id.device_owner_warning); + deviceOwnerWarning.setText(msg); + // Make the link "learn more" clickable. + deviceOwnerWarning.setMovementMethod(new LinkMovementMethod()); + if (primaryVpn == null) { + dialogView.findViewById(R.id.vpn_icon).setVisibility(View.GONE); + dialogView.findViewById(R.id.vpn_subtitle).setVisibility(View.GONE); + dialogView.findViewById(R.id.vpn_warning).setVisibility(View.GONE); + } else { + final SpannableStringBuilder message = new SpannableStringBuilder(); + message.append(mContext.getString(R.string.monitoring_description_do_body_vpn, + primaryVpn)); + message.append(mContext.getString( + R.string.monitoring_description_vpn_settings_separator)); + message.append(mContext.getString(R.string.monitoring_description_vpn_settings), + new VpnSpan(), 0); + + TextView vpnWarning = (TextView) dialogView.findViewById(R.id.vpn_warning); + vpnWarning.setText(message); + // Make the link "Open VPN Settings" clickable. + vpnWarning.setMovementMethod(new LinkMovementMethod()); + } + if (!isNetworkLoggingEnabled) { + dialogView.findViewById(R.id.network_logging_icon).setVisibility(View.GONE); + dialogView.findViewById(R.id.network_logging_subtitle).setVisibility(View.GONE); + dialogView.findViewById(R.id.network_logging_warning).setVisibility(View.GONE); + } } + + mDialog.setButton(DialogInterface.BUTTON_POSITIVE, getPositiveButton(isBranded), this); mDialog.show(); + mDialog.getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.WRAP_CONTENT); } private String getSettingsButton() { @@ -187,22 +228,15 @@ public class QSFooter implements OnClickListener, DialogInterface.OnClickListene return mContext.getString(isBranded ? android.R.string.ok : R.string.quick_settings_done); } - private String getMessage(String deviceOwner, String profileOwner, String primaryVpn, - String profileVpn, boolean primaryUserIsManaged, boolean isBranded) { - // Show a special warning when the device has device owner, but -- - // TODO See b/25779452 -- device owner doesn't actually have monitoring power. - if (deviceOwner != null) { - if (primaryVpn != null) { - return mContext.getString(R.string.monitoring_description_vpn_app_device_owned, - deviceOwner, primaryVpn); - } else { - return mContext.getString(R.string.monitoring_description_device_owned, - deviceOwner); - } + protected CharSequence getMessage(String deviceOwnerPackage, String profileOwnerPackage, + String primaryVpn, String profileVpn, boolean hasProfileOwner, boolean isBranded) { + if (deviceOwnerPackage != null) { + return mContext.getString(R.string.monitoring_description_device_owned, + deviceOwnerPackage); } else if (primaryVpn != null) { if (profileVpn != null) { return mContext.getString(R.string.monitoring_description_app_personal_work, - profileOwner, profileVpn, primaryVpn); + profileOwnerPackage, profileVpn, primaryVpn); } else { if (isBranded) { return mContext.getString(R.string.branded_monitoring_description_app_personal, @@ -214,10 +248,10 @@ public class QSFooter implements OnClickListener, DialogInterface.OnClickListene } } else if (profileVpn != null) { return mContext.getString(R.string.monitoring_description_app_work, - profileOwner, profileVpn); - } else if (profileOwner != null && primaryUserIsManaged) { + profileOwnerPackage, profileVpn); + } else if (profileOwnerPackage != null && hasProfileOwner) { return mContext.getString(R.string.monitoring_description_device_owned, - profileOwner); + profileOwnerPackage); } else { // No device owner, no personal VPN, no work VPN, no user owner. Why are we here? return null; @@ -286,4 +320,13 @@ public class QSFooter implements OnClickListener, DialogInterface.OnClickListene } } + protected class VpnSpan extends ClickableSpan { + @Override + public void onClick(View widget) { + final Intent intent = new Intent(Settings.ACTION_VPN_SETTINGS); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); + mDialog.dismiss(); + mContext.startActivity(intent); + } + } } |