Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0ada0a60 authored by Philip P. Moltmann's avatar Philip P. Moltmann
Browse files

Change DevicePolicyManager APIs as requested

This requires RestrictedLockUtils to change which then causes further
changes.

I left the old APIs available for non-system-api customers.

Test: RunSettingsLibRoboTests
Bug: 116798569
Change-Id: Id5384ee074bb245e615012b7e0d5298b8bf27ba4
parent 421f1a15
Loading
Loading
Loading
Loading
+2 −3
Original line number Original line Diff line number Diff line
@@ -523,11 +523,11 @@ package android.app.admin {
    method public android.content.ComponentName getDeviceOwnerComponentOnAnyUser();
    method public android.content.ComponentName getDeviceOwnerComponentOnAnyUser();
    method public java.lang.String getDeviceOwnerNameOnAnyUser();
    method public java.lang.String getDeviceOwnerNameOnAnyUser();
    method public java.lang.CharSequence getDeviceOwnerOrganizationName();
    method public java.lang.CharSequence getDeviceOwnerOrganizationName();
    method public int getDeviceOwnerUserId();
    method public android.os.UserHandle getDeviceOwnerUser();
    method public java.util.List<java.lang.String> getPermittedAccessibilityServices(int);
    method public java.util.List<java.lang.String> getPermittedAccessibilityServices(int);
    method public java.util.List<java.lang.String> getPermittedInputMethodsForCurrentUser();
    method public java.util.List<java.lang.String> getPermittedInputMethodsForCurrentUser();
    method public android.content.ComponentName getProfileOwner() throws java.lang.IllegalArgumentException;
    method public android.content.ComponentName getProfileOwner() throws java.lang.IllegalArgumentException;
    method public android.content.ComponentName getProfileOwnerAsUser(int);
    method public android.content.ComponentName getProfileOwnerAsUser(android.os.UserHandle);
    method public java.lang.String getProfileOwnerNameAsUser(int) throws java.lang.IllegalArgumentException;
    method public java.lang.String getProfileOwnerNameAsUser(int) throws java.lang.IllegalArgumentException;
    method public int getUserProvisioningState();
    method public int getUserProvisioningState();
    method public boolean isDeviceManaged();
    method public boolean isDeviceManaged();
@@ -4132,7 +4132,6 @@ package android.os {
    field public static final android.os.UserHandle ALL;
    field public static final android.os.UserHandle ALL;
    field public static final android.os.UserHandle CURRENT;
    field public static final android.os.UserHandle CURRENT;
    field public static final android.os.UserHandle SYSTEM;
    field public static final android.os.UserHandle SYSTEM;
    field public static final int USER_NULL = -10000; // 0xffffd8f0
  }
  }


  public class UserManager {
  public class UserManager {
+33 −2
Original line number Original line Diff line number Diff line
@@ -5224,13 +5224,30 @@ public class DevicePolicyManager {
    }
    }


    /**
    /**
     * @return ID of the user who runs device owner, or {@link UserHandle#USER_NULL} if there's
     * @return Handle of the user who runs device owner, or {@code null} if there's no device owner.
     * no device owner.
     *
     *
     * @hide
     * @hide
     */
     */
    @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
    @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
    @SystemApi
    @SystemApi
    public @Nullable UserHandle getDeviceOwnerUser() {
        if (mService != null) {
            try {
                int userId = mService.getDeviceOwnerUserId();

                if (userId != UserHandle.USER_NULL) {
                    return UserHandle.of(userId);
                }
            } catch (RemoteException re) {
                throw re.rethrowFromSystemServer();
            }
        }
        return null;
    }

    /**
     * @hide
     */
    public int getDeviceOwnerUserId() {
    public int getDeviceOwnerUserId() {
        if (mService != null) {
        if (mService != null) {
            try {
            try {
@@ -5653,6 +5670,20 @@ public class DevicePolicyManager {
    @RequiresPermission(value = android.Manifest.permission.INTERACT_ACROSS_USERS,
    @RequiresPermission(value = android.Manifest.permission.INTERACT_ACROSS_USERS,
            conditional = true)
            conditional = true)
    @SystemApi
    @SystemApi
    public @Nullable ComponentName getProfileOwnerAsUser(@NonNull UserHandle user) {
        if (mService != null) {
            try {
                return mService.getProfileOwnerAsUser(user.getIdentifier());
            } catch (RemoteException re) {
                throw re.rethrowFromSystemServer();
            }
        }
        return null;
    }

    /**
     * @hide
     */
    public @Nullable ComponentName getProfileOwnerAsUser(final int userId) {
    public @Nullable ComponentName getProfileOwnerAsUser(final int userId) {
        if (mService != null) {
        if (mService != null) {
            try {
            try {
+0 −1
Original line number Original line Diff line number Diff line
@@ -61,7 +61,6 @@ public final class UserHandle implements Parcelable {
    public static final UserHandle CURRENT_OR_SELF = new UserHandle(USER_CURRENT_OR_SELF);
    public static final UserHandle CURRENT_OR_SELF = new UserHandle(USER_CURRENT_OR_SELF);


    /** @hide An undefined user id */
    /** @hide An undefined user id */
    @SystemApi
    public static final @UserIdInt int USER_NULL = -10000;
    public static final @UserIdInt int USER_NULL = -10000;


    /**
    /**
+23 −22
Original line number Original line Diff line number Diff line
@@ -33,13 +33,13 @@ import java.util.Objects;
 * support message dialog.
 * support message dialog.
 */
 */
public class RestrictedLockUtils {
public class RestrictedLockUtils {
    public static EnforcedAdmin getProfileOrDeviceOwner(Context context, int userId) {
    public static EnforcedAdmin getProfileOrDeviceOwner(Context context, UserHandle user) {
        return getProfileOrDeviceOwner(context, null, userId);
        return getProfileOrDeviceOwner(context, null, user);
    }
    }


    public static EnforcedAdmin getProfileOrDeviceOwner(
    public static EnforcedAdmin getProfileOrDeviceOwner(
            Context context, String enforcedRestriction, int userId) {
            Context context, String enforcedRestriction, UserHandle user) {
        if (userId == UserHandle.USER_NULL) {
        if (user == null) {
            return null;
            return null;
        }
        }
        final DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(
        final DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(
@@ -47,14 +47,14 @@ public class RestrictedLockUtils {
        if (dpm == null) {
        if (dpm == null) {
            return null;
            return null;
        }
        }
        ComponentName adminComponent = dpm.getProfileOwnerAsUser(userId);
        ComponentName adminComponent = dpm.getProfileOwnerAsUser(user);
        if (adminComponent != null) {
        if (adminComponent != null) {
            return new EnforcedAdmin(adminComponent, enforcedRestriction, userId);
            return new EnforcedAdmin(adminComponent, enforcedRestriction, user);
        }
        }
        if (dpm.getDeviceOwnerUserId() == userId) {
        if (Objects.equals(dpm.getDeviceOwnerUser(), user)) {
            adminComponent = dpm.getDeviceOwnerComponentOnAnyUser();
            adminComponent = dpm.getDeviceOwnerComponentOnAnyUser();
            if (adminComponent != null) {
            if (adminComponent != null) {
                return new EnforcedAdmin(adminComponent, enforcedRestriction, userId);
                return new EnforcedAdmin(adminComponent, enforcedRestriction, user);
            }
            }
        }
        }
        return null;
        return null;
@@ -66,9 +66,9 @@ public class RestrictedLockUtils {
    public static void sendShowAdminSupportDetailsIntent(Context context, EnforcedAdmin admin) {
    public static void sendShowAdminSupportDetailsIntent(Context context, EnforcedAdmin admin) {
        final Intent intent = getShowAdminSupportDetailsIntent(context, admin);
        final Intent intent = getShowAdminSupportDetailsIntent(context, admin);
        int targetUserId = UserHandle.myUserId();
        int targetUserId = UserHandle.myUserId();
        if (admin != null && admin.userId != UserHandle.USER_NULL
        if (admin != null && admin.user != null
                && isCurrentUserOrProfile(context, admin.userId)) {
                && isCurrentUserOrProfile(context, admin.user.getIdentifier())) {
            targetUserId = admin.userId;
            targetUserId = admin.user.getIdentifier();
        }
        }
        intent.putExtra(DevicePolicyManager.EXTRA_RESTRICTION, admin.enforcedRestriction);
        intent.putExtra(DevicePolicyManager.EXTRA_RESTRICTION, admin.enforcedRestriction);
        context.startActivityAsUser(intent, UserHandle.of(targetUserId));
        context.startActivityAsUser(intent, UserHandle.of(targetUserId));
@@ -81,8 +81,8 @@ public class RestrictedLockUtils {
                intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, admin.component);
                intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, admin.component);
            }
            }
            int adminUserId = UserHandle.myUserId();
            int adminUserId = UserHandle.myUserId();
            if (admin.userId != UserHandle.USER_NULL) {
            if (admin.user != null) {
                adminUserId = admin.userId;
                adminUserId = admin.user.getIdentifier();
            }
            }
            intent.putExtra(Intent.EXTRA_USER_ID, adminUserId);
            intent.putExtra(Intent.EXTRA_USER_ID, adminUserId);
        }
        }
@@ -109,7 +109,8 @@ public class RestrictedLockUtils {
         */
         */
        @Nullable
        @Nullable
        public String enforcedRestriction = null;
        public String enforcedRestriction = null;
        public int userId = UserHandle.USER_NULL;
        @Nullable
        public UserHandle user = null;


        // We use this to represent the case where a policy is enforced by multiple admins.
        // We use this to represent the case where a policy is enforced by multiple admins.
        public final static EnforcedAdmin MULTIPLE_ENFORCED_ADMIN = new EnforcedAdmin();
        public final static EnforcedAdmin MULTIPLE_ENFORCED_ADMIN = new EnforcedAdmin();
@@ -121,15 +122,15 @@ public class RestrictedLockUtils {
            return enforcedAdmin;
            return enforcedAdmin;
        }
        }


        public EnforcedAdmin(ComponentName component, int userId) {
        public EnforcedAdmin(ComponentName component, UserHandle user) {
            this.component = component;
            this.component = component;
            this.userId = userId;
            this.user = user;
        }
        }


        public EnforcedAdmin(ComponentName component, String enforcedRestriction, int userId) {
        public EnforcedAdmin(ComponentName component, String enforcedRestriction, UserHandle user) {
            this.component = component;
            this.component = component;
            this.enforcedRestriction = enforcedRestriction;
            this.enforcedRestriction = enforcedRestriction;
            this.userId = userId;
            this.user = user;
        }
        }


        public EnforcedAdmin(EnforcedAdmin other) {
        public EnforcedAdmin(EnforcedAdmin other) {
@@ -138,7 +139,7 @@ public class RestrictedLockUtils {
            }
            }
            this.component = other.component;
            this.component = other.component;
            this.enforcedRestriction = other.enforcedRestriction;
            this.enforcedRestriction = other.enforcedRestriction;
            this.userId = other.userId;
            this.user = other.user;
        }
        }


        public EnforcedAdmin() {
        public EnforcedAdmin() {
@@ -149,14 +150,14 @@ public class RestrictedLockUtils {
            if (this == o) return true;
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            if (o == null || getClass() != o.getClass()) return false;
            EnforcedAdmin that = (EnforcedAdmin) o;
            EnforcedAdmin that = (EnforcedAdmin) o;
            return userId == that.userId &&
            return Objects.equals(user, that.user) &&
                    Objects.equals(component, that.component) &&
                    Objects.equals(component, that.component) &&
                    Objects.equals(enforcedRestriction, that.enforcedRestriction);
                    Objects.equals(enforcedRestriction, that.enforcedRestriction);
        }
        }


        @Override
        @Override
        public int hashCode() {
        public int hashCode() {
            return Objects.hash(component, enforcedRestriction, userId);
            return Objects.hash(component, enforcedRestriction, user);
        }
        }


        @Override
        @Override
@@ -164,7 +165,7 @@ public class RestrictedLockUtils {
            return "EnforcedAdmin{" +
            return "EnforcedAdmin{" +
                    "component=" + component +
                    "component=" + component +
                    ", enforcedRestriction='" + enforcedRestriction +
                    ", enforcedRestriction='" + enforcedRestriction +
                    ", userId=" + userId +
                    ", user=" + user +
                    '}';
                    '}';
        }
        }
    }
    }
+33 −15
Original line number Original line Diff line number Diff line
@@ -163,6 +163,17 @@ public class RestrictedLockUtilsInternal extends RestrictedLockUtils {
        return checkForLockSetting(context, userId, check);
        return checkForLockSetting(context, userId, check);
    }
    }


    /**
     * @return the UserHandle for a userId. Return null for USER_NULL
     */
    private static UserHandle getUserHandleOf(@UserIdInt int userId) {
        if (userId == UserHandle.USER_NULL) {
            return null;
        } else {
            return UserHandle.of(userId);
        }
    }

    /**
    /**
     * Filter a set of device admins based on a predicate {@code check}. This is equivalent to
     * Filter a set of device admins based on a predicate {@code check}. This is equivalent to
     * {@code admins.stream().filter(check).map(x → new EnforcedAdmin(admin, userId)} except it's
     * {@code admins.stream().filter(check).map(x → new EnforcedAdmin(admin, userId)} except it's
@@ -183,11 +194,13 @@ public class RestrictedLockUtilsInternal extends RestrictedLockUtils {
        if (admins == null) {
        if (admins == null) {
            return null;
            return null;
        }
        }

        final UserHandle user = getUserHandleOf(userId);
        EnforcedAdmin enforcedAdmin = null;
        EnforcedAdmin enforcedAdmin = null;
        for (ComponentName admin : admins) {
        for (ComponentName admin : admins) {
            if (check.isEnforcing(dpm, admin, userId)) {
            if (check.isEnforcing(dpm, admin, userId)) {
                if (enforcedAdmin == null) {
                if (enforcedAdmin == null) {
                    enforcedAdmin = new EnforcedAdmin(admin, userId);
                    enforcedAdmin = new EnforcedAdmin(admin, user);
                } else {
                } else {
                    return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN;
                    return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN;
                }
                }
@@ -211,7 +224,7 @@ public class RestrictedLockUtilsInternal extends RestrictedLockUtils {
        IPackageManager ipm = AppGlobals.getPackageManager();
        IPackageManager ipm = AppGlobals.getPackageManager();
        try {
        try {
            if (ipm.getBlockUninstallForUser(packageName, userId)) {
            if (ipm.getBlockUninstallForUser(packageName, userId)) {
                return getProfileOrDeviceOwner(context, userId);
                return getProfileOrDeviceOwner(context, getUserHandleOf(userId));
            }
            }
        } catch (RemoteException e) {
        } catch (RemoteException e) {
            // Nothing to do
            // Nothing to do
@@ -230,7 +243,7 @@ public class RestrictedLockUtilsInternal extends RestrictedLockUtils {
        IPackageManager ipm = AppGlobals.getPackageManager();
        IPackageManager ipm = AppGlobals.getPackageManager();
        try {
        try {
            if (ipm.isPackageSuspendedForUser(packageName, userId)) {
            if (ipm.isPackageSuspendedForUser(packageName, userId)) {
                return getProfileOrDeviceOwner(context, userId);
                return getProfileOrDeviceOwner(context, getUserHandleOf(userId));
            }
            }
        } catch (RemoteException | IllegalArgumentException e) {
        } catch (RemoteException | IllegalArgumentException e) {
            // Nothing to do
            // Nothing to do
@@ -245,14 +258,15 @@ public class RestrictedLockUtilsInternal extends RestrictedLockUtils {
        if (dpm == null) {
        if (dpm == null) {
            return null;
            return null;
        }
        }
        EnforcedAdmin admin = getProfileOrDeviceOwner(context, userId);
        EnforcedAdmin admin = getProfileOrDeviceOwner(context, getUserHandleOf(userId));
        boolean permitted = true;
        boolean permitted = true;
        if (admin != null) {
        if (admin != null) {
            permitted = dpm.isInputMethodPermittedByAdmin(admin.component,
            permitted = dpm.isInputMethodPermittedByAdmin(admin.component,
                    packageName, userId);
                    packageName, userId);
        }
        }
        int managedProfileId = getManagedProfileId(context, userId);
        int managedProfileId = getManagedProfileId(context, userId);
        EnforcedAdmin profileAdmin = getProfileOrDeviceOwner(context, managedProfileId);
        EnforcedAdmin profileAdmin = getProfileOrDeviceOwner(context,
                getUserHandleOf(managedProfileId));
        boolean permittedByProfileAdmin = true;
        boolean permittedByProfileAdmin = true;
        if (profileAdmin != null) {
        if (profileAdmin != null) {
            permittedByProfileAdmin = dpm.isInputMethodPermittedByAdmin(profileAdmin.component,
            permittedByProfileAdmin = dpm.isInputMethodPermittedByAdmin(profileAdmin.component,
@@ -298,14 +312,15 @@ public class RestrictedLockUtilsInternal extends RestrictedLockUtils {
        if (dpm == null) {
        if (dpm == null) {
            return null;
            return null;
        }
        }
        EnforcedAdmin admin = getProfileOrDeviceOwner(context, userId);
        EnforcedAdmin admin = getProfileOrDeviceOwner(context, getUserHandleOf(userId));
        boolean permitted = true;
        boolean permitted = true;
        if (admin != null) {
        if (admin != null) {
            permitted = dpm.isAccessibilityServicePermittedByAdmin(admin.component,
            permitted = dpm.isAccessibilityServicePermittedByAdmin(admin.component,
                    packageName, userId);
                    packageName, userId);
        }
        }
        int managedProfileId = getManagedProfileId(context, userId);
        int managedProfileId = getManagedProfileId(context, userId);
        EnforcedAdmin profileAdmin = getProfileOrDeviceOwner(context, managedProfileId);
        EnforcedAdmin profileAdmin = getProfileOrDeviceOwner(context,
                getUserHandleOf(managedProfileId));
        boolean permittedByProfileAdmin = true;
        boolean permittedByProfileAdmin = true;
        if (profileAdmin != null) {
        if (profileAdmin != null) {
            permittedByProfileAdmin = dpm.isAccessibilityServicePermittedByAdmin(
            permittedByProfileAdmin = dpm.isAccessibilityServicePermittedByAdmin(
@@ -365,7 +380,7 @@ public class RestrictedLockUtilsInternal extends RestrictedLockUtils {
        if (!isAccountTypeDisabled) {
        if (!isAccountTypeDisabled) {
            return null;
            return null;
        }
        }
        return getProfileOrDeviceOwner(context, userId);
        return getProfileOrDeviceOwner(context, getUserHandleOf(userId));
    }
    }


    /**
    /**
@@ -377,7 +392,8 @@ public class RestrictedLockUtilsInternal extends RestrictedLockUtils {
     */
     */
    public static EnforcedAdmin checkIfMeteredDataRestricted(Context context,
    public static EnforcedAdmin checkIfMeteredDataRestricted(Context context,
            String packageName, int userId) {
            String packageName, int userId) {
        final EnforcedAdmin enforcedAdmin = getProfileOrDeviceOwner(context, userId);
        final EnforcedAdmin enforcedAdmin = getProfileOrDeviceOwner(context,
                getUserHandleOf(userId));
        if (enforcedAdmin == null) {
        if (enforcedAdmin == null) {
            return null;
            return null;
        }
        }
@@ -402,7 +418,7 @@ public class RestrictedLockUtilsInternal extends RestrictedLockUtils {
            return null;
            return null;
        }
        }
        ComponentName adminComponent = dpm.getDeviceOwnerComponentOnCallingUser();
        ComponentName adminComponent = dpm.getDeviceOwnerComponentOnCallingUser();
        return new EnforcedAdmin(adminComponent, UserHandle.myUserId());
        return new EnforcedAdmin(adminComponent, getUserHandleOf(UserHandle.myUserId()));
    }
    }


    /**
    /**
@@ -434,10 +450,11 @@ public class RestrictedLockUtilsInternal extends RestrictedLockUtils {
                return null;
                return null;
            }
            }
            EnforcedAdmin enforcedAdmin = null;
            EnforcedAdmin enforcedAdmin = null;
            final UserHandle user = getUserHandleOf(userId);
            for (ComponentName admin : admins) {
            for (ComponentName admin : admins) {
                if (check.isEnforcing(dpm, admin, userId)) {
                if (check.isEnforcing(dpm, admin, userId)) {
                    if (enforcedAdmin == null) {
                    if (enforcedAdmin == null) {
                        enforcedAdmin = new EnforcedAdmin(admin, userId);
                        enforcedAdmin = new EnforcedAdmin(admin, user);
                    } else {
                    } else {
                        return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN;
                        return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN;
                    }
                    }
@@ -488,13 +505,14 @@ public class RestrictedLockUtilsInternal extends RestrictedLockUtils {
            if (admins == null) {
            if (admins == null) {
                continue;
                continue;
            }
            }
            final UserHandle user = getUserHandleOf(userInfo.id);
            final boolean isSeparateProfileChallengeEnabled =
            final boolean isSeparateProfileChallengeEnabled =
                    sProxy.isSeparateProfileChallengeEnabled(lockPatternUtils, userInfo.id);
                    sProxy.isSeparateProfileChallengeEnabled(lockPatternUtils, userInfo.id);
            for (ComponentName admin : admins) {
            for (ComponentName admin : admins) {
                if (!isSeparateProfileChallengeEnabled) {
                if (!isSeparateProfileChallengeEnabled) {
                    if (check.isEnforcing(dpm, admin, userInfo.id)) {
                    if (check.isEnforcing(dpm, admin, userInfo.id)) {
                        if (enforcedAdmin == null) {
                        if (enforcedAdmin == null) {
                            enforcedAdmin = new EnforcedAdmin(admin, userInfo.id);
                            enforcedAdmin = new EnforcedAdmin(admin, user);
                        } else {
                        } else {
                            return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN;
                            return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN;
                        }
                        }
@@ -511,7 +529,7 @@ public class RestrictedLockUtilsInternal extends RestrictedLockUtils {
                    DevicePolicyManager parentDpm = sProxy.getParentProfileInstance(dpm, userInfo);
                    DevicePolicyManager parentDpm = sProxy.getParentProfileInstance(dpm, userInfo);
                    if (check.isEnforcing(parentDpm, admin, userInfo.id)) {
                    if (check.isEnforcing(parentDpm, admin, userInfo.id)) {
                        if (enforcedAdmin == null) {
                        if (enforcedAdmin == null) {
                            enforcedAdmin = new EnforcedAdmin(admin, userInfo.id);
                            enforcedAdmin = new EnforcedAdmin(admin, user);
                        } else {
                        } else {
                            return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN;
                            return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN;
                        }
                        }
@@ -535,7 +553,7 @@ public class RestrictedLockUtilsInternal extends RestrictedLockUtils {
        ComponentName adminComponent = dpm.getDeviceOwnerComponentOnAnyUser();
        ComponentName adminComponent = dpm.getDeviceOwnerComponentOnAnyUser();
        if (adminComponent != null) {
        if (adminComponent != null) {
            return new EnforcedAdmin(
            return new EnforcedAdmin(
                    adminComponent, enforcedRestriction, dpm.getDeviceOwnerUserId());
                    adminComponent, enforcedRestriction, dpm.getDeviceOwnerUser());
        }
        }
        return null;
        return null;
    }
    }
@@ -556,7 +574,7 @@ public class RestrictedLockUtilsInternal extends RestrictedLockUtils {
        }
        }
        ComponentName adminComponent = dpm.getProfileOwnerAsUser(userId);
        ComponentName adminComponent = dpm.getProfileOwnerAsUser(userId);
        if (adminComponent != null) {
        if (adminComponent != null) {
            return new EnforcedAdmin(adminComponent, enforcedRestriction, userId);
            return new EnforcedAdmin(adminComponent, enforcedRestriction, getUserHandleOf(userId));
        }
        }
        return null;
        return null;
    }
    }
Loading