Merge changes I0a880124,I2e5c3e7f

* changes:
  Include the TV Input Service uid in metrics logging.
  Add TifTuneStateChanged atom.
This commit is contained in:
Nick Chalko
2020-11-19 01:52:06 +00:00
committed by Android (Google) Code Review
3 changed files with 244 additions and 10 deletions

View File

@@ -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.

View File

@@ -0,0 +1,56 @@
/*
* 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;
}

View File

@@ -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.