Merge "Add support to register Java listeners for prox activation" into sc-dev

This commit is contained in:
TreeHugger Robot
2021-06-01 15:53:59 +00:00
committed by Android (Google) Code Review
3 changed files with 247 additions and 16 deletions

View File

@@ -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);
}
}

View File

@@ -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);
@@ -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) {
@@ -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);
}
}
}
}

View File

@@ -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));
}