1 /*
2  * Copyright (C) 2021 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 static com.android.server.hdmi.HdmiCecMessageValidator.ERROR_PARAMETER_SHORT;
20 import static com.android.server.hdmi.HdmiCecMessageValidator.OK;
21 import static com.android.server.hdmi.HdmiCecMessageValidator.ValidationResult;
22 
23 /**
24  * Represents a validated <Set Audio Volume Level> message with parsed parameters.
25  */
26 public class SetAudioVolumeLevelMessage extends HdmiCecMessage {
27     private final int mAudioVolumeLevel;
28 
SetAudioVolumeLevelMessage(int source, int destination, byte[] params, int audioVolumeLevel)29     private SetAudioVolumeLevelMessage(int source, int destination, byte[] params,
30             int audioVolumeLevel) {
31         super(source, destination, Constants.MESSAGE_SET_AUDIO_VOLUME_LEVEL, params, OK);
32         mAudioVolumeLevel = audioVolumeLevel;
33     }
34 
35     /**
36      * Static factory method. Intended for constructing outgoing or test messages, as it uses
37      * structured types instead of raw bytes to construct the parameters.
38      *
39      * @param source Initiator address. Cannot be {@link Constants#ADDR_UNREGISTERED}
40      * @param destination Destination address. Cannot be {@link Constants#ADDR_BROADCAST}
41      * @param audioVolumeLevel [Audio Volume Level]. Either 0x7F (representing no volume change)
42      *                         or between 0 and 100 inclusive (representing volume percentage).
43      */
build(int source, int destination, int audioVolumeLevel)44     public static HdmiCecMessage build(int source, int destination, int audioVolumeLevel) {
45         byte[] params = { (byte) (audioVolumeLevel & 0xFF) };
46 
47         @ValidationResult
48         int addressValidationResult = validateAddress(source, destination);
49         if (addressValidationResult == OK) {
50             return new SetAudioVolumeLevelMessage(source, destination, params, audioVolumeLevel);
51         } else {
52             return new HdmiCecMessage(source, destination, Constants.MESSAGE_SET_AUDIO_VOLUME_LEVEL,
53                     params, addressValidationResult);
54         }
55     }
56 
57     /**
58      * Must only be called from {@link HdmiCecMessage#build}.
59      *
60      * Parses and validates CEC message data as a <SetAudioVolumeLevel> message. Intended for
61      * constructing a representation of an incoming message, as it takes raw bytes for
62      * parameters.
63      *
64      * If successful, returns an instance of {@link SetAudioVolumeLevelMessage}.
65      * If unsuccessful, returns an {@link HdmiCecMessage} with the reason for validation failure
66      * accessible through {@link HdmiCecMessage#getValidationResult}.
67      */
build(int source, int destination, byte[] params)68     public static HdmiCecMessage build(int source, int destination, byte[] params) {
69         if (params.length == 0) {
70             return new HdmiCecMessage(source, destination, Constants.MESSAGE_SET_AUDIO_VOLUME_LEVEL,
71                     params, ERROR_PARAMETER_SHORT);
72         }
73 
74         int audioVolumeLevel = params[0];
75 
76         @ValidationResult
77         int addressValidationResult = validateAddress(source, destination);
78         if (addressValidationResult == OK) {
79             return new SetAudioVolumeLevelMessage(source, destination, params, audioVolumeLevel);
80         } else {
81             return new HdmiCecMessage(source, destination, Constants.MESSAGE_SET_AUDIO_VOLUME_LEVEL,
82                     params, addressValidationResult);
83         }
84     }
85 
86     /**
87      * Validates the source and destination addresses for a <Set Audio Volume Level> message.
88      */
validateAddress(int source, int destination)89     public static int validateAddress(int source, int destination) {
90         return HdmiCecMessageValidator.validateAddress(source, destination,
91                 HdmiCecMessageValidator.ADDR_NOT_UNREGISTERED, HdmiCecMessageValidator.ADDR_DIRECT);
92     }
93 
94     /**
95      * Returns the contents of the [Audio Volume Level] operand:
96      * either 0x7F, indicating no change to the current volume level,
97      * or a percentage between 0 and 100 (inclusive).
98      */
getAudioVolumeLevel()99     public int getAudioVolumeLevel() {
100         return mAudioVolumeLevel;
101     }
102 }
103