IMS中Binder案例
- 1、FWK层中AIDL形式
- 1.1 服务端实现Stub
- 1.2 客户端获取proxy
- 2、Native层中AIDL形式
- 2.1 服务端对应Bn端
- 2.2 客户端对应Bp端
android12-release
1、FWK层中AIDL形式
Android 接口定义语言 (AIDL)、Android 应用层 到 HAL 层
AIDL
形式是Android中binder机制
的具体实现。按照规范aidl/hidl文件自动生成相应代码文件:
客户端获取proxy:asInterface(android.os.IBinder obj)
服务端实现Stub:class Stub extends android.os.Binder
1.1 服务端实现Stub
InputManagerService
继承IInputManager.Stub
,SystemServer.java
中服务初始化添加到ServiceManager
中
frameworks/base/services/core/java/com/android/server/input/InputManagerService.java
frameworks/base/core/java/android/hardware/input/IInputManager.aidl
/** @hide */
interface IInputManager {
// Gets input device information.
InputDevice getInputDevice(int deviceId);
int[] getInputDeviceIds();
// Enable/disable input device.
boolean isInputDeviceEnabled(int deviceId);
void enableInputDevice(int deviceId);
void disableInputDevice(int deviceId);
// Reports whether the hardware supports the given keys; returns true if successful
boolean hasKeys(int deviceId, int sourceMask, in int[] keyCodes, out boolean[] keyExists);
// Temporarily changes the pointer speed.
void tryPointerSpeed(int speed);
// Injects an input event into the system. To inject into windows owned by other
// applications, the caller must have the INJECT_EVENTS permission.
@UnsupportedAppUsage
boolean injectInputEvent(in InputEvent ev, int mode);
VerifiedInputEvent verifyInputEvent(in InputEvent ev);
// Calibrate input device position
TouchCalibration getTouchCalibrationForInputDevice(String inputDeviceDescriptor, int rotation);
void setTouchCalibrationForInputDevice(String inputDeviceDescriptor, int rotation,
in TouchCalibration calibration);
// Keyboard layouts configuration.
KeyboardLayout[] getKeyboardLayouts();
KeyboardLayout[] getKeyboardLayoutsForInputDevice(in InputDeviceIdentifier identifier);
KeyboardLayout getKeyboardLayout(String keyboardLayoutDescriptor);
String getCurrentKeyboardLayoutForInputDevice(in InputDeviceIdentifier identifier);
void setCurrentKeyboardLayoutForInputDevice(in InputDeviceIdentifier identifier,
String keyboardLayoutDescriptor);
String[] getEnabledKeyboardLayoutsForInputDevice(in InputDeviceIdentifier identifier);
void addKeyboardLayoutForInputDevice(in InputDeviceIdentifier identifier,
String keyboardLayoutDescriptor);
void removeKeyboardLayoutForInputDevice(in InputDeviceIdentifier identifier,
String keyboardLayoutDescriptor);
// Registers an input devices changed listener.
void registerInputDevicesChangedListener(IInputDevicesChangedListener listener);
// Queries whether the device is currently in tablet mode
int isInTabletMode();
// Registers a tablet mode change listener
void registerTabletModeChangedListener(ITabletModeChangedListener listener);
// Queries whether the device's microphone is muted by switch
int isMicMuted();
// Input device vibrator control.
void vibrate(int deviceId, in VibrationEffect effect, IBinder token);
void vibrateCombined(int deviceId, in CombinedVibration vibration, IBinder token);
void cancelVibrate(int deviceId, IBinder token);
int[] getVibratorIds(int deviceId);
boolean isVibrating(int deviceId);
boolean registerVibratorStateListener(int deviceId, in IVibratorStateListener listener);
boolean unregisterVibratorStateListener(int deviceId, in IVibratorStateListener listener);
// Input device battery query.
int getBatteryStatus(int deviceId);
int getBatteryCapacity(int deviceId);
void setPointerIconType(int typeId);
void setCustomPointerIcon(in PointerIcon icon);
oneway void requestPointerCapture(IBinder inputChannelToken, boolean enabled);
/** Create an input monitor for gestures. */
InputMonitor monitorGestureInput(String name, int displayId);
// Add a runtime association between the input port and the display port. This overrides any
// static associations.
void addPortAssociation(in String inputPort, int displayPort);
// Remove the runtime association between the input port and the display port. Any existing
// static association for the cleared input port will be restored.
void removePortAssociation(in String inputPort);
// Add a runtime association between the input device and display.
void addUniqueIdAssociation(in String inputDeviceName, in String displayUniqueId);
// Remove the runtime association between the input device and display.
void removeUniqueIdAssociation(in String inputDeviceName);
InputSensorInfo[] getSensorList(int deviceId);
boolean registerSensorListener(IInputSensorEventListener listener);
void unregisterSensorListener(IInputSensorEventListener listener);
boolean enableSensor(int deviceId, int sensorType, int samplingPeriodUs,
int maxBatchReportLatencyUs);
void disableSensor(int deviceId, int sensorType);
boolean flushSensor(int deviceId, int sensorType);
List<Light> getLights(int deviceId);
LightState getLightState(int deviceId, int lightId);
void setLightStates(int deviceId, in int[] lightIds, in LightState[] states, in IBinder token);
void openLightSession(int deviceId, String opPkg, in IBinder token);
void closeLightSession(int deviceId, in IBinder token);
}
frameworks/base/services/java/com/android/server/SystemServer.java
t.traceBegin("StartInputManagerService");
inputManager = new InputManagerService(context);
t.traceEnd();
t.traceBegin("DeviceStateManagerService");
mSystemServiceManager.startService(DeviceStateManagerService.class);
t.traceEnd();
if (!disableCameraService) {
t.traceBegin("StartCameraServiceProxy");
mSystemServiceManager.startService(CameraServiceProxy.class);
t.traceEnd();
}
t.traceBegin("StartWindowManagerService");
// WMS needs sensor service ready
mSystemServiceManager.startBootPhase(t, SystemService.PHASE_WAIT_FOR_SENSOR_SERVICE);
wm = WindowManagerService.main(context, inputManager, !mFirstBoot, mOnlyCore,
new PhoneWindowManager(), mActivityManagerService.mActivityTaskManager);
ServiceManager.addService(Context.WINDOW_SERVICE, wm, /* allowIsolated= */ false,
DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PROTO);
ServiceManager.addService(Context.INPUT_SERVICE, inputManager,
/* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL);
t.traceEnd();
1.2 客户端获取proxy
应用端获取服务
getSystemService(Context.INPUT_SERVICE))
,这里获取InputManager
初始化InputManager.getInstance()
(即是IInputManager.Stub.asInterface(ServiceManager.getServiceOrThrow(Context.INPUT_SERVICE))
)
frameworks/base/core/java/android/app/SystemServiceRegistry.java
frameworks/base/core/java/android/hardware/input/InputManager.java
/**
* Gets an instance of the input manager.
*
* @return The input manager instance.
*
* @hide
*/
@UnsupportedAppUsage
public static InputManager getInstance() {
synchronized (InputManager.class) {
if (sInstance == null) {
try {
sInstance = new InputManager(IInputManager.Stub
.asInterface(ServiceManager.getServiceOrThrow(Context.INPUT_SERVICE)));
} catch (ServiceNotFoundException e) {
throw new IllegalStateException(e);
}
}
return sInstance;
}
}
2、Native层中AIDL形式
Android 接口定义语言 (AIDL)、Android 应用层 到 HAL 层
AIDL
形式是Android中binder机制
的具体实现。按照规范aidl/hidl文件自动生成相应代码文件:
C++中客户端对应Bp端
,服务端对应Bn端
2.1 服务端对应Bn端
JNI调用到Native层,
ServiceManager
中添加"inputflinger"
对应InputManager
,InputManager继承BnInputFlinger端
,对应方法实现返回binder::Status
frameworks/native/libs/input/Android.bp
frameworks/native/libs/input/android/os/IInputFlinger.aidl
package android.os;
import android.FocusRequest;
import android.InputChannel;
import android.InputWindowInfo;
import android.os.ISetInputWindowsListener;
/** @hide */
interface IInputFlinger
{
// SurfaceFlinger is the caller of this method, it uses the listener callback to ensure the
// ordering when needed.
// SurfaceFlinger calls this only every VSync, so overflow of binder's oneway buffer
// shouldn't be a concern.
oneway void setInputWindows(in InputWindowInfo[] inputHandles,
in @nullable ISetInputWindowsListener setInputWindowsListener);
InputChannel createInputChannel(in @utf8InCpp String name);
void removeInputChannel(in IBinder connectionToken);
/**
* Sets focus to the window identified by the token. This must be called
* after updating any input window handles.
*/
oneway void setFocusedWindow(in FocusRequest request);
}
frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
NativeInputManager::NativeInputManager(jobject contextObj,
jobject serviceObj, const sp<Looper>& looper) :
mLooper(looper), mInteractive(true) {
JNIEnv* env = jniEnv();
mServiceObj = env->NewGlobalRef(serviceObj);
{
AutoMutex _l(mLock);
mLocked.systemUiLightsOut = false;
mLocked.pointerSpeed = 0;
mLocked.pointerGesturesEnabled = true;
mLocked.showTouches = false;
mLocked.pointerCapture = false;
mLocked.pointerDisplayId = ADISPLAY_ID_DEFAULT;
}
mInteractive = true;
InputManager* im = new InputManager(this, this);
mInputManager = im;
defaultServiceManager()->addService(String16("inputflinger"), im);
}
frameworks/native/services/inputflinger/InputManager.cpp
frameworks/native/services/inputflinger/InputManager.h
binder::Status setInputWindows(
const std::vector<InputWindowInfo>& handles,
const sp<ISetInputWindowsListener>& setInputWindowsListener) override;
binder::Status createInputChannel(const std::string& name, InputChannel* outChannel) override;
binder::Status removeInputChannel(const sp<IBinder>& connectionToken) override;
binder::Status setFocusedWindow(const FocusRequest&) override;
2.2 客户端对应Bp端
系统中查看在
SurfaceFlinger::bootFinished()
中有获取"inputflinger"
服务使用。
frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
void SurfaceFlinger::bootFinished() {
if (mBootFinished == true) {
ALOGE("Extra call to bootFinished");
return;
}
mBootFinished = true;
if (mStartPropertySetThread->join() != NO_ERROR) {
ALOGE("Join StartPropertySetThread failed!");
}
if (mRenderEnginePrimeCacheFuture.valid()) {
mRenderEnginePrimeCacheFuture.get();
}
const nsecs_t now = systemTime();
const nsecs_t duration = now - mBootTime;
ALOGI("Boot is finished (%ld ms)", long(ns2ms(duration)) );
mFrameTracer->initialize();
mFrameTimeline->onBootFinished();
// wait patiently for the window manager death
const String16 name("window");
mWindowManager = defaultServiceManager()->getService(name);
if (mWindowManager != 0) {
mWindowManager->linkToDeath(static_cast<IBinder::DeathRecipient*>(this));
}
// stop boot animation
// formerly we would just kill the process, but we now ask it to exit so it
// can choose where to stop the animation.
property_set("service.bootanim.exit", "1");
const int LOGTAG_SF_STOP_BOOTANIM = 60110;
LOG_EVENT_LONG(LOGTAG_SF_STOP_BOOTANIM,
ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
sp<IBinder> input(defaultServiceManager()->getService(String16("inputflinger")));
static_cast<void>(schedule([=] {
if (input == nullptr) {
ALOGE("Failed to link to input service");
} else {
mInputFlinger = interface_cast<os::IInputFlinger>(input);
}
readPersistentProperties();
mPowerAdvisor.onBootFinished();
mBootStage = BootStage::FINISHED;
if (property_get_bool("sf.debug.show_refresh_rate_overlay", false)) {
enableRefreshRateOverlay(true);
}
}));
}
void SurfaceFlinger::updateInputFlinger() {
ATRACE_CALL();
if (!mInputFlinger) {
return;
}
if (mVisibleRegionsDirty || mInputInfoChanged) {
mInputInfoChanged = false;
updateInputWindowInfo();
} else if (mInputWindowCommands.syncInputWindows) {
// If the caller requested to sync input windows, but there are no
// changes to input windows, notify immediately.
setInputWindowsFinished();
}
for (const auto& focusRequest : mInputWindowCommands.focusRequests) {
mInputFlinger->setFocusedWindow(focusRequest);
}
mInputWindowCommands.clear();
}
void SurfaceFlinger::updateInputWindowInfo() {
std::vector<InputWindowInfo> inputInfos;
mDrawingState.traverseInReverseZOrder([&](Layer* layer) {
if (!layer->needsInputInfo()) return;
sp<DisplayDevice> display;
if (enablePerWindowInputRotation()) {
for (const auto& pair : ON_MAIN_THREAD(mDisplays)) {
const auto& displayDevice = pair.second;
if (!displayDevice->getCompositionDisplay()
->belongsInOutput(layer->getLayerStack(),
layer->getPrimaryDisplayOnly())) {
continue;
}
display = displayDevice;
}
}
// When calculating the screen bounds we ignore the transparent region since it may
// result in an unwanted offset.
inputInfos.push_back(layer->fillInputInfo(display));
});
mInputFlinger->setInputWindows(inputInfos,
mInputWindowCommands.syncInputWindows ? mSetInputWindowsListener
: nullptr);
}