• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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 package com.android.settings.applications.specialaccess.interactacrossprofiles;
17 
18 import static android.app.admin.DevicePolicyResources.Strings.Settings.APP_CAN_ACCESS_PERSONAL_DATA;
19 import static android.app.admin.DevicePolicyResources.Strings.Settings.APP_CAN_ACCESS_PERSONAL_PERMISSIONS;
20 import static android.app.admin.DevicePolicyResources.Strings.Settings.CONNECTED_APPS_SHARE_PERMISSIONS_AND_DATA;
21 import static android.app.admin.DevicePolicyResources.Strings.Settings.CONNECTED_WORK_AND_PERSONAL_APPS_TITLE;
22 import static android.app.admin.DevicePolicyResources.Strings.Settings.CONNECT_APPS_DIALOG_SUMMARY;
23 import static android.app.admin.DevicePolicyResources.Strings.Settings.CONNECT_APPS_DIALOG_TITLE;
24 import static android.app.admin.DevicePolicyResources.Strings.Settings.HOW_TO_DISCONNECT_APPS;
25 import static android.app.admin.DevicePolicyResources.Strings.Settings.INSTALL_IN_PERSONAL_PROFILE_TO_CONNECT_PROMPT;
26 import static android.app.admin.DevicePolicyResources.Strings.Settings.INSTALL_IN_WORK_PROFILE_TO_CONNECT_PROMPT;
27 import static android.app.admin.DevicePolicyResources.Strings.Settings.ONLY_CONNECT_TRUSTED_APPS;
28 import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE;
29 import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
30 import static android.provider.Settings.ACTION_MANAGE_CROSS_PROFILE_ACCESS;
31 
32 import android.Manifest;
33 import android.annotation.UserIdInt;
34 import android.app.ActionBar;
35 import android.app.AppOpsManager;
36 import android.app.admin.DevicePolicyEventLogger;
37 import android.app.admin.DevicePolicyManager;
38 import android.app.settings.SettingsEnums;
39 import android.content.Context;
40 import android.content.DialogInterface;
41 import android.content.Intent;
42 import android.content.PermissionChecker;
43 import android.content.pm.CrossProfileApps;
44 import android.content.pm.PackageInfo;
45 import android.content.pm.PackageManager;
46 import android.graphics.ColorMatrix;
47 import android.graphics.ColorMatrixColorFilter;
48 import android.graphics.drawable.Drawable;
49 import android.os.Bundle;
50 import android.os.UserHandle;
51 import android.os.UserManager;
52 import android.stats.devicepolicy.DevicePolicyEnums;
53 import android.util.IconDrawableFactory;
54 import android.view.LayoutInflater;
55 import android.view.View;
56 import android.view.ViewGroup;
57 import android.widget.ImageView;
58 import android.widget.TextView;
59 
60 import androidx.appcompat.app.AlertDialog;
61 import androidx.preference.Preference;
62 
63 import com.android.settings.R;
64 import com.android.settings.applications.AppInfoBase;
65 import com.android.settings.applications.AppStoreUtil;
66 import com.android.settings.widget.CardPreference;
67 import com.android.settingslib.RestrictedLockUtils;
68 import com.android.settingslib.RestrictedSwitchPreference;
69 import com.android.settingslib.widget.LayoutPreference;
70 
71 public class InteractAcrossProfilesDetails extends AppInfoBase
72         implements Preference.OnPreferenceClickListener {
73 
74     private static final String INTERACT_ACROSS_PROFILES_SETTINGS_SWITCH =
75             "interact_across_profiles_settings_switch";
76     private static final String INTERACT_ACROSS_PROFILES_HEADER = "interact_across_profiles_header";
77     public static final String INSTALL_APP_BANNER_KEY = "install_app_banner";
78     public static final String INTERACT_ACROSS_PROFILE_EXTRA_SUMMARY_KEY =
79             "interact_across_profiles_extra_summary";
80     public static final String EXTRA_SHOW_FRAGMENT_ARGS = ":settings:show_fragment_args";
81     public static final String INTENT_KEY = "intent";
82     private static final String TAG = "InteractAcrossProfilesDetails";
83 
84     private Context mContext;
85     private CrossProfileApps mCrossProfileApps;
86     private UserManager mUserManager;
87     private RestrictedSwitchPreference mSwitchPref;
88     private LayoutPreference mHeader;
89     private CardPreference mInstallBanner;
90     private PackageManager mPackageManager;
91     private UserHandle mPersonalProfile;
92     private UserHandle mWorkProfile;
93     private boolean mInstalledInPersonal;
94     private boolean mInstalledInWork;
95     private String mAppLabel;
96     private Intent mInstallAppIntent;
97     private boolean mIsPageLaunchedByApp;
98 
99     @Override
onCreate(Bundle savedInstanceState)100     public void onCreate(Bundle savedInstanceState) {
101         super.onCreate(savedInstanceState);
102         mContext = getContext();
103         mCrossProfileApps = mContext.getSystemService(CrossProfileApps.class);
104         mUserManager = mContext.getSystemService(UserManager.class);
105         mPackageManager = mContext.getPackageManager();
106 
107         mWorkProfile = InteractAcrossProfilesSettings.getWorkProfile(mUserManager);
108         mPersonalProfile = mUserManager.getProfileParent(mWorkProfile);
109         mInstalledInWork = isPackageInstalled(mPackageName, mWorkProfile.getIdentifier());
110         mInstalledInPersonal = isPackageInstalled(mPackageName, mPersonalProfile.getIdentifier());
111 
112         mAppLabel = mPackageInfo.applicationInfo.loadLabel(mPackageManager).toString();
113         mInstallAppIntent = AppStoreUtil.getAppStoreLink(mContext, mPackageName);
114 
115         addPreferencesFromResource(R.xml.interact_across_profiles_permissions_details);
116     }
117 
118     @Override
onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)119     public View onCreateView(LayoutInflater inflater, ViewGroup container,
120             Bundle savedInstanceState) {
121         final View view =  super.onCreateView(inflater, container, savedInstanceState);
122 
123         replaceEnterprisePreferenceScreenTitle(CONNECTED_WORK_AND_PERSONAL_APPS_TITLE,
124                 R.string.interact_across_profiles_title);
125         replaceEnterpriseStringSummary("interact_across_profiles_summary_1",
126                 CONNECTED_APPS_SHARE_PERMISSIONS_AND_DATA,
127                 R.string.interact_across_profiles_summary_1);
128         replaceEnterpriseStringSummary("interact_across_profiles_summary_2",
129                 ONLY_CONNECT_TRUSTED_APPS,
130                 R.string.interact_across_profiles_summary_2);
131         replaceEnterpriseStringSummary("interact_across_profiles_extra_summary",
132                 HOW_TO_DISCONNECT_APPS,
133                 R.string.interact_across_profiles_summary_3);
134 
135         mSwitchPref = findPreference(INTERACT_ACROSS_PROFILES_SETTINGS_SWITCH);
136         mSwitchPref.setOnPreferenceClickListener(this);
137 
138         mHeader = findPreference(INTERACT_ACROSS_PROFILES_HEADER);
139 
140         mInstallBanner = findPreference(INSTALL_APP_BANNER_KEY);
141         mInstallBanner.setOnPreferenceClickListener(this);
142 
143         mIsPageLaunchedByApp = launchedByApp();
144 
145         // refreshUi checks that the user can still configure the appOp, return to the
146         // previous page if it can't.
147         if (!refreshUi()) {
148             setIntentAndFinish(true/* appChanged */);
149         }
150         addAppTitleAndIcons(mPersonalProfile, mWorkProfile);
151         styleActionBar();
152         maybeShowExtraSummary();
153         logPageLaunchMetrics();
154 
155         return view;
156     }
157 
maybeShowExtraSummary()158     private void maybeShowExtraSummary() {
159         Preference extraSummary = findPreference(INTERACT_ACROSS_PROFILE_EXTRA_SUMMARY_KEY);
160         if (extraSummary == null) {
161             return;
162         }
163         extraSummary.setVisible(mIsPageLaunchedByApp);
164     }
165 
logPageLaunchMetrics()166     private void logPageLaunchMetrics() {
167         if (!mCrossProfileApps.canConfigureInteractAcrossProfiles(mPackageName)) {
168             logNonConfigurableAppMetrics();
169         }
170         if (mIsPageLaunchedByApp) {
171             logEvent(DevicePolicyEnums.CROSS_PROFILE_SETTINGS_PAGE_LAUNCHED_FROM_APP);
172         } else {
173             logEvent(DevicePolicyEnums.CROSS_PROFILE_SETTINGS_PAGE_LAUNCHED_FROM_SETTINGS);
174         }
175     }
176 
logNonConfigurableAppMetrics()177     private void logNonConfigurableAppMetrics() {
178         if (!isCrossProfilePackageAllowlisted(mPackageName)) {
179             logEvent(DevicePolicyEnums.CROSS_PROFILE_SETTINGS_PAGE_ADMIN_RESTRICTED);
180             return;
181         }
182         if (mInstallBanner == null) {
183             logEvent(DevicePolicyEnums.CROSS_PROFILE_SETTINGS_PAGE_MISSING_INSTALL_BANNER_INTENT);
184         }
185         if (!mInstalledInPersonal) {
186             logEvent(DevicePolicyEnums.CROSS_PROFILE_SETTINGS_PAGE_MISSING_PERSONAL_APP);
187             return;
188         }
189         if (!mInstalledInWork) {
190             logEvent(DevicePolicyEnums.CROSS_PROFILE_SETTINGS_PAGE_MISSING_WORK_APP);
191         }
192     }
193 
logEvent(int eventId)194     private void logEvent(int eventId) {
195         DevicePolicyEventLogger.createEvent(eventId)
196                 .setStrings(mPackageName)
197                 .setInt(UserHandle.myUserId())
198                 .setAdmin(RestrictedLockUtils.getProfileOrDeviceOwner(
199                         mContext, mWorkProfile).component)
200                 .write();
201     }
202 
addAppTitleAndIcons(UserHandle personalProfile, UserHandle workProfile)203     private void addAppTitleAndIcons(UserHandle personalProfile, UserHandle workProfile) {
204         final TextView title = mHeader.findViewById(R.id.entity_header_title);
205         if (title != null) {
206             final String appLabel = mPackageInfo.applicationInfo.loadLabel(
207                     mPackageManager).toString();
208             title.setText(appLabel);
209         }
210 
211         final ImageView personalIconView = mHeader.findViewById(R.id.entity_header_icon_personal);
212         if (personalIconView != null) {
213             Drawable icon = IconDrawableFactory.newInstance(mContext)
214                     .getBadgedIcon(mPackageInfo.applicationInfo, personalProfile.getIdentifier())
215                     .mutate();
216             if (!mInstalledInPersonal) {
217                 icon.setColorFilter(createSuspendedColorMatrix());
218             }
219             personalIconView.setImageDrawable(icon);
220         }
221 
222         final ImageView workIconView = mHeader.findViewById(R.id.entity_header_icon_work);
223         if (workIconView != null) {
224             Drawable icon = IconDrawableFactory.newInstance(mContext)
225                     .getBadgedIcon(mPackageInfo.applicationInfo, workProfile.getIdentifier())
226                     .mutate();
227             if (!mInstalledInWork) {
228                 icon.setColorFilter(createSuspendedColorMatrix());
229             }
230             workIconView.setImageDrawable(icon);
231         }
232     }
233 
styleActionBar()234     private void styleActionBar() {
235         final ActionBar actionBar = getActivity().getActionBar();
236         if (actionBar != null) {
237             actionBar.setElevation(0);
238         }
239     }
240 
createSuspendedColorMatrix()241     private ColorMatrixColorFilter createSuspendedColorMatrix() {
242         int grayValue = 127;
243         float scale = 0.5f; // half bright
244 
245         ColorMatrix tempBrightnessMatrix = new ColorMatrix();
246         float[] mat = tempBrightnessMatrix.getArray();
247         mat[0] = scale;
248         mat[6] = scale;
249         mat[12] = scale;
250         mat[4] = grayValue;
251         mat[9] = grayValue;
252         mat[14] = grayValue;
253 
254         ColorMatrix matrix = new ColorMatrix();
255         matrix.setSaturation(0.0f);
256         matrix.preConcat(tempBrightnessMatrix);
257         return new ColorMatrixColorFilter(matrix);
258     }
259 
260     @Override
onPreferenceClick(Preference preference)261     public boolean onPreferenceClick(Preference preference) {
262         // refreshUi checks that the user can still configure the appOp, return to the
263         // previous page if it can't.
264         if (!refreshUi()) {
265             setIntentAndFinish(true/* appChanged */);
266         }
267         if (preference == mSwitchPref) {
268             handleSwitchPreferenceClick();
269             return true;
270         }
271         if (preference == mInstallBanner) {
272             handleInstallBannerClick();
273             return true;
274         }
275         return false;
276     }
277 
handleSwitchPreferenceClick()278     private void handleSwitchPreferenceClick() {
279         if (isInteractAcrossProfilesEnabled()) {
280             logEvent(DevicePolicyEnums.CROSS_PROFILE_SETTINGS_PAGE_PERMISSION_REVOKED);
281             enableInteractAcrossProfiles(false);
282             refreshUi();
283         } else {
284             showConsentDialog();
285         }
286     }
287 
showConsentDialog()288     private void showConsentDialog() {
289         final View dialogView = getLayoutInflater().inflate(
290                 R.layout.interact_across_profiles_consent_dialog, null);
291 
292         final TextView dialogTitle = dialogView.findViewById(
293                 R.id.interact_across_profiles_consent_dialog_title);
294         dialogTitle.setText(mDpm.getResources().getString(CONNECT_APPS_DIALOG_TITLE, () ->
295                 getString(R.string.interact_across_profiles_consent_dialog_title, mAppLabel),
296                 mAppLabel));
297 
298         final TextView appDataSummary = dialogView.findViewById(R.id.app_data_summary);
299         appDataSummary.setText(
300                 mDpm.getResources().getString(APP_CAN_ACCESS_PERSONAL_DATA,
301                         () -> getString(
302                                 R.string.interact_across_profiles_consent_dialog_app_data_summary,
303                                 mAppLabel), mAppLabel));
304 
305         final TextView permissionsSummary = dialogView.findViewById(R.id.permissions_summary);
306         permissionsSummary.setText(mDpm.getResources().getString(
307                 APP_CAN_ACCESS_PERSONAL_PERMISSIONS,
308                 () -> getString(
309                         R.string.interact_across_profiles_consent_dialog_permissions_summary,
310                         mAppLabel),
311                 mAppLabel));
312 
313         final TextView dialogSummary =
314                 dialogView.findViewById(R.id.interact_across_profiles_consent_dialog_summary);
315         dialogSummary.setText(mDpm.getResources().getString(CONNECT_APPS_DIALOG_SUMMARY,
316                 () -> getString(
317                         R.string.interact_across_profiles_consent_dialog_summary)));
318 
319         AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
320         builder.setView(dialogView)
321                 .setPositiveButton(R.string.allow, new DialogInterface.OnClickListener() {
322                     public void onClick(DialogInterface dialog, int which) {
323                         logEvent(DevicePolicyEnums.CROSS_PROFILE_SETTINGS_PAGE_USER_CONSENTED);
324                         enableInteractAcrossProfiles(true);
325                         refreshUi();
326                         if (mIsPageLaunchedByApp) {
327                             setIntentAndFinish(/* appChanged= */ true);
328                         }
329                     }
330                 })
331                 .setNegativeButton(R.string.deny, new DialogInterface.OnClickListener() {
332                     public void onClick(DialogInterface dialog, int which) {
333                         logEvent(
334                                 DevicePolicyEnums.CROSS_PROFILE_SETTINGS_PAGE_USER_DECLINED_CONSENT);
335                         refreshUi();
336                     }
337                 })
338                 .create().show();
339     }
340 
isInteractAcrossProfilesEnabled()341     private boolean isInteractAcrossProfilesEnabled() {
342         return isInteractAcrossProfilesEnabled(mContext, mPackageName);
343     }
344 
isInteractAcrossProfilesEnabled( Context context, String packageName)345     static boolean isInteractAcrossProfilesEnabled(
346             Context context, String packageName) {
347         UserManager userManager = context.getSystemService(UserManager.class);
348         UserHandle workProfile = InteractAcrossProfilesSettings.getWorkProfile(userManager);
349         if (workProfile == null) {
350             return false;
351         }
352         UserHandle personalProfile = userManager.getProfileParent(workProfile);
353         return context.getSystemService(
354                 CrossProfileApps.class).canConfigureInteractAcrossProfiles(packageName)
355                 && isInteractAcrossProfilesEnabledInProfile(context, packageName, personalProfile)
356                 && isInteractAcrossProfilesEnabledInProfile(context, packageName, workProfile);
357 
358     }
359 
isInteractAcrossProfilesEnabledInProfile( Context context, String packageName, UserHandle userHandle)360     private static boolean isInteractAcrossProfilesEnabledInProfile(
361             Context context, String packageName, UserHandle userHandle) {
362         final PackageManager packageManager = context.getPackageManager();
363         final int uid;
364         try {
365             uid = packageManager.getApplicationInfoAsUser(
366                     packageName, /* flags= */0, userHandle).uid;
367         } catch (PackageManager.NameNotFoundException e) {
368             return false;
369         }
370         return PermissionChecker.PERMISSION_GRANTED
371                 == PermissionChecker.checkPermissionForPreflight(
372                 context,
373                 Manifest.permission.INTERACT_ACROSS_PROFILES,
374                 PermissionChecker.PID_UNKNOWN,
375                 uid,
376                 packageName);
377     }
378 
enableInteractAcrossProfiles(boolean newState)379     private void enableInteractAcrossProfiles(boolean newState) {
380         mCrossProfileApps.setInteractAcrossProfilesAppOp(
381                 mPackageName, newState ? AppOpsManager.MODE_ALLOWED : AppOpsManager.MODE_IGNORED);
382     }
383 
handleInstallBannerClick()384     private void handleInstallBannerClick() {
385         if (mInstallAppIntent == null) {
386             logEvent(
387                     DevicePolicyEnums.CROSS_PROFILE_SETTINGS_PAGE_INSTALL_BANNER_NO_INTENT_CLICKED);
388             return;
389         }
390         if (!mInstalledInWork) {
391             logEvent(DevicePolicyEnums.CROSS_PROFILE_SETTINGS_PAGE_INSTALL_BANNER_CLICKED);
392             mContext.startActivityAsUser(mInstallAppIntent, mWorkProfile);
393             return;
394         }
395         if (!mInstalledInPersonal) {
396             logEvent(DevicePolicyEnums.CROSS_PROFILE_SETTINGS_PAGE_INSTALL_BANNER_CLICKED);
397             mContext.startActivityAsUser(mInstallAppIntent, mPersonalProfile);
398         }
399     }
400 
401     /**
402      * @return the summary for the current state of whether the app associated with the given
403      * {@code packageName} is allowed to interact across profiles.
404      */
getPreferenceSummary(Context context, String packageName)405     public static String getPreferenceSummary(Context context, String packageName) {
406         return context.getString(isInteractAcrossProfilesEnabled(context, packageName)
407                 ? R.string.interact_across_profiles_summary_allowed
408                 : R.string.interact_across_profiles_summary_not_allowed);
409     }
410 
411     @Override
refreshUi()412     protected boolean refreshUi() {
413         if (mPackageInfo == null || mPackageInfo.applicationInfo == null) {
414             return false;
415         }
416         if (!mCrossProfileApps.canUserAttemptToConfigureInteractAcrossProfiles(mPackageName)) {
417             // Invalid app entry. Should not allow changing permission
418             mSwitchPref.setEnabled(false);
419             return false;
420         }
421         if (!mCrossProfileApps.canConfigureInteractAcrossProfiles(mPackageName)) {
422             return refreshUiForNonConfigurableApps();
423         }
424         refreshUiForConfigurableApps();
425         return true;
426     }
427 
refreshUiForNonConfigurableApps()428     private boolean refreshUiForNonConfigurableApps() {
429         mSwitchPref.setChecked(false);
430         mSwitchPref.setTitle(R.string.interact_across_profiles_switch_disabled);
431         if (!isCrossProfilePackageAllowlisted(mPackageName)) {
432             mInstallBanner.setVisible(false);
433             mSwitchPref.setDisabledByAdmin(RestrictedLockUtils.getProfileOrDeviceOwner(
434                     mContext, mWorkProfile));
435             return true;
436         }
437         mSwitchPref.setEnabled(false);
438         if (!mInstalledInPersonal && !mInstalledInWork) {
439             return false;
440         }
441         if (!mInstalledInPersonal) {
442             mInstallBanner.setTitle(
443                     mDpm.getResources().getString(INSTALL_IN_PERSONAL_PROFILE_TO_CONNECT_PROMPT,
444                             () -> getString(
445                                     R.string.interact_across_profiles_install_personal_app_title,
446                                     mAppLabel),
447                             mAppLabel));
448             if (mInstallAppIntent != null) {
449                 mInstallBanner.setSummary(
450                         R.string.interact_across_profiles_install_app_summary);
451             }
452             mInstallBanner.setVisible(true);
453             return true;
454         }
455         if (!mInstalledInWork) {
456             mInstallBanner.setTitle(
457                     mDpm.getResources().getString(INSTALL_IN_WORK_PROFILE_TO_CONNECT_PROMPT,
458                             () -> getString(
459                                     R.string.interact_across_profiles_install_work_app_title,
460                                     mAppLabel),
461                             mAppLabel));
462             if (mInstallAppIntent != null) {
463                 mInstallBanner.setSummary(
464                         R.string.interact_across_profiles_install_app_summary);
465             }
466             mInstallBanner.setVisible(true);
467             return true;
468         }
469         return false;
470     }
471 
isCrossProfilePackageAllowlisted(String packageName)472     private boolean isCrossProfilePackageAllowlisted(String packageName) {
473         return mContext.getSystemService(DevicePolicyManager.class)
474                 .getAllCrossProfilePackages().contains(packageName);
475     }
476 
isPackageInstalled(String packageName, @UserIdInt int userId)477     private boolean isPackageInstalled(String packageName, @UserIdInt int userId) {
478         final PackageInfo info;
479         try {
480             info = mContext.createContextAsUser(UserHandle.of(userId), /* flags= */0)
481                     .getPackageManager().getPackageInfo(packageName,
482                             MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE);
483         } catch (PackageManager.NameNotFoundException e) {
484             return false;
485         }
486         return info != null;
487     }
488 
refreshUiForConfigurableApps()489     private void refreshUiForConfigurableApps() {
490         mInstallBanner.setVisible(false);
491         mSwitchPref.setEnabled(true);
492         if (isInteractAcrossProfilesEnabled()) {
493             enableSwitchPref();
494         } else {
495             disableSwitchPref();
496         }
497     }
498 
enableSwitchPref()499     private void enableSwitchPref() {
500         mSwitchPref.setChecked(true);
501         mSwitchPref.setTitle(R.string.interact_across_profiles_switch_enabled);
502         final ImageView horizontalArrowIcon = mHeader.findViewById(R.id.entity_header_swap_horiz);
503         if (horizontalArrowIcon != null) {
504             horizontalArrowIcon.setImageDrawable(
505                     mContext.getDrawable(R.drawable.ic_swap_horiz_blue));
506         }
507     }
508 
disableSwitchPref()509     private void disableSwitchPref() {
510         mSwitchPref.setChecked(false);
511         mSwitchPref.setTitle(R.string.interact_across_profiles_switch_disabled);
512         final ImageView horizontalArrowIcon = mHeader.findViewById(R.id.entity_header_swap_horiz);
513         if (horizontalArrowIcon != null) {
514             horizontalArrowIcon.setImageDrawable(
515                     mContext.getDrawable(R.drawable.ic_swap_horiz_grey));
516         }
517     }
518 
519     @Override
createDialog(int id, int errorCode)520     protected AlertDialog createDialog(int id, int errorCode) {
521         return null;
522     }
523 
524     @Override
getMetricsCategory()525     public int getMetricsCategory() {
526         return SettingsEnums.INTERACT_ACROSS_PROFILES;
527     }
528 
launchedByApp()529     private boolean launchedByApp() {
530         final Bundle bundle = getIntent().getBundleExtra(EXTRA_SHOW_FRAGMENT_ARGS);
531         if (bundle == null) {
532             return false;
533         }
534         final Intent intent = (Intent) bundle.get(INTENT_KEY);
535         if (intent == null) {
536             return false;
537         }
538         return ACTION_MANAGE_CROSS_PROFILE_ACCESS.equals(intent.getAction());
539     }
540 }
541