Merge "Audio Injection respect Enterprise Policy"
This commit is contained in:
committed by
Android (Google) Code Review
commit
8cb4fa9e89
@@ -43,13 +43,20 @@ public final class AudioInjection {
|
||||
private static final String TAG = "AudioInjection";
|
||||
|
||||
private final Object mLock = new Object();
|
||||
|
||||
@GuardedBy("mLock")
|
||||
@Nullable
|
||||
private AudioTrack mAudioTrack;
|
||||
|
||||
@GuardedBy("mLock")
|
||||
private int mPlayState = PLAYSTATE_STOPPED;
|
||||
@GuardedBy("mLock")
|
||||
private boolean mIsSilent;
|
||||
|
||||
/** Sets if the injected microphone sound is silent. */
|
||||
void setSilent(boolean isSilent) {
|
||||
synchronized (mLock) {
|
||||
mIsSilent = isSilent;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link AudioTrack} to handle audio injection.
|
||||
@@ -86,7 +93,7 @@ public final class AudioInjection {
|
||||
public int write(@NonNull ByteBuffer audioBuffer, int sizeInBytes, int writeMode) {
|
||||
final int sizeWrite;
|
||||
synchronized (mLock) {
|
||||
if (mAudioTrack != null) {
|
||||
if (mAudioTrack != null && !mIsSilent) {
|
||||
sizeWrite = mAudioTrack.write(audioBuffer, sizeInBytes, writeMode);
|
||||
} else {
|
||||
sizeWrite = 0;
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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 android.companion.virtual.audio;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.os.Bundle;
|
||||
import android.os.UserManager;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
|
||||
/**
|
||||
* Class to detect the user restrictions change for microphone usage.
|
||||
*/
|
||||
final class UserRestrictionsDetector extends BroadcastReceiver {
|
||||
private static final String TAG = "UserRestrictionsDetector";
|
||||
|
||||
/** Interface for listening user restrictions change. */
|
||||
interface UserRestrictionsCallback {
|
||||
|
||||
/** Notifies when value of {@link UserManager#DISALLOW_UNMUTE_MICROPHONE} is changed. */
|
||||
void onMicrophoneRestrictionChanged(boolean isUnmuteMicDisallowed);
|
||||
}
|
||||
|
||||
private final Context mContext;
|
||||
private final UserManager mUserManager;
|
||||
private final Object mLock = new Object();
|
||||
@GuardedBy("mLock")
|
||||
private boolean mIsUnmuteMicDisallowed;
|
||||
private UserRestrictionsCallback mUserRestrictionsCallback;
|
||||
|
||||
UserRestrictionsDetector(Context context) {
|
||||
mContext = context;
|
||||
mUserManager = context.getSystemService(UserManager.class);
|
||||
}
|
||||
|
||||
/** Returns value of {@link UserManager#DISALLOW_UNMUTE_MICROPHONE}. */
|
||||
boolean isUnmuteMicrophoneDisallowed() {
|
||||
Bundle bundle = mUserManager.getUserRestrictions();
|
||||
return bundle.getBoolean(UserManager.DISALLOW_UNMUTE_MICROPHONE);
|
||||
}
|
||||
|
||||
/** Registers user restrictions change. */
|
||||
void register(@NonNull UserRestrictionsCallback callback) {
|
||||
mUserRestrictionsCallback = callback;
|
||||
|
||||
IntentFilter filter = new IntentFilter();
|
||||
filter.addAction(UserManager.ACTION_USER_RESTRICTIONS_CHANGED);
|
||||
mContext.registerReceiver(/* receiver= */ this, filter);
|
||||
|
||||
synchronized (mLock) {
|
||||
// Gets initial value.
|
||||
mIsUnmuteMicDisallowed = isUnmuteMicrophoneDisallowed();
|
||||
}
|
||||
}
|
||||
|
||||
/** Unregisters user restrictions change. */
|
||||
void unregister() {
|
||||
mUserRestrictionsCallback = null;
|
||||
mContext.unregisterReceiver(/* receiver= */ this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
final String action = intent.getAction();
|
||||
if (UserManager.ACTION_USER_RESTRICTIONS_CHANGED.equals(action)) {
|
||||
boolean isUnmuteMicDisallowed = isUnmuteMicrophoneDisallowed();
|
||||
synchronized (mLock) {
|
||||
if (isUnmuteMicDisallowed == mIsUnmuteMicDisallowed) {
|
||||
return;
|
||||
}
|
||||
mIsUnmuteMicDisallowed = isUnmuteMicDisallowed;
|
||||
}
|
||||
if (mUserRestrictionsCallback != null) {
|
||||
mUserRestrictionsCallback.onMicrophoneRestrictionChanged(isUnmuteMicDisallowed);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,7 @@ package android.companion.virtual.audio;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.RequiresPermission;
|
||||
import android.companion.virtual.audio.UserRestrictionsDetector.UserRestrictionsCallback;
|
||||
import android.companion.virtual.audio.VirtualAudioDevice.AudioConfigurationChangeCallback;
|
||||
import android.content.Context;
|
||||
import android.media.AudioFormat;
|
||||
@@ -50,10 +51,11 @@ import java.util.concurrent.Executor;
|
||||
*/
|
||||
@VisibleForTesting
|
||||
public final class VirtualAudioSession extends IAudioSessionCallback.Stub implements
|
||||
Closeable {
|
||||
UserRestrictionsCallback, Closeable {
|
||||
private static final String TAG = "VirtualAudioSession";
|
||||
|
||||
private final Context mContext;
|
||||
private final UserRestrictionsDetector mUserRestrictionsDetector;
|
||||
/** The {@link Executor} for sending {@link AudioConfigurationChangeCallback} to the caller */
|
||||
private final Executor mExecutor;
|
||||
@Nullable
|
||||
@@ -81,6 +83,7 @@ public final class VirtualAudioSession extends IAudioSessionCallback.Stub implem
|
||||
public VirtualAudioSession(Context context,
|
||||
@Nullable AudioConfigurationChangeCallback callback, @Nullable Executor executor) {
|
||||
mContext = context;
|
||||
mUserRestrictionsDetector = new UserRestrictionsDetector(context);
|
||||
mCallback = callback;
|
||||
mExecutor = executor != null ? executor : context.getMainExecutor();
|
||||
}
|
||||
@@ -117,7 +120,7 @@ public final class VirtualAudioSession extends IAudioSessionCallback.Stub implem
|
||||
@NonNull
|
||||
public AudioInjection startAudioInjection(@NonNull AudioFormat injectionFormat) {
|
||||
Objects.requireNonNull(injectionFormat, "injectionFormat must not be null");
|
||||
|
||||
mUserRestrictionsDetector.register(/* callback= */ this);
|
||||
synchronized (mLock) {
|
||||
if (mAudioInjection != null) {
|
||||
throw new IllegalStateException(
|
||||
@@ -127,6 +130,7 @@ public final class VirtualAudioSession extends IAudioSessionCallback.Stub implem
|
||||
mInjectionFormat = injectionFormat;
|
||||
mAudioInjection = new AudioInjection();
|
||||
mAudioInjection.play();
|
||||
mAudioInjection.setSilent(mUserRestrictionsDetector.isUnmuteMicrophoneDisallowed());
|
||||
return mAudioInjection;
|
||||
}
|
||||
}
|
||||
@@ -170,6 +174,7 @@ public final class VirtualAudioSession extends IAudioSessionCallback.Stub implem
|
||||
@RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
|
||||
@Override
|
||||
public void close() {
|
||||
mUserRestrictionsDetector.unregister();
|
||||
releaseAudioStreams();
|
||||
synchronized (mLock) {
|
||||
mAudioCapture = null;
|
||||
@@ -179,6 +184,15 @@ public final class VirtualAudioSession extends IAudioSessionCallback.Stub implem
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMicrophoneRestrictionChanged(boolean isUnmuteMicDisallowed) {
|
||||
synchronized (mLock) {
|
||||
if (mAudioInjection != null) {
|
||||
mAudioInjection.setSilent(isUnmuteMicDisallowed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
|
||||
private void createAudioStreams(int[] appUids) {
|
||||
synchronized (mLock) {
|
||||
|
||||
Reference in New Issue
Block a user