Merge changes If9068025,I728e5bf9,I9d41169d am: 3b6a00ec3c am: 225b9d90c2
am: 3aadf0a4d9
Change-Id: I739f574365d36af6b37d47f5593b9ca14f26ef47
diff --git a/core/java/android/hardware/input/IInputManager.aidl b/core/java/android/hardware/input/IInputManager.aidl
index 0daf30f25..638d81b 100644
--- a/core/java/android/hardware/input/IInputManager.aidl
+++ b/core/java/android/hardware/input/IInputManager.aidl
@@ -76,6 +76,9 @@
// Registers a tablet mode change listener
void registerTabletModeChangedListener(ITabletModeChangedListener listener);
+ // Queries whether the device's microphone is muted by switch
+ int isMicMuted();
+
// Input device vibrator control.
void vibrate(int deviceId, in long[] pattern, int repeat, IBinder token);
void cancelVibrate(int deviceId, IBinder token);
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
index 2a59be2..0c0f248 100644
--- a/core/java/android/hardware/input/InputManager.java
+++ b/core/java/android/hardware/input/InputManager.java
@@ -520,6 +520,22 @@
}
/**
+ * Queries whether the device's microphone is muted
+ *
+ * @return The mic mute switch state which is one of {@link #SWITCH_STATE_UNKNOWN},
+ * {@link #SWITCH_STATE_OFF} or {@link #SWITCH_STATE_ON}.
+ * @hide
+ */
+ @SwitchState
+ public int isMicMuted() {
+ try {
+ return mIm.isMicMuted();
+ } catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Gets information about all supported keyboard layouts.
* <p>
* The input manager consults the built-in keyboard layouts as well
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 2d6cd24..f797da7 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -1857,12 +1857,37 @@
}
/**
+ * @hide
+ * Sets the microphone from switch mute on or off.
+ * <p>
+ * This method should only be used by InputManager to notify
+ * Audio Subsystem about Microphone Mute switch state.
+ *
+ * @param on set <var>true</var> to mute the microphone;
+ * <var>false</var> to turn mute off
+ */
+ @UnsupportedAppUsage
+ public void setMicrophoneMuteFromSwitch(boolean on) {
+ final IAudioService service = getService();
+ try {
+ service.setMicrophoneMuteFromSwitch(on);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Checks whether the microphone mute is on or off.
*
* @return true if microphone is muted, false if it's not
*/
public boolean isMicrophoneMute() {
- return AudioSystem.isMicrophoneMuted();
+ final IAudioService service = getService();
+ try {
+ return service.isMicrophoneMuted();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
}
/**
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index 71f52a1..fc05610 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -106,8 +106,12 @@
List<AudioProductStrategy> getAudioProductStrategies();
+ boolean isMicrophoneMuted();
+
void setMicrophoneMute(boolean on, String callingPackage, int userId);
+ oneway void setMicrophoneMuteFromSwitch(boolean on);
+
void setRingerModeExternal(int ringerMode, String caller);
void setRingerModeInternal(int ringerMode, String caller);
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 77b3fee..7f7ef17 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -59,6 +59,7 @@
import android.hardware.hdmi.HdmiControlManager;
import android.hardware.hdmi.HdmiPlaybackClient;
import android.hardware.hdmi.HdmiTvClient;
+import android.hardware.input.InputManager;
import android.hardware.usb.UsbManager;
import android.media.AudioAttributes;
import android.media.AudioFocusInfo;
@@ -545,6 +546,10 @@
private String mEnabledSurroundFormats;
private boolean mSurroundModeChanged;
+ private boolean mMicMuteFromSwitch;
+ private boolean mMicMuteFromApi;
+ private boolean mMicMuteFromRestrictions;
+
@GuardedBy("mSettingsLock")
private int mAssistantUid;
@@ -882,6 +887,8 @@
mRoleObserver.register();
onIndicateSystemReady();
+
+ setMicMuteFromSwitchInput();
}
RoleObserver mRoleObserver;
@@ -1021,6 +1028,8 @@
sendMsg(mAudioHandler, MSG_DISPATCH_AUDIO_SERVER_STATE,
SENDMSG_QUEUE, 1, 0, null, 0);
+
+ setMicMuteFromSwitchInput();
}
private void onDispatchAudioServerStateChange(boolean state) {
@@ -2837,20 +2846,45 @@
!= PackageManager.PERMISSION_GRANTED) {
return;
}
- setMicrophoneMuteNoCallerCheck(on, userId);
+ mMicMuteFromApi = on;
+ setMicrophoneMuteNoCallerCheck(userId);
}
- private void setMicrophoneMuteNoCallerCheck(boolean on, int userId) {
+ /** @see AudioManager#setMicrophoneMuteFromSwitch(boolean) */
+ public void setMicrophoneMuteFromSwitch(boolean on) {
+ int userId = Binder.getCallingUid();
+ if (userId != android.os.Process.SYSTEM_UID) {
+ Log.e(TAG, "setMicrophoneMuteFromSwitch() called from non system user!");
+ return;
+ }
+ mMicMuteFromSwitch = on;
+ setMicrophoneMuteNoCallerCheck(userId);
+ }
+
+ private void setMicMuteFromSwitchInput() {
+ InputManager im = mContext.getSystemService(InputManager.class);
+ final int isMicMuted = im.isMicMuted();
+ if (isMicMuted != InputManager.SWITCH_STATE_UNKNOWN) {
+ setMicrophoneMuteFromSwitch(im.isMicMuted() != InputManager.SWITCH_STATE_OFF);
+ }
+ }
+
+ public boolean isMicrophoneMuted() {
+ return mMicMuteFromSwitch || mMicMuteFromRestrictions || mMicMuteFromApi;
+ }
+
+ private void setMicrophoneMuteNoCallerCheck(int userId) {
+ final boolean muted = isMicrophoneMuted();
if (DEBUG_VOL) {
- Log.d(TAG, String.format("Mic mute %s, user=%d", on, userId));
+ Log.d(TAG, String.format("Mic mute %d, user=%d", muted, userId));
}
// only mute for the current user
- if (getCurrentUserId() == userId) {
+ if (getCurrentUserId() == userId || userId == android.os.Process.SYSTEM_UID) {
final boolean currentMute = AudioSystem.isMicrophoneMuted();
final long identity = Binder.clearCallingIdentity();
- AudioSystem.muteMicrophone(on);
+ AudioSystem.muteMicrophone(muted);
Binder.restoreCallingIdentity(identity);
- if (on != currentMute) {
+ if (muted != currentMute) {
mContext.sendBroadcastAsUser(
new Intent(AudioManager.ACTION_MICROPHONE_MUTE_CHANGED)
.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY), UserHandle.ALL);
@@ -5378,7 +5412,8 @@
final boolean isRestricted =
newRestrictions.getBoolean(UserManager.DISALLOW_UNMUTE_MICROPHONE);
if (wasRestricted != isRestricted) {
- setMicrophoneMuteNoCallerCheck(isRestricted, userId);
+ mMicMuteFromRestrictions = isRestricted;
+ setMicrophoneMuteNoCallerCheck(userId);
}
}
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 75b9705..b338705 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -47,6 +47,7 @@
import android.hardware.input.InputManagerInternal;
import android.hardware.input.KeyboardLayout;
import android.hardware.input.TouchCalibration;
+import android.media.AudioManager;
import android.os.Binder;
import android.os.Bundle;
import android.os.Environment;
@@ -294,6 +295,9 @@
/** Switch code: Camera lens cover. When set the lens is covered. */
public static final int SW_CAMERA_LENS_COVER = 0x09;
+ /** Switch code: Microphone. When set it is off. */
+ public static final int SW_MUTE_DEVICE = 0x0e;
+
public static final int SW_LID_BIT = 1 << SW_LID;
public static final int SW_TABLET_MODE_BIT = 1 << SW_TABLET_MODE;
public static final int SW_KEYPAD_SLIDE_BIT = 1 << SW_KEYPAD_SLIDE;
@@ -304,6 +308,7 @@
public static final int SW_JACK_BITS =
SW_HEADPHONE_INSERT_BIT | SW_MICROPHONE_INSERT_BIT | SW_JACK_PHYSICAL_INSERT_BIT | SW_LINEOUT_INSERT_BIT;
public static final int SW_CAMERA_LENS_COVER_BIT = 1 << SW_CAMERA_LENS_COVER;
+ public static final int SW_MUTE_DEVICE_BIT = 1 << SW_MUTE_DEVICE;
/** Whether to use the dev/input/event or uevent subsystem for the audio jack. */
final boolean mUseDevInputEventForAudioJack;
@@ -970,6 +975,11 @@
}
@Override // Binder call
+ public int isMicMuted() {
+ return getSwitchState(-1, InputDevice.SOURCE_ANY, SW_MUTE_DEVICE);
+ }
+
+ @Override // Binder call
public void registerTabletModeChangedListener(ITabletModeChangedListener listener) {
if (!checkCallingPermission(android.Manifest.permission.TABLET_MODE,
"registerTabletModeChangedListener()")) {
@@ -1779,6 +1789,12 @@
mHandler.obtainMessage(MSG_DELIVER_TABLET_MODE_CHANGED,
args).sendToTarget();
}
+
+ if ((switchMask & SW_MUTE_DEVICE_BIT) != 0) {
+ final boolean micMute = ((switchValues & SW_MUTE_DEVICE_BIT) != 0);
+ AudioManager audioManager = mContext.getSystemService(AudioManager.class);
+ audioManager.setMicrophoneMuteFromSwitch(micMute);
+ }
}
// Native callback.