Loading services/core/java/com/android/server/sensors/SensorManagerInternal.java 0 → 100644 +55 −0 Original line number Diff line number Diff line /* * Copyright (C) 2021 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 com.android.server.sensors; import android.annotation.NonNull; import java.util.concurrent.Executor; /** * Local system service interface for sensors. * * @hide Only for use within system server. */ public abstract class SensorManagerInternal { /** * Adds a listener for changes in proximity sensor state. * @param executor The {@link Executor} to {@link Executor#execute invoke} the listener on. * @param listener The listener to add. * * @throws IllegalArgumentException when adding a listener that is already listening */ public abstract void addProximityActiveListener(@NonNull Executor executor, @NonNull ProximityActiveListener listener); /** * Removes a previously registered listener of proximity sensor state changes. * @param listener The listener to remove. */ public abstract void removeProximityActiveListener(@NonNull ProximityActiveListener listener); /** * Listener for proximity sensor state changes. */ public interface ProximityActiveListener { /** * Callback invoked when the proximity sensor state changes * @param isActive whether the sensor is being enabled or disabled. */ void onProximityActive(boolean isActive); } } services/core/java/com/android/server/sensors/SensorService.java +90 −3 Original line number Diff line number Diff line Loading @@ -16,25 +16,41 @@ package com.android.server.sensors; import static com.android.server.sensors.SensorManagerInternal.ProximityActiveListener; import android.annotation.NonNull; import android.content.Context; import android.util.ArrayMap; import com.android.internal.annotations.GuardedBy; import com.android.internal.util.ConcurrentUtils; import com.android.server.LocalServices; import com.android.server.SystemServerInitThreadPool; import com.android.server.SystemService; import com.android.server.utils.TimingsTraceAndSlog; import java.util.Objects; import java.util.concurrent.Executor; import java.util.concurrent.Future; public class SensorService extends SystemService { private static final String START_NATIVE_SENSOR_SERVICE = "StartNativeSensorService"; private final Object mLock = new Object(); @GuardedBy("mLock") private final ArrayMap<ProximityActiveListener, ProximityListenerProxy> mProximityListeners = new ArrayMap<>(); @GuardedBy("mLock") private Future<?> mSensorServiceStart; @GuardedBy("mLock") private long mPtr; /** Start the sensor service. This is a blocking call and can take time. */ private static native void startNativeSensorService(); private static native long startSensorServiceNative(ProximityActiveListener listener); private static native void registerProximityActiveListenerNative(long ptr); private static native void unregisterProximityActiveListenerNative(long ptr); public SensorService(Context ctx) { super(ctx); Loading @@ -42,14 +58,19 @@ public class SensorService extends SystemService { mSensorServiceStart = SystemServerInitThreadPool.submit(() -> { TimingsTraceAndSlog traceLog = TimingsTraceAndSlog.newAsyncLog(); traceLog.traceBegin(START_NATIVE_SENSOR_SERVICE); startNativeSensorService(); long ptr = startSensorServiceNative(new ProximityListenerDelegate()); synchronized (mLock) { mPtr = ptr; } traceLog.traceEnd(); }, START_NATIVE_SENSOR_SERVICE); } } @Override public void onStart() { } public void onStart() { LocalServices.addService(SensorManagerInternal.class, new LocalService()); } @Override public void onBootPhase(int phase) { Loading @@ -61,4 +82,70 @@ public class SensorService extends SystemService { } } } class LocalService extends SensorManagerInternal { @Override public void addProximityActiveListener(@NonNull Executor executor, @NonNull ProximityActiveListener listener) { Objects.requireNonNull(executor, "executor must not be null"); Objects.requireNonNull(listener, "listener must not be null"); ProximityListenerProxy proxy = new ProximityListenerProxy(executor, listener); synchronized (mLock) { if (mProximityListeners.containsKey(listener)) { throw new IllegalArgumentException("listener already registered"); } mProximityListeners.put(listener, proxy); if (mProximityListeners.size() == 1) { registerProximityActiveListenerNative(mPtr); } } } @Override public void removeProximityActiveListener(@NonNull ProximityActiveListener listener) { Objects.requireNonNull(listener, "listener must not be null"); synchronized (mLock) { ProximityListenerProxy proxy = mProximityListeners.remove(listener); if (proxy == null) { throw new IllegalArgumentException( "listener was not registered with sensor service"); } if (mProximityListeners.isEmpty()) { unregisterProximityActiveListenerNative(mPtr); } } } } private static class ProximityListenerProxy implements ProximityActiveListener { private final Executor mExecutor; private final ProximityActiveListener mListener; ProximityListenerProxy(Executor executor, ProximityActiveListener listener) { mExecutor = executor; mListener = listener; } @Override public void onProximityActive(boolean isActive) { mExecutor.execute(() -> mListener.onProximityActive(isActive)); } } private class ProximityListenerDelegate implements ProximityActiveListener { @Override public void onProximityActive(boolean isActive) { final ProximityListenerProxy[] listeners; // We can't call out while holding the lock because clients might be calling into us // while holding their own locks (e.g. when registering / unregistering their // listeners).This would break lock ordering and create deadlocks. Instead, we need to // copy the listeners out and then only invoke them once we've dropped the lock. synchronized (mLock) { listeners = mProximityListeners.values().toArray(new ProximityListenerProxy[0]); } for (ProximityListenerProxy listener : listeners) { listener.onProximityActive(isActive); } } } } services/core/jni/com_android_server_sensor_SensorService.cpp +102 −13 Original line number Diff line number Diff line Loading @@ -14,34 +14,123 @@ * limitations under the License. */ #define LOG_TAG "SensorService" #include <nativehelper/JNIHelp.h> #include "android_runtime/AndroidRuntime.h" #include "core_jni_helpers.h" #include "jni.h" #define LOG_TAG "NativeSensorService" #include <android-base/properties.h> #include <android_runtime/AndroidRuntime.h> #include <core_jni_helpers.h> #include <cutils/properties.h> #include <jni.h> #include <sensorservice/SensorService.h> #include <utils/Log.h> #include <utils/misc.h> #include <mutex> #define PROXIMITY_ACTIVE_CLASS \ "com/android/server/sensors/SensorManagerInternal$ProximityActiveListener" namespace android { static void startNativeSensorService(JNIEnv* env, jclass clazz) { char propBuf[PROPERTY_VALUE_MAX]; property_get("system_init.startsensorservice", propBuf, "1"); if (strcmp(propBuf, "1") == 0) { SensorService::publish(false /* allowIsolated */, IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL); static jmethodID sMethodIdOnProximityActive; class NativeSensorService { public: NativeSensorService(JNIEnv* env, jobject listener); void registerProximityActiveListener(); void unregisterProximityActiveListener(); private: sp<SensorService> mService; class ProximityActiveListenerDelegate : public SensorService::ProximityActiveListener { public: ProximityActiveListenerDelegate(JNIEnv* env, jobject listener); ~ProximityActiveListenerDelegate(); void onProximityActive(bool isActive) override; private: jobject mListener; }; sp<ProximityActiveListenerDelegate> mProximityActiveListenerDelegate; }; NativeSensorService::NativeSensorService(JNIEnv* env, jobject listener) : mProximityActiveListenerDelegate(new ProximityActiveListenerDelegate(env, listener)) { if (base::GetBoolProperty("system_init.startsensorservice", true)) { sp<IServiceManager> sm(defaultServiceManager()); mService = new SensorService(); sm->addService(String16(SensorService::getServiceName()), mService, false /* allowIsolated */, IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL); } } void NativeSensorService::registerProximityActiveListener() { if (mService == nullptr) { ALOGD("Dropping registerProximityActiveListener, sensor service not available."); return; } mService->addProximityActiveListener(mProximityActiveListenerDelegate); } void NativeSensorService::unregisterProximityActiveListener() { if (mService == nullptr) { ALOGD("Dropping unregisterProximityActiveListener, sensor service not available."); return; } mService->removeProximityActiveListener(mProximityActiveListenerDelegate); } NativeSensorService::ProximityActiveListenerDelegate::ProximityActiveListenerDelegate( JNIEnv* env, jobject listener) : mListener(env->NewGlobalRef(listener)) {} NativeSensorService::ProximityActiveListenerDelegate::~ProximityActiveListenerDelegate() { AndroidRuntime::getJNIEnv()->DeleteGlobalRef(mListener); } void NativeSensorService::ProximityActiveListenerDelegate::onProximityActive(bool isActive) { AndroidRuntime::getJNIEnv()->CallVoidMethod(mListener, sMethodIdOnProximityActive, static_cast<jboolean>(isActive)); } static jlong startSensorServiceNative(JNIEnv* env, jclass, jobject listener) { NativeSensorService* service = new NativeSensorService(env, listener); return reinterpret_cast<jlong>(service); } static void registerProximityActiveListenerNative(JNIEnv* env, jclass, jlong ptr) { auto* service = reinterpret_cast<NativeSensorService*>(ptr); service->registerProximityActiveListener(); } static void unregisterProximityActiveListenerNative(JNIEnv* env, jclass, jlong ptr) { auto* service = reinterpret_cast<NativeSensorService*>(ptr); service->unregisterProximityActiveListener(); } static const JNINativeMethod methods[] = { {"startNativeSensorService", "()V", (void*)startNativeSensorService}, { "startSensorServiceNative", "(L" PROXIMITY_ACTIVE_CLASS ";)J", reinterpret_cast<void*>(startSensorServiceNative) }, { "registerProximityActiveListenerNative", "(J)V", reinterpret_cast<void*>(registerProximityActiveListenerNative) }, { "unregisterProximityActiveListenerNative", "(J)V", reinterpret_cast<void*>(unregisterProximityActiveListenerNative) }, }; int register_android_server_sensor_SensorService(JNIEnv* env) { jclass listenerClass = FindClassOrDie(env, PROXIMITY_ACTIVE_CLASS); sMethodIdOnProximityActive = GetMethodIDOrDie(env, listenerClass, "onProximityActive", "(Z)V"); return jniRegisterNativeMethods(env, "com/android/server/sensors/SensorService", methods, NELEM(methods)); } Loading Loading
services/core/java/com/android/server/sensors/SensorManagerInternal.java 0 → 100644 +55 −0 Original line number Diff line number Diff line /* * Copyright (C) 2021 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 com.android.server.sensors; import android.annotation.NonNull; import java.util.concurrent.Executor; /** * Local system service interface for sensors. * * @hide Only for use within system server. */ public abstract class SensorManagerInternal { /** * Adds a listener for changes in proximity sensor state. * @param executor The {@link Executor} to {@link Executor#execute invoke} the listener on. * @param listener The listener to add. * * @throws IllegalArgumentException when adding a listener that is already listening */ public abstract void addProximityActiveListener(@NonNull Executor executor, @NonNull ProximityActiveListener listener); /** * Removes a previously registered listener of proximity sensor state changes. * @param listener The listener to remove. */ public abstract void removeProximityActiveListener(@NonNull ProximityActiveListener listener); /** * Listener for proximity sensor state changes. */ public interface ProximityActiveListener { /** * Callback invoked when the proximity sensor state changes * @param isActive whether the sensor is being enabled or disabled. */ void onProximityActive(boolean isActive); } }
services/core/java/com/android/server/sensors/SensorService.java +90 −3 Original line number Diff line number Diff line Loading @@ -16,25 +16,41 @@ package com.android.server.sensors; import static com.android.server.sensors.SensorManagerInternal.ProximityActiveListener; import android.annotation.NonNull; import android.content.Context; import android.util.ArrayMap; import com.android.internal.annotations.GuardedBy; import com.android.internal.util.ConcurrentUtils; import com.android.server.LocalServices; import com.android.server.SystemServerInitThreadPool; import com.android.server.SystemService; import com.android.server.utils.TimingsTraceAndSlog; import java.util.Objects; import java.util.concurrent.Executor; import java.util.concurrent.Future; public class SensorService extends SystemService { private static final String START_NATIVE_SENSOR_SERVICE = "StartNativeSensorService"; private final Object mLock = new Object(); @GuardedBy("mLock") private final ArrayMap<ProximityActiveListener, ProximityListenerProxy> mProximityListeners = new ArrayMap<>(); @GuardedBy("mLock") private Future<?> mSensorServiceStart; @GuardedBy("mLock") private long mPtr; /** Start the sensor service. This is a blocking call and can take time. */ private static native void startNativeSensorService(); private static native long startSensorServiceNative(ProximityActiveListener listener); private static native void registerProximityActiveListenerNative(long ptr); private static native void unregisterProximityActiveListenerNative(long ptr); public SensorService(Context ctx) { super(ctx); Loading @@ -42,14 +58,19 @@ public class SensorService extends SystemService { mSensorServiceStart = SystemServerInitThreadPool.submit(() -> { TimingsTraceAndSlog traceLog = TimingsTraceAndSlog.newAsyncLog(); traceLog.traceBegin(START_NATIVE_SENSOR_SERVICE); startNativeSensorService(); long ptr = startSensorServiceNative(new ProximityListenerDelegate()); synchronized (mLock) { mPtr = ptr; } traceLog.traceEnd(); }, START_NATIVE_SENSOR_SERVICE); } } @Override public void onStart() { } public void onStart() { LocalServices.addService(SensorManagerInternal.class, new LocalService()); } @Override public void onBootPhase(int phase) { Loading @@ -61,4 +82,70 @@ public class SensorService extends SystemService { } } } class LocalService extends SensorManagerInternal { @Override public void addProximityActiveListener(@NonNull Executor executor, @NonNull ProximityActiveListener listener) { Objects.requireNonNull(executor, "executor must not be null"); Objects.requireNonNull(listener, "listener must not be null"); ProximityListenerProxy proxy = new ProximityListenerProxy(executor, listener); synchronized (mLock) { if (mProximityListeners.containsKey(listener)) { throw new IllegalArgumentException("listener already registered"); } mProximityListeners.put(listener, proxy); if (mProximityListeners.size() == 1) { registerProximityActiveListenerNative(mPtr); } } } @Override public void removeProximityActiveListener(@NonNull ProximityActiveListener listener) { Objects.requireNonNull(listener, "listener must not be null"); synchronized (mLock) { ProximityListenerProxy proxy = mProximityListeners.remove(listener); if (proxy == null) { throw new IllegalArgumentException( "listener was not registered with sensor service"); } if (mProximityListeners.isEmpty()) { unregisterProximityActiveListenerNative(mPtr); } } } } private static class ProximityListenerProxy implements ProximityActiveListener { private final Executor mExecutor; private final ProximityActiveListener mListener; ProximityListenerProxy(Executor executor, ProximityActiveListener listener) { mExecutor = executor; mListener = listener; } @Override public void onProximityActive(boolean isActive) { mExecutor.execute(() -> mListener.onProximityActive(isActive)); } } private class ProximityListenerDelegate implements ProximityActiveListener { @Override public void onProximityActive(boolean isActive) { final ProximityListenerProxy[] listeners; // We can't call out while holding the lock because clients might be calling into us // while holding their own locks (e.g. when registering / unregistering their // listeners).This would break lock ordering and create deadlocks. Instead, we need to // copy the listeners out and then only invoke them once we've dropped the lock. synchronized (mLock) { listeners = mProximityListeners.values().toArray(new ProximityListenerProxy[0]); } for (ProximityListenerProxy listener : listeners) { listener.onProximityActive(isActive); } } } }
services/core/jni/com_android_server_sensor_SensorService.cpp +102 −13 Original line number Diff line number Diff line Loading @@ -14,34 +14,123 @@ * limitations under the License. */ #define LOG_TAG "SensorService" #include <nativehelper/JNIHelp.h> #include "android_runtime/AndroidRuntime.h" #include "core_jni_helpers.h" #include "jni.h" #define LOG_TAG "NativeSensorService" #include <android-base/properties.h> #include <android_runtime/AndroidRuntime.h> #include <core_jni_helpers.h> #include <cutils/properties.h> #include <jni.h> #include <sensorservice/SensorService.h> #include <utils/Log.h> #include <utils/misc.h> #include <mutex> #define PROXIMITY_ACTIVE_CLASS \ "com/android/server/sensors/SensorManagerInternal$ProximityActiveListener" namespace android { static void startNativeSensorService(JNIEnv* env, jclass clazz) { char propBuf[PROPERTY_VALUE_MAX]; property_get("system_init.startsensorservice", propBuf, "1"); if (strcmp(propBuf, "1") == 0) { SensorService::publish(false /* allowIsolated */, IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL); static jmethodID sMethodIdOnProximityActive; class NativeSensorService { public: NativeSensorService(JNIEnv* env, jobject listener); void registerProximityActiveListener(); void unregisterProximityActiveListener(); private: sp<SensorService> mService; class ProximityActiveListenerDelegate : public SensorService::ProximityActiveListener { public: ProximityActiveListenerDelegate(JNIEnv* env, jobject listener); ~ProximityActiveListenerDelegate(); void onProximityActive(bool isActive) override; private: jobject mListener; }; sp<ProximityActiveListenerDelegate> mProximityActiveListenerDelegate; }; NativeSensorService::NativeSensorService(JNIEnv* env, jobject listener) : mProximityActiveListenerDelegate(new ProximityActiveListenerDelegate(env, listener)) { if (base::GetBoolProperty("system_init.startsensorservice", true)) { sp<IServiceManager> sm(defaultServiceManager()); mService = new SensorService(); sm->addService(String16(SensorService::getServiceName()), mService, false /* allowIsolated */, IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL); } } void NativeSensorService::registerProximityActiveListener() { if (mService == nullptr) { ALOGD("Dropping registerProximityActiveListener, sensor service not available."); return; } mService->addProximityActiveListener(mProximityActiveListenerDelegate); } void NativeSensorService::unregisterProximityActiveListener() { if (mService == nullptr) { ALOGD("Dropping unregisterProximityActiveListener, sensor service not available."); return; } mService->removeProximityActiveListener(mProximityActiveListenerDelegate); } NativeSensorService::ProximityActiveListenerDelegate::ProximityActiveListenerDelegate( JNIEnv* env, jobject listener) : mListener(env->NewGlobalRef(listener)) {} NativeSensorService::ProximityActiveListenerDelegate::~ProximityActiveListenerDelegate() { AndroidRuntime::getJNIEnv()->DeleteGlobalRef(mListener); } void NativeSensorService::ProximityActiveListenerDelegate::onProximityActive(bool isActive) { AndroidRuntime::getJNIEnv()->CallVoidMethod(mListener, sMethodIdOnProximityActive, static_cast<jboolean>(isActive)); } static jlong startSensorServiceNative(JNIEnv* env, jclass, jobject listener) { NativeSensorService* service = new NativeSensorService(env, listener); return reinterpret_cast<jlong>(service); } static void registerProximityActiveListenerNative(JNIEnv* env, jclass, jlong ptr) { auto* service = reinterpret_cast<NativeSensorService*>(ptr); service->registerProximityActiveListener(); } static void unregisterProximityActiveListenerNative(JNIEnv* env, jclass, jlong ptr) { auto* service = reinterpret_cast<NativeSensorService*>(ptr); service->unregisterProximityActiveListener(); } static const JNINativeMethod methods[] = { {"startNativeSensorService", "()V", (void*)startNativeSensorService}, { "startSensorServiceNative", "(L" PROXIMITY_ACTIVE_CLASS ";)J", reinterpret_cast<void*>(startSensorServiceNative) }, { "registerProximityActiveListenerNative", "(J)V", reinterpret_cast<void*>(registerProximityActiveListenerNative) }, { "unregisterProximityActiveListenerNative", "(J)V", reinterpret_cast<void*>(unregisterProximityActiveListenerNative) }, }; int register_android_server_sensor_SensorService(JNIEnv* env) { jclass listenerClass = FindClassOrDie(env, PROXIMITY_ACTIVE_CLASS); sMethodIdOnProximityActive = GetMethodIDOrDie(env, listenerClass, "onProximityActive", "(Z)V"); return jniRegisterNativeMethods(env, "com/android/server/sensors/SensorService", methods, NELEM(methods)); } Loading