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:
Lais Andrade
2020-08-27 15:58:22 +00:00
parent fe13065ce3
commit d049dc442f
10 changed files with 359 additions and 21 deletions

View 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();
}

View File

@@ -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

View File

@@ -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

View File

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

View File

@@ -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. */

View File

@@ -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",

View File

@@ -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

View File

@@ -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

View File

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

View File

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