Create IVibratorManagerService.aidl
Introduce skeleton for new VibratorManager service, with a single method to recover the vibrator IDs. Bug: 166586119 Test: atest FrameworksServicesTests:VibratorManagerServiceTest Change-Id: Ie633c937c9030d837532548b200867f35968a9de
This commit is contained in:
24
core/java/android/os/IVibratorManagerService.aidl
Normal file
24
core/java/android/os/IVibratorManagerService.aidl
Normal file
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package android.os;
|
||||
|
||||
import android.os.VibrationAttributes;
|
||||
|
||||
/** {@hide} */
|
||||
interface IVibratorManagerService {
|
||||
int[] getVibratorIds();
|
||||
}
|
||||
@@ -3,6 +3,7 @@ per-file ExternalVibration.aidl = michaelwr@google.com
|
||||
per-file ExternalVibration.java = michaelwr@google.com
|
||||
per-file IExternalVibrationController.aidl = michaelwr@google.com
|
||||
per-file IExternalVibratorService.aidl = michaelwr@google.com
|
||||
per-file IVibratorManagerService.aidl = michaelwr@google.com
|
||||
per-file IVibratorService.aidl = michaelwr@google.com
|
||||
per-file NullVibrator.java = michaelwr@google.com
|
||||
per-file SystemVibrator.java = michaelwr@google.com
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
per-file ConnectivityService.java,NetworkManagementService.java,NsdService.java = codewiz@google.com, ek@google.com, jchalard@google.com, junyulai@google.com, lorenzo@google.com, reminv@google.com, satk@google.com
|
||||
|
||||
# Vibrator / Threads
|
||||
per-file VibratorService.java, DisplayThread.java = michaelwr@google.com
|
||||
per-file VibratorService.java, DisplayThread.java = ogunwale@google.com
|
||||
per-file VibratorManagerService.java, VibratorService.java, DisplayThread.java = michaelwr@google.com, ogunwale@google.com
|
||||
|
||||
# Zram writeback
|
||||
per-file ZramWriteback.java = minchan@google.com, rajekumar@google.com, srnvs@google.com
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.android.server;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.IBinder;
|
||||
import android.os.IVibratorManagerService;
|
||||
import android.os.ResultReceiver;
|
||||
import android.os.ShellCallback;
|
||||
import android.os.ShellCommand;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
|
||||
import libcore.util.NativeAllocationRegistry;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Arrays;
|
||||
|
||||
/** System implementation of {@link IVibratorManagerService}. */
|
||||
public class VibratorManagerService extends IVibratorManagerService.Stub {
|
||||
private static final String TAG = "VibratorManagerService";
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
private final Context mContext;
|
||||
private final NativeWrapper mNativeWrapper;
|
||||
private final int[] mVibratorIds;
|
||||
|
||||
static native long nativeInit();
|
||||
|
||||
static native long nativeGetFinalizer();
|
||||
|
||||
static native int[] nativeGetVibratorIds(long nativeServicePtr);
|
||||
|
||||
VibratorManagerService(Context context) {
|
||||
this(context, new Injector());
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
VibratorManagerService(Context context, Injector injector) {
|
||||
mContext = context;
|
||||
mNativeWrapper = injector.getNativeWrapper();
|
||||
|
||||
mNativeWrapper.init();
|
||||
|
||||
int[] vibratorIds = mNativeWrapper.getVibratorIds();
|
||||
mVibratorIds = vibratorIds == null ? new int[0] : vibratorIds;
|
||||
}
|
||||
|
||||
@Override // Binder call
|
||||
public int[] getVibratorIds() {
|
||||
return Arrays.copyOf(mVibratorIds, mVibratorIds.length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
|
||||
String[] args, ShellCallback cb, ResultReceiver resultReceiver) {
|
||||
new VibratorManagerShellCommand(this).exec(this, in, out, err, args, cb, resultReceiver);
|
||||
}
|
||||
|
||||
/** Point of injection for test dependencies */
|
||||
@VisibleForTesting
|
||||
static class Injector {
|
||||
|
||||
NativeWrapper getNativeWrapper() {
|
||||
return new NativeWrapper();
|
||||
}
|
||||
}
|
||||
|
||||
/** Wrapper around the static-native methods of {@link VibratorManagerService} for tests. */
|
||||
@VisibleForTesting
|
||||
public static class NativeWrapper {
|
||||
|
||||
private long mNativeServicePtr = 0;
|
||||
|
||||
/** Returns native pointer to newly created controller and connects with HAL service. */
|
||||
public void init() {
|
||||
mNativeServicePtr = VibratorManagerService.nativeInit();
|
||||
long finalizerPtr = VibratorManagerService.nativeGetFinalizer();
|
||||
|
||||
if (finalizerPtr != 0) {
|
||||
NativeAllocationRegistry registry =
|
||||
NativeAllocationRegistry.createMalloced(
|
||||
VibratorManagerService.class.getClassLoader(), finalizerPtr);
|
||||
registry.registerNativeAllocation(this, mNativeServicePtr);
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns vibrator ids. */
|
||||
public int[] getVibratorIds() {
|
||||
return VibratorManagerService.nativeGetVibratorIds(mNativeServicePtr);
|
||||
}
|
||||
}
|
||||
|
||||
/** Provides limited functionality from {@link VibratorManagerService} as shell commands. */
|
||||
private final class VibratorManagerShellCommand extends ShellCommand {
|
||||
|
||||
private final IBinder mToken;
|
||||
|
||||
private VibratorManagerShellCommand(IBinder token) {
|
||||
mToken = token;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onCommand(String cmd) {
|
||||
if ("list".equals(cmd)) {
|
||||
return runListVibrators();
|
||||
}
|
||||
return handleDefaultCommands(cmd);
|
||||
}
|
||||
|
||||
private int runListVibrators() {
|
||||
try (PrintWriter pw = getOutPrintWriter();) {
|
||||
if (mVibratorIds.length == 0) {
|
||||
pw.println("No vibrator found");
|
||||
} else {
|
||||
for (int id : mVibratorIds) {
|
||||
pw.println(id);
|
||||
}
|
||||
}
|
||||
pw.println("");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onHelp() {
|
||||
try (PrintWriter pw = getOutPrintWriter();) {
|
||||
pw.println("Vibrator Manager commands:");
|
||||
pw.println(" help");
|
||||
pw.println(" Prints this help text.");
|
||||
pw.println("");
|
||||
pw.println(" list");
|
||||
pw.println(" Prints the id of device vibrators. This do not include any ");
|
||||
pw.println(" connected input device.");
|
||||
pw.println("");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -385,15 +385,7 @@ public class VibratorService extends IVibratorService.Stub
|
||||
mNativeWrapper = injector.getNativeWrapper();
|
||||
mH = injector.createHandler(Looper.myLooper());
|
||||
|
||||
long nativeServicePtr = mNativeWrapper.vibratorInit(this::onVibrationComplete);
|
||||
long finalizerPtr = mNativeWrapper.vibratorGetFinalizer();
|
||||
|
||||
if (finalizerPtr != 0) {
|
||||
NativeAllocationRegistry registry =
|
||||
NativeAllocationRegistry.createMalloced(
|
||||
VibratorService.class.getClassLoader(), finalizerPtr);
|
||||
registry.registerNativeAllocation(this, nativeServicePtr);
|
||||
}
|
||||
mNativeWrapper.vibratorInit(this::onVibrationComplete);
|
||||
|
||||
// Reset the hardware to a default state, in case this is a runtime
|
||||
// restart instead of a fresh boot.
|
||||
@@ -1746,18 +1738,17 @@ public class VibratorService extends IVibratorService.Stub
|
||||
return VibratorService.vibratorExists(mNativeServicePtr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns native pointer to newly created controller and initializes connection to vibrator
|
||||
* HAL service.
|
||||
*/
|
||||
public long vibratorInit(OnCompleteListener listener) {
|
||||
/** Initializes connection to vibrator HAL service. */
|
||||
public void vibratorInit(OnCompleteListener listener) {
|
||||
mNativeServicePtr = VibratorService.vibratorInit(listener);
|
||||
return mNativeServicePtr;
|
||||
}
|
||||
long finalizerPtr = VibratorService.vibratorGetFinalizer();
|
||||
|
||||
/** Returns pointer to native finalizer function to be called by GC. */
|
||||
public long vibratorGetFinalizer() {
|
||||
return VibratorService.vibratorGetFinalizer();
|
||||
if (finalizerPtr != 0) {
|
||||
NativeAllocationRegistry registry =
|
||||
NativeAllocationRegistry.createMalloced(
|
||||
VibratorService.class.getClassLoader(), finalizerPtr);
|
||||
registry.registerNativeAllocation(this, mNativeServicePtr);
|
||||
}
|
||||
}
|
||||
|
||||
/** Turns vibrator on for given time. */
|
||||
|
||||
@@ -53,6 +53,7 @@ cc_library_static {
|
||||
"com_android_server_UsbDescriptorParser.cpp",
|
||||
"com_android_server_UsbMidiDevice.cpp",
|
||||
"com_android_server_UsbHostManager.cpp",
|
||||
"com_android_server_VibratorManagerService.cpp",
|
||||
"com_android_server_VibratorService.cpp",
|
||||
"com_android_server_PersistentDataBlockService.cpp",
|
||||
"com_android_server_am_CachedAppOptimizer.cpp",
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
per-file com_android_server_lights_LightsService.cpp = michaelwr@google.com, santoscordon@google.com
|
||||
|
||||
# Haptics
|
||||
per-file com_android_server_VibratorManagerService.cpp = michaelwr@google.com
|
||||
per-file com_android_server_VibratorService.cpp = michaelwr@google.com
|
||||
|
||||
# Input
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "VibratorManagerService"
|
||||
|
||||
#include <nativehelper/JNIHelp.h>
|
||||
#include "android_runtime/AndroidRuntime.h"
|
||||
#include "core_jni_helpers.h"
|
||||
#include "jni.h"
|
||||
|
||||
#include <utils/Log.h>
|
||||
#include <utils/misc.h>
|
||||
|
||||
#include <vibratorservice/VibratorManagerHalWrapper.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
class NativeVibratorManagerService {
|
||||
public:
|
||||
NativeVibratorManagerService() : mHal(std::make_unique<vibrator::LegacyManagerHalWrapper>()) {}
|
||||
~NativeVibratorManagerService() = default;
|
||||
|
||||
vibrator::ManagerHalWrapper* hal() const { return mHal.get(); }
|
||||
|
||||
private:
|
||||
const std::unique_ptr<vibrator::ManagerHalWrapper> mHal;
|
||||
};
|
||||
|
||||
static void destroyNativeService(void* ptr) {
|
||||
NativeVibratorManagerService* service = reinterpret_cast<NativeVibratorManagerService*>(ptr);
|
||||
if (service) {
|
||||
delete service;
|
||||
}
|
||||
}
|
||||
|
||||
static jlong nativeInit(JNIEnv* /* env */, jclass /* clazz */) {
|
||||
std::unique_ptr<NativeVibratorManagerService> service =
|
||||
std::make_unique<NativeVibratorManagerService>();
|
||||
return reinterpret_cast<jlong>(service.release());
|
||||
}
|
||||
|
||||
static jlong nativeGetFinalizer(JNIEnv* /* env */, jclass /* clazz */) {
|
||||
return static_cast<jlong>(reinterpret_cast<uintptr_t>(&destroyNativeService));
|
||||
}
|
||||
|
||||
static jintArray nativeGetVibratorIds(JNIEnv* env, jclass /* clazz */, jlong servicePtr) {
|
||||
NativeVibratorManagerService* service =
|
||||
reinterpret_cast<NativeVibratorManagerService*>(servicePtr);
|
||||
if (service == nullptr) {
|
||||
ALOGE("nativeGetVibratorIds failed because native service was not initialized");
|
||||
return nullptr;
|
||||
}
|
||||
auto result = service->hal()->getVibratorIds();
|
||||
if (!result.isOk()) {
|
||||
return nullptr;
|
||||
}
|
||||
std::vector<int32_t> vibratorIds = result.value();
|
||||
jintArray ids = env->NewIntArray(vibratorIds.size());
|
||||
env->SetIntArrayRegion(ids, 0, vibratorIds.size(), reinterpret_cast<jint*>(vibratorIds.data()));
|
||||
return ids;
|
||||
}
|
||||
|
||||
static const JNINativeMethod method_table[] = {
|
||||
{"nativeInit", "()J", (void*)nativeInit},
|
||||
{"nativeGetFinalizer", "()J", (void*)nativeGetFinalizer},
|
||||
{"nativeGetVibratorIds", "(J)[I", (void*)nativeGetVibratorIds},
|
||||
};
|
||||
|
||||
int register_android_server_VibratorManagerService(JNIEnv* env) {
|
||||
return jniRegisterNativeMethods(env, "com/android/server/VibratorManagerService", method_table,
|
||||
NELEM(method_table));
|
||||
}
|
||||
|
||||
}; // namespace android
|
||||
@@ -37,6 +37,7 @@ int register_android_server_UsbDeviceManager(JNIEnv* env);
|
||||
int register_android_server_UsbMidiDevice(JNIEnv* env);
|
||||
int register_android_server_UsbHostManager(JNIEnv* env);
|
||||
int register_android_server_vr_VrManagerService(JNIEnv* env);
|
||||
int register_android_server_VibratorManagerService(JNIEnv* env);
|
||||
int register_android_server_VibratorService(JavaVM* vm, JNIEnv* env);
|
||||
int register_android_server_location_GnssLocationProvider(JNIEnv* env);
|
||||
int register_android_server_connectivity_Vpn(JNIEnv* env);
|
||||
@@ -90,6 +91,7 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
|
||||
register_android_server_UsbAlsaJackDetector(env);
|
||||
register_android_server_UsbHostManager(env);
|
||||
register_android_server_vr_VrManagerService(env);
|
||||
register_android_server_VibratorManagerService(env);
|
||||
register_android_server_VibratorService(vm, env);
|
||||
register_android_server_SystemServer(env);
|
||||
register_android_server_location_GnssLocationProvider(env);
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.android.server;
|
||||
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.platform.test.annotations.Presubmit;
|
||||
|
||||
import androidx.test.InstrumentationRegistry;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnit;
|
||||
import org.mockito.junit.MockitoRule;
|
||||
|
||||
/**
|
||||
* Tests for {@link VibratorManagerService}.
|
||||
*
|
||||
* Build/Install/Run:
|
||||
* atest FrameworksServicesTests:VibratorManagerServiceTest
|
||||
*/
|
||||
@Presubmit
|
||||
public class VibratorManagerServiceTest {
|
||||
|
||||
@Rule public MockitoRule rule = MockitoJUnit.rule();
|
||||
|
||||
@Mock private VibratorManagerService.NativeWrapper mNativeWrapperMock;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
}
|
||||
|
||||
private VibratorManagerService createService() {
|
||||
return new VibratorManagerService(InstrumentationRegistry.getContext(),
|
||||
new VibratorManagerService.Injector() {
|
||||
@Override
|
||||
VibratorManagerService.NativeWrapper getNativeWrapper() {
|
||||
return mNativeWrapperMock;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createService_initializesNativeService() {
|
||||
createService();
|
||||
verify(mNativeWrapperMock).init();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getVibratorIds_withNullResultFromNative_returnsEmptyArray() {
|
||||
when(mNativeWrapperMock.getVibratorIds()).thenReturn(null);
|
||||
assertArrayEquals(new int[0], createService().getVibratorIds());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getVibratorIds_withNonEmptyResultFromNative_returnsSameArray() {
|
||||
when(mNativeWrapperMock.getVibratorIds()).thenReturn(new int[]{ 1, 2 });
|
||||
assertArrayEquals(new int[]{ 1, 2 }, createService().getVibratorIds());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user