1 /*
2  * Copyright (C) 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.systemui.car.systemdialogs;
18 
19 import static android.app.admin.DevicePolicyManager.DEVICE_OWNER_TYPE_FINANCED;
20 import static android.view.WindowInsets.Type.statusBars;
21 
22 import android.app.AlertDialog;
23 import android.content.Context;
24 import android.content.DialogInterface;
25 import android.content.Intent;
26 import android.provider.Settings;
27 import android.view.LayoutInflater;
28 import android.view.View;
29 import android.view.Window;
30 import android.view.WindowManager;
31 import android.widget.TextView;
32 
33 import androidx.annotation.Nullable;
34 
35 import com.android.systemui.R;
36 import com.android.systemui.dagger.SysUISingleton;
37 import com.android.systemui.settings.UserTracker;
38 import com.android.systemui.statusbar.policy.SecurityController;
39 
40 import javax.inject.Inject;
41 
42 /**
43  * A controller that can create and control the visibility of various system dialogs.
44  */
45 @SysUISingleton
46 public class SystemDialogsViewController {
47     private final Context mContext;
48     private final SecurityController mSecurityController;
49     private final AlertDialog.OnClickListener mOnDeviceMonitoringDialogClickListener;
50 
51     @Inject
SystemDialogsViewController( Context context, SecurityController securityController, UserTracker userTracker)52     public SystemDialogsViewController(
53             Context context,
54             SecurityController securityController,
55             UserTracker userTracker) {
56         mContext = context;
57         mSecurityController = securityController;
58         mOnDeviceMonitoringDialogClickListener = (dialog, which) -> {
59             dialog.dismiss();
60             if (which == DialogInterface.BUTTON_NEUTRAL) {
61                 Intent intent = new Intent(Settings.ACTION_ENTERPRISE_PRIVACY_SETTINGS);
62                 mContext.startActivityAsUser(intent, userTracker.getUserHandle());
63             }
64         };
65     }
66 
showDeviceMonitoringDialog()67     protected void showDeviceMonitoringDialog() {
68         AlertDialog dialog = new AlertDialog.Builder(mContext,
69                 com.android.internal.R.style.Theme_DeviceDefault_Dialog_Alert)
70                 .setView(createDialogView())
71                 .setPositiveButton(R.string.ok, mOnDeviceMonitoringDialogClickListener)
72                 .setNeutralButton(R.string.monitoring_button_view_policies,
73                         mOnDeviceMonitoringDialogClickListener)
74                 .create();
75 
76         applyCarSysUIDialogFlags(dialog);
77         dialog.show();
78     }
79 
createDialogView()80     private View createDialogView() {
81         View dialogView = LayoutInflater.from(mContext)
82                 .inflate(R.layout.device_management_dialog, null, false);
83 
84         CharSequence deviceOwnerOrganization = mSecurityController.getDeviceOwnerOrganizationName();
85         boolean isDeviceManaged = mSecurityController.isDeviceManaged();
86 
87         // device management section
88         TextView deviceManagementSubtitle =
89                 dialogView.requireViewById(R.id.device_management_subtitle);
90         deviceManagementSubtitle.setText(getDeviceMonitoringTitle(deviceOwnerOrganization));
91 
92         CharSequence managementMessage = getDeviceMonitoringMessage(deviceOwnerOrganization);
93         if (managementMessage == null) {
94             dialogView.requireViewById(R.id.device_management_disclosures).setVisibility(View.GONE);
95         } else {
96             dialogView.requireViewById(R.id.device_management_disclosures)
97                     .setVisibility(View.VISIBLE);
98             TextView deviceManagementWarning =
99                     dialogView.requireViewById(R.id.device_management_warning);
100             deviceManagementWarning.setText(managementMessage);
101         }
102 
103         // CA certificate section
104         CharSequence caCertsMessage = getCaCertsMessage(isDeviceManaged);
105         if (caCertsMessage == null) {
106             dialogView.requireViewById(R.id.ca_certs_disclosures).setVisibility(View.GONE);
107         } else {
108             dialogView.requireViewById(R.id.ca_certs_disclosures).setVisibility(View.VISIBLE);
109             TextView caCertsWarning = dialogView.requireViewById(R.id.ca_certs_warning);
110             caCertsWarning.setText(caCertsMessage);
111         }
112 
113         // network logging section
114         CharSequence networkLoggingMessage = getNetworkLoggingMessage(isDeviceManaged);
115         if (networkLoggingMessage == null) {
116             dialogView.requireViewById(R.id.network_logging_disclosures).setVisibility(View.GONE);
117         } else {
118             dialogView.requireViewById(R.id.network_logging_disclosures)
119                     .setVisibility(View.VISIBLE);
120             TextView networkLoggingWarning =
121                     dialogView.requireViewById(R.id.network_logging_warning);
122             networkLoggingWarning.setText(networkLoggingMessage);
123         }
124 
125         // VPN section
126         CharSequence vpnMessage = getVpnMessage(isDeviceManaged);
127         if (vpnMessage == null) {
128             dialogView.requireViewById(R.id.vpn_disclosures).setVisibility(View.GONE);
129         } else {
130             dialogView.requireViewById(R.id.vpn_disclosures).setVisibility(View.VISIBLE);
131             TextView vpnWarning = dialogView.requireViewById(R.id.vpn_warning);
132             vpnWarning.setText(vpnMessage);
133         }
134 
135         return dialogView;
136     }
137 
getDeviceMonitoringTitle(CharSequence deviceOwnerOrganization)138     private CharSequence getDeviceMonitoringTitle(CharSequence deviceOwnerOrganization) {
139         if (deviceOwnerOrganization != null && isFinancedDevice()) {
140             return mContext.getString(R.string.monitoring_title_financed_device,
141                     deviceOwnerOrganization);
142         } else {
143             return mContext.getString(R.string.monitoring_title_device_owned);
144         }
145     }
146 
getDeviceMonitoringMessage(CharSequence deviceOwnerOrganization)147     private CharSequence getDeviceMonitoringMessage(CharSequence deviceOwnerOrganization) {
148         if (deviceOwnerOrganization != null) {
149             if (isFinancedDevice()) {
150                 return mContext.getString(R.string.monitoring_financed_description_named_management,
151                         deviceOwnerOrganization, deviceOwnerOrganization);
152             } else {
153                 return mContext.getString(
154                         R.string.monitoring_description_named_management, deviceOwnerOrganization);
155             }
156         }
157         return mContext.getString(R.string.monitoring_description_management);
158     }
159 
160     @Nullable
getCaCertsMessage(boolean isDeviceManaged)161     private CharSequence getCaCertsMessage(boolean isDeviceManaged) {
162         boolean hasCACerts = mSecurityController.hasCACertInCurrentUser();
163         boolean hasCACertsInWorkProfile = mSecurityController.hasCACertInWorkProfile();
164         if (!(hasCACerts || hasCACertsInWorkProfile)) return null;
165         if (isDeviceManaged) {
166             return mContext.getString(R.string.monitoring_description_management_ca_certificate);
167         }
168         if (hasCACertsInWorkProfile) {
169             return mContext.getString(
170                     R.string.monitoring_description_managed_profile_ca_certificate);
171         }
172         return mContext.getString(R.string.monitoring_description_ca_certificate);
173     }
174 
175     @Nullable
getNetworkLoggingMessage(boolean isDeviceManaged)176     private CharSequence getNetworkLoggingMessage(boolean isDeviceManaged) {
177         boolean isNetworkLoggingEnabled = mSecurityController.isNetworkLoggingEnabled();
178         if (!isNetworkLoggingEnabled) return null;
179         if (isDeviceManaged) {
180             return mContext.getString(R.string.monitoring_description_management_network_logging);
181         } else {
182             return mContext.getString(
183                     R.string.monitoring_description_managed_profile_network_logging);
184         }
185     }
186 
187     @Nullable
getVpnMessage(boolean isDeviceManaged)188     private CharSequence getVpnMessage(boolean isDeviceManaged) {
189         boolean hasWorkProfile = mSecurityController.hasWorkProfile();
190         String vpnName = mSecurityController.getPrimaryVpnName();
191         String vpnNameWorkProfile = mSecurityController.getWorkProfileVpnName();
192         if (vpnName == null && vpnNameWorkProfile == null) return null;
193         if (isDeviceManaged) {
194             if (vpnName != null && vpnNameWorkProfile != null) {
195                 return mContext.getString(R.string.monitoring_description_two_named_vpns,
196                         vpnName, vpnNameWorkProfile);
197             } else {
198                 return mContext.getString(R.string.monitoring_description_managed_device_named_vpn,
199                         vpnName != null ? vpnName : vpnNameWorkProfile);
200             }
201         } else {
202             if (vpnName != null && vpnNameWorkProfile != null) {
203                 return mContext.getString(R.string.monitoring_description_two_named_vpns,
204                         vpnName, vpnNameWorkProfile);
205             } else if (vpnNameWorkProfile != null) {
206                 return mContext.getString(R.string.monitoring_description_managed_profile_named_vpn,
207                         vpnNameWorkProfile);
208             } else if (hasWorkProfile) {
209                 return mContext.getString(
210                         R.string.monitoring_description_personal_profile_named_vpn, vpnName);
211             } else {
212                 return mContext.getString(R.string.monitoring_description_named_vpn, vpnName);
213             }
214         }
215     }
216 
isFinancedDevice()217     private boolean isFinancedDevice() {
218         return mSecurityController.isDeviceManaged()
219                 && mSecurityController.getDeviceOwnerType(
220                 mSecurityController.getDeviceOwnerComponentOnAnyUser())
221                 == DEVICE_OWNER_TYPE_FINANCED;
222     }
223 
applyCarSysUIDialogFlags(AlertDialog dialog)224     private void applyCarSysUIDialogFlags(AlertDialog dialog) {
225         Window window = dialog.getWindow();
226         window.setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
227         window.addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
228                 | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
229         window.getAttributes().setFitInsetsTypes(
230                 window.getAttributes().getFitInsetsTypes() & ~statusBars());
231     }
232 }
233