diff --git a/services/core/java/com/android/server/hdmi/HdmiAnnotations.java b/services/core/java/com/android/server/hdmi/HdmiAnnotations.java
new file mode 100644
index 0000000000000..969595d812dc6
--- /dev/null
+++ b/services/core/java/com/android/server/hdmi/HdmiAnnotations.java
@@ -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 {
+ }
+}
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecController.java b/services/core/java/com/android/server/hdmi/HdmiCecController.java
index 6d05e82cad5d8..4fbe84515ecdf 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecController.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecController.java
@@ -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 {
*
*
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 {
*
*
Declared as package-private. accessed by {@link HdmiControlService} only.
*/
+ @ServiceThreadOnly
int getVersion() {
assertRunOnServiceThread();
return nativeGetVersion(mNativePtr);
@@ -297,6 +307,7 @@ final class HdmiCecController {
*
*
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 {
*
*
Declared as package-private. accessed by {@link HdmiControlService} only.
*/
+ @ServiceThreadOnly
List 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 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));
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
index f86d655af4707..6f7f5c2dca5c9 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
@@ -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 :" + 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
boolean hasAction(final Class clazz) {
assertRunOnServiceThread();
for (FeatureAction action : mActions) {
@@ -293,6 +307,7 @@ abstract class HdmiCecLocalDevice {
}
// Returns all actions matched with given class type.
+ @ServiceThreadOnly
List getActions(final Class clazz) {
assertRunOnServiceThread();
ArrayList 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
void removeAction(final Class clazz) {
+ assertRunOnServiceThread();
removeActionExcept(clazz, null);
}
// Remove all actions matched with the given Class type besides |exception|.
+ @ServiceThreadOnly
void removeActionExcept(final Class 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);
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
index 01345ef0db975..d7e36b37d00bd 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
@@ -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();
}
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
index 1a3fcfe0572e3..1d5a7d3eb7baf 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
@@ -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 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 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 is started by
@@ -341,6 +354,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
}
@Override
+ @ServiceThreadOnly
protected boolean handleTerminateArc(HdmiCecMessage message) {
assertRunOnServiceThread();
// In case where is started by
@@ -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 {
* Declared as package-private. accessed by {@link HdmiControlService} only.
* This is not thread-safe. For thread safety, call {@link #getSafeDeviceInfoList(boolean)}.
*/
+ @ServiceThreadOnly
List getDeviceInfoList(boolean includelLocalDevice) {
assertRunOnServiceThread();
if (includelLocalDevice) {
@@ -463,6 +482,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
}
}
+ @ServiceThreadOnly
private void updateSafeDeviceInfoList() {
assertRunOnServiceThread();
List 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.
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 77748786f4836..055751b51f17d 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -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 deviceTypes) {
+ assertRunOnServiceThread();
// A container for [Logical Address, Local device info].
final SparseArray devices = new SparseArray<>();
final SparseIntArray finished = new SparseIntArray();
@@ -195,7 +198,9 @@ public final class HdmiControlService extends SystemService {
}
}
+ @ServiceThreadOnly
private void notifyAddressAllocated(SparseArray 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 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();