diff options
| author | 2024-04-03 16:32:31 +0000 | |
|---|---|---|
| committer | 2024-06-17 10:58:27 +0000 | |
| commit | cf700c6d443d2f4f99edec4b16bc113ea3361123 (patch) | |
| tree | 7e889d6c54d0c9044ad5c34cb738d02e2ba6addd | |
| parent | 8d9d7e2a5d999853ec432308b7509f75b5d37df0 (diff) | |
Populate management mode in the device policy atom
Bug: 293091314
Test: tested with statsd_testdrive <ATOM_ID>
Flag: android.app.admin.flags.management_mode_policy_metrics
Change-Id: I08aff645c77529eb19216861dca8a067652422b3
3 files changed, 157 insertions, 2 deletions
diff --git a/core/java/android/app/admin/flags/flags.aconfig b/core/java/android/app/admin/flags/flags.aconfig index 7d5806a294e0..82271129c69e 100644 --- a/core/java/android/app/admin/flags/flags.aconfig +++ b/core/java/android/app/admin/flags/flags.aconfig @@ -383,3 +383,13 @@ flag {      purpose: PURPOSE_BUGFIX    }  } + +flag { +    name: "management_mode_policy_metrics" +    namespace: "enterprise" +    description: "Enabling management mode and password complexity policy metrics collection" +    bug: "293091314" +    metadata { +        purpose: PURPOSE_BUGFIX +    } +} diff --git a/services/devicepolicy/Android.bp b/services/devicepolicy/Android.bp index da965bb02460..32b571a8ee69 100644 --- a/services/devicepolicy/Android.bp +++ b/services/devicepolicy/Android.bp @@ -17,8 +17,10 @@ filegroup {  java_library_static {      name: "services.devicepolicy",      defaults: ["platform_service_defaults"], -    srcs: [":services.devicepolicy-sources"], - +    srcs: [ +        ":services.devicepolicy-sources", +        ":statslog-devicepolicy-java-gen", +    ],      libs: [          "services.core",          "app-compat-annotations", @@ -27,3 +29,11 @@ java_library_static {          "androidx.annotation_annotation",      ],  } + +genrule { +    name: "statslog-devicepolicy-java-gen", +    tools: ["stats-log-api-gen"], +    cmd: "$(location stats-log-api-gen) --java $(out) --module devicepolicy" + +        " --javaPackage com.android.server.devicepolicy --javaClass DevicePolicyStatsLog", +    out: ["com/android/server/devicepolicy/DevicePolicyStatsLog.java"], +} diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index e8204e0434c3..43a2a931f31f 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -109,6 +109,7 @@ import static android.app.AppOpsManager.OPSTR_SYSTEM_EXEMPT_FROM_POWER_RESTRICTI  import static android.app.AppOpsManager.OPSTR_SYSTEM_EXEMPT_FROM_SUSPENSION;  import static android.app.AppOpsManager.OP_RUN_ANY_IN_BACKGROUND;  import static android.app.AppOpsManager.OP_RUN_IN_BACKGROUND; +import static android.app.StatsManager.PULL_SUCCESS;  import static android.app.admin.DeviceAdminInfo.HEADLESS_DEVICE_OWNER_MODE_AFFILIATED;  import static android.app.admin.DeviceAdminInfo.HEADLESS_DEVICE_OWNER_MODE_SINGLE_USER;  import static android.app.admin.DeviceAdminInfo.HEADLESS_DEVICE_OWNER_MODE_UNSUPPORTED; @@ -265,12 +266,26 @@ import static android.provider.Telephony.Carriers.INVALID_APN_ID;  import static android.security.keystore.AttestationUtils.USE_INDIVIDUAL_ATTESTATION;  import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PROVISIONING_ENTRY_POINT_ADB; +import static com.android.internal.util.ConcurrentUtils.DIRECT_EXECUTOR;  import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_NONE;  import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_ADAPTIVE_AUTH_REQUEST;  import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW;  import static com.android.server.SystemTimeZone.TIME_ZONE_CONFIDENCE_HIGH;  import static com.android.server.am.ActivityManagerService.STOCK_PM_FLAGS;  import static com.android.server.devicepolicy.DevicePolicyEngine.DEFAULT_POLICY_SIZE_LIMIT; +import static com.android.server.devicepolicy.DevicePolicyStatsLog.DEVICE_POLICY_MANAGEMENT_MODE; +import static com.android.server.devicepolicy.DevicePolicyStatsLog.DEVICE_POLICY_MANAGEMENT_MODE__MANAGEMENT_MODE__COPE; +import static com.android.server.devicepolicy.DevicePolicyStatsLog.DEVICE_POLICY_MANAGEMENT_MODE__MANAGEMENT_MODE__DEVICE_OWNER; +import static com.android.server.devicepolicy.DevicePolicyStatsLog.DEVICE_POLICY_MANAGEMENT_MODE__MANAGEMENT_MODE__DEVICE_OWNER_FINANCED; +import static com.android.server.devicepolicy.DevicePolicyStatsLog.DEVICE_POLICY_MANAGEMENT_MODE__MANAGEMENT_MODE__MANAGEMENT_MODE_UNSPECIFIED; +import static com.android.server.devicepolicy.DevicePolicyStatsLog.DEVICE_POLICY_MANAGEMENT_MODE__MANAGEMENT_MODE__PROFILE_OWNER; +import static com.android.server.devicepolicy.DevicePolicyStatsLog.DEVICE_POLICY_STATE; +import static com.android.server.devicepolicy.DevicePolicyStatsLog.DEVICE_POLICY_STATE__PASSWORD_COMPLEXITY__COMPLEXITY_HIGH; +import static com.android.server.devicepolicy.DevicePolicyStatsLog.DEVICE_POLICY_STATE__PASSWORD_COMPLEXITY__COMPLEXITY_LEGACY; +import static com.android.server.devicepolicy.DevicePolicyStatsLog.DEVICE_POLICY_STATE__PASSWORD_COMPLEXITY__COMPLEXITY_LOW; +import static com.android.server.devicepolicy.DevicePolicyStatsLog.DEVICE_POLICY_STATE__PASSWORD_COMPLEXITY__COMPLEXITY_MEDIUM; +import static com.android.server.devicepolicy.DevicePolicyStatsLog.DEVICE_POLICY_STATE__PASSWORD_COMPLEXITY__COMPLEXITY_NONE; +import static com.android.server.devicepolicy.DevicePolicyStatsLog.DEVICE_POLICY_STATE__PASSWORD_COMPLEXITY__COMPLEXITY_UNSPECIFIED;  import static com.android.server.devicepolicy.TransferOwnershipMetadataManager.ADMIN_TYPE_DEVICE_OWNER;  import static com.android.server.devicepolicy.TransferOwnershipMetadataManager.ADMIN_TYPE_PROFILE_OWNER;  import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME; @@ -305,6 +320,7 @@ import android.app.IServiceConnection;  import android.app.Notification;  import android.app.NotificationManager;  import android.app.PendingIntent; +import android.app.StatsManager;  import android.app.StatusBarManager;  import android.app.admin.AccountTypePolicyKey;  import android.app.admin.BooleanPolicyValue; @@ -477,6 +493,7 @@ import android.util.IntArray;  import android.util.Pair;  import android.util.Slog;  import android.util.SparseArray; +import android.util.StatsEvent;  import android.util.Xml;  import android.view.IWindowManager;  import android.view.accessibility.AccessibilityManager; @@ -3348,6 +3365,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {                  synchronized (getLockObject()) {                      mDevicePolicyEngine.reapplyAllPoliciesOnBootLocked();                  } +                if (Flags.managementModePolicyMetrics()) { +                    registerStatsCallbacks(); +                }                  break;              case SystemService.PHASE_ACTIVITY_MANAGER_READY:                  synchronized (getLockObject()) { @@ -3487,6 +3507,121 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {          return true;      } +    /** Register callbacks for statsd pulled atoms. */ +    private void registerStatsCallbacks() { +        final StatsManager statsManager = mContext.getSystemService(StatsManager.class); +        if (statsManager == null) { +            Slog.wtf(LOG_TAG, "StatsManager system service not found."); +            return; +        } +        statsManager.setPullAtomCallback( +                DEVICE_POLICY_MANAGEMENT_MODE, +                null, // use defaultPullAtomMetadata values +                DIRECT_EXECUTOR, +                this::onPullManagementModeAtom); +        statsManager.setPullAtomCallback( +                DEVICE_POLICY_STATE, +                null, // use defaultPullAtomMetadata values +                DIRECT_EXECUTOR, +                this::onPullPolicyStateAtom); +    } + +    /** Writes the pulled atoms. */ +    private int onPullManagementModeAtom(int atomTag, List<StatsEvent> statsEvents) { +        synchronized (getLockObject()) { +            statsEvents.add(DevicePolicyStatsLog.buildStatsEvent( +                    DEVICE_POLICY_MANAGEMENT_MODE, +                    getStatsManagementModeLocked().managementMode())); +            return PULL_SUCCESS; +        } +    } + +    /** Writes the pulled atoms. */ +    private int onPullPolicyStateAtom(int atomTag, List<StatsEvent> statsEvents) { +        synchronized (getLockObject()) { +            StatsManagementMode statsManagementMode = getStatsManagementModeLocked(); +            if (statsManagementMode.admin() != null) { +                statsEvents.add(DevicePolicyStatsLog.buildStatsEvent(DEVICE_POLICY_STATE, +                        getRequiredPasswordComplexityStatsLocked(statsManagementMode.admin()), +                        statsManagementMode.managementMode() +                        )); +            } else { +                statsEvents.add(DevicePolicyStatsLog.buildStatsEvent(DEVICE_POLICY_STATE, +                        DEVICE_POLICY_STATE__PASSWORD_COMPLEXITY__COMPLEXITY_NONE, +                        DEVICE_POLICY_MANAGEMENT_MODE__MANAGEMENT_MODE__MANAGEMENT_MODE_UNSPECIFIED +                )); +            } +            return PULL_SUCCESS; +        } +    } + +    private StatsManagementMode getStatsManagementModeLocked() { +        int managementMode = +                DEVICE_POLICY_MANAGEMENT_MODE__MANAGEMENT_MODE__MANAGEMENT_MODE_UNSPECIFIED; +        ActiveAdmin admin = getDeviceOwnerAdminLocked(); +        if (admin != null) { +            managementMode = getDeviceOwnerTypeLocked( +                    getDeviceOwnerComponent(false).getPackageName()) +                    != DEVICE_OWNER_TYPE_FINANCED +                    ? DEVICE_POLICY_MANAGEMENT_MODE__MANAGEMENT_MODE__DEVICE_OWNER +                    : DEVICE_POLICY_MANAGEMENT_MODE__MANAGEMENT_MODE__DEVICE_OWNER_FINANCED; +        } else { +            // Find the first user with managing_app. +            for (Integer profileUserId : mOwners.getProfileOwnerKeys()) { +                if (isManagedProfile(profileUserId)) { +                    admin = getProfileOwnerAdminLocked(profileUserId); +                    managementMode = mOwners.isProfileOwnerOfOrganizationOwnedDevice( +                            profileUserId) +                            ? DEVICE_POLICY_MANAGEMENT_MODE__MANAGEMENT_MODE__COPE +                            : DEVICE_POLICY_MANAGEMENT_MODE__MANAGEMENT_MODE__PROFILE_OWNER; +                    break; +                } +            } +        } +        return new StatsManagementMode(managementMode, admin); +    } + +    private record StatsManagementMode(int managementMode, ActiveAdmin admin) { +    } + +    @GuardedBy("getLockObject()") +    private int getRequiredPasswordComplexityStatsLocked(ActiveAdmin admin) { +        int userId = admin.getUserHandle().getIdentifier(); +        EnforcingAdmin enforcingAdmin = EnforcingAdmin.createEnterpriseEnforcingAdmin( +                admin.info.getComponent(), +                userId, +                admin); + +        Integer passwordComplexity = mDevicePolicyEngine.getLocalPolicySetByAdmin( +                PolicyDefinition.PASSWORD_COMPLEXITY, +                enforcingAdmin, +                userId); +        if (passwordComplexity == null) { +            return admin.mPasswordPolicy.quality != PASSWORD_QUALITY_UNSPECIFIED +                    ? DEVICE_POLICY_STATE__PASSWORD_COMPLEXITY__COMPLEXITY_LEGACY +                    : DEVICE_POLICY_STATE__PASSWORD_COMPLEXITY__COMPLEXITY_UNSPECIFIED; +        } +        switch (passwordComplexity) { +            case PASSWORD_COMPLEXITY_NONE -> { +                return DEVICE_POLICY_STATE__PASSWORD_COMPLEXITY__COMPLEXITY_NONE; +            } +            case PASSWORD_COMPLEXITY_LOW -> { +                return DEVICE_POLICY_STATE__PASSWORD_COMPLEXITY__COMPLEXITY_LOW; +            } +            case PASSWORD_COMPLEXITY_MEDIUM -> { +                return DEVICE_POLICY_STATE__PASSWORD_COMPLEXITY__COMPLEXITY_MEDIUM; +            } +            case PASSWORD_COMPLEXITY_HIGH -> { +                return DEVICE_POLICY_STATE__PASSWORD_COMPLEXITY__COMPLEXITY_HIGH; +            } +            default -> { +                Slogf.wtf(LOG_TAG, "Unhandled password complexity: " + passwordComplexity); +                // The following line is unreachable as Slogf.wtf crashes the process. +                // But we need this to avoid compilation error missing return statement. +                return DEVICE_POLICY_STATE__PASSWORD_COMPLEXITY__COMPLEXITY_UNSPECIFIED; +            } +        } +    }      private void applyManagedSubscriptionsPolicyIfRequired() {          int copeProfileUserId = getOrganizationOwnedProfileUserId();  |