blob: 01547c16e9b54014cf9c05a88723e4d04b791d9e [file] [log] [blame]
Jinsuk Kima6ce7702014-05-11 06:54:49 +09001/*
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;
Jungshik Jang61f4fbd2014-08-06 19:21:12 +090021import android.hardware.hdmi.HdmiDeviceInfo;
Jinsuk Kimc0c20d02014-07-04 14:34:31 +090022import android.hardware.hdmi.HdmiControlManager;
Jinsuk Kima6ce7702014-05-11 06:54:49 +090023import android.os.RemoteException;
24import android.util.Slog;
25
Jinsuk Kim72b7d732014-07-24 09:15:35 +090026import com.android.server.hdmi.HdmiCecLocalDevice.ActiveSource;
27
Jinsuk Kima6ce7702014-05-11 06:54:49 +090028/**
29 * Handles CEC command <Active Source>.
Jungshik Jang79c58a42014-06-16 16:45:36 +090030 * <p>
Jinsuk Kim83335712014-06-24 07:57:00 +090031 * Used by feature actions that need to handle the command in their flow. Only for TV
32 * local device.
Jinsuk Kima6ce7702014-05-11 06:54:49 +090033 */
34final class ActiveSourceHandler {
35 private static final String TAG = "ActiveSourceHandler";
36
Jinsuk Kim83335712014-06-24 07:57:00 +090037 private final HdmiCecLocalDeviceTv mSource;
Jinsuk Kima6ce7702014-05-11 06:54:49 +090038 private final HdmiControlService mService;
Jungshik Jang79c58a42014-06-16 16:45:36 +090039 @Nullable
40 private final IHdmiControlCallback mCallback;
Jinsuk Kima6ce7702014-05-11 06:54:49 +090041
Jinsuk Kim83335712014-06-24 07:57:00 +090042 static ActiveSourceHandler create(HdmiCecLocalDeviceTv source, IHdmiControlCallback callback) {
Jungshik Jang79c58a42014-06-16 16:45:36 +090043 if (source == null) {
Jinsuk Kima6ce7702014-05-11 06:54:49 +090044 Slog.e(TAG, "Wrong arguments");
45 return null;
46 }
Jungshik Jang79c58a42014-06-16 16:45:36 +090047 return new ActiveSourceHandler(source, callback);
Jinsuk Kima6ce7702014-05-11 06:54:49 +090048 }
49
Jinsuk Kim83335712014-06-24 07:57:00 +090050 private ActiveSourceHandler(HdmiCecLocalDeviceTv source, IHdmiControlCallback callback) {
Jungshik Jang79c58a42014-06-16 16:45:36 +090051 mSource = source;
52 mService = mSource.getService();
Jinsuk Kima6ce7702014-05-11 06:54:49 +090053 mCallback = callback;
54 }
55
56 /**
57 * Handles the incoming active source command.
58 *
Jinsuk Kim72b7d732014-07-24 09:15:35 +090059 * @param newActive new active source information
Jinsuk Kimbdf27fb2014-10-20 10:00:04 +090060 * @param deviceType device type of the new active source
Jinsuk Kima6ce7702014-05-11 06:54:49 +090061 */
Jinsuk Kimbdf27fb2014-10-20 10:00:04 +090062 void process(ActiveSource newActive, int deviceType) {
Jinsuk Kim83335712014-06-24 07:57:00 +090063 // Seq #17
64 HdmiCecLocalDeviceTv tv = mSource;
Jungshik Jang61f4fbd2014-08-06 19:21:12 +090065 HdmiDeviceInfo device = mService.getDeviceInfo(newActive.logicalAddress);
Jinsuk Kima6ce7702014-05-11 06:54:49 +090066 if (device == null) {
Jinsuk Kimbdf27fb2014-10-20 10:00:04 +090067 tv.startNewDeviceAction(newActive, deviceType);
Jinsuk Kima6ce7702014-05-11 06:54:49 +090068 }
69
Jinsuk Kim4d43d932014-07-03 16:43:58 +090070 if (!tv.isProhibitMode()) {
Jinsuk Kim04f813c2015-04-02 16:56:49 +090071 ActiveSource old = ActiveSource.of(tv.getActiveSource());
Jinsuk Kim72b7d732014-07-24 09:15:35 +090072 tv.updateActiveSource(newActive);
Jinsuk Kim7c3a9562014-08-01 11:07:42 +090073 boolean notifyInputChange = (mCallback == null);
Jinsuk Kim04f813c2015-04-02 16:56:49 +090074 if (!old.equals(newActive)) {
75 tv.setPrevPortId(tv.getActivePortId());
76 }
Jinsuk Kim7c3a9562014-08-01 11:07:42 +090077 tv.updateActiveInput(newActive.physicalAddress, notifyInputChange);
Jinsuk Kimc0c20d02014-07-04 14:34:31 +090078 invokeCallback(HdmiControlManager.RESULT_SUCCESS);
Jinsuk Kima6ce7702014-05-11 06:54:49 +090079 } else {
80 // TV is in a mode that should keep its current source/input from
81 // being changed for its operation. Reclaim the active source
82 // or switch the port back to the one used for the current mode.
Jinsuk Kim7c3a9562014-08-01 11:07:42 +090083 ActiveSource current = tv.getActiveSource();
Jinsuk Kim72b7d732014-07-24 09:15:35 +090084 if (current.logicalAddress == getSourceAddress()) {
85 HdmiCecMessage activeSourceCommand = HdmiCecMessageBuilder.buildActiveSource(
86 current.logicalAddress, current.physicalAddress);
87 mService.sendCecCommand(activeSourceCommand);
88 tv.updateActiveSource(current);
Jinsuk Kimc0c20d02014-07-04 14:34:31 +090089 invokeCallback(HdmiControlManager.RESULT_SUCCESS);
Jinsuk Kima6ce7702014-05-11 06:54:49 +090090 } else {
Jinsuk Kim546d8672014-11-24 07:30:54 +090091 tv.startRoutingControl(newActive.physicalAddress, current.physicalAddress, true,
92 mCallback);
Jinsuk Kima6ce7702014-05-11 06:54:49 +090093 }
94 }
95 }
96
Jungshik Jang79c58a42014-06-16 16:45:36 +090097 private final int getSourceAddress() {
98 return mSource.getDeviceInfo().getLogicalAddress();
99 }
100
Jinsuk Kima6ce7702014-05-11 06:54:49 +0900101 private void invokeCallback(int result) {
102 if (mCallback == null) {
103 return;
104 }
105 try {
106 mCallback.onComplete(result);
107 } catch (RemoteException e) {
108 Slog.e(TAG, "Callback failed:" + e);
109 }
110 }
111}