Extract QSSecurityFooterUtils out of QSSecurityFooter
This CL extracts QSSecurityFooterUtils out of QSSecurityFooter to make it usable outside of QSSecurityFooter, which is a ViewController scoped to the Quick Settings fragment. This will make the utils usable outside this controller, e.g. in an Interactor/ViewModel not scope to QS. Bug: 242040009 Test: atest QSSecurityFooterTest Change-Id: If8289c9f28525f35603d03ed0ba3e646b7c06df8
This commit is contained in:
@@ -15,122 +15,59 @@
|
||||
*/
|
||||
package com.android.systemui.qs;
|
||||
|
||||
import static android.app.admin.DevicePolicyManager.DEVICE_OWNER_TYPE_FINANCED;
|
||||
import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_DIALOG_MANAGEMENT;
|
||||
import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_DIALOG_MANAGEMENT_CA_CERT;
|
||||
import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_DIALOG_MANAGEMENT_NAMED_VPN;
|
||||
import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_DIALOG_MANAGEMENT_NETWORK;
|
||||
import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_DIALOG_MANAGEMENT_TITLE;
|
||||
import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_DIALOG_MANAGEMENT_TWO_NAMED_VPN;
|
||||
import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_DIALOG_MONITORING_CA_CERT_SUBTITLE;
|
||||
import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_DIALOG_MONITORING_NETWORK_SUBTITLE;
|
||||
import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_DIALOG_MONITORING_VPN_SUBTITLE;
|
||||
import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_DIALOG_NAMED_MANAGEMENT;
|
||||
import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_DIALOG_PERSONAL_PROFILE_NAMED_VPN;
|
||||
import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_DIALOG_VIEW_POLICIES;
|
||||
import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_DIALOG_WORK_PROFILE_CA_CERT;
|
||||
import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_DIALOG_WORK_PROFILE_NAMED_VPN;
|
||||
import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_DIALOG_WORK_PROFILE_NETWORK;
|
||||
import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_MSG_MANAGEMENT;
|
||||
import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_MSG_MANAGEMENT_MONITORING;
|
||||
import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_MSG_MANAGEMENT_MULTIPLE_VPNS;
|
||||
import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_MSG_MANAGEMENT_NAMED_VPN;
|
||||
import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_MSG_NAMED_MANAGEMENT;
|
||||
import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_MSG_NAMED_MANAGEMENT_MONITORING;
|
||||
import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_MSG_NAMED_MANAGEMENT_MULTIPLE_VPNS;
|
||||
import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_MSG_NAMED_MANAGEMENT_NAMED_VPN;
|
||||
import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_MSG_NAMED_WORK_PROFILE_MONITORING;
|
||||
import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_MSG_PERSONAL_PROFILE_NAMED_VPN;
|
||||
import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_MSG_WORK_PROFILE_MONITORING;
|
||||
import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_MSG_WORK_PROFILE_NAMED_VPN;
|
||||
import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_MSG_WORK_PROFILE_NETWORK;
|
||||
|
||||
import static com.android.systemui.qs.dagger.QSFragmentModule.QS_SECURITY_FOOTER_VIEW;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.app.admin.DeviceAdminInfo;
|
||||
import android.app.admin.DevicePolicyEventLogger;
|
||||
import android.app.admin.DevicePolicyManager;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
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.View.OnClickListener;
|
||||
import android.view.Window;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import com.android.internal.jank.InteractionJankMonitor;
|
||||
import com.android.internal.util.FrameworkStatsLog;
|
||||
import com.android.systemui.FontSizeUtils;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.animation.DialogCuj;
|
||||
import com.android.systemui.animation.DialogLaunchAnimator;
|
||||
import com.android.systemui.broadcast.BroadcastDispatcher;
|
||||
import com.android.systemui.common.shared.model.Icon;
|
||||
import com.android.systemui.dagger.qualifiers.Background;
|
||||
import com.android.systemui.dagger.qualifiers.Main;
|
||||
import com.android.systemui.plugins.ActivityStarter;
|
||||
import com.android.systemui.qs.dagger.QSScope;
|
||||
import com.android.systemui.qs.footer.domain.model.SecurityButtonConfig;
|
||||
import com.android.systemui.security.data.model.SecurityModel;
|
||||
import com.android.systemui.settings.UserTracker;
|
||||
import com.android.systemui.statusbar.phone.SystemUIDialog;
|
||||
import com.android.systemui.statusbar.policy.SecurityController;
|
||||
import com.android.systemui.util.ViewController;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
|
||||
/** Helper class for the configuration of the QS security footer button. */
|
||||
/** ViewController for the footer actions. */
|
||||
// TODO(b/242040009): Remove this class.
|
||||
@QSScope
|
||||
public class QSSecurityFooter extends ViewController<View>
|
||||
implements OnClickListener, DialogInterface.OnClickListener,
|
||||
VisibilityChangedDispatcher {
|
||||
implements OnClickListener, VisibilityChangedDispatcher {
|
||||
protected static final String TAG = "QSSecurityFooter";
|
||||
protected static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
|
||||
private static final boolean DEBUG_FORCE_VISIBLE = false;
|
||||
|
||||
private static final String INTERACTION_JANK_TAG = "managed_device_info";
|
||||
|
||||
private final TextView mFooterText;
|
||||
private final ImageView mPrimaryFooterIcon;
|
||||
private Context mContext;
|
||||
private final DevicePolicyManager mDpm;
|
||||
private final Callback mCallback = new Callback();
|
||||
private final SecurityController mSecurityController;
|
||||
private final ActivityStarter mActivityStarter;
|
||||
private final Handler mMainHandler;
|
||||
private final UserTracker mUserTracker;
|
||||
private final DialogLaunchAnimator mDialogLaunchAnimator;
|
||||
private final BroadcastDispatcher mBroadcastDispatcher;
|
||||
private final QSSecurityFooterUtils mQSSecurityFooterUtils;
|
||||
|
||||
private final AtomicBoolean mShouldUseSettingsButton = new AtomicBoolean(false);
|
||||
|
||||
private AlertDialog mDialog;
|
||||
protected H mHandler;
|
||||
|
||||
private boolean mIsVisible;
|
||||
@@ -152,82 +89,21 @@ public class QSSecurityFooter extends ViewController<View>
|
||||
}
|
||||
};
|
||||
|
||||
private Supplier<String> mManagementTitleSupplier = () ->
|
||||
mContext == null ? null : mContext.getString(R.string.monitoring_title_device_owned);
|
||||
|
||||
private Supplier<String> mManagementMessageSupplier = () ->
|
||||
mContext == null ? null : mContext.getString(
|
||||
R.string.quick_settings_disclosure_management);
|
||||
|
||||
private Supplier<String> mManagementMonitoringStringSupplier = () ->
|
||||
mContext == null ? null : mContext.getString(
|
||||
R.string.quick_settings_disclosure_management_monitoring);
|
||||
|
||||
private Supplier<String> mManagementMultipleVpnStringSupplier = () ->
|
||||
mContext == null ? null : mContext.getString(
|
||||
R.string.quick_settings_disclosure_management_vpns);
|
||||
|
||||
private Supplier<String> mWorkProfileMonitoringStringSupplier = () ->
|
||||
mContext == null ? null : mContext.getString(
|
||||
R.string.quick_settings_disclosure_managed_profile_monitoring);
|
||||
|
||||
private Supplier<String> mWorkProfileNetworkStringSupplier = () ->
|
||||
mContext == null ? null : mContext.getString(
|
||||
R.string.quick_settings_disclosure_managed_profile_network_activity);
|
||||
|
||||
private Supplier<String> mMonitoringSubtitleCaCertStringSupplier = () ->
|
||||
mContext == null ? null : mContext.getString(
|
||||
R.string.monitoring_subtitle_ca_certificate);
|
||||
|
||||
private Supplier<String> mMonitoringSubtitleNetworkStringSupplier = () ->
|
||||
mContext == null ? null : mContext.getString(
|
||||
R.string.monitoring_subtitle_network_logging);
|
||||
|
||||
private Supplier<String> mMonitoringSubtitleVpnStringSupplier = () ->
|
||||
mContext == null ? null : mContext.getString(R.string.monitoring_subtitle_vpn);
|
||||
|
||||
private Supplier<String> mViewPoliciesButtonStringSupplier = () ->
|
||||
mContext == null ? null : mContext.getString(R.string.monitoring_button_view_policies);
|
||||
|
||||
private Supplier<String> mManagementDialogStringSupplier = () ->
|
||||
mContext == null ? null : mContext.getString(
|
||||
R.string.monitoring_description_management);
|
||||
|
||||
private Supplier<String> mManagementDialogCaCertStringSupplier = () ->
|
||||
mContext == null ? null : mContext.getString(
|
||||
R.string.monitoring_description_management_ca_certificate);
|
||||
|
||||
private Supplier<String> mWorkProfileDialogCaCertStringSupplier = () ->
|
||||
mContext == null ? null : mContext.getString(
|
||||
R.string.monitoring_description_managed_profile_ca_certificate);
|
||||
|
||||
private Supplier<String> mManagementDialogNetworkStringSupplier = () ->
|
||||
mContext == null ? null : mContext.getString(
|
||||
R.string.monitoring_description_management_network_logging);
|
||||
|
||||
private Supplier<String> mWorkProfileDialogNetworkStringSupplier = () ->
|
||||
mContext == null ? null : mContext.getString(
|
||||
R.string.monitoring_description_managed_profile_network_logging);
|
||||
|
||||
@Inject
|
||||
QSSecurityFooter(@Named(QS_SECURITY_FOOTER_VIEW) View rootView,
|
||||
UserTracker userTracker, @Main Handler mainHandler,
|
||||
ActivityStarter activityStarter, SecurityController securityController,
|
||||
DialogLaunchAnimator dialogLaunchAnimator, @Background Looper bgLooper,
|
||||
BroadcastDispatcher broadcastDispatcher) {
|
||||
@Main Handler mainHandler, SecurityController securityController,
|
||||
@Background Looper bgLooper, BroadcastDispatcher broadcastDispatcher,
|
||||
QSSecurityFooterUtils qSSecurityFooterUtils) {
|
||||
super(rootView);
|
||||
mFooterText = mView.findViewById(R.id.footer_text);
|
||||
mPrimaryFooterIcon = mView.findViewById(R.id.primary_footer_icon);
|
||||
mFooterIcon = new Icon.Resource(R.drawable.ic_info_outline);
|
||||
mContext = rootView.getContext();
|
||||
mDpm = rootView.getContext().getSystemService(DevicePolicyManager.class);
|
||||
mMainHandler = mainHandler;
|
||||
mActivityStarter = activityStarter;
|
||||
mSecurityController = securityController;
|
||||
mMainHandler = mainHandler;
|
||||
mHandler = new H(bgLooper);
|
||||
mUserTracker = userTracker;
|
||||
mDialogLaunchAnimator = dialogLaunchAnimator;
|
||||
mBroadcastDispatcher = broadcastDispatcher;
|
||||
mQSSecurityFooterUtils = qSSecurityFooterUtils;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -292,16 +168,7 @@ public class QSSecurityFooter extends ViewController<View>
|
||||
|
||||
// TODO(b/242040009): Remove this.
|
||||
public void showDeviceMonitoringDialog() {
|
||||
showDeviceMonitoringDialog(mContext, mView);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the device monitoring dialog, and expand it from {@code view} if it's not null.
|
||||
*
|
||||
* Important: {@code view} must be associated to the same {@link Context} as the QSFragment.
|
||||
*/
|
||||
public void showDeviceMonitoringDialog(Context quickSettingsContext, @Nullable View view) {
|
||||
createDialog(quickSettingsContext, view);
|
||||
mQSSecurityFooterUtils.showDeviceMonitoringDialog(mContext, mView);
|
||||
}
|
||||
|
||||
public void refreshState() {
|
||||
@@ -310,7 +177,7 @@ public class QSSecurityFooter extends ViewController<View>
|
||||
|
||||
private void handleRefreshState() {
|
||||
SecurityModel securityModel = SecurityModel.create(mSecurityController);
|
||||
SecurityButtonConfig buttonConfig = getButtonConfig(securityModel);
|
||||
SecurityButtonConfig buttonConfig = mQSSecurityFooterUtils.getButtonConfig(securityModel);
|
||||
|
||||
if (buttonConfig == null) {
|
||||
mIsVisible = false;
|
||||
@@ -326,577 +193,6 @@ public class QSSecurityFooter extends ViewController<View>
|
||||
mMainHandler.post(mUpdateDisplayState);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the {@link SecurityButtonConfig} of the security button, or {@code null} if no
|
||||
* security button should be shown.
|
||||
*/
|
||||
@Nullable
|
||||
public SecurityButtonConfig getButtonConfig(SecurityModel securityModel) {
|
||||
final boolean isDeviceManaged = securityModel.isDeviceManaged();
|
||||
final UserInfo currentUser = mUserTracker.getUserInfo();
|
||||
final boolean isDemoDevice = UserManager.isDeviceInDemoMode(mContext) && currentUser != null
|
||||
&& currentUser.isDemo();
|
||||
final boolean hasWorkProfile = securityModel.getHasWorkProfile();
|
||||
final boolean hasCACerts = securityModel.getHasCACertInCurrentUser();
|
||||
final boolean hasCACertsInWorkProfile = securityModel.getHasCACertInWorkProfile();
|
||||
final boolean isNetworkLoggingEnabled = securityModel.isNetworkLoggingEnabled();
|
||||
final String vpnName = securityModel.getPrimaryVpnName();
|
||||
final String vpnNameWorkProfile = securityModel.getWorkProfileVpnName();
|
||||
final CharSequence organizationName = securityModel.getDeviceOwnerOrganizationName();
|
||||
final CharSequence workProfileOrganizationName =
|
||||
securityModel.getWorkProfileOrganizationName();
|
||||
final boolean isProfileOwnerOfOrganizationOwnedDevice =
|
||||
securityModel.isProfileOwnerOfOrganizationOwnedDevice();
|
||||
final boolean isParentalControlsEnabled = securityModel.isParentalControlsEnabled();
|
||||
final boolean isWorkProfileOn = securityModel.isWorkProfileOn();
|
||||
final boolean hasDisclosableWorkProfilePolicy = hasCACertsInWorkProfile
|
||||
|| vpnNameWorkProfile != null || (hasWorkProfile && isNetworkLoggingEnabled);
|
||||
// Update visibility of footer
|
||||
boolean isVisible = (isDeviceManaged && !isDemoDevice)
|
||||
|| hasCACerts
|
||||
|| vpnName != null
|
||||
|| isProfileOwnerOfOrganizationOwnedDevice
|
||||
|| isParentalControlsEnabled
|
||||
|| (hasDisclosableWorkProfilePolicy && isWorkProfileOn);
|
||||
if (!isVisible && !DEBUG_FORCE_VISIBLE) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Update the view to be untappable if the device is an organization-owned device with a
|
||||
// managed profile and there is either:
|
||||
// a) no policy set which requires a privacy disclosure.
|
||||
// b) a specific work policy set but the work profile is turned off.
|
||||
boolean isClickable = !(isProfileOwnerOfOrganizationOwnedDevice
|
||||
&& (!hasDisclosableWorkProfilePolicy || !isWorkProfileOn));
|
||||
|
||||
String text = getFooterText(isDeviceManaged, hasWorkProfile,
|
||||
hasCACerts, hasCACertsInWorkProfile, isNetworkLoggingEnabled, vpnName,
|
||||
vpnNameWorkProfile, organizationName, workProfileOrganizationName,
|
||||
isProfileOwnerOfOrganizationOwnedDevice, isParentalControlsEnabled,
|
||||
isWorkProfileOn).toString();
|
||||
|
||||
Icon icon;
|
||||
if (isParentalControlsEnabled) {
|
||||
icon = new Icon.Loaded(securityModel.getDeviceAdminIcon());
|
||||
} else if (vpnName != null || vpnNameWorkProfile != null) {
|
||||
if (securityModel.isVpnBranded()) {
|
||||
icon = new Icon.Resource(R.drawable.stat_sys_branded_vpn);
|
||||
} else {
|
||||
icon = new Icon.Resource(R.drawable.stat_sys_vpn_ic);
|
||||
}
|
||||
} else {
|
||||
icon = new Icon.Resource(R.drawable.ic_info_outline);
|
||||
}
|
||||
|
||||
return new SecurityButtonConfig(icon, text, isClickable);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected CharSequence getFooterText(boolean isDeviceManaged, boolean hasWorkProfile,
|
||||
boolean hasCACerts, boolean hasCACertsInWorkProfile, boolean isNetworkLoggingEnabled,
|
||||
String vpnName, String vpnNameWorkProfile, CharSequence organizationName,
|
||||
CharSequence workProfileOrganizationName,
|
||||
boolean isProfileOwnerOfOrganizationOwnedDevice, boolean isParentalControlsEnabled,
|
||||
boolean isWorkProfileOn) {
|
||||
if (isParentalControlsEnabled) {
|
||||
return mContext.getString(R.string.quick_settings_disclosure_parental_controls);
|
||||
}
|
||||
if (isDeviceManaged || DEBUG_FORCE_VISIBLE) {
|
||||
return getManagedDeviceFooterText(hasCACerts, hasCACertsInWorkProfile,
|
||||
isNetworkLoggingEnabled, vpnName, vpnNameWorkProfile, organizationName);
|
||||
}
|
||||
return getManagedAndPersonalProfileFooterText(hasWorkProfile, hasCACerts,
|
||||
hasCACertsInWorkProfile, isNetworkLoggingEnabled, vpnName, vpnNameWorkProfile,
|
||||
workProfileOrganizationName, isProfileOwnerOfOrganizationOwnedDevice,
|
||||
isWorkProfileOn);
|
||||
}
|
||||
|
||||
private String getManagedDeviceFooterText(
|
||||
boolean hasCACerts, boolean hasCACertsInWorkProfile, boolean isNetworkLoggingEnabled,
|
||||
String vpnName, String vpnNameWorkProfile, CharSequence organizationName) {
|
||||
if (hasCACerts || hasCACertsInWorkProfile || isNetworkLoggingEnabled) {
|
||||
return getManagedDeviceMonitoringText(organizationName);
|
||||
}
|
||||
if (vpnName != null || vpnNameWorkProfile != null) {
|
||||
return getManagedDeviceVpnText(vpnName, vpnNameWorkProfile, organizationName);
|
||||
}
|
||||
return getMangedDeviceGeneralText(organizationName);
|
||||
}
|
||||
|
||||
private String getManagedDeviceMonitoringText(CharSequence organizationName) {
|
||||
if (organizationName == null) {
|
||||
return mDpm.getResources().getString(
|
||||
QS_MSG_MANAGEMENT_MONITORING, mManagementMonitoringStringSupplier);
|
||||
}
|
||||
return mDpm.getResources().getString(
|
||||
QS_MSG_NAMED_MANAGEMENT_MONITORING,
|
||||
() -> mContext.getString(
|
||||
R.string.quick_settings_disclosure_named_management_monitoring,
|
||||
organizationName),
|
||||
organizationName);
|
||||
}
|
||||
|
||||
private String getManagedDeviceVpnText(
|
||||
String vpnName, String vpnNameWorkProfile, CharSequence organizationName) {
|
||||
if (vpnName != null && vpnNameWorkProfile != null) {
|
||||
if (organizationName == null) {
|
||||
return mDpm.getResources().getString(
|
||||
QS_MSG_MANAGEMENT_MULTIPLE_VPNS, mManagementMultipleVpnStringSupplier);
|
||||
}
|
||||
return mDpm.getResources().getString(
|
||||
QS_MSG_NAMED_MANAGEMENT_MULTIPLE_VPNS,
|
||||
() -> mContext.getString(
|
||||
R.string.quick_settings_disclosure_named_management_vpns,
|
||||
organizationName),
|
||||
organizationName);
|
||||
}
|
||||
String name = vpnName != null ? vpnName : vpnNameWorkProfile;
|
||||
if (organizationName == null) {
|
||||
return mDpm.getResources().getString(
|
||||
QS_MSG_MANAGEMENT_NAMED_VPN,
|
||||
() -> mContext.getString(
|
||||
R.string.quick_settings_disclosure_management_named_vpn,
|
||||
name),
|
||||
name);
|
||||
}
|
||||
return mDpm.getResources().getString(
|
||||
QS_MSG_NAMED_MANAGEMENT_NAMED_VPN,
|
||||
() -> mContext.getString(
|
||||
R.string.quick_settings_disclosure_named_management_named_vpn,
|
||||
organizationName,
|
||||
name),
|
||||
organizationName,
|
||||
name);
|
||||
}
|
||||
|
||||
private String getMangedDeviceGeneralText(CharSequence organizationName) {
|
||||
if (organizationName == null) {
|
||||
return mDpm.getResources().getString(QS_MSG_MANAGEMENT, mManagementMessageSupplier);
|
||||
}
|
||||
if (isFinancedDevice()) {
|
||||
return mContext.getString(
|
||||
R.string.quick_settings_financed_disclosure_named_management,
|
||||
organizationName);
|
||||
} else {
|
||||
return mDpm.getResources().getString(
|
||||
QS_MSG_NAMED_MANAGEMENT,
|
||||
() -> mContext.getString(
|
||||
R.string.quick_settings_disclosure_named_management,
|
||||
organizationName),
|
||||
organizationName);
|
||||
}
|
||||
}
|
||||
|
||||
private String getManagedAndPersonalProfileFooterText(boolean hasWorkProfile,
|
||||
boolean hasCACerts, boolean hasCACertsInWorkProfile, boolean isNetworkLoggingEnabled,
|
||||
String vpnName, String vpnNameWorkProfile, CharSequence workProfileOrganizationName,
|
||||
boolean isProfileOwnerOfOrganizationOwnedDevice, boolean isWorkProfileOn) {
|
||||
if (hasCACerts || (hasCACertsInWorkProfile && isWorkProfileOn)) {
|
||||
return getMonitoringText(
|
||||
hasCACerts, hasCACertsInWorkProfile, workProfileOrganizationName,
|
||||
isWorkProfileOn);
|
||||
}
|
||||
if (vpnName != null || (vpnNameWorkProfile != null && isWorkProfileOn)) {
|
||||
return getVpnText(hasWorkProfile, vpnName, vpnNameWorkProfile, isWorkProfileOn);
|
||||
}
|
||||
if (hasWorkProfile && isNetworkLoggingEnabled && isWorkProfileOn) {
|
||||
return getManagedProfileNetworkActivityText();
|
||||
}
|
||||
if (isProfileOwnerOfOrganizationOwnedDevice) {
|
||||
return getMangedDeviceGeneralText(workProfileOrganizationName);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private String getMonitoringText(boolean hasCACerts, boolean hasCACertsInWorkProfile,
|
||||
CharSequence workProfileOrganizationName, boolean isWorkProfileOn) {
|
||||
if (hasCACertsInWorkProfile && isWorkProfileOn) {
|
||||
if (workProfileOrganizationName == null) {
|
||||
return mDpm.getResources().getString(
|
||||
QS_MSG_WORK_PROFILE_MONITORING, mWorkProfileMonitoringStringSupplier);
|
||||
}
|
||||
return mDpm.getResources().getString(
|
||||
QS_MSG_NAMED_WORK_PROFILE_MONITORING,
|
||||
() -> mContext.getString(
|
||||
R.string.quick_settings_disclosure_named_managed_profile_monitoring,
|
||||
workProfileOrganizationName),
|
||||
workProfileOrganizationName);
|
||||
}
|
||||
if (hasCACerts) {
|
||||
return mContext.getString(R.string.quick_settings_disclosure_monitoring);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private String getVpnText(boolean hasWorkProfile, String vpnName, String vpnNameWorkProfile,
|
||||
boolean isWorkProfileOn) {
|
||||
if (vpnName != null && vpnNameWorkProfile != null) {
|
||||
return mContext.getString(R.string.quick_settings_disclosure_vpns);
|
||||
}
|
||||
if (vpnNameWorkProfile != null && isWorkProfileOn) {
|
||||
return mDpm.getResources().getString(
|
||||
QS_MSG_WORK_PROFILE_NAMED_VPN,
|
||||
() -> mContext.getString(
|
||||
R.string.quick_settings_disclosure_managed_profile_named_vpn,
|
||||
vpnNameWorkProfile),
|
||||
vpnNameWorkProfile);
|
||||
}
|
||||
if (vpnName != null) {
|
||||
if (hasWorkProfile) {
|
||||
return mDpm.getResources().getString(
|
||||
QS_MSG_PERSONAL_PROFILE_NAMED_VPN,
|
||||
() -> mContext.getString(
|
||||
R.string.quick_settings_disclosure_personal_profile_named_vpn,
|
||||
vpnName),
|
||||
vpnName);
|
||||
}
|
||||
return mContext.getString(R.string.quick_settings_disclosure_named_vpn,
|
||||
vpnName);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private String getManagedProfileNetworkActivityText() {
|
||||
return mDpm.getResources().getString(
|
||||
QS_MSG_WORK_PROFILE_NETWORK, mWorkProfileNetworkStringSupplier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
if (which == DialogInterface.BUTTON_NEGATIVE) {
|
||||
final Intent intent = new Intent(Settings.ACTION_ENTERPRISE_PRIVACY_SETTINGS);
|
||||
dialog.dismiss();
|
||||
// This dismisses the shade on opening the activity
|
||||
mActivityStarter.postStartActivityDismissingKeyguard(intent, 0);
|
||||
}
|
||||
}
|
||||
|
||||
private void createDialog(Context quickSettingsContext, @Nullable View view) {
|
||||
mShouldUseSettingsButton.set(false);
|
||||
mHandler.post(() -> {
|
||||
String settingsButtonText = getSettingsButton();
|
||||
final View dialogView = createDialogView();
|
||||
mMainHandler.post(() -> {
|
||||
mDialog = new SystemUIDialog(quickSettingsContext, 0);
|
||||
mDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
mDialog.setButton(DialogInterface.BUTTON_POSITIVE, getPositiveButton(), this);
|
||||
mDialog.setButton(DialogInterface.BUTTON_NEGATIVE, mShouldUseSettingsButton.get()
|
||||
? settingsButtonText : getNegativeButton(), this);
|
||||
|
||||
mDialog.setView(dialogView);
|
||||
if (view != null && view.isAggregatedVisible()) {
|
||||
mDialogLaunchAnimator.showFromView(mDialog, view, new DialogCuj(
|
||||
InteractionJankMonitor.CUJ_SHADE_DIALOG_OPEN, INTERACTION_JANK_TAG));
|
||||
} else {
|
||||
mDialog.show();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
Dialog getDialog() {
|
||||
return mDialog;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
View createDialogView() {
|
||||
if (mSecurityController.isParentalControlsEnabled()) {
|
||||
return createParentalControlsDialogView();
|
||||
}
|
||||
return createOrganizationDialogView();
|
||||
}
|
||||
|
||||
private View createOrganizationDialogView() {
|
||||
final boolean isDeviceManaged = mSecurityController.isDeviceManaged();
|
||||
final boolean hasWorkProfile = mSecurityController.hasWorkProfile();
|
||||
final CharSequence deviceOwnerOrganization =
|
||||
mSecurityController.getDeviceOwnerOrganizationName();
|
||||
final boolean hasCACerts = mSecurityController.hasCACertInCurrentUser();
|
||||
final boolean hasCACertsInWorkProfile = mSecurityController.hasCACertInWorkProfile();
|
||||
final boolean isNetworkLoggingEnabled = mSecurityController.isNetworkLoggingEnabled();
|
||||
final String vpnName = mSecurityController.getPrimaryVpnName();
|
||||
final String vpnNameWorkProfile = mSecurityController.getWorkProfileVpnName();
|
||||
|
||||
View dialogView = LayoutInflater.from(mContext)
|
||||
.inflate(R.layout.quick_settings_footer_dialog, null, false);
|
||||
|
||||
// device management section
|
||||
TextView deviceManagementSubtitle =
|
||||
dialogView.findViewById(R.id.device_management_subtitle);
|
||||
deviceManagementSubtitle.setText(getManagementTitle(deviceOwnerOrganization));
|
||||
|
||||
CharSequence managementMessage = getManagementMessage(isDeviceManaged,
|
||||
deviceOwnerOrganization);
|
||||
if (managementMessage == null) {
|
||||
dialogView.findViewById(R.id.device_management_disclosures).setVisibility(View.GONE);
|
||||
} else {
|
||||
dialogView.findViewById(R.id.device_management_disclosures).setVisibility(View.VISIBLE);
|
||||
TextView deviceManagementWarning =
|
||||
(TextView) dialogView.findViewById(R.id.device_management_warning);
|
||||
deviceManagementWarning.setText(managementMessage);
|
||||
mShouldUseSettingsButton.set(true);
|
||||
}
|
||||
|
||||
// ca certificate section
|
||||
CharSequence caCertsMessage = getCaCertsMessage(isDeviceManaged, hasCACerts,
|
||||
hasCACertsInWorkProfile);
|
||||
if (caCertsMessage == null) {
|
||||
dialogView.findViewById(R.id.ca_certs_disclosures).setVisibility(View.GONE);
|
||||
} else {
|
||||
dialogView.findViewById(R.id.ca_certs_disclosures).setVisibility(View.VISIBLE);
|
||||
TextView caCertsWarning = (TextView) dialogView.findViewById(R.id.ca_certs_warning);
|
||||
caCertsWarning.setText(caCertsMessage);
|
||||
// Make "Open trusted credentials"-link clickable
|
||||
caCertsWarning.setMovementMethod(new LinkMovementMethod());
|
||||
|
||||
TextView caCertsSubtitle = (TextView) dialogView.findViewById(R.id.ca_certs_subtitle);
|
||||
String caCertsSubtitleMessage = mDpm.getResources().getString(
|
||||
QS_DIALOG_MONITORING_CA_CERT_SUBTITLE, mMonitoringSubtitleCaCertStringSupplier);
|
||||
caCertsSubtitle.setText(caCertsSubtitleMessage);
|
||||
|
||||
}
|
||||
|
||||
// network logging section
|
||||
CharSequence networkLoggingMessage = getNetworkLoggingMessage(isDeviceManaged,
|
||||
isNetworkLoggingEnabled);
|
||||
if (networkLoggingMessage == null) {
|
||||
dialogView.findViewById(R.id.network_logging_disclosures).setVisibility(View.GONE);
|
||||
} else {
|
||||
dialogView.findViewById(R.id.network_logging_disclosures).setVisibility(View.VISIBLE);
|
||||
TextView networkLoggingWarning =
|
||||
(TextView) dialogView.findViewById(R.id.network_logging_warning);
|
||||
networkLoggingWarning.setText(networkLoggingMessage);
|
||||
|
||||
TextView networkLoggingSubtitle = (TextView) dialogView.findViewById(
|
||||
R.id.network_logging_subtitle);
|
||||
String networkLoggingSubtitleMessage = mDpm.getResources().getString(
|
||||
QS_DIALOG_MONITORING_NETWORK_SUBTITLE,
|
||||
mMonitoringSubtitleNetworkStringSupplier);
|
||||
networkLoggingSubtitle.setText(networkLoggingSubtitleMessage);
|
||||
}
|
||||
|
||||
// vpn section
|
||||
CharSequence vpnMessage = getVpnMessage(isDeviceManaged, hasWorkProfile, vpnName,
|
||||
vpnNameWorkProfile);
|
||||
if (vpnMessage == null) {
|
||||
dialogView.findViewById(R.id.vpn_disclosures).setVisibility(View.GONE);
|
||||
} else {
|
||||
dialogView.findViewById(R.id.vpn_disclosures).setVisibility(View.VISIBLE);
|
||||
TextView vpnWarning = (TextView) dialogView.findViewById(R.id.vpn_warning);
|
||||
vpnWarning.setText(vpnMessage);
|
||||
// Make "Open VPN Settings"-link clickable
|
||||
vpnWarning.setMovementMethod(new LinkMovementMethod());
|
||||
|
||||
TextView vpnSubtitle = (TextView) dialogView.findViewById(R.id.vpn_subtitle);
|
||||
String vpnSubtitleMessage = mDpm.getResources().getString(
|
||||
QS_DIALOG_MONITORING_VPN_SUBTITLE, mMonitoringSubtitleVpnStringSupplier);
|
||||
vpnSubtitle.setText(vpnSubtitleMessage);
|
||||
}
|
||||
|
||||
// Note: if a new section is added, should update configSubtitleVisibility to include
|
||||
// the handling of the subtitle
|
||||
configSubtitleVisibility(managementMessage != null,
|
||||
caCertsMessage != null,
|
||||
networkLoggingMessage != null,
|
||||
vpnMessage != null,
|
||||
dialogView);
|
||||
|
||||
return dialogView;
|
||||
}
|
||||
|
||||
private View createParentalControlsDialogView() {
|
||||
View dialogView = LayoutInflater.from(mContext)
|
||||
.inflate(R.layout.quick_settings_footer_dialog_parental_controls, null, false);
|
||||
|
||||
DeviceAdminInfo info = mSecurityController.getDeviceAdminInfo();
|
||||
Drawable icon = mSecurityController.getIcon(info);
|
||||
if (icon != null) {
|
||||
ImageView imageView = (ImageView) dialogView.findViewById(R.id.parental_controls_icon);
|
||||
imageView.setImageDrawable(icon);
|
||||
}
|
||||
|
||||
TextView parentalControlsTitle =
|
||||
(TextView) dialogView.findViewById(R.id.parental_controls_title);
|
||||
parentalControlsTitle.setText(mSecurityController.getLabel(info));
|
||||
|
||||
return dialogView;
|
||||
}
|
||||
|
||||
protected void configSubtitleVisibility(boolean showDeviceManagement, boolean showCaCerts,
|
||||
boolean showNetworkLogging, boolean showVpn, View dialogView) {
|
||||
// Device Management title should always been shown
|
||||
// When there is a Device Management message, all subtitles should be shown
|
||||
if (showDeviceManagement) {
|
||||
return;
|
||||
}
|
||||
// Hide the subtitle if there is only 1 message shown
|
||||
int mSectionCountExcludingDeviceMgt = 0;
|
||||
if (showCaCerts) { mSectionCountExcludingDeviceMgt++; }
|
||||
if (showNetworkLogging) { mSectionCountExcludingDeviceMgt++; }
|
||||
if (showVpn) { mSectionCountExcludingDeviceMgt++; }
|
||||
|
||||
// No work needed if there is no sections or more than 1 section
|
||||
if (mSectionCountExcludingDeviceMgt != 1) {
|
||||
return;
|
||||
}
|
||||
if (showCaCerts) {
|
||||
dialogView.findViewById(R.id.ca_certs_subtitle).setVisibility(View.GONE);
|
||||
}
|
||||
if (showNetworkLogging) {
|
||||
dialogView.findViewById(R.id.network_logging_subtitle).setVisibility(View.GONE);
|
||||
}
|
||||
if (showVpn) {
|
||||
dialogView.findViewById(R.id.vpn_subtitle).setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
// This should not be called on the main thread to avoid making an IPC.
|
||||
@VisibleForTesting
|
||||
String getSettingsButton() {
|
||||
return mDpm.getResources().getString(
|
||||
QS_DIALOG_VIEW_POLICIES, mViewPoliciesButtonStringSupplier);
|
||||
}
|
||||
|
||||
private String getPositiveButton() {
|
||||
return mContext.getString(R.string.ok);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private String getNegativeButton() {
|
||||
if (mSecurityController.isParentalControlsEnabled()) {
|
||||
return mContext.getString(R.string.monitoring_button_view_controls);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected CharSequence getManagementMessage(boolean isDeviceManaged,
|
||||
CharSequence organizationName) {
|
||||
if (!isDeviceManaged) {
|
||||
return null;
|
||||
}
|
||||
if (organizationName != null) {
|
||||
if (isFinancedDevice()) {
|
||||
return mContext.getString(R.string.monitoring_financed_description_named_management,
|
||||
organizationName, organizationName);
|
||||
} else {
|
||||
return mDpm.getResources().getString(
|
||||
QS_DIALOG_NAMED_MANAGEMENT,
|
||||
() -> mContext.getString(
|
||||
R.string.monitoring_description_named_management,
|
||||
organizationName),
|
||||
organizationName);
|
||||
}
|
||||
}
|
||||
return mDpm.getResources().getString(QS_DIALOG_MANAGEMENT, mManagementDialogStringSupplier);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected CharSequence getCaCertsMessage(boolean isDeviceManaged, boolean hasCACerts,
|
||||
boolean hasCACertsInWorkProfile) {
|
||||
if (!(hasCACerts || hasCACertsInWorkProfile)) return null;
|
||||
if (isDeviceManaged) {
|
||||
return mDpm.getResources().getString(
|
||||
QS_DIALOG_MANAGEMENT_CA_CERT, mManagementDialogCaCertStringSupplier);
|
||||
}
|
||||
if (hasCACertsInWorkProfile) {
|
||||
return mDpm.getResources().getString(
|
||||
QS_DIALOG_WORK_PROFILE_CA_CERT, mWorkProfileDialogCaCertStringSupplier);
|
||||
}
|
||||
return mContext.getString(R.string.monitoring_description_ca_certificate);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected CharSequence getNetworkLoggingMessage(boolean isDeviceManaged,
|
||||
boolean isNetworkLoggingEnabled) {
|
||||
if (!isNetworkLoggingEnabled) return null;
|
||||
if (isDeviceManaged) {
|
||||
return mDpm.getResources().getString(
|
||||
QS_DIALOG_MANAGEMENT_NETWORK, mManagementDialogNetworkStringSupplier);
|
||||
} else {
|
||||
return mDpm.getResources().getString(
|
||||
QS_DIALOG_WORK_PROFILE_NETWORK, mWorkProfileDialogNetworkStringSupplier);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected CharSequence getVpnMessage(boolean isDeviceManaged, boolean hasWorkProfile,
|
||||
String vpnName, String vpnNameWorkProfile) {
|
||||
if (vpnName == null && vpnNameWorkProfile == null) return null;
|
||||
final SpannableStringBuilder message = new SpannableStringBuilder();
|
||||
if (isDeviceManaged) {
|
||||
if (vpnName != null && vpnNameWorkProfile != null) {
|
||||
String namedVpns = mDpm.getResources().getString(
|
||||
QS_DIALOG_MANAGEMENT_TWO_NAMED_VPN,
|
||||
() -> mContext.getString(
|
||||
R.string.monitoring_description_two_named_vpns,
|
||||
vpnName, vpnNameWorkProfile),
|
||||
vpnName, vpnNameWorkProfile);
|
||||
message.append(namedVpns);
|
||||
} else {
|
||||
String name = vpnName != null ? vpnName : vpnNameWorkProfile;
|
||||
String namedVp = mDpm.getResources().getString(
|
||||
QS_DIALOG_MANAGEMENT_NAMED_VPN,
|
||||
() -> mContext.getString(R.string.monitoring_description_named_vpn, name),
|
||||
name);
|
||||
message.append(namedVp);
|
||||
}
|
||||
} else {
|
||||
if (vpnName != null && vpnNameWorkProfile != null) {
|
||||
String namedVpns = mDpm.getResources().getString(
|
||||
QS_DIALOG_MANAGEMENT_TWO_NAMED_VPN,
|
||||
() -> mContext.getString(
|
||||
R.string.monitoring_description_two_named_vpns,
|
||||
vpnName, vpnNameWorkProfile),
|
||||
vpnName, vpnNameWorkProfile);
|
||||
message.append(namedVpns);
|
||||
} else if (vpnNameWorkProfile != null) {
|
||||
String namedVpn = mDpm.getResources().getString(
|
||||
QS_DIALOG_WORK_PROFILE_NAMED_VPN,
|
||||
() -> mContext.getString(
|
||||
R.string.monitoring_description_managed_profile_named_vpn,
|
||||
vpnNameWorkProfile),
|
||||
vpnNameWorkProfile);
|
||||
message.append(namedVpn);
|
||||
} else if (hasWorkProfile) {
|
||||
String namedVpn = mDpm.getResources().getString(
|
||||
QS_DIALOG_PERSONAL_PROFILE_NAMED_VPN,
|
||||
() -> mContext.getString(
|
||||
R.string.monitoring_description_personal_profile_named_vpn,
|
||||
vpnName),
|
||||
vpnName);
|
||||
message.append(namedVpn);
|
||||
} else {
|
||||
message.append(mContext.getString(R.string.monitoring_description_named_vpn,
|
||||
vpnName));
|
||||
}
|
||||
}
|
||||
message.append(mContext.getString(R.string.monitoring_description_vpn_settings_separator));
|
||||
message.append(mContext.getString(R.string.monitoring_description_vpn_settings),
|
||||
new VpnSpan(), 0);
|
||||
return message;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
CharSequence getManagementTitle(CharSequence deviceOwnerOrganization) {
|
||||
if (deviceOwnerOrganization != null && isFinancedDevice()) {
|
||||
return mContext.getString(R.string.monitoring_title_financed_device,
|
||||
deviceOwnerOrganization);
|
||||
} else {
|
||||
return mDpm.getResources().getString(
|
||||
QS_DIALOG_MANAGEMENT_TITLE,
|
||||
mManagementTitleSupplier);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isFinancedDevice() {
|
||||
return mSecurityController.isDeviceManaged()
|
||||
&& mSecurityController.getDeviceOwnerType(
|
||||
mSecurityController.getDeviceOwnerComponentOnAnyUser())
|
||||
== DEVICE_OWNER_TYPE_FINANCED;
|
||||
}
|
||||
|
||||
private final Runnable mUpdatePrimaryIcon = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@@ -914,7 +210,7 @@ public class QSSecurityFooter extends ViewController<View>
|
||||
if (mFooterTextContent != null) {
|
||||
mFooterText.setText(mFooterTextContent);
|
||||
}
|
||||
mView.setVisibility(mIsVisible || DEBUG_FORCE_VISIBLE ? View.VISIBLE : View.GONE);
|
||||
mView.setVisibility(mIsVisible ? View.VISIBLE : View.GONE);
|
||||
if (mVisibilityChangedListener != null) {
|
||||
mVisibilityChangedListener.onVisibilityChanged(mView.getVisibility());
|
||||
}
|
||||
@@ -961,25 +257,4 @@ public class QSSecurityFooter extends ViewController<View>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected class VpnSpan extends ClickableSpan {
|
||||
@Override
|
||||
public void onClick(View widget) {
|
||||
final Intent intent = new Intent(Settings.ACTION_VPN_SETTINGS);
|
||||
mDialog.dismiss();
|
||||
// This dismisses the shade on opening the activity
|
||||
mActivityStarter.postStartActivityDismissingKeyguard(intent, 0);
|
||||
}
|
||||
|
||||
// for testing, to compare two CharSequences containing VpnSpans
|
||||
@Override
|
||||
public boolean equals(Object object) {
|
||||
return object instanceof VpnSpan;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return 314159257; // prime
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,792 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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.
|
||||
*/
|
||||
package com.android.systemui.qs;
|
||||
|
||||
import static android.app.admin.DevicePolicyManager.DEVICE_OWNER_TYPE_FINANCED;
|
||||
import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_DIALOG_MANAGEMENT;
|
||||
import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_DIALOG_MANAGEMENT_CA_CERT;
|
||||
import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_DIALOG_MANAGEMENT_NAMED_VPN;
|
||||
import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_DIALOG_MANAGEMENT_NETWORK;
|
||||
import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_DIALOG_MANAGEMENT_TITLE;
|
||||
import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_DIALOG_MANAGEMENT_TWO_NAMED_VPN;
|
||||
import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_DIALOG_MONITORING_CA_CERT_SUBTITLE;
|
||||
import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_DIALOG_MONITORING_NETWORK_SUBTITLE;
|
||||
import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_DIALOG_MONITORING_VPN_SUBTITLE;
|
||||
import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_DIALOG_NAMED_MANAGEMENT;
|
||||
import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_DIALOG_PERSONAL_PROFILE_NAMED_VPN;
|
||||
import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_DIALOG_VIEW_POLICIES;
|
||||
import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_DIALOG_WORK_PROFILE_CA_CERT;
|
||||
import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_DIALOG_WORK_PROFILE_NAMED_VPN;
|
||||
import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_DIALOG_WORK_PROFILE_NETWORK;
|
||||
import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_MSG_MANAGEMENT;
|
||||
import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_MSG_MANAGEMENT_MONITORING;
|
||||
import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_MSG_MANAGEMENT_MULTIPLE_VPNS;
|
||||
import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_MSG_MANAGEMENT_NAMED_VPN;
|
||||
import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_MSG_NAMED_MANAGEMENT;
|
||||
import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_MSG_NAMED_MANAGEMENT_MONITORING;
|
||||
import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_MSG_NAMED_MANAGEMENT_MULTIPLE_VPNS;
|
||||
import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_MSG_NAMED_MANAGEMENT_NAMED_VPN;
|
||||
import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_MSG_NAMED_WORK_PROFILE_MONITORING;
|
||||
import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_MSG_PERSONAL_PROFILE_NAMED_VPN;
|
||||
import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_MSG_WORK_PROFILE_MONITORING;
|
||||
import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_MSG_WORK_PROFILE_NAMED_VPN;
|
||||
import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_MSG_WORK_PROFILE_NETWORK;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.app.admin.DeviceAdminInfo;
|
||||
import android.app.admin.DevicePolicyManager;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.UserManager;
|
||||
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.Window;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import com.android.internal.jank.InteractionJankMonitor;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.animation.DialogCuj;
|
||||
import com.android.systemui.animation.DialogLaunchAnimator;
|
||||
import com.android.systemui.common.shared.model.Icon;
|
||||
import com.android.systemui.dagger.SysUISingleton;
|
||||
import com.android.systemui.dagger.qualifiers.Application;
|
||||
import com.android.systemui.dagger.qualifiers.Background;
|
||||
import com.android.systemui.dagger.qualifiers.Main;
|
||||
import com.android.systemui.plugins.ActivityStarter;
|
||||
import com.android.systemui.qs.footer.domain.model.SecurityButtonConfig;
|
||||
import com.android.systemui.security.data.model.SecurityModel;
|
||||
import com.android.systemui.settings.UserTracker;
|
||||
import com.android.systemui.statusbar.phone.SystemUIDialog;
|
||||
import com.android.systemui.statusbar.policy.SecurityController;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
/** Helper class for the configuration of the QS security footer button. */
|
||||
@SysUISingleton
|
||||
public class QSSecurityFooterUtils implements DialogInterface.OnClickListener {
|
||||
protected static final String TAG = "QSSecurityFooterUtils";
|
||||
protected static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
|
||||
private static final boolean DEBUG_FORCE_VISIBLE = false;
|
||||
|
||||
private static final String INTERACTION_JANK_TAG = "managed_device_info";
|
||||
|
||||
@Application private Context mContext;
|
||||
private final DevicePolicyManager mDpm;
|
||||
|
||||
private final SecurityController mSecurityController;
|
||||
private final ActivityStarter mActivityStarter;
|
||||
private final Handler mMainHandler;
|
||||
private final UserTracker mUserTracker;
|
||||
private final DialogLaunchAnimator mDialogLaunchAnimator;
|
||||
|
||||
private final AtomicBoolean mShouldUseSettingsButton = new AtomicBoolean(false);
|
||||
|
||||
protected Handler mBgHandler;
|
||||
private AlertDialog mDialog;
|
||||
|
||||
private Supplier<String> mManagementTitleSupplier = () ->
|
||||
mContext == null ? null : mContext.getString(R.string.monitoring_title_device_owned);
|
||||
|
||||
private Supplier<String> mManagementMessageSupplier = () ->
|
||||
mContext == null ? null : mContext.getString(
|
||||
R.string.quick_settings_disclosure_management);
|
||||
|
||||
private Supplier<String> mManagementMonitoringStringSupplier = () ->
|
||||
mContext == null ? null : mContext.getString(
|
||||
R.string.quick_settings_disclosure_management_monitoring);
|
||||
|
||||
private Supplier<String> mManagementMultipleVpnStringSupplier = () ->
|
||||
mContext == null ? null : mContext.getString(
|
||||
R.string.quick_settings_disclosure_management_vpns);
|
||||
|
||||
private Supplier<String> mWorkProfileMonitoringStringSupplier = () ->
|
||||
mContext == null ? null : mContext.getString(
|
||||
R.string.quick_settings_disclosure_managed_profile_monitoring);
|
||||
|
||||
private Supplier<String> mWorkProfileNetworkStringSupplier = () ->
|
||||
mContext == null ? null : mContext.getString(
|
||||
R.string.quick_settings_disclosure_managed_profile_network_activity);
|
||||
|
||||
private Supplier<String> mMonitoringSubtitleCaCertStringSupplier = () ->
|
||||
mContext == null ? null : mContext.getString(
|
||||
R.string.monitoring_subtitle_ca_certificate);
|
||||
|
||||
private Supplier<String> mMonitoringSubtitleNetworkStringSupplier = () ->
|
||||
mContext == null ? null : mContext.getString(
|
||||
R.string.monitoring_subtitle_network_logging);
|
||||
|
||||
private Supplier<String> mMonitoringSubtitleVpnStringSupplier = () ->
|
||||
mContext == null ? null : mContext.getString(R.string.monitoring_subtitle_vpn);
|
||||
|
||||
private Supplier<String> mViewPoliciesButtonStringSupplier = () ->
|
||||
mContext == null ? null : mContext.getString(R.string.monitoring_button_view_policies);
|
||||
|
||||
private Supplier<String> mManagementDialogStringSupplier = () ->
|
||||
mContext == null ? null : mContext.getString(
|
||||
R.string.monitoring_description_management);
|
||||
|
||||
private Supplier<String> mManagementDialogCaCertStringSupplier = () ->
|
||||
mContext == null ? null : mContext.getString(
|
||||
R.string.monitoring_description_management_ca_certificate);
|
||||
|
||||
private Supplier<String> mWorkProfileDialogCaCertStringSupplier = () ->
|
||||
mContext == null ? null : mContext.getString(
|
||||
R.string.monitoring_description_managed_profile_ca_certificate);
|
||||
|
||||
private Supplier<String> mManagementDialogNetworkStringSupplier = () ->
|
||||
mContext == null ? null : mContext.getString(
|
||||
R.string.monitoring_description_management_network_logging);
|
||||
|
||||
private Supplier<String> mWorkProfileDialogNetworkStringSupplier = () ->
|
||||
mContext == null ? null : mContext.getString(
|
||||
R.string.monitoring_description_managed_profile_network_logging);
|
||||
|
||||
@Inject
|
||||
QSSecurityFooterUtils(
|
||||
@Application Context context, UserTracker userTracker, @Main Handler mainHandler,
|
||||
ActivityStarter activityStarter, SecurityController securityController,
|
||||
@Background Looper bgLooper, DialogLaunchAnimator dialogLaunchAnimator) {
|
||||
mContext = context;
|
||||
mDpm = mContext.getSystemService(DevicePolicyManager.class);
|
||||
mUserTracker = userTracker;
|
||||
mMainHandler = mainHandler;
|
||||
mActivityStarter = activityStarter;
|
||||
mSecurityController = securityController;
|
||||
mBgHandler = new Handler(bgLooper);
|
||||
mDialogLaunchAnimator = dialogLaunchAnimator;
|
||||
}
|
||||
|
||||
/** Show the device monitoring dialog. */
|
||||
public void showDeviceMonitoringDialog(Context quickSettingsContext, @Nullable View view) {
|
||||
createDialog(quickSettingsContext, view);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the {@link SecurityButtonConfig} of the security button, or {@code null} if no
|
||||
* security button should be shown.
|
||||
*/
|
||||
@Nullable
|
||||
public SecurityButtonConfig getButtonConfig(SecurityModel securityModel) {
|
||||
final boolean isDeviceManaged = securityModel.isDeviceManaged();
|
||||
final UserInfo currentUser = mUserTracker.getUserInfo();
|
||||
final boolean isDemoDevice = UserManager.isDeviceInDemoMode(mContext) && currentUser != null
|
||||
&& currentUser.isDemo();
|
||||
final boolean hasWorkProfile = securityModel.getHasWorkProfile();
|
||||
final boolean hasCACerts = securityModel.getHasCACertInCurrentUser();
|
||||
final boolean hasCACertsInWorkProfile = securityModel.getHasCACertInWorkProfile();
|
||||
final boolean isNetworkLoggingEnabled = securityModel.isNetworkLoggingEnabled();
|
||||
final String vpnName = securityModel.getPrimaryVpnName();
|
||||
final String vpnNameWorkProfile = securityModel.getWorkProfileVpnName();
|
||||
final CharSequence organizationName = securityModel.getDeviceOwnerOrganizationName();
|
||||
final CharSequence workProfileOrganizationName =
|
||||
securityModel.getWorkProfileOrganizationName();
|
||||
final boolean isProfileOwnerOfOrganizationOwnedDevice =
|
||||
securityModel.isProfileOwnerOfOrganizationOwnedDevice();
|
||||
final boolean isParentalControlsEnabled = securityModel.isParentalControlsEnabled();
|
||||
final boolean isWorkProfileOn = securityModel.isWorkProfileOn();
|
||||
final boolean hasDisclosableWorkProfilePolicy = hasCACertsInWorkProfile
|
||||
|| vpnNameWorkProfile != null || (hasWorkProfile && isNetworkLoggingEnabled);
|
||||
// Update visibility of footer
|
||||
boolean isVisible = (isDeviceManaged && !isDemoDevice)
|
||||
|| hasCACerts
|
||||
|| vpnName != null
|
||||
|| isProfileOwnerOfOrganizationOwnedDevice
|
||||
|| isParentalControlsEnabled
|
||||
|| (hasDisclosableWorkProfilePolicy && isWorkProfileOn);
|
||||
if (!isVisible && !DEBUG_FORCE_VISIBLE) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Update the view to be untappable if the device is an organization-owned device with a
|
||||
// managed profile and there is either:
|
||||
// a) no policy set which requires a privacy disclosure.
|
||||
// b) a specific work policy set but the work profile is turned off.
|
||||
boolean isClickable = !(isProfileOwnerOfOrganizationOwnedDevice
|
||||
&& (!hasDisclosableWorkProfilePolicy || !isWorkProfileOn));
|
||||
|
||||
String text = getFooterText(isDeviceManaged, hasWorkProfile,
|
||||
hasCACerts, hasCACertsInWorkProfile, isNetworkLoggingEnabled, vpnName,
|
||||
vpnNameWorkProfile, organizationName, workProfileOrganizationName,
|
||||
isProfileOwnerOfOrganizationOwnedDevice, isParentalControlsEnabled,
|
||||
isWorkProfileOn).toString();
|
||||
|
||||
Icon icon;
|
||||
if (isParentalControlsEnabled) {
|
||||
icon = new Icon.Loaded(securityModel.getDeviceAdminIcon());
|
||||
} else if (vpnName != null || vpnNameWorkProfile != null) {
|
||||
if (securityModel.isVpnBranded()) {
|
||||
icon = new Icon.Resource(R.drawable.stat_sys_branded_vpn);
|
||||
} else {
|
||||
icon = new Icon.Resource(R.drawable.stat_sys_vpn_ic);
|
||||
}
|
||||
} else {
|
||||
icon = new Icon.Resource(R.drawable.ic_info_outline);
|
||||
}
|
||||
|
||||
return new SecurityButtonConfig(icon, text, isClickable);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected CharSequence getFooterText(boolean isDeviceManaged, boolean hasWorkProfile,
|
||||
boolean hasCACerts, boolean hasCACertsInWorkProfile, boolean isNetworkLoggingEnabled,
|
||||
String vpnName, String vpnNameWorkProfile, CharSequence organizationName,
|
||||
CharSequence workProfileOrganizationName,
|
||||
boolean isProfileOwnerOfOrganizationOwnedDevice, boolean isParentalControlsEnabled,
|
||||
boolean isWorkProfileOn) {
|
||||
if (isParentalControlsEnabled) {
|
||||
return mContext.getString(R.string.quick_settings_disclosure_parental_controls);
|
||||
}
|
||||
if (isDeviceManaged || DEBUG_FORCE_VISIBLE) {
|
||||
return getManagedDeviceFooterText(hasCACerts, hasCACertsInWorkProfile,
|
||||
isNetworkLoggingEnabled, vpnName, vpnNameWorkProfile, organizationName);
|
||||
}
|
||||
return getManagedAndPersonalProfileFooterText(hasWorkProfile, hasCACerts,
|
||||
hasCACertsInWorkProfile, isNetworkLoggingEnabled, vpnName, vpnNameWorkProfile,
|
||||
workProfileOrganizationName, isProfileOwnerOfOrganizationOwnedDevice,
|
||||
isWorkProfileOn);
|
||||
}
|
||||
|
||||
private String getManagedDeviceFooterText(
|
||||
boolean hasCACerts, boolean hasCACertsInWorkProfile, boolean isNetworkLoggingEnabled,
|
||||
String vpnName, String vpnNameWorkProfile, CharSequence organizationName) {
|
||||
if (hasCACerts || hasCACertsInWorkProfile || isNetworkLoggingEnabled) {
|
||||
return getManagedDeviceMonitoringText(organizationName);
|
||||
}
|
||||
if (vpnName != null || vpnNameWorkProfile != null) {
|
||||
return getManagedDeviceVpnText(vpnName, vpnNameWorkProfile, organizationName);
|
||||
}
|
||||
return getMangedDeviceGeneralText(organizationName);
|
||||
}
|
||||
|
||||
private String getManagedDeviceMonitoringText(CharSequence organizationName) {
|
||||
if (organizationName == null) {
|
||||
return mDpm.getResources().getString(
|
||||
QS_MSG_MANAGEMENT_MONITORING, mManagementMonitoringStringSupplier);
|
||||
}
|
||||
return mDpm.getResources().getString(
|
||||
QS_MSG_NAMED_MANAGEMENT_MONITORING,
|
||||
() -> mContext.getString(
|
||||
R.string.quick_settings_disclosure_named_management_monitoring,
|
||||
organizationName),
|
||||
organizationName);
|
||||
}
|
||||
|
||||
private String getManagedDeviceVpnText(
|
||||
String vpnName, String vpnNameWorkProfile, CharSequence organizationName) {
|
||||
if (vpnName != null && vpnNameWorkProfile != null) {
|
||||
if (organizationName == null) {
|
||||
return mDpm.getResources().getString(
|
||||
QS_MSG_MANAGEMENT_MULTIPLE_VPNS, mManagementMultipleVpnStringSupplier);
|
||||
}
|
||||
return mDpm.getResources().getString(
|
||||
QS_MSG_NAMED_MANAGEMENT_MULTIPLE_VPNS,
|
||||
() -> mContext.getString(
|
||||
R.string.quick_settings_disclosure_named_management_vpns,
|
||||
organizationName),
|
||||
organizationName);
|
||||
}
|
||||
String name = vpnName != null ? vpnName : vpnNameWorkProfile;
|
||||
if (organizationName == null) {
|
||||
return mDpm.getResources().getString(
|
||||
QS_MSG_MANAGEMENT_NAMED_VPN,
|
||||
() -> mContext.getString(
|
||||
R.string.quick_settings_disclosure_management_named_vpn,
|
||||
name),
|
||||
name);
|
||||
}
|
||||
return mDpm.getResources().getString(
|
||||
QS_MSG_NAMED_MANAGEMENT_NAMED_VPN,
|
||||
() -> mContext.getString(
|
||||
R.string.quick_settings_disclosure_named_management_named_vpn,
|
||||
organizationName,
|
||||
name),
|
||||
organizationName,
|
||||
name);
|
||||
}
|
||||
|
||||
private String getMangedDeviceGeneralText(CharSequence organizationName) {
|
||||
if (organizationName == null) {
|
||||
return mDpm.getResources().getString(QS_MSG_MANAGEMENT, mManagementMessageSupplier);
|
||||
}
|
||||
if (isFinancedDevice()) {
|
||||
return mContext.getString(
|
||||
R.string.quick_settings_financed_disclosure_named_management,
|
||||
organizationName);
|
||||
} else {
|
||||
return mDpm.getResources().getString(
|
||||
QS_MSG_NAMED_MANAGEMENT,
|
||||
() -> mContext.getString(
|
||||
R.string.quick_settings_disclosure_named_management,
|
||||
organizationName),
|
||||
organizationName);
|
||||
}
|
||||
}
|
||||
|
||||
private String getManagedAndPersonalProfileFooterText(boolean hasWorkProfile,
|
||||
boolean hasCACerts, boolean hasCACertsInWorkProfile, boolean isNetworkLoggingEnabled,
|
||||
String vpnName, String vpnNameWorkProfile, CharSequence workProfileOrganizationName,
|
||||
boolean isProfileOwnerOfOrganizationOwnedDevice, boolean isWorkProfileOn) {
|
||||
if (hasCACerts || (hasCACertsInWorkProfile && isWorkProfileOn)) {
|
||||
return getMonitoringText(
|
||||
hasCACerts, hasCACertsInWorkProfile, workProfileOrganizationName,
|
||||
isWorkProfileOn);
|
||||
}
|
||||
if (vpnName != null || (vpnNameWorkProfile != null && isWorkProfileOn)) {
|
||||
return getVpnText(hasWorkProfile, vpnName, vpnNameWorkProfile, isWorkProfileOn);
|
||||
}
|
||||
if (hasWorkProfile && isNetworkLoggingEnabled && isWorkProfileOn) {
|
||||
return getManagedProfileNetworkActivityText();
|
||||
}
|
||||
if (isProfileOwnerOfOrganizationOwnedDevice) {
|
||||
return getMangedDeviceGeneralText(workProfileOrganizationName);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private String getMonitoringText(boolean hasCACerts, boolean hasCACertsInWorkProfile,
|
||||
CharSequence workProfileOrganizationName, boolean isWorkProfileOn) {
|
||||
if (hasCACertsInWorkProfile && isWorkProfileOn) {
|
||||
if (workProfileOrganizationName == null) {
|
||||
return mDpm.getResources().getString(
|
||||
QS_MSG_WORK_PROFILE_MONITORING, mWorkProfileMonitoringStringSupplier);
|
||||
}
|
||||
return mDpm.getResources().getString(
|
||||
QS_MSG_NAMED_WORK_PROFILE_MONITORING,
|
||||
() -> mContext.getString(
|
||||
R.string.quick_settings_disclosure_named_managed_profile_monitoring,
|
||||
workProfileOrganizationName),
|
||||
workProfileOrganizationName);
|
||||
}
|
||||
if (hasCACerts) {
|
||||
return mContext.getString(R.string.quick_settings_disclosure_monitoring);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private String getVpnText(boolean hasWorkProfile, String vpnName, String vpnNameWorkProfile,
|
||||
boolean isWorkProfileOn) {
|
||||
if (vpnName != null && vpnNameWorkProfile != null) {
|
||||
return mContext.getString(R.string.quick_settings_disclosure_vpns);
|
||||
}
|
||||
if (vpnNameWorkProfile != null && isWorkProfileOn) {
|
||||
return mDpm.getResources().getString(
|
||||
QS_MSG_WORK_PROFILE_NAMED_VPN,
|
||||
() -> mContext.getString(
|
||||
R.string.quick_settings_disclosure_managed_profile_named_vpn,
|
||||
vpnNameWorkProfile),
|
||||
vpnNameWorkProfile);
|
||||
}
|
||||
if (vpnName != null) {
|
||||
if (hasWorkProfile) {
|
||||
return mDpm.getResources().getString(
|
||||
QS_MSG_PERSONAL_PROFILE_NAMED_VPN,
|
||||
() -> mContext.getString(
|
||||
R.string.quick_settings_disclosure_personal_profile_named_vpn,
|
||||
vpnName),
|
||||
vpnName);
|
||||
}
|
||||
return mContext.getString(R.string.quick_settings_disclosure_named_vpn,
|
||||
vpnName);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private String getManagedProfileNetworkActivityText() {
|
||||
return mDpm.getResources().getString(
|
||||
QS_MSG_WORK_PROFILE_NETWORK, mWorkProfileNetworkStringSupplier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
if (which == DialogInterface.BUTTON_NEGATIVE) {
|
||||
final Intent intent = new Intent(Settings.ACTION_ENTERPRISE_PRIVACY_SETTINGS);
|
||||
dialog.dismiss();
|
||||
// This dismisses the shade on opening the activity
|
||||
mActivityStarter.postStartActivityDismissingKeyguard(intent, 0);
|
||||
}
|
||||
}
|
||||
|
||||
private void createDialog(Context quickSettingsContext, @Nullable View view) {
|
||||
mShouldUseSettingsButton.set(false);
|
||||
mBgHandler.post(() -> {
|
||||
String settingsButtonText = getSettingsButton();
|
||||
final View dialogView = createDialogView();
|
||||
mMainHandler.post(() -> {
|
||||
mDialog = new SystemUIDialog(quickSettingsContext, 0);
|
||||
mDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
mDialog.setButton(DialogInterface.BUTTON_POSITIVE, getPositiveButton(), this);
|
||||
mDialog.setButton(DialogInterface.BUTTON_NEGATIVE, mShouldUseSettingsButton.get()
|
||||
? settingsButtonText : getNegativeButton(), this);
|
||||
|
||||
mDialog.setView(dialogView);
|
||||
if (view != null && view.isAggregatedVisible()) {
|
||||
mDialogLaunchAnimator.showFromView(mDialog, view, new DialogCuj(
|
||||
InteractionJankMonitor.CUJ_SHADE_DIALOG_OPEN, INTERACTION_JANK_TAG));
|
||||
} else {
|
||||
mDialog.show();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
Dialog getDialog() {
|
||||
return mDialog;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
View createDialogView() {
|
||||
if (mSecurityController.isParentalControlsEnabled()) {
|
||||
return createParentalControlsDialogView();
|
||||
}
|
||||
return createOrganizationDialogView();
|
||||
}
|
||||
|
||||
private View createOrganizationDialogView() {
|
||||
final boolean isDeviceManaged = mSecurityController.isDeviceManaged();
|
||||
final boolean hasWorkProfile = mSecurityController.hasWorkProfile();
|
||||
final CharSequence deviceOwnerOrganization =
|
||||
mSecurityController.getDeviceOwnerOrganizationName();
|
||||
final boolean hasCACerts = mSecurityController.hasCACertInCurrentUser();
|
||||
final boolean hasCACertsInWorkProfile = mSecurityController.hasCACertInWorkProfile();
|
||||
final boolean isNetworkLoggingEnabled = mSecurityController.isNetworkLoggingEnabled();
|
||||
final String vpnName = mSecurityController.getPrimaryVpnName();
|
||||
final String vpnNameWorkProfile = mSecurityController.getWorkProfileVpnName();
|
||||
|
||||
View dialogView = LayoutInflater.from(mContext)
|
||||
.inflate(R.layout.quick_settings_footer_dialog, null, false);
|
||||
|
||||
// device management section
|
||||
TextView deviceManagementSubtitle =
|
||||
dialogView.findViewById(R.id.device_management_subtitle);
|
||||
deviceManagementSubtitle.setText(getManagementTitle(deviceOwnerOrganization));
|
||||
|
||||
CharSequence managementMessage = getManagementMessage(isDeviceManaged,
|
||||
deviceOwnerOrganization);
|
||||
if (managementMessage == null) {
|
||||
dialogView.findViewById(R.id.device_management_disclosures).setVisibility(View.GONE);
|
||||
} else {
|
||||
dialogView.findViewById(R.id.device_management_disclosures).setVisibility(View.VISIBLE);
|
||||
TextView deviceManagementWarning =
|
||||
(TextView) dialogView.findViewById(R.id.device_management_warning);
|
||||
deviceManagementWarning.setText(managementMessage);
|
||||
mShouldUseSettingsButton.set(true);
|
||||
}
|
||||
|
||||
// ca certificate section
|
||||
CharSequence caCertsMessage = getCaCertsMessage(isDeviceManaged, hasCACerts,
|
||||
hasCACertsInWorkProfile);
|
||||
if (caCertsMessage == null) {
|
||||
dialogView.findViewById(R.id.ca_certs_disclosures).setVisibility(View.GONE);
|
||||
} else {
|
||||
dialogView.findViewById(R.id.ca_certs_disclosures).setVisibility(View.VISIBLE);
|
||||
TextView caCertsWarning = (TextView) dialogView.findViewById(R.id.ca_certs_warning);
|
||||
caCertsWarning.setText(caCertsMessage);
|
||||
// Make "Open trusted credentials"-link clickable
|
||||
caCertsWarning.setMovementMethod(new LinkMovementMethod());
|
||||
|
||||
TextView caCertsSubtitle = (TextView) dialogView.findViewById(R.id.ca_certs_subtitle);
|
||||
String caCertsSubtitleMessage = mDpm.getResources().getString(
|
||||
QS_DIALOG_MONITORING_CA_CERT_SUBTITLE, mMonitoringSubtitleCaCertStringSupplier);
|
||||
caCertsSubtitle.setText(caCertsSubtitleMessage);
|
||||
|
||||
}
|
||||
|
||||
// network logging section
|
||||
CharSequence networkLoggingMessage = getNetworkLoggingMessage(isDeviceManaged,
|
||||
isNetworkLoggingEnabled);
|
||||
if (networkLoggingMessage == null) {
|
||||
dialogView.findViewById(R.id.network_logging_disclosures).setVisibility(View.GONE);
|
||||
} else {
|
||||
dialogView.findViewById(R.id.network_logging_disclosures).setVisibility(View.VISIBLE);
|
||||
TextView networkLoggingWarning =
|
||||
(TextView) dialogView.findViewById(R.id.network_logging_warning);
|
||||
networkLoggingWarning.setText(networkLoggingMessage);
|
||||
|
||||
TextView networkLoggingSubtitle = (TextView) dialogView.findViewById(
|
||||
R.id.network_logging_subtitle);
|
||||
String networkLoggingSubtitleMessage = mDpm.getResources().getString(
|
||||
QS_DIALOG_MONITORING_NETWORK_SUBTITLE,
|
||||
mMonitoringSubtitleNetworkStringSupplier);
|
||||
networkLoggingSubtitle.setText(networkLoggingSubtitleMessage);
|
||||
}
|
||||
|
||||
// vpn section
|
||||
CharSequence vpnMessage = getVpnMessage(isDeviceManaged, hasWorkProfile, vpnName,
|
||||
vpnNameWorkProfile);
|
||||
if (vpnMessage == null) {
|
||||
dialogView.findViewById(R.id.vpn_disclosures).setVisibility(View.GONE);
|
||||
} else {
|
||||
dialogView.findViewById(R.id.vpn_disclosures).setVisibility(View.VISIBLE);
|
||||
TextView vpnWarning = (TextView) dialogView.findViewById(R.id.vpn_warning);
|
||||
vpnWarning.setText(vpnMessage);
|
||||
// Make "Open VPN Settings"-link clickable
|
||||
vpnWarning.setMovementMethod(new LinkMovementMethod());
|
||||
|
||||
TextView vpnSubtitle = (TextView) dialogView.findViewById(R.id.vpn_subtitle);
|
||||
String vpnSubtitleMessage = mDpm.getResources().getString(
|
||||
QS_DIALOG_MONITORING_VPN_SUBTITLE, mMonitoringSubtitleVpnStringSupplier);
|
||||
vpnSubtitle.setText(vpnSubtitleMessage);
|
||||
}
|
||||
|
||||
// Note: if a new section is added, should update configSubtitleVisibility to include
|
||||
// the handling of the subtitle
|
||||
configSubtitleVisibility(managementMessage != null,
|
||||
caCertsMessage != null,
|
||||
networkLoggingMessage != null,
|
||||
vpnMessage != null,
|
||||
dialogView);
|
||||
|
||||
return dialogView;
|
||||
}
|
||||
|
||||
private View createParentalControlsDialogView() {
|
||||
View dialogView = LayoutInflater.from(mContext)
|
||||
.inflate(R.layout.quick_settings_footer_dialog_parental_controls, null, false);
|
||||
|
||||
DeviceAdminInfo info = mSecurityController.getDeviceAdminInfo();
|
||||
Drawable icon = mSecurityController.getIcon(info);
|
||||
if (icon != null) {
|
||||
ImageView imageView = (ImageView) dialogView.findViewById(R.id.parental_controls_icon);
|
||||
imageView.setImageDrawable(icon);
|
||||
}
|
||||
|
||||
TextView parentalControlsTitle =
|
||||
(TextView) dialogView.findViewById(R.id.parental_controls_title);
|
||||
parentalControlsTitle.setText(mSecurityController.getLabel(info));
|
||||
|
||||
return dialogView;
|
||||
}
|
||||
|
||||
protected void configSubtitleVisibility(boolean showDeviceManagement, boolean showCaCerts,
|
||||
boolean showNetworkLogging, boolean showVpn, View dialogView) {
|
||||
// Device Management title should always been shown
|
||||
// When there is a Device Management message, all subtitles should be shown
|
||||
if (showDeviceManagement) {
|
||||
return;
|
||||
}
|
||||
// Hide the subtitle if there is only 1 message shown
|
||||
int mSectionCountExcludingDeviceMgt = 0;
|
||||
if (showCaCerts) {
|
||||
mSectionCountExcludingDeviceMgt++;
|
||||
}
|
||||
if (showNetworkLogging) {
|
||||
mSectionCountExcludingDeviceMgt++;
|
||||
}
|
||||
if (showVpn) {
|
||||
mSectionCountExcludingDeviceMgt++;
|
||||
}
|
||||
|
||||
// No work needed if there is no sections or more than 1 section
|
||||
if (mSectionCountExcludingDeviceMgt != 1) {
|
||||
return;
|
||||
}
|
||||
if (showCaCerts) {
|
||||
dialogView.findViewById(R.id.ca_certs_subtitle).setVisibility(View.GONE);
|
||||
}
|
||||
if (showNetworkLogging) {
|
||||
dialogView.findViewById(R.id.network_logging_subtitle).setVisibility(View.GONE);
|
||||
}
|
||||
if (showVpn) {
|
||||
dialogView.findViewById(R.id.vpn_subtitle).setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
// This should not be called on the main thread to avoid making an IPC.
|
||||
@VisibleForTesting
|
||||
String getSettingsButton() {
|
||||
return mDpm.getResources().getString(
|
||||
QS_DIALOG_VIEW_POLICIES, mViewPoliciesButtonStringSupplier);
|
||||
}
|
||||
|
||||
private String getPositiveButton() {
|
||||
return mContext.getString(R.string.ok);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private String getNegativeButton() {
|
||||
if (mSecurityController.isParentalControlsEnabled()) {
|
||||
return mContext.getString(R.string.monitoring_button_view_controls);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected CharSequence getManagementMessage(boolean isDeviceManaged,
|
||||
CharSequence organizationName) {
|
||||
if (!isDeviceManaged) {
|
||||
return null;
|
||||
}
|
||||
if (organizationName != null) {
|
||||
if (isFinancedDevice()) {
|
||||
return mContext.getString(R.string.monitoring_financed_description_named_management,
|
||||
organizationName, organizationName);
|
||||
} else {
|
||||
return mDpm.getResources().getString(
|
||||
QS_DIALOG_NAMED_MANAGEMENT,
|
||||
() -> mContext.getString(
|
||||
R.string.monitoring_description_named_management,
|
||||
organizationName),
|
||||
organizationName);
|
||||
}
|
||||
}
|
||||
return mDpm.getResources().getString(QS_DIALOG_MANAGEMENT, mManagementDialogStringSupplier);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected CharSequence getCaCertsMessage(boolean isDeviceManaged, boolean hasCACerts,
|
||||
boolean hasCACertsInWorkProfile) {
|
||||
if (!(hasCACerts || hasCACertsInWorkProfile)) return null;
|
||||
if (isDeviceManaged) {
|
||||
return mDpm.getResources().getString(
|
||||
QS_DIALOG_MANAGEMENT_CA_CERT, mManagementDialogCaCertStringSupplier);
|
||||
}
|
||||
if (hasCACertsInWorkProfile) {
|
||||
return mDpm.getResources().getString(
|
||||
QS_DIALOG_WORK_PROFILE_CA_CERT, mWorkProfileDialogCaCertStringSupplier);
|
||||
}
|
||||
return mContext.getString(R.string.monitoring_description_ca_certificate);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected CharSequence getNetworkLoggingMessage(boolean isDeviceManaged,
|
||||
boolean isNetworkLoggingEnabled) {
|
||||
if (!isNetworkLoggingEnabled) return null;
|
||||
if (isDeviceManaged) {
|
||||
return mDpm.getResources().getString(
|
||||
QS_DIALOG_MANAGEMENT_NETWORK, mManagementDialogNetworkStringSupplier);
|
||||
} else {
|
||||
return mDpm.getResources().getString(
|
||||
QS_DIALOG_WORK_PROFILE_NETWORK, mWorkProfileDialogNetworkStringSupplier);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected CharSequence getVpnMessage(boolean isDeviceManaged, boolean hasWorkProfile,
|
||||
String vpnName, String vpnNameWorkProfile) {
|
||||
if (vpnName == null && vpnNameWorkProfile == null) return null;
|
||||
final SpannableStringBuilder message = new SpannableStringBuilder();
|
||||
if (isDeviceManaged) {
|
||||
if (vpnName != null && vpnNameWorkProfile != null) {
|
||||
String namedVpns = mDpm.getResources().getString(
|
||||
QS_DIALOG_MANAGEMENT_TWO_NAMED_VPN,
|
||||
() -> mContext.getString(
|
||||
R.string.monitoring_description_two_named_vpns,
|
||||
vpnName, vpnNameWorkProfile),
|
||||
vpnName, vpnNameWorkProfile);
|
||||
message.append(namedVpns);
|
||||
} else {
|
||||
String name = vpnName != null ? vpnName : vpnNameWorkProfile;
|
||||
String namedVp = mDpm.getResources().getString(
|
||||
QS_DIALOG_MANAGEMENT_NAMED_VPN,
|
||||
() -> mContext.getString(R.string.monitoring_description_named_vpn, name),
|
||||
name);
|
||||
message.append(namedVp);
|
||||
}
|
||||
} else {
|
||||
if (vpnName != null && vpnNameWorkProfile != null) {
|
||||
String namedVpns = mDpm.getResources().getString(
|
||||
QS_DIALOG_MANAGEMENT_TWO_NAMED_VPN,
|
||||
() -> mContext.getString(
|
||||
R.string.monitoring_description_two_named_vpns,
|
||||
vpnName, vpnNameWorkProfile),
|
||||
vpnName, vpnNameWorkProfile);
|
||||
message.append(namedVpns);
|
||||
} else if (vpnNameWorkProfile != null) {
|
||||
String namedVpn = mDpm.getResources().getString(
|
||||
QS_DIALOG_WORK_PROFILE_NAMED_VPN,
|
||||
() -> mContext.getString(
|
||||
R.string.monitoring_description_managed_profile_named_vpn,
|
||||
vpnNameWorkProfile),
|
||||
vpnNameWorkProfile);
|
||||
message.append(namedVpn);
|
||||
} else if (hasWorkProfile) {
|
||||
String namedVpn = mDpm.getResources().getString(
|
||||
QS_DIALOG_PERSONAL_PROFILE_NAMED_VPN,
|
||||
() -> mContext.getString(
|
||||
R.string.monitoring_description_personal_profile_named_vpn,
|
||||
vpnName),
|
||||
vpnName);
|
||||
message.append(namedVpn);
|
||||
} else {
|
||||
message.append(mContext.getString(R.string.monitoring_description_named_vpn,
|
||||
vpnName));
|
||||
}
|
||||
}
|
||||
message.append(mContext.getString(R.string.monitoring_description_vpn_settings_separator));
|
||||
message.append(mContext.getString(R.string.monitoring_description_vpn_settings),
|
||||
new VpnSpan(), 0);
|
||||
return message;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
CharSequence getManagementTitle(CharSequence deviceOwnerOrganization) {
|
||||
if (deviceOwnerOrganization != null && isFinancedDevice()) {
|
||||
return mContext.getString(R.string.monitoring_title_financed_device,
|
||||
deviceOwnerOrganization);
|
||||
} else {
|
||||
return mDpm.getResources().getString(
|
||||
QS_DIALOG_MANAGEMENT_TITLE,
|
||||
mManagementTitleSupplier);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isFinancedDevice() {
|
||||
return mSecurityController.isDeviceManaged()
|
||||
&& mSecurityController.getDeviceOwnerType(
|
||||
mSecurityController.getDeviceOwnerComponentOnAnyUser())
|
||||
== DEVICE_OWNER_TYPE_FINANCED;
|
||||
}
|
||||
|
||||
protected class VpnSpan extends ClickableSpan {
|
||||
@Override
|
||||
public void onClick(View widget) {
|
||||
final Intent intent = new Intent(Settings.ACTION_VPN_SETTINGS);
|
||||
mDialog.dismiss();
|
||||
// This dismisses the shade on opening the activity
|
||||
mActivityStarter.postStartActivityDismissingKeyguard(intent, 0);
|
||||
}
|
||||
|
||||
// for testing, to compare two CharSequences containing VpnSpans
|
||||
@Override
|
||||
public boolean equals(Object object) {
|
||||
return object instanceof VpnSpan;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return 314159257; // prime
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -100,6 +100,7 @@ public class QSSecurityFooterTest extends SysuiTestCase {
|
||||
private TextView mFooterText;
|
||||
private TestableImageView mPrimaryFooterIcon;
|
||||
private QSSecurityFooter mFooter;
|
||||
private QSSecurityFooterUtils mFooterUtils;
|
||||
@Mock
|
||||
private SecurityController mSecurityController;
|
||||
@Mock
|
||||
@@ -118,13 +119,15 @@ public class QSSecurityFooterTest extends SysuiTestCase {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mTestableLooper = TestableLooper.get(this);
|
||||
Looper looper = mTestableLooper.getLooper();
|
||||
Handler mainHandler = new Handler(looper);
|
||||
when(mUserTracker.getUserInfo()).thenReturn(mock(UserInfo.class));
|
||||
mRootView = (ViewGroup) new LayoutInflaterBuilder(mContext)
|
||||
.replace("ImageView", TestableImageView.class)
|
||||
.build().inflate(R.layout.quick_settings_security_footer, null, false);
|
||||
mFooter = new QSSecurityFooter(mRootView, mUserTracker, new Handler(looper),
|
||||
mActivityStarter, mSecurityController, mDialogLaunchAnimator, looper,
|
||||
mBroadcastDispatcher);
|
||||
mFooterUtils = new QSSecurityFooterUtils(getContext(), mUserTracker, mainHandler,
|
||||
mActivityStarter, mSecurityController, looper, mDialogLaunchAnimator);
|
||||
mFooter = new QSSecurityFooter(mRootView, mainHandler, mSecurityController, looper,
|
||||
mBroadcastDispatcher, mFooterUtils);
|
||||
mFooterText = mRootView.findViewById(R.id.footer_text);
|
||||
mPrimaryFooterIcon = mRootView.findViewById(R.id.primary_footer_icon);
|
||||
|
||||
@@ -520,7 +523,7 @@ public class QSSecurityFooterTest extends SysuiTestCase {
|
||||
when(mSecurityController.isDeviceManaged()).thenReturn(true);
|
||||
|
||||
assertEquals(mContext.getString(R.string.monitoring_title_device_owned),
|
||||
mFooter.getManagementTitle(MANAGING_ORGANIZATION));
|
||||
mFooterUtils.getManagementTitle(MANAGING_ORGANIZATION));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -531,12 +534,12 @@ public class QSSecurityFooterTest extends SysuiTestCase {
|
||||
|
||||
assertEquals(mContext.getString(R.string.monitoring_title_financed_device,
|
||||
MANAGING_ORGANIZATION),
|
||||
mFooter.getManagementTitle(MANAGING_ORGANIZATION));
|
||||
mFooterUtils.getManagementTitle(MANAGING_ORGANIZATION));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetManagementMessage_noManagement() {
|
||||
assertEquals(null, mFooter.getManagementMessage(
|
||||
assertEquals(null, mFooterUtils.getManagementMessage(
|
||||
/* isDeviceManaged= */ false, MANAGING_ORGANIZATION));
|
||||
}
|
||||
|
||||
@@ -544,10 +547,10 @@ public class QSSecurityFooterTest extends SysuiTestCase {
|
||||
public void testGetManagementMessage_deviceOwner() {
|
||||
assertEquals(mContext.getString(R.string.monitoring_description_named_management,
|
||||
MANAGING_ORGANIZATION),
|
||||
mFooter.getManagementMessage(
|
||||
mFooterUtils.getManagementMessage(
|
||||
/* isDeviceManaged= */ true, MANAGING_ORGANIZATION));
|
||||
assertEquals(mContext.getString(R.string.monitoring_description_management),
|
||||
mFooter.getManagementMessage(
|
||||
mFooterUtils.getManagementMessage(
|
||||
/* isDeviceManaged= */ true,
|
||||
/* organizationName= */ null));
|
||||
}
|
||||
@@ -560,68 +563,68 @@ public class QSSecurityFooterTest extends SysuiTestCase {
|
||||
|
||||
assertEquals(mContext.getString(R.string.monitoring_financed_description_named_management,
|
||||
MANAGING_ORGANIZATION, MANAGING_ORGANIZATION),
|
||||
mFooter.getManagementMessage(
|
||||
mFooterUtils.getManagementMessage(
|
||||
/* isDeviceManaged= */ true, MANAGING_ORGANIZATION));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetCaCertsMessage() {
|
||||
assertEquals(null, mFooter.getCaCertsMessage(true, false, false));
|
||||
assertEquals(null, mFooter.getCaCertsMessage(false, false, false));
|
||||
assertEquals(null, mFooterUtils.getCaCertsMessage(true, false, false));
|
||||
assertEquals(null, mFooterUtils.getCaCertsMessage(false, false, false));
|
||||
assertEquals(mContext.getString(R.string.monitoring_description_management_ca_certificate),
|
||||
mFooter.getCaCertsMessage(true, true, true));
|
||||
mFooterUtils.getCaCertsMessage(true, true, true));
|
||||
assertEquals(mContext.getString(R.string.monitoring_description_management_ca_certificate),
|
||||
mFooter.getCaCertsMessage(true, false, true));
|
||||
mFooterUtils.getCaCertsMessage(true, false, true));
|
||||
assertEquals(mContext.getString(
|
||||
R.string.monitoring_description_managed_profile_ca_certificate),
|
||||
mFooter.getCaCertsMessage(false, false, true));
|
||||
mFooterUtils.getCaCertsMessage(false, false, true));
|
||||
assertEquals(mContext.getString(
|
||||
R.string.monitoring_description_ca_certificate),
|
||||
mFooter.getCaCertsMessage(false, true, false));
|
||||
mFooterUtils.getCaCertsMessage(false, true, false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetNetworkLoggingMessage() {
|
||||
// Test network logging message on a device with a device owner.
|
||||
// Network traffic may be monitored on the device.
|
||||
assertEquals(null, mFooter.getNetworkLoggingMessage(true, false));
|
||||
assertEquals(null, mFooterUtils.getNetworkLoggingMessage(true, false));
|
||||
assertEquals(mContext.getString(R.string.monitoring_description_management_network_logging),
|
||||
mFooter.getNetworkLoggingMessage(true, true));
|
||||
mFooterUtils.getNetworkLoggingMessage(true, true));
|
||||
|
||||
// Test network logging message on a device with a managed profile owner
|
||||
// Network traffic may be monitored on the work profile.
|
||||
assertEquals(null, mFooter.getNetworkLoggingMessage(false, false));
|
||||
assertEquals(null, mFooterUtils.getNetworkLoggingMessage(false, false));
|
||||
assertEquals(
|
||||
mContext.getString(R.string.monitoring_description_managed_profile_network_logging),
|
||||
mFooter.getNetworkLoggingMessage(false, true));
|
||||
mFooterUtils.getNetworkLoggingMessage(false, true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetVpnMessage() {
|
||||
assertEquals(null, mFooter.getVpnMessage(true, true, null, null));
|
||||
assertEquals(null, mFooterUtils.getVpnMessage(true, true, null, null));
|
||||
assertEquals(addLink(mContext.getString(R.string.monitoring_description_two_named_vpns,
|
||||
VPN_PACKAGE, VPN_PACKAGE_2)),
|
||||
mFooter.getVpnMessage(true, true, VPN_PACKAGE, VPN_PACKAGE_2));
|
||||
mFooterUtils.getVpnMessage(true, true, VPN_PACKAGE, VPN_PACKAGE_2));
|
||||
assertEquals(addLink(mContext.getString(R.string.monitoring_description_two_named_vpns,
|
||||
VPN_PACKAGE, VPN_PACKAGE_2)),
|
||||
mFooter.getVpnMessage(false, true, VPN_PACKAGE, VPN_PACKAGE_2));
|
||||
mFooterUtils.getVpnMessage(false, true, VPN_PACKAGE, VPN_PACKAGE_2));
|
||||
assertEquals(addLink(mContext.getString(R.string.monitoring_description_named_vpn,
|
||||
VPN_PACKAGE)),
|
||||
mFooter.getVpnMessage(true, false, VPN_PACKAGE, null));
|
||||
mFooterUtils.getVpnMessage(true, false, VPN_PACKAGE, null));
|
||||
assertEquals(addLink(mContext.getString(R.string.monitoring_description_named_vpn,
|
||||
VPN_PACKAGE)),
|
||||
mFooter.getVpnMessage(false, false, VPN_PACKAGE, null));
|
||||
mFooterUtils.getVpnMessage(false, false, VPN_PACKAGE, null));
|
||||
assertEquals(addLink(mContext.getString(R.string.monitoring_description_named_vpn,
|
||||
VPN_PACKAGE_2)),
|
||||
mFooter.getVpnMessage(true, true, null, VPN_PACKAGE_2));
|
||||
mFooterUtils.getVpnMessage(true, true, null, VPN_PACKAGE_2));
|
||||
assertEquals(addLink(mContext.getString(
|
||||
R.string.monitoring_description_managed_profile_named_vpn,
|
||||
VPN_PACKAGE_2)),
|
||||
mFooter.getVpnMessage(false, true, null, VPN_PACKAGE_2));
|
||||
mFooterUtils.getVpnMessage(false, true, null, VPN_PACKAGE_2));
|
||||
assertEquals(addLink(mContext.getString(
|
||||
R.string.monitoring_description_personal_profile_named_vpn,
|
||||
VPN_PACKAGE)),
|
||||
mFooter.getVpnMessage(false, true, VPN_PACKAGE, null));
|
||||
mFooterUtils.getVpnMessage(false, true, VPN_PACKAGE, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -631,19 +634,19 @@ public class QSSecurityFooterTest extends SysuiTestCase {
|
||||
|
||||
// Device Management subtitle should be shown when there is Device Management section only
|
||||
// Other sections visibility will be set somewhere else so it will not be tested here
|
||||
mFooter.configSubtitleVisibility(true, false, false, false, view);
|
||||
mFooterUtils.configSubtitleVisibility(true, false, false, false, view);
|
||||
assertEquals(View.VISIBLE,
|
||||
view.findViewById(R.id.device_management_subtitle).getVisibility());
|
||||
|
||||
// If there are multiple sections, all subtitles should be shown
|
||||
mFooter.configSubtitleVisibility(true, true, false, false, view);
|
||||
mFooterUtils.configSubtitleVisibility(true, true, false, false, view);
|
||||
assertEquals(View.VISIBLE,
|
||||
view.findViewById(R.id.device_management_subtitle).getVisibility());
|
||||
assertEquals(View.VISIBLE,
|
||||
view.findViewById(R.id.ca_certs_subtitle).getVisibility());
|
||||
|
||||
// If there are multiple sections, all subtitles should be shown
|
||||
mFooter.configSubtitleVisibility(true, true, true, true, view);
|
||||
mFooterUtils.configSubtitleVisibility(true, true, true, true, view);
|
||||
assertEquals(View.VISIBLE,
|
||||
view.findViewById(R.id.device_management_subtitle).getVisibility());
|
||||
assertEquals(View.VISIBLE,
|
||||
@@ -655,7 +658,7 @@ public class QSSecurityFooterTest extends SysuiTestCase {
|
||||
|
||||
// If there are multiple sections, all subtitles should be shown, event if there is no
|
||||
// Device Management section
|
||||
mFooter.configSubtitleVisibility(false, true, true, true, view);
|
||||
mFooterUtils.configSubtitleVisibility(false, true, true, true, view);
|
||||
assertEquals(View.VISIBLE,
|
||||
view.findViewById(R.id.ca_certs_subtitle).getVisibility());
|
||||
assertEquals(View.VISIBLE,
|
||||
@@ -664,13 +667,13 @@ public class QSSecurityFooterTest extends SysuiTestCase {
|
||||
view.findViewById(R.id.vpn_subtitle).getVisibility());
|
||||
|
||||
// If there is only 1 section, the title should be hidden
|
||||
mFooter.configSubtitleVisibility(false, true, false, false, view);
|
||||
mFooterUtils.configSubtitleVisibility(false, true, false, false, view);
|
||||
assertEquals(View.GONE,
|
||||
view.findViewById(R.id.ca_certs_subtitle).getVisibility());
|
||||
mFooter.configSubtitleVisibility(false, false, true, false, view);
|
||||
mFooterUtils.configSubtitleVisibility(false, false, true, false, view);
|
||||
assertEquals(View.GONE,
|
||||
view.findViewById(R.id.network_logging_subtitle).getVisibility());
|
||||
mFooter.configSubtitleVisibility(false, false, false, true, view);
|
||||
mFooterUtils.configSubtitleVisibility(false, false, false, true, view);
|
||||
assertEquals(View.GONE,
|
||||
view.findViewById(R.id.vpn_subtitle).getVisibility());
|
||||
}
|
||||
@@ -722,7 +725,7 @@ public class QSSecurityFooterTest extends SysuiTestCase {
|
||||
when(mSecurityController.isParentalControlsEnabled()).thenReturn(true);
|
||||
when(mSecurityController.getLabel(any())).thenReturn(PARENTAL_CONTROLS_LABEL);
|
||||
|
||||
View view = mFooter.createDialogView();
|
||||
View view = mFooterUtils.createDialogView();
|
||||
TextView textView = (TextView) view.findViewById(R.id.parental_controls_title);
|
||||
assertEquals(PARENTAL_CONTROLS_LABEL, textView.getText());
|
||||
}
|
||||
@@ -745,7 +748,7 @@ public class QSSecurityFooterTest extends SysuiTestCase {
|
||||
when(mSecurityController.getDeviceOwnerType(DEVICE_OWNER_COMPONENT))
|
||||
.thenReturn(DEVICE_OWNER_TYPE_FINANCED);
|
||||
|
||||
View view = mFooter.createDialogView();
|
||||
View view = mFooterUtils.createDialogView();
|
||||
|
||||
TextView managementSubtitle = view.findViewById(R.id.device_management_subtitle);
|
||||
assertEquals(View.VISIBLE, managementSubtitle.getVisibility());
|
||||
@@ -756,7 +759,7 @@ public class QSSecurityFooterTest extends SysuiTestCase {
|
||||
assertEquals(mContext.getString(R.string.monitoring_financed_description_named_management,
|
||||
MANAGING_ORGANIZATION, MANAGING_ORGANIZATION), managementMessage.getText());
|
||||
assertEquals(mContext.getString(R.string.monitoring_button_view_policies),
|
||||
mFooter.getSettingsButton());
|
||||
mFooterUtils.getSettingsButton());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -776,7 +779,7 @@ public class QSSecurityFooterTest extends SysuiTestCase {
|
||||
AlertDialog dialog = dialogCaptor.getValue();
|
||||
dialog.create();
|
||||
|
||||
assertEquals(mFooter.getSettingsButton(),
|
||||
assertEquals(mFooterUtils.getSettingsButton(),
|
||||
dialog.getButton(DialogInterface.BUTTON_NEGATIVE).getText());
|
||||
|
||||
dialog.dismiss();
|
||||
@@ -819,8 +822,8 @@ public class QSSecurityFooterTest extends SysuiTestCase {
|
||||
new Intent(DevicePolicyManager.ACTION_SHOW_DEVICE_MONITORING_DIALOG));
|
||||
mTestableLooper.processAllMessages();
|
||||
|
||||
assertTrue(mFooter.getDialog().isShowing());
|
||||
mFooter.getDialog().dismiss();
|
||||
assertTrue(mFooterUtils.getDialog().isShowing());
|
||||
mFooterUtils.getDialog().dismiss();
|
||||
}
|
||||
|
||||
private CharSequence addLink(CharSequence description) {
|
||||
@@ -828,7 +831,7 @@ public class QSSecurityFooterTest extends SysuiTestCase {
|
||||
message.append(description);
|
||||
message.append(mContext.getString(R.string.monitoring_description_vpn_settings_separator));
|
||||
message.append(mContext.getString(R.string.monitoring_description_vpn_settings),
|
||||
mFooter.new VpnSpan(), 0);
|
||||
mFooterUtils.new VpnSpan(), 0);
|
||||
return message;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user