Merge changes from topic "invert-capture-rvc" into rvc-dev am: 40ee6ffa32

Change-Id: I997ab2a1e580e770dc6423fcd659cd702371bdec
This commit is contained in:
Ytai Ben-tsvi
2020-04-01 23:07:36 +00:00
committed by Automerger Merge Worker
5 changed files with 119 additions and 87 deletions

View File

@@ -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 * For simplicity, there is currently no way to stop the tracker. This is possible to add if the
* need ever arises. * need ever arises.
*/ */
public class ExternalCaptureStateTracker { class ExternalCaptureStateTracker {
private static final String TAG = "CaptureStateTracker"; private static final String TAG = "CaptureStateTracker";
/** Our client's listener. */ /** Our client's listener. */
private final Consumer<Boolean> mListener; 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. */ /** This semaphore will get a permit every time we need to reconnect. */
private final Semaphore mNeedToConnect = new Semaphore(1); 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. * 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 * @param listener A client provided listener that will be called on state
* changes. May be * changes. May be
* called multiple consecutive times with the same value. Never * called multiple consecutive times with the same value. Never
* called * called
* concurrently. * concurrently.
*/ */
public ExternalCaptureStateTracker(String audioPolicyServiceName, ExternalCaptureStateTracker(Consumer<Boolean> listener) {
Consumer<Boolean> listener) {
mAudioPolicyServiceName = audioPolicyServiceName;
mListener = listener; mListener = listener;
new Thread(this::run).start(); new Thread(this::run).start();
} }
@@ -80,78 +63,29 @@ public class ExternalCaptureStateTracker {
private void run() { private void run() {
while (true) { while (true) {
mNeedToConnect.acquireUninterruptibly(); mNeedToConnect.acquireUninterruptibly();
connectWithRetry();
}
}
/**
* Try to connect. Retry in case of RemoteException.
*/
private void connectWithRetry() {
while (true) {
try {
connect(); 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 to the service, install listener and death notifier. * Connect to the service, install listener and death notifier.
*
* @throws RemoteException In case of a binder issue.
*/ */
private void connect() throws RemoteException, ServiceManager.ServiceNotFoundException { private native void connect();
Log.d(TAG, "Connecting to audio policy service: " + mAudioPolicyServiceName);
mService = ServiceManager.getServiceOrThrow(mAudioPolicyServiceName);
synchronized (mListenerLock) { /**
boolean active = registerSoundTriggerCaptureStateListener(mService, mSyncListener); * 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); mListener.accept(active);
} }
mService.linkToDeath(() -> {
Log.w(TAG, "Audio policy service died");
mNeedToConnect.release();
}, 0);
}
/** /**
* Since the audio policy service does not have an AIDL interface, this method does the * Called by native code when the remote service died.
* 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.
*/ */
private boolean registerSoundTriggerCaptureStateListener(IBinder service, private void binderDied() {
ICaptureStateListener listener) throws RemoteException { Log.w(TAG, "Audio policy service died");
Parcel request = Parcel.obtain(); mNeedToConnect.release();
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);
}
}
} }
} }

View File

@@ -71,7 +71,7 @@ public class SoundTriggerMiddlewareService extends ISoundTriggerMiddlewareServic
*/ */
private SoundTriggerMiddlewareService(@NonNull ISoundTriggerMiddlewareInternal delegate) { private SoundTriggerMiddlewareService(@NonNull ISoundTriggerMiddlewareInternal delegate) {
mDelegate = Objects.requireNonNull(delegate); mDelegate = Objects.requireNonNull(delegate);
new ExternalCaptureStateTracker("media.audio_policy", active -> { new ExternalCaptureStateTracker(active -> {
try { try {
mDelegate.setCaptureState(active); mDelegate.setCaptureState(active);
} catch (RemoteException e) { } catch (RemoteException e) {

View File

@@ -40,6 +40,7 @@ cc_library_static {
"com_android_server_security_VerityUtils.cpp", "com_android_server_security_VerityUtils.cpp",
"com_android_server_SerialService.cpp", "com_android_server_SerialService.cpp",
"com_android_server_soundtrigger_middleware_AudioSessionProviderImpl.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_stats_pull_StatsPullAtomService.cpp",
"com_android_server_storage_AppFuseBridge.cpp", "com_android_server_storage_AppFuseBridge.cpp",
"com_android_server_SystemServer.cpp", "com_android_server_SystemServer.cpp",

View File

@@ -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

View File

@@ -58,6 +58,8 @@ int register_android_server_am_CachedAppOptimizer(JNIEnv* env);
int register_android_server_am_LowMemDetector(JNIEnv* env); int register_android_server_am_LowMemDetector(JNIEnv* env);
int register_com_android_server_soundtrigger_middleware_AudioSessionProviderImpl( int register_com_android_server_soundtrigger_middleware_AudioSessionProviderImpl(
JNIEnv* env); 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_com_android_server_pm_PackageManagerShellCommandDataLoader(JNIEnv* env);
int register_android_server_stats_pull_StatsPullAtomService(JNIEnv* env); int register_android_server_stats_pull_StatsPullAtomService(JNIEnv* env);
int register_android_server_AdbDebuggingManager(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_android_server_am_LowMemDetector(env);
register_com_android_server_soundtrigger_middleware_AudioSessionProviderImpl( register_com_android_server_soundtrigger_middleware_AudioSessionProviderImpl(
env); env);
register_com_android_server_soundtrigger_middleware_ExternalCaptureStateTracker(
env);
register_android_server_com_android_server_pm_PackageManagerShellCommandDataLoader(env); register_android_server_com_android_server_pm_PackageManagerShellCommandDataLoader(env);
register_android_server_stats_pull_StatsPullAtomService(env); register_android_server_stats_pull_StatsPullAtomService(env);
register_android_server_AdbDebuggingManager(env); register_android_server_AdbDebuggingManager(env);