1 
2 /*
3  * Copyright (C) 2014 The Android Open Source Project
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 package com.android.settings.password;
19 
20 import static android.app.admin.DevicePolicyResources.Strings.Settings.CONFIRM_WORK_PROFILE_PASSWORD_HEADER;
21 import static android.app.admin.DevicePolicyResources.Strings.Settings.CONFIRM_WORK_PROFILE_PATTERN_HEADER;
22 import static android.app.admin.DevicePolicyResources.Strings.Settings.CONFIRM_WORK_PROFILE_PIN_HEADER;
23 import static android.Manifest.permission.SET_BIOMETRIC_DIALOG_ADVANCED;
24 import static android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS;
25 
26 import static com.android.systemui.biometrics.Utils.toBitmap;
27 
28 import android.app.Activity;
29 import android.app.KeyguardManager;
30 import android.app.RemoteLockscreenValidationSession;
31 import android.app.admin.DevicePolicyManager;
32 import android.app.admin.ManagedSubscriptionsPolicy;
33 import android.app.trust.TrustManager;
34 import android.content.ComponentName;
35 import android.content.Context;
36 import android.content.Intent;
37 import android.content.pm.PackageManager;
38 import android.content.pm.UserProperties;
39 import android.content.res.Configuration;
40 import android.graphics.Bitmap;
41 import android.graphics.Color;
42 import android.hardware.biometrics.BiometricConstants;
43 import android.hardware.biometrics.BiometricPrompt;
44 import android.hardware.biometrics.BiometricPrompt.AuthenticationCallback;
45 import android.hardware.biometrics.PromptInfo;
46 import android.os.Bundle;
47 import android.os.Handler;
48 import android.os.Looper;
49 import android.os.UserHandle;
50 import android.os.UserManager;
51 import android.os.storage.StorageManager;
52 import android.text.TextUtils;
53 import android.util.Log;
54 import android.view.WindowManager;
55 
56 import androidx.annotation.NonNull;
57 import androidx.fragment.app.FragmentActivity;
58 
59 import com.android.internal.widget.LockPatternUtils;
60 import com.android.settings.R;
61 import com.android.settings.Utils;
62 
63 import java.util.concurrent.Executor;
64 
65 /**
66  * Launch this when you want to confirm the user is present by asking them to enter their
67  * PIN/password/pattern.
68  */
69 public class ConfirmDeviceCredentialActivity extends FragmentActivity {
70     public static final String TAG = ConfirmDeviceCredentialActivity.class.getSimpleName();
71 
72     private static final String TAG_BIOMETRIC_FRAGMENT = "fragment";
73 
74     /** Use this extra value to provide a custom logo for the biometric prompt. **/
75     public static final String CUSTOM_BIOMETRIC_PROMPT_LOGO_RES_ID_KEY = "custom_logo_res_id";
76     /** Use this extra value to provide a custom logo description for the biometric prompt. **/
77     public static final String CUSTOM_BIOMETRIC_PROMPT_LOGO_DESCRIPTION_KEY =
78             "custom_logo_description";
79 
80     public static class InternalActivity extends ConfirmDeviceCredentialActivity {
81     }
82 
83     private BiometricFragment mBiometricFragment;
84     private DevicePolicyManager mDevicePolicyManager;
85     private LockPatternUtils mLockPatternUtils;
86     private UserManager mUserManager;
87     private TrustManager mTrustManager;
88     private Handler mHandler = new Handler(Looper.getMainLooper());
89     private Context mContext;
90     private boolean mCheckDevicePolicyManager;
91     private boolean mTaskOverlay;
92 
93     private String mTitle;
94     private CharSequence mDetails;
95     private int mUserId;
96     // Used to force the verification path required to unlock profile that shares credentials with
97     // with parent
98     private boolean mForceVerifyPath = false;
99     private boolean mGoingToBackground;
100     private boolean mWaitingForBiometricCallback;
101 
102     private Executor mExecutor = (runnable -> {
103         mHandler.post(runnable);
104     });
105 
106     private AuthenticationCallback mAuthenticationCallback = new AuthenticationCallback() {
107         @Override
108         public void onAuthenticationError(int errorCode, @NonNull CharSequence errString) {
109             if (!mGoingToBackground) {
110                 mWaitingForBiometricCallback = false;
111                 if (errorCode == BiometricPrompt.BIOMETRIC_ERROR_USER_CANCELED
112                         || errorCode == BiometricPrompt.BIOMETRIC_ERROR_CANCELED) {
113                     finish();
114                 } else if (mUserManager.getUserInfo(mUserId) == null) {
115                     // This can happen when profile gets wiped due to too many failed auth attempts.
116                     Log.i(TAG, "Finishing, user no longer valid: " + mUserId);
117                     finish();
118                 } else {
119                     // All other errors go to some version of CC
120                     showConfirmCredentials();
121                 }
122             } else if (mWaitingForBiometricCallback) { // mGoingToBackground is true
123                 mWaitingForBiometricCallback = false;
124                 finish();
125             }
126         }
127 
128         @Override
129         public void onAuthenticationSucceeded(BiometricPrompt.AuthenticationResult result) {
130             mWaitingForBiometricCallback = false;
131             mTrustManager.setDeviceLockedForUser(mUserId, false);
132             final boolean isStrongAuth = result.getAuthenticationType()
133                     == BiometricPrompt.AUTHENTICATION_RESULT_TYPE_DEVICE_CREDENTIAL;
134             ConfirmDeviceCredentialUtils.reportSuccessfulAttempt(mLockPatternUtils, mUserManager,
135                     mDevicePolicyManager, mUserId, isStrongAuth);
136             ConfirmDeviceCredentialUtils.checkForPendingIntent(
137                     ConfirmDeviceCredentialActivity.this);
138 
139             setResult(Activity.RESULT_OK);
140             finish();
141         }
142 
143         @Override
144         public void onAuthenticationFailed() {
145             mWaitingForBiometricCallback = false;
146             mDevicePolicyManager.reportFailedBiometricAttempt(mUserId);
147         }
148 
149         @Override
150         public void onSystemEvent(int event) {
151             Log.d(TAG, "SystemEvent: " + event);
152             switch (event) {
153                 case BiometricConstants.BIOMETRIC_SYSTEM_EVENT_EARLY_USER_CANCEL:
154                     finish();
155                     break;
156             }
157         }
158     };
159 
160     @Override
onCreate(Bundle savedInstanceState)161     protected void onCreate(Bundle savedInstanceState) {
162         super.onCreate(savedInstanceState);
163 
164         getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
165         getWindow().setStatusBarColor(Color.TRANSPARENT);
166 
167         mDevicePolicyManager = getSystemService(DevicePolicyManager.class);
168         mUserManager = UserManager.get(this);
169         mTrustManager = getSystemService(TrustManager.class);
170         mLockPatternUtils = new LockPatternUtils(this);
171 
172         Intent intent = getIntent();
173         mContext = this;
174         mCheckDevicePolicyManager = intent
175                 .getBooleanExtra(KeyguardManager.EXTRA_DISALLOW_BIOMETRICS_IF_POLICY_EXISTS, false);
176         mTitle = intent.getStringExtra(KeyguardManager.EXTRA_TITLE);
177         mDetails = intent.getCharSequenceExtra(KeyguardManager.EXTRA_DESCRIPTION);
178         String alternateButton = intent.getStringExtra(
179                 KeyguardManager.EXTRA_ALTERNATE_BUTTON_LABEL);
180         final boolean frp =
181                 KeyguardManager.ACTION_CONFIRM_FRP_CREDENTIAL.equals(intent.getAction());
182         final boolean repairMode =
183                 KeyguardManager.ACTION_CONFIRM_REPAIR_MODE_DEVICE_CREDENTIAL
184                         .equals(intent.getAction());
185         final boolean remoteValidation =
186                 KeyguardManager.ACTION_CONFIRM_REMOTE_DEVICE_CREDENTIAL.equals(intent.getAction());
187         mTaskOverlay = isInternalActivity()
188                 && intent.getBooleanExtra(KeyguardManager.EXTRA_FORCE_TASK_OVERLAY, false);
189         final boolean prepareRepairMode =
190                 KeyguardManager.ACTION_PREPARE_REPAIR_MODE_DEVICE_CREDENTIAL.equals(
191                         intent.getAction());
192 
193         mUserId = UserHandle.myUserId();
194         if (isInternalActivity()) {
195             try {
196                 mUserId = Utils.getUserIdFromBundle(this, intent.getExtras());
197             } catch (SecurityException se) {
198                 Log.e(TAG, "Invalid intent extra", se);
199             }
200         }
201         final int effectiveUserId = mUserManager.getCredentialOwnerProfile(mUserId);
202         final boolean isEffectiveUserManagedProfile =
203                 mUserManager.isManagedProfile(effectiveUserId);
204         final UserProperties userProperties =
205                 mUserManager.getUserProperties(UserHandle.of(mUserId));
206         // if the client app did not hand in a title and we are about to show the work challenge,
207         // check whether there is a policy setting the organization name and use that as title
208         if ((mTitle == null) && isEffectiveUserManagedProfile) {
209             mTitle = getTitleFromOrganizationName(mUserId);
210         }
211 
212         final PromptInfo promptInfo = new PromptInfo();
213         promptInfo.setTitle(mTitle);
214         promptInfo.setDescription(mDetails);
215         promptInfo.setDisallowBiometricsIfPolicyExists(mCheckDevicePolicyManager);
216 
217         if (android.multiuser.Flags.enablePrivateSpaceFeatures()
218                 && android.multiuser.Flags.usePrivateSpaceIconInBiometricPrompt()
219                 && hasSetBiometricDialogAdvanced(mContext, getLaunchedFromUid())
220         ) {
221             final int iconResId = intent.getIntExtra(CUSTOM_BIOMETRIC_PROMPT_LOGO_RES_ID_KEY, 0);
222             if (iconResId != 0) {
223                 final Bitmap iconBitmap = toBitmap(mContext.getDrawable(iconResId));
224                 promptInfo.setLogo(iconResId, iconBitmap);
225             }
226             String logoDescription = intent.getStringExtra(
227                     CUSTOM_BIOMETRIC_PROMPT_LOGO_DESCRIPTION_KEY);
228             if (!TextUtils.isEmpty(logoDescription)) {
229                 promptInfo.setLogoDescription(logoDescription);
230             }
231         }
232 
233         final int policyType = mDevicePolicyManager.getManagedSubscriptionsPolicy().getPolicyType();
234 
235         if (isEffectiveUserManagedProfile
236                 && (policyType == ManagedSubscriptionsPolicy.TYPE_ALL_MANAGED_SUBSCRIPTIONS)) {
237             promptInfo.setShowEmergencyCallButton(true);
238         }
239 
240         final @LockPatternUtils.CredentialType int credentialType = Utils.getCredentialType(
241                 mContext, effectiveUserId);
242         if (mTitle == null) {
243             promptInfo.setDeviceCredentialTitle(
244                     getTitleFromCredentialType(credentialType, isEffectiveUserManagedProfile));
245         }
246         if (mDetails == null) {
247             promptInfo.setDeviceCredentialSubtitle(
248                     Utils.getConfirmCredentialStringForUser(this, mUserId, credentialType));
249         }
250 
251         boolean launchedBiometric = false;
252         boolean launchedCDC = false;
253         // If the target is a managed user and user key not unlocked yet, we will force unlock
254         // tied profile so it will enable work mode and unlock managed profile, when personal
255         // challenge is unlocked.
256         if (frp) {
257             final ChooseLockSettingsHelper.Builder builder =
258                     new ChooseLockSettingsHelper.Builder(this);
259             launchedCDC = builder.setHeader(mTitle) // Show the title in the header location
260                     .setDescription(mDetails)
261                     .setAlternateButton(alternateButton)
262                     .setExternal(true)
263                     .setUserId(LockPatternUtils.USER_FRP)
264                     .show();
265         } else if (repairMode) {
266             final ChooseLockSettingsHelper.Builder builder =
267                     new ChooseLockSettingsHelper.Builder(this);
268             launchedCDC = builder.setHeader(mTitle)
269                     .setDescription(mDetails)
270                     .setExternal(true)
271                     .setUserId(LockPatternUtils.USER_REPAIR_MODE)
272                     .show();
273         } else if (remoteValidation) {
274             RemoteLockscreenValidationSession remoteLockscreenValidationSession =
275                     intent.getParcelableExtra(
276                             KeyguardManager.EXTRA_REMOTE_LOCKSCREEN_VALIDATION_SESSION,
277                             RemoteLockscreenValidationSession.class);
278             ComponentName remoteLockscreenValidationServiceComponent =
279                     intent.getParcelableExtra(Intent.EXTRA_COMPONENT_NAME, ComponentName.class);
280 
281             String checkboxLabel = intent.getStringExtra(KeyguardManager.EXTRA_CHECKBOX_LABEL);
282             final ChooseLockSettingsHelper.Builder builder =
283                     new ChooseLockSettingsHelper.Builder(this);
284             launchedCDC = builder
285                     .setRemoteLockscreenValidation(true)
286                     .setRemoteLockscreenValidationSession(remoteLockscreenValidationSession)
287                     .setRemoteLockscreenValidationServiceComponent(
288                             remoteLockscreenValidationServiceComponent)
289                     .setRequestGatekeeperPasswordHandle(true)
290                     .setReturnCredentials(true) // returns only password handle.
291                     .setHeader(mTitle) // Show the title in the header location
292                     .setDescription(mDetails)
293                     .setCheckboxLabel(checkboxLabel)
294                     .setAlternateButton(alternateButton)
295                     .setExternal(true)
296                     .show();
297             return;
298         } else if (prepareRepairMode) {
299             final ChooseLockSettingsHelper.Builder builder =
300                     new ChooseLockSettingsHelper.Builder(this);
301             launchedCDC = builder.setHeader(mTitle)
302                     .setDescription(mDetails)
303                     .setExternal(true)
304                     .setUserId(mUserId)
305                     .setTaskOverlay(mTaskOverlay)
306                     .setRequestWriteRepairModePassword(true)
307                     .setForceVerifyPath(true)
308                     .show();
309         } else if (mLockPatternUtils.isManagedProfileWithUnifiedChallenge(mUserId)
310                 && isInternalActivity()) {
311             // When the mForceVerifyPath is set to true, we launch the real confirm credential
312             // activity with an explicit but fake challenge value (0L). This will result in
313             // ConfirmLockPassword calling verifyTiedProfileChallenge() (if it's a profile with
314             // unified challenge), due to the difference between
315             // ConfirmLockPassword.startVerifyPassword() and
316             // ConfirmLockPassword.startCheckPassword(). Calling verifyTiedProfileChallenge() here
317             // is necessary when this is part of the turning on work profile flow, because it forces
318             // unlocking the work profile even before the profile is running.
319             // TODO: Remove the duplication of checkPassword and verifyPassword in
320             //  ConfirmLockPassword,
321             // LockPatternChecker and LockPatternUtils. verifyPassword should be the only API to
322             // use, which optionally accepts a challenge.
323             mForceVerifyPath = true;
324             if (isBiometricAllowed(effectiveUserId, mUserId)) {
325                 showBiometricPrompt(promptInfo, mUserId);
326                 launchedBiometric = true;
327             } else {
328                 showConfirmCredentials();
329                 launchedCDC = true;
330             }
331         } else if (android.os.Flags.allowPrivateProfile()
332                 && android.multiuser.Flags.enablePrivateSpaceFeatures()
333                 && userProperties != null
334                 && userProperties.isAuthAlwaysRequiredToDisableQuietMode()
335                 && isInternalActivity()) {
336             // Force verification path is required to be invoked as we might need to verify the
337             // tied profile challenge if the profile is using the unified challenge mode. This
338             // would result in ConfirmLockPassword.startVerifyPassword/
339             // ConfirmLockPattern.startVerifyPattern being called instead of the
340             // startCheckPassword/startCheckPattern
341             mForceVerifyPath = userProperties.isCredentialShareableWithParent();
342             if (android.multiuser.Flags.enableBiometricsToUnlockPrivateSpace()
343                     && isBiometricAllowed(effectiveUserId, mUserId)) {
344                 setBiometricPromptPropertiesForPrivateProfile(promptInfo);
345                 showBiometricPrompt(promptInfo, effectiveUserId);
346                 launchedBiometric = true;
347             } else {
348                 showConfirmCredentials();
349                 launchedCDC = true;
350             }
351         } else {
352             if (isBiometricAllowed(effectiveUserId, mUserId)) {
353                 // Don't need to check if biometrics / pin/pattern/pass are enrolled. It will go to
354                 // onAuthenticationError and do the right thing automatically.
355                 showBiometricPrompt(promptInfo, mUserId);
356                 launchedBiometric = true;
357             } else {
358                 showConfirmCredentials();
359                 launchedCDC = true;
360             }
361         }
362 
363         if (launchedCDC) {
364             finish();
365         } else if (launchedBiometric) {
366             // Keep this activity alive until BiometricPrompt goes away
367             mWaitingForBiometricCallback = true;
368         } else {
369             Log.d(TAG, "No pattern, password or PIN set.");
370             setResult(Activity.RESULT_OK);
371             finish();
372         }
373     }
374 
setBiometricPromptPropertiesForPrivateProfile(PromptInfo promptInfo)375     private static void setBiometricPromptPropertiesForPrivateProfile(PromptInfo promptInfo) {
376         promptInfo.setUseParentProfileForDeviceCredential(true);
377         promptInfo.setConfirmationRequested(false);
378     }
379 
getTitleFromCredentialType(@ockPatternUtils.CredentialType int credentialType, boolean isEffectiveUserManagedProfile)380     private String getTitleFromCredentialType(@LockPatternUtils.CredentialType int credentialType,
381             boolean isEffectiveUserManagedProfile) {
382         switch (credentialType) {
383             case LockPatternUtils.CREDENTIAL_TYPE_PIN:
384                 if (isEffectiveUserManagedProfile) {
385                     return mDevicePolicyManager.getResources().getString(
386                             CONFIRM_WORK_PROFILE_PIN_HEADER,
387                             () -> getString(R.string.lockpassword_confirm_your_work_pin_header));
388                 }
389 
390                 return getString(R.string.lockpassword_confirm_your_pin_header);
391             case LockPatternUtils.CREDENTIAL_TYPE_PATTERN:
392                 if (isEffectiveUserManagedProfile) {
393                     return mDevicePolicyManager.getResources().getString(
394                             CONFIRM_WORK_PROFILE_PATTERN_HEADER,
395                             () -> getString(
396                                     R.string.lockpassword_confirm_your_work_pattern_header));
397                 }
398 
399                 return getString(R.string.lockpassword_confirm_your_pattern_header);
400             case LockPatternUtils.CREDENTIAL_TYPE_PASSWORD:
401                 if (isEffectiveUserManagedProfile) {
402                     return mDevicePolicyManager.getResources().getString(
403                             CONFIRM_WORK_PROFILE_PASSWORD_HEADER,
404                             () -> getString(
405                                     R.string.lockpassword_confirm_your_work_password_header));
406                 }
407 
408                 return getString(R.string.lockpassword_confirm_your_password_header);
409         }
410         return null;
411     }
412 
413     @Override
onStart()414     protected void onStart() {
415         super.onStart();
416         // Translucent activity that is "visible", so it doesn't complain about finish()
417         // not being called before onResume().
418         setVisible(true);
419 
420         if ((getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK)
421                 != Configuration.UI_MODE_NIGHT_YES) {
422             getWindow().getInsetsController().setSystemBarsAppearance(
423                     APPEARANCE_LIGHT_STATUS_BARS, APPEARANCE_LIGHT_STATUS_BARS);
424         }
425     }
426 
427     @Override
onPause()428     public void onPause() {
429         super.onPause();
430         if (!isChangingConfigurations()) {
431             mGoingToBackground = true;
432             if (!mWaitingForBiometricCallback) {
433                 finish();
434             }
435         } else {
436             mGoingToBackground = false;
437         }
438     }
439 
440     /**
441      * Checks if the calling uid has the permission to set biometric dialog icon and description.
442      */
hasSetBiometricDialogAdvanced(@onNull Context context, int callingUid)443     private static boolean hasSetBiometricDialogAdvanced(@NonNull Context context, int callingUid) {
444         return context.checkPermission(SET_BIOMETRIC_DIALOG_ADVANCED, /* pid */ -1, callingUid)
445                 == PackageManager.PERMISSION_GRANTED;
446     }
447 
448     // User could be locked while Effective user is unlocked even though the effective owns the
449     // credential. Otherwise, biometric can't unlock fbe/keystore through
450     // verifyTiedProfileChallenge. In such case, we also wanna show the user message that
451     // biometric is disabled due to device restart.
isStrongAuthRequired(int effectiveUserId)452     private boolean isStrongAuthRequired(int effectiveUserId) {
453         return !mLockPatternUtils.isBiometricAllowedForUser(effectiveUserId)
454                 || doesUserStateEnforceStrongAuth(mUserId);
455     }
456 
doesUserStateEnforceStrongAuth(int userId)457     private boolean doesUserStateEnforceStrongAuth(int userId) {
458         if (android.os.Flags.allowPrivateProfile()
459                 && android.multiuser.Flags.enableBiometricsToUnlockPrivateSpace()
460                 && android.multiuser.Flags.enablePrivateSpaceFeatures()) {
461             // Check if CE storage for user is locked since biometrics can't unlock fbe/keystore of
462             // the profile user using verifyTiedProfileChallenge. Biometrics can still be used if
463             // the user is stopped with delayed locking (i.e., with storage unlocked), so the user
464             // state (whether the user is in the RUNNING_UNLOCKED state) should not be relied upon.
465             return !StorageManager.isCeStorageUnlocked(userId);
466         }
467         return !mUserManager.isUserUnlocked(userId);
468     }
469 
isBiometricAllowed(int effectiveUserId, int realUserId)470     private boolean isBiometricAllowed(int effectiveUserId, int realUserId) {
471         return !isStrongAuthRequired(effectiveUserId) && !mLockPatternUtils
472                 .hasPendingEscrowToken(realUserId);
473     }
474 
showBiometricPrompt(PromptInfo promptInfo, int userId)475     private void showBiometricPrompt(PromptInfo promptInfo, int userId) {
476         mBiometricFragment = (BiometricFragment) getSupportFragmentManager()
477                 .findFragmentByTag(TAG_BIOMETRIC_FRAGMENT);
478         boolean newFragment = false;
479 
480         if (mBiometricFragment == null) {
481             mBiometricFragment = BiometricFragment.newInstance(promptInfo,
482                     getCallingActivity());
483             newFragment = true;
484         }
485         mBiometricFragment.setCallbacks(mExecutor, mAuthenticationCallback);
486         // TODO(b/315864564): Move the logic of choosing the user id against which the
487         //  authentication needs to happen to the BiometricPrompt API
488         mBiometricFragment.setUser(userId);
489 
490         if (newFragment) {
491             getSupportFragmentManager().beginTransaction()
492                     .add(mBiometricFragment, TAG_BIOMETRIC_FRAGMENT).commit();
493         }
494     }
495 
496     /**
497      * Shows ConfirmDeviceCredentials for normal apps.
498      */
showConfirmCredentials()499     private void showConfirmCredentials() {
500         boolean launched = new ChooseLockSettingsHelper.Builder(this)
501                 .setHeader(mTitle)
502                 .setDescription(mDetails)
503                 .setExternal(true)
504                 .setUserId(mUserId)
505                 .setTaskOverlay(mTaskOverlay)
506                 .setForceVerifyPath(mForceVerifyPath)
507                 .show();
508 
509         if (!launched) {
510             Log.d(TAG, "No pin/pattern/pass set");
511             setResult(Activity.RESULT_OK);
512         }
513         finish();
514     }
515 
isInternalActivity()516     private boolean isInternalActivity() {
517         return this instanceof ConfirmDeviceCredentialActivity.InternalActivity;
518     }
519 
getTitleFromOrganizationName(int userId)520     private String getTitleFromOrganizationName(int userId) {
521         DevicePolicyManager dpm = (DevicePolicyManager) getSystemService(
522                 Context.DEVICE_POLICY_SERVICE);
523         CharSequence organizationNameForUser = (dpm != null)
524                 ? dpm.getOrganizationNameForUser(userId) : null;
525         return organizationNameForUser != null ? organizationNameForUser.toString() : null;
526     }
527 }
528