DO NOT MERGE Rework Device Monitoring Dialog in Quicksettings
If a device owner is active, the layout is changed from a
standard AlertDialog with only one string to a custom dialog
that includes information on Device Owners, and VPN and Network Logging,
if enabled.
Cherry-picked from master and modified to not rely on changes that are not in
N:
A change in master renamed some variables in QSFooter.createDialog() and made
them final, this change is also included here.
The owner's organization name cannot be set in N.
In the case of active Device Owner and active VPN, there was a specialized
string for this in N. This string was now replaced by using the simpler
Device Owner string + an own entry for VPN in the new layout.
Some imports had to be included that were already there on master.
The dimen-tag throws an error message on floats during build, replaced by an
item-tag.
BUG: 29748723
BUG: 33126622
Test: Manual, CTS-Verifier tests will be added later
(cherry picked from commit 9e450e1233)
Change-Id: I2bfca9d9d02a42d9c3b17683625eda29e9369666
This commit is contained in:
@@ -24,6 +24,6 @@ Copyright (C) 2016 The Android Open Source Project
|
|||||||
android:tint="#4DFFFFFF" >
|
android:tint="#4DFFFFFF" >
|
||||||
<path
|
<path
|
||||||
android:fillColor="#FFFFFFFF"
|
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>
|
</vector>
|
||||||
|
|||||||
117
packages/SystemUI/res/layout/quick_settings_footer_dialog.xml
Normal file
117
packages/SystemUI/res/layout/quick_settings_footer_dialog.xml
Normal file
@@ -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>
|
||||||
@@ -212,6 +212,13 @@
|
|||||||
<!-- How far the expanded QS panel peeks from the header in collapsed state. -->
|
<!-- How far the expanded QS panel peeks from the header in collapsed state. -->
|
||||||
<dimen name="qs_peek_height">0dp</dimen>
|
<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 -->
|
<!-- Zen mode panel: condition item button padding -->
|
||||||
<dimen name="zen_mode_condition_detail_button_padding">8dp</dimen>
|
<dimen name="zen_mode_condition_detail_button_padding">8dp</dimen>
|
||||||
|
|
||||||
|
|||||||
@@ -1013,6 +1013,13 @@
|
|||||||
<!-- Monitoring dialog title for normal devices [CHAR LIMIT=35]-->
|
<!-- Monitoring dialog title for normal devices [CHAR LIMIT=35]-->
|
||||||
<string name="monitoring_title">Network monitoring</string>
|
<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] -->
|
<!-- Monitoring dialog disable vpn button [CHAR LIMIT=30] -->
|
||||||
<string name="disable_vpn">Disable VPN</string>
|
<string name="disable_vpn">Disable VPN</string>
|
||||||
|
|
||||||
@@ -1022,6 +1029,19 @@
|
|||||||
<!-- Monitoring dialog device owner body text [CHAR LIMIT=400] -->
|
<!-- 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>
|
<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] -->
|
<!-- 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>
|
<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>
|
||||||
|
|
||||||
|
|||||||
@@ -24,9 +24,14 @@ import android.os.Handler;
|
|||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
import android.os.UserHandle;
|
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.util.Log;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
import android.view.View.OnClickListener;
|
import android.view.View.OnClickListener;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
@@ -159,24 +164,60 @@ public class QSFooter implements OnClickListener, DialogInterface.OnClickListene
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void createDialog() {
|
private void createDialog() {
|
||||||
String deviceOwner = mSecurityController.getDeviceOwnerName();
|
final String deviceOwnerPackage = mSecurityController.getDeviceOwnerName();
|
||||||
String profileOwner = mSecurityController.getProfileOwnerName();
|
final String profileOwnerPackage = mSecurityController.getProfileOwnerName();
|
||||||
String primaryVpn = mSecurityController.getPrimaryVpnName();
|
final boolean isNetworkLoggingEnabled = mSecurityController.isNetworkLoggingEnabled();
|
||||||
String profileVpn = mSecurityController.getProfileVpnName();
|
final String primaryVpn = mSecurityController.getPrimaryVpnName();
|
||||||
boolean managed = mSecurityController.hasProfileOwner();
|
final String profileVpn = mSecurityController.getProfileVpnName();
|
||||||
boolean isBranded = deviceOwner == null && mSecurityController.isVpnBranded();
|
boolean hasProfileOwner = mSecurityController.hasProfileOwner();
|
||||||
|
boolean isBranded = deviceOwnerPackage == null && mSecurityController.isVpnBranded();
|
||||||
|
|
||||||
mDialog = new SystemUIDialog(mContext);
|
mDialog = new SystemUIDialog(mContext);
|
||||||
if (!isBranded) {
|
if (!isBranded) {
|
||||||
mDialog.setTitle(getTitle(deviceOwner));
|
mDialog.setTitle(getTitle(deviceOwnerPackage));
|
||||||
}
|
}
|
||||||
mDialog.setMessage(getMessage(deviceOwner, profileOwner, primaryVpn, profileVpn, managed,
|
CharSequence msg = getMessage(deviceOwnerPackage, profileOwnerPackage, primaryVpn,
|
||||||
isBranded));
|
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.setButton(DialogInterface.BUTTON_POSITIVE, getPositiveButton(isBranded), this);
|
||||||
if (mSecurityController.isVpnEnabled() && !mSecurityController.isVpnRestricted()) {
|
|
||||||
mDialog.setButton(DialogInterface.BUTTON_NEGATIVE, getSettingsButton(), this);
|
|
||||||
}
|
|
||||||
mDialog.show();
|
mDialog.show();
|
||||||
|
mDialog.getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT,
|
||||||
|
ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getSettingsButton() {
|
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);
|
return mContext.getString(isBranded ? android.R.string.ok : R.string.quick_settings_done);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getMessage(String deviceOwner, String profileOwner, String primaryVpn,
|
protected CharSequence getMessage(String deviceOwnerPackage, String profileOwnerPackage,
|
||||||
String profileVpn, boolean primaryUserIsManaged, boolean isBranded) {
|
String primaryVpn, String profileVpn, boolean hasProfileOwner, boolean isBranded) {
|
||||||
// Show a special warning when the device has device owner, but --
|
if (deviceOwnerPackage != null) {
|
||||||
// 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,
|
return mContext.getString(R.string.monitoring_description_device_owned,
|
||||||
deviceOwner);
|
deviceOwnerPackage);
|
||||||
}
|
|
||||||
} else if (primaryVpn != null) {
|
} else if (primaryVpn != null) {
|
||||||
if (profileVpn != null) {
|
if (profileVpn != null) {
|
||||||
return mContext.getString(R.string.monitoring_description_app_personal_work,
|
return mContext.getString(R.string.monitoring_description_app_personal_work,
|
||||||
profileOwner, profileVpn, primaryVpn);
|
profileOwnerPackage, profileVpn, primaryVpn);
|
||||||
} else {
|
} else {
|
||||||
if (isBranded) {
|
if (isBranded) {
|
||||||
return mContext.getString(R.string.branded_monitoring_description_app_personal,
|
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) {
|
} else if (profileVpn != null) {
|
||||||
return mContext.getString(R.string.monitoring_description_app_work,
|
return mContext.getString(R.string.monitoring_description_app_work,
|
||||||
profileOwner, profileVpn);
|
profileOwnerPackage, profileVpn);
|
||||||
} else if (profileOwner != null && primaryUserIsManaged) {
|
} else if (profileOwnerPackage != null && hasProfileOwner) {
|
||||||
return mContext.getString(R.string.monitoring_description_device_owned,
|
return mContext.getString(R.string.monitoring_description_device_owned,
|
||||||
profileOwner);
|
profileOwnerPackage);
|
||||||
} else {
|
} else {
|
||||||
// No device owner, no personal VPN, no work VPN, no user owner. Why are we here?
|
// No device owner, no personal VPN, no work VPN, no user owner. Why are we here?
|
||||||
return null;
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user