• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.hdmi;
18 
19 import android.stats.hdmi.HdmiStatsEnums;
20 
21 import com.android.internal.annotations.VisibleForTesting;
22 import com.android.internal.util.FrameworkStatsLog;
23 
24 /**
25  * Provides methods for writing HDMI-CEC statsd atoms.
26  */
27 @VisibleForTesting
28 public class HdmiCecAtomWriter {
29 
30     private static final int FEATURE_ABORT_OPCODE_UNKNOWN = 0x100;
31     private static final int ERROR_CODE_UNKNOWN = -1;
32 
33     /**
34      * Writes a HdmiCecMessageReported atom representing an HDMI CEC message.
35      * Should only be directly used for sent messages; for received messages,
36      * use the overloaded version with the errorCode argument omitted.
37      *
38      * @param message      The HDMI CEC message
39      * @param direction    Whether the message is incoming, outgoing, or neither
40      * @param errorCode    The error code from the final attempt to send the message
41      * @param callingUid   The calling uid of the app that triggered this message
42      */
messageReported( HdmiCecMessage message, int direction, int callingUid, int errorCode)43     public void messageReported(
44             HdmiCecMessage message, int direction, int callingUid, int errorCode) {
45         MessageReportedGenericArgs genericArgs = createMessageReportedGenericArgs(
46                 message, direction, errorCode, callingUid);
47         MessageReportedSpecialArgs specialArgs = createMessageReportedSpecialArgs(message);
48         messageReportedBase(genericArgs, specialArgs);
49     }
50 
51     /**
52      * Version of messageReported for received messages, where no error code is present.
53      *
54      * @param message      The HDMI CEC message
55      * @param direction    Whether the message is incoming, outgoing, or neither
56      * @param callingUid   The calling uid of the app that triggered this message
57      */
messageReported(HdmiCecMessage message, int direction, int callingUid)58     public void messageReported(HdmiCecMessage message, int direction, int callingUid) {
59         messageReported(message, direction, callingUid, ERROR_CODE_UNKNOWN);
60     }
61 
62     /**
63      * Constructs the generic arguments for logging a HDMI CEC message.
64      *
65      * @param message      The HDMI CEC message
66      * @param direction    Whether the message is incoming, outgoing, or neither
67      * @param errorCode    The error code of the message if it's outgoing;
68      *                     otherwise, ERROR_CODE_UNKNOWN
69      */
createMessageReportedGenericArgs( HdmiCecMessage message, int direction, int errorCode, int callingUid)70     private MessageReportedGenericArgs createMessageReportedGenericArgs(
71             HdmiCecMessage message, int direction, int errorCode, int callingUid) {
72         int sendMessageResult = errorCode == ERROR_CODE_UNKNOWN
73                 ? HdmiStatsEnums.SEND_MESSAGE_RESULT_UNKNOWN
74                 : errorCode + 10;
75         return new MessageReportedGenericArgs(callingUid, direction, message.getSource(),
76                 message.getDestination(), message.getOpcode(), sendMessageResult);
77     }
78 
79     /**
80      * Constructs the special arguments for logging an HDMI CEC message.
81      *
82      * @param message The HDMI CEC message to log
83      * @return An object containing the special arguments for the message
84      */
createMessageReportedSpecialArgs(HdmiCecMessage message)85     private MessageReportedSpecialArgs createMessageReportedSpecialArgs(HdmiCecMessage message) {
86         // Special arguments depend on message opcode
87         switch (message.getOpcode()) {
88             case Constants.MESSAGE_USER_CONTROL_PRESSED:
89                 return createUserControlPressedSpecialArgs(message);
90             case Constants.MESSAGE_FEATURE_ABORT:
91                 return createFeatureAbortSpecialArgs(message);
92             default:
93                 return new MessageReportedSpecialArgs();
94         }
95     }
96 
97     /**
98      * Constructs the special arguments for a <User Control Pressed> message.
99      *
100      * @param message The HDMI CEC message to log
101      */
createUserControlPressedSpecialArgs( HdmiCecMessage message)102     private MessageReportedSpecialArgs createUserControlPressedSpecialArgs(
103             HdmiCecMessage message) {
104         MessageReportedSpecialArgs specialArgs = new MessageReportedSpecialArgs();
105 
106         int keycode = message.getParams()[0];
107         if (keycode >= 0x1E && keycode <= 0x29) {
108             specialArgs.mUserControlPressedCommand = HdmiStatsEnums.NUMBER;
109         } else {
110             specialArgs.mUserControlPressedCommand = keycode + 0x100;
111         }
112 
113         return specialArgs;
114     }
115 
116     /**
117      * Constructs method for constructing the special arguments for a <Feature Abort> message.
118      *
119      * @param message The HDMI CEC message to log
120      */
createFeatureAbortSpecialArgs(HdmiCecMessage message)121     private MessageReportedSpecialArgs createFeatureAbortSpecialArgs(HdmiCecMessage message) {
122         MessageReportedSpecialArgs specialArgs = new MessageReportedSpecialArgs();
123 
124         specialArgs.mFeatureAbortOpcode = message.getParams()[0] & 0xFF; // Unsigned byte
125         specialArgs.mFeatureAbortReason = message.getParams()[1] + 10;
126 
127         return specialArgs;
128     }
129 
130     /**
131      * Writes a HdmiCecMessageReported atom.
132      *
133      * @param genericArgs Generic arguments; shared by all HdmiCecMessageReported atoms
134      * @param specialArgs Special arguments; depends on the opcode of the message
135      */
messageReportedBase(MessageReportedGenericArgs genericArgs, MessageReportedSpecialArgs specialArgs)136     private void messageReportedBase(MessageReportedGenericArgs genericArgs,
137             MessageReportedSpecialArgs specialArgs) {
138         FrameworkStatsLog.write(
139                 FrameworkStatsLog.HDMI_CEC_MESSAGE_REPORTED,
140                 genericArgs.mUid,
141                 genericArgs.mDirection,
142                 genericArgs.mInitiatorLogicalAddress,
143                 genericArgs.mDestinationLogicalAddress,
144                 genericArgs.mOpcode,
145                 genericArgs.mSendMessageResult,
146                 specialArgs.mUserControlPressedCommand,
147                 specialArgs.mFeatureAbortOpcode,
148                 specialArgs.mFeatureAbortReason);
149     }
150 
151 
152     /**
153      * Writes a HdmiCecActiveSourceChanged atom representing a change in the active source.
154      *
155      * @param logicalAddress             The Logical Address of the new active source
156      * @param physicalAddress            The Physical Address of the new active source
157      * @param relationshipToActiveSource The relationship between this device and the active source
158      */
activeSourceChanged(int logicalAddress, int physicalAddress, @Constants.PathRelationship int relationshipToActiveSource)159     public void activeSourceChanged(int logicalAddress, int physicalAddress,
160             @Constants.PathRelationship int relationshipToActiveSource) {
161         FrameworkStatsLog.write(
162                 FrameworkStatsLog.HDMI_CEC_ACTIVE_SOURCE_CHANGED,
163                 logicalAddress,
164                 physicalAddress,
165                 relationshipToActiveSource
166         );
167     }
168 
169     /**
170      * Contains the required arguments for creating any HdmiCecMessageReported atom
171      */
172     private class MessageReportedGenericArgs {
173         final int mUid;
174         final int mDirection;
175         final int mInitiatorLogicalAddress;
176         final int mDestinationLogicalAddress;
177         final int mOpcode;
178         final int mSendMessageResult;
179 
MessageReportedGenericArgs(int uid, int direction, int initiatorLogicalAddress, int destinationLogicalAddress, int opcode, int sendMessageResult)180         MessageReportedGenericArgs(int uid, int direction, int initiatorLogicalAddress,
181                 int destinationLogicalAddress, int opcode, int sendMessageResult) {
182             this.mUid = uid;
183             this.mDirection = direction;
184             this.mInitiatorLogicalAddress = initiatorLogicalAddress;
185             this.mDestinationLogicalAddress = destinationLogicalAddress;
186             this.mOpcode = opcode;
187             this.mSendMessageResult = sendMessageResult;
188         }
189     }
190 
191     /**
192      * Contains the opcode-dependent arguments for creating a HdmiCecMessageReported atom. Each
193      * field is initialized to a null-like value by default. Therefore, a freshly constructed
194      * instance of this object represents a HDMI CEC message whose type does not require any
195      * additional arguments.
196      */
197     private class MessageReportedSpecialArgs {
198         int mUserControlPressedCommand = HdmiStatsEnums.USER_CONTROL_PRESSED_COMMAND_UNKNOWN;
199         int mFeatureAbortOpcode = FEATURE_ABORT_OPCODE_UNKNOWN;
200         int mFeatureAbortReason = HdmiStatsEnums.FEATURE_ABORT_REASON_UNKNOWN;
201     }
202 }
203