Merge changes from topic "invert-capture-rvc" into rvc-dev am: 40ee6ffa32
Change-Id: I997ab2a1e580e770dc6423fcd659cd702371bdec
This commit is contained in:
@@ -36,40 +36,23 @@ import java.util.function.Consumer;
|
||||
* For simplicity, there is currently no way to stop the tracker. This is possible to add if the
|
||||
* need ever arises.
|
||||
*/
|
||||
public class ExternalCaptureStateTracker {
|
||||
class ExternalCaptureStateTracker {
|
||||
private static final String TAG = "CaptureStateTracker";
|
||||
/** Our client's listener. */
|
||||
private final Consumer<Boolean> mListener;
|
||||
/** A lock used to ensure synchronized access to mListener. */
|
||||
private final Object mListenerLock = new Object();
|
||||
/**
|
||||
* The binder listener that we're providing to the audio policy service. Ensures synchronized
|
||||
* access to mListener.
|
||||
*/
|
||||
private final Listener mSyncListener = new Listener();
|
||||
/** The name of the audio policy service. */
|
||||
private final String mAudioPolicyServiceName;
|
||||
/** This semaphore will get a permit every time we need to reconnect. */
|
||||
private final Semaphore mNeedToConnect = new Semaphore(1);
|
||||
/**
|
||||
* We must hold a reference to the APM service, even though we're not actually using it after
|
||||
* installing the callback. Otherwise, binder silently un-links our death listener.
|
||||
*/
|
||||
private IBinder mService;
|
||||
|
||||
/**
|
||||
* Constructor. Will start a background thread to do the work.
|
||||
*
|
||||
* @param audioPolicyServiceName The name of the audio policy service to connect to.
|
||||
* @param listener A client provided listener that will be called on state
|
||||
* changes. May be
|
||||
* called multiple consecutive times with the same value. Never
|
||||
* called
|
||||
* concurrently.
|
||||
* @param listener A client provided listener that will be called on state
|
||||
* changes. May be
|
||||
* called multiple consecutive times with the same value. Never
|
||||
* called
|
||||
* concurrently.
|
||||
*/
|
||||
public ExternalCaptureStateTracker(String audioPolicyServiceName,
|
||||
Consumer<Boolean> listener) {
|
||||
mAudioPolicyServiceName = audioPolicyServiceName;
|
||||
ExternalCaptureStateTracker(Consumer<Boolean> listener) {
|
||||
mListener = listener;
|
||||
new Thread(this::run).start();
|
||||
}
|
||||
@@ -80,78 +63,29 @@ public class ExternalCaptureStateTracker {
|
||||
private void run() {
|
||||
while (true) {
|
||||
mNeedToConnect.acquireUninterruptibly();
|
||||
connectWithRetry();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to connect. Retry in case of RemoteException.
|
||||
*/
|
||||
private void connectWithRetry() {
|
||||
while (true) {
|
||||
try {
|
||||
connect();
|
||||
return;
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Exception caught trying to connect", e);
|
||||
} catch (ServiceManager.ServiceNotFoundException e) {
|
||||
Log.w(TAG, "Service not yet available, waiting", e);
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException ex) {
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Unexpected exception caught trying to connect", e);
|
||||
throw e;
|
||||
}
|
||||
connect();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect to the service, install listener and death notifier.
|
||||
*
|
||||
* @throws RemoteException In case of a binder issue.
|
||||
*/
|
||||
private void connect() throws RemoteException, ServiceManager.ServiceNotFoundException {
|
||||
Log.d(TAG, "Connecting to audio policy service: " + mAudioPolicyServiceName);
|
||||
mService = ServiceManager.getServiceOrThrow(mAudioPolicyServiceName);
|
||||
private native void connect();
|
||||
|
||||
synchronized (mListenerLock) {
|
||||
boolean active = registerSoundTriggerCaptureStateListener(mService, mSyncListener);
|
||||
mListener.accept(active);
|
||||
}
|
||||
|
||||
mService.linkToDeath(() -> {
|
||||
Log.w(TAG, "Audio policy service died");
|
||||
mNeedToConnect.release();
|
||||
}, 0);
|
||||
/**
|
||||
* Called by native code to invoke the client listener.
|
||||
*
|
||||
* @param active true when external capture is active.
|
||||
*/
|
||||
private void setCaptureState(boolean active) {
|
||||
mListener.accept(active);
|
||||
}
|
||||
|
||||
/**
|
||||
* Since the audio policy service does not have an AIDL interface, this method does the
|
||||
* necessary manual marshalling.
|
||||
*
|
||||
* @param service The service binder object.
|
||||
* @param listener The listener binder object to register.
|
||||
* @return The active state at the time of registration.
|
||||
* Called by native code when the remote service died.
|
||||
*/
|
||||
private boolean registerSoundTriggerCaptureStateListener(IBinder service,
|
||||
ICaptureStateListener listener) throws RemoteException {
|
||||
Parcel request = Parcel.obtain();
|
||||
Parcel response = Parcel.obtain();
|
||||
request.writeInterfaceToken("android.media.IAudioPolicyService");
|
||||
request.writeStrongBinder(listener.asBinder());
|
||||
service.transact(82 /* REGISTER_SOUNDTRIGGER_CAPTURE_STATE_LISTENER */, request, response,
|
||||
0);
|
||||
return response.readBoolean();
|
||||
}
|
||||
|
||||
private class Listener extends ICaptureStateListener.Stub {
|
||||
@Override
|
||||
public void setCaptureState(boolean active) {
|
||||
synchronized (mListenerLock) {
|
||||
mListener.accept(active);
|
||||
}
|
||||
}
|
||||
private void binderDied() {
|
||||
Log.w(TAG, "Audio policy service died");
|
||||
mNeedToConnect.release();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ public class SoundTriggerMiddlewareService extends ISoundTriggerMiddlewareServic
|
||||
*/
|
||||
private SoundTriggerMiddlewareService(@NonNull ISoundTriggerMiddlewareInternal delegate) {
|
||||
mDelegate = Objects.requireNonNull(delegate);
|
||||
new ExternalCaptureStateTracker("media.audio_policy", active -> {
|
||||
new ExternalCaptureStateTracker(active -> {
|
||||
try {
|
||||
mDelegate.setCaptureState(active);
|
||||
} catch (RemoteException e) {
|
||||
|
||||
@@ -40,6 +40,7 @@ cc_library_static {
|
||||
"com_android_server_security_VerityUtils.cpp",
|
||||
"com_android_server_SerialService.cpp",
|
||||
"com_android_server_soundtrigger_middleware_AudioSessionProviderImpl.cpp",
|
||||
"com_android_server_soundtrigger_middleware_ExternalCaptureStateTracker.cpp",
|
||||
"com_android_server_stats_pull_StatsPullAtomService.cpp",
|
||||
"com_android_server_storage_AppFuseBridge.cpp",
|
||||
"com_android_server_SystemServer.cpp",
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#define LOG_TAG "ExternalCaptureStateTracker"
|
||||
|
||||
#include "core_jni_helpers.h"
|
||||
#include <log/log.h>
|
||||
#include <media/AudioSystem.h>
|
||||
|
||||
namespace android {
|
||||
namespace {
|
||||
|
||||
#define PACKAGE "com/android/server/soundtrigger_middleware"
|
||||
#define CLASSNAME PACKAGE "/ExternalCaptureStateTracker"
|
||||
|
||||
jclass gExternalCaptureStateTrackerClassId;
|
||||
jmethodID gSetCaptureStateMethodId;
|
||||
jmethodID gBinderDiedMethodId;
|
||||
|
||||
void PopulateIds(JNIEnv* env) {
|
||||
gExternalCaptureStateTrackerClassId =
|
||||
(jclass) env->NewGlobalRef(FindClassOrDie(env, CLASSNAME));
|
||||
gSetCaptureStateMethodId = GetMethodIDOrDie(env,
|
||||
gExternalCaptureStateTrackerClassId,
|
||||
"setCaptureState",
|
||||
"(Z)V");
|
||||
gBinderDiedMethodId = GetMethodIDOrDie(env,
|
||||
gExternalCaptureStateTrackerClassId,
|
||||
"binderDied",
|
||||
"()V");
|
||||
}
|
||||
|
||||
class Listener : public AudioSystem::CaptureStateListener {
|
||||
public:
|
||||
Listener(JNIEnv* env, jobject obj) : mObj(env->NewGlobalRef(obj)) {}
|
||||
|
||||
~Listener() {
|
||||
JNIEnv* env = AndroidRuntime::getJNIEnv();
|
||||
env->DeleteGlobalRef(mObj);
|
||||
}
|
||||
|
||||
void onStateChanged(bool active) override {
|
||||
JNIEnv* env = AndroidRuntime::getJNIEnv();
|
||||
env->CallVoidMethod(mObj, gSetCaptureStateMethodId, active);
|
||||
}
|
||||
|
||||
void onServiceDied() override {
|
||||
JNIEnv* env = AndroidRuntime::getJNIEnv();
|
||||
env->CallVoidMethod(mObj, gBinderDiedMethodId);
|
||||
}
|
||||
|
||||
private:
|
||||
jobject mObj;
|
||||
};
|
||||
|
||||
void connect(JNIEnv* env, jobject obj) {
|
||||
sp<AudioSystem::CaptureStateListener> listener(new Listener(env, obj));
|
||||
status_t status =
|
||||
AudioSystem::registerSoundTriggerCaptureStateListener(listener);
|
||||
LOG_ALWAYS_FATAL_IF(status != NO_ERROR);
|
||||
}
|
||||
|
||||
const JNINativeMethod gMethods[] = {
|
||||
{"connect", "()V", reinterpret_cast<void*>(connect)},
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
int register_com_android_server_soundtrigger_middleware_ExternalCaptureStateTracker(
|
||||
JNIEnv* env) {
|
||||
PopulateIds(env);
|
||||
return RegisterMethodsOrDie(env,
|
||||
CLASSNAME,
|
||||
gMethods,
|
||||
NELEM(gMethods));
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
@@ -58,6 +58,8 @@ int register_android_server_am_CachedAppOptimizer(JNIEnv* env);
|
||||
int register_android_server_am_LowMemDetector(JNIEnv* env);
|
||||
int register_com_android_server_soundtrigger_middleware_AudioSessionProviderImpl(
|
||||
JNIEnv* env);
|
||||
int register_com_android_server_soundtrigger_middleware_ExternalCaptureStateTracker(
|
||||
JNIEnv* env);
|
||||
int register_android_server_com_android_server_pm_PackageManagerShellCommandDataLoader(JNIEnv* env);
|
||||
int register_android_server_stats_pull_StatsPullAtomService(JNIEnv* env);
|
||||
int register_android_server_AdbDebuggingManager(JNIEnv* env);
|
||||
@@ -112,6 +114,8 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
|
||||
register_android_server_am_LowMemDetector(env);
|
||||
register_com_android_server_soundtrigger_middleware_AudioSessionProviderImpl(
|
||||
env);
|
||||
register_com_android_server_soundtrigger_middleware_ExternalCaptureStateTracker(
|
||||
env);
|
||||
register_android_server_com_android_server_pm_PackageManagerShellCommandDataLoader(env);
|
||||
register_android_server_stats_pull_StatsPullAtomService(env);
|
||||
register_android_server_AdbDebuggingManager(env);
|
||||
|
||||
Reference in New Issue
Block a user