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 
isLocalDeviceReady()59         protected boolean isLocalDeviceReady() {
60             if (tv() == null) {
61                 Slog.e(TAG, "Local tv device not available");
62                 invokeCallback(HdmiControlManager.RESULT_SOURCE_NOT_AVAILABLE);
63                 return false;
64             }
65             return true;
66         }
67 
invokeCallback(int reason)68         private void invokeCallback(int reason) {
69             try {
70                 if (mCallback != null) {
71                     mCallback.onComplete(reason);
72                 }
73             } catch (RemoteException e) {
74                 Slog.e(TAG, "Invoking callback failed:" + e);
75             }
76         }
77 
78         /**
79          * Implement this method with a customize action to perform when the request gets
80          * invoked in a deferred manner.
81          */
process()82         public abstract void process();
83     }
84 
85     public static class DeviceSelectRequest extends SelectRequest {
DeviceSelectRequest(HdmiControlService srv, int id, IHdmiControlCallback callback)86         private DeviceSelectRequest(HdmiControlService srv, int id, IHdmiControlCallback callback) {
87             super(srv, id, callback);
88         }
89 
90         @Override
process()91         public void process() {
92             if (isLocalDeviceReady()) {
93                 Slog.v(TAG, "calling delayed deviceSelect id:" + mId);
94                 tv().deviceSelect(mId, mCallback);
95             }
96         }
97     }
98 
99     public static class PortSelectRequest extends SelectRequest {
PortSelectRequest(HdmiControlService srv, int id, IHdmiControlCallback callback)100         private PortSelectRequest(HdmiControlService srv, int id, IHdmiControlCallback callback) {
101             super(srv, id, callback);
102         }
103 
104         @Override
process()105         public void process() {
106             if (isLocalDeviceReady()) {
107                 Slog.v(TAG, "calling delayed portSelect id:" + mId);
108                 tv().doManualPortSwitching(mId, mCallback);
109             }
110         }
111     }
112 
newDeviceSelect(HdmiControlService srv, int id, IHdmiControlCallback callback)113     public static DeviceSelectRequest newDeviceSelect(HdmiControlService srv, int id,
114             IHdmiControlCallback callback) {
115         return new DeviceSelectRequest(srv, id, callback);
116     }
117 
newPortSelect(HdmiControlService srv, int id, IHdmiControlCallback callback)118     public static PortSelectRequest newPortSelect(HdmiControlService srv, int id,
119             IHdmiControlCallback callback) {
120         return new PortSelectRequest(srv, id, callback);
121     }
122 
123     // The last select request made by system/app. Note that we do not manage a list of requests
124     // but just keep only the last one since it already invalidates the older ones.
125     private SelectRequest mRequest;
126 
set(SelectRequest request)127     public void set(SelectRequest request) {
128         mRequest = request;
129     }
130 
process()131     public void process() {
132         if (mRequest != null) {
133             mRequest.process();
134             clear();
135         }
136     }
137 
clear()138     public void clear() {
139         mRequest = null;
140     }
141 }
142