Introduce @ServiceThreadOnly and @IothreadOnly to HdmiControlService
Many of hdmi service modules assumes that it runs on service thread without any lock. But it's a bit hard to distinguish whether a method runs on service thread or not even though there is run-time assertion (runOnServiceThread()) is top of method. @ServiceThreadOnly interface documents that a method should run on service thread while @IoThreadOnly documents that a method should run on io thread. Change-Id: Ia4a6a48675d2302fb2cb7a8a807fcf112da5d4e7
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.hdmi;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Annotation container for Hdmi control service package.
|
||||
*/
|
||||
public class HdmiAnnotations {
|
||||
/**
|
||||
* Annotation type to used to mark a method which should be run on service thread.
|
||||
* This annotation should go with {@code assertRunOnServiceThread} used to verify
|
||||
* whether it's called from service thread.
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.METHOD)
|
||||
public @interface ServiceThreadOnly {
|
||||
}
|
||||
|
||||
/**
|
||||
* Annotation type to used to mark a method which should be run on io thread.
|
||||
* This annotation should go with {@code assertRunOnIoThread} used to verify
|
||||
* whether it's called from io thread.
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.METHOD)
|
||||
public @interface IoThreadOnly {
|
||||
}
|
||||
}
|
||||
@@ -26,6 +26,8 @@ import android.util.Slog;
|
||||
import android.util.SparseArray;
|
||||
|
||||
import com.android.internal.util.Predicate;
|
||||
import com.android.server.hdmi.HdmiAnnotations.IoThreadOnly;
|
||||
import com.android.server.hdmi.HdmiAnnotations.ServiceThreadOnly;
|
||||
import com.android.server.hdmi.HdmiControlService.DevicePollingCallback;
|
||||
|
||||
import libcore.util.EmptyArray;
|
||||
@@ -144,7 +146,9 @@ final class HdmiCecController {
|
||||
mNativePtr = nativePtr;
|
||||
}
|
||||
|
||||
@ServiceThreadOnly
|
||||
void addLocalDevice(int deviceType, HdmiCecLocalDevice device) {
|
||||
assertRunOnServiceThread();
|
||||
mLocalDevices.put(deviceType, device);
|
||||
}
|
||||
|
||||
@@ -161,6 +165,7 @@ final class HdmiCecController {
|
||||
* Otherwise, scan address will start from {@code preferredAddress}
|
||||
* @param callback callback interface to report allocated logical address to caller
|
||||
*/
|
||||
@ServiceThreadOnly
|
||||
void allocateLogicalAddress(final int deviceType, final int preferredAddress,
|
||||
final AllocateAddressCallback callback) {
|
||||
assertRunOnServiceThread();
|
||||
@@ -173,6 +178,7 @@ final class HdmiCecController {
|
||||
});
|
||||
}
|
||||
|
||||
@IoThreadOnly
|
||||
private void handleAllocateLogicalAddress(final int deviceType, int preferredAddress,
|
||||
final AllocateAddressCallback callback) {
|
||||
assertRunOnIoThread();
|
||||
@@ -245,6 +251,7 @@ final class HdmiCecController {
|
||||
* @param newLogicalAddress a logical address to be added
|
||||
* @return 0 on success. Otherwise, returns negative value
|
||||
*/
|
||||
@ServiceThreadOnly
|
||||
int addLogicalAddress(int newLogicalAddress) {
|
||||
assertRunOnServiceThread();
|
||||
if (HdmiCec.isValidAddress(newLogicalAddress)) {
|
||||
@@ -259,6 +266,7 @@ final class HdmiCecController {
|
||||
*
|
||||
* <p>Declared as package-private. accessed by {@link HdmiControlService} only.
|
||||
*/
|
||||
@ServiceThreadOnly
|
||||
void clearLogicalAddress() {
|
||||
assertRunOnServiceThread();
|
||||
// TODO: consider to backup logical address so that new logical address
|
||||
@@ -277,6 +285,7 @@ final class HdmiCecController {
|
||||
* @return CEC physical address of the device. The range of success address
|
||||
* is between 0x0000 and 0xFFFF. If failed it returns -1
|
||||
*/
|
||||
@ServiceThreadOnly
|
||||
int getPhysicalAddress() {
|
||||
assertRunOnServiceThread();
|
||||
return nativeGetPhysicalAddress(mNativePtr);
|
||||
@@ -287,6 +296,7 @@ final class HdmiCecController {
|
||||
*
|
||||
* <p>Declared as package-private. accessed by {@link HdmiControlService} only.
|
||||
*/
|
||||
@ServiceThreadOnly
|
||||
int getVersion() {
|
||||
assertRunOnServiceThread();
|
||||
return nativeGetVersion(mNativePtr);
|
||||
@@ -297,6 +307,7 @@ final class HdmiCecController {
|
||||
*
|
||||
* <p>Declared as package-private. accessed by {@link HdmiControlService} only.
|
||||
*/
|
||||
@ServiceThreadOnly
|
||||
int getVendorId() {
|
||||
assertRunOnServiceThread();
|
||||
return nativeGetVendorId(mNativePtr);
|
||||
@@ -311,6 +322,7 @@ final class HdmiCecController {
|
||||
* @param value a value of option. Actual value varies flag. For more
|
||||
* details, look at description of flags
|
||||
*/
|
||||
@ServiceThreadOnly
|
||||
void setOption(int flag, int value) {
|
||||
assertRunOnServiceThread();
|
||||
nativeSetOption(mNativePtr, flag, value);
|
||||
@@ -321,6 +333,7 @@ final class HdmiCecController {
|
||||
*
|
||||
* @param enabled whether to enable/disable ARC
|
||||
*/
|
||||
@ServiceThreadOnly
|
||||
void setAudioReturnChannel(boolean enabled) {
|
||||
assertRunOnServiceThread();
|
||||
nativeSetAudioReturnChannel(mNativePtr, enabled);
|
||||
@@ -332,6 +345,7 @@ final class HdmiCecController {
|
||||
* @param port port number to check connection status
|
||||
* @return true if connected; otherwise, return false
|
||||
*/
|
||||
@ServiceThreadOnly
|
||||
boolean isConnected(int port) {
|
||||
assertRunOnServiceThread();
|
||||
return nativeIsConnected(mNativePtr, port);
|
||||
@@ -347,6 +361,7 @@ final class HdmiCecController {
|
||||
* @param pickStrategy strategy how to pick polling candidates
|
||||
* @param retryCount the number of retry used to send polling message to remote devices
|
||||
*/
|
||||
@ServiceThreadOnly
|
||||
void pollDevices(DevicePollingCallback callback, int pickStrategy, int retryCount) {
|
||||
assertRunOnServiceThread();
|
||||
|
||||
@@ -360,6 +375,7 @@ final class HdmiCecController {
|
||||
*
|
||||
* <p>Declared as package-private. accessed by {@link HdmiControlService} only.
|
||||
*/
|
||||
@ServiceThreadOnly
|
||||
List<HdmiCecLocalDevice> getLocalDeviceList() {
|
||||
assertRunOnServiceThread();
|
||||
return HdmiUtils.sparseArrayToList(mLocalDevices);
|
||||
@@ -400,7 +416,9 @@ final class HdmiCecController {
|
||||
return pollingCandidates;
|
||||
}
|
||||
|
||||
@ServiceThreadOnly
|
||||
private boolean isAllocatedLocalDeviceAddress(int address) {
|
||||
assertRunOnServiceThread();
|
||||
for (int i = 0; i < mLocalDevices.size(); ++i) {
|
||||
if (mLocalDevices.valueAt(i).isAddressOf(address)) {
|
||||
return true;
|
||||
@@ -409,6 +427,7 @@ final class HdmiCecController {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ServiceThreadOnly
|
||||
private void runDevicePolling(final List<Integer> candidates, final int retryCount,
|
||||
final DevicePollingCallback callback) {
|
||||
assertRunOnServiceThread();
|
||||
@@ -433,6 +452,7 @@ final class HdmiCecController {
|
||||
});
|
||||
}
|
||||
|
||||
@IoThreadOnly
|
||||
private boolean sendPollMessage(int address, int retryCount) {
|
||||
assertRunOnIoThread();
|
||||
for (int i = 0; i < retryCount; ++i) {
|
||||
@@ -480,6 +500,7 @@ final class HdmiCecController {
|
||||
return isAllocatedLocalDeviceAddress(address);
|
||||
}
|
||||
|
||||
@ServiceThreadOnly
|
||||
private void onReceiveCommand(HdmiCecMessage message) {
|
||||
assertRunOnServiceThread();
|
||||
if (isAcceptableAddress(message.getDestination())
|
||||
@@ -493,16 +514,20 @@ final class HdmiCecController {
|
||||
HdmiCecMessage cecMessage = HdmiCecMessageBuilder.buildFeatureAbortCommand(
|
||||
sourceAddress, message.getSource(), message.getOpcode(),
|
||||
HdmiConstants.ABORT_REFUSED);
|
||||
sendCommand(cecMessage, null);
|
||||
sendCommand(cecMessage);
|
||||
}
|
||||
}
|
||||
|
||||
@ServiceThreadOnly
|
||||
void sendCommand(HdmiCecMessage cecMessage) {
|
||||
assertRunOnServiceThread();
|
||||
sendCommand(cecMessage, null);
|
||||
}
|
||||
|
||||
@ServiceThreadOnly
|
||||
void sendCommand(final HdmiCecMessage cecMessage,
|
||||
final HdmiControlService.SendMessageCallback callback) {
|
||||
assertRunOnServiceThread();
|
||||
runOnIoThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@@ -527,6 +552,7 @@ final class HdmiCecController {
|
||||
/**
|
||||
* Called by native when incoming CEC message arrived.
|
||||
*/
|
||||
@ServiceThreadOnly
|
||||
private void handleIncomingCecCommand(int srcAddress, int dstAddress, byte[] body) {
|
||||
assertRunOnServiceThread();
|
||||
onReceiveCommand(HdmiCecMessageBuilder.of(srcAddress, dstAddress, body));
|
||||
|
||||
@@ -23,6 +23,7 @@ import android.os.Looper;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.server.hdmi.HdmiAnnotations.ServiceThreadOnly;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
@@ -87,7 +88,9 @@ abstract class HdmiCecLocalDevice {
|
||||
}
|
||||
}
|
||||
|
||||
@ServiceThreadOnly
|
||||
void init() {
|
||||
assertRunOnServiceThread();
|
||||
mPreferredAddress = HdmiCec.ADDR_UNREGISTERED;
|
||||
// TODO: load preferred address from permanent storage.
|
||||
}
|
||||
@@ -103,9 +106,9 @@ abstract class HdmiCecLocalDevice {
|
||||
* @param message incoming message
|
||||
* @return true if consumed a message; otherwise, return false.
|
||||
*/
|
||||
@ServiceThreadOnly
|
||||
final boolean dispatchMessage(HdmiCecMessage message) {
|
||||
assertRunOnServiceThread();
|
||||
|
||||
int dest = message.getDestination();
|
||||
if (dest != mAddress && dest != HdmiCec.ADDR_BROADCAST) {
|
||||
return false;
|
||||
@@ -115,9 +118,9 @@ abstract class HdmiCecLocalDevice {
|
||||
return onMessage(message);
|
||||
}
|
||||
|
||||
@ServiceThreadOnly
|
||||
protected final boolean onMessage(HdmiCecMessage message) {
|
||||
assertRunOnServiceThread();
|
||||
|
||||
if (dispatchMessageToAction(message)) {
|
||||
return true;
|
||||
}
|
||||
@@ -147,7 +150,9 @@ abstract class HdmiCecLocalDevice {
|
||||
}
|
||||
}
|
||||
|
||||
@ServiceThreadOnly
|
||||
private boolean dispatchMessageToAction(HdmiCecMessage message) {
|
||||
assertRunOnServiceThread();
|
||||
for (FeatureAction action : mActions) {
|
||||
if (action.processCommand(message)) {
|
||||
return true;
|
||||
@@ -156,6 +161,7 @@ abstract class HdmiCecLocalDevice {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ServiceThreadOnly
|
||||
protected boolean handleGivePhysicalAddress() {
|
||||
assertRunOnServiceThread();
|
||||
|
||||
@@ -166,9 +172,9 @@ abstract class HdmiCecLocalDevice {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ServiceThreadOnly
|
||||
protected boolean handleGiveDeviceVendorId() {
|
||||
assertRunOnServiceThread();
|
||||
|
||||
int vendorId = mService.getVendorId();
|
||||
HdmiCecMessage cecMessage = HdmiCecMessageBuilder.buildDeviceVendorIdCommand(
|
||||
mAddress, vendorId);
|
||||
@@ -176,9 +182,9 @@ abstract class HdmiCecLocalDevice {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ServiceThreadOnly
|
||||
protected boolean handleGetCecVersion(HdmiCecMessage message) {
|
||||
assertRunOnServiceThread();
|
||||
|
||||
int version = mService.getCecVersion();
|
||||
HdmiCecMessage cecMessage = HdmiCecMessageBuilder.buildCecVersion(message.getDestination(),
|
||||
message.getSource(), version);
|
||||
@@ -186,9 +192,9 @@ abstract class HdmiCecLocalDevice {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ServiceThreadOnly
|
||||
protected boolean handleGetMenuLanguage(HdmiCecMessage message) {
|
||||
assertRunOnServiceThread();
|
||||
|
||||
Slog.w(TAG, "Only TV can handle <Get Menu Language>:" + message.toString());
|
||||
mService.sendCecCommand(
|
||||
HdmiCecMessageBuilder.buildFeatureAbortCommand(mAddress,
|
||||
@@ -197,9 +203,9 @@ abstract class HdmiCecLocalDevice {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ServiceThreadOnly
|
||||
protected boolean handleGiveOsdName(HdmiCecMessage message) {
|
||||
assertRunOnServiceThread();
|
||||
|
||||
// Note that since this method is called after logical address allocation is done,
|
||||
// mDeviceInfo should not be null.
|
||||
HdmiCecMessage cecMessage = HdmiCecMessageBuilder.buildSetOsdNameCommand(
|
||||
@@ -236,45 +242,52 @@ abstract class HdmiCecLocalDevice {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ServiceThreadOnly
|
||||
final void handleAddressAllocated(int logicalAddress) {
|
||||
assertRunOnServiceThread();
|
||||
|
||||
mAddress = mPreferredAddress = logicalAddress;
|
||||
onAddressAllocated(logicalAddress);
|
||||
}
|
||||
|
||||
@ServiceThreadOnly
|
||||
HdmiCecDeviceInfo getDeviceInfo() {
|
||||
assertRunOnServiceThread();
|
||||
return mDeviceInfo;
|
||||
}
|
||||
|
||||
@ServiceThreadOnly
|
||||
void setDeviceInfo(HdmiCecDeviceInfo info) {
|
||||
assertRunOnServiceThread();
|
||||
mDeviceInfo = info;
|
||||
}
|
||||
|
||||
// Returns true if the logical address is same as the argument.
|
||||
@ServiceThreadOnly
|
||||
boolean isAddressOf(int addr) {
|
||||
assertRunOnServiceThread();
|
||||
return addr == mAddress;
|
||||
}
|
||||
|
||||
// Resets the logical address to unregistered(15), meaning the logical device is invalid.
|
||||
@ServiceThreadOnly
|
||||
void clearAddress() {
|
||||
assertRunOnServiceThread();
|
||||
mAddress = HdmiCec.ADDR_UNREGISTERED;
|
||||
}
|
||||
|
||||
@ServiceThreadOnly
|
||||
void setPreferredAddress(int addr) {
|
||||
assertRunOnServiceThread();
|
||||
mPreferredAddress = addr;
|
||||
}
|
||||
|
||||
@ServiceThreadOnly
|
||||
int getPreferredAddress() {
|
||||
assertRunOnServiceThread();
|
||||
return mPreferredAddress;
|
||||
}
|
||||
|
||||
@ServiceThreadOnly
|
||||
void addAndStartAction(final FeatureAction action) {
|
||||
assertRunOnServiceThread();
|
||||
mActions.add(action);
|
||||
@@ -282,6 +295,7 @@ abstract class HdmiCecLocalDevice {
|
||||
}
|
||||
|
||||
// See if we have an action of a given type in progress.
|
||||
@ServiceThreadOnly
|
||||
<T extends FeatureAction> boolean hasAction(final Class<T> clazz) {
|
||||
assertRunOnServiceThread();
|
||||
for (FeatureAction action : mActions) {
|
||||
@@ -293,6 +307,7 @@ abstract class HdmiCecLocalDevice {
|
||||
}
|
||||
|
||||
// Returns all actions matched with given class type.
|
||||
@ServiceThreadOnly
|
||||
<T extends FeatureAction> List<T> getActions(final Class<T> clazz) {
|
||||
assertRunOnServiceThread();
|
||||
ArrayList<T> actions = new ArrayList<>();
|
||||
@@ -309,17 +324,21 @@ abstract class HdmiCecLocalDevice {
|
||||
*
|
||||
* @param action {@link FeatureAction} to remove
|
||||
*/
|
||||
@ServiceThreadOnly
|
||||
void removeAction(final FeatureAction action) {
|
||||
assertRunOnServiceThread();
|
||||
mActions.remove(action);
|
||||
}
|
||||
|
||||
// Remove all actions matched with the given Class type.
|
||||
@ServiceThreadOnly
|
||||
<T extends FeatureAction> void removeAction(final Class<T> clazz) {
|
||||
assertRunOnServiceThread();
|
||||
removeActionExcept(clazz, null);
|
||||
}
|
||||
|
||||
// Remove all actions matched with the given Class type besides |exception|.
|
||||
@ServiceThreadOnly
|
||||
<T extends FeatureAction> void removeActionExcept(final Class<T> clazz,
|
||||
final FeatureAction exception) {
|
||||
assertRunOnServiceThread();
|
||||
@@ -352,7 +371,9 @@ abstract class HdmiCecLocalDevice {
|
||||
return mService;
|
||||
}
|
||||
|
||||
@ServiceThreadOnly
|
||||
final boolean isConnectedToArcPort(int path) {
|
||||
assertRunOnServiceThread();
|
||||
return mService.isConnectedToArcPort(path);
|
||||
}
|
||||
|
||||
@@ -442,11 +463,13 @@ abstract class HdmiCecLocalDevice {
|
||||
}
|
||||
}
|
||||
|
||||
@ServiceThreadOnly
|
||||
HdmiCecMessageCache getCecMessageCache() {
|
||||
assertRunOnServiceThread();
|
||||
return mCecMessageCache;
|
||||
}
|
||||
|
||||
@ServiceThreadOnly
|
||||
int pathToPortId(int newPath) {
|
||||
assertRunOnServiceThread();
|
||||
return mService.pathToPortId(newPath);
|
||||
|
||||
@@ -21,6 +21,8 @@ import android.hardware.hdmi.IHdmiControlCallback;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.server.hdmi.HdmiAnnotations.ServiceThreadOnly;
|
||||
|
||||
/**
|
||||
* Represent a logical device of type Playback residing in Android system.
|
||||
*/
|
||||
@@ -32,11 +34,14 @@ final class HdmiCecLocalDevicePlayback extends HdmiCecLocalDevice {
|
||||
}
|
||||
|
||||
@Override
|
||||
@ServiceThreadOnly
|
||||
protected void onAddressAllocated(int logicalAddress) {
|
||||
assertRunOnServiceThread();
|
||||
mService.sendCecCommand(HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
|
||||
mAddress, mService.getPhysicalAddress(), mDeviceType));
|
||||
}
|
||||
|
||||
@ServiceThreadOnly
|
||||
void oneTouchPlay(IHdmiControlCallback callback) {
|
||||
assertRunOnServiceThread();
|
||||
if (hasAction(OneTouchPlayAction.class)) {
|
||||
@@ -56,6 +61,7 @@ final class HdmiCecLocalDevicePlayback extends HdmiCecLocalDevice {
|
||||
addAndStartAction(action);
|
||||
}
|
||||
|
||||
@ServiceThreadOnly
|
||||
void queryDisplayStatus(IHdmiControlCallback callback) {
|
||||
assertRunOnServiceThread();
|
||||
if (hasAction(DevicePowerStatusAction.class)) {
|
||||
@@ -73,7 +79,9 @@ final class HdmiCecLocalDevicePlayback extends HdmiCecLocalDevice {
|
||||
addAndStartAction(action);
|
||||
}
|
||||
|
||||
@ServiceThreadOnly
|
||||
private void invokeCallback(IHdmiControlCallback callback, int result) {
|
||||
assertRunOnServiceThread();
|
||||
try {
|
||||
callback.onComplete(result);
|
||||
} catch (RemoteException e) {
|
||||
@@ -82,7 +90,9 @@ final class HdmiCecLocalDevicePlayback extends HdmiCecLocalDevice {
|
||||
}
|
||||
|
||||
@Override
|
||||
@ServiceThreadOnly
|
||||
void onHotplug(int portId, boolean connected) {
|
||||
assertRunOnServiceThread();
|
||||
// TODO: clear devices connected to the given port id.
|
||||
mCecMessageCache.flushAll();
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import android.util.SparseArray;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.server.hdmi.DeviceDiscoveryAction.DeviceDiscoveryCallback;
|
||||
import com.android.server.hdmi.HdmiAnnotations.ServiceThreadOnly;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
@@ -66,6 +67,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
|
||||
}
|
||||
|
||||
@Override
|
||||
@ServiceThreadOnly
|
||||
protected void onAddressAllocated(int logicalAddress) {
|
||||
assertRunOnServiceThread();
|
||||
// TODO: vendor-specific initialization here.
|
||||
@@ -76,7 +78,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
|
||||
mAddress, mService.getVendorId()));
|
||||
|
||||
launchDeviceDiscovery();
|
||||
// TODO: Start routing control action, device discovery action.
|
||||
// TODO: Start routing control action
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -85,6 +87,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
|
||||
* @param targetAddress logical address of the device to select
|
||||
* @param callback callback object to report the result with
|
||||
*/
|
||||
@ServiceThreadOnly
|
||||
void deviceSelect(int targetAddress, IHdmiControlCallback callback) {
|
||||
assertRunOnServiceThread();
|
||||
HdmiCecDeviceInfo targetDevice = getDeviceInfo(targetAddress);
|
||||
@@ -102,6 +105,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
|
||||
* @param portId new HDMI port to route to
|
||||
* @param callback callback object to report the result with
|
||||
*/
|
||||
@ServiceThreadOnly
|
||||
void portSelect(int portId, IHdmiControlCallback callback) {
|
||||
assertRunOnServiceThread();
|
||||
if (isInPresetInstallationMode()) {
|
||||
@@ -136,6 +140,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
|
||||
* @param keyCode key code to send. Defined in {@link android.view.KeyEvent}.
|
||||
* @param isPressed true if this is keypress event
|
||||
*/
|
||||
@ServiceThreadOnly
|
||||
void sendKeyEvent(int keyCode, boolean isPressed) {
|
||||
assertRunOnServiceThread();
|
||||
List<SendKeyAction> action = getActions(SendKeyAction.class);
|
||||
@@ -162,6 +167,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
|
||||
}
|
||||
|
||||
@Override
|
||||
@ServiceThreadOnly
|
||||
protected boolean handleGetMenuLanguage(HdmiCecMessage message) {
|
||||
assertRunOnServiceThread();
|
||||
HdmiCecMessage command = HdmiCecMessageBuilder.buildSetMenuLanguageCommand(
|
||||
@@ -176,6 +182,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
|
||||
}
|
||||
|
||||
@Override
|
||||
@ServiceThreadOnly
|
||||
protected boolean handleReportPhysicalAddress(HdmiCecMessage message) {
|
||||
assertRunOnServiceThread();
|
||||
// Ignore if [Device Discovery Action] is going on.
|
||||
@@ -198,6 +205,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
|
||||
}
|
||||
|
||||
@Override
|
||||
@ServiceThreadOnly
|
||||
protected boolean handleVendorSpecificCommand(HdmiCecMessage message) {
|
||||
assertRunOnServiceThread();
|
||||
List<VendorSpecificAction> actions = Collections.emptyList();
|
||||
@@ -223,6 +231,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ServiceThreadOnly
|
||||
private void launchDeviceDiscovery() {
|
||||
assertRunOnServiceThread();
|
||||
clearDeviceInfoList();
|
||||
@@ -257,12 +266,14 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
|
||||
}
|
||||
|
||||
// Clear all device info.
|
||||
@ServiceThreadOnly
|
||||
private void clearDeviceInfoList() {
|
||||
assertRunOnServiceThread();
|
||||
mDeviceInfos.clear();
|
||||
updateSafeDeviceInfoList();
|
||||
}
|
||||
|
||||
@ServiceThreadOnly
|
||||
void changeSystemAudioMode(boolean enabled, IHdmiControlCallback callback) {
|
||||
assertRunOnServiceThread();
|
||||
HdmiCecDeviceInfo avr = getAvrDeviceInfo();
|
||||
@@ -324,11 +335,13 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
|
||||
}
|
||||
}
|
||||
|
||||
@ServiceThreadOnly
|
||||
void setAudioStatus(boolean mute, int volume) {
|
||||
mService.setAudioStatus(mute, volume);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ServiceThreadOnly
|
||||
protected boolean handleInitiateArc(HdmiCecMessage message) {
|
||||
assertRunOnServiceThread();
|
||||
// In case where <Initiate Arc> is started by <Request ARC Initiation>
|
||||
@@ -341,6 +354,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
|
||||
}
|
||||
|
||||
@Override
|
||||
@ServiceThreadOnly
|
||||
protected boolean handleTerminateArc(HdmiCecMessage message) {
|
||||
assertRunOnServiceThread();
|
||||
// In case where <Terminate Arc> is started by <Request ARC Termination>
|
||||
@@ -355,6 +369,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
|
||||
}
|
||||
|
||||
@Override
|
||||
@ServiceThreadOnly
|
||||
protected boolean handleSetSystemAudioMode(HdmiCecMessage message) {
|
||||
assertRunOnServiceThread();
|
||||
if (!isMessageForSystemAudio(message)) {
|
||||
@@ -367,6 +382,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
|
||||
}
|
||||
|
||||
@Override
|
||||
@ServiceThreadOnly
|
||||
protected boolean handleSystemAudioModeStatus(HdmiCecMessage message) {
|
||||
assertRunOnServiceThread();
|
||||
if (!isMessageForSystemAudio(message)) {
|
||||
@@ -396,6 +412,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
|
||||
* @return {@code null} if it is new device. Otherwise, returns old {@HdmiCecDeviceInfo}
|
||||
* that has the same logical address as new one has.
|
||||
*/
|
||||
@ServiceThreadOnly
|
||||
HdmiCecDeviceInfo addDeviceInfo(HdmiCecDeviceInfo deviceInfo) {
|
||||
assertRunOnServiceThread();
|
||||
HdmiCecDeviceInfo oldDeviceInfo = getDeviceInfo(deviceInfo.getLogicalAddress());
|
||||
@@ -416,6 +433,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
|
||||
* @param logicalAddress logical address of device to be removed
|
||||
* @return removed {@link HdmiCecDeviceInfo} it exists. Otherwise, returns {@code null}
|
||||
*/
|
||||
@ServiceThreadOnly
|
||||
HdmiCecDeviceInfo removeDeviceInfo(int logicalAddress) {
|
||||
assertRunOnServiceThread();
|
||||
HdmiCecDeviceInfo deviceInfo = mDeviceInfos.get(logicalAddress);
|
||||
@@ -432,6 +450,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
|
||||
* <p>Declared as package-private. accessed by {@link HdmiControlService} only.
|
||||
* This is not thread-safe. For thread safety, call {@link #getSafeDeviceInfoList(boolean)}.
|
||||
*/
|
||||
@ServiceThreadOnly
|
||||
List<HdmiCecDeviceInfo> getDeviceInfoList(boolean includelLocalDevice) {
|
||||
assertRunOnServiceThread();
|
||||
if (includelLocalDevice) {
|
||||
@@ -463,6 +482,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
|
||||
}
|
||||
}
|
||||
|
||||
@ServiceThreadOnly
|
||||
private void updateSafeDeviceInfoList() {
|
||||
assertRunOnServiceThread();
|
||||
List<HdmiCecDeviceInfo> copiedDevices = HdmiUtils.sparseArrayToList(mDeviceInfos);
|
||||
@@ -473,6 +493,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
|
||||
}
|
||||
}
|
||||
|
||||
@ServiceThreadOnly
|
||||
private boolean isLocalDeviceAddress(int address) {
|
||||
assertRunOnServiceThread();
|
||||
for (HdmiCecLocalDevice device : mService.getAllLocalDevices()) {
|
||||
@@ -493,11 +514,13 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
|
||||
* @return {@link HdmiCecDeviceInfo} matched with the given {@code logicalAddress}.
|
||||
* Returns null if no logical address matched
|
||||
*/
|
||||
@ServiceThreadOnly
|
||||
HdmiCecDeviceInfo getDeviceInfo(int logicalAddress) {
|
||||
assertRunOnServiceThread();
|
||||
return mDeviceInfos.get(logicalAddress);
|
||||
}
|
||||
|
||||
@ServiceThreadOnly
|
||||
HdmiCecDeviceInfo getAvrDeviceInfo() {
|
||||
assertRunOnServiceThread();
|
||||
return getDeviceInfo(HdmiCec.ADDR_AUDIO_SYSTEM);
|
||||
@@ -525,6 +548,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
|
||||
*
|
||||
* @param info device info of a new device.
|
||||
*/
|
||||
@ServiceThreadOnly
|
||||
final void addCecDevice(HdmiCecDeviceInfo info) {
|
||||
assertRunOnServiceThread();
|
||||
addDeviceInfo(info);
|
||||
@@ -540,6 +564,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
|
||||
*
|
||||
* @param address a logical address of a device to be removed
|
||||
*/
|
||||
@ServiceThreadOnly
|
||||
final void removeCecDevice(int address) {
|
||||
assertRunOnServiceThread();
|
||||
HdmiCecDeviceInfo info = removeDeviceInfo(address);
|
||||
@@ -555,6 +580,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
|
||||
* @param path routing path or physical address
|
||||
* @return {@link HdmiCecDeviceInfo} if the matched info is found; otherwise null
|
||||
*/
|
||||
@ServiceThreadOnly
|
||||
final HdmiCecDeviceInfo getDeviceInfoByPath(int path) {
|
||||
assertRunOnServiceThread();
|
||||
for (HdmiCecDeviceInfo info : getDeviceInfoList(false)) {
|
||||
@@ -574,6 +600,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
|
||||
* @param logicalAddress logical address of a device to be searched
|
||||
* @return true if exist; otherwise false
|
||||
*/
|
||||
@ServiceThreadOnly
|
||||
boolean isInDeviceList(int physicalAddress, int logicalAddress) {
|
||||
assertRunOnServiceThread();
|
||||
HdmiCecDeviceInfo device = getDeviceInfo(logicalAddress);
|
||||
@@ -584,6 +611,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
|
||||
}
|
||||
|
||||
@Override
|
||||
@ServiceThreadOnly
|
||||
void onHotplug(int portNo, boolean connected) {
|
||||
assertRunOnServiceThread();
|
||||
// TODO: delegate onHotplug event to each local device.
|
||||
|
||||
@@ -40,6 +40,7 @@ import android.util.SparseIntArray;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.server.SystemService;
|
||||
import com.android.server.hdmi.HdmiAnnotations.ServiceThreadOnly;
|
||||
import com.android.server.hdmi.HdmiCecController.AllocateAddressCallback;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -163,7 +164,9 @@ public final class HdmiControlService extends SystemService {
|
||||
// start to monitor the preference value and invoke SystemAudioActionFromTv if needed.
|
||||
}
|
||||
|
||||
@ServiceThreadOnly
|
||||
private void initializeLocalDevices(final List<Integer> deviceTypes) {
|
||||
assertRunOnServiceThread();
|
||||
// A container for [Logical Address, Local device info].
|
||||
final SparseArray<HdmiCecLocalDevice> devices = new SparseArray<>();
|
||||
final SparseIntArray finished = new SparseIntArray();
|
||||
@@ -195,7 +198,9 @@ public final class HdmiControlService extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
@ServiceThreadOnly
|
||||
private void notifyAddressAllocated(SparseArray<HdmiCecLocalDevice> devices) {
|
||||
assertRunOnServiceThread();
|
||||
for (int i = 0; i < devices.size(); ++i) {
|
||||
int address = devices.keyAt(i);
|
||||
HdmiCecLocalDevice device = devices.valueAt(i);
|
||||
@@ -205,7 +210,9 @@ public final class HdmiControlService extends SystemService {
|
||||
|
||||
// Initialize HDMI port information. Combine the information from CEC and MHL HAL and
|
||||
// keep them in one place.
|
||||
@ServiceThreadOnly
|
||||
private List<HdmiPortInfo> initPortInfo() {
|
||||
assertRunOnServiceThread();
|
||||
HdmiPortInfo[] cecPortInfo = null;
|
||||
|
||||
// CEC HAL provides majority of the info while MHL does only MHL support flag for
|
||||
@@ -325,6 +332,7 @@ public final class HdmiControlService extends SystemService {
|
||||
return mCecController.getVendorId();
|
||||
}
|
||||
|
||||
@ServiceThreadOnly
|
||||
HdmiCecDeviceInfo getDeviceInfo(int logicalAddress) {
|
||||
assertRunOnServiceThread();
|
||||
HdmiCecLocalDeviceTv tv = tv();
|
||||
@@ -374,15 +382,21 @@ public final class HdmiControlService extends SystemService {
|
||||
* @param command CEC command to send out
|
||||
* @param callback interface used to the result of send command
|
||||
*/
|
||||
@ServiceThreadOnly
|
||||
void sendCecCommand(HdmiCecMessage command, @Nullable SendMessageCallback callback) {
|
||||
assertRunOnServiceThread();
|
||||
mCecController.sendCommand(command, callback);
|
||||
}
|
||||
|
||||
@ServiceThreadOnly
|
||||
void sendCecCommand(HdmiCecMessage command) {
|
||||
assertRunOnServiceThread();
|
||||
mCecController.sendCommand(command, null);
|
||||
}
|
||||
|
||||
@ServiceThreadOnly
|
||||
boolean handleCecCommand(HdmiCecMessage message) {
|
||||
assertRunOnServiceThread();
|
||||
return dispatchMessageToLocalDevice(message);
|
||||
}
|
||||
|
||||
@@ -390,7 +404,9 @@ public final class HdmiControlService extends SystemService {
|
||||
mCecController.setAudioReturnChannel(enabled);
|
||||
}
|
||||
|
||||
@ServiceThreadOnly
|
||||
private boolean dispatchMessageToLocalDevice(HdmiCecMessage message) {
|
||||
assertRunOnServiceThread();
|
||||
for (HdmiCecLocalDevice device : mCecController.getLocalDeviceList()) {
|
||||
if (device.dispatchMessage(message)
|
||||
&& message.getDestination() != HdmiCec.ADDR_BROADCAST) {
|
||||
@@ -408,13 +424,12 @@ public final class HdmiControlService extends SystemService {
|
||||
* @param portNo hdmi port number where hot plug event issued.
|
||||
* @param connected whether to be plugged in or not
|
||||
*/
|
||||
@ServiceThreadOnly
|
||||
void onHotplug(int portNo, boolean connected) {
|
||||
assertRunOnServiceThread();
|
||||
|
||||
for (HdmiCecLocalDevice device : mCecController.getLocalDeviceList()) {
|
||||
device.onHotplug(portNo, connected);
|
||||
}
|
||||
|
||||
announceHotplugEvent(portNo, connected);
|
||||
}
|
||||
|
||||
@@ -427,7 +442,9 @@ public final class HdmiControlService extends SystemService {
|
||||
* @param retryCount the number of retry used to send polling message to remote devices
|
||||
* @throw IllegalArgumentException if {@code pickStrategy} is invalid value
|
||||
*/
|
||||
@ServiceThreadOnly
|
||||
void pollDevices(DevicePollingCallback callback, int pickStrategy, int retryCount) {
|
||||
assertRunOnServiceThread();
|
||||
mCecController.pollDevices(callback, checkPollStrategy(pickStrategy), retryCount);
|
||||
}
|
||||
|
||||
@@ -700,6 +717,7 @@ public final class HdmiControlService extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
@ServiceThreadOnly
|
||||
private void oneTouchPlay(final IHdmiControlCallback callback) {
|
||||
assertRunOnServiceThread();
|
||||
HdmiCecLocalDevicePlayback source = playback();
|
||||
@@ -711,6 +729,7 @@ public final class HdmiControlService extends SystemService {
|
||||
source.oneTouchPlay(callback);
|
||||
}
|
||||
|
||||
@ServiceThreadOnly
|
||||
private void queryDisplayStatus(final IHdmiControlCallback callback) {
|
||||
assertRunOnServiceThread();
|
||||
HdmiCecLocalDevicePlayback source = playback();
|
||||
|
||||
Reference in New Issue
Block a user