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

Commit e341344b authored by Jason Hsu's avatar Jason Hsu Committed by Android (Google) Code Review
Browse files

Merge "Log accessibility floating menu stats and accessibility shortcut stats." into sc-v2-dev

parents 4252eccb bef0fa76
Loading
Loading
Loading
Loading
+166 −0
Original line number Diff line number Diff line
@@ -67,6 +67,7 @@ import static java.util.concurrent.TimeUnit.MICROSECONDS;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.ActivityManagerInternal;
import android.app.AppOpsManager;
import android.app.AppOpsManager.HistoricalOp;
@@ -82,6 +83,7 @@ import android.app.StatsManager.PullAtomMetadata;
import android.bluetooth.BluetoothActivityEnergyInfo;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.UidTraffic;
import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
@@ -734,6 +736,10 @@ public class StatsPullAtomService extends SystemService {
                    case FrameworkStatsLog.RKP_ERROR_STATS:
                    case FrameworkStatsLog.KEYSTORE2_CRASH_STATS:
                        return pullKeystoreAtoms(atomTag, data);
                    case FrameworkStatsLog.ACCESSIBILITY_SHORTCUT_STATS:
                        return pullAccessibilityShortcutStatsLocked(atomTag, data);
                    case FrameworkStatsLog.ACCESSIBILITY_FLOATING_MENU_STATS:
                        return pullAccessibilityFloatingMenuStatsLocked(atomTag, data);
                    default:
                        throw new UnsupportedOperationException("Unknown tagId=" + atomTag);
                }
@@ -930,6 +936,8 @@ public class StatsPullAtomService extends SystemService {
        registerKeystoreKeyOperationWithGeneralInfo();
        registerRkpErrorStats();
        registerKeystoreCrashStats();
        registerAccessibilityShortcutStats();
        registerAccessibilityFloatingMenuStats();
    }

    private void initAndRegisterNetworkStatsPullers() {
@@ -4150,6 +4158,26 @@ public class StatsPullAtomService extends SystemService {
                mStatsCallbackImpl);
    }

    private void registerAccessibilityShortcutStats() {
        int tagId = FrameworkStatsLog.ACCESSIBILITY_SHORTCUT_STATS;
        mStatsManager.setPullAtomCallback(
                tagId,
                null, // use default PullAtomMetadata values
                DIRECT_EXECUTOR,
                mStatsCallbackImpl
        );
    }

    private void registerAccessibilityFloatingMenuStats() {
        int tagId = FrameworkStatsLog.ACCESSIBILITY_FLOATING_MENU_STATS;
        mStatsManager.setPullAtomCallback(
                tagId,
                null, // use default PullAtomMetadata values
                DIRECT_EXECUTOR,
                mStatsCallbackImpl
        );
    }

    int parseKeystoreStorageStats(KeystoreAtom[] atoms, List<StatsEvent> pulledData) {
        for (KeystoreAtom atomWrapper : atoms) {
            if (atomWrapper.payload.getTag() != KeystoreAtomPayload.storageStats) {
@@ -4341,6 +4369,144 @@ public class StatsPullAtomService extends SystemService {
        }
    }

    int pullAccessibilityShortcutStatsLocked(int atomTag, List<StatsEvent> pulledData) {
        UserManager userManager = mContext.getSystemService(UserManager.class);
        if (userManager == null) {
            return StatsManager.PULL_SKIP;
        }
        final long token = Binder.clearCallingIdentity();
        try {
            final ContentResolver resolver = mContext.getContentResolver();
            final int hardware_shortcut_type =
                    FrameworkStatsLog.ACCESSIBILITY_SHORTCUT_REPORTED__SHORTCUT_TYPE__VOLUME_KEY;
            final int triple_tap_shortcut =
                    FrameworkStatsLog.ACCESSIBILITY_SHORTCUT_REPORTED__SHORTCUT_TYPE__TRIPLE_TAP;
            for (UserInfo userInfo : userManager.getUsers()) {
                final int userId = userInfo.getUserHandle().getIdentifier();

                if (isAccessibilityShortcutUser(mContext, userId)) {
                    final int software_shortcut_type = Settings.Secure.getIntForUser(resolver,
                            Settings.Secure.ACCESSIBILITY_BUTTON_MODE, 0, userId);
                    final String software_shortcut_list = Settings.Secure.getStringForUser(resolver,
                            Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS, userId);
                    final int software_shortcut_service_num = countAccessibilityServices(
                            software_shortcut_list);

                    final String hardware_shortcut_list = Settings.Secure.getStringForUser(resolver,
                            Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE, userId);
                    final int hardware_shortcut_service_num = countAccessibilityServices(
                            hardware_shortcut_list);

                    // only allow magnification to use it for now
                    final int triple_tap_service_num = Settings.Secure.getIntForUser(resolver,
                            Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED, 0, userId);

                    pulledData.add(
                            FrameworkStatsLog.buildStatsEvent(atomTag,
                                    software_shortcut_type, software_shortcut_service_num,
                                    hardware_shortcut_type, hardware_shortcut_service_num,
                                    triple_tap_shortcut, triple_tap_service_num));
                }
            }
        } catch (RuntimeException e) {
            Slog.e(TAG, "pulling accessibility shortcuts stats failed at getUsers", e);
            return StatsManager.PULL_SKIP;
        } finally {
            Binder.restoreCallingIdentity(token);
        }
        return StatsManager.PULL_SUCCESS;
    }

    int pullAccessibilityFloatingMenuStatsLocked(int atomTag, List<StatsEvent> pulledData) {
        UserManager userManager = mContext.getSystemService(UserManager.class);
        if (userManager == null) {
            return StatsManager.PULL_SKIP;
        }
        final long token = Binder.clearCallingIdentity();
        try {
            final ContentResolver resolver = mContext.getContentResolver();
            final int defaultSize = 0;
            final int defaultIconType = 0;
            final int defaultFadeEnabled = 1;
            final float defaultOpacity = 0.55f;

            for (UserInfo userInfo : userManager.getUsers()) {
                final int userId = userInfo.getUserHandle().getIdentifier();

                if (isAccessibilityFloatingMenuUser(mContext, userId)) {
                    final int size = Settings.Secure.getIntForUser(resolver,
                            Settings.Secure.ACCESSIBILITY_FLOATING_MENU_SIZE, defaultSize, userId);
                    final int type = Settings.Secure.getIntForUser(resolver,
                            Settings.Secure.ACCESSIBILITY_FLOATING_MENU_ICON_TYPE,
                            defaultIconType, userId);
                    final boolean fadeEnabled = (Settings.Secure.getIntForUser(resolver,
                            Settings.Secure.ACCESSIBILITY_FLOATING_MENU_FADE_ENABLED,
                            defaultFadeEnabled, userId)) == 1;
                    final float opacity = Settings.Secure.getFloatForUser(resolver,
                            Settings.Secure.ACCESSIBILITY_FLOATING_MENU_OPACITY,
                            defaultOpacity, userId);

                    pulledData.add(
                            FrameworkStatsLog.buildStatsEvent(atomTag, size, type, fadeEnabled,
                                    opacity));
                }
            }
        }  catch (RuntimeException e) {
            Slog.e(TAG, "pulling accessibility floating menu stats failed at getUsers", e);
            return StatsManager.PULL_SKIP;
        } finally {
            Binder.restoreCallingIdentity(token);
        }
        return StatsManager.PULL_SUCCESS;
    }

    /**
     * Counts how many accessibility services (including features) there are in the colon-separated
     * string list.
     *
     * @param semicolonList colon-separated string, it should be
     *                        {@link Settings.Secure#ACCESSIBILITY_BUTTON_TARGETS} or
     *                        {@link Settings.Secure#ACCESSIBILITY_SHORTCUT_TARGET_SERVICE}.
     * @return The number of accessibility services
     */
    private int countAccessibilityServices(String semicolonList) {
        if (TextUtils.isEmpty(semicolonList)) {
            return 0;
        }
        final int semiColonNums = (int) semicolonList.chars().filter(ch -> ch == ':').count();
        return TextUtils.isEmpty(semicolonList) ? 0 : semiColonNums + 1;
    }

    private boolean isAccessibilityShortcutUser(Context context, @UserIdInt int userId) {
        final ContentResolver resolver = context.getContentResolver();

        final String software_shortcut_list = Settings.Secure.getStringForUser(resolver,
                Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS, userId);
        final String hardware_shortcut_list = Settings.Secure.getStringForUser(resolver,
                Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE, userId);
        final boolean hardware_shortcut_dialog_shown = Settings.Secure.getIntForUser(resolver,
                Settings.Secure.ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN, 0, userId) == 1;
        final boolean software_shortcut_enabled = !TextUtils.isEmpty(software_shortcut_list);
        final boolean hardware_shortcut_enabled =
                hardware_shortcut_dialog_shown && !TextUtils.isEmpty(hardware_shortcut_list);
        final boolean triple_tap_shortcut_enabled = Settings.Secure.getIntForUser(resolver,
                Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED, 0, userId) == 1;

        return software_shortcut_enabled || hardware_shortcut_enabled
                || triple_tap_shortcut_enabled;
    }

    private boolean isAccessibilityFloatingMenuUser(Context context, @UserIdInt int userId) {
        final ContentResolver resolver = context.getContentResolver();
        final int mode = Settings.Secure.getIntForUser(resolver,
                Settings.Secure.ACCESSIBILITY_BUTTON_MODE, 0, userId);
        final String software_string = Settings.Secure.getStringForUser(resolver,
                Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS, userId);

        return (mode == Settings.Secure.ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU)
                && !TextUtils.isEmpty(software_string);
    }

    // Thermal event received from vendor thermal management subsystem
    private static final class ThermalEventListener extends IThermalEventListener.Stub {
        @Override