summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/api/current.txt2
-rw-r--r--core/java/android/hardware/hdmi/HdmiControlManager.java88
-rw-r--r--core/java/android/hardware/hdmi/HdmiControlServiceWrapper.java11
-rw-r--r--core/java/android/hardware/hdmi/IHdmiCecVolumeControlFeatureListener.aidl4
-rw-r--r--core/java/android/hardware/hdmi/IHdmiControlService.aidl2
-rw-r--r--core/java/android/os/SystemVibrator.java29
-rw-r--r--core/tests/hdmitests/src/android/hardware/hdmi/HdmiAudioSystemClientTest.java9
-rw-r--r--media/java/android/media/MediaDrm.java27
-rw-r--r--media/jni/android_media_MediaDrm.cpp27
-rw-r--r--packages/SystemUI/res/values-television/config.xml1
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/systemsounds/HomeSoundEffectController.java82
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/systemsounds/HomeSoundEffectControllerTest.java158
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java24
-rw-r--r--services/core/java/com/android/server/am/ProcessList.java4
-rw-r--r--services/core/java/com/android/server/audio/AudioService.java6
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiCecConfig.java28
-rwxr-xr-xservices/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java7
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java6
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java12
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiControlService.java84
-rw-r--r--services/core/java/com/android/server/hdmi/cec_config.xml9
-rwxr-xr-xservices/core/java/com/android/server/notification/NotificationManagerService.java15
-rw-r--r--services/core/java/com/android/server/utils/quota/MultiRateLimiter.java32
-rw-r--r--services/core/java/com/android/server/utils/quota/QuotaTracker.java4
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java2
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/utils/quota/MultiRateLimiterTest.java94
-rw-r--r--services/tests/servicestests/src/com/android/server/hdmi/FakeHdmiCecConfig.java9
-rw-r--r--services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java17
-rw-r--r--services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java30
-rw-r--r--services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTest.java31
-rw-r--r--services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceBinderAPITest.java7
-rw-r--r--services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java136
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java15
34 files changed, 809 insertions, 210 deletions
diff --git a/core/api/current.txt b/core/api/current.txt
index 27660ec88f44..5e5d7c629a38 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -21520,6 +21520,8 @@ package android.media {
method public void removeKeys(@NonNull byte[]);
method public void removeOfflineLicense(@NonNull byte[]);
method public void removeSecureStop(@NonNull byte[]);
+ method public boolean requiresSecureDecoder(@NonNull String);
+ method public boolean requiresSecureDecoder(@NonNull String, @android.media.MediaDrm.SecurityLevel int);
method public void restoreKeys(@NonNull byte[], @NonNull byte[]);
method public void setOnEventListener(@Nullable android.media.MediaDrm.OnEventListener);
method public void setOnEventListener(@Nullable android.media.MediaDrm.OnEventListener, @Nullable android.os.Handler);
diff --git a/core/java/android/hardware/hdmi/HdmiControlManager.java b/core/java/android/hardware/hdmi/HdmiControlManager.java
index b09eda4ad2b6..dddf7352424b 100644
--- a/core/java/android/hardware/hdmi/HdmiControlManager.java
+++ b/core/java/android/hardware/hdmi/HdmiControlManager.java
@@ -454,6 +454,33 @@ public final class HdmiControlManager {
@Retention(RetentionPolicy.SOURCE)
public @interface SystemAudioModeMuting {}
+ // -- Whether the HDMI CEC volume control is enabled or disabled.
+ /**
+ * HDMI CEC enabled.
+ *
+ * @see HdmiControlManager#CEC_SETTING_NAME_VOLUME_CONTROL_MODE
+ * @hide
+ */
+ public static final int VOLUME_CONTROL_ENABLED = 1;
+ /**
+ * HDMI CEC disabled.
+ *
+ * @see HdmiControlManager#CEC_SETTING_NAME_VOLUME_CONTROL_MODE
+ * @hide
+ */
+ public static final int VOLUME_CONTROL_DISABLED = 0;
+ /**
+ * @see HdmiControlManager#CEC_SETTING_NAME_VOLUME_CONTROL_MODE
+ * @hide
+ */
+ @IntDef({
+ VOLUME_CONTROL_ENABLED,
+ VOLUME_CONTROL_DISABLED
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface VolumeControl {}
+
+
// -- Settings available in the CEC Configuration.
/**
* Name of a setting deciding whether the CEC is enabled.
@@ -492,6 +519,43 @@ public final class HdmiControlManager {
@SystemApi
public static final String CEC_SETTING_NAME_SYSTEM_AUDIO_MODE_MUTING =
"system_audio_mode_muting";
+
+ /**
+ * Controls whether volume control commands via HDMI CEC are enabled.
+ *
+ * <p>Effects on different device types:
+ * <table>
+ * <tr><th>HDMI CEC device type</th><th>0: disabled</th><th>1: enabled</th></tr>
+ * <tr>
+ * <td>TV (type: 0)</td>
+ * <td>Per CEC specification.</td>
+ * <td>TV changes system volume. TV no longer reacts to incoming volume changes
+ * via {@code <User Control Pressed>}. TV no longer handles {@code <Report Audio
+ * Status>}.</td>
+ * </tr>
+ * <tr>
+ * <td>Playback device (type: 4)</td>
+ * <td>Device sends volume commands to TV/Audio system via {@code <User Control
+ * Pressed>}</td>
+ * <td>Device does not send volume commands via {@code <User Control Pressed>}.</td>
+ * </tr>
+ * <tr>
+ * <td>Audio device (type: 5)</td>
+ * <td>Full "System Audio Control" capabilities.</td>
+ * <td>Audio device no longer reacts to incoming {@code <User Control Pressed>}
+ * volume commands. Audio device no longer reports volume changes via {@code
+ * <Report Audio Status>}.</td>
+ * </tr>
+ * </table>
+ *
+ * <p> Due to the resulting behavior, usage on TV and Audio devices is discouraged.
+ *
+ * @hide
+ * @see android.hardware.hdmi.HdmiControlManager#setHdmiCecVolumeControlEnabled(int)
+ */
+ public static final String CEC_SETTING_NAME_VOLUME_CONTROL_MODE =
+ "volume_control_enabled";
+
/**
* @hide
*/
@@ -501,6 +565,7 @@ public final class HdmiControlManager {
CEC_SETTING_NAME_POWER_CONTROL_MODE,
CEC_SETTING_NAME_POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST,
CEC_SETTING_NAME_SYSTEM_AUDIO_MODE_MUTING,
+ CEC_SETTING_NAME_VOLUME_CONTROL_MODE,
})
public @interface CecSettingName {}
@@ -913,14 +978,16 @@ public final class HdmiControlManager {
*
* <p> Due to the resulting behavior, usage on TV and Audio devices is discouraged.
*
- * @param isHdmiCecVolumeControlEnabled target state of HDMI CEC volume control.
- * @see Settings.Global.HDMI_CONTROL_VOLUME_CONTROL_ENABLED
+ * @param hdmiCecVolumeControlEnabled target state of HDMI CEC volume control.
+ * @see HdmiControlManager#CEC_SETTING_NAME_VOLUME_CONTROL_MODE
* @hide
*/
@RequiresPermission(android.Manifest.permission.HDMI_CEC)
- public void setHdmiCecVolumeControlEnabled(boolean isHdmiCecVolumeControlEnabled) {
+ public void setHdmiCecVolumeControlEnabled(
+ @VolumeControl int hdmiCecVolumeControlEnabled) {
try {
- mService.setHdmiCecVolumeControlEnabled(isHdmiCecVolumeControlEnabled);
+ mService.setCecSettingIntValue(CEC_SETTING_NAME_VOLUME_CONTROL_MODE,
+ hdmiCecVolumeControlEnabled);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -931,9 +998,10 @@ public final class HdmiControlManager {
* @hide
*/
@RequiresPermission(android.Manifest.permission.HDMI_CEC)
- public boolean isHdmiCecVolumeControlEnabled() {
+ @VolumeControl
+ public int getHdmiCecVolumeControlEnabled() {
try {
- return mService.isHdmiCecVolumeControlEnabled();
+ return mService.getCecSettingIntValue(CEC_SETTING_NAME_VOLUME_CONTROL_MODE);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1056,10 +1124,10 @@ public final class HdmiControlManager {
/**
* Called when the HDMI Control (CEC) volume control feature is enabled/disabled.
*
- * @param enabled status of HDMI CEC volume control feature
- * @see {@link HdmiControlManager#setHdmiCecVolumeControlEnabled(boolean)} ()}
+ * @param hdmiCecVolumeControl status of HDMI CEC volume control feature
+ * @see {@link HdmiControlManager#setHdmiCecVolumeControlEnabled(int)} ()}
**/
- void onHdmiCecVolumeControlFeature(boolean enabled);
+ void onHdmiCecVolumeControlFeature(@VolumeControl int hdmiCecVolumeControl);
}
private final ArrayMap<HdmiCecVolumeControlFeatureListener,
@@ -1360,7 +1428,7 @@ public final class HdmiControlManager {
Executor executor, final HdmiCecVolumeControlFeatureListener listener) {
return new android.hardware.hdmi.IHdmiCecVolumeControlFeatureListener.Stub() {
@Override
- public void onHdmiCecVolumeControlFeature(boolean enabled) {
+ public void onHdmiCecVolumeControlFeature(int enabled) {
final long token = Binder.clearCallingIdentity();
try {
executor.execute(() -> listener.onHdmiCecVolumeControlFeature(enabled));
diff --git a/core/java/android/hardware/hdmi/HdmiControlServiceWrapper.java b/core/java/android/hardware/hdmi/HdmiControlServiceWrapper.java
index 89a7afa894eb..9a9e945a91cf 100644
--- a/core/java/android/hardware/hdmi/HdmiControlServiceWrapper.java
+++ b/core/java/android/hardware/hdmi/HdmiControlServiceWrapper.java
@@ -273,17 +273,6 @@ public final class HdmiControlServiceWrapper {
}
@Override
- public void setHdmiCecVolumeControlEnabled(boolean isHdmiCecVolumeControlEnabled) {
- HdmiControlServiceWrapper.this.setHdmiCecVolumeControlEnabled(
- isHdmiCecVolumeControlEnabled);
- }
-
- @Override
- public boolean isHdmiCecVolumeControlEnabled() {
- return HdmiControlServiceWrapper.this.isHdmiCecVolumeControlEnabled();
- }
-
- @Override
public void reportAudioStatus(int deviceType, int volume, int maxVolume, boolean isMute) {
HdmiControlServiceWrapper.this.reportAudioStatus(deviceType, volume, maxVolume, isMute);
}
diff --git a/core/java/android/hardware/hdmi/IHdmiCecVolumeControlFeatureListener.aidl b/core/java/android/hardware/hdmi/IHdmiCecVolumeControlFeatureListener.aidl
index 873438bb1d20..f7c5887864c9 100644
--- a/core/java/android/hardware/hdmi/IHdmiCecVolumeControlFeatureListener.aidl
+++ b/core/java/android/hardware/hdmi/IHdmiCecVolumeControlFeatureListener.aidl
@@ -26,7 +26,7 @@ oneway interface IHdmiCecVolumeControlFeatureListener {
* Called when the HDMI Control (CEC) volume control feature is enabled/disabled.
*
* @param enabled status of HDMI CEC volume control feature
- * @see {@link HdmiControlManager#setHdmiCecVolumeControlEnabled(boolean)} ()}
+ * @see {@link HdmiControlManager#setHdmiCecVolumeControlEnabled(int)} ()}
**/
- void onHdmiCecVolumeControlFeature(boolean enabled);
+ void onHdmiCecVolumeControlFeature(int hdmiCecVolumeControl);
}
diff --git a/core/java/android/hardware/hdmi/IHdmiControlService.aidl b/core/java/android/hardware/hdmi/IHdmiControlService.aidl
index d7329e0ba3b5..7f0e53ea2e68 100644
--- a/core/java/android/hardware/hdmi/IHdmiControlService.aidl
+++ b/core/java/android/hardware/hdmi/IHdmiControlService.aidl
@@ -86,8 +86,6 @@ interface IHdmiControlService {
void sendMhlVendorCommand(int portId, int offset, int length, in byte[] data);
void addHdmiMhlVendorCommandListener(IHdmiMhlVendorCommandListener listener);
void setStandbyMode(boolean isStandbyModeOn);
- void setHdmiCecVolumeControlEnabled(boolean isHdmiCecVolumeControlEnabled);
- boolean isHdmiCecVolumeControlEnabled();
void reportAudioStatus(int deviceType, int volume, int maxVolume, boolean isMute);
void setSystemAudioModeOnForAudioOnlySource();
void addCecSettingChangeListener(String name, IHdmiCecSettingChangeListener listener);
diff --git a/core/java/android/os/SystemVibrator.java b/core/java/android/os/SystemVibrator.java
index 0330500f0997..30afe38be397 100644
--- a/core/java/android/os/SystemVibrator.java
+++ b/core/java/android/os/SystemVibrator.java
@@ -17,6 +17,7 @@
package android.os;
import android.annotation.CallbackExecutor;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.compat.annotation.UnsupportedAppUsage;
@@ -27,6 +28,8 @@ import android.util.Log;
import com.android.internal.annotations.GuardedBy;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.Objects;
import java.util.concurrent.Executor;
@@ -38,6 +41,14 @@ import java.util.concurrent.Executor;
public class SystemVibrator extends Vibrator {
private static final String TAG = "Vibrator";
+ private static final int VIBRATOR_PRESENT_UNKNOWN = 0;
+ private static final int VIBRATOR_PRESENT_YES = 1;
+ private static final int VIBRATOR_PRESENT_NO = 2;
+
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({VIBRATOR_PRESENT_UNKNOWN, VIBRATOR_PRESENT_YES, VIBRATOR_PRESENT_NO})
+ private @interface VibratorPresent {}
+
private final IVibratorService mService;
private final IVibratorManagerService mManagerService;
private final Object mLock = new Object();
@@ -45,6 +56,9 @@ public class SystemVibrator extends Vibrator {
private final Context mContext;
@GuardedBy("mLock")
private VibratorInfo mVibratorInfo;
+ @GuardedBy("mLock")
+ @VibratorPresent
+ private int mVibratorPresent;
@GuardedBy("mDelegates")
private final ArrayMap<OnVibratorStateChangedListener,
@@ -69,15 +83,18 @@ public class SystemVibrator extends Vibrator {
@Override
public boolean hasVibrator() {
- if (mService == null) {
- Log.w(TAG, "Failed to vibrate; no vibrator service.");
- return false;
- }
try {
- return mService.hasVibrator();
+ synchronized (mLock) {
+ if (mVibratorPresent == VIBRATOR_PRESENT_UNKNOWN && mService != null) {
+ mVibratorPresent =
+ mService.hasVibrator() ? VIBRATOR_PRESENT_YES : VIBRATOR_PRESENT_NO;
+ }
+ return mVibratorPresent == VIBRATOR_PRESENT_YES;
+ }
} catch (RemoteException e) {
+ Log.w(TAG, "Failed to query vibrator presence", e);
+ return false;
}
- return false;
}
/**
diff --git a/core/tests/hdmitests/src/android/hardware/hdmi/HdmiAudioSystemClientTest.java b/core/tests/hdmitests/src/android/hardware/hdmi/HdmiAudioSystemClientTest.java
index 6019b90ca13b..597ea14df56d 100644
--- a/core/tests/hdmitests/src/android/hardware/hdmi/HdmiAudioSystemClientTest.java
+++ b/core/tests/hdmitests/src/android/hardware/hdmi/HdmiAudioSystemClientTest.java
@@ -366,15 +366,6 @@ public class HdmiAudioSystemClientTest {
}
@Override
- public void setHdmiCecVolumeControlEnabled(boolean isHdmiCecVolumeControlEnabled) {
- }
-
- @Override
- public boolean isHdmiCecVolumeControlEnabled() {
- return true;
- }
-
- @Override
public void addHdmiCecVolumeControlFeatureListener(
IHdmiCecVolumeControlFeatureListener listener) {
}
diff --git a/media/java/android/media/MediaDrm.java b/media/java/android/media/MediaDrm.java
index 13bd85634fda..2703ee35b099 100644
--- a/media/java/android/media/MediaDrm.java
+++ b/media/java/android/media/MediaDrm.java
@@ -1993,6 +1993,33 @@ public final class MediaDrm implements AutoCloseable {
return signRSANative(this, sessionId, algorithm, wrappedKey, message);
}
+ /**
+ * Query if the crypto scheme requires the use of a secure decoder
+ * to decode data of the given mime type at the default security level.
+ * The default security level is defined as the highest security level
+ * supported on the device.
+ *
+ * @param mime The mime type of the media data
+ */
+ public boolean requiresSecureDecoder(@NonNull String mime) {
+ return requiresSecureDecoder(mime, getMaxSecurityLevel());
+ }
+
+ /**
+ * Query if the crypto scheme requires the use of a secure decoder
+ * to decode data of the given mime type at the given security level.
+ *
+ * @param mime The mime type of the media data
+ * @param level a security level between {@link #SECURITY_LEVEL_SW_SECURE_CRYPTO}
+ * and {@link #SECURITY_LEVEL_HW_SECURE_ALL}. Otherwise the special value
+ * {@link #getMaxSecurityLevel()} is also permitted;
+ * use {@link #getMaxSecurityLevel()} to indicate the maximum security level
+ * supported by the device.
+ * @throws IllegalArgumentException if the requested security level is none of the documented
+ * values for the parameter {@code level}.
+ */
+ public native boolean requiresSecureDecoder(@NonNull String mime, @SecurityLevel int level);
+
@Override
protected void finalize() throws Throwable {
try {
diff --git a/media/jni/android_media_MediaDrm.cpp b/media/jni/android_media_MediaDrm.cpp
index f38a29c69a3e..babb16b1c880 100644
--- a/media/jni/android_media_MediaDrm.cpp
+++ b/media/jni/android_media_MediaDrm.cpp
@@ -1953,6 +1953,30 @@ static jbyteArray android_media_MediaDrm_signRSANative(
return VectorToJByteArray(env, signature);
}
+static jboolean android_media_MediaDrm_requiresSecureDecoder(
+ JNIEnv *env, jobject thiz, jstring jmimeType,
+ jint jSecurityLevel) {
+ sp<IDrm> drm = GetDrm(env, thiz);
+ if (!CheckDrm(env, drm)) {
+ return JNI_FALSE;
+ }
+
+ String8 mimeType;
+ if (jmimeType != NULL) {
+ mimeType = JStringToString8(env, jmimeType);
+ }
+
+ DrmPlugin::SecurityLevel securityLevel = jintToSecurityLevel(jSecurityLevel);
+ if (securityLevel == DrmPlugin::kSecurityLevelUnknown) {
+ jniThrowException(env, "java/lang/IllegalArgumentException", "Invalid security level");
+ return JNI_FALSE;
+ }
+
+ if (securityLevel == DrmPlugin::kSecurityLevelMax) {
+ return drm->requiresSecureDecoder(mimeType.c_str());
+ }
+ return drm->requiresSecureDecoder(mimeType.c_str(), securityLevel);
+}
static const JNINativeMethod gMethods[] = {
{ "native_release", "()V", (void *)android_media_MediaDrm_native_release },
@@ -2075,6 +2099,9 @@ static const JNINativeMethod gMethods[] = {
{ "getMetricsNative", "()Landroid/os/PersistableBundle;",
(void *)android_media_MediaDrm_native_getMetrics },
+
+ { "requiresSecureDecoder", "(Ljava/lang/String;I)Z",
+ (void *)android_media_MediaDrm_requiresSecureDecoder },
};
int register_android_media_Drm(JNIEnv *env) {
diff --git a/packages/SystemUI/res/values-television/config.xml b/packages/SystemUI/res/values-television/config.xml
index 0c8c5c443c4a..dec83d95f0be 100644
--- a/packages/SystemUI/res/values-television/config.xml
+++ b/packages/SystemUI/res/values-television/config.xml
@@ -43,6 +43,7 @@
<item>com.android.systemui.statusbar.notification.InstantAppNotifier</item>
<item>com.android.systemui.toast.ToastUI</item>
<item>com.android.systemui.wmshell.WMShell</item>
+ <item>com.android.systemui.media.systemsounds.HomeSoundEffectController</item>
</string-array>
<!-- Svelte specific logic, see RecentsConfiguration.SVELTE_* constants. -->
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java
index 9f6c19bdf06f..55359ea70873 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java
@@ -27,6 +27,7 @@ import com.android.systemui.biometrics.AuthController;
import com.android.systemui.globalactions.GlobalActionsComponent;
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.keyguard.dagger.KeyguardModule;
+import com.android.systemui.media.systemsounds.HomeSoundEffectController;
import com.android.systemui.power.PowerUI;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.RecentsModule;
@@ -178,4 +179,10 @@ public abstract class SystemUIBinder {
@IntoMap
@ClassKey(WMShell.class)
public abstract SystemUI bindWMShell(WMShell sysui);
+
+ /** Inject into HomeSoundEffectController. */
+ @Binds
+ @IntoMap
+ @ClassKey(HomeSoundEffectController.class)
+ public abstract SystemUI bindHomeSoundEffectController(HomeSoundEffectController sysui);
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/systemsounds/HomeSoundEffectController.java b/packages/SystemUI/src/com/android/systemui/media/systemsounds/HomeSoundEffectController.java
new file mode 100644
index 000000000000..dd3d02a86672
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/media/systemsounds/HomeSoundEffectController.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2020 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.systemui.media.systemsounds;
+
+import android.app.ActivityManager;
+import android.app.WindowConfiguration;
+import android.content.Context;
+import android.media.AudioManager;
+
+import com.android.systemui.SystemUI;
+import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.shared.system.TaskStackChangeListener;
+import com.android.systemui.shared.system.TaskStackChangeListeners;
+
+import javax.inject.Inject;
+
+/**
+ * If a sound effect is defined for {@link android.media.AudioManager#FX_HOME}, a sound is played
+ * when the home task moves to front and the last task that moved to front was not the home task.
+ */
+@SysUISingleton
+public class HomeSoundEffectController extends SystemUI {
+
+ private final AudioManager mAudioManager;
+ private final TaskStackChangeListeners mTaskStackChangeListeners;
+ // Initialize true because home sound should not be played when the system boots.
+ private boolean mIsLastTaskHome = true;
+
+ @Inject
+ public HomeSoundEffectController(
+ Context context,
+ AudioManager audioManager,
+ TaskStackChangeListeners taskStackChangeListeners) {
+ super(context);
+ mAudioManager = audioManager;
+ mTaskStackChangeListeners = taskStackChangeListeners;
+ }
+
+ @Override
+ public void start() {
+ if (mAudioManager.isHomeSoundEffectEnabled()) {
+ mTaskStackChangeListeners.registerTaskStackListener(
+ new TaskStackChangeListener() {
+ @Override
+ public void onTaskMovedToFront(ActivityManager.RunningTaskInfo taskInfo) {
+ handleHomeTaskMovedToFront(taskInfo);
+ }
+ });
+ }
+ }
+
+ private boolean isHomeTask(ActivityManager.RunningTaskInfo taskInfo) {
+ return taskInfo.getActivityType() == WindowConfiguration.ACTIVITY_TYPE_HOME;
+ }
+
+ /**
+ * To enable a home sound, check if the home app moves to front.
+ */
+ private void handleHomeTaskMovedToFront(ActivityManager.RunningTaskInfo taskInfo) {
+ boolean isCurrentTaskHome = isHomeTask(taskInfo);
+ // If the last task is home we don't want to play the home sound. This avoids playing
+ // the home sound after FallbackHome transitions to Home
+ if (!mIsLastTaskHome && isCurrentTaskHome) {
+ mAudioManager.playSoundEffect(AudioManager.FX_HOME);
+ }
+ mIsLastTaskHome = isCurrentTaskHome;
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/systemsounds/HomeSoundEffectControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/systemsounds/HomeSoundEffectControllerTest.java
new file mode 100644
index 000000000000..3a77f7eec7f9
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/systemsounds/HomeSoundEffectControllerTest.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2021 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.systemui.media.systemsounds;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.app.ActivityManager;
+import android.app.WindowConfiguration;
+import android.content.Context;
+import android.media.AudioManager;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.shared.system.TaskStackChangeListener;
+import com.android.systemui.shared.system.TaskStackChangeListeners;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class HomeSoundEffectControllerTest extends SysuiTestCase {
+
+ private @Mock Context mContext;
+ private @Mock AudioManager mAudioManager;
+ private @Mock TaskStackChangeListeners mTaskStackChangeListeners;
+ private @Mock ActivityManager.RunningTaskInfo mStandardActivityTaskInfo;
+ private @Mock ActivityManager.RunningTaskInfo mHomeActivityTaskInfo;
+
+ private HomeSoundEffectController mController;
+ private TaskStackChangeListener mTaskStackChangeListener;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+
+ doReturn(WindowConfiguration.ACTIVITY_TYPE_STANDARD).when(
+ mStandardActivityTaskInfo).getActivityType();
+ doReturn(WindowConfiguration.ACTIVITY_TYPE_HOME).when(
+ mHomeActivityTaskInfo).getActivityType();
+
+ mController = new HomeSoundEffectController(mContext, mAudioManager,
+ mTaskStackChangeListeners);
+ }
+
+ @Test
+ public void testHomeSoundEffectNotPlayedWhenHomeFirstMovesToFront() {
+ // When HomeSoundEffectController is started and the home sound effect is enabled,
+ startController(true /* isHomeSoundEffectEnabled */);
+
+ // And the home task moves to the front,
+ mTaskStackChangeListener.onTaskMovedToFront(mHomeActivityTaskInfo);
+
+ // Then no home sound effect should be played.
+ verify(mAudioManager, never()).playSoundEffect(AudioManager.FX_HOME);
+ }
+
+ @Test
+ public void testHomeSoundEffectPlayedWhenEnabled() {
+ // When HomeSoundEffectController is started and the home sound effect is enabled,
+ startController(true /* isHomeSoundEffectEnabled */);
+
+ // And first a task different from the home task moves to front,
+ mTaskStackChangeListener.onTaskMovedToFront(mStandardActivityTaskInfo);
+
+ // And the home task moves to the front,
+ mTaskStackChangeListener.onTaskMovedToFront(mHomeActivityTaskInfo);
+
+ // Then the home sound effect should be played.
+ verify(mAudioManager).playSoundEffect(AudioManager.FX_HOME);
+ }
+
+ @Test
+ public void testHomeSoundEffectNotPlayedTwiceInRow() {
+ // When HomeSoundEffectController is started and the home sound effect is enabled,
+ startController(true /* isHomeSoundEffectEnabled */);
+
+ // And first a task different from the home task moves to front,
+ mTaskStackChangeListener.onTaskMovedToFront(mStandardActivityTaskInfo);
+
+ // And the home task moves to the front,
+ mTaskStackChangeListener.onTaskMovedToFront(mHomeActivityTaskInfo);
+
+ // Then the home sound effect should be played.
+ verify(mAudioManager).playSoundEffect(AudioManager.FX_HOME);
+
+ // If the home task moves to front a second time in a row,
+ mTaskStackChangeListener.onTaskMovedToFront(mHomeActivityTaskInfo);
+
+ // Then no home sound effect should be played.
+ verify(mAudioManager, times(1)).playSoundEffect(AudioManager.FX_HOME);
+ }
+
+ @Test
+ public void testHomeSoundEffectNotPlayedWhenNonHomeTaskMovesToFront() {
+ // When HomeSoundEffectController is started and the home sound effect is enabled,
+ startController(true /* isHomeSoundEffectEnabled */);
+
+ // And a standard, non-home task, moves to the front,
+ mTaskStackChangeListener.onTaskMovedToFront(mStandardActivityTaskInfo);
+
+ // Then no home sound effect should be played.
+ verify(mAudioManager, never()).playSoundEffect(AudioManager.FX_HOME);
+ }
+
+ @Test
+ public void testHomeSoundEffectDisabled() {
+ // When HomeSoundEffectController is started and the home sound effect is disabled,
+ startController(false /* isHomeSoundEffectEnabled */);
+
+ // Then no TaskStackListener should be registered
+ verify(mTaskStackChangeListeners, never()).registerTaskStackListener(
+ any(TaskStackChangeListener.class));
+ }
+
+ /**
+ * Sets {@link AudioManager#isHomeSoundEffectEnabled()} and starts HomeSoundEffectController.
+ * If the home sound effect is enabled, the registered TaskStackChangeListener is extracted.
+ */
+ private void startController(boolean isHomeSoundEffectEnabled) {
+ // Configure home sound effect to be enabled
+ doReturn(isHomeSoundEffectEnabled).when(mAudioManager).isHomeSoundEffectEnabled();
+
+ mController.start();
+
+ if (isHomeSoundEffectEnabled) {
+ // Construct controller. Save the TaskStackListener for injecting events.
+ final ArgumentCaptor<TaskStackChangeListener> listenerCaptor =
+ ArgumentCaptor.forClass(TaskStackChangeListener.class);
+ verify(mTaskStackChangeListeners).registerTaskStackListener(listenerCaptor.capture());
+ mTaskStackChangeListener = listenerCaptor.getValue();
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 1f48aeb91de8..b07c892ff226 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -6003,23 +6003,21 @@ public class ActivityManagerService extends IActivityManager.Stub
final ProcessRecord addAppLocked(ApplicationInfo info, String customProcess, boolean isolated,
String abiOverride, int zygotePolicyFlags) {
return addAppLocked(info, customProcess, isolated, false /* disableHiddenApiChecks */,
- false /* mountExtStorageFull */, abiOverride, zygotePolicyFlags);
+ abiOverride, zygotePolicyFlags);
}
@GuardedBy("this")
final ProcessRecord addAppLocked(ApplicationInfo info, String customProcess, boolean isolated,
- boolean disableHiddenApiChecks, boolean mountExtStorageFull, String abiOverride,
- int zygotePolicyFlags) {
+ boolean disableHiddenApiChecks, String abiOverride, int zygotePolicyFlags) {
return addAppLocked(info, customProcess, isolated, disableHiddenApiChecks,
- false /* disableTestApiChecks */, mountExtStorageFull, abiOverride,
- zygotePolicyFlags);
+ false /* disableTestApiChecks */, abiOverride, zygotePolicyFlags);
}
// TODO: Move to ProcessList?
@GuardedBy("this")
final ProcessRecord addAppLocked(ApplicationInfo info, String customProcess, boolean isolated,
boolean disableHiddenApiChecks, boolean disableTestApiChecks,
- boolean mountExtStorageFull, String abiOverride, int zygotePolicyFlags) {
+ String abiOverride, int zygotePolicyFlags) {
ProcessRecord app;
if (!isolated) {
app = getProcessRecordLocked(customProcess != null ? customProcess : info.processName,
@@ -6054,8 +6052,7 @@ public class ActivityManagerService extends IActivityManager.Stub
mPersistentStartingProcesses.add(app);
mProcessList.startProcessLocked(app, new HostingRecord("added application",
customProcess != null ? customProcess : app.processName),
- zygotePolicyFlags, disableHiddenApiChecks, disableTestApiChecks,
- mountExtStorageFull, abiOverride);
+ zygotePolicyFlags, disableHiddenApiChecks, disableTestApiChecks, abiOverride);
}
return app;
@@ -7612,10 +7609,10 @@ public class ActivityManagerService extends IActivityManager.Stub
crashInfo.throwLineNumber);
FrameworkStatsLog.write(FrameworkStatsLog.APP_CRASH_OCCURRED,
- Binder.getCallingUid(),
+ (r != null) ? r.uid : -1,
eventType,
processName,
- Binder.getCallingPid(),
+ (r != null) ? r.pid : -1,
(r != null && r.info != null) ? r.info.packageName : "",
(r != null && r.info != null) ? (r.info.isInstantApp()
? FrameworkStatsLog.APP_CRASH_OCCURRED__IS_INSTANT_APP__TRUE
@@ -14356,10 +14353,6 @@ public class ActivityManagerService extends IActivityManager.Stub
"disable hidden API checks");
}
- // TODO(b/158750470): remove
- final boolean mountExtStorageFull = isCallerShell()
- && (flags & INSTR_FLAG_DISABLE_ISOLATED_STORAGE) != 0;
-
final long origId = Binder.clearCallingIdentity();
ProcessRecord app;
@@ -14375,8 +14368,7 @@ public class ActivityManagerService extends IActivityManager.Stub
UsageEvents.Event.SYSTEM_INTERACTION);
}
app = addAppLocked(ai, defProcess, false, disableHiddenApiChecks,
- disableTestApiChecks, mountExtStorageFull, abiOverride,
- ZYGOTE_POLICY_FLAG_EMPTY);
+ disableTestApiChecks, abiOverride, ZYGOTE_POLICY_FLAG_EMPTY);
}
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 6f6cad043a42..47b7e1b5fa41 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -1737,7 +1737,7 @@ public final class ProcessList {
@GuardedBy("mService")
boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord,
int zygotePolicyFlags, boolean disableHiddenApiChecks, boolean disableTestApiChecks,
- boolean mountExtStorageFull, String abiOverride) {
+ String abiOverride) {
if (app.pendingStart) {
return true;
}
@@ -2331,7 +2331,7 @@ public final class ProcessList {
int zygotePolicyFlags, String abiOverride) {
return startProcessLocked(app, hostingRecord, zygotePolicyFlags,
false /* disableHiddenApiChecks */, false /* disableTestApiChecks */,
- false /* mountExtStorageFull */, abiOverride);
+ abiOverride);
}
@GuardedBy("mService")
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 17627fa23a96..e13d6af99231 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -7734,10 +7734,12 @@ public class AudioService extends IAudioService.Stub
private class MyHdmiCecVolumeControlFeatureListener
implements HdmiControlManager.HdmiCecVolumeControlFeatureListener {
- public void onHdmiCecVolumeControlFeature(boolean enabled) {
+ public void onHdmiCecVolumeControlFeature(
+ @HdmiControlManager.VolumeControl int hdmiCecVolumeControl) {
synchronized (mHdmiClientLock) {
if (mHdmiManager == null) return;
- mHdmiCecVolumeControlEnabled = enabled;
+ mHdmiCecVolumeControlEnabled =
+ hdmiCecVolumeControl == HdmiControlManager.VOLUME_CONTROL_ENABLED;
}
}
};
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecConfig.java b/services/core/java/com/android/server/hdmi/HdmiCecConfig.java
index 16695d1237b6..e854481985ce 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecConfig.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecConfig.java
@@ -291,6 +291,8 @@ public class HdmiCecConfig {
return STORAGE_GLOBAL_SETTINGS;
case HdmiControlManager.CEC_SETTING_NAME_POWER_CONTROL_MODE:
return STORAGE_GLOBAL_SETTINGS;
+ case HdmiControlManager.CEC_SETTING_NAME_VOLUME_CONTROL_MODE:
+ return STORAGE_GLOBAL_SETTINGS;
case HdmiControlManager.CEC_SETTING_NAME_POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST:
return STORAGE_SHARED_PREFS;
case HdmiControlManager.CEC_SETTING_NAME_SYSTEM_AUDIO_MODE_MUTING:
@@ -309,6 +311,8 @@ public class HdmiCecConfig {
return Global.HDMI_CEC_VERSION;
case HdmiControlManager.CEC_SETTING_NAME_POWER_CONTROL_MODE:
return Global.HDMI_CONTROL_SEND_STANDBY_ON_SLEEP;
+ case HdmiControlManager.CEC_SETTING_NAME_VOLUME_CONTROL_MODE:
+ return Global.HDMI_CONTROL_VOLUME_CONTROL_ENABLED;
case HdmiControlManager.CEC_SETTING_NAME_POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST:
return setting.getName();
case HdmiControlManager.CEC_SETTING_NAME_SYSTEM_AUDIO_MODE_MUTING:
@@ -323,13 +327,13 @@ public class HdmiCecConfig {
@Storage int storage = getStorage(setting);
String storageKey = getStorageKey(setting);
if (storage == STORAGE_SYSPROPS) {
- Slog.d(TAG, "Reading '" + storageKey + "' sysprop.");
+ HdmiLogger.debug("Reading '" + storageKey + "' sysprop.");
return mStorageAdapter.retrieveSystemProperty(storageKey, defaultValue);
} else if (storage == STORAGE_GLOBAL_SETTINGS) {
- Slog.d(TAG, "Reading '" + storageKey + "' global setting.");
+ HdmiLogger.debug("Reading '" + storageKey + "' global setting.");
return mStorageAdapter.retrieveGlobalSetting(storageKey, defaultValue);
} else if (storage == STORAGE_SHARED_PREFS) {
- Slog.d(TAG, "Reading '" + storageKey + "' shared preference.");
+ HdmiLogger.debug("Reading '" + storageKey + "' shared preference.");
return mStorageAdapter.retrieveSharedPref(storageKey, defaultValue);
}
return null;
@@ -339,13 +343,13 @@ public class HdmiCecConfig {
@Storage int storage = getStorage(setting);
String storageKey = getStorageKey(setting);
if (storage == STORAGE_SYSPROPS) {
- Slog.d(TAG, "Setting '" + storageKey + "' sysprop.");
+ HdmiLogger.debug("Setting '" + storageKey + "' sysprop.");
mStorageAdapter.storeSystemProperty(storageKey, value);
} else if (storage == STORAGE_GLOBAL_SETTINGS) {
- Slog.d(TAG, "Setting '" + storageKey + "' global setting.");
+ HdmiLogger.debug("Setting '" + storageKey + "' global setting.");
mStorageAdapter.storeGlobalSetting(storageKey, value);
} else if (storage == STORAGE_SHARED_PREFS) {
- Slog.d(TAG, "Setting '" + storageKey + "' shared pref.");
+ HdmiLogger.debug("Setting '" + storageKey + "' shared pref.");
mStorageAdapter.storeSharedPref(storageKey, value);
notifySettingChanged(setting);
}
@@ -366,6 +370,9 @@ public class HdmiCecConfig {
case Global.HDMI_CONTROL_SEND_STANDBY_ON_SLEEP:
notifySettingChanged(HdmiControlManager.CEC_SETTING_NAME_POWER_CONTROL_MODE);
break;
+ case Global.HDMI_CONTROL_VOLUME_CONTROL_ENABLED:
+ notifySettingChanged(HdmiControlManager.CEC_SETTING_NAME_VOLUME_CONTROL_MODE);
+ break;
}
}
@@ -399,6 +406,7 @@ public class HdmiCecConfig {
Global.HDMI_CONTROL_ENABLED,
Global.HDMI_CEC_VERSION,
Global.HDMI_CONTROL_SEND_STANDBY_ON_SLEEP,
+ Global.HDMI_CONTROL_VOLUME_CONTROL_ENABLED,
};
for (String setting: settings) {
resolver.registerContentObserver(Global.getUriFor(setting), false,
@@ -597,7 +605,7 @@ public class HdmiCecConfig {
throw new IllegalArgumentException("Setting '" + name
+ "' is not a string-type setting.");
}
- Slog.d(TAG, "Getting CEC setting value '" + name + "'.");
+ HdmiLogger.debug("Getting CEC setting value '" + name + "'.");
return retrieveValue(setting, setting.getDefaultValue().getStringValue());
}
@@ -613,7 +621,7 @@ public class HdmiCecConfig {
throw new IllegalArgumentException("Setting '" + name
+ "' is not a int-type setting.");
}
- Slog.d(TAG, "Getting CEC setting value '" + name + "'.");
+ HdmiLogger.debug("Getting CEC setting value '" + name + "'.");
String defaultValue = Integer.toString(getIntValue(setting.getDefaultValue()));
String value = retrieveValue(setting, defaultValue);
return Integer.parseInt(value);
@@ -638,7 +646,7 @@ public class HdmiCecConfig {
throw new IllegalArgumentException("Invalid CEC setting '" + name
+ "' value: '" + value + "'.");
}
- Slog.d(TAG, "Updating CEC setting '" + name + "' to '" + value + "'.");
+ HdmiLogger.debug("Updating CEC setting '" + name + "' to '" + value + "'.");
storeValue(setting, value);
}
@@ -661,7 +669,7 @@ public class HdmiCecConfig {
throw new IllegalArgumentException("Invalid CEC setting '" + name
+ "' value: '" + value + "'.");
}
- Slog.d(TAG, "Updating CEC setting '" + name + "' to '" + value + "'.");
+ HdmiLogger.debug("Updating CEC setting '" + name + "' to '" + value + "'.");
storeValue(setting, Integer.toString(value));
}
}
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
index 0b10cc36ded9..ccce9dc43e6d 100755
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
@@ -619,7 +619,9 @@ abstract class HdmiCecLocalDevice {
} else if (mService.isPowerStandbyOrTransient() && isPowerOnOrToggleCommand(message)) {
mService.wakeUp();
return true;
- } else if (!mService.isHdmiCecVolumeControlEnabled() && isVolumeOrMuteCommand(message)) {
+ } else if (mService.getHdmiCecVolumeControl()
+ == HdmiControlManager.VOLUME_CONTROL_DISABLED && isVolumeOrMuteCommand(
+ message)) {
return false;
}
@@ -1142,7 +1144,8 @@ abstract class HdmiCecLocalDevice {
@ServiceThreadOnly
protected void sendVolumeKeyEvent(int keyCode, boolean isPressed) {
assertRunOnServiceThread();
- if (!mService.isHdmiCecVolumeControlEnabled()) {
+ if (mService.getHdmiCecVolumeControl()
+ == HdmiControlManager.VOLUME_CONTROL_DISABLED) {
return;
}
if (!HdmiCecKeycode.isVolumeKeycode(keyCode)) {
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java
index a945c90d30ef..b909b1639e1a 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java
@@ -373,7 +373,8 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource {
@ServiceThreadOnly
protected boolean handleGiveAudioStatus(HdmiCecMessage message) {
assertRunOnServiceThread();
- if (isSystemAudioControlFeatureEnabled() && mService.isHdmiCecVolumeControlEnabled()) {
+ if (isSystemAudioControlFeatureEnabled() && mService.getHdmiCecVolumeControl()
+ == HdmiControlManager.VOLUME_CONTROL_ENABLED) {
reportAudioStatus(message.getSource());
} else {
mService.maySendFeatureAbortCommand(message, Constants.ABORT_REFUSED);
@@ -723,7 +724,8 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource {
void reportAudioStatus(int source) {
assertRunOnServiceThread();
- if (!mService.isHdmiCecVolumeControlEnabled()) {
+ if (mService.getHdmiCecVolumeControl()
+ == HdmiControlManager.VOLUME_CONTROL_DISABLED) {
return;
}
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
index ad3773e78b6a..e568aa228b40 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
@@ -618,7 +618,8 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
@ServiceThreadOnly
protected boolean handleReportAudioStatus(HdmiCecMessage message) {
assertRunOnServiceThread();
- if (!mService.isHdmiCecVolumeControlEnabled()) {
+ if (mService.getHdmiCecVolumeControl()
+ == HdmiControlManager.VOLUME_CONTROL_DISABLED) {
return false;
}
@@ -897,7 +898,8 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
}
void setAudioStatus(boolean mute, int volume) {
- if (!isSystemAudioActivated() || !mService.isHdmiCecVolumeControlEnabled()) {
+ if (!isSystemAudioActivated() || mService.getHdmiCecVolumeControl()
+ == HdmiControlManager.VOLUME_CONTROL_DISABLED) {
return;
}
synchronized (mLock) {
@@ -919,7 +921,8 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
// On initialization process, getAvrDeviceInfo() may return null and cause exception
return;
}
- if (delta == 0 || !isSystemAudioActivated() || !mService.isHdmiCecVolumeControlEnabled()) {
+ if (delta == 0 || !isSystemAudioActivated() || mService.getHdmiCecVolumeControl()
+ == HdmiControlManager.VOLUME_CONTROL_DISABLED) {
return;
}
@@ -948,7 +951,8 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
@ServiceThreadOnly
void changeMute(boolean mute) {
assertRunOnServiceThread();
- if (getAvrDeviceInfo() == null || !mService.isHdmiCecVolumeControlEnabled()) {
+ if (getAvrDeviceInfo() == null || mService.getHdmiCecVolumeControl()
+ == HdmiControlManager.VOLUME_CONTROL_DISABLED) {
// On initialization process, getAvrDeviceInfo() may return null and cause exception
return;
}
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index b427bd0a0b06..beaf6d53370d 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -206,7 +206,8 @@ public class HdmiControlService extends SystemService {
// Whether HDMI CEC volume control is enabled or not.
@GuardedBy("mLock")
- private boolean mHdmiCecVolumeControlEnabled;
+ @HdmiControlManager.VolumeControl
+ private int mHdmiCecVolumeControl;
// Make sure HdmiCecConfig is instantiated and the XMLs are read.
private final HdmiCecConfig mHdmiCecConfig;
@@ -478,8 +479,8 @@ public class HdmiControlService extends SystemService {
mHdmiControlEnabled = mHdmiCecConfig.getIntValue(
HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_ENABLED)
== HdmiControlManager.HDMI_CEC_CONTROL_ENABLED;
- mHdmiCecVolumeControlEnabled = readBooleanSetting(
- Global.HDMI_CONTROL_VOLUME_CONTROL_ENABLED, true);
+ setHdmiCecVolumeControlEnabledInternal(getHdmiCecConfig().getIntValue(
+ HdmiControlManager.CEC_SETTING_NAME_VOLUME_CONTROL_MODE));
mMhlInputChangeEnabled = readBooleanSetting(Global.MHL_INPUT_SWITCHING_ENABLED, true);
if (mCecController == null) {
@@ -676,7 +677,8 @@ public class HdmiControlService extends SystemService {
boolean enabled = readBooleanSetting(option, true);
switch (option) {
case Global.HDMI_CONTROL_VOLUME_CONTROL_ENABLED:
- setHdmiCecVolumeControlEnabledInternal(enabled);
+ setHdmiCecVolumeControlEnabledInternal(getHdmiCecConfig().getIntValue(
+ HdmiControlManager.CEC_SETTING_NAME_VOLUME_CONTROL_MODE));
break;
case Global.HDMI_CONTROL_AUTO_WAKEUP_ENABLED:
if (isTvDeviceEnabled()) {
@@ -1212,7 +1214,8 @@ public class HdmiControlService extends SystemService {
void setAudioStatus(boolean mute, int volume) {
if (!isTvDeviceEnabled()
|| !tv().isSystemAudioActivated()
- || !isHdmiCecVolumeControlEnabled()) {
+ || getHdmiCecVolumeControl()
+ == HdmiControlManager.VOLUME_CONTROL_DISABLED) {
return;
}
AudioManager audioManager = getAudioManager();
@@ -2120,24 +2123,6 @@ public class HdmiControlService extends SystemService {
}
@Override
- public boolean isHdmiCecVolumeControlEnabled() {
- initBinderCall();
- return HdmiControlService.this.isHdmiCecVolumeControlEnabled();
- }
-
- @Override
- public void setHdmiCecVolumeControlEnabled(final boolean isHdmiCecVolumeControlEnabled) {
- initBinderCall();
- final long token = Binder.clearCallingIdentity();
- try {
- HdmiControlService.this.setHdmiCecVolumeControlEnabled(
- isHdmiCecVolumeControlEnabled);
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- @Override
public void reportAudioStatus(final int deviceType, final int volume, final int maxVolume,
final boolean isMute) {
initBinderCall();
@@ -2211,7 +2196,7 @@ public class HdmiControlService extends SystemService {
pw.println("mHdmiControlEnabled: " + mHdmiControlEnabled);
pw.println("mMhlInputChangeEnabled: " + mMhlInputChangeEnabled);
pw.println("mSystemAudioActivated: " + isSystemAudioActivated());
- pw.println("mHdmiCecVolumeControlEnabled: " + mHdmiCecVolumeControlEnabled);
+ pw.println("mHdmiCecVolumeControlEnabled: " + mHdmiCecVolumeControl);
pw.decreaseIndent();
// CEC settings
@@ -2340,6 +2325,13 @@ public class HdmiControlService extends SystemService {
}
}
+ @VisibleForTesting
+ void setHdmiCecVolumeControlEnabledInternal(
+ @HdmiControlManager.VolumeControl int hdmiCecVolumeControl) {
+ mHdmiCecVolumeControl = hdmiCecVolumeControl;
+ announceHdmiCecVolumeControlFeatureChange(hdmiCecVolumeControl);
+ }
+
// Get the source address to send out commands to devices connected to the current device
// when other services interact with HdmiControlService.
private int getRemoteControlSourceAddress() {
@@ -2533,10 +2525,10 @@ public class HdmiControlService extends SystemService {
// Return the current status of mHdmiCecVolumeControlEnabled;
synchronized (mLock) {
try {
- listener.onHdmiCecVolumeControlFeature(mHdmiCecVolumeControlEnabled);
+ listener.onHdmiCecVolumeControlFeature(mHdmiCecVolumeControl);
} catch (RemoteException e) {
Slog.e(TAG, "Failed to report HdmiControlVolumeControlStatusChange: "
- + mHdmiCecVolumeControlEnabled, e);
+ + mHdmiCecVolumeControl, e);
}
}
}
@@ -2835,15 +2827,16 @@ public class HdmiControlService extends SystemService {
}
}
- private void announceHdmiCecVolumeControlFeatureChange(boolean isEnabled) {
+ private void announceHdmiCecVolumeControlFeatureChange(
+ @HdmiControlManager.VolumeControl int hdmiCecVolumeControl) {
assertRunOnServiceThread();
mHdmiCecVolumeControlFeatureListenerRecords.broadcast(listener -> {
try {
- listener.onHdmiCecVolumeControlFeature(isEnabled);
+ listener.onHdmiCecVolumeControlFeature(hdmiCecVolumeControl);
} catch (RemoteException e) {
Slog.e(TAG,
"Failed to report HdmiControlVolumeControlStatusChange: "
- + isEnabled);
+ + hdmiCecVolumeControl);
}
});
}
@@ -3193,31 +3186,10 @@ public class HdmiControlService extends SystemService {
}
}
- void setHdmiCecVolumeControlEnabled(boolean isHdmiCecVolumeControlEnabled) {
- setHdmiCecVolumeControlEnabledInternal(isHdmiCecVolumeControlEnabled);
-
- writeBooleanSetting(Global.HDMI_CONTROL_VOLUME_CONTROL_ENABLED,
- isHdmiCecVolumeControlEnabled);
- }
-
- @VisibleForTesting
- void setHdmiCecVolumeControlEnabledInternal(boolean isHdmiCecVolumeControlEnabled) {
- synchronized (mLock) {
- mHdmiCecVolumeControlEnabled = isHdmiCecVolumeControlEnabled;
-
- boolean storedValue = readBooleanSetting(Global.HDMI_CONTROL_VOLUME_CONTROL_ENABLED,
- true);
- if (storedValue != isHdmiCecVolumeControlEnabled) {
- HdmiLogger.debug("Changing HDMI CEC volume control feature state: %s",
- isHdmiCecVolumeControlEnabled);
- }
- }
- announceHdmiCecVolumeControlFeatureChange(isHdmiCecVolumeControlEnabled);
- }
-
- boolean isHdmiCecVolumeControlEnabled() {
+ @HdmiControlManager.VolumeControl
+ int getHdmiCecVolumeControl() {
synchronized (mLock) {
- return mHdmiCecVolumeControlEnabled;
+ return mHdmiCecVolumeControl;
}
}
@@ -3261,12 +3233,12 @@ public class HdmiControlService extends SystemService {
if (enabled) {
enableHdmiControlService();
- setHdmiCecVolumeControlEnabledInternal(
- readBooleanSetting(Global.HDMI_CONTROL_VOLUME_CONTROL_ENABLED, true));
+ setHdmiCecVolumeControlEnabledInternal(getHdmiCecConfig().getIntValue(
+ HdmiControlManager.CEC_SETTING_NAME_VOLUME_CONTROL_MODE));
return;
}
- setHdmiCecVolumeControlEnabledInternal(false);
+ setHdmiCecVolumeControlEnabledInternal(HdmiControlManager.VOLUME_CONTROL_DISABLED);
// Call the vendor handler before the service is disabled.
invokeVendorCommandListenersOnControlStateChanged(false,
HdmiControlManager.CONTROL_STATE_CHANGED_REASON_SETTING);
diff --git a/services/core/java/com/android/server/hdmi/cec_config.xml b/services/core/java/com/android/server/hdmi/cec_config.xml
index 480e0ec040a8..e6e3c2f5eda1 100644
--- a/services/core/java/com/android/server/hdmi/cec_config.xml
+++ b/services/core/java/com/android/server/hdmi/cec_config.xml
@@ -46,4 +46,13 @@
</allowed-values>
<default-value int-value="1" />
</setting>
+ <setting name="volume_control_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>
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 61b218ce7196..60d83f1fd4e8 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -3085,8 +3085,23 @@ public class NotificationManagerService extends SystemService {
synchronized (mToastQueue) {
int uid = Binder.getCallingUid();
+ int userId = UserHandle.getUserId(uid);
if (enable) {
mToastRateLimitingDisabledUids.remove(uid);
+ try {
+ String[] packages = mPackageManager.getPackagesForUid(uid);
+ if (packages == null) {
+ Slog.e(TAG, "setToastRateLimitingEnabled method haven't found any "
+ + "packages for the given uid: " + uid + ", toast rate "
+ + "limiter not reset for that uid.");
+ return;
+ }
+ for (String pkg : packages) {
+ mToastRateLimiter.clear(userId, pkg);
+ }
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to reset toast rate limiter for given uid", e);
+ }
} else {
mToastRateLimitingDisabledUids.add(uid);
}
diff --git a/services/core/java/com/android/server/utils/quota/MultiRateLimiter.java b/services/core/java/com/android/server/utils/quota/MultiRateLimiter.java
index fdbe4b425d39..82c6d01056fd 100644
--- a/services/core/java/com/android/server/utils/quota/MultiRateLimiter.java
+++ b/services/core/java/com/android/server/utils/quota/MultiRateLimiter.java
@@ -19,6 +19,8 @@ package com.android.server.utils.quota;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
+import android.content.pm.PackageManager;
+import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
@@ -48,15 +50,18 @@ import java.util.List;
* @hide
*/
public class MultiRateLimiter {
+ private static final String TAG = "MultiRateLimiter";
private static final CountQuotaTracker[] EMPTY_TRACKER_ARRAY = {};
private final Object mLock = new Object();
@GuardedBy("mLock")
private final CountQuotaTracker[] mQuotaTrackers;
+ private final PackageManager mPackageManager;
- private MultiRateLimiter(List<CountQuotaTracker> quotaTrackers) {
+ private MultiRateLimiter(List<CountQuotaTracker> quotaTrackers, PackageManager packageManager) {
mQuotaTrackers = quotaTrackers.toArray(EMPTY_TRACKER_ARRAY);
+ mPackageManager = packageManager;
}
/** Record that an event happened and count it towards the given quota. */
@@ -73,6 +78,13 @@ public class MultiRateLimiter {
}
}
+ /** Remove all saved events from the rate limiter for the given app (reset it). */
+ public void clear(int userId, @NonNull String packageName) {
+ synchronized (mLock) {
+ clearLocked(userId, packageName);
+ }
+ }
+
@GuardedBy("mLock")
private void noteEventLocked(int userId, @NonNull String packageName, @Nullable String tag) {
for (CountQuotaTracker quotaTracker : mQuotaTrackers) {
@@ -91,6 +103,22 @@ public class MultiRateLimiter {
return true;
}
+ @GuardedBy("mLock")
+ private void clearLocked(int userId, @NonNull String packageName) {
+ try {
+ int uid = mPackageManager.getApplicationInfoAsUser(packageName, 0, userId).uid;
+ for (CountQuotaTracker quotaTracker : mQuotaTrackers) {
+ // This method behaves as if the package has been removed from the device, which
+ // isn't the case here, but it does similar clean-up to what we are aiming for here,
+ // so it works for this use case.
+ quotaTracker.onAppRemovedLocked(packageName, uid);
+ }
+ } catch (PackageManager.NameNotFoundException e) {
+ Slog.e(TAG, "clear(userId, packageName) called with unrecognized arguments, no "
+ + "action taken");
+ }
+ }
+
/** Can create a new {@link MultiRateLimiter}. */
public static class Builder {
@@ -154,7 +182,7 @@ public class MultiRateLimiter {
* limit.
*/
public MultiRateLimiter build() {
- return new MultiRateLimiter(mQuotaTrackers);
+ return new MultiRateLimiter(mQuotaTrackers, mContext.getPackageManager());
}
}
diff --git a/services/core/java/com/android/server/utils/quota/QuotaTracker.java b/services/core/java/com/android/server/utils/quota/QuotaTracker.java
index 7f446185f63f..673862cc18e5 100644
--- a/services/core/java/com/android/server/utils/quota/QuotaTracker.java
+++ b/services/core/java/com/android/server/utils/quota/QuotaTracker.java
@@ -58,7 +58,7 @@ import java.util.PriorityQueue;
* of quota until it is below that limit again. Limits are applied according to the category
* the UPTC is placed in. Categories are basic constructs to apply different limits to
* different groups of UPTCs. For example, standby buckets can be a set of categories, or
- * foreground & background could be two categories. If every UPTC should have the limits
+ * foreground & background could be two categories. If every UPTC should have the same limits
* applied, then only one category is needed.
*
* Note: all limits are enforced per category unless explicitly stated otherwise.
@@ -361,7 +361,7 @@ abstract class QuotaTracker {
abstract void handleRemovedAppLocked(String packageName, int uid);
@GuardedBy("mLock")
- private void onAppRemovedLocked(String packageName, int uid) {
+ void onAppRemovedLocked(String packageName, int uid) {
if (packageName == null) {
Slog.wtf(TAG, "Told app removed but given null package name.");
return;
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index f9cc33453e15..0f4bb4c5b081 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -2606,7 +2606,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
finishActivityResults(resultCode, resultData, resultGrants);
- final boolean endTask = task.getActivityBelow(this) == null
+ final boolean endTask = task.getTopNonFinishingActivity() == null
&& !task.isClearingToReuseTask();
final int transit = endTask ? TRANSIT_OLD_TASK_CLOSE : TRANSIT_OLD_ACTIVITY_CLOSE;
if (isState(RESUMED)) {
diff --git a/services/tests/mockingservicestests/src/com/android/server/utils/quota/MultiRateLimiterTest.java b/services/tests/mockingservicestests/src/com/android/server/utils/quota/MultiRateLimiterTest.java
index df533f3c122a..ab86e19c4a56 100644
--- a/services/tests/mockingservicestests/src/com/android/server/utils/quota/MultiRateLimiterTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/utils/quota/MultiRateLimiterTest.java
@@ -16,15 +16,29 @@
package com.android.server.utils.quota;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
+
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.when;
+
+import android.content.ContextWrapper;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.os.UserHandle;
import android.testing.TestableContext;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
+import org.junit.After;
+import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoSession;
+import org.mockito.quality.Strictness;
import java.time.Duration;
@@ -32,15 +46,20 @@ import java.time.Duration;
public class MultiRateLimiterTest {
private static final int USER_ID = 1;
+ private static final int UID_1 = 10_001;
private static final String PACKAGE_NAME_1 = "com.android.package.one";
private static final String PACKAGE_NAME_2 = "com.android.package.two";
private static final String TAG = "tag";
@Rule
- public final TestableContext mContext =
+ public final TestableContext mTestableContext =
new TestableContext(InstrumentationRegistry.getContext(), null);
private final InjectorForTest mInjector = new InjectorForTest();
+ private MockitoSession mMockingSession;
+ private ContextWrapper mContext;
+
+ @Mock private PackageManager mPackageManager;
private static class InjectorForTest extends QuotaTracker.Injector {
Duration mElapsedTime = Duration.ZERO;
@@ -56,6 +75,35 @@ public class MultiRateLimiterTest {
}
}
+ @Before
+ public void setup() throws Exception {
+ mMockingSession = mockitoSession()
+ .initMocks(this)
+ .strictness(Strictness.LENIENT)
+ .mockStatic(UserHandle.class)
+ .startMocking();
+ doReturn(USER_ID).when(() -> UserHandle.getUserId(UID_1));
+
+ ApplicationInfo applicationInfo = new ApplicationInfo();
+ applicationInfo.uid = UID_1;
+ when(mPackageManager.getApplicationInfoAsUser(PACKAGE_NAME_1, 0, USER_ID))
+ .thenReturn(applicationInfo);
+
+ mContext = new ContextWrapper(mTestableContext) {
+ @Override
+ public PackageManager getPackageManager() {
+ return mPackageManager;
+ }
+ };
+ }
+
+ @After
+ public void tearDown() {
+ if (mMockingSession != null) {
+ mMockingSession.finishMocking();
+ }
+ }
+
@Test
public void testSingleRateLimit_belowLimit_isWithinQuota() {
MultiRateLimiter multiRateLimiter = new MultiRateLimiter.Builder(mContext, mInjector)
@@ -194,4 +242,48 @@ public class MultiRateLimiterTest {
assertThat(multiRateLimiter.isWithinQuota(USER_ID, PACKAGE_NAME_1, TAG)).isTrue();
assertThat(multiRateLimiter.isWithinQuota(USER_ID, PACKAGE_NAME_2, TAG)).isTrue();
}
+
+ @Test
+ public void clearRateLimiterForPackage_afterReachingQuota_quotaIsReset() {
+ MultiRateLimiter multiRateLimiter = new MultiRateLimiter.Builder(mContext, mInjector)
+ .addRateLimit(1, Duration.ofSeconds(100))
+ .build();
+
+ mInjector.mElapsedTime = Duration.ZERO;
+ assertThat(multiRateLimiter.isWithinQuota(USER_ID, PACKAGE_NAME_1, TAG)).isTrue();
+ multiRateLimiter.noteEvent(USER_ID, PACKAGE_NAME_1, TAG);
+
+ mInjector.mElapsedTime = Duration.ofSeconds(1);
+ assertThat(multiRateLimiter.isWithinQuota(USER_ID, PACKAGE_NAME_1, TAG)).isFalse();
+
+ multiRateLimiter.clear(USER_ID, PACKAGE_NAME_1);
+
+ // Quota for that package is reset.
+ mInjector.mElapsedTime = Duration.ofSeconds(1);
+ assertThat(multiRateLimiter.isWithinQuota(USER_ID, PACKAGE_NAME_1, TAG)).isTrue();
+
+ // Quota is enforced again.
+ mInjector.mElapsedTime = Duration.ofSeconds(1);
+ multiRateLimiter.noteEvent(USER_ID, PACKAGE_NAME_1, TAG);
+ assertThat(multiRateLimiter.isWithinQuota(USER_ID, PACKAGE_NAME_1, TAG)).isFalse();
+ }
+
+ @Test
+ public void clearRateLimiterForPackage_doesntAffectOtherPackages() {
+ MultiRateLimiter multiRateLimiter = new MultiRateLimiter.Builder(mContext, mInjector)
+ .addRateLimit(1, Duration.ofSeconds(100))
+ .build();
+
+ mInjector.mElapsedTime = Duration.ZERO;
+ assertThat(multiRateLimiter.isWithinQuota(USER_ID, PACKAGE_NAME_2, TAG)).isTrue();
+ multiRateLimiter.noteEvent(USER_ID, PACKAGE_NAME_2, TAG);
+
+ mInjector.mElapsedTime = Duration.ofSeconds(1);
+ assertThat(multiRateLimiter.isWithinQuota(USER_ID, PACKAGE_NAME_2, TAG)).isFalse();
+
+ multiRateLimiter.clear(USER_ID, PACKAGE_NAME_1);
+
+ // Doesn't affect the other package.
+ assertThat(multiRateLimiter.isWithinQuota(USER_ID, PACKAGE_NAME_2, TAG)).isFalse();
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/FakeHdmiCecConfig.java b/services/tests/servicestests/src/com/android/server/hdmi/FakeHdmiCecConfig.java
index aeeca1a39cc0..8e37f94828fb 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/FakeHdmiCecConfig.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/FakeHdmiCecConfig.java
@@ -95,6 +95,15 @@ final class FakeHdmiCecConfig extends HdmiCecConfig {
+ " </allowed-values>"
+ " <default-value int-value=\"1\" />"
+ " </setting>"
+ + " <setting name=\"volume_control_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>";
FakeHdmiCecConfig(@NonNull Context context) {
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java
index 6bb68da2a894..95a0a7439904 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java
@@ -195,8 +195,9 @@ public class HdmiCecLocalDeviceAudioSystemTest {
}
};
- mHdmiControlService.setHdmiCecVolumeControlEnabled(true);
-
+ mHdmiControlService.getHdmiCecConfig().setIntValue(
+ HdmiControlManager.CEC_SETTING_NAME_VOLUME_CONTROL_MODE,
+ HdmiControlManager.VOLUME_CONTROL_ENABLED);
mMyLooper = mTestLooper.getLooper();
mHdmiCecLocalDeviceAudioSystem = new HdmiCecLocalDeviceAudioSystem(mHdmiControlService);
mHdmiCecLocalDevicePlayback = new HdmiCecLocalDevicePlayback(mHdmiControlService) {
@@ -710,7 +711,8 @@ public class HdmiCecLocalDeviceAudioSystemTest {
public void giveAudioStatus_volumeEnabled() {
mMusicVolume = 50;
mMusicMaxVolume = 100;
- mHdmiControlService.setHdmiCecVolumeControlEnabled(true);
+ mHdmiControlService.setHdmiCecVolumeControlEnabledInternal(
+ HdmiControlManager.VOLUME_CONTROL_ENABLED);
mHdmiCecLocalDeviceAudioSystem.setSystemAudioControlFeatureEnabled(true);
int volume = mHdmiControlService.getAudioManager()
@@ -740,7 +742,8 @@ public class HdmiCecLocalDeviceAudioSystemTest {
public void giveAudioStatus_volumeDisabled() {
mMusicVolume = 50;
mMusicMaxVolume = 100;
- mHdmiControlService.setHdmiCecVolumeControlEnabled(false);
+ mHdmiControlService.setHdmiCecVolumeControlEnabledInternal(
+ HdmiControlManager.VOLUME_CONTROL_DISABLED);
mHdmiCecLocalDeviceAudioSystem.setSystemAudioControlFeatureEnabled(true);
int volume = mHdmiControlService.getAudioManager()
@@ -770,7 +773,8 @@ public class HdmiCecLocalDeviceAudioSystemTest {
public void reportAudioStatus_volumeEnabled() {
mMusicVolume = 50;
mMusicMaxVolume = 100;
- mHdmiControlService.setHdmiCecVolumeControlEnabled(true);
+ mHdmiControlService.setHdmiCecVolumeControlEnabledInternal(
+ HdmiControlManager.VOLUME_CONTROL_ENABLED);
mHdmiCecLocalDeviceAudioSystem.setSystemAudioControlFeatureEnabled(true);
int volume = mHdmiControlService.getAudioManager()
@@ -794,7 +798,8 @@ public class HdmiCecLocalDeviceAudioSystemTest {
public void reportAudioStatus_volumeDisabled() {
mMusicVolume = 50;
mMusicMaxVolume = 100;
- mHdmiControlService.setHdmiCecVolumeControlEnabled(false);
+ mHdmiControlService.setHdmiCecVolumeControlEnabledInternal(
+ HdmiControlManager.VOLUME_CONTROL_DISABLED);
mHdmiCecLocalDeviceAudioSystem.setSystemAudioControlFeatureEnabled(true);
int volume = mHdmiControlService.getAudioManager()
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java
index 7aea4ffe1b03..bc808762b855 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java
@@ -862,7 +862,8 @@ public class HdmiCecLocalDevicePlaybackTest {
@Test
public void sendVolumeKeyEvent_up_volumeEnabled() {
- mHdmiControlService.setHdmiCecVolumeControlEnabled(true);
+ mHdmiControlService.setHdmiCecVolumeControlEnabledInternal(
+ HdmiControlManager.VOLUME_CONTROL_ENABLED);
mHdmiCecLocalDevicePlayback.sendVolumeKeyEvent(KeyEvent.KEYCODE_VOLUME_UP, true);
mHdmiCecLocalDevicePlayback.sendVolumeKeyEvent(KeyEvent.KEYCODE_VOLUME_UP, false);
mTestLooper.dispatchAll();
@@ -879,7 +880,8 @@ public class HdmiCecLocalDevicePlaybackTest {
@Test
public void sendVolumeKeyEvent_down_volumeEnabled() {
- mHdmiControlService.setHdmiCecVolumeControlEnabled(true);
+ mHdmiControlService.setHdmiCecVolumeControlEnabledInternal(
+ HdmiControlManager.VOLUME_CONTROL_ENABLED);
mHdmiCecLocalDevicePlayback.sendVolumeKeyEvent(KeyEvent.KEYCODE_VOLUME_DOWN, true);
mHdmiCecLocalDevicePlayback.sendVolumeKeyEvent(KeyEvent.KEYCODE_VOLUME_DOWN, false);
mTestLooper.dispatchAll();
@@ -896,7 +898,8 @@ public class HdmiCecLocalDevicePlaybackTest {
@Test
public void sendVolumeKeyEvent_mute_volumeEnabled() {
- mHdmiControlService.setHdmiCecVolumeControlEnabled(true);
+ mHdmiControlService.setHdmiCecVolumeControlEnabledInternal(
+ HdmiControlManager.VOLUME_CONTROL_ENABLED);
mHdmiCecLocalDevicePlayback.sendVolumeKeyEvent(KeyEvent.KEYCODE_VOLUME_MUTE, true);
mHdmiCecLocalDevicePlayback.sendVolumeKeyEvent(KeyEvent.KEYCODE_VOLUME_MUTE, false);
mTestLooper.dispatchAll();
@@ -913,7 +916,8 @@ public class HdmiCecLocalDevicePlaybackTest {
@Test
public void sendVolumeKeyEvent_up_volumeDisabled() {
- mHdmiControlService.setHdmiCecVolumeControlEnabled(false);
+ mHdmiControlService.setHdmiCecVolumeControlEnabledInternal(
+ HdmiControlManager.VOLUME_CONTROL_DISABLED);
mHdmiCecLocalDevicePlayback.sendVolumeKeyEvent(KeyEvent.KEYCODE_VOLUME_UP, true);
mHdmiCecLocalDevicePlayback.sendVolumeKeyEvent(KeyEvent.KEYCODE_VOLUME_UP, false);
mTestLooper.dispatchAll();
@@ -930,7 +934,8 @@ public class HdmiCecLocalDevicePlaybackTest {
@Test
public void sendVolumeKeyEvent_down_volumeDisabled() {
- mHdmiControlService.setHdmiCecVolumeControlEnabled(false);
+ mHdmiControlService.setHdmiCecVolumeControlEnabledInternal(
+ HdmiControlManager.VOLUME_CONTROL_DISABLED);
mHdmiCecLocalDevicePlayback.sendVolumeKeyEvent(KeyEvent.KEYCODE_VOLUME_DOWN, true);
mHdmiCecLocalDevicePlayback.sendVolumeKeyEvent(KeyEvent.KEYCODE_VOLUME_DOWN, false);
mTestLooper.dispatchAll();
@@ -947,7 +952,8 @@ public class HdmiCecLocalDevicePlaybackTest {
@Test
public void sendVolumeKeyEvent_mute_volumeDisabled() {
- mHdmiControlService.setHdmiCecVolumeControlEnabled(false);
+ mHdmiControlService.setHdmiCecVolumeControlEnabledInternal(
+ HdmiControlManager.VOLUME_CONTROL_DISABLED);
mHdmiCecLocalDevicePlayback.sendVolumeKeyEvent(KeyEvent.KEYCODE_VOLUME_MUTE, true);
mHdmiCecLocalDevicePlayback.sendVolumeKeyEvent(KeyEvent.KEYCODE_VOLUME_MUTE, false);
mTestLooper.dispatchAll();
@@ -964,7 +970,8 @@ public class HdmiCecLocalDevicePlaybackTest {
@Test
public void sendVolumeKeyEvent_toTv_activeSource() {
- mHdmiControlService.setHdmiCecVolumeControlEnabled(true);
+ mHdmiControlService.setHdmiCecVolumeControlEnabledInternal(
+ HdmiControlManager.VOLUME_CONTROL_ENABLED);
mHdmiControlService.setSystemAudioActivated(false);
mHdmiControlService.setActiveSource(mPlaybackLogicalAddress, mPlaybackPhysicalAddress,
"HdmiCecLocalDevicePlaybackTest");
@@ -984,7 +991,8 @@ public class HdmiCecLocalDevicePlaybackTest {
@Test
public void sendVolumeKeyEvent_toAudio_activeSource() {
- mHdmiControlService.setHdmiCecVolumeControlEnabled(true);
+ mHdmiControlService.setHdmiCecVolumeControlEnabledInternal(
+ HdmiControlManager.VOLUME_CONTROL_ENABLED);
mHdmiControlService.setSystemAudioActivated(true);
mHdmiControlService.setActiveSource(mPlaybackLogicalAddress, mPlaybackPhysicalAddress,
"HdmiCecLocalDevicePlaybackTest");
@@ -1004,7 +1012,8 @@ public class HdmiCecLocalDevicePlaybackTest {
@Test
public void sendVolumeKeyEvent_toTv_inactiveSource() {
- mHdmiControlService.setHdmiCecVolumeControlEnabled(true);
+ mHdmiControlService.setHdmiCecVolumeControlEnabledInternal(
+ HdmiControlManager.VOLUME_CONTROL_ENABLED);
mHdmiControlService.setSystemAudioActivated(false);
mHdmiControlService.setActiveSource(ADDR_TV, 0x0000, "HdmiCecLocalDevicePlaybackTest");
@@ -1023,7 +1032,8 @@ public class HdmiCecLocalDevicePlaybackTest {
@Test
public void sendVolumeKeyEvent_toAudio_inactiveSource() {
- mHdmiControlService.setHdmiCecVolumeControlEnabled(true);
+ mHdmiControlService.setHdmiCecVolumeControlEnabledInternal(
+ HdmiControlManager.VOLUME_CONTROL_ENABLED);
mHdmiControlService.setSystemAudioActivated(true);
mHdmiControlService.setActiveSource(ADDR_TV, 0x0000, "HdmiCecLocalDevicePlaybackTest");
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTest.java
index eb2f9608f6f3..0717112da12c 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTest.java
@@ -32,6 +32,7 @@ import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
+import android.content.Context;
import android.hardware.hdmi.HdmiControlManager;
import android.hardware.hdmi.HdmiPortInfo;
import android.os.test.TestLooper;
@@ -124,8 +125,13 @@ public class HdmiCecLocalDeviceTest {
@Before
public void SetUp() {
+
+ Context context = InstrumentationRegistry.getTargetContext();
+
+ HdmiCecConfig hdmiCecConfig = new FakeHdmiCecConfig(context);
+
mHdmiControlService =
- new HdmiControlService(InstrumentationRegistry.getTargetContext()) {
+ new HdmiControlService(context) {
@Override
boolean isControlEnabled() {
return isControlEnabled;
@@ -157,6 +163,11 @@ public class HdmiCecLocalDeviceTest {
void wakeUp() {
mWakeupMessageReceived = true;
}
+
+ @Override
+ protected HdmiCecConfig getHdmiCecConfig() {
+ return hdmiCecConfig;
+ }
};
mHdmiControlService.setIoLooper(mTestLooper.getLooper());
mNativeWrapper = new FakeNativeWrapper();
@@ -244,7 +255,8 @@ public class HdmiCecLocalDeviceTest {
@Test
public void handleUserControlPressed_volumeUp() {
- mHdmiControlService.setHdmiCecVolumeControlEnabled(true);
+ mHdmiControlService.setHdmiCecVolumeControlEnabledInternal(
+ HdmiControlManager.VOLUME_CONTROL_ENABLED);
boolean result = mHdmiLocalDevice.handleUserControlPressed(
HdmiCecMessageBuilder.buildUserControlPressed(ADDR_PLAYBACK_1, ADDR_TV,
HdmiCecKeycode.CEC_KEYCODE_VOLUME_UP));
@@ -254,7 +266,8 @@ public class HdmiCecLocalDeviceTest {
@Test
public void handleUserControlPressed_volumeDown() {
- mHdmiControlService.setHdmiCecVolumeControlEnabled(true);
+ mHdmiControlService.setHdmiCecVolumeControlEnabledInternal(
+ HdmiControlManager.VOLUME_CONTROL_ENABLED);
boolean result = mHdmiLocalDevice.handleUserControlPressed(
HdmiCecMessageBuilder.buildUserControlPressed(ADDR_PLAYBACK_1, ADDR_TV,
HdmiCecKeycode.CEC_KEYCODE_VOLUME_DOWN));
@@ -264,7 +277,8 @@ public class HdmiCecLocalDeviceTest {
@Test
public void handleUserControlPressed_volumeMute() {
- mHdmiControlService.setHdmiCecVolumeControlEnabled(true);
+ mHdmiControlService.setHdmiCecVolumeControlEnabledInternal(
+ HdmiControlManager.VOLUME_CONTROL_ENABLED);
boolean result = mHdmiLocalDevice.handleUserControlPressed(
HdmiCecMessageBuilder.buildUserControlPressed(ADDR_PLAYBACK_1, ADDR_TV,
HdmiCecKeycode.CEC_KEYCODE_MUTE));
@@ -274,7 +288,8 @@ public class HdmiCecLocalDeviceTest {
@Test
public void handleUserControlPressed_volumeUp_disabled() {
- mHdmiControlService.setHdmiCecVolumeControlEnabled(false);
+ mHdmiControlService.setHdmiCecVolumeControlEnabledInternal(
+ HdmiControlManager.VOLUME_CONTROL_DISABLED);
boolean result = mHdmiLocalDevice.handleUserControlPressed(
HdmiCecMessageBuilder.buildUserControlPressed(ADDR_PLAYBACK_1, ADDR_TV,
HdmiCecKeycode.CEC_KEYCODE_VOLUME_UP));
@@ -284,7 +299,8 @@ public class HdmiCecLocalDeviceTest {
@Test
public void handleUserControlPressed_volumeDown_disabled() {
- mHdmiControlService.setHdmiCecVolumeControlEnabled(false);
+ mHdmiControlService.setHdmiCecVolumeControlEnabledInternal(
+ HdmiControlManager.VOLUME_CONTROL_DISABLED);
boolean result = mHdmiLocalDevice.handleUserControlPressed(
HdmiCecMessageBuilder.buildUserControlPressed(ADDR_PLAYBACK_1, ADDR_TV,
HdmiCecKeycode.CEC_KEYCODE_VOLUME_DOWN));
@@ -294,7 +310,8 @@ public class HdmiCecLocalDeviceTest {
@Test
public void handleUserControlPressed_volumeMute_disabled() {
- mHdmiControlService.setHdmiCecVolumeControlEnabled(false);
+ mHdmiControlService.setHdmiCecVolumeControlEnabledInternal(
+ HdmiControlManager.VOLUME_CONTROL_DISABLED);
boolean result = mHdmiLocalDevice.handleUserControlPressed(
HdmiCecMessageBuilder.buildUserControlPressed(ADDR_PLAYBACK_1, ADDR_TV,
HdmiCecKeycode.CEC_KEYCODE_MUTE));
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceBinderAPITest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceBinderAPITest.java
index c212bf868c76..70718f765412 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceBinderAPITest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceBinderAPITest.java
@@ -136,6 +136,8 @@ public class HdmiControlServiceBinderAPITest {
// Some tests expect no logical addresses being allocated at the beginning of the test.
setHdmiControlEnabled(false);
+ HdmiCecConfig hdmiCecConfig = new FakeHdmiCecConfig(mContext);
+
mHdmiControlService =
new HdmiControlService(mContext) {
@Override
@@ -158,6 +160,11 @@ public class HdmiControlServiceBinderAPITest {
boolean isPowerStandby() {
return mPowerStatus == HdmiControlManager.POWER_STATUS_STANDBY;
}
+
+ @Override
+ protected HdmiCecConfig getHdmiCecConfig() {
+ return hdmiCecConfig;
+ }
};
mMyLooper = mTestLooper.getLooper();
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java
index 9152e1e84b71..dbb03cb6dbdc 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java
@@ -291,136 +291,175 @@ public class HdmiControlServiceTest {
@Test
public void setAndGetCecVolumeControlEnabled_isApi() {
- mHdmiControlService.setHdmiCecVolumeControlEnabled(false);
- assertThat(mHdmiControlService.isHdmiCecVolumeControlEnabled()).isFalse();
+ mHdmiControlService.getHdmiCecConfig().setIntValue(
+ HdmiControlManager.CEC_SETTING_NAME_VOLUME_CONTROL_MODE,
+ HdmiControlManager.VOLUME_CONTROL_DISABLED);
+ assertThat(mHdmiControlService.getHdmiCecConfig().getIntValue(
+ HdmiControlManager.CEC_SETTING_NAME_VOLUME_CONTROL_MODE)).isEqualTo(
+ HdmiControlManager.VOLUME_CONTROL_DISABLED);
- mHdmiControlService.setHdmiCecVolumeControlEnabled(true);
- assertThat(mHdmiControlService.isHdmiCecVolumeControlEnabled()).isTrue();
+ mHdmiControlService.getHdmiCecConfig().setIntValue(
+ HdmiControlManager.CEC_SETTING_NAME_VOLUME_CONTROL_MODE,
+ HdmiControlManager.VOLUME_CONTROL_ENABLED);
+ assertThat(mHdmiControlService.getHdmiCecConfig().getIntValue(
+ HdmiControlManager.CEC_SETTING_NAME_VOLUME_CONTROL_MODE)).isEqualTo(
+ HdmiControlManager.VOLUME_CONTROL_ENABLED);
}
@Test
public void setAndGetCecVolumeControlEnabled_changesSetting() {
- mHdmiControlService.setHdmiCecVolumeControlEnabled(false);
- assertThat(mHdmiControlService.readBooleanSetting(
- Settings.Global.HDMI_CONTROL_VOLUME_CONTROL_ENABLED, true)).isFalse();
+ mHdmiControlService.getHdmiCecConfig().setIntValue(
+ HdmiControlManager.CEC_SETTING_NAME_VOLUME_CONTROL_MODE,
+ HdmiControlManager.VOLUME_CONTROL_DISABLED);
+ assertThat(mHdmiControlService.readIntSetting(
+ Settings.Global.HDMI_CONTROL_VOLUME_CONTROL_ENABLED, -1)).isEqualTo(
+ HdmiControlManager.VOLUME_CONTROL_DISABLED);
- mHdmiControlService.setHdmiCecVolumeControlEnabled(true);
- assertThat(mHdmiControlService.readBooleanSetting(
- Settings.Global.HDMI_CONTROL_VOLUME_CONTROL_ENABLED, true)).isTrue();
+ mHdmiControlService.getHdmiCecConfig().setIntValue(
+ HdmiControlManager.CEC_SETTING_NAME_VOLUME_CONTROL_MODE,
+ HdmiControlManager.VOLUME_CONTROL_ENABLED);
+ assertThat(mHdmiControlService.readIntSetting(
+ Settings.Global.HDMI_CONTROL_VOLUME_CONTROL_ENABLED, -1)).isEqualTo(
+ HdmiControlManager.VOLUME_CONTROL_ENABLED);
}
@Test
public void setAndGetCecVolumeControlEnabledInternal_doesNotChangeSetting() {
- mHdmiControlService.setHdmiCecVolumeControlEnabledInternal(true);
-
- mHdmiControlService.setHdmiCecVolumeControlEnabledInternal(false);
- assertThat(mHdmiControlService.readBooleanSetting(
- Settings.Global.HDMI_CONTROL_VOLUME_CONTROL_ENABLED, true)).isTrue();
-
- mHdmiControlService.setHdmiCecVolumeControlEnabledInternal(true);
- assertThat(mHdmiControlService.readBooleanSetting(
- Settings.Global.HDMI_CONTROL_VOLUME_CONTROL_ENABLED, true)).isTrue();
+ mHdmiControlService.getHdmiCecConfig().setIntValue(
+ HdmiControlManager.CEC_SETTING_NAME_VOLUME_CONTROL_MODE,
+ HdmiControlManager.VOLUME_CONTROL_ENABLED);
+
+ mHdmiControlService.setHdmiCecVolumeControlEnabledInternal(
+ HdmiControlManager.VOLUME_CONTROL_DISABLED);
+ assertThat(mHdmiControlService.getHdmiCecConfig().getIntValue(
+ HdmiControlManager.CEC_SETTING_NAME_VOLUME_CONTROL_MODE)).isEqualTo(
+ HdmiControlManager.VOLUME_CONTROL_ENABLED);
+
+ mHdmiControlService.setHdmiCecVolumeControlEnabledInternal(
+ HdmiControlManager.VOLUME_CONTROL_ENABLED);
+ assertThat(mHdmiControlService.getHdmiCecConfig().getIntValue(
+ HdmiControlManager.CEC_SETTING_NAME_VOLUME_CONTROL_MODE)).isEqualTo(
+ HdmiControlManager.VOLUME_CONTROL_ENABLED);
}
@Test
public void disableAndReenableCec_volumeControlReturnsToOriginalValue_enabled() {
- boolean volumeControlEnabled = true;
- mHdmiControlService.setHdmiCecVolumeControlEnabled(volumeControlEnabled);
+ int volumeControlEnabled = HdmiControlManager.VOLUME_CONTROL_ENABLED;
+ mHdmiControlService.setHdmiCecVolumeControlEnabledInternal(volumeControlEnabled);
mHdmiControlService.setControlEnabled(false);
- assertThat(mHdmiControlService.isHdmiCecVolumeControlEnabled()).isFalse();
+ assertThat(mHdmiControlService.getHdmiCecVolumeControl()).isEqualTo(
+ HdmiControlManager.VOLUME_CONTROL_DISABLED);
mHdmiControlService.setControlEnabled(true);
- assertThat(mHdmiControlService.isHdmiCecVolumeControlEnabled()).isEqualTo(
- volumeControlEnabled);
+ assertThat(mHdmiControlService.getHdmiCecVolumeControl()).isEqualTo(volumeControlEnabled);
}
@Test
public void disableAndReenableCec_volumeControlReturnsToOriginalValue_disabled() {
- boolean volumeControlEnabled = false;
- mHdmiControlService.setHdmiCecVolumeControlEnabled(volumeControlEnabled);
+ int volumeControlEnabled = HdmiControlManager.VOLUME_CONTROL_DISABLED;
+ mHdmiControlService.getHdmiCecConfig().setIntValue(
+ HdmiControlManager.CEC_SETTING_NAME_VOLUME_CONTROL_MODE, volumeControlEnabled);
mHdmiControlService.setControlEnabled(false);
- assertThat(mHdmiControlService.isHdmiCecVolumeControlEnabled()).isFalse();
+ assertThat(mHdmiControlService.getHdmiCecConfig().getIntValue(
+ HdmiControlManager.CEC_SETTING_NAME_VOLUME_CONTROL_MODE)).isEqualTo(
+ volumeControlEnabled);
mHdmiControlService.setControlEnabled(true);
- assertThat(mHdmiControlService.isHdmiCecVolumeControlEnabled()).isEqualTo(
+ assertThat(mHdmiControlService.getHdmiCecConfig().getIntValue(
+ HdmiControlManager.CEC_SETTING_NAME_VOLUME_CONTROL_MODE)).isEqualTo(
volumeControlEnabled);
}
@Test
public void disableAndReenableCec_volumeControlFeatureListenersNotified() {
- mHdmiControlService.setHdmiCecVolumeControlEnabled(true);
+ mHdmiControlService.getHdmiCecConfig().setIntValue(
+ HdmiControlManager.CEC_SETTING_NAME_VOLUME_CONTROL_MODE,
+ HdmiControlManager.VOLUME_CONTROL_ENABLED);
VolumeControlFeatureCallback callback = new VolumeControlFeatureCallback();
mHdmiControlService.addHdmiCecVolumeControlFeatureListener(callback);
mHdmiControlService.setControlEnabled(false);
assertThat(callback.mCallbackReceived).isTrue();
- assertThat(callback.mVolumeControlEnabled).isFalse();
+ assertThat(callback.mVolumeControlEnabled).isEqualTo(
+ HdmiControlManager.VOLUME_CONTROL_DISABLED);
mHdmiControlService.setControlEnabled(true);
- assertThat(callback.mVolumeControlEnabled).isTrue();
+ assertThat(callback.mVolumeControlEnabled).isEqualTo(
+ HdmiControlManager.VOLUME_CONTROL_ENABLED);
}
@Test
public void addHdmiCecVolumeControlFeatureListener_emitsCurrentState_enabled() {
- mHdmiControlService.setHdmiCecVolumeControlEnabled(true);
+ mHdmiControlService.setHdmiCecVolumeControlEnabledInternal(
+ HdmiControlManager.VOLUME_CONTROL_ENABLED);
VolumeControlFeatureCallback callback = new VolumeControlFeatureCallback();
mHdmiControlService.addHdmiCecVolumeControlFeatureListener(callback);
mTestLooper.dispatchAll();
assertThat(callback.mCallbackReceived).isTrue();
- assertThat(callback.mVolumeControlEnabled).isTrue();
+ assertThat(callback.mVolumeControlEnabled).isEqualTo(
+ HdmiControlManager.VOLUME_CONTROL_ENABLED);
}
@Test
public void addHdmiCecVolumeControlFeatureListener_emitsCurrentState_disabled() {
- mHdmiControlService.setHdmiCecVolumeControlEnabled(false);
+ mHdmiControlService.setHdmiCecVolumeControlEnabledInternal(
+ HdmiControlManager.VOLUME_CONTROL_DISABLED);
VolumeControlFeatureCallback callback = new VolumeControlFeatureCallback();
mHdmiControlService.addHdmiCecVolumeControlFeatureListener(callback);
mTestLooper.dispatchAll();
assertThat(callback.mCallbackReceived).isTrue();
- assertThat(callback.mVolumeControlEnabled).isFalse();
+ assertThat(callback.mVolumeControlEnabled).isEqualTo(
+ HdmiControlManager.VOLUME_CONTROL_DISABLED);
}
@Test
public void addHdmiCecVolumeControlFeatureListener_notifiesStateUpdate() {
- mHdmiControlService.setHdmiCecVolumeControlEnabled(false);
+ mHdmiControlService.setHdmiCecVolumeControlEnabledInternal(
+ HdmiControlManager.VOLUME_CONTROL_DISABLED);
VolumeControlFeatureCallback callback = new VolumeControlFeatureCallback();
mHdmiControlService.addHdmiCecVolumeControlFeatureListener(callback);
- mHdmiControlService.setHdmiCecVolumeControlEnabled(true);
+ mHdmiControlService.setHdmiCecVolumeControlEnabledInternal(
+ HdmiControlManager.VOLUME_CONTROL_ENABLED);
mTestLooper.dispatchAll();
assertThat(callback.mCallbackReceived).isTrue();
- assertThat(callback.mVolumeControlEnabled).isTrue();
+ assertThat(callback.mVolumeControlEnabled).isEqualTo(
+ HdmiControlManager.VOLUME_CONTROL_ENABLED);
}
@Test
public void addHdmiCecVolumeControlFeatureListener_honorsUnregistration() {
- mHdmiControlService.setHdmiCecVolumeControlEnabled(false);
+ mHdmiControlService.setHdmiCecVolumeControlEnabledInternal(
+ HdmiControlManager.VOLUME_CONTROL_DISABLED);
VolumeControlFeatureCallback callback = new VolumeControlFeatureCallback();
mHdmiControlService.addHdmiCecVolumeControlFeatureListener(callback);
mTestLooper.dispatchAll();
mHdmiControlService.removeHdmiControlVolumeControlStatusChangeListener(callback);
- mHdmiControlService.setHdmiCecVolumeControlEnabled(true);
+ mHdmiControlService.setHdmiCecVolumeControlEnabledInternal(
+ HdmiControlManager.VOLUME_CONTROL_ENABLED);
mTestLooper.dispatchAll();
assertThat(callback.mCallbackReceived).isTrue();
- assertThat(callback.mVolumeControlEnabled).isFalse();
+ assertThat(callback.mVolumeControlEnabled).isEqualTo(
+ HdmiControlManager.VOLUME_CONTROL_DISABLED);
}
@Test
public void addHdmiCecVolumeControlFeatureListener_notifiesStateUpdate_multiple() {
- mHdmiControlService.setHdmiCecVolumeControlEnabled(false);
+ mHdmiControlService.setHdmiCecVolumeControlEnabledInternal(
+ HdmiControlManager.VOLUME_CONTROL_DISABLED);
VolumeControlFeatureCallback callback1 = new VolumeControlFeatureCallback();
VolumeControlFeatureCallback callback2 = new VolumeControlFeatureCallback();
@@ -428,13 +467,16 @@ public class HdmiControlServiceTest {
mHdmiControlService.addHdmiCecVolumeControlFeatureListener(callback2);
- mHdmiControlService.setHdmiCecVolumeControlEnabled(true);
+ mHdmiControlService.setHdmiCecVolumeControlEnabledInternal(
+ HdmiControlManager.VOLUME_CONTROL_ENABLED);
mTestLooper.dispatchAll();
assertThat(callback1.mCallbackReceived).isTrue();
assertThat(callback2.mCallbackReceived).isTrue();
- assertThat(callback1.mVolumeControlEnabled).isTrue();
- assertThat(callback2.mVolumeControlEnabled).isTrue();
+ assertThat(callback1.mVolumeControlEnabled).isEqualTo(
+ HdmiControlManager.VOLUME_CONTROL_ENABLED);
+ assertThat(callback2.mVolumeControlEnabled).isEqualTo(
+ HdmiControlManager.VOLUME_CONTROL_ENABLED);
}
@Test
@@ -579,10 +621,10 @@ public class HdmiControlServiceTest {
private static class VolumeControlFeatureCallback extends
IHdmiCecVolumeControlFeatureListener.Stub {
boolean mCallbackReceived = false;
- boolean mVolumeControlEnabled = false;
+ int mVolumeControlEnabled = -1;
@Override
- public void onHdmiCecVolumeControlFeature(boolean enabled) throws RemoteException {
+ public void onHdmiCecVolumeControlFeature(int enabled) throws RemoteException {
this.mCallbackReceived = true;
this.mVolumeControlEnabled = enabled;
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index 6f584ee9a18c..ef96a2d5960a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -1064,6 +1064,21 @@ public class ActivityRecordTests extends WindowTestsBase {
}
/**
+ * Verify that finish bottom activity from a task won't boost it to top.
+ */
+ @Test
+ public void testFinishBottomActivityIfPossible_noZBoost() {
+ final ActivityRecord bottomActivity = createActivityWithTask();
+ final ActivityRecord topActivity = new ActivityBuilder(mAtm)
+ .setTask(bottomActivity.getTask()).build();
+ topActivity.mVisibleRequested = true;
+ // simulating bottomActivity as a trampoline activity.
+ bottomActivity.setState(RESUMED, "test");
+ bottomActivity.finishIfPossible("test", false);
+ assertFalse(bottomActivity.mNeedsZBoost);
+ }
+
+ /**
* Verify that complete finish request for visible activity must be delayed before the next one
* becomes visible.
*/