Android入門之從輸入裝置中獲取訊息——視窗建立過程
上文講到訊息獲取過程,本文來詳細看程式碼。
我們說視窗建立時會建立本地的ViewRoot,然後呼叫WmS的addWindow方法,所以我們首先來看看WmS的程式碼。
你會看到frameworks/base/services/java/com/android/server/WindowManagerService.java中,沒有公開的構造子,但有一個main方法,我們推測main方法即是此類的入口(當然,網路上很多資料表明,main方法就是WmS的入口)。
main方法程式碼如下所示:
public static WindowManagerService main(Context context, PowerManagerService pm, boolean haveInputMethods) { WMThread thr = new WMThread(context, pm, haveInputMethods); thr.start(); synchronized (thr) { while (thr.mService == null) { try { thr.wait(); } catch (InterruptedException e) { } } } return thr.mService; }
建立一個WMThread,然後啟動它,WMThread定義在WindowManagerService.java裡面,它的run方法如下所示:
先忽略Looper,後面會再次描述到。public void run() { Looper.prepare(); WindowManagerService s = new WindowManagerService(mContext, mPM, mHaveInputMethods); android.os.Process.setThreadPriority( android.os.Process.THREAD_PRIORITY_DISPLAY); android.os.Process.setCanSelfBackground(false); synchronized (this) { mService = s; notifyAll(); } Looper.loop(); }
主體部分是建立一個WindowManagerService,後面是設定執行緒優先順序等,所以有必要看看WindowManagerService的構造方法做了什麼:
private WindowManagerService(Context context, PowerManagerService pm, boolean haveInputMethods) { mContext = context; mHaveInputMethods = haveInputMethods; mLimitedAlphaCompositing = context.getResources().getBoolean( com.android.internal.R.bool.config_sf_limitedAlpha); mPowerManager = pm; mPowerManager.setPolicy(mPolicy); PowerManager pmc = (PowerManager)context.getSystemService(Context.POWER_SERVICE); mScreenFrozenLock = pmc.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "SCREEN_FROZEN"); mScreenFrozenLock.setReferenceCounted(false); mActivityManager = ActivityManagerNative.getDefault(); mBatteryStats = BatteryStatsService.getService(); // Get persisted window scale setting mWindowAnimationScale = Settings.System.getFloat(context.getContentResolver(), Settings.System.WINDOW_ANIMATION_SCALE, mWindowAnimationScale); mTransitionAnimationScale = Settings.System.getFloat(context.getContentResolver(), Settings.System.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScale); // Track changes to DevicePolicyManager state so we can enable/disable keyguard. IntentFilter filter = new IntentFilter(); filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED); mContext.registerReceiver(mBroadcastReceiver, filter); mHoldingScreenWakeLock = pmc.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "KEEP_SCREEN_ON_FLAG"); mHoldingScreenWakeLock.setReferenceCounted(false); mInputManager = new InputManager(context, this); PolicyThread thr = new PolicyThread(mPolicy, this, context, pm); thr.start(); synchronized (thr) { while (!thr.mRunning) { try { thr.wait(); } catch (InterruptedException e) { } } } mInputManager.start(); // Add ourself to the Watchdog monitors. Watchdog.getInstance().addMonitor(this); }
在WindowManagerService的構造子中,建立了一個InputManager物件,並呼叫它的start()方法,我們可以淺顯地判斷InputManager是一個執行緒類,對應的構造子如下:
public InputManager(Context context, WindowManagerService windowManagerService) {
this.mContext = context;
this.mWindowManagerService = windowManagerService;
this.mCallbacks = new Callbacks();
init();
}
這裡有兩點需要注意,一是Callbacks方法,進入到Callbacks類裡面,可以看到它主要是呼叫了WindowManagerService的其他方法。另一個是init()方法,init內部呼叫了initNative()方法,跟蹤initNative()方法時你會發現它僅僅是有以下定義:
private static native void nativeInit(Callbacks callbacks);
它沒有具體的實現方法,我們知道,InputManager是Java類,它會與對應的C函式進行互動,所以我們判斷nativeInit實現上是使用JNI呼叫C函式執行操作,那怎麼找到InputManager方法對應的C函式呢?
InputManager類的全路徑是frameworks/base/services/java/com/android/server/InputManager.java,所以它對應的JNI一定是在frameworks/base/services/jni下,我們找到這個目錄,發現該目錄下有個檔名為com_android_server_InputManager.cpp,與Java檔案的路徑可以找到共同點,於是我們判斷,com_android_server_InputManager.cpp即為InputManager.java對應的C函式。
InputManager.cpp中定義了一個NativeInputManager物件,該物件有個構造子:
NativeInputManager::NativeInputManager(jobject callbacksObj) :
mFilterTouchEvents(-1), mFilterJumpyTouchEvents(-1), mVirtualKeyQuietTime(-1),
mMaxEventsPerSecond(-1),
mDisplayWidth(-1), mDisplayHeight(-1), mDisplayOrientation(ROTATION_0) {
JNIEnv* env = jniEnv();
mCallbacksObj = env->NewGlobalRef(callbacksObj);
sp<EventHub> eventHub = new EventHub();
mInputManager = new InputManager(eventHub, this, this);
}
這個構造子即對應了initNative(Callbacks callbacks)方法。
你會看到在NativeInputManager的構造子中,建立了一個InputManager物件,C程式碼不能直接呼叫Java程式碼,所以這個InputManager當然不是InputManager.java。跟到frameworks/base/libs/ui/InputManager.cpp裡面去,找到對應的InputManager物件的構造子,程式碼如下所示:
InputManager::InputManager(
const sp<EventHubInterface>& eventHub,
const sp<InputReaderPolicyInterface>& readerPolicy,
const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
mDispatcher = new InputDispatcher(dispatcherPolicy);
mReader = new InputReader(eventHub, readerPolicy, mDispatcher);
initialize();
}
或以看到,在InputManager.cpp的構造子中,建立了一個InputDispatcher物件和一個InputReader物件。接著看initialize()方法:
void InputManager::initialize() {
mReaderThread = new InputReaderThread(mReader);
mDispatcherThread = new InputDispatcherThread(mDispatcher);
}
很明顯,在initialize()方法中,分別建立了InputReader執行緒和InputDispatcher執行緒。
再返回WindowManagerService的構造子,發現其最後一行程式碼是:
Watchdog.getInstance().addMonitor(this);
再看看WindowManagerService的定義:
public class WindowManagerService extends IWindowManager.Stub
implements Watchdog.Monitor {
由此我們可以判斷,WindowManagerService事實上是一個Monitor,構造子的最後一行,是把WmS本身這個InputMonitor新增到Watchdog裡面。
再聯絡上文的視窗建立過程:
我們很容易地把程式碼與上圖關聯起來了。
相關推薦
Android入門之從輸入裝置中獲取訊息——視窗建立過程
上文講到訊息獲取過程,本文來詳細看程式碼。 我們說視窗建立時會建立本地的ViewRoot,然後呼叫WmS的addWindow方法,所以我們首先來看看WmS的程式碼。 你會看到frameworks/base/services/j
struts框架問題六之從值棧中獲取值
6. 問題六: 在JSP中獲取值棧的資料 * 總結幾個小問題: > 訪問root中資料 不需要# > 訪問context其它物件資料 加 # > 如果向root中存入物件的話,優先使用push方法。 > 如果向
c++ 從輸入流中獲取輸入
點選開啟連結 輸入流物件cin讀取輸入流的三種方式 c++ 從輸入流中獲取特定型別的資料的方式: 1、cin(以空白【空格,製表符和換行符】結束讀取) 2、cin的成員函式 getline(),用法:cin.getline()。功能:獲取一行輸入,包括空白【
Android-從音訊檔案中獲取專輯圖片
如何獲取本地音訊檔案的專輯圖片呢?不多說了,直接上程式碼吧: public static Bitmap setArtwork(Context context, String url, ImageVie
android封裝框架入門之從自定義對話方塊開始callback幫你忙
android封裝框架入門之從封裝確定、取消對話方塊開始 最近,封裝了一個輕量級的網路非同步網路請求框架MHttpUtils(傳送門),由於非常喜歡RxJava和Retrofit等的鏈式程式設計風格,於是自己搗鼓著按這種風格來封裝,期間的一些封裝思路抽取出
android 如何從系統相簿中獲取圖片
http://bbs.csdn.net/topics/390133207 需要在專案中加入一個從系統相簿中選取圖片的功能,選擇的圖片bitmap顯示出來即可,不需要圖片剪下功能網上的例子很多,我用的以下程式碼實現的Intent intent=new Intent(Inten
Android開發之--從app中跳轉到淘寶店鋪
首先、一個工具類 方法,檢測該包名下的應用是否存在 public static boolean checkPackage(Context context ,String packageName) { if (packageName == null || "".
Cocos2d-x3.0 從代碼中獲取cocostudio編輯的UI控件
ucid 編輯 top ica sans sce nero val -i 依據名字查找控件 須要包括的頭文件及名字空間: #include "cocostudio/CocoStudio.h"#include "ui/CocosGUI.h"using namespac
從package.json中獲取屬性
pack tps .json over href from version span package var pjson = require(‘./package.json‘); console.log(pjson.version); 詳見:https://stack
Android入門之文件系統操作(二)文件操作相關指令
-h tools strong abc his art 為什麽 重命名 path (一)獲取總根 [java] view plain copy File[] fileList=File.listRoots(); //返回fileList.length為1 /
volley6--CacheDispatcher從緩存中獲取數據
splay nbsp anti without .post getc rri software req 源碼: 1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 *
volley7--NetworkDispatcher從網絡中獲取數據
ota ria ould min over med unless col call 源碼: 1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed u
[轉]使用@Test 也可以從spring容器中獲取依賴註入
oca fig article ring1 detail ice 如果 text resource 轉自:http://blog.csdn.net/u010987379/article/details/52091790 @RunWith(SpringJUnit4Cla
Elasticsearch入門之從零開始安裝ik分詞器
gpo article terms n) rm -rf 從零開始 系列 pack 默認 起因 需要在ES中使用聚合進行統計分析,但是聚合字段值為中文,ES的默認分詞器對於中文支持非常不友好:會把完整的中文詞語拆分為一系列獨立的漢字進行聚合,顯然這並不是我的初衷。我們來看個
postman實現從response headers中獲取cookie,並將其設置為環境變量
png header 參數 ESS 數組 字段 分割 src 圖片 1.最近在學習postman的使用方法,為了保證後續模塊操作,必須在登錄時獲取的session值,並將其設置為環境變量,session的位置處於response headers裏面返回的set-cookie
php 從指定數字中獲取隨機組合的方法
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!  
js方法從json物件中獲取特定值
//從json中獲得key指定值 function getJsonValue(obj,name){ var result = null; var v
從資料夾中獲取指定檔案的檔名
從資料夾中獲取指定檔案的檔名 有時候我們需要從資料夾中判斷一個指定的檔案是否存在,如果存在就返回檔名+字尾名,不存在返回空。前臺可以根據此判斷選擇性的進行圖片的展示情況。 前臺請求獲取響應的檔名 1.配置檔案內:配置路徑資訊 #圖片儲存路徑 本地磁碟C 下面的"XX資料夾"
Jmeter使用Beanshell前處理器從指定列表中獲取隨機值
變數mynation從列表{"china","US","UK"}中隨機取值 String[] nation = new String[]{"china","US","UK"}; Random random = new Random(); int i = random.nexInt(nation.le
JAVA WEB快速入門之從編寫一個JSP WEB網站了解JSP WEB網站的基本結構、除錯、部署
接上篇《JAVA WEB快速入門之環境搭建》,在完成了環境搭建後(JDK、Tomcat、IDE),現在是萬事具備,就差寫程式碼了,今天就來從編寫一個JSP WEB網站了解JSP WEB網站的基本結構、除錯、部署,至於為什麼要先寫JSP WEB,而不是直接上SSM(Spring、SpringMVC、Mybati