Merge "Add support to register Java listeners for prox activation" into sc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
c05ebb5b25
@@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
* 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,25 +16,41 @@
|
|||||||
|
|
||||||
package com.android.server.sensors;
|
package com.android.server.sensors;
|
||||||
|
|
||||||
|
import static com.android.server.sensors.SensorManagerInternal.ProximityActiveListener;
|
||||||
|
|
||||||
|
import android.annotation.NonNull;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.util.ArrayMap;
|
||||||
|
|
||||||
import com.android.internal.annotations.GuardedBy;
|
import com.android.internal.annotations.GuardedBy;
|
||||||
import com.android.internal.util.ConcurrentUtils;
|
import com.android.internal.util.ConcurrentUtils;
|
||||||
|
import com.android.server.LocalServices;
|
||||||
import com.android.server.SystemServerInitThreadPool;
|
import com.android.server.SystemServerInitThreadPool;
|
||||||
import com.android.server.SystemService;
|
import com.android.server.SystemService;
|
||||||
import com.android.server.utils.TimingsTraceAndSlog;
|
import com.android.server.utils.TimingsTraceAndSlog;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
|
|
||||||
public class SensorService extends SystemService {
|
public class SensorService extends SystemService {
|
||||||
private static final String START_NATIVE_SENSOR_SERVICE = "StartNativeSensorService";
|
private static final String START_NATIVE_SENSOR_SERVICE = "StartNativeSensorService";
|
||||||
private final Object mLock = new Object();
|
private final Object mLock = new Object();
|
||||||
@GuardedBy("mLock")
|
@GuardedBy("mLock")
|
||||||
|
private final ArrayMap<ProximityActiveListener, ProximityListenerProxy> mProximityListeners =
|
||||||
|
new ArrayMap<>();
|
||||||
|
@GuardedBy("mLock")
|
||||||
private Future<?> mSensorServiceStart;
|
private Future<?> mSensorServiceStart;
|
||||||
|
@GuardedBy("mLock")
|
||||||
|
private long mPtr;
|
||||||
|
|
||||||
|
|
||||||
/** Start the sensor service. This is a blocking call and can take time. */
|
/** 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) {
|
public SensorService(Context ctx) {
|
||||||
super(ctx);
|
super(ctx);
|
||||||
@@ -42,14 +58,19 @@ public class SensorService extends SystemService {
|
|||||||
mSensorServiceStart = SystemServerInitThreadPool.submit(() -> {
|
mSensorServiceStart = SystemServerInitThreadPool.submit(() -> {
|
||||||
TimingsTraceAndSlog traceLog = TimingsTraceAndSlog.newAsyncLog();
|
TimingsTraceAndSlog traceLog = TimingsTraceAndSlog.newAsyncLog();
|
||||||
traceLog.traceBegin(START_NATIVE_SENSOR_SERVICE);
|
traceLog.traceBegin(START_NATIVE_SENSOR_SERVICE);
|
||||||
startNativeSensorService();
|
long ptr = startSensorServiceNative(new ProximityListenerDelegate());
|
||||||
|
synchronized (mLock) {
|
||||||
|
mPtr = ptr;
|
||||||
|
}
|
||||||
traceLog.traceEnd();
|
traceLog.traceEnd();
|
||||||
}, START_NATIVE_SENSOR_SERVICE);
|
}, START_NATIVE_SENSOR_SERVICE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStart() { }
|
public void onStart() {
|
||||||
|
LocalServices.addService(SensorManagerInternal.class, new LocalService());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBootPhase(int phase) {
|
public void onBootPhase(int phase) {
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,34 +14,123 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define LOG_TAG "SensorService"
|
#define LOG_TAG "NativeSensorService"
|
||||||
|
|
||||||
#include <nativehelper/JNIHelp.h>
|
|
||||||
#include "android_runtime/AndroidRuntime.h"
|
|
||||||
#include "core_jni_helpers.h"
|
|
||||||
#include "jni.h"
|
|
||||||
|
|
||||||
|
#include <android-base/properties.h>
|
||||||
|
#include <android_runtime/AndroidRuntime.h>
|
||||||
|
#include <core_jni_helpers.h>
|
||||||
#include <cutils/properties.h>
|
#include <cutils/properties.h>
|
||||||
|
#include <jni.h>
|
||||||
#include <sensorservice/SensorService.h>
|
#include <sensorservice/SensorService.h>
|
||||||
#include <utils/Log.h>
|
#include <utils/Log.h>
|
||||||
#include <utils/misc.h>
|
#include <utils/misc.h>
|
||||||
|
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
#define PROXIMITY_ACTIVE_CLASS \
|
||||||
|
"com/android/server/sensors/SensorManagerInternal$ProximityActiveListener"
|
||||||
|
|
||||||
namespace android {
|
namespace android {
|
||||||
|
|
||||||
static void startNativeSensorService(JNIEnv* env, jclass clazz) {
|
static jmethodID sMethodIdOnProximityActive;
|
||||||
char propBuf[PROPERTY_VALUE_MAX];
|
|
||||||
property_get("system_init.startsensorservice", propBuf, "1");
|
class NativeSensorService {
|
||||||
if (strcmp(propBuf, "1") == 0) {
|
public:
|
||||||
SensorService::publish(false /* allowIsolated */,
|
NativeSensorService(JNIEnv* env, jobject listener);
|
||||||
IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL);
|
|
||||||
|
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[] = {
|
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) {
|
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,
|
return jniRegisterNativeMethods(env, "com/android/server/sensors/SensorService", methods,
|
||||||
NELEM(methods));
|
NELEM(methods));
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user