summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/audio/AudioService.java58
-rw-r--r--services/core/java/com/android/server/audio/AudioServiceEvents.java19
-rw-r--r--services/core/java/com/android/server/audio/AudioSystemAdapter.java9
-rw-r--r--services/core/java/com/android/server/audio/SystemServerAdapter.java14
-rw-r--r--services/tests/servicestests/src/com/android/server/audio/AudioServiceTest.java40
-rw-r--r--services/tests/servicestests/src/com/android/server/audio/NoOpAudioSystemAdapter.java5
-rw-r--r--services/tests/servicestests/src/com/android/server/audio/NoOpSystemServerAdapter.java5
7 files changed, 116 insertions, 34 deletions
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 71424b14373b..aa9cb1e99ac8 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -393,6 +393,7 @@ public class AudioService extends IAudioService.Stub
private static final int MSG_DISPATCH_PREFERRED_MIXER_ATTRIBUTES = 52;
private static final int MSG_LOWER_VOLUME_TO_RS1 = 53;
private static final int MSG_CONFIGURATION_CHANGED = 54;
+ private static final int MSG_BROADCAST_MASTER_MUTE = 55;
/** Messages handled by the {@link SoundDoseHelper}. */
/*package*/ static final int SAFE_MEDIA_VOLUME_MSG_START = 1000;
@@ -975,6 +976,9 @@ public class AudioService extends IAudioService.Stub
@GuardedBy("mSettingsLock")
private boolean mRttEnabled = false;
+ private AtomicBoolean mMasterMute = new AtomicBoolean(false);
+
+
///////////////////////////////////////////////////////////////////////////
// Construction
///////////////////////////////////////////////////////////////////////////
@@ -2738,21 +2742,18 @@ public class AudioService extends IAudioService.Stub
}
final int currentUser = getCurrentUserId();
+ if (mUseFixedVolume) {
+ AudioSystem.setMasterVolume(1.0f);
+ }
+
// Check the current user restriction.
boolean masterMute =
mUserManagerInternal.getUserRestriction(currentUser,
UserManager.DISALLOW_UNMUTE_DEVICE)
|| mUserManagerInternal.getUserRestriction(currentUser,
UserManager.DISALLOW_ADJUST_VOLUME);
- if (mUseFixedVolume) {
- masterMute = false;
- AudioSystem.setMasterVolume(1.0f);
- }
- if (DEBUG_VOL) {
- Log.d(TAG, String.format("Master mute %s, user=%d", masterMute, currentUser));
- }
- AudioSystem.setMasterMute(masterMute);
- broadcastMasterMuteStatus(masterMute);
+ setMasterMuteInternalNoCallerCheck(
+ masterMute, /* flags =*/ 0, currentUser, "readUserRestrictions");
mMicMuteFromRestrictions = mUserManagerInternal.getUserRestriction(
currentUser, UserManager.DISALLOW_UNMUTE_MICROPHONE);
@@ -4768,16 +4769,10 @@ public class AudioService extends IAudioService.Stub
// UI update and Broadcast Intent
private void sendMasterMuteUpdate(boolean muted, int flags) {
mVolumeController.postMasterMuteChanged(updateFlagsForTvPlatform(flags));
- broadcastMasterMuteStatus(muted);
+ sendMsg(mAudioHandler, MSG_BROADCAST_MASTER_MUTE,
+ SENDMSG_QUEUE, muted ? 1 : 0, 0, null, 0);
}
- private void broadcastMasterMuteStatus(boolean muted) {
- Intent intent = new Intent(AudioManager.MASTER_MUTE_CHANGED_ACTION);
- intent.putExtra(AudioManager.EXTRA_MASTER_VOLUME_MUTED, muted);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
- | Intent.FLAG_RECEIVER_REPLACE_PENDING);
- sendStickyBroadcastToAll(intent);
- }
/**
* Sets the stream state's index, and posts a message to set system volume.
@@ -4944,18 +4939,21 @@ public class AudioService extends IAudioService.Stub
!= PackageManager.PERMISSION_GRANTED) {
return;
}
- setMasterMuteInternalNoCallerCheck(mute, flags, userId);
+ setMasterMuteInternalNoCallerCheck(mute, flags, userId, "setMasterMute");
}
- private void setMasterMuteInternalNoCallerCheck(boolean mute, int flags, int userId) {
+ private void setMasterMuteInternalNoCallerCheck(
+ boolean mute, int flags, int userId, String eventSource) {
if (DEBUG_VOL) {
- Log.d(TAG, String.format("Master mute %s, %d, user=%d", mute, flags, userId));
+ Log.d(TAG, TextUtils.formatSimple("Master mute %s, %d, user=%d from %s",
+ mute, flags, userId, eventSource));
}
+
if (!isPlatformAutomotive() && mUseFixedVolume) {
// If using fixed volume, we don't mute.
// TODO: remove the isPlatformAutomotive check here.
// The isPlatformAutomotive check is added for safety but may not be necessary.
- return;
+ mute = false;
}
// For automotive,
// - the car service is always running as system user
@@ -4964,8 +4962,10 @@ public class AudioService extends IAudioService.Stub
// Therefore, the getCurrentUser() is always different to the foreground user.
if ((isPlatformAutomotive() && userId == UserHandle.USER_SYSTEM)
|| (getCurrentUserId() == userId)) {
- if (mute != AudioSystem.getMasterMute()) {
- AudioSystem.setMasterMute(mute);
+ if (mute != mMasterMute.getAndSet(mute)) {
+ sVolumeLogger.enqueue(new VolumeEvent(
+ VolumeEvent.VOL_MASTER_MUTE, mute));
+ mAudioSystem.setMasterMute(mute);
sendMasterMuteUpdate(mute, flags);
}
}
@@ -4973,7 +4973,7 @@ public class AudioService extends IAudioService.Stub
/** get global mute state. */
public boolean isMasterMute() {
- return AudioSystem.getMasterMute();
+ return mMasterMute.get();
}
@android.annotation.EnforcePermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
@@ -9278,6 +9278,10 @@ public class AudioService extends IAudioService.Stub
mSystemServer.sendMicrophoneMuteChangedIntent();
break;
+ case MSG_BROADCAST_MASTER_MUTE:
+ mSystemServer.broadcastMasterMuteStatus(msg.arg1 == 1);
+ break;
+
case MSG_CHECK_MODE_FOR_UID:
synchronized (mDeviceBroker.mSetModeLock) {
if (msg.obj == null) {
@@ -9675,7 +9679,8 @@ public class AudioService extends IAudioService.Stub
newRestrictions.getBoolean(UserManager.DISALLOW_ADJUST_VOLUME)
|| newRestrictions.getBoolean(UserManager.DISALLOW_UNMUTE_DEVICE);
if (wasRestricted != isRestricted) {
- setMasterMuteInternalNoCallerCheck(isRestricted, /* flags =*/ 0, userId);
+ setMasterMuteInternalNoCallerCheck(
+ isRestricted, /* flags =*/ 0, userId, "onUserRestrictionsChanged");
}
}
}
@@ -11033,10 +11038,11 @@ public class AudioService extends IAudioService.Stub
pw.print(" mHdmiCecVolumeControlEnabled="); pw.println(mHdmiCecVolumeControlEnabled);
}
pw.print(" mIsCallScreeningModeSupported="); pw.println(mIsCallScreeningModeSupported);
- pw.print(" mic mute FromSwitch=" + mMicMuteFromSwitch
+ pw.println(" mic mute FromSwitch=" + mMicMuteFromSwitch
+ " FromRestrictions=" + mMicMuteFromRestrictions
+ " FromApi=" + mMicMuteFromApi
+ " from system=" + mMicMuteFromSystemCached);
+ pw.print(" mMasterMute="); pw.println(mMasterMute.get());
dumpAccessibilityServiceUids(pw);
dumpAssistantServicesUids(pw);
diff --git a/services/core/java/com/android/server/audio/AudioServiceEvents.java b/services/core/java/com/android/server/audio/AudioServiceEvents.java
index 6ebb42e08ade..aac868f45fe3 100644
--- a/services/core/java/com/android/server/audio/AudioServiceEvents.java
+++ b/services/core/java/com/android/server/audio/AudioServiceEvents.java
@@ -228,6 +228,7 @@ public class AudioServiceEvents {
static final int VOL_MUTE_STREAM_INT = 9;
static final int VOL_SET_LE_AUDIO_VOL = 10;
static final int VOL_ADJUST_GROUP_VOL = 11;
+ static final int VOL_MASTER_MUTE = 12;
final int mOp;
final int mStream;
@@ -321,6 +322,17 @@ public class AudioServiceEvents {
logMetricEvent();
}
+ /** used for VOL_MASTER_MUTE */
+ VolumeEvent(int op, boolean state) {
+ mOp = op;
+ mStream = -1;
+ mVal1 = state ? 1 : 0;
+ mVal2 = 0;
+ mCaller = null;
+ mGroupName = null;
+ logMetricEvent();
+ }
+
/**
* Audio Analytics unique Id.
@@ -429,6 +441,9 @@ public class AudioServiceEvents {
case VOL_MUTE_STREAM_INT:
// No value in logging metrics for this internal event
return;
+ case VOL_MASTER_MUTE:
+ // No value in logging metrics for this internal event
+ return;
default:
return;
}
@@ -510,6 +525,10 @@ public class AudioServiceEvents {
.append(AudioSystem.streamToString(mStream))
.append(mVal1 == 1 ? ", muted)" : ", unmuted)")
.toString();
+ case VOL_MASTER_MUTE:
+ return new StringBuilder("Master mute:")
+ .append(mVal1 == 1 ? " muted)" : " unmuted)")
+ .toString();
default: return new StringBuilder("FIXME invalid op:").append(mOp).toString();
}
}
diff --git a/services/core/java/com/android/server/audio/AudioSystemAdapter.java b/services/core/java/com/android/server/audio/AudioSystemAdapter.java
index 43438942a060..e70b6497538e 100644
--- a/services/core/java/com/android/server/audio/AudioSystemAdapter.java
+++ b/services/core/java/com/android/server/audio/AudioSystemAdapter.java
@@ -685,6 +685,15 @@ public class AudioSystemAdapter implements AudioSystem.RoutingUpdateCallback,
}
/**
+ * Sets master mute state in audio flinger
+ * @param mute the mute state to set
+ * @return operation status
+ */
+ public int setMasterMute(boolean mute) {
+ return AudioSystem.setMasterMute(mute);
+ }
+
+ /**
* Part of AudioService dump
* @param pw
*/
diff --git a/services/core/java/com/android/server/audio/SystemServerAdapter.java b/services/core/java/com/android/server/audio/SystemServerAdapter.java
index 22456bcf3f66..dfcd2e9a8a39 100644
--- a/services/core/java/com/android/server/audio/SystemServerAdapter.java
+++ b/services/core/java/com/android/server/audio/SystemServerAdapter.java
@@ -145,4 +145,18 @@ public class SystemServerAdapter {
ActivityManager.broadcastStickyIntent(intent, profileId);
}
}
+
+ /*package*/ void broadcastMasterMuteStatus(boolean muted) {
+ Intent intent = new Intent(AudioManager.MASTER_MUTE_CHANGED_ACTION);
+ intent.putExtra(AudioManager.EXTRA_MASTER_VOLUME_MUTED, muted);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
+ | Intent.FLAG_RECEIVER_REPLACE_PENDING
+ | Intent.FLAG_RECEIVER_FOREGROUND);
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/audio/AudioServiceTest.java b/services/tests/servicestests/src/com/android/server/audio/AudioServiceTest.java
index 88d57ac1ab88..e565faa1c00b 100644
--- a/services/tests/servicestests/src/com/android/server/audio/AudioServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/audio/AudioServiceTest.java
@@ -18,7 +18,7 @@ package com.android.server.audio;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.after;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
@@ -42,10 +42,10 @@ import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.mockito.junit.MockitoJUnit;
-import org.mockito.junit.MockitoRule;
import org.mockito.Mock;
import org.mockito.Spy;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
@MediumTest
@RunWith(AndroidJUnit4.class)
@@ -58,7 +58,7 @@ public class AudioServiceTest {
public final MockitoRule mockito = MockitoJUnit.rule();
private Context mContext;
- private AudioSystemAdapter mAudioSystem;
+ private AudioSystemAdapter mSpyAudioSystem;
private SettingsAdapter mSettingsAdapter;
@Spy private NoOpSystemServerAdapter mSpySystemServer;
@@ -78,11 +78,11 @@ public class AudioServiceTest {
sLooperPrepared = true;
}
mContext = InstrumentationRegistry.getTargetContext();
- mAudioSystem = new NoOpAudioSystemAdapter();
+ mSpyAudioSystem = spy(new NoOpAudioSystemAdapter());
mSettingsAdapter = new NoOpSettingsAdapter();
when(mMockAppOpsManager.noteOp(anyInt(), anyInt(), anyString(), anyString(), anyString()))
.thenReturn(AppOpsManager.MODE_ALLOWED);
- mAudioService = new AudioService(mContext, mAudioSystem, mSpySystemServer,
+ mAudioService = new AudioService(mContext, mSpyAudioSystem, mSpySystemServer,
mSettingsAdapter, mMockAudioPolicy, null, mMockAppOpsManager,
mMockPermissionEnforcer);
}
@@ -95,7 +95,7 @@ public class AudioServiceTest {
public void testMuteMicrophone() throws Exception {
Log.i(TAG, "running testMuteMicrophone");
Assert.assertNotNull(mAudioService);
- final NoOpAudioSystemAdapter testAudioSystem = (NoOpAudioSystemAdapter) mAudioSystem;
+ final NoOpAudioSystemAdapter testAudioSystem = (NoOpAudioSystemAdapter) mSpyAudioSystem;
testAudioSystem.configureMuteMicrophoneToFail(false);
for (boolean muted : new boolean[] { true, false}) {
testAudioSystem.configureIsMicrophoneMuted(!muted);
@@ -120,7 +120,7 @@ public class AudioServiceTest {
public void testMuteMicrophoneWhenFail() throws Exception {
Log.i(TAG, "running testMuteMicrophoneWhenFail");
Assert.assertNotNull(mAudioService);
- final NoOpAudioSystemAdapter testAudioSystem = (NoOpAudioSystemAdapter) mAudioSystem;
+ final NoOpAudioSystemAdapter testAudioSystem = (NoOpAudioSystemAdapter) mSpyAudioSystem;
testAudioSystem.configureMuteMicrophoneToFail(true);
for (boolean muted : new boolean[] { true, false}) {
testAudioSystem.configureIsMicrophoneMuted(!muted);
@@ -175,4 +175,28 @@ public class AudioServiceTest {
Assert.assertEquals(false, mAudioService.isHotwordStreamSupported(false));
Assert.assertEquals(false, mAudioService.isHotwordStreamSupported(true));
}
+
+ /**
+ * Test master mute setter and getter
+ */
+ @Test
+ public void testMasterMute() throws Exception {
+ Log.i(TAG, "running testMasterMute");
+ Assert.assertNotNull(mAudioService);
+ for (boolean mute : new boolean[] { true, false}) {
+ boolean wasMute = mAudioService.isMasterMute();
+ mAudioService.setMasterMute(mute, 0 /* flags */, mContext.getOpPackageName(),
+ UserHandle.getCallingUserId(), null);
+
+ Assert.assertEquals("master mute reporting wrong value",
+ mute, mAudioService.isMasterMute());
+
+ verify(mSpyAudioSystem, times(wasMute == mute ? 0 : 1)).setMasterMute(mute);
+ // verify the intent for master mute changed is supposed to be fired
+ verify(mSpySystemServer,
+ after(MAX_MESSAGE_HANDLING_DELAY_MS).times(wasMute == mute ? 0 : 1))
+ .broadcastMasterMuteStatus(mute);
+ reset(mSpySystemServer);
+ }
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/audio/NoOpAudioSystemAdapter.java b/services/tests/servicestests/src/com/android/server/audio/NoOpAudioSystemAdapter.java
index 08a0878e6e7c..0eac718c2f14 100644
--- a/services/tests/servicestests/src/com/android/server/audio/NoOpAudioSystemAdapter.java
+++ b/services/tests/servicestests/src/com/android/server/audio/NoOpAudioSystemAdapter.java
@@ -142,4 +142,9 @@ public class NoOpAudioSystemAdapter extends AudioSystemAdapter {
@NonNull AudioAttributes attributes, boolean forVolume) {
return new ArrayList<>();
}
+
+ @Override
+ public int setMasterMute(boolean muted) {
+ return AudioSystem.AUDIO_STATUS_OK;
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/audio/NoOpSystemServerAdapter.java b/services/tests/servicestests/src/com/android/server/audio/NoOpSystemServerAdapter.java
index 83c566376e44..a715f519e667 100644
--- a/services/tests/servicestests/src/com/android/server/audio/NoOpSystemServerAdapter.java
+++ b/services/tests/servicestests/src/com/android/server/audio/NoOpSystemServerAdapter.java
@@ -39,4 +39,9 @@ public class NoOpSystemServerAdapter extends SystemServerAdapter {
public void sendDeviceBecomingNoisyIntent() {
// no-op
}
+
+ @Override
+ public void broadcastMasterMuteStatus(boolean muted) {
+ // no-op
+ }
}