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

Commit 258212e7 authored by Nick Chalko's avatar Nick Chalko Committed by Android (Google) Code Review
Browse files

Merge changes I0a880124,I2e5c3e7f

* changes:
  Include the TV Input Service uid in metrics logging.
  Add TifTuneStateChanged atom.
parents 203346d3 d2df7036
Loading
Loading
Loading
Loading
+35 −0
Original line number Diff line number Diff line
@@ -60,6 +60,7 @@ import "frameworks/base/core/proto/android/stats/storage/storage_enums.proto";
import "frameworks/base/core/proto/android/stats/style/style_enums.proto";
import "frameworks/base/core/proto/android/stats/sysui/notification_enums.proto";
import "frameworks/base/core/proto/android/stats/tls/enums.proto";
import "frameworks/base/core/proto/android/stats/tv/tif_enums.proto";
import "frameworks/base/core/proto/android/telecomm/enums.proto";
import "frameworks/base/core/proto/android/telephony/enums.proto";
import "frameworks/base/core/proto/android/view/enums.proto";
@@ -510,6 +511,7 @@ message Atom {
        MediaPlaybackTrackChanged media_playback_track_changed = 324;
        WifiScanReported wifi_scan_reported = 325 [(module) = "wifi"];
        WifiPnoScanReported wifi_pno_scan_reported = 326  [(module) = "wifi"];
        TifTuneStateChanged tif_tune_changed = 327 [(module) = "framework"];

        // StatsdStats tracks platform atoms with ids upto 500.
        // Update StatsdStats::kMaxPushedAtomId when atom ids here approach that value.
@@ -10351,6 +10353,39 @@ message CellBroadcastMessageError {
    optional string exception_message = 2;
}

/**
 * Logs when a TV Input Service Session changes tune state
 * This is atom ID 327.
 *
 * Logged from:
 *   frameworks/base/services/core/java/com/android/server/tv/TvInputManagerService.java
 */
message TifTuneStateChanged {

    // Tv Input Service uid, TV Player uid
    repeated AttributionNode attribution_node = 1 [
        (state_field_option).primary_field_first_uid = true
    ];
    optional android.stats.tv.TifTuneState state = 2 [
        (state_field_option).exclusive_state = true,
        (state_field_option).default_state_value = 0,
        (state_field_option).nested = false
    ];
    // This a globally unique 128 bit random number created by TvInputManagerService when
    // android.media.tv.TvInputManager#createSession is called.
    // It is has no device or user association.
    // See android.media.tv.TvInputService.onCreateSession(java.lang.String, java.lang.String)
    // WARNING: Any changes to this field should be carefully reviewed for privacy.
    //          Inspect the code at
    //          framework/base/cmds/statsd/src/atoms.proto
    //               TifTuneState
    //          frameworks/base/services/core/java/com/android/server/tv/TvInputManagerService.java
    //              logTuneStateChanged
    //              BinderService.createSession
    //              SessionState.sessionId
    optional string tif_session_id = 3 [(state_field_option).primary_field = true];
}

/**
 * Logs when a tune occurs through device's Frontend.
 * This is atom ID 276.
+56 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

syntax = "proto2";

package android.stats.tv;
option java_multiple_files = true;

// Enums for TV Input Framework
option java_outer_classname = "TifStatsEnums";

// Tune State of a TV Input Service Framework
enum TifTuneState {
  TIF_TUNE_STATE_UNKNOWN = 0;
  CREATED = 1;
  SURFACE_ATTACHED = 2;
  SURFACE_DETACHED = 3;
  RELEASED = 4;
  TUNE_STARTED = 5;
  VIDEO_AVAILABLE = 6;

  // Keep in sync with TvInputManager
  // Use the TvInputManager value + 100
  VIDEO_UNAVAILABLE_REASON_UNKNOWN = 100;
  VIDEO_UNAVAILABLE_REASON_TUNING = 101;
  VIDEO_UNAVAILABLE_REASON_WEAK_SIGNAL = 102;
  VIDEO_UNAVAILABLE_REASON_BUFFERING = 103;
  VIDEO_UNAVAILABLE_REASON_AUDIO_ONLY = 104;
  VIDEO_UNAVAILABLE_REASON_NOT_CONNECTED = 105;
  VIDEO_UNAVAILABLE_REASON_INSUFFICIENT_RESOURCE = 106;
  VIDEO_UNAVAILABLE_REASON_CAS_INSUFFICIENT_OUTPUT_PROTECTION=107;
  VIDEO_UNAVAILABLE_REASON_CAS_PVR_RECORDING_NOT_ALLOWED=108;
  VIDEO_UNAVAILABLE_REASON_CAS_NO_LICENSE=109;
  VIDEO_UNAVAILABLE_REASON_CAS_LICENSE_EXPIRED=110;
  VIDEO_UNAVAILABLE_REASON_CAS_NEED_ACTIVATION=111;
  VIDEO_UNAVAILABLE_REASON_CAS_NEED_PAIRING=112;
  VIDEO_UNAVAILABLE_REASON_CAS_NO_CARD=113;
  VIDEO_UNAVAILABLE_REASON_CAS_CARD_MUTE=114;
  VIDEO_UNAVAILABLE_REASON_CAS_CARD_INVALID=115;
  VIDEO_UNAVAILABLE_REASON_CAS_BLACKOUT=116;
  VIDEO_UNAVAILABLE_REASON_CAS_REBOOTING=117;
  VIDEO_UNAVAILABLE_REASON_CAS_UNKNOWN=118;
}
+153 −10
Original line number Diff line number Diff line
@@ -87,6 +87,7 @@ import com.android.internal.annotations.GuardedBy;
import com.android.internal.content.PackageMonitor;
import com.android.internal.os.SomeArgs;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.IoThread;
import com.android.server.SystemService;
@@ -337,6 +338,7 @@ public final class TvInputManagerService extends SystemService {
                inputState = new TvInputState();
            }
            inputState.info = info;
            inputState.uid = getInputUid(info);
            inputMap.put(info.getId(), inputState);
        }

@@ -371,6 +373,16 @@ public final class TvInputManagerService extends SystemService {
        userState.inputMap = inputMap;
    }

    private int getInputUid(TvInputInfo info) {
        try {
            return getContext().getPackageManager().getApplicationInfo(
                    info.getServiceInfo().packageName, 0).uid;
        } catch (NameNotFoundException e) {
            Slog.w(TAG, "Unable to get UID for  " + info, e);
            return Process.INVALID_UID;
        }
    }

    @GuardedBy("mLock")
    private void buildTvContentRatingSystemListLocked(int userId) {
        UserState userState = getOrCreateUserStateLocked(userId);
@@ -405,7 +417,7 @@ public final class TvInputManagerService extends SystemService {
                return;
            }
            if (mUserStates.contains(mCurrentUserId)) {
                UserState userState = mUserStates.get(mCurrentUserId);
                UserState userState = getUserStateLocked(mCurrentUserId);
                List<SessionState> sessionStatesToRelease = new ArrayList<>();
                for (SessionState sessionState : userState.sessionStateMap.values()) {
                    if (sessionState.session != null && !sessionState.isRecordingSession) {
@@ -474,7 +486,7 @@ public final class TvInputManagerService extends SystemService {

    private void removeUser(int userId) {
        synchronized (mLock) {
            UserState userState = mUserStates.get(userId);
            UserState userState = getUserStateLocked(userId);
            if (userState == null) {
                return;
            }
@@ -535,7 +547,7 @@ public final class TvInputManagerService extends SystemService {

    @GuardedBy("mLock")
    private UserState getOrCreateUserStateLocked(int userId) {
        UserState userState = mUserStates.get(userId);
        UserState userState = getUserStateLocked(userId);
        if (userState == null) {
            userState = new UserState(mContext, userId);
            mUserStates.put(userId, userState);
@@ -715,7 +727,8 @@ public final class TvInputManagerService extends SystemService {
    }

    @GuardedBy("mLock")
    private void releaseSessionLocked(IBinder sessionToken, int callingUid, int userId) {
    @Nullable
    private SessionState releaseSessionLocked(IBinder sessionToken, int callingUid, int userId) {
        SessionState sessionState = null;
        try {
            sessionState = getSessionStateLocked(sessionToken, callingUid, userId);
@@ -738,6 +751,7 @@ public final class TvInputManagerService extends SystemService {
            }
        }
        removeSessionStateLocked(sessionToken, userId);
        return sessionState;
    }

    @GuardedBy("mLock")
@@ -908,6 +922,7 @@ public final class TvInputManagerService extends SystemService {
            return;
        }
        inputState.info = inputInfo;
        inputState.uid = getInputUid(inputInfo);

        int n = userState.mCallbacks.beginBroadcast();
        for (int i = 0; i < n; ++i) {
@@ -1248,7 +1263,22 @@ public final class TvInputManagerService extends SystemService {
            final int resolvedUserId = resolveCallingUserId(callingPid, callingUid,
                    userId, "createSession");
            final long identity = Binder.clearCallingIdentity();
            // Generate a unique session id with a random UUID.
            /**
             * A randomly generated id for this this session.
             *
             * <p>This field contains no user or device reference and is large enough to be
             * effectively globally unique.
             *
             * <p><b>WARNING</b> Any changes to this field should be carefully reviewed for privacy.
             * Inspect the code at:
             *
             * <ul>
             *   <li>framework/base/cmds/statsd/src/atoms.proto#TifTuneState
             *   <li>{@link #logTuneStateChanged}
             *   <li>{@link TvInputManagerService.BinderService#createSession}
             *   <li>{@link SessionState#sessionId}
             * </ul>
             */
            String uniqueSessionId = UUID.randomUUID().toString();
            try {
                synchronized (mLock) {
@@ -1269,6 +1299,8 @@ public final class TvInputManagerService extends SystemService {
                    TvInputInfo info = inputState.info;
                    ServiceState serviceState = userState.serviceStateMap.get(info.getComponent());
                    if (serviceState == null) {
                        int tisUid = PackageManager.getApplicationInfoAsUserCached(
                                info.getComponent().getPackageName(), 0, resolvedUserId).uid;
                        serviceState = new ServiceState(info.getComponent(), resolvedUserId);
                        userState.serviceStateMap.put(info.getComponent(), serviceState);
                    }
@@ -1301,6 +1333,8 @@ public final class TvInputManagerService extends SystemService {
                    } else {
                        updateServiceConnectionLocked(info.getComponent(), resolvedUserId);
                    }
                    logTuneStateChanged(FrameworkStatsLog.TIF_TUNE_STATE_CHANGED__STATE__CREATED,
                            sessionState, inputState);
                }
            } finally {
                Binder.restoreCallingIdentity(identity);
@@ -1317,8 +1351,17 @@ public final class TvInputManagerService extends SystemService {
                    userId, "releaseSession");
            final long identity = Binder.clearCallingIdentity();
            try {
                SessionState sessionState = null;
                UserState userState = null;
                synchronized (mLock) {
                    releaseSessionLocked(sessionToken, callingUid, resolvedUserId);
                    sessionState = releaseSessionLocked(sessionToken, callingUid, resolvedUserId);
                    userState = getUserStateLocked(userId);
                }
                if (sessionState != null) {
                    TvInputState tvInputState = TvInputManagerService.getTvInputState(sessionState,
                            userState);
                    logTuneStateChanged(FrameworkStatsLog.TIF_TUNE_STATE_CHANGED__STATE__RELEASED,
                            sessionState, tvInputState);
                }
            } finally {
                Binder.restoreCallingIdentity(identity);
@@ -1372,10 +1415,13 @@ public final class TvInputManagerService extends SystemService {
            final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid,
                    userId, "setSurface");
            final long identity = Binder.clearCallingIdentity();
            SessionState sessionState = null;
            UserState userState = null;
            try {
                synchronized (mLock) {
                    try {
                        SessionState sessionState = getSessionStateLocked(sessionToken, callingUid,
                        userState = getUserStateLocked(userId);
                        sessionState = getSessionStateLocked(sessionToken, callingUid,
                                resolvedUserId);
                        if (sessionState.hardwareSessionToken == null) {
                            getSessionLocked(sessionState).setSurface(surface);
@@ -1392,6 +1438,14 @@ public final class TvInputManagerService extends SystemService {
                    // surface is not used in TvInputManagerService.
                    surface.release();
                }
                if (sessionState != null) {
                    int state = surface == null
                            ?
                            FrameworkStatsLog.TIF_TUNE_STATE_CHANGED__STATE__SURFACE_ATTACHED
                            : FrameworkStatsLog.TIF_TUNE_STATE_CHANGED__STATE__SURFACE_DETACHED;
                    logTuneStateChanged(state, sessionState,
                            TvInputManagerService.getTvInputState(sessionState, userState));
                }
                Binder.restoreCallingIdentity(identity);
            }
        }
@@ -1479,6 +1533,10 @@ public final class TvInputManagerService extends SystemService {
                            return;
                        }

                        logTuneStateChanged(
                                FrameworkStatsLog.TIF_TUNE_STATE_CHANGED__STATE__TUNE_STARTED,
                                sessionState,
                                TvInputManagerService.getTvInputState(sessionState, userState));
                        // Log the start of watch.
                        SomeArgs args = SomeArgs.obtain();
                        args.arg1 = sessionState.componentName.getPackageName();
@@ -2302,6 +2360,16 @@ public final class TvInputManagerService extends SystemService {
        }
    }

    @Nullable
    private static TvInputState getTvInputState(
            SessionState sessionState,
            @Nullable UserState userState) {
        if (userState != null) {
            return userState.inputMap.get(sessionState.inputId);
        }
        return null;
    }

    @GuardedBy("mLock")
    private List<TunedInfo> getCurrentTunedInfosInternalLocked(
            UserState userState, int callingPid, int callingUid) {
@@ -2367,6 +2435,28 @@ public final class TvInputManagerService extends SystemService {
        }
    }

    /**
     * Log Tune state changes to {@link FrameworkStatsLog}.
     *
     * <p><b>WARNING</b> Any changes to this field should be carefully reviewed for privacy.
     * Inspect the code at:
     *
     * <ul>
     *   <li>framework/base/cmds/statsd/src/atoms.proto#TifTuneState
     *   <li>{@link #logTuneStateChanged}
     *   <li>{@link TvInputManagerService.BinderService#createSession}
     *   <li>{@link SessionState#sessionId}
     * </ul>
     */
    private void logTuneStateChanged(int state, SessionState sessionState,
            @Nullable TvInputState inputState) {
        // TODO(b/173536904): log input type and id
        FrameworkStatsLog.write(FrameworkStatsLog.TIF_TUNE_CHANGED,
                new int[]{sessionState.callingUid,
                        inputState == null ? Process.INVALID_UID : inputState.uid},
                new String[]{"tif_player", "tv_input_service"}, state, sessionState.sessionId);
    }

    private static final class UserState {
        // A mapping from the TV input id to its TvInputState.
        private Map<String, TvInputState> inputMap = new HashMap<>();
@@ -2464,10 +2554,25 @@ public final class TvInputManagerService extends SystemService {
    }

    private static final class TvInputState {
        // A TvInputInfo object which represents the TV input.

        /** A TvInputInfo object which represents the TV input. */
        private TvInputInfo info;

        // The state of TV input. Connected by default.
        /**
         * The kernel user-ID that has been assigned to the application the TvInput is a part of.
         *
         * <p>
         * Currently this is not a unique ID (multiple applications can have
         * the same uid).
         */
        private int uid;

        /**
         * The state of TV input.
         *
         * <p>
         * Connected by default
         */
        private int state = INPUT_STATE_CONNECTED;

        @Override
@@ -2478,6 +2583,23 @@ public final class TvInputManagerService extends SystemService {

    private final class SessionState implements IBinder.DeathRecipient {
        private final String inputId;

        /**
         * A randomly generated id for this this session.
         *
         * <p>This field contains no user or device reference and is large enough to be
         * effectively globally unique.
         *
         * <p><b>WARNING</b> Any changes to this field should be carefully reviewed for privacy.
         * Inspect the code at:
         *
         * <ul>
         *   <li>framework/base/cmds/statsd/src/atoms.proto#TifTuneState
         *   <li>{@link #logTuneStateChanged}
         *   <li>{@link TvInputManagerService.BinderService#createSession}
         *   <li>{@link SessionState#sessionId}
         * </ul>
         */
        private final String sessionId;
        private final ComponentName componentName;
        private final boolean isRecordingSession;
@@ -2545,7 +2667,7 @@ public final class TvInputManagerService extends SystemService {
                Slog.d(TAG, "onServiceConnected(component=" + component + ")");
            }
            synchronized (mLock) {
                UserState userState = mUserStates.get(mUserId);
                UserState userState = getUserStateLocked(mUserId);
                if (userState == null) {
                    // The user was removed while connecting.
                    mContext.unbindService(this);
@@ -2815,8 +2937,13 @@ public final class TvInputManagerService extends SystemService {
                if (mSessionState.session == null || mSessionState.client == null) {
                    return;
                }
                TvInputState tvInputState = getTvInputState(mSessionState,
                        getUserStateLocked(mCurrentUserId));
                try {
                    mSessionState.client.onVideoAvailable(mSessionState.seq);
                    logTuneStateChanged(
                            FrameworkStatsLog.TIF_TUNE_STATE_CHANGED__STATE__VIDEO_AVAILABLE,
                            mSessionState, tvInputState);
                } catch (RemoteException e) {
                    Slog.e(TAG, "error in onVideoAvailable", e);
                }
@@ -2832,8 +2959,20 @@ public final class TvInputManagerService extends SystemService {
                if (mSessionState.session == null || mSessionState.client == null) {
                    return;
                }
                TvInputState tvInputState = getTvInputState(mSessionState,
                        getUserStateLocked(mCurrentUserId));
                try {
                    mSessionState.client.onVideoUnavailable(reason, mSessionState.seq);
                    int loggedReason = reason + FrameworkStatsLog
                            .TIF_TUNE_STATE_CHANGED__STATE__VIDEO_UNAVAILABLE_REASON_UNKNOWN;
                    if (loggedReason < FrameworkStatsLog
                            .TIF_TUNE_STATE_CHANGED__STATE__VIDEO_UNAVAILABLE_REASON_UNKNOWN
                            || loggedReason > FrameworkStatsLog
                            .TIF_TUNE_STATE_CHANGED__STATE__VIDEO_UNAVAILABLE_REASON_CAS_UNKNOWN) {
                        loggedReason = FrameworkStatsLog
                                .TIF_TUNE_STATE_CHANGED__STATE__VIDEO_UNAVAILABLE_REASON_UNKNOWN;
                    }
                    logTuneStateChanged(loggedReason, mSessionState, tvInputState);
                } catch (RemoteException e) {
                    Slog.e(TAG, "error in onVideoUnavailable", e);
                }
@@ -3019,6 +3158,10 @@ public final class TvInputManagerService extends SystemService {
        }
    }

    private UserState getUserStateLocked(int userId) {
        return mUserStates.get(userId);
    }

    private static final class WatchLogHandler extends Handler {
        // There are only two kinds of watch events that can happen on the system:
        // 1. The current TV input session is tuned to a new channel.