1 /*
2  * Copyright (C) 2015 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.hardware.hdmi.HdmiControlManager;
20 import android.hardware.hdmi.IHdmiControlCallback;
21 import android.os.RemoteException;
22 import android.util.Slog;
23 
24 /**
25  * Buffer for portSelect/deviceSelect requests. Requests made before the address allocation
26  * are stored in this buffer, and processed when the allocation is completed.
27  *
28  * <p>This is put into action only if we are a TV device.
29  */
30 public class SelectRequestBuffer {
31     private static final String TAG = "SelectRequestBuffer";
32 
33     public static final SelectRequestBuffer EMPTY_BUFFER = new SelectRequestBuffer() {
34         @Override
35         public void process() {
36             // Do nothing.
37         }
38     };
39 
40     /**
41      * Parent class from which buffer for select requests are inherited. Keeps the callback
42      * and the device/port ID.
43      */
44     public static abstract class SelectRequest {
45         protected final HdmiControlService mService;
46         protected final IHdmiControlCallback mCallback;
47         protected final int mId;
48 
SelectRequest(HdmiControlService service, int id, IHdmiControlCallback callback)49         public SelectRequest(HdmiControlService service, int id, IHdmiControlCallback callback) {
50             mService = service;
51             mId = id;
52             mCallback = callback;
53         }
54 
tv()55         protected HdmiCecLocalDeviceTv tv() {
56             return mService.tv();
57         }
58 
audioSystem()59         protected HdmiCecLocalDeviceAudioSystem audioSystem() {
60             return mService.audioSystem();
61         }
62 
isLocalDeviceReady()63         protected boolean isLocalDeviceReady() {
64             if (tv() == null) {
65                 Slog.e(TAG, "Local tv device not available");
66                 invokeCallback(HdmiControlManager.RESULT_SOURCE_NOT_AVAILABLE);
67                 return false;
68             }
69             return true;
70         }
71 
invokeCallback(int reason)72         private void invokeCallback(int reason) {
73             try {
74                 if (mCallback != null) {
75                     mCallback.onComplete(reason);
76                 }
77             } catch (RemoteException e) {
78                 Slog.e(TAG, "Invoking callback failed:" + e);
79             }
80         }
81 
82         /**
83          * Implement this method with a customize action to perform when the request gets
84          * invoked in a deferred manner.
85          */
process()86         public abstract void process();
87     }
88 
89     public static class DeviceSelectRequest extends SelectRequest {
DeviceSelectRequest(HdmiControlService srv, int id, IHdmiControlCallback callback)90         private DeviceSelectRequest(HdmiControlService srv, int id, IHdmiControlCallback callback) {
91             super(srv, id, callback);
92         }
93 
94         @Override
process()95         public void process() {
96             if (isLocalDeviceReady()) {
97                 Slog.v(TAG, "calling delayed deviceSelect id:" + mId);
98                 tv().deviceSelect(mId, mCallback);
99             }
100         }
101     }
102 
103     public static class PortSelectRequest extends SelectRequest {
PortSelectRequest(HdmiControlService srv, int id, IHdmiControlCallback callback)104         private PortSelectRequest(HdmiControlService srv, int id, IHdmiControlCallback callback) {
105             super(srv, id, callback);
106         }
107 
108         @Override
process()109         public void process() {
110             if (isLocalDeviceReady()) {
111                 Slog.v(TAG, "calling delayed portSelect id:" + mId);
112                 HdmiCecLocalDeviceTv tv = tv();
113                 if (tv != null) {
114                     tv.doManualPortSwitching(mId, mCallback);
115                     return;
116                 }
117                 HdmiCecLocalDeviceAudioSystem audioSystem = audioSystem();
118                 if (audioSystem != null) {
119                     audioSystem.doManualPortSwitching(mId, mCallback);
120                 }
121             }
122         }
123     }
124 
newDeviceSelect(HdmiControlService srv, int id, IHdmiControlCallback callback)125     public static DeviceSelectRequest newDeviceSelect(HdmiControlService srv, int id,
126             IHdmiControlCallback callback) {
127         return new DeviceSelectRequest(srv, id, callback);
128     }
129 
newPortSelect(HdmiControlService srv, int id, IHdmiControlCallback callback)130     public static PortSelectRequest newPortSelect(HdmiControlService srv, int id,
131             IHdmiControlCallback callback) {
132         return new PortSelectRequest(srv, id, callback);
133     }
134 
135     // The last select request made by system/app. Note that we do not manage a list of requests
136     // but just keep only the last one since it already invalidates the older ones.
137     private SelectRequest mRequest;
138 
set(SelectRequest request)139     public void set(SelectRequest request) {
140         mRequest = request;
141     }
142 
process()143     public void process() {
144         if (mRequest != null) {
145             mRequest.process();
146             clear();
147         }
148     }
149 
clear()150     public void clear() {
151         mRequest = null;
152     }
153 }
154