current position:Home>Creation and startup of inputmanagerservice
Creation and startup of inputmanagerservice
2022-01-27 03:44:51 【Big stomach porridge】
The power of analysis
Recently, I'm making face recognition products , A permanent screen rotation function is realized , This function includes the conversion of touch coordinates . so what , Another customer took a touch screen with abnormal coordinate system , Let me adjust . The adjustment of this coordinate system , In fact, I did a mapping of the coordinate system , In the driver layer, I feel very good. It can be realized , But I didn't choose to implement it in the driver layer , Instead, I want to input native Layer implementation .
In order to meet various needs in the future , I decided to start analyzing the input system . Of course , The whole input system is very complex , I must stand on the shoulders of giants , So I studied teacher Deng Fanping's << In depth understanding of Android volume 3>> Analysis of input system in . Okay , Gossip , Let's get down to business .
This analysis is based on Android 11 Code for , The path of the class used is as follows
frameworks/base/services/java/com/android/server/SystemServer.java frameworks/base/services/core/java/com/android/server/input/InputManagerService.java frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp frameworks/native/services/inputflinger/InputManager.cpp
InputManagerService It's a system Binder service , It's in system_server Start in progress
private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
// ..
// 1. establish InputManagerService service
inputManager = new InputManagerService(context);
ServiceManager.addService(Context.INPUT_SERVICE, inputManager,
/* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL);
// 2. start-up InputManagerService service
inputManager.setWindowManagerCallbacks(wm.getInputManagerCallback());
inputManager.start();
// ...
}
Copy code
Here is just a brief list InputManagerService Create and start code , Actually InputManagerService Also with WindowManagerService and DisplayManagerService There is interaction , But this is another long topic , This series of articles is not intended to analyze this interaction process .
This article will be IMS abbreviation InputManagerService.
establish IMS
So first of all IMS The creation process of
public InputManagerService(Context context) {
this.mContext = context;
// A background thread Handler
this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper());
// Read /vendor/etc/input-port-associations.xml The contents of the document
// This is a unique function of the platform , Generally, there is no such file
mStaticAssociations = loadStaticInputPortAssociations();
/** When true use the linux /dev/input/event subsystem to detect the switch changes on the headphone/microphone jack. When false use the older uevent framework. */
// The acquiescence value is false
mUseDevInputEventForAudioJack =
context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack);
Slog.i(TAG, "Initializing input manager, mUseDevInputEventForAudioJack="
+ mUseDevInputEventForAudioJack);
// initialization JNI layer ,mPtr Point to JNI Layer of NativeInputManager object
mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());
// File used to enable the double touch gesture.
// The default value is null
String doubleTouchGestureEnablePath = context.getResources().getString(
R.string.config_doubleTouchGestureEnableFile);
// null
mDoubleTouchGestureEnableFile = TextUtils.isEmpty(doubleTouchGestureEnablePath) ? null :
new File(doubleTouchGestureEnablePath);
// Provide system_server Interface is used inside the process
LocalServices.addService(InputManagerInternal.class, new LocalService());
}
Copy code
IMS Constructors , The main thing is to call nativeInit() To initialize the JNI layer , Then register the local interface , For other services to call .
Be careful ,nativeInit() There is a return value , What it returns is a pointer , So what does this pointer point to ?
static jlong nativeInit(JNIEnv* env, jclass /* clazz */, jobject serviceObj, jobject contextObj, jobject messageQueueObj) {
// Get the bottom MessageQueue
sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
if (messageQueue == nullptr) {
jniThrowRuntimeException(env, "MessageQueue is not initialized.");
return 0;
}
// establish NativeInputManager
NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,
messageQueue->getLooper());
im->incStrong(0);
// Return to point NativeInputManager Object pointer
return reinterpret_cast<jlong>(im);
}
Copy code
From the final return value, we can see ,nativeInit() Function returns a pointer , This pointer points to JNI Created by layer NativeInputManager object . therefore , Upper layer InputManagerService Member variables of long mPtr
In fact, it points to JNI Layer of NativeInputManager object .
NativeInputManager The declaration and implementation of are placed in com_android_server_input_InputManagerService.cpp in , It also reminds us NativeInputManager It's a JNI Stratoid .
establish NativeInputManager
Now let's look at NativeInputManager The creation process of
NativeInputManager::NativeInputManager(jobject contextObj,
jobject serviceObj, const sp<Looper>& looper) :
mLooper(looper), mInteractive(true) {
JNIEnv* env = jniEnv();
// 1. Save the upper layer InputManagerService object
mServiceObj = env->NewGlobalRef(serviceObj);
{
AutoMutex _l(mLock);
// 2. Initialize some parameters
// mLocked The type is struct Locked, What's the use of initializing some parameters here ?
mLocked.systemUiVisibility = ASYSTEM_UI_VISIBILITY_STATUS_BAR_VISIBLE;
mLocked.pointerSpeed = 0;
mLocked.pointerGesturesEnabled = true;
mLocked.showTouches = false;
mLocked.pointerCapture = false;
// ADISPLAY_ID_DEFAULT The value is 0, Indicates the default screen
mLocked.pointerDisplayId = ADISPLAY_ID_DEFAULT;
}
mInteractive = true;
// 2. Create and register the underlying services InputManager
mInputManager = new InputManager(this, this);
defaultServiceManager()->addService(String16("inputflinger"),
mInputManager, false);
}
Copy code
establish NativeInputManager The process is divided into three steps .
First step , Through member variables mServiceObj Pointing to the top InputManagerService object . And just , Has been used InputManagerService Member variables of mPrt Yes NativeInputManager. In this way , Upper and JNI The layers pay attention to each other , Can communicate with each other .
The second step , For a type of struct Locked The object of mLocked, Some member variables are initialized .
This struct Locked The design of the structure looks chaotic , So what role does it play ?
The third step , Created the underlying Binder service InputManager, And registered to Service Manager in . We noticed the creation of InputManager Two are used this Parameters , Let's look at the relationship diagram of these two classes
NativeInputManager Realized InputReaderPolicyInterface and InputDispatcherPolicyInterface Two interfaces , and InputManager The constructor just needs these two interfaces .
From the current analysis , We can conclude that the input system Java Layer to JNI Layer to Native Communication diagram of layer
JNI Layer of NativeInputManager It's actually a bridge , It's connected Java Layer and the Native layer .
However, this figure does not show InputManager How to communicate up , This is because this function is implemented by its sub modules , Let's look down InputManager The creation process of .
establish InputManager service
From the above code we can see that , establish InputManager The code for the object is as follows
mInputManager = new InputManager(this, this);
Copy code
Now let's look at creating InputManager Constructor for
InputManager::InputManager(
const sp<InputReaderPolicyInterface>& readerPolicy,
const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
// 1. establish InputDispatcher object , Use InputDispatcherPolicyInterface Interface
mDispatcher = createInputDispatcher(dispatcherPolicy);
// 2. establish InputClassifier object , Use InputListenerInterface
mClassifier = new InputClassifier(mDispatcher);
// 3. establish InputReader object , Use InputReaderPolicyInterface and InputListenerInterface
mReader = createInputReader(readerPolicy, mClassifier);
}
sp<InputDispatcherInterface> createInputDispatcher( const sp<InputDispatcherPolicyInterface>& policy) {
return new android::inputdispatcher::InputDispatcher(policy);
}
sp<InputReaderInterface> createInputReader(const sp<InputReaderPolicyInterface>& policy, const sp<InputListenerInterface>& listener) {
return new InputReader(std::make_unique<EventHub>(), policy, listener);
}
Copy code
Be careful , From the above analysis, we can see ,InputManager The implementation classes of the two interfaces used by the constructor are NativeInputManager. These two interfaces are not directly InputManager Used by the ,InputDispatcherPolicyInterface By InputDispatcher Used by the , and InputReaderPolicyInterface By InputReader Used by the . therefore InputReader The ability to communicate upward is determined by InputDispatcher and InputReader Realized .
InputManager Created three modules ,InputReader、InputClassifier、InputDispatcher. InputReader In charge of from EventHub Get events in , Then process the event , Send to InputClassfier.InputClassifer Will send the event to InputDispatcher, But it classifies touch events . Last InputDispatcher Distribute events to .
So now we can roughly calculate the relationship diagram of the input system , as follows
This diagram well reflects the single responsibility principle of design pattern .
EventHub In fact, it only belongs to InputReader, So to dissect the whole input system , We have to dissect them one by one InputReader、InputClassifier、InputDispatcher. The following series of articles will analyze one by one .
start-up IMS
Now I know something about the whole input system , But there seems to be something else ? The system doesn't seem to have started ? The starting point is system_server process .
// Create input system
inputManager = new InputManagerService(context);
// Start the input system
inputManager.start();
Copy code
Now let's see how the whole input system starts !
public void start() {
Slog.i(TAG, "Starting input manager");
// 1. start-up native layer
nativeStart(mPtr);
// Add ourself to the Watchdog monitors.
Watchdog.getInstance().addMonitor(this);
// 2. Monitor the database , When the value changes , adopt native layer
// monitor Settings.System.POINTER_SPEED, This represents the speed of the finger
registerPointerSpeedSettingObserver();
// monitor Settings.System.SHOW_TOUCHES, This indicates whether the touch coordinates are displayed on the screen
registerShowTouchesSettingObserver();
// monitor Settings.Secure.ACCESSIBILITY_LARGE_POINTER_ICON
registerAccessibilityLargePointerSettingObserver();
// monitor Settings.Secure.LONG_PRESS_TIMEOUT, How many milliseconds does this trigger a long press event
registerLongPressTimeoutObserver();
// Monitor user switching
mContext.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
updatePointerSpeedFromSettings();
updateShowTouchesFromSettings();
updateAccessibilityLargePointerFromSettings();
updateDeepPressStatusFromSettings("user switched");
}
}, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mHandler);
// 3. Get value from database , And pass it on to native layer
updatePointerSpeedFromSettings();
updateShowTouchesFromSettings();
updateAccessibilityLargePointerFromSettings();
updateDeepPressStatusFromSettings("just booted");
}
Copy code
InputManagerService Startup time , Will pass first nativeStart()
start-up native layer , Then read some values from the database , Pass to native layer .
Read the value from the database and pass it to native, This process is not analyzed . If you analyze the code later , Encountered these values , I'll mention it again .
Now focus your analysis on native On the start of
static void nativeStart(JNIEnv* env, jclass /* clazz */, jlong ptr) {
NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
// call InputManager::start()
status_t result = im->getInputManager()->start();
if (result) {
jniThrowRuntimeException(env, "Input manager could not be started.");
}
}
Copy code
adopt JNI Layer of NativeInputMangaer This bridge to start InputManager.
The previous picture shows NativeInputManager The bridge function of , Do you feel it now ?
status_t InputManager::start() {
// start-up Dispatcher
status_t result = mDispatcher->start();
if (result) {
ALOGE("Could not start InputDispatcher thread due to error %d.", result);
return result;
}
// start-up InputReader
result = mReader->start();
if (result) {
ALOGE("Could not start InputReader due to error %d.", result);
mDispatcher->stop();
return result;
}
return OK;
}
Copy code
because InputReader Will eventually pass the processed event to InputDispatcher, So start InputManager when , It will start first InputDisapcher, Restart InputReader.
that InputReader and InputDispatcher What did you do after startup ? Let's analyze later .
end
This paper makes a preliminary description of the creation and startup of the input system , But the function of this input system is huge , Fortunately, this function is subdivided in the source code , In this way, we can analyze the functions of each sub module one by one , So as to dissect the whole input system .
copyright notice
author[Big stomach porridge],Please bring the original link to reprint, thank you.
https://en.cdmana.com/2022/01/202201270344446819.html
The sidebar is recommended
- Spring IOC container loading process
- [thinking] the difference between singleton mode and static method - object-oriented programming
- Hadoop environment setup (MySQL environment configuration)
- 10 minutes, using node JS creates a real-time early warning system for bad weather!
- Git tool
- Force deduction algorithm - 92 Reverse linked list II
- What is the sub problem of dynamic programming?
- C / C + +: static keyword summary
- Idea does not have the artifacts option when configuring Tomcat
- Anaconda can't open it
guess what you like
-
I don't know how to start this
-
Matlab simulation of transportation optimization algorithm based on PSO
-
MySQL slow log optimization
-
[Vue] as the window is stretched (larger, smaller, wider and higher), the text will not be displayed
-
Popular Linux distributions for embedded computing
-
Suzhou computer research
-
After installing SSL Certificate in Windows + tomcat, the domain name request is not successful. Please answer!!
-
Implementation time output and greetings of jQuery instance
-
The 72 year old uncle became popular. Wu Jing and Guo fan made his story into a film, which made countless dreamers blush
-
How to save computer research
Random recommended
- Springboot implements excel import and export, which is easy to use, and poi can be thrown away
- The final examination subjects of a class are mathematical programming, and the scores are sorted and output from high to low
- Two pronged approach, Tsinghua Professor Pro code JDK and hotspot source code notes, one-time learning to understand
- C + + recursive knapsack problem
- The use of GIT and GitHub and the latest git tutorial are easy to understand -- Video notes of crazy God speaking
- PostgreSQL statement query
- Ignition database test
- Context didn't understand why he got a high salary?, Nginxfair principle
- Bootstrap switch switch control user's guide, springcloud actual combat video
- A list that contains only strings. What other search methods can be used except sequential search
- [matlab path planning] multi ant colony algorithm grid map path planning [including GUI source code 650]
- [matlab path planning] improved genetic algorithm grid map path planning [including source code phase 525]
- Iinternet network path management system
- Appium settings app is not running after 5000ms
- Reactnative foundation - 07 (background image, status bar, statusbar)
- Reactnative foundation - 04 (custom rpx)
- If you want an embedded database (H2, hsql or Derby), please put it on the classpath
- When using stm32g070 Hal library, if you want to write to flash, you must perform an erase. If you don't let it, you can't write continuously.
- Linux checks where the software is installed and what files are installed
- SQL statement fuzzy query and time interval filtering
- 69. Sqrt (x) (c + + problem solving version with vs runnable source program)
- Fresh students are about to graduate. Do you choose Java development or big data?
- Java project: OA management system (java + SSM + bootstrap + MySQL + JSP)
- Titanic passenger survival prediction
- Vectorization of deep learning formula
- Configuration and use of private image warehouse of microservice architect docker
- Relearn JavaScript events
- For someone, delete return 1 and return 0
- How does Java dynamically obtain what type of data is passed? It is used to judge whether the data is the same, dynamic data type
- How does the database cow optimize SQL?
- [data structure] chain structure of binary tree (pre order traversal) (middle order traversal) (post order traversal) (sequence traversal)
- Webpack packaging optimization solution
- 5. Operation element
- Detailed explanation of red and black trees
- redhat7. 9 install database 19C
- Blue Bridge Cup notes: (the given elements are not repeated) complete arrangement (arrangement cannot be repeated, arrangement can be repeated)
- Detailed explanation of springboot default package scanning mechanism and @ componentscan specified scanning path
- How to solve the run-time exception of test times
- Detailed explanation of k8s management tool kubectl
- Android system view memory command