HdmiCecLocalDevicePlayback.java revision 38db629d897e9d7c8e31ce0a7e985981e3e12996
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.hardware.hdmi.HdmiCec; 20import android.hardware.hdmi.HdmiCecMessage; 21import android.hardware.hdmi.IHdmiControlCallback; 22import android.os.RemoteException; 23import android.util.Slog; 24 25import com.android.server.hdmi.HdmiAnnotations.ServiceThreadOnly; 26 27/** 28 * Represent a logical device of type Playback residing in Android system. 29 */ 30final class HdmiCecLocalDevicePlayback extends HdmiCecLocalDevice { 31 private static final String TAG = "HdmiCecLocalDevicePlayback"; 32 33 private boolean mIsActiveSource = false; 34 35 HdmiCecLocalDevicePlayback(HdmiControlService service) { 36 super(service, HdmiCec.DEVICE_PLAYBACK); 37 } 38 39 @Override 40 @ServiceThreadOnly 41 protected void onAddressAllocated(int logicalAddress) { 42 assertRunOnServiceThread(); 43 mService.sendCecCommand(HdmiCecMessageBuilder.buildReportPhysicalAddressCommand( 44 mAddress, mService.getPhysicalAddress(), mDeviceType)); 45 } 46 47 @ServiceThreadOnly 48 void oneTouchPlay(IHdmiControlCallback callback) { 49 assertRunOnServiceThread(); 50 if (hasAction(OneTouchPlayAction.class)) { 51 Slog.w(TAG, "oneTouchPlay already in progress"); 52 invokeCallback(callback, HdmiCec.RESULT_ALREADY_IN_PROGRESS); 53 return; 54 } 55 56 // TODO: Consider the case of multiple TV sets. For now we always direct the command 57 // to the primary one. 58 OneTouchPlayAction action = OneTouchPlayAction.create(this, HdmiCec.ADDR_TV, callback); 59 if (action == null) { 60 Slog.w(TAG, "Cannot initiate oneTouchPlay"); 61 invokeCallback(callback, HdmiCec.RESULT_EXCEPTION); 62 return; 63 } 64 addAndStartAction(action); 65 } 66 67 @ServiceThreadOnly 68 void queryDisplayStatus(IHdmiControlCallback callback) { 69 assertRunOnServiceThread(); 70 if (hasAction(DevicePowerStatusAction.class)) { 71 Slog.w(TAG, "queryDisplayStatus already in progress"); 72 invokeCallback(callback, HdmiCec.RESULT_ALREADY_IN_PROGRESS); 73 return; 74 } 75 DevicePowerStatusAction action = DevicePowerStatusAction.create(this, 76 HdmiCec.ADDR_TV, callback); 77 if (action == null) { 78 Slog.w(TAG, "Cannot initiate queryDisplayStatus"); 79 invokeCallback(callback, HdmiCec.RESULT_EXCEPTION); 80 return; 81 } 82 addAndStartAction(action); 83 } 84 85 @ServiceThreadOnly 86 private void invokeCallback(IHdmiControlCallback callback, int result) { 87 assertRunOnServiceThread(); 88 try { 89 callback.onComplete(result); 90 } catch (RemoteException e) { 91 Slog.e(TAG, "Invoking callback failed:" + e); 92 } 93 } 94 95 @Override 96 @ServiceThreadOnly 97 void onHotplug(int portId, boolean connected) { 98 assertRunOnServiceThread(); 99 mCecMessageCache.flushAll(); 100 mIsActiveSource = false; 101 if (connected && mService.isPowerStandbyOrTransient()) { 102 mService.wakeUp(); 103 } 104 } 105 106 @ServiceThreadOnly 107 void markActiveSource() { 108 assertRunOnServiceThread(); 109 mIsActiveSource = true; 110 } 111 112 @Override 113 @ServiceThreadOnly 114 protected boolean handleActiveSource(HdmiCecMessage message) { 115 assertRunOnServiceThread(); 116 int physicalAddress = HdmiUtils.twoBytesToInt(message.getParams()); 117 if (physicalAddress != mService.getPhysicalAddress()) { 118 mIsActiveSource = false; 119 if (mService.isPowerOnOrTransient()) { 120 mService.standby(); 121 } 122 return true; 123 } 124 return false; 125 } 126 127 @Override 128 @ServiceThreadOnly 129 protected boolean handleSetStreamPath(HdmiCecMessage message) { 130 assertRunOnServiceThread(); 131 int physicalAddress = HdmiUtils.twoBytesToInt(message.getParams()); 132 if (physicalAddress == mService.getPhysicalAddress()) { 133 if (mService.isPowerStandbyOrTransient()) { 134 mService.wakeUp(); 135 } 136 return true; 137 } 138 return false; 139 } 140 141 @Override 142 @ServiceThreadOnly 143 protected void onTransitionToStandby(boolean initiatedByCec) { 144 assertRunOnServiceThread(); 145 if (!initiatedByCec && mIsActiveSource) { 146 mService.sendCecCommand(HdmiCecMessageBuilder.buildInactiveSource( 147 mAddress, mService.getPhysicalAddress())); 148 } 149 mIsActiveSource = false; 150 checkIfPendingActionsCleared(); 151 } 152} 153