1 /*
2  * Copyright (C) 2018 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 package android.hardware.hdmi;
17 
18 import android.annotation.CallbackExecutor;
19 import android.annotation.NonNull;
20 import android.annotation.SystemApi;
21 import android.hardware.hdmi.HdmiControlManager.ControlCallbackResult;
22 import android.os.Binder;
23 import android.os.RemoteException;
24 import android.util.Log;
25 
26 import java.util.Collections;
27 import java.util.List;
28 import java.util.Objects;
29 import java.util.concurrent.Executor;
30 
31 /**
32  * An {@code HdmiSwitchClient} represents a HDMI-CEC switch device.
33  *
34  * <p>HdmiSwitchClient has a CEC device type of HdmiDeviceInfo.DEVICE_PURE_CEC_SWITCH, but it is
35  * used by all Android devices that have multiple HDMI inputs, even if it is not a "pure" swicth
36  * and has another device type like TV or Player.
37  *
38  * @hide
39  */
40 @SystemApi
41 public class HdmiSwitchClient extends HdmiClient {
42 
43     private static final String TAG = "HdmiSwitchClient";
44 
HdmiSwitchClient(IHdmiControlService service)45     /* package */ HdmiSwitchClient(IHdmiControlService service) {
46         super(service);
47     }
48 
getCallbackWrapper(final OnSelectListener listener)49     private static IHdmiControlCallback getCallbackWrapper(final OnSelectListener listener) {
50         return new IHdmiControlCallback.Stub() {
51             @Override
52             public void onComplete(int result) {
53                 listener.onSelect(result);
54             }
55         };
56     }
57 
58     @Override
59     public int getDeviceType() {
60         return HdmiDeviceInfo.DEVICE_PURE_CEC_SWITCH;
61     }
62 
63     /**
64      * Selects a CEC logical device to be a new active source.
65      *
66      * @param logicalAddress logical address of the device to select
67      * @param listener listener to get the result with
68      *
69      * @hide
70      */
71     public void selectDevice(int logicalAddress, @NonNull OnSelectListener listener) {
72         Objects.requireNonNull(listener);
73         try {
74             mService.deviceSelect(logicalAddress, getCallbackWrapper(listener));
75         } catch (RemoteException e) {
76             Log.e(TAG, "failed to select device: ", e);
77             throw e.rethrowFromSystemServer();
78         }
79     }
80 
81     /**
82      * Selects a HDMI port to be a new route path.
83      *
84      * @param portId HDMI port to select
85      * @see {@link android.media.tv.TvInputHardwareInfo#getHdmiPortId()}
86      *     to get portId of a specific TV Input.
87      * @param listener listener to get the result with
88      * @hide
89      */
90     @SystemApi
91     public void selectPort(int portId, @NonNull OnSelectListener listener) {
92         Objects.requireNonNull(listener);
93         try {
94             mService.portSelect(portId, getCallbackWrapper(listener));
95         } catch (RemoteException e) {
96             Log.e(TAG, "failed to select port: ", e);
97             throw e.rethrowFromSystemServer();
98         }
99     }
100 
101     /**
102      * Selects a CEC logical device to be a new active source.
103      *
104      * @param logicalAddress logical address of the device to select
105      * @param listener       listener to get the result with
106      * @deprecated Please use {@link HdmiClient#selectDevice} instead.
107      * @hide
108      */
109     @Deprecated
110     public void selectDevice(
111             int logicalAddress,
112             @NonNull @CallbackExecutor Executor executor,
113             @NonNull OnSelectListener listener) {
114         Objects.requireNonNull(listener);
115         try {
116             mService.deviceSelect(logicalAddress,
117                     new IHdmiControlCallback.Stub() {
118                             @Override
119                             public void onComplete(int result) {
120                                 Binder.withCleanCallingIdentity(
121                                         () -> executor.execute(() -> listener.onSelect(result)));
122                             }
123                     }
124             );
125         } catch (RemoteException e) {
126             Log.e(TAG, "failed to select device: ", e);
127             throw e.rethrowFromSystemServer();
128         }
129     }
130 
131     /**
132      * Selects a HDMI port to be a new route path.
133      *
134      * @param portId   HDMI port to select
135      * @param listener listener to get the result with
136      * @hide
137      */
138     @SystemApi
139     public void selectPort(
140             int portId,
141             @NonNull @CallbackExecutor Executor executor,
142             @NonNull OnSelectListener listener) {
143         Objects.requireNonNull(listener);
144         try {
145             mService.portSelect(portId,
146                     new IHdmiControlCallback.Stub() {
147                             @Override
148                             public void onComplete(int result) {
149                                 Binder.withCleanCallingIdentity(
150                                         () -> executor.execute(() -> listener.onSelect(result)));
151                             }
152                     }
153             );
154         } catch (RemoteException e) {
155             Log.e(TAG, "failed to select port: ", e);
156             throw e.rethrowFromSystemServer();
157         }
158     }
159 
160     /**
161      * Returns all the CEC devices connected to the device.
162      *
163      * <p>This only applies to device with multiple HDMI inputs
164      *
165      * @return list of {@link HdmiDeviceInfo} for connected CEC devices. Empty list is returned if
166      *     there is none.
167      *
168      * @hide
169      * @deprecated Please use {@link HdmiControlManager#getConnectedDevices()} instead.
170      */
171     @Deprecated
172     public List<HdmiDeviceInfo> getDeviceList() {
173         try {
174             return mService.getDeviceList();
175         } catch (RemoteException e) {
176             Log.e("TAG", "Failed to call getDeviceList():", e);
177             return Collections.<HdmiDeviceInfo>emptyList();
178         }
179     }
180 
181     /**
182      * Get the list of the HDMI input port configuration.
183      *
184      * <p>This returns an empty list when the current device does not have HDMI input.
185      *
186      * @return a list of {@link HdmiPortInfo}
187      *
188      * @deprecated Please use {@link HdmiControlManager#getPortInfo()} instead.
189      */
190     @Deprecated
191     @NonNull
192     public List<HdmiPortInfo> getPortInfo() {
193         try {
194             return mService.getPortInfo();
195         } catch (RemoteException e) {
196             Log.e("TAG", "Failed to call getPortInfo():", e);
197             return Collections.<HdmiPortInfo>emptyList();
198         }
199     }
200 
201     /**
202      * Listener interface used to get the result of {@link #deviceSelect} or {@link #portSelect}.
203      *
204      * @hide
205      */
206     @SystemApi
207     public interface OnSelectListener {
208 
209         /**
210          * Called when the operation is finished.
211          *
212          * @param result callback result.
213          * @see {@link ControlCallbackResult}
214          */
215         void onSelect(@ControlCallbackResult int result);
216     }
217 }
218