diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java b/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java index d983ece8f280a..b20d7ba333972 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java @@ -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 - 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 } }; - private Supplier mManagementTitleSupplier = () -> - mContext == null ? null : mContext.getString(R.string.monitoring_title_device_owned); - - private Supplier mManagementMessageSupplier = () -> - mContext == null ? null : mContext.getString( - R.string.quick_settings_disclosure_management); - - private Supplier mManagementMonitoringStringSupplier = () -> - mContext == null ? null : mContext.getString( - R.string.quick_settings_disclosure_management_monitoring); - - private Supplier mManagementMultipleVpnStringSupplier = () -> - mContext == null ? null : mContext.getString( - R.string.quick_settings_disclosure_management_vpns); - - private Supplier mWorkProfileMonitoringStringSupplier = () -> - mContext == null ? null : mContext.getString( - R.string.quick_settings_disclosure_managed_profile_monitoring); - - private Supplier mWorkProfileNetworkStringSupplier = () -> - mContext == null ? null : mContext.getString( - R.string.quick_settings_disclosure_managed_profile_network_activity); - - private Supplier mMonitoringSubtitleCaCertStringSupplier = () -> - mContext == null ? null : mContext.getString( - R.string.monitoring_subtitle_ca_certificate); - - private Supplier mMonitoringSubtitleNetworkStringSupplier = () -> - mContext == null ? null : mContext.getString( - R.string.monitoring_subtitle_network_logging); - - private Supplier mMonitoringSubtitleVpnStringSupplier = () -> - mContext == null ? null : mContext.getString(R.string.monitoring_subtitle_vpn); - - private Supplier mViewPoliciesButtonStringSupplier = () -> - mContext == null ? null : mContext.getString(R.string.monitoring_button_view_policies); - - private Supplier mManagementDialogStringSupplier = () -> - mContext == null ? null : mContext.getString( - R.string.monitoring_description_management); - - private Supplier mManagementDialogCaCertStringSupplier = () -> - mContext == null ? null : mContext.getString( - R.string.monitoring_description_management_ca_certificate); - - private Supplier mWorkProfileDialogCaCertStringSupplier = () -> - mContext == null ? null : mContext.getString( - R.string.monitoring_description_managed_profile_ca_certificate); - - private Supplier mManagementDialogNetworkStringSupplier = () -> - mContext == null ? null : mContext.getString( - R.string.monitoring_description_management_network_logging); - - private Supplier 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 // 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 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 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 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 } } } - - 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 - } - } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooterUtils.java b/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooterUtils.java new file mode 100644 index 0000000000000..43b53b5cf1913 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooterUtils.java @@ -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 mManagementTitleSupplier = () -> + mContext == null ? null : mContext.getString(R.string.monitoring_title_device_owned); + + private Supplier mManagementMessageSupplier = () -> + mContext == null ? null : mContext.getString( + R.string.quick_settings_disclosure_management); + + private Supplier mManagementMonitoringStringSupplier = () -> + mContext == null ? null : mContext.getString( + R.string.quick_settings_disclosure_management_monitoring); + + private Supplier mManagementMultipleVpnStringSupplier = () -> + mContext == null ? null : mContext.getString( + R.string.quick_settings_disclosure_management_vpns); + + private Supplier mWorkProfileMonitoringStringSupplier = () -> + mContext == null ? null : mContext.getString( + R.string.quick_settings_disclosure_managed_profile_monitoring); + + private Supplier mWorkProfileNetworkStringSupplier = () -> + mContext == null ? null : mContext.getString( + R.string.quick_settings_disclosure_managed_profile_network_activity); + + private Supplier mMonitoringSubtitleCaCertStringSupplier = () -> + mContext == null ? null : mContext.getString( + R.string.monitoring_subtitle_ca_certificate); + + private Supplier mMonitoringSubtitleNetworkStringSupplier = () -> + mContext == null ? null : mContext.getString( + R.string.monitoring_subtitle_network_logging); + + private Supplier mMonitoringSubtitleVpnStringSupplier = () -> + mContext == null ? null : mContext.getString(R.string.monitoring_subtitle_vpn); + + private Supplier mViewPoliciesButtonStringSupplier = () -> + mContext == null ? null : mContext.getString(R.string.monitoring_button_view_policies); + + private Supplier mManagementDialogStringSupplier = () -> + mContext == null ? null : mContext.getString( + R.string.monitoring_description_management); + + private Supplier mManagementDialogCaCertStringSupplier = () -> + mContext == null ? null : mContext.getString( + R.string.monitoring_description_management_ca_certificate); + + private Supplier mWorkProfileDialogCaCertStringSupplier = () -> + mContext == null ? null : mContext.getString( + R.string.monitoring_description_managed_profile_ca_certificate); + + private Supplier mManagementDialogNetworkStringSupplier = () -> + mContext == null ? null : mContext.getString( + R.string.monitoring_description_management_network_logging); + + private Supplier 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 + } + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java index 5d08c18d08d27..a156a609c0508 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java @@ -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; } }