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