ActiveSourceHandler.java revision 60cffce420db4c3395f86d3b9bb36003adf26f5d
1/*
2 * Copyright (C) 2014 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
17package com.android.server.hdmi;
18
19import android.annotation.Nullable;
20import android.hardware.hdmi.IHdmiControlCallback;
21import android.hardware.hdmi.HdmiCec;
22import android.hardware.hdmi.HdmiCecDeviceInfo;
23import android.hardware.hdmi.HdmiCecMessage;
24import android.os.RemoteException;
25import android.util.Slog;
26
27/**
28 * Handles CEC command <Active Source>.
29 *
30 * <p>Used by feature actions that need to handle the command in their flow.
31 */
32final class ActiveSourceHandler {
33    private static final String TAG = "ActiveSourceHandler";
34
35    private final HdmiControlService mService;
36    private final int mSourceAddress;
37    private final int mSourcePath;
38    @Nullable private final IHdmiControlCallback mCallback;
39
40    static ActiveSourceHandler create(HdmiControlService service, int sourceAddress,
41            int sourcePath, IHdmiControlCallback callback) {
42        if (service == null) {
43            Slog.e(TAG, "Wrong arguments");
44            return null;
45        }
46        return new ActiveSourceHandler(service, sourceAddress, sourcePath, callback);
47    }
48
49    private ActiveSourceHandler(HdmiControlService service, int sourceAddress, int sourcePath,
50            IHdmiControlCallback callback) {
51        mService = service;
52        mSourceAddress = sourceAddress;
53        mSourcePath = sourcePath;
54        mCallback = callback;
55    }
56
57    /**
58     * Handles the incoming active source command.
59     *
60     * @param deviceLogicalAddress logical address of the device to be the active source
61     * @param routingPath routing path of the device to be the active source
62     */
63    void process(int deviceLogicalAddress, int routingPath) {
64        if (mSourcePath == routingPath && mService.getActiveSource() == mSourceAddress) {
65            invokeCallback(HdmiCec.RESULT_SUCCESS);
66            return;
67        }
68        HdmiCecDeviceInfo device = mService.getDeviceInfo(deviceLogicalAddress);
69        if (device == null) {
70            // "New device action" initiated by <Active Source> does not require
71            // "Routing change action".
72            mService.addAndStartAction(new NewDeviceAction(mService, mSourceAddress,
73                    deviceLogicalAddress, routingPath, false));
74        }
75
76        if (!mService.isInPresetInstallationMode()) {
77            int prevActiveInput = mService.getActiveInput();
78            mService.updateActiveDevice(deviceLogicalAddress, routingPath);
79            if (prevActiveInput != mService.getActiveInput()) {
80                // TODO: change port input here.
81            }
82            invokeCallback(HdmiCec.RESULT_SUCCESS);
83        } else {
84            // TV is in a mode that should keep its current source/input from
85            // being changed for its operation. Reclaim the active source
86            // or switch the port back to the one used for the current mode.
87            if (mService.getActiveSource() == mSourceAddress) {
88                HdmiCecMessage activeSource =
89                        HdmiCecMessageBuilder.buildActiveSource(mSourceAddress, mSourcePath);
90                mService.sendCecCommand(activeSource);
91                mService.updateActiveDevice(deviceLogicalAddress, routingPath);
92                invokeCallback(HdmiCec.RESULT_SUCCESS);
93            } else {
94                int activePath = mService.getActivePath();
95                mService.sendCecCommand(HdmiCecMessageBuilder.buildRoutingChange(mSourceAddress,
96                        routingPath, activePath));
97                // TODO: Start port select action here
98                // PortSelectAction action = new PortSelectAction(mService, mSourceAddress,
99                //        activePath, mCallback);
100                // mService.addActionAndStart(action);
101            }
102        }
103    }
104
105    private void invokeCallback(int result) {
106        if (mCallback == null) {
107            return;
108        }
109        try {
110            mCallback.onComplete(result);
111        } catch (RemoteException e) {
112            Slog.e(TAG, "Callback failed:" + e);
113        }
114    }
115}
116