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

Commit d1a1f36d authored by Kriti Dang's avatar Kriti Dang
Browse files

Fetch display metrics

Bug: 203185126
Test: m statsd_testdrive; statsd_testdrive 10130
Change-Id: I53939f3439a12661d376427cb11fbd934206fa8d
parent f7709fdb
Loading
Loading
Loading
Loading
+124 −12
Original line number Diff line number Diff line
@@ -93,9 +93,12 @@ import android.content.pm.PackageManager;
import android.content.pm.PermissionInfo;
import android.content.pm.UserInfo;
import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.display.DisplayManager;
import android.hardware.face.FaceManager;
import android.hardware.fingerprint.FingerprintManager;
import android.media.AudioManager;
import android.media.MediaDrm;
import android.media.UnsupportedSchemeException;
import android.net.ConnectivityManager;
import android.net.INetworkStatsService;
import android.net.INetworkStatsSession;
@@ -164,6 +167,7 @@ import android.util.Slog;
import android.util.SparseArray;
import android.util.StatsEvent;
import android.util.proto.ProtoOutputStream;
import android.view.Display;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.app.procstats.IProcessStats;
@@ -4492,10 +4496,8 @@ public class StatsPullAtomService extends SystemService {

        // get the surround sound metrics information
        Map<Integer, Boolean> surroundEncodingsMap = audioManager.getSurroundFormats();
        byte[] surroundEncodings =
                getAudioEncodingsAsProto(new ArrayList(surroundEncodingsMap.keySet()));
        byte[] sinkSurroundEncodings =
                getAudioEncodingsAsProto(audioManager.getReportedSurroundFormats());
        byte[] surroundEncodings = toBytes(new ArrayList(surroundEncodingsMap.keySet()));
        byte[] sinkSurroundEncodings = toBytes(audioManager.getReportedSurroundFormats());
        List<Integer> disabledSurroundEncodingsList = new ArrayList<>();
        List<Integer> enabledSurroundEncodingsList = new ArrayList<>();
        for (int surroundEncoding:  surroundEncodingsMap.keySet()) {
@@ -4505,24 +4507,68 @@ public class StatsPullAtomService extends SystemService {
                enabledSurroundEncodingsList.add(surroundEncoding);
            }
        }
        byte[] disabledSurroundEncodings = getAudioEncodingsAsProto(disabledSurroundEncodingsList);
        byte[] enabledSurroundEncodings = getAudioEncodingsAsProto(enabledSurroundEncodingsList);
        byte[] disabledSurroundEncodings = toBytes(disabledSurroundEncodingsList);
        byte[] enabledSurroundEncodings = toBytes(enabledSurroundEncodingsList);
        int surroundOutputMode = audioManager.getEncodedSurroundMode();

        // TODO(b/203185126) : Remove the display capabilities metrics mock and retrieve actual
        //  metrics
        byte[] mockByteArray = new byte[0];
        DisplayManager displayManager = mContext.getSystemService(DisplayManager.class);
        Display display = displayManager.getDisplay(Display.DEFAULT_DISPLAY);
        // get the display capabilities metrics information
        Display.HdrCapabilities hdrCapabilities = display.getHdrCapabilities();
        byte[] sinkHdrFormats = new byte[]{};
        if (hdrCapabilities != null) {
            sinkHdrFormats = toBytes(hdrCapabilities.getSupportedHdrTypes());
        }
        byte[] sinkDisplayModes = toBytes(display.getSupportedModes());
        int hdcpLevel = -1;
        List<UUID> uuids = MediaDrm.getSupportedCryptoSchemes();
        try {
            if (!uuids.isEmpty()) {
                MediaDrm mediaDrm = new MediaDrm(uuids.get(0));
                hdcpLevel = mediaDrm.getConnectedHdcpLevel();
            }
        } catch (UnsupportedSchemeException exception) {
            Slog.e(TAG, "pulling hdcp level failed.", exception);
            hdcpLevel = -1;
        }

        // get the display settings metrics information
        int matchContentFrameRateUserPreference =
                displayManager.getMatchContentFrameRateUserPreference();
        byte[] userDisabledHdrTypes = toBytes(displayManager.getUserDisabledHdrTypes());
        Display.Mode userPreferredDisplayMode = displayManager.getUserPreferredDisplayMode();
        int userPreferredWidth = userPreferredDisplayMode != null
                ? userPreferredDisplayMode.getPhysicalWidth() : -1;
        int userPreferredHeight = userPreferredDisplayMode != null
                ? userPreferredDisplayMode.getPhysicalHeight() : -1;
        float userPreferredRefreshRate = userPreferredDisplayMode != null
                ? userPreferredDisplayMode.getRefreshRate() : 0.0f;
        boolean hasUserDisabledAllm = false;
        try {
            hasUserDisabledAllm = Settings.Secure.getIntForUser(
                    mContext.getContentResolver(),
                    Settings.Secure.MINIMAL_POST_PROCESSING_ALLOWED,
                    1) == 0;
        } catch (Settings.SettingNotFoundException exception) {
            Slog.e(
                    TAG, "unable to find setting for MINIMAL_POST_PROCESSING_ALLOWED.",
                    exception);
            hasUserDisabledAllm = false;
        }

        pulledData.add(
                FrameworkStatsLog.buildStatsEvent(
                        atomTag, surroundEncodings, sinkSurroundEncodings,
                        disabledSurroundEncodings, enabledSurroundEncodings, surroundOutputMode,
                        mockByteArray, mockByteArray, -1, -1, mockByteArray,
                        -1, -1, 0.0f, false));
                        sinkHdrFormats, sinkDisplayModes, hdcpLevel,
                        matchContentFrameRateUserPreference, userDisabledHdrTypes,
                        userPreferredWidth, userPreferredHeight, userPreferredRefreshRate,
                        hasUserDisabledAllm));

        return StatsManager.PULL_SUCCESS;
    }

    private byte[] getAudioEncodingsAsProto(List<Integer> audioEncodings) {
    private byte[] toBytes(List<Integer> audioEncodings) {
        ProtoOutputStream protoOutputStream = new ProtoOutputStream();
        for (int audioEncoding : audioEncodings) {
            protoOutputStream.write(
@@ -4532,6 +4578,72 @@ public class StatsPullAtomService extends SystemService {
        return protoOutputStream.getBytes();
    }

    private byte[] toBytes(int[] array) {
        ProtoOutputStream protoOutputStream = new ProtoOutputStream();
        for (int element : array) {
            protoOutputStream.write(
                    ProtoOutputStream.FIELD_COUNT_REPEATED | ProtoOutputStream.FIELD_TYPE_ENUM | 1,
                    element);
        }
        return protoOutputStream.getBytes();
    }

    private byte[] toBytes(Display.Mode[] displayModes) {
        Map<Integer, Integer> modeGroupIds = createModeGroups(displayModes);
        ProtoOutputStream protoOutputStream = new ProtoOutputStream();
        for (Display.Mode element : displayModes) {
            ProtoOutputStream protoOutputStreamMode = new ProtoOutputStream();
            protoOutputStreamMode.write(
                    ProtoOutputStream.FIELD_COUNT_SINGLE | ProtoOutputStream.FIELD_TYPE_INT32 | 1,
                    element.getPhysicalHeight());
            protoOutputStreamMode.write(
                    ProtoOutputStream.FIELD_COUNT_SINGLE | ProtoOutputStream.FIELD_TYPE_INT32 | 2,
                    element.getPhysicalWidth());
            protoOutputStreamMode.write(
                    ProtoOutputStream.FIELD_COUNT_SINGLE | ProtoOutputStream.FIELD_TYPE_FLOAT | 3,
                    element.getRefreshRate());
            protoOutputStreamMode.write(
                    ProtoOutputStream.FIELD_COUNT_SINGLE | ProtoOutputStream.FIELD_TYPE_INT32 | 4,
                    modeGroupIds.get(element.getModeId()));
            protoOutputStream.write(
                    ProtoOutputStream.FIELD_COUNT_REPEATED
                            | ProtoOutputStream.FIELD_TYPE_MESSAGE | 1,
                    protoOutputStreamMode.getBytes());
        }
        return protoOutputStream.getBytes();
    }

    // Returns map modeId -> groupId such that all modes with the same group have alternative
    // refresh rates
    private Map<Integer, Integer> createModeGroups(Display.Mode[] supportedModes) {
        Map<Integer, Integer> modeGroupIds = new ArrayMap<>();
        int groupId = 1;
        for (Display.Mode mode : supportedModes) {
            if (modeGroupIds.containsKey(mode.getModeId())) {
                continue;
            }
            modeGroupIds.put(mode.getModeId(), groupId);
            for (float refreshRate : mode.getAlternativeRefreshRates()) {
                int alternativeModeId = findModeId(supportedModes, mode.getPhysicalWidth(),
                        mode.getPhysicalHeight(), refreshRate);
                if (alternativeModeId != -1 && !modeGroupIds.containsKey(alternativeModeId)) {
                    modeGroupIds.put(alternativeModeId, groupId);
                }
            }
            groupId++;
        }
        return modeGroupIds;
    }

    private int findModeId(Display.Mode[] modes, int width, int height, float refreshRate) {
        for (Display.Mode mode : modes) {
            if (mode.matches(width, height, refreshRate)) {
                return mode.getModeId();
            }
        }
        return -1;
    }

    /**
     * Counts how many accessibility services (including features) there are in the colon-separated
     * string list.