Merge "Revert^3 "[CEC Configuration] Add listener support to the HdmiCecConfig""
This commit is contained in:
commit
dd6308cafb
@ -22,19 +22,12 @@ import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.StringDef;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.database.ContentObserver;
|
||||
import android.hardware.hdmi.HdmiControlManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Environment;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.SystemProperties;
|
||||
import android.os.UserHandle;
|
||||
import android.provider.Settings.Global;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
@ -95,23 +88,6 @@ public class HdmiCecConfig {
|
||||
@Nullable private final CecSettings mProductConfig;
|
||||
@Nullable private final CecSettings mVendorOverride;
|
||||
|
||||
private final ArrayMap<Setting, Set<SettingChangeListener>>
|
||||
mSettingChangeListeners = new ArrayMap<>();
|
||||
|
||||
private SettingsObserver mSettingsObserver;
|
||||
|
||||
/**
|
||||
* Listener used to get notifications when value of a setting changes.
|
||||
*/
|
||||
public interface SettingChangeListener {
|
||||
/**
|
||||
* Called when value of a setting changes.
|
||||
*
|
||||
* @param setting name of a CEC setting that changed
|
||||
*/
|
||||
void onChange(@NonNull @CecSettingName String setting);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setting storage input/output helper class.
|
||||
*/
|
||||
@ -183,18 +159,6 @@ public class HdmiCecConfig {
|
||||
}
|
||||
}
|
||||
|
||||
private class SettingsObserver extends ContentObserver {
|
||||
SettingsObserver(Handler handler) {
|
||||
super(handler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChange(boolean selfChange, Uri uri) {
|
||||
String setting = uri.getLastPathSegment();
|
||||
HdmiCecConfig.this.notifyGlobalSettingChanged(setting);
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
HdmiCecConfig(@NonNull Context context,
|
||||
@NonNull StorageAdapter storageAdapter,
|
||||
@ -347,7 +311,6 @@ public class HdmiCecConfig {
|
||||
} else if (storage == STORAGE_SHARED_PREFS) {
|
||||
Slog.d(TAG, "Setting '" + storageKey + "' shared pref.");
|
||||
mStorageAdapter.storeSharedPref(storageKey, value);
|
||||
notifySettingChanged(setting);
|
||||
}
|
||||
}
|
||||
|
||||
@ -355,103 +318,6 @@ public class HdmiCecConfig {
|
||||
return Integer.decode(value.getIntValue());
|
||||
}
|
||||
|
||||
private void notifyGlobalSettingChanged(String setting) {
|
||||
switch (setting) {
|
||||
case Global.HDMI_CONTROL_ENABLED:
|
||||
notifySettingChanged(HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_ENABLED);
|
||||
break;
|
||||
case Global.HDMI_CEC_VERSION:
|
||||
notifySettingChanged(HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_VERSION);
|
||||
break;
|
||||
case Global.HDMI_CONTROL_SEND_STANDBY_ON_SLEEP:
|
||||
notifySettingChanged(HdmiControlManager.CEC_SETTING_NAME_SEND_STANDBY_ON_SLEEP);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void notifySettingChanged(@NonNull @CecSettingName String name) {
|
||||
Setting setting = getSetting(name);
|
||||
if (setting == null) {
|
||||
throw new IllegalArgumentException("Setting '" + name + "' does not exist.");
|
||||
}
|
||||
notifySettingChanged(setting);
|
||||
}
|
||||
|
||||
private void notifySettingChanged(@NonNull Setting setting) {
|
||||
Set<SettingChangeListener> listeners = mSettingChangeListeners.get(setting);
|
||||
if (listeners == null) {
|
||||
return; // No listeners registered, do nothing.
|
||||
}
|
||||
for (SettingChangeListener listener: listeners) {
|
||||
listener.onChange(setting.getName());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method registers Global Setting change observer.
|
||||
* Needs to be called once after initialization of HdmiCecConfig.
|
||||
*/
|
||||
public void registerGlobalSettingsObserver(Looper looper) {
|
||||
Handler handler = new Handler(looper);
|
||||
mSettingsObserver = new SettingsObserver(handler);
|
||||
ContentResolver resolver = mContext.getContentResolver();
|
||||
String[] settings = new String[] {
|
||||
Global.HDMI_CONTROL_ENABLED,
|
||||
Global.HDMI_CEC_VERSION,
|
||||
Global.HDMI_CONTROL_SEND_STANDBY_ON_SLEEP,
|
||||
};
|
||||
for (String setting: settings) {
|
||||
resolver.registerContentObserver(Global.getUriFor(setting), false,
|
||||
mSettingsObserver, UserHandle.USER_ALL);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method unregisters Global Setting change observer.
|
||||
*/
|
||||
public void unregisterGlobalSettingsObserver() {
|
||||
ContentResolver resolver = mContext.getContentResolver();
|
||||
resolver.unregisterContentObserver(mSettingsObserver);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register change listener for a given setting name.
|
||||
*/
|
||||
public void registerChangeListener(@NonNull @CecSettingName String name,
|
||||
SettingChangeListener listener) {
|
||||
Setting setting = getSetting(name);
|
||||
if (setting == null) {
|
||||
throw new IllegalArgumentException("Setting '" + name + "' does not exist.");
|
||||
}
|
||||
@Storage int storage = getStorage(setting);
|
||||
if (storage != STORAGE_GLOBAL_SETTINGS && storage != STORAGE_SHARED_PREFS) {
|
||||
throw new IllegalArgumentException("Change listeners for setting '" + name
|
||||
+ "' not supported.");
|
||||
}
|
||||
if (!mSettingChangeListeners.containsKey(setting)) {
|
||||
mSettingChangeListeners.put(setting, new HashSet<>());
|
||||
}
|
||||
mSettingChangeListeners.get(setting).add(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove change listener for a given setting name.
|
||||
*/
|
||||
public void removeChangeListener(@NonNull @CecSettingName String name,
|
||||
SettingChangeListener listener) {
|
||||
Setting setting = getSetting(name);
|
||||
if (setting == null) {
|
||||
throw new IllegalArgumentException("Setting '" + name + "' does not exist.");
|
||||
}
|
||||
if (mSettingChangeListeners.containsKey(setting)) {
|
||||
Set<SettingChangeListener> listeners = mSettingChangeListeners.get(setting);
|
||||
listeners.remove(listener);
|
||||
if (listeners.isEmpty()) {
|
||||
mSettingChangeListeners.remove(setting);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of all settings based on the XML metadata.
|
||||
*/
|
||||
|
@ -496,7 +496,6 @@ public class HdmiControlService extends SystemService {
|
||||
if (mMessageValidator == null) {
|
||||
mMessageValidator = new HdmiCecMessageValidator(this);
|
||||
}
|
||||
mHdmiCecConfig.registerGlobalSettingsObserver(mIoLooper);
|
||||
}
|
||||
|
||||
private void bootCompleted() {
|
||||
|
@ -18,17 +18,13 @@ package com.android.server.hdmi;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static junit.framework.Assert.assertTrue;
|
||||
import static junit.framework.Assert.fail;
|
||||
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.testng.Assert.assertThrows;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.content.Context;
|
||||
import android.hardware.hdmi.HdmiControlManager;
|
||||
import android.os.test.TestLooper;
|
||||
import android.platform.test.annotations.Presubmit;
|
||||
import android.provider.Settings.Global;
|
||||
|
||||
@ -42,23 +38,15 @@ import org.junit.runners.JUnit4;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@SmallTest
|
||||
@Presubmit
|
||||
@RunWith(JUnit4.class)
|
||||
public final class HdmiCecConfigTest {
|
||||
private static final String TAG = "HdmiCecConfigTest";
|
||||
|
||||
private static final int TIMEOUT_CONTENT_CHANGE_SEC = 4;
|
||||
|
||||
private final TestLooper mTestLooper = new TestLooper();
|
||||
|
||||
private Context mContext;
|
||||
|
||||
@Mock private HdmiCecConfig.StorageAdapter mStorageAdapter;
|
||||
@Mock private HdmiCecConfig.SettingChangeListener mSettingChangeListener;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
@ -1031,124 +1019,4 @@ public final class HdmiCecConfigTest {
|
||||
HdmiControlManager.CEC_SETTING_NAME_SYSTEM_AUDIO_MODE_MUTING,
|
||||
Integer.toString(HdmiControlManager.SYSTEM_AUDIO_MODE_MUTING_DISABLED));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void registerChangeListener_SharedPref_BasicSanity() {
|
||||
HdmiCecConfig hdmiCecConfig = HdmiCecConfig.createFromStrings(
|
||||
mContext, mStorageAdapter,
|
||||
"<?xml version='1.0' encoding='utf-8' standalone='yes' ?>"
|
||||
+ "<cec-settings>"
|
||||
+ " <setting name=\"system_audio_mode_muting\""
|
||||
+ " value-type=\"int\""
|
||||
+ " user-configurable=\"true\">"
|
||||
+ " <allowed-values>"
|
||||
+ " <value int-value=\"0\" />"
|
||||
+ " <value int-value=\"1\" />"
|
||||
+ " </allowed-values>"
|
||||
+ " <default-value int-value=\"1\" />"
|
||||
+ " </setting>"
|
||||
+ "</cec-settings>", null);
|
||||
hdmiCecConfig.registerChangeListener(
|
||||
HdmiControlManager.CEC_SETTING_NAME_SYSTEM_AUDIO_MODE_MUTING,
|
||||
mSettingChangeListener);
|
||||
hdmiCecConfig.setIntValue(
|
||||
HdmiControlManager.CEC_SETTING_NAME_SYSTEM_AUDIO_MODE_MUTING,
|
||||
HdmiControlManager.SYSTEM_AUDIO_MODE_MUTING_DISABLED);
|
||||
verify(mSettingChangeListener).onChange(
|
||||
HdmiControlManager.CEC_SETTING_NAME_SYSTEM_AUDIO_MODE_MUTING);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void removeChangeListener_SharedPref_BasicSanity() {
|
||||
HdmiCecConfig hdmiCecConfig = HdmiCecConfig.createFromStrings(
|
||||
mContext, mStorageAdapter,
|
||||
"<?xml version='1.0' encoding='utf-8' standalone='yes' ?>"
|
||||
+ "<cec-settings>"
|
||||
+ " <setting name=\"system_audio_mode_muting\""
|
||||
+ " value-type=\"int\""
|
||||
+ " user-configurable=\"true\">"
|
||||
+ " <allowed-values>"
|
||||
+ " <value int-value=\"0\" />"
|
||||
+ " <value int-value=\"1\" />"
|
||||
+ " </allowed-values>"
|
||||
+ " <default-value int-value=\"1\" />"
|
||||
+ " </setting>"
|
||||
+ "</cec-settings>", null);
|
||||
hdmiCecConfig.registerChangeListener(
|
||||
HdmiControlManager.CEC_SETTING_NAME_SYSTEM_AUDIO_MODE_MUTING,
|
||||
mSettingChangeListener);
|
||||
hdmiCecConfig.removeChangeListener(
|
||||
HdmiControlManager.CEC_SETTING_NAME_SYSTEM_AUDIO_MODE_MUTING,
|
||||
mSettingChangeListener);
|
||||
hdmiCecConfig.setIntValue(
|
||||
HdmiControlManager.CEC_SETTING_NAME_SYSTEM_AUDIO_MODE_MUTING,
|
||||
HdmiControlManager.SYSTEM_AUDIO_MODE_MUTING_DISABLED);
|
||||
verify(mSettingChangeListener, never()).onChange(
|
||||
HdmiControlManager.CEC_SETTING_NAME_SYSTEM_AUDIO_MODE_MUTING);
|
||||
}
|
||||
|
||||
/**
|
||||
* Externally modified Global Settings still need to be supported. This test verifies that
|
||||
* setting change notification is being forwarded to listeners registered via HdmiCecConfig.
|
||||
*/
|
||||
@Test
|
||||
public void globalSettingObserver_BasicSanity() throws Exception {
|
||||
CountDownLatch notifyLatch = new CountDownLatch(1);
|
||||
// Get current value of the setting in the system.
|
||||
String originalValue = Global.getString(mContext.getContentResolver(),
|
||||
Global.HDMI_CONTROL_ENABLED);
|
||||
try {
|
||||
HdmiCecConfig hdmiCecConfig = HdmiCecConfig.createFromStrings(
|
||||
mContext, mStorageAdapter,
|
||||
"<?xml version='1.0' encoding='utf-8' standalone='yes' ?>"
|
||||
+ "<cec-settings>"
|
||||
+ " <setting name=\"hdmi_cec_enabled\""
|
||||
+ " value-type=\"int\""
|
||||
+ " user-configurable=\"true\">"
|
||||
+ " <allowed-values>"
|
||||
+ " <value int-value=\"0\" />"
|
||||
+ " <value int-value=\"1\" />"
|
||||
+ " </allowed-values>"
|
||||
+ " <default-value int-value=\"1\" />"
|
||||
+ " </setting>"
|
||||
+ "</cec-settings>", null);
|
||||
hdmiCecConfig.registerGlobalSettingsObserver(mTestLooper.getLooper());
|
||||
HdmiCecConfig.SettingChangeListener latchUpdateListener =
|
||||
new HdmiCecConfig.SettingChangeListener() {
|
||||
@Override
|
||||
public void onChange(
|
||||
@NonNull @HdmiControlManager.CecSettingName String setting) {
|
||||
notifyLatch.countDown();
|
||||
assertThat(setting).isEqualTo(
|
||||
HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_ENABLED);
|
||||
}
|
||||
};
|
||||
hdmiCecConfig.registerChangeListener(
|
||||
HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_ENABLED,
|
||||
latchUpdateListener);
|
||||
mTestLooper.dispatchAll();
|
||||
|
||||
// Flip the value of the setting.
|
||||
String valueToSet = ((originalValue == null || originalValue.equals("1")) ? "0" : "1");
|
||||
Global.putString(mContext.getContentResolver(), Global.HDMI_CONTROL_ENABLED,
|
||||
valueToSet);
|
||||
assertThat(Global.getString(mContext.getContentResolver(),
|
||||
Global.HDMI_CONTROL_ENABLED)).isEqualTo(valueToSet);
|
||||
|
||||
// Write Setting a 2nd time as the listener doesn't always trigger on the first write
|
||||
// in the test.
|
||||
Global.putString(mContext.getContentResolver(), Global.HDMI_CONTROL_ENABLED,
|
||||
valueToSet);
|
||||
mTestLooper.dispatchAll();
|
||||
|
||||
if (!notifyLatch.await(TIMEOUT_CONTENT_CHANGE_SEC, TimeUnit.SECONDS)) {
|
||||
fail("Timed out waiting for the notify callback");
|
||||
}
|
||||
hdmiCecConfig.unregisterGlobalSettingsObserver();
|
||||
} finally {
|
||||
// Restore the previous value of the setting in the system.
|
||||
Global.putString(mContext.getContentResolver(), Global.HDMI_CONTROL_ENABLED,
|
||||
originalValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user