blob: b682cb09b598ff673bc3cc85f947d6092d6aade2 [file] [log] [blame]
Jason Monke5b770e2017-03-03 21:49:29 -05001/*
2 * Copyright (C) 2014 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 */
16package com.android.systemui.qs;
17
Christine Franks50971112017-07-18 18:12:31 -070018import android.app.ActivityManager;
Jason Monke5b770e2017-03-03 21:49:29 -050019import android.app.AlertDialog;
arangelov28a61722018-12-10 14:54:57 +000020import android.app.admin.DevicePolicyEventLogger;
Jason Monke5b770e2017-03-03 21:49:29 -050021import android.content.Context;
22import android.content.DialogInterface;
23import android.content.Intent;
Christine Franks50971112017-07-18 18:12:31 -070024import android.content.pm.UserInfo;
Jason Monke5b770e2017-03-03 21:49:29 -050025import android.os.Handler;
26import android.os.Looper;
27import android.os.Message;
Christine Franks50971112017-07-18 18:12:31 -070028import android.os.UserManager;
Jason Monke5b770e2017-03-03 21:49:29 -050029import android.provider.Settings;
30import android.text.SpannableStringBuilder;
31import android.text.method.LinkMovementMethod;
32import android.text.style.ClickableSpan;
33import android.util.Log;
arangelov28a61722018-12-10 14:54:57 +000034import android.util.StatsLog;
phweissb3512c272017-06-13 15:23:13 +020035import android.view.ContextThemeWrapper;
Jason Monke5b770e2017-03-03 21:49:29 -050036import android.view.LayoutInflater;
37import android.view.View;
Jason Monke5b770e2017-03-03 21:49:29 -050038import android.view.View.OnClickListener;
Gus Prevasab336792018-11-14 13:52:20 -050039import android.view.ViewGroup;
phweiss0330f882017-04-19 20:14:51 +020040import android.view.Window;
Jason Monke5b770e2017-03-03 21:49:29 -050041import android.widget.ImageView;
42import android.widget.TextView;
43
44import com.android.systemui.Dependency;
45import com.android.systemui.FontSizeUtils;
46import com.android.systemui.R;
47import com.android.systemui.plugins.ActivityStarter;
48import com.android.systemui.statusbar.phone.SystemUIDialog;
49import com.android.systemui.statusbar.policy.SecurityController;
50
Jason Monke5b770e2017-03-03 21:49:29 -050051public class QSSecurityFooter implements OnClickListener, DialogInterface.OnClickListener {
52 protected static final String TAG = "QSSecurityFooter";
53 protected static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
54
55 private final View mRootView;
56 private final TextView mFooterText;
57 private final ImageView mFooterIcon;
Jason Monke5b770e2017-03-03 21:49:29 -050058 private final Context mContext;
59 private final Callback mCallback = new Callback();
60 private final SecurityController mSecurityController;
61 private final ActivityStarter mActivityStarter;
62 private final Handler mMainHandler;
phweiss774c6542017-04-12 19:32:55 +020063 private final View mDivider;
Jason Monke5b770e2017-03-03 21:49:29 -050064
Christine Franks50971112017-07-18 18:12:31 -070065 private final UserManager mUm;
66
Jason Monke5b770e2017-03-03 21:49:29 -050067 private AlertDialog mDialog;
68 private QSTileHost mHost;
69 protected H mHandler;
70
71 private boolean mIsVisible;
Jason Monke5b770e2017-03-03 21:49:29 -050072 private CharSequence mFooterTextContent = null;
73 private int mFooterTextId;
74 private int mFooterIconId;
Jason Monke5b770e2017-03-03 21:49:29 -050075
76 public QSSecurityFooter(QSPanel qsPanel, Context context) {
77 mRootView = LayoutInflater.from(context)
78 .inflate(R.layout.quick_settings_footer, qsPanel, false);
79 mRootView.setOnClickListener(this);
80 mFooterText = (TextView) mRootView.findViewById(R.id.footer_text);
81 mFooterIcon = (ImageView) mRootView.findViewById(R.id.footer_icon);
phweiss774c6542017-04-12 19:32:55 +020082 mFooterIconId = R.drawable.ic_info_outline;
Jason Monke5b770e2017-03-03 21:49:29 -050083 mContext = context;
Jason Monka716bac2018-12-05 15:48:21 -050084 mMainHandler = new Handler(Looper.myLooper());
Jason Monke5b770e2017-03-03 21:49:29 -050085 mActivityStarter = Dependency.get(ActivityStarter.class);
86 mSecurityController = Dependency.get(SecurityController.class);
87 mHandler = new H(Dependency.get(Dependency.BG_LOOPER));
phweiss774c6542017-04-12 19:32:55 +020088 mDivider = qsPanel == null ? null : qsPanel.getDivider();
Christine Franks50971112017-07-18 18:12:31 -070089 mUm = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
Jason Monke5b770e2017-03-03 21:49:29 -050090 }
91
92 public void setHostEnvironment(QSTileHost host) {
93 mHost = host;
94 }
95
96 public void setListening(boolean listening) {
97 if (listening) {
98 mSecurityController.addCallback(mCallback);
Fabian Kozynskib7199c42018-09-10 12:36:37 -040099 refreshState();
Jason Monke5b770e2017-03-03 21:49:29 -0500100 } else {
101 mSecurityController.removeCallback(mCallback);
102 }
103 }
104
105 public void onConfigurationChanged() {
106 FontSizeUtils.updateFontSize(mFooterText, R.dimen.qs_tile_text_size);
107 }
108
109 public View getView() {
110 return mRootView;
111 }
112
113 public boolean hasFooter() {
114 return mRootView.getVisibility() != View.GONE;
115 }
116
117 @Override
118 public void onClick(View v) {
119 mHandler.sendEmptyMessage(H.CLICK);
120 }
121
122 private void handleClick() {
123 showDeviceMonitoringDialog();
arangelov28a61722018-12-10 14:54:57 +0000124 DevicePolicyEventLogger
125 .createEvent(StatsLog.DEVICE_POLICY_EVENT__EVENT_ID__DO_USER_INFO_CLICKED)
126 .write();
Jason Monke5b770e2017-03-03 21:49:29 -0500127 }
128
129 public void showDeviceMonitoringDialog() {
130 mHost.collapsePanels();
131 // TODO: Delay dialog creation until after panels are collapsed.
132 createDialog();
133 }
134
135 public void refreshState() {
136 mHandler.sendEmptyMessage(H.REFRESH_STATE);
137 }
138
139 private void handleRefreshState() {
phweiss774c6542017-04-12 19:32:55 +0200140 final boolean isDeviceManaged = mSecurityController.isDeviceManaged();
Christine Franks50971112017-07-18 18:12:31 -0700141 final UserInfo currentUser = mUm.getUserInfo(ActivityManager.getCurrentUser());
142 final boolean isDemoDevice = UserManager.isDeviceInDemoMode(mContext) && currentUser != null
143 && currentUser.isDemo();
phweiss774c6542017-04-12 19:32:55 +0200144 final boolean hasWorkProfile = mSecurityController.hasWorkProfile();
145 final boolean hasCACerts = mSecurityController.hasCACertInCurrentUser();
146 final boolean hasCACertsInWorkProfile = mSecurityController.hasCACertInWorkProfile();
147 final boolean isNetworkLoggingEnabled = mSecurityController.isNetworkLoggingEnabled();
148 final String vpnName = mSecurityController.getPrimaryVpnName();
149 final String vpnNameWorkProfile = mSecurityController.getWorkProfileVpnName();
150 final CharSequence organizationName = mSecurityController.getDeviceOwnerOrganizationName();
151 final CharSequence workProfileName = mSecurityController.getWorkProfileOrganizationName();
152 // Update visibility of footer
Christine Franks50971112017-07-18 18:12:31 -0700153 mIsVisible = (isDeviceManaged && !isDemoDevice) || hasCACerts || hasCACertsInWorkProfile ||
phweiss774c6542017-04-12 19:32:55 +0200154 vpnName != null || vpnNameWorkProfile != null;
155 // Update the string
156 mFooterTextContent = getFooterText(isDeviceManaged, hasWorkProfile,
157 hasCACerts, hasCACertsInWorkProfile, isNetworkLoggingEnabled, vpnName,
158 vpnNameWorkProfile, organizationName, workProfileName);
159 // Update the icon
Anarghya Mitra10422892018-06-07 13:26:14 -0700160 int footerIconId = R.drawable.ic_info_outline;
161 if (vpnName != null || vpnNameWorkProfile != null) {
162 if (mSecurityController.isVpnBranded()) {
Amin Shaikh283e29f2019-03-29 14:23:43 -0400163 footerIconId = R.drawable.stat_sys_branded_vpn;
Anarghya Mitra10422892018-06-07 13:26:14 -0700164 } else {
Amin Shaikh283e29f2019-03-29 14:23:43 -0400165 footerIconId = R.drawable.stat_sys_vpn_ic;
Anarghya Mitra10422892018-06-07 13:26:14 -0700166 }
167 }
phweiss774c6542017-04-12 19:32:55 +0200168 if (mFooterIconId != footerIconId) {
169 mFooterIconId = footerIconId;
170 mMainHandler.post(mUpdateIcon);
Jason Monke5b770e2017-03-03 21:49:29 -0500171 }
172 mMainHandler.post(mUpdateDisplayState);
173 }
174
phweiss774c6542017-04-12 19:32:55 +0200175 protected CharSequence getFooterText(boolean isDeviceManaged, boolean hasWorkProfile,
176 boolean hasCACerts, boolean hasCACertsInWorkProfile, boolean isNetworkLoggingEnabled,
177 String vpnName, String vpnNameWorkProfile, CharSequence organizationName,
178 CharSequence workProfileName) {
179 if (isDeviceManaged) {
180 if (hasCACerts || hasCACertsInWorkProfile || isNetworkLoggingEnabled) {
181 if (organizationName == null) {
182 return mContext.getString(
183 R.string.quick_settings_disclosure_management_monitoring);
184 }
185 return mContext.getString(
186 R.string.quick_settings_disclosure_named_management_monitoring,
187 organizationName);
188 }
189 if (vpnName != null && vpnNameWorkProfile != null) {
190 if (organizationName == null) {
191 return mContext.getString(R.string.quick_settings_disclosure_management_vpns);
192 }
193 return mContext.getString(R.string.quick_settings_disclosure_named_management_vpns,
194 organizationName);
195 }
196 if (vpnName != null || vpnNameWorkProfile != null) {
197 if (organizationName == null) {
198 return mContext.getString(
199 R.string.quick_settings_disclosure_management_named_vpn,
200 vpnName != null ? vpnName : vpnNameWorkProfile);
201 }
202 return mContext.getString(
203 R.string.quick_settings_disclosure_named_management_named_vpn,
204 organizationName,
205 vpnName != null ? vpnName : vpnNameWorkProfile);
206 }
207 if (organizationName == null) {
208 return mContext.getString(R.string.quick_settings_disclosure_management);
209 }
210 return mContext.getString(R.string.quick_settings_disclosure_named_management,
211 organizationName);
212 } // end if(isDeviceManaged)
213 if (hasCACertsInWorkProfile) {
214 if (workProfileName == null) {
215 return mContext.getString(
216 R.string.quick_settings_disclosure_managed_profile_monitoring);
217 }
218 return mContext.getString(
219 R.string.quick_settings_disclosure_named_managed_profile_monitoring,
220 workProfileName);
221 }
222 if (hasCACerts) {
223 return mContext.getString(R.string.quick_settings_disclosure_monitoring);
224 }
225 if (vpnName != null && vpnNameWorkProfile != null) {
226 return mContext.getString(R.string.quick_settings_disclosure_vpns);
227 }
228 if (vpnNameWorkProfile != null) {
229 return mContext.getString(R.string.quick_settings_disclosure_managed_profile_named_vpn,
230 vpnNameWorkProfile);
231 }
232 if (vpnName != null) {
233 if (hasWorkProfile) {
234 return mContext.getString(
235 R.string.quick_settings_disclosure_personal_profile_named_vpn,
236 vpnName);
237 }
238 return mContext.getString(R.string.quick_settings_disclosure_named_vpn,
239 vpnName);
240 }
241 return null;
242 }
243
Jason Monke5b770e2017-03-03 21:49:29 -0500244 @Override
245 public void onClick(DialogInterface dialog, int which) {
246 if (which == DialogInterface.BUTTON_NEGATIVE) {
phweiss0330f882017-04-19 20:14:51 +0200247 final Intent intent = new Intent(Settings.ACTION_ENTERPRISE_PRIVACY_SETTINGS);
248 mDialog.dismiss();
249 mActivityStarter.postStartActivityDismissingKeyguard(intent, 0);
Jason Monke5b770e2017-03-03 21:49:29 -0500250 }
251 }
252
253 private void createDialog() {
phweiss0330f882017-04-19 20:14:51 +0200254 final boolean isDeviceManaged = mSecurityController.isDeviceManaged();
255 final boolean hasWorkProfile = mSecurityController.hasWorkProfile();
Jason Monke5b770e2017-03-03 21:49:29 -0500256 final CharSequence deviceOwnerOrganization =
257 mSecurityController.getDeviceOwnerOrganizationName();
phweiss0330f882017-04-19 20:14:51 +0200258 final boolean hasCACerts = mSecurityController.hasCACertInCurrentUser();
259 final boolean hasCACertsInWorkProfile = mSecurityController.hasCACertInWorkProfile();
260 final boolean isNetworkLoggingEnabled = mSecurityController.isNetworkLoggingEnabled();
261 final String vpnName = mSecurityController.getPrimaryVpnName();
262 final String vpnNameWorkProfile = mSecurityController.getWorkProfileVpnName();
Jason Monke5b770e2017-03-03 21:49:29 -0500263
264 mDialog = new SystemUIDialog(mContext);
phweiss0330f882017-04-19 20:14:51 +0200265 mDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
phweissb3512c272017-06-13 15:23:13 +0200266 View dialogView = LayoutInflater.from(
267 new ContextThemeWrapper(mContext, R.style.Theme_SystemUI_Dialog))
268 .inflate(R.layout.quick_settings_footer_dialog, null, false);
phweiss0330f882017-04-19 20:14:51 +0200269 mDialog.setView(dialogView);
270 mDialog.setButton(DialogInterface.BUTTON_POSITIVE, getPositiveButton(), this);
Jason Monke5b770e2017-03-03 21:49:29 -0500271
phweiss0330f882017-04-19 20:14:51 +0200272 // device management section
273 CharSequence managementMessage = getManagementMessage(isDeviceManaged,
274 deviceOwnerOrganization);
275 if (managementMessage == null) {
276 dialogView.findViewById(R.id.device_management_disclosures).setVisibility(View.GONE);
277 } else {
278 dialogView.findViewById(R.id.device_management_disclosures).setVisibility(View.VISIBLE);
279 TextView deviceManagementWarning =
280 (TextView) dialogView.findViewById(R.id.device_management_warning);
281 deviceManagementWarning.setText(managementMessage);
282 mDialog.setButton(DialogInterface.BUTTON_NEGATIVE, getSettingsButton(), this);
Jason Monke5b770e2017-03-03 21:49:29 -0500283 }
284
phweiss0330f882017-04-19 20:14:51 +0200285 // ca certificate section
286 CharSequence caCertsMessage = getCaCertsMessage(isDeviceManaged, hasCACerts,
287 hasCACertsInWorkProfile);
288 if (caCertsMessage == null) {
289 dialogView.findViewById(R.id.ca_certs_disclosures).setVisibility(View.GONE);
290 } else {
291 dialogView.findViewById(R.id.ca_certs_disclosures).setVisibility(View.VISIBLE);
292 TextView caCertsWarning = (TextView) dialogView.findViewById(R.id.ca_certs_warning);
293 caCertsWarning.setText(caCertsMessage);
294 // Make "Open trusted credentials"-link clickable
295 caCertsWarning.setMovementMethod(new LinkMovementMethod());
296 }
297
298 // network logging section
299 CharSequence networkLoggingMessage = getNetworkLoggingMessage(isNetworkLoggingEnabled);
300 if (networkLoggingMessage == null) {
301 dialogView.findViewById(R.id.network_logging_disclosures).setVisibility(View.GONE);
302 } else {
303 dialogView.findViewById(R.id.network_logging_disclosures).setVisibility(View.VISIBLE);
304 TextView networkLoggingWarning =
305 (TextView) dialogView.findViewById(R.id.network_logging_warning);
306 networkLoggingWarning.setText(networkLoggingMessage);
307 }
308
309 // vpn section
310 CharSequence vpnMessage = getVpnMessage(isDeviceManaged, hasWorkProfile, vpnName,
311 vpnNameWorkProfile);
312 if (vpnMessage == null) {
313 dialogView.findViewById(R.id.vpn_disclosures).setVisibility(View.GONE);
314 } else {
315 dialogView.findViewById(R.id.vpn_disclosures).setVisibility(View.VISIBLE);
316 TextView vpnWarning = (TextView) dialogView.findViewById(R.id.vpn_warning);
317 vpnWarning.setText(vpnMessage);
318 // Make "Open VPN Settings"-link clickable
319 vpnWarning.setMovementMethod(new LinkMovementMethod());
320 }
321
Winston Man9aaa8cf2017-08-15 13:15:24 +0100322 // Note: if a new section is added, should update configSubtitleVisibility to include
323 // the handling of the subtitle
324 configSubtitleVisibility(managementMessage != null,
325 caCertsMessage != null,
326 networkLoggingMessage != null,
327 vpnMessage != null,
328 dialogView);
329
Jason Monke5b770e2017-03-03 21:49:29 -0500330 mDialog.show();
phweiss0330f882017-04-19 20:14:51 +0200331 mDialog.getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT,
332 ViewGroup.LayoutParams.WRAP_CONTENT);
Jason Monke5b770e2017-03-03 21:49:29 -0500333 }
334
Winston Man9aaa8cf2017-08-15 13:15:24 +0100335 protected void configSubtitleVisibility(boolean showDeviceManagement, boolean showCaCerts,
336 boolean showNetworkLogging, boolean showVpn, View dialogView) {
337 // Device Management title should always been shown
338 // When there is a Device Management message, all subtitles should be shown
339 if (showDeviceManagement) {
340 return;
341 }
342 // Hide the subtitle if there is only 1 message shown
343 int mSectionCountExcludingDeviceMgt = 0;
344 if (showCaCerts) { mSectionCountExcludingDeviceMgt++; }
345 if (showNetworkLogging) { mSectionCountExcludingDeviceMgt++; }
346 if (showVpn) { mSectionCountExcludingDeviceMgt++; }
347
348 // No work needed if there is no sections or more than 1 section
349 if (mSectionCountExcludingDeviceMgt != 1) {
350 return;
351 }
352 if (showCaCerts) {
353 dialogView.findViewById(R.id.ca_certs_subtitle).setVisibility(View.GONE);
354 }
355 if (showNetworkLogging) {
356 dialogView.findViewById(R.id.network_logging_subtitle).setVisibility(View.GONE);
357 }
358 if (showVpn) {
359 dialogView.findViewById(R.id.vpn_subtitle).setVisibility(View.GONE);
360 }
361 }
362
Jason Monke5b770e2017-03-03 21:49:29 -0500363 private String getSettingsButton() {
phweiss0330f882017-04-19 20:14:51 +0200364 return mContext.getString(R.string.monitoring_button_view_policies);
Jason Monke5b770e2017-03-03 21:49:29 -0500365 }
366
phweiss774c6542017-04-12 19:32:55 +0200367 private String getPositiveButton() {
Tony Mak57d22f62017-08-10 15:41:12 +0100368 return mContext.getString(R.string.ok);
Jason Monke5b770e2017-03-03 21:49:29 -0500369 }
370
phweiss0330f882017-04-19 20:14:51 +0200371 protected CharSequence getManagementMessage(boolean isDeviceManaged,
372 CharSequence organizationName) {
373 if (!isDeviceManaged) return null;
374 if (organizationName != null)
375 return mContext.getString(
376 R.string.monitoring_description_named_management, organizationName);
377 return mContext.getString(R.string.monitoring_description_management);
378 }
379
380 protected CharSequence getCaCertsMessage(boolean isDeviceManaged, boolean hasCACerts,
381 boolean hasCACertsInWorkProfile) {
382 if (!(hasCACerts || hasCACertsInWorkProfile)) return null;
383 if (isDeviceManaged) {
384 return mContext.getString(R.string.monitoring_description_management_ca_certificate);
Jason Monke5b770e2017-03-03 21:49:29 -0500385 }
phweiss0330f882017-04-19 20:14:51 +0200386 if (hasCACertsInWorkProfile) {
387 return mContext.getString(
388 R.string.monitoring_description_managed_profile_ca_certificate);
389 }
390 return mContext.getString(R.string.monitoring_description_ca_certificate);
391 }
392
393 protected CharSequence getNetworkLoggingMessage(boolean isNetworkLoggingEnabled) {
394 if (!isNetworkLoggingEnabled) return null;
395 return mContext.getString(R.string.monitoring_description_management_network_logging);
396 }
397
398 protected CharSequence getVpnMessage(boolean isDeviceManaged, boolean hasWorkProfile,
399 String vpnName, String vpnNameWorkProfile) {
400 if (vpnName == null && vpnNameWorkProfile == null) return null;
401 final SpannableStringBuilder message = new SpannableStringBuilder();
402 if (isDeviceManaged) {
403 if (vpnName != null && vpnNameWorkProfile != null) {
404 message.append(mContext.getString(R.string.monitoring_description_two_named_vpns,
405 vpnName, vpnNameWorkProfile));
406 } else {
407 message.append(mContext.getString(R.string.monitoring_description_named_vpn,
408 vpnName != null ? vpnName : vpnNameWorkProfile));
409 }
410 } else {
411 if (vpnName != null && vpnNameWorkProfile != null) {
412 message.append(mContext.getString(R.string.monitoring_description_two_named_vpns,
413 vpnName, vpnNameWorkProfile));
414 } else if (vpnNameWorkProfile != null) {
415 message.append(mContext.getString(
416 R.string.monitoring_description_managed_profile_named_vpn,
417 vpnNameWorkProfile));
418 } else if (hasWorkProfile) {
419 message.append(mContext.getString(
420 R.string.monitoring_description_personal_profile_named_vpn, vpnName));
421 } else {
422 message.append(mContext.getString(R.string.monitoring_description_named_vpn,
423 vpnName));
424 }
425 }
426 message.append(mContext.getString(R.string.monitoring_description_vpn_settings_separator));
427 message.append(mContext.getString(R.string.monitoring_description_vpn_settings),
428 new VpnSpan(), 0);
429 return message;
Jason Monke5b770e2017-03-03 21:49:29 -0500430 }
431
432 private int getTitle(String deviceOwner) {
433 if (deviceOwner != null) {
434 return R.string.monitoring_title_device_owned;
435 } else {
436 return R.string.monitoring_title;
437 }
438 }
439
440 private final Runnable mUpdateIcon = new Runnable() {
441 @Override
442 public void run() {
443 mFooterIcon.setImageResource(mFooterIconId);
Jason Monke5b770e2017-03-03 21:49:29 -0500444 }
445 };
446
447 private final Runnable mUpdateDisplayState = new Runnable() {
448 @Override
449 public void run() {
450 if (mFooterTextContent != null) {
451 mFooterText.setText(mFooterTextContent);
452 }
453 mRootView.setVisibility(mIsVisible ? View.VISIBLE : View.GONE);
phweiss774c6542017-04-12 19:32:55 +0200454 if (mDivider != null) mDivider.setVisibility(mIsVisible ? View.GONE : View.VISIBLE);
Jason Monke5b770e2017-03-03 21:49:29 -0500455 }
456 };
457
458 private class Callback implements SecurityController.SecurityControllerCallback {
459 @Override
460 public void onStateChanged() {
461 refreshState();
462 }
463 }
464
465 private class H extends Handler {
466 private static final int CLICK = 0;
467 private static final int REFRESH_STATE = 1;
468
469 private H(Looper looper) {
470 super(looper);
471 }
472
473 @Override
474 public void handleMessage(Message msg) {
475 String name = null;
476 try {
477 if (msg.what == REFRESH_STATE) {
478 name = "handleRefreshState";
479 handleRefreshState();
480 } else if (msg.what == CLICK) {
481 name = "handleClick";
482 handleClick();
483 }
484 } catch (Throwable t) {
485 final String error = "Error in " + name;
486 Log.w(TAG, error, t);
487 mHost.warn(error, t);
488 }
489 }
490 }
491
Jason Monke5b770e2017-03-03 21:49:29 -0500492 protected class VpnSpan extends ClickableSpan {
493 @Override
494 public void onClick(View widget) {
495 final Intent intent = new Intent(Settings.ACTION_VPN_SETTINGS);
Jason Monke5b770e2017-03-03 21:49:29 -0500496 mDialog.dismiss();
Bartosz Fabianowskie46e2b92017-04-03 13:29:12 +0200497 mActivityStarter.postStartActivityDismissingKeyguard(intent, 0);
Jason Monke5b770e2017-03-03 21:49:29 -0500498 }
phweiss0330f882017-04-19 20:14:51 +0200499
500 // for testing, to compare two CharSequences containing VpnSpans
501 @Override
502 public boolean equals(Object object) {
503 return object instanceof VpnSpan;
504 }
505
506 @Override
507 public int hashCode() {
508 return 314159257; // prime
509 }
Jason Monke5b770e2017-03-03 21:49:29 -0500510 }
511}