ActiveSourceHandler.java revision c0c20d0522d7756d80f011e7a54bf3b51c78df41
1a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim/*
2a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim * Copyright (C) 2014 The Android Open Source Project
3a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim *
4a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim * Licensed under the Apache License, Version 2.0 (the "License");
5a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim * you may not use this file except in compliance with the License.
6a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim * You may obtain a copy of the License at
7a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim *
8a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim *      http://www.apache.org/licenses/LICENSE-2.0
9a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim *
10a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim * Unless required by applicable law or agreed to in writing, software
11a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim * distributed under the License is distributed on an "AS IS" BASIS,
12a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim * See the License for the specific language governing permissions and
14a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim * limitations under the License.
15a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim */
16a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim
17a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kimpackage com.android.server.hdmi;
18a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim
19a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kimimport android.annotation.Nullable;
20a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kimimport android.hardware.hdmi.IHdmiControlCallback;
21a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kimimport android.hardware.hdmi.HdmiCecDeviceInfo;
22c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kimimport android.hardware.hdmi.HdmiControlManager;
23a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kimimport android.os.RemoteException;
24a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kimimport android.util.Slog;
25a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim
26a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim/**
27a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim * Handles CEC command <Active Source>.
2879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang * <p>
298333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim * Used by feature actions that need to handle the command in their flow. Only for TV
308333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim * local device.
31a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim */
32a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kimfinal class ActiveSourceHandler {
33a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim    private static final String TAG = "ActiveSourceHandler";
34a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim
358333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim    private final HdmiCecLocalDeviceTv mSource;
36a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim    private final HdmiControlService mService;
3779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang    @Nullable
3879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang    private final IHdmiControlCallback mCallback;
39a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim
408333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim    static ActiveSourceHandler create(HdmiCecLocalDeviceTv source, IHdmiControlCallback callback) {
4179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang        if (source == null) {
42a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim            Slog.e(TAG, "Wrong arguments");
43a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim            return null;
44a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim        }
4579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang        return new ActiveSourceHandler(source, callback);
46a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim    }
47a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim
488333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim    private ActiveSourceHandler(HdmiCecLocalDeviceTv source, IHdmiControlCallback callback) {
4979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang        mSource = source;
5079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang        mService = mSource.getService();
51a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim        mCallback = callback;
52a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim    }
53a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim
54a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim    /**
55a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim     * Handles the incoming active source command.
56a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim     *
578333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim     * @param activeAddress logical address of the device to be the active source
588333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim     * @param activePath routing path of the device to be the active source
59a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim     */
608333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim    void process(int activeAddress, int activePath) {
618333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim        // Seq #17
628333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim        HdmiCecLocalDeviceTv tv = mSource;
638333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim        if (getSourcePath() == activePath && tv.getActiveSource() == getSourceAddress()) {
64c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim            invokeCallback(HdmiControlManager.RESULT_SUCCESS);
65a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim            return;
66a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim        }
678333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim        HdmiCecDeviceInfo device = mService.getDeviceInfo(activeAddress);
68a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim        if (device == null) {
6992b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim            tv.addAndStartAction(new NewDeviceAction(tv, activeAddress, activePath));
70a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim        }
71a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim
728333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim        int currentActive = tv.getActiveSource();
738333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim        int currentPath = tv.getActivePath();
744d43d93743222311c6377d4904c19ccb93699d3bJinsuk Kim        if (!tv.isProhibitMode()) {
758333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim            tv.updateActiveSource(activeAddress, activePath);
768333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim            if (currentActive != activeAddress && currentPath != activePath) {
778333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim                tv.updateActivePortId(mService.pathToPortId(activePath));
78a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim            }
79c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim            invokeCallback(HdmiControlManager.RESULT_SUCCESS);
80a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim        } else {
81a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim            // TV is in a mode that should keep its current source/input from
82a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim            // being changed for its operation. Reclaim the active source
83a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim            // or switch the port back to the one used for the current mode.
848333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim            if (currentActive == getSourceAddress()) {
85a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim                HdmiCecMessage activeSource =
868333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim                        HdmiCecMessageBuilder.buildActiveSource(currentActive, currentPath);
87a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim                mService.sendCecCommand(activeSource);
888333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim                tv.updateActiveSource(currentActive, currentPath);
89c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim                invokeCallback(HdmiControlManager.RESULT_SUCCESS);
90a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim            } else {
918333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim                HdmiCecMessage routingChange = HdmiCecMessageBuilder.buildRoutingChange(
928333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim                        getSourceAddress(), activePath, currentPath);
938333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim                mService.sendCecCommand(routingChange);
9404fd28046acc2ac74339ed94cec76a0bfda846f7Jinsuk Kim                tv.addAndStartAction(new RoutingControlAction(tv, currentPath, true, mCallback));
95a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim            }
96a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim        }
97a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim    }
98a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim
9979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang    private final int getSourceAddress() {
10079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang        return mSource.getDeviceInfo().getLogicalAddress();
10179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang    }
10279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang
10379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang    private final int getSourcePath() {
10479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang        return mSource.getDeviceInfo().getPhysicalAddress();
10579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang    }
10679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang
107a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim    private void invokeCallback(int result) {
108a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim        if (mCallback == null) {
109a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim            return;
110a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim        }
111a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim        try {
112a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim            mCallback.onComplete(result);
113a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim        } catch (RemoteException e) {
114a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim            Slog.e(TAG, "Callback failed:" + e);
115a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim        }
116a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim    }
117a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim}
118