summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/soundtrigger_middleware/ExternalCaptureStateTracker.java102
-rw-r--r--services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareService.java2
-rw-r--r--services/core/jni/Android.bp1
-rw-r--r--services/core/jni/com_android_server_soundtrigger_middleware_ExternalCaptureStateTracker.cpp93
-rw-r--r--services/core/jni/onload.cpp4
5 files changed, 117 insertions, 85 deletions
diff --git a/services/core/java/com/android/server/soundtrigger_middleware/ExternalCaptureStateTracker.java b/services/core/java/com/android/server/soundtrigger_middleware/ExternalCaptureStateTracker.java
index c341df392621..7977e931c37f 100644
--- a/services/core/java/com/android/server/soundtrigger_middleware/ExternalCaptureStateTracker.java
+++ b/services/core/java/com/android/server/soundtrigger_middleware/ExternalCaptureStateTracker.java
@@ -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();
+ connect();
}
}
/**
- * Try to connect. Retry in case of RemoteException.
+ * Connect to the service, install listener and death notifier.
*/
- 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;
- }
- }
- }
+ private native void connect();
/**
- * Connect to the service, install listener and death notifier.
+ * Called by native code to invoke the client listener.
*
- * @throws RemoteException In case of a binder issue.
+ * @param active true when external capture is active.
*/
- private void connect() throws RemoteException, ServiceManager.ServiceNotFoundException {
- Log.d(TAG, "Connecting to audio policy service: " + mAudioPolicyServiceName);
- mService = ServiceManager.getServiceOrThrow(mAudioPolicyServiceName);
-
- synchronized (mListenerLock) {
- boolean active = registerSoundTriggerCaptureStateListener(mService, mSyncListener);
- mListener.accept(active);
- }
-
- mService.linkToDeath(() -> {
- Log.w(TAG, "Audio policy service died");
- mNeedToConnect.release();
- }, 0);
+ 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();
}
}
diff --git a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareService.java b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareService.java
index 33b21416b23f..929d92f56c44 100644
--- a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareService.java
+++ b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareService.java
@@ -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) {
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index 74982c6918a2..4c3f73d2d129 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -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",
diff --git a/services/core/jni/com_android_server_soundtrigger_middleware_ExternalCaptureStateTracker.cpp b/services/core/jni/com_android_server_soundtrigger_middleware_ExternalCaptureStateTracker.cpp
new file mode 100644
index 000000000000..ae6cb187fa47
--- /dev/null
+++ b/services/core/jni/com_android_server_soundtrigger_middleware_ExternalCaptureStateTracker.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
diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp
index eb486fea0116..b988bd45d786 100644
--- a/services/core/jni/onload.cpp
+++ b/services/core/jni/onload.cpp
@@ -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);