在Android 2.3(Gingerbread) 系統的時候,我寫過一篇關於“Android 震動馬達系統“的文章,當時的Linux內核還是2.6版本的。寫那篇文章的目的,是想徹底的了解從硬件到驅動,再到應用的運作流程。完成了之后,文章一直仍在草稿箱里面沒發表;今天看到,決定整理一下,重新發表。目的是想和大家分享自己對Android系統的一點認識:以馬達為代表,來考究“Android是如何一步步工作的。它從硬件設計,到Linux驅動,再到HAL,再到JNI,再到Framework,最后到被應用調用,這整套的流程到底是怎么樣的!”
轉載請注明出處:http://www.cnblogs.com/skywang12345/p/3404808.html
Part 1 馬達的硬件設計
馬達的震動原理很簡單,給馬達通電,馬達就能震動。至於馬達是如何工作,如何將電能轉化為機械能,這不是我們關心的重點。但是,我們要需要了解如何控制馬達的通電。在硬件上,我們是通過一個IO口(GPIO)去控制;對於馬達而言,我們可以將IO理解為一個開關。當開關合上時,馬達震動;開關斷開,馬達停止震動。
GPIO(General Purpose Input Output),稱為通用輸入/輸出。它可以被配置為中斷、輸入、輸出等類型,從而對各個IO進行控制。對於馬達而已,GPIO就相當於一個開關。下面看看硬件原理圖中的馬達部分,如下圖:
注:上面原理圖對應CPU是“三星A8”。不同平台的馬達,馬達的接法和GPIO都不一樣;但原理都是類似的。
原理圖中紅線標注部分的含義:GPH3_3是馬達的GPIO。三星A8中有很多組GPIO,而馬達對應和GPH3_3連接。
Part 2 馬達的驅動代碼
知道馬達的硬件設計之后,我們就可以進行Linux Driver開發工作,也就是編寫馬達的驅動。Linux的一個非常重要的特點,一切都是文件!而我們進行Linux Driver開發的目的,就是將硬件設備映射成一個文件;然后,我們可以通過操作文件,來操作對應的硬件設備。
OK!理解了驅動的作用和原理之后,我們接下來開發講解馬達的驅動開發。
1. Datasheet中相關信息
我們知道,馬達是通過GPIO去控制;接下來,我們就是找到馬達對應的GPIO信息,然后控制該GPIO即可。
通過馬達的原理圖,我們知道馬達和GPH3_3相連接。我們查閱“三星A8 的Datasheet”,查找GPH3_3的相關信息。
所謂Datasheet,就是CPU芯片的數據手冊。 上面記載了CPU的功能特性和操作方式等信息。任何一個廠家在發布它的芯片時,都會提供對應的Datasheet給它的客戶;客戶根據Datasheet上面所描述的CPU的特性,就可以進行相關的開發(當然,實際開發中可能還需要芯片廠商的支持)。例如,國內手機都是采用MTK平台,對於MTK方案開發商來說,它要開發MTK6577的產品。那么首先,MTK原廠會提供一份MTK6577的BSP包,BSP包中包括了MTK6577的Datasheet,也就是該芯片的數據手冊。方案開發商有任何關於MTK6577的問題,都可以查閱該Datasheet。
說明:
(01) GPH3_3對應CPU中的寄存器是GPH3CON[3]。
(02) [15:12] 表示寄存器的第12~15位,一個寄存器共32 bits。而第三列的 0000, 0001, 0010, 0011, 1111表示“寄存器取不同值的時候,該GPIO的功能”。
例如, 0000表示將該GPIO作為輸入,0001表示將GPIO作為輸出,1111表示將該GPIO作為中斷。
前面,我們已經說過,操作馬達就是相當與將它作為一個開關操作。因此,我們需要將馬達的GPIO設為“輸入”類型;然后輸入1,相當於開啟馬達;輸入0,則是關閉馬達!
下面,我們需要做的就是在Driver中將GPH3_3(也就是GPH3CON[3])映射為一個文件節點,並將它配置為“輸入”類型,即將GPH3CON[3]的寄存器值設為0000。
2. 馬達的驅動
我們編寫馬達驅動(drivers/misc/misc_sysfs.c),將馬達(vibrator)注冊道platform總線上。源碼如下:
1 #include <linux/kernel.h> 2 #include <linux/types.h> 3 #include <linux/module.h> 4 #include <linux/device.h> 5 #include <linux/platform_device.h> 6 #include <linux/delay.h> 7 #include <linux/irq.h> 8 #include <linux/interrupt.h> 9 #include <linux/sysfs.h> 10 #include <linux/input.h> 11 #include <mach/gpio.h> 12 13 // vibrator 對應的GPIO 14 #define VIBRATOR_POWER_PORT (S5PV210_GPH3(3)) 15 16 typedef struct combo_module__t { 17 unsigned char status_vibrator; 18 } combo_module_t ; 19 20 static combo_module_t combo_module; 21 22 /* 23 * vibrator初始化函數:申請GPIO,並初始化vibrator狀態。 24 */ 25 static void combo_module_init(void) 26 { 27 if(gpio_request(VIBRATOR_POWER_PORT, "vibrator power")) { 28 printk("misc_sysfs.c request vibrator gpio failse.\n"); 29 } 30 gpio_pull_updown(VIBRATOR_POWER_PORT, PullDisable); 31 gpio_direction_output(VIBRATOR_POWER_PORT, GPIO_LOW); 32 33 combo_module.status_vibrator = 0; 34 } 35 36 /* 37 * vibrator控制函數 38 */ 39 staticvoid combo_module_control(void) 40 { 41 if(combo_module.status_vibrator) 42 { 43 gpio_direction_output(VIBRATOR_POWER_PORT, GPIO_HIGH); 44 } 45 else 46 { 47 gpio_direction_output(VIBRATOR_POWER_PORT, GPIO_LOW); 48 } 49 50 } 51 52 53 /////////////////////////////////////////////////////////////////////////////////////////////////////////// 54 55 static ssize_t show_vibrator_onoff (struct device *dev, struct device_attribute *attr, char *buf) 56 { 57 return sprintf(buf, "%d\n", combo_module.status_vibrator); 58 } 59 60 static ssize_t set_vibrator_onoff (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) 61 { 62 unsigned int val; 63 64 if(!(sscanf(buf, "%u\n", &val))) return -EINVAL; 65 66 //printk("set_vibrator_onoff:%d\n",val); 67 68 if(!val ) 69 { 70 combo_module.status_vibrator = 0; 71 combo_module_control(); 72 } 73 else 74 { 75 combo_module.status_vibrator = 1; 76 combo_module_control(); 77 78 msleep(val); 79 80 combo_module.status_vibrator = 0; 81 combo_module_control(); 82 } 83 84 return count; 85 } 86 87 static ssize_t show_vibrator_onoff (struct device *dev, struct device_attribute *attr, char *buf); 88 static ssize_t set_vibrator_onoff (struct device *dev, struct device_attribute *attr, const char *buf, size_t count); 89 // 將vibrator注冊到sysfs文件系統。 90 // 參數說明: 91 // vibrator_onoff : vibrator對應在sysfs下的文件節點名稱 92 // S_IRWXUGO : 文件節點的屬性 93 // show_vibrator_onoff : 對應的讀函數 94 // set_vibrator_onoff : 對應的寫函數 95 static DEVICE_ATTR(vibrator_onoff, S_IRWXUGO, show_vibrator_onoff, set_vibrator_onoff); 96 97 98 static struct attribute *control_sysfs_entries[] = { 99 &dev_attr_vibrator_onoff.attr, 100 NULL 101 }; 102 103 static struct attribute_group control_sysfs_attr_group = { 104 .name = NULL, 105 .attrs = control_sysfs_entries, 106 }; 107 108 static int control_sysfs_probe(struct platform_device *pdev) 109 { 110 printk("vibrator probe"); 111 combo_module_init(); 112 combo_module_control(); 113 return sysfs_create_group(&pdev->dev.kobj, &control_sysfs_attr_group); 114 } 115 116 staticint control_sysfs_remove(struct platform_device *pdev) 117 { 118 sysfs_remove_group(&pdev->dev.kobj, &control_sysfs_attr_group); 119 120 return 0; 121 } 122 123 #ifdef CONFIG_PM 124 static int control_sysfs_resume(struct platform_device *dev) 125 { 126 127 combo_module_control(); 128 129 return 0; 130 } 131 132 static int control_sysfs_suspend(struct platform_device *dev, pm_message_t state) 133 { 134 135 combo_module_control(); 136 137 return 0; 138 } 139 #else 140 #define control_sysfs_suspend NULL 141 #define control_sysfs_resume NULL 142 #endif 143 144 145 static struct platform_driver control_sysfs_driver = { 146 .driver = { 147 .name = "misc_ctl", 148 .owner = THIS_MODULE, 149 }, 150 .probe = control_sysfs_probe, 151 .remove = control_sysfs_remove, 152 .suspend = control_sysfs_suspend, 153 .resume = control_sysfs_resume, 154 }; 155 156 static int __init control_sysfs_init(void) 157 { 158 // 將vibrator注冊到platform總線 159 printk("vibrator init"); 160 return platform_driver_register(&control_sysfs_driver); 161 } 162 163 static void __exit control_sysfs_exit(void) 164 { 165 platform_driver_unregister(&control_sysfs_driver); 166 } 167 168 169 module_init(control_sysfs_init); 170 module_exit(control_sysfs_exit); 171 172 173 MODULE_DESCRIPTION("misc control driver"); 174 MODULE_AUTHOR("other"); 175 MODULE_LICENSE("GPL");
說明:
若您熟悉驅動開發,應該很容易理解上面的代碼。不熟悉也不要緊,您只需要了解“Linux系統中,一切都是文件”,上面代碼的作用是,
將馬達(vibrator)映射到“/sys/devices/platform/misc_ctl/vibrator_onoff”文件上,我們可以通過讀寫vibrator_onoff來操作馬達的開啟和關閉。
有了馬達的源碼之后,我們還需要將該源碼編譯到Linux內核中。這就是通過Kconfig和Makefile來完成的,關於Kconfig和Makefile的知識,這里就不過多說明了。目前您只需要了解,通過Kconfig和Makefile,我們能將馬達驅動編譯到內核中,該驅動會在驅動加載的時候自動運行就可以了!
馬達對應的Kconfig(driver/misc/Kconfig)內容如下:
config MISC_VIBRATOR
tristate"misc vabrator"
default y
馬達對應的Makefile(driver/misc/Makefile)內容如下:
obj-$(CONFIG_MISC_VIBRATOR) += misc_sysfs.o
至此,我們已經完成馬達的驅動開發了!也就是說,我們已經成功的將馬達映射到文件節點上;接下來,我們通過操作文件節點,就可以操作馬達了。下面從HAL層到Framework曾,都是基於Android4.2系統進行說明的。
Part 3 馬達的HAL實現
HAL (Hardware Abstraction Layer), 又稱為“硬件抽象層”。在Linux驅動中,我們已經將馬達設為映射為文件了;而該HAL層的存在的意義,就是“對設備文件進行操作,從而相當於硬件進行操作”。HAL層的作用,一是操作硬件設備,二是操作接口封裝,外界能方便的使用HAL提供的接口直接操作硬件設備。
理解了HAL之后,我們看看Android中如何在HAL層對馬達進行操作。
在Android系統中,我們在libhardware_legacy中,實現馬達的HAL層控制。
馬達在HAL中的代碼路徑:hardware/libhardware_legacy/vibrator/vibrator.c
vibrator.c的代碼如下:
1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 #include <hardware_legacy/vibrator.h> 17 #include "qemu.h" 18 19 #include <stdio.h> 20 #include <unistd.h> 21 #include <fcntl.h> 22 #include <errno.h> 23 24 #define THE_DEVICE "/sys/devices/platform/misc_ctl/vibrator_onoff" 25 26 int vibrator_exists() 27 { 28 int fd; 29 30 #ifdef QEMU_HARDWARE 31 if (qemu_check()) { 32 return 1; 33 } 34 #endif 35 36 fd = open(THE_DEVICE, O_RDWR); 37 if(fd < 0) 38 return 0; 39 close(fd); 40 return 1; 41 } 42 43 static int sendit(int timeout_ms) 44 { 45 int nwr, ret, fd; 46 char value[20]; 47 48 #ifdef QEMU_HARDWARE 49 if (qemu_check()) { 50 return qemu_control_command( "vibrator:%d", timeout_ms ); 51 } 52 #endif 53 54 fd = open(THE_DEVICE, O_RDWR); 55 if(fd < 0) 56 return errno; 57 58 nwr = sprintf(value, "%d\n", timeout_ms); 59 ret = write(fd, value, nwr); 60 61 close(fd); 62 63 return (ret == nwr) ? 0 : -1; 64 } 65 66 int vibrator_on(int timeout_ms) 67 { 68 /* constant on, up to maximum allowed time */ 69 return sendit(timeout_ms); 70 } 71 72 int vibrator_off() 73 { 74 return sendit(0); 75 }
在kernel的驅動中,我們已經將馬達注冊到sys文件系統中(/sys/devices/platform/misc_ctl/vibrator_onoff)。在vibrator.c中,我們就是通過讀寫“vibrator_onoff文件節點”來實現對馬達的操作。
Part 4 馬達的JNI部分
1 馬達的JNI實現
JNI(Java Native Interface),中文是“Java本地接口”。
JNI是Java中一種技術,它存在的意義,是保證本地代碼(C/C++代碼)能在任何Java虛擬機下工作。簡單點說,Java通過JNI接口,能夠調用到C/C++代碼。 關於“JNI的更多內容”,請參考“Android JNI和NDK學習系列文章”。
在了解了vibrator的HAL層實現之后,我們再來看看android是如何通過JNI將震動馬達注冊到android系統中。馬達對應的JNI層代碼路徑如下:frameworks/base/services/jni/com_android_server_VibratorService.cpp
com_android_server_VibratorService.cpp的源碼如下:
1 /* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #define LOG_TAG "VibratorService" 18 19 #include "jni.h" 20 #include "JNIHelp.h" 21 #include "android_runtime/AndroidRuntime.h" 22 23 #include <utils/misc.h> 24 #include <utils/Log.h> 25 #include <hardware_legacy/vibrator.h> 26 27 #include <stdio.h> 28 29 namespace android 30 { 31 32 static jboolean vibratorExists(JNIEnv *env, jobject clazz) 33 { 34 return vibrator_exists() > 0 ? JNI_TRUE : JNI_FALSE; 35 } 36 37 static void vibratorOn(JNIEnv *env, jobject clazz, jlong timeout_ms) 38 { 39 // ALOGI("vibratorOn\n"); 40 vibrator_on(timeout_ms); 41 } 42 43 static void vibratorOff(JNIEnv *env, jobject clazz) 44 { 45 // ALOGI("vibratorOff\n"); 46 vibrator_off(); 47 } 48 49 static JNINativeMethod method_table[] = { 50 { "vibratorExists", "()Z", (void*)vibratorExists }, 51 { "vibratorOn", "(J)V", (void*)vibratorOn }, 52 { "vibratorOff", "()V", (void*)vibratorOff } 53 }; 54 55 int register_android_server_VibratorService(JNIEnv *env) 56 { 57 return jniRegisterNativeMethods(env, "com/android/server/VibratorService", 58 method_table, NELEM(method_table)); 59 } 60 61 };
下面,對這部分的JNI代碼進行簡單說明。
(01) 通過 jniRegisterNativeMethods(),我們將method_table中的方法注冊到 com.android.server.VibratorService.java 中。配對表格如下:
---------------------------------------------------++++------------------------------------------- VibratorService.java com_android_server_VibratorService.cpp native static boolean vibratorExists(); static jboolean vibratorExists(JNIEnv *env, jobject clazz) native static void vibratorOn(long milliseconds); static void vibratorOn(JNIEnv *env, jobject clazz, jlong timeout_ms) native static void vibratorOff(); static void vibratorOff(JNIEnv *env, jobject clazz)
通過JNI,我們就能將Java層和HAL層的代碼聯系起來。
以vibratorOff()來說,我們在VibratorService.java中調用vibratorOff();實際上會調用到com_android_server_VibratorService.cpp中的vibratorOff()函數;進一步會調用到vibrator_off()函數,而vibrator_off()是我們在 “HAL層的vibrator.c中的接口”。
2 馬達的JNI如何和HAL關聯方式
在繼續接下來的研究之前,我們先搞清楚:JNI如何和HAL層代碼關聯起來的。即com_android_server_VibratorService.cpp是如何調用到vibrator.c中的代碼的。
實際上道理很簡單,我們先將vibrator.c封裝成.so庫;然后在com_android_server_VibratorService.cpp中導入該庫,就可以調用vibrator.c的接口了。下面,看看Android中具體是如何做到的。
(01) vibrator.c封裝到libhardware_legacy.so中的步驟
在hardware/libhardware_legacy/vibrator/Android.mk中,會將vibrator.c添加到 LOCAL_SRC_FILES 變量中。
hardware/libhardware_legacy/vibrator/Android.mk源碼如下:
LOCAL_SRC_FILES += vibrator/vibrator.c
在hardware/libhardware_legacy/Android.mk中,它會調用子目錄的Android.mk並將它們導入當前的Android.mk中。
hardware/libhardware_legacy/Android.mk源碼如下:
legacy_modules := power uevent vibrator wifi qemu qemu_tracing SAVE_MAKEFILES := $(call all-named-subdir-makefiles,$(legacy_modules)) LEGACY_AUDIO_MAKEFILES := $(call all-named-subdir-makefiles,audio) include $(SAVE_MAKEFILES) ... LOCAL_MODULE:= libhardware_legacy include $(BUILD_SHARED_LIBRARY)
在“我們編譯Android系統”或“通過 mmm hardware/libhardware_legacy進行模塊編譯”的時候,就會生成庫libhardware_legacy.so;而且vibrator.c被包含在該庫中。
(02) 在 com_android_server_VibratorService.cpp 對應的Android.mk中,會導入libhardware_legacy.so。
com_android_server_VibratorService.cpp 對應的frameworks/base/services/jni/Android.mk 的源碼如下:
LOCAL_SRC_FILES:= \
com_android_server_VibratorService.cpp \
...
LOCAL_SHARED_LIBRARIES := \
libhardware_legacy \
...
LOCAL_MODULE:= libandroid_servers
include $(BUILD_SHARED_LIBRARY)
Part 5 馬達的Framework層實現
應用層操作馬達,是通過馬達服務進行操作的。而馬達服務是通過aidl實現的,aidl是Android進程間的通信方式。關於aidl的更多說明可以參考“Android Service總結06 之AIDL”。
馬達服務涉及的主要文件如下:
1 frameworks/base/services/java/com/android/server/SystemServer.java 2 frameworks/base/services/java/com/android/server/VibratorService.java 3 frameworks/base/core/java/android/os/IVibratorService.aidl 4 frameworks/base/core/java/android/os/Vibrator.java 5 frameworks/base/core/java/android/os/SystemVibrator.java
下面,對這幾個文件的功能進行簡要說明。
文件1: SystemServer.java
它是系統服務,作用是啟動、管理系統服務,包括“馬達服務、Wifi服務、Activity管理服務”等等。
SystemServer是通過Zygote啟動的,而Zygote又是在init中啟動的,init則是kernel加載完畢之后啟動的第一個進程。在這里,我們只需要知道“SystemServer是用來啟動/管理馬達服務即可。”
文件2: IVibratorService.aidl
它是馬達服務對應的aidl配置文件。我們在aidl中定義了其它進程可以訪問的外部接口;然后再通過VibratorService.java實現這些接口。
文件3: VibratorService.java
它是馬達服務對應的aidl接口的實現程序。它實現IVibratorService.aidl的接口,從而實現馬達服務;它的函數接口,是通過調用JNI層對應的馬達控制函數來實現的。
文件4: Vibrator.java
它是馬達服務開放給應用層的調用類。理論上講,我們完全可以通過aidl直接調用馬達服務,而不需要Vibrator.java類。但是!既然它存在,就肯定有它的理由。事實的確如此,Google之所以這么做。有以下幾個原因:
第一,提供統一而且方便的服務調用方式。這里的“統一”,是指和所有其它的系統服務一樣,我們調用服務時,需先通過getSystemService()獲取服務,然后再調用服務的函數接口。這里的“方便”,是指若我們直接通過aidl調用,操作比較繁瑣(若你用過aidl就會知道,需要先實現ServiceConnection接口以獲取IBinder對象,然后再通過IBinder對象調用aidl的接口); 而Vibrator.java封裝之后的接口,將許多細節都隱藏了,非常便於應用者調用!
第二,基於安全的考慮。Vibrator.java封裝隱藏了許多細節,而這些都是應用開發者不必要知道的。
第三,Vibrator是抽象類。它便於我們支持不同類型的馬達:包括“將馬達直接映射到文件”以及“將馬達注冊到輸入子系統”中。
文件5: SystemVibrator.java
它是Vibrator.java的子類,實現了馬達的服務接口。
下面,我們繼續Read The Fucking Source Code,加深對上面知識的理解。
1 SystemServer.java
在frameworks/base/services/java/com/android/server/SystemServer.java中關於馬達的代碼如下:
1 { 2 VibratorService vibrator = null; 3 4 Slog.i(TAG, "Vibrator Service"); 5 vibrator = new VibratorService(context); 6 ServiceManager.addService("vibrator", vibrator); 7 8 ... 9 10 try { 11 vibrator.systemReady(); 12 } catch (Throwable e) { 13 reportWtf("making Vibrator Service ready", e); 14 } 15 }
從中,我們知道:
(01) SystemServer中會通過VibratorService()新建馬達服務,並將其添加到ServiceManager中。
(02) 在Android系統啟動完成之后,SystemServer會調用vibrator.systemReady()。
2 IVibratorService.aidl
在查看VibratorService.java之前,我們先看看它對應的aidl文件。frameworks/base/core/java/android/os/IVibratorService.aidl源碼如下:
1 package android.os; 2 3 /** {@hide} */ 4 interface IVibratorService 5 { 6 boolean hasVibrator(); 7 void vibrate(long milliseconds, IBinder token); 8 void vibratePattern(in long[] pattern, int repeat, IBinder token); 9 void cancelVibrate(IBinder token); 10 }
3 VibratorService.java
frameworks/base/services/java/com/android/server/VibratorService.java源碼如下:
1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server; 18 19 import android.content.BroadcastReceiver; 20 import android.content.Context; 21 import android.content.Intent; 22 import android.content.IntentFilter; 23 import android.content.pm.PackageManager; 24 import android.database.ContentObserver; 25 import android.hardware.input.InputManager; 26 import android.os.Handler; 27 import android.os.IVibratorService; 28 import android.os.PowerManager; 29 import android.os.Process; 30 import android.os.RemoteException; 31 import android.os.IBinder; 32 import android.os.Binder; 33 import android.os.SystemClock; 34 import android.os.UserHandle; 35 import android.os.Vibrator; 36 import android.os.WorkSource; 37 import android.provider.Settings; 38 import android.provider.Settings.SettingNotFoundException; 39 import android.util.Slog; 40 import android.view.InputDevice; 41 42 import java.util.ArrayList; 43 import java.util.LinkedList; 44 import java.util.ListIterator; 45 46 public class VibratorService extends IVibratorService.Stub 47 implements InputManager.InputDeviceListener { 48 private static final String TAG = "VibratorService"; 49 50 private final LinkedList<Vibration> mVibrations; 51 private Vibration mCurrentVibration; 52 private final WorkSource mTmpWorkSource = new WorkSource(); 53 private final Handler mH = new Handler(); 54 55 private final Context mContext; 56 private final PowerManager.WakeLock mWakeLock; 57 private InputManager mIm; 58 59 volatile VibrateThread mThread; 60 61 // mInputDeviceVibrators lock should be acquired after mVibrations lock, if both are 62 // to be acquired 63 private final ArrayList<Vibrator> mInputDeviceVibrators = new ArrayList<Vibrator>(); 64 private boolean mVibrateInputDevicesSetting; // guarded by mInputDeviceVibrators 65 private boolean mInputDeviceListenerRegistered; // guarded by mInputDeviceVibrators 66 67 native static boolean vibratorExists(); 68 native static void vibratorOn(long milliseconds); 69 native static void vibratorOff(); 70 71 private class Vibration implements IBinder.DeathRecipient { 72 private final IBinder mToken; 73 private final long mTimeout; 74 private final long mStartTime; 75 private final long[] mPattern; 76 private final int mRepeat; 77 private final int mUid; 78 79 Vibration(IBinder token, long millis, int uid) { 80 this(token, millis, null, 0, uid); 81 } 82 83 Vibration(IBinder token, long[] pattern, int repeat, int uid) { 84 this(token, 0, pattern, repeat, uid); 85 } 86 87 private Vibration(IBinder token, long millis, long[] pattern, 88 int repeat, int uid) { 89 mToken = token; 90 mTimeout = millis; 91 mStartTime = SystemClock.uptimeMillis(); 92 mPattern = pattern; 93 mRepeat = repeat; 94 mUid = uid; 95 } 96 97 public void binderDied() { 98 synchronized (mVibrations) { 99 mVibrations.remove(this); 100 if (this == mCurrentVibration) { 101 doCancelVibrateLocked(); 102 startNextVibrationLocked(); 103 } 104 } 105 } 106 107 public boolean hasLongerTimeout(long millis) { 108 if (mTimeout == 0) { 109 // This is a pattern, return false to play the simple 110 // vibration. 111 return false; 112 } 113 if ((mStartTime + mTimeout) 114 < (SystemClock.uptimeMillis() + millis)) { 115 // If this vibration will end before the time passed in, let 116 // the new vibration play. 117 return false; 118 } 119 return true; 120 } 121 } 122 123 VibratorService(Context context) { 124 // Reset the hardware to a default state, in case this is a runtime 125 // restart instead of a fresh boot. 126 vibratorOff(); 127 128 mContext = context; 129 PowerManager pm = (PowerManager)context.getSystemService( 130 Context.POWER_SERVICE); 131 mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*vibrator*"); 132 mWakeLock.setReferenceCounted(true); 133 134 mVibrations = new LinkedList<Vibration>(); 135 136 IntentFilter filter = new IntentFilter(); 137 filter.addAction(Intent.ACTION_SCREEN_OFF); 138 context.registerReceiver(mIntentReceiver, filter); 139 } 140 141 public void systemReady() { 142 mIm = (InputManager)mContext.getSystemService(Context.INPUT_SERVICE); 143 144 mContext.getContentResolver().registerContentObserver( 145 Settings.System.getUriFor(Settings.System.VIBRATE_INPUT_DEVICES), true, 146 new ContentObserver(mH) { 147 @Override 148 public void onChange(boolean selfChange) { 149 updateInputDeviceVibrators(); 150 } 151 }, UserHandle.USER_ALL); 152 153 mContext.registerReceiver(new BroadcastReceiver() { 154 @Override 155 public void onReceive(Context context, Intent intent) { 156 updateInputDeviceVibrators(); 157 } 158 }, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mH); 159 160 updateInputDeviceVibrators(); 161 } 162 163 public boolean hasVibrator() { 164 return doVibratorExists(); 165 } 166 167 public void vibrate(long milliseconds, IBinder token) { 168 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.VIBRATE) 169 != PackageManager.PERMISSION_GRANTED) { 170 throw new SecurityException("Requires VIBRATE permission"); 171 } 172 int uid = Binder.getCallingUid(); 173 // We're running in the system server so we cannot crash. Check for a 174 // timeout of 0 or negative. This will ensure that a vibration has 175 // either a timeout of > 0 or a non-null pattern. 176 if (milliseconds <= 0 || (mCurrentVibration != null 177 && mCurrentVibration.hasLongerTimeout(milliseconds))) { 178 // Ignore this vibration since the current vibration will play for 179 // longer than milliseconds. 180 return; 181 } 182 183 Vibration vib = new Vibration(token, milliseconds, uid); 184 synchronized (mVibrations) { 185 removeVibrationLocked(token); 186 doCancelVibrateLocked(); 187 mCurrentVibration = vib; 188 startVibrationLocked(vib); 189 } 190 } 191 192 private boolean isAll0(long[] pattern) { 193 int N = pattern.length; 194 for (int i = 0; i < N; i++) { 195 if (pattern[i] != 0) { 196 return false; 197 } 198 } 199 return true; 200 } 201 202 public void vibratePattern(long[] pattern, int repeat, IBinder token) { 203 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.VIBRATE) 204 != PackageManager.PERMISSION_GRANTED) { 205 throw new SecurityException("Requires VIBRATE permission"); 206 } 207 int uid = Binder.getCallingUid(); 208 // so wakelock calls will succeed 209 long identity = Binder.clearCallingIdentity(); 210 try { 211 if (false) { 212 String s = ""; 213 int N = pattern.length; 214 for (int i=0; i<N; i++) { 215 s += " " + pattern[i]; 216 } 217 Slog.i(TAG, "vibrating with pattern: " + s); 218 } 219 220 // we're running in the server so we can't fail 221 if (pattern == null || pattern.length == 0 222 || isAll0(pattern) 223 || repeat >= pattern.length || token == null) { 224 return; 225 } 226 227 Vibration vib = new Vibration(token, pattern, repeat, uid); 228 try { 229 token.linkToDeath(vib, 0); 230 } catch (RemoteException e) { 231 return; 232 } 233 234 synchronized (mVibrations) { 235 removeVibrationLocked(token); 236 doCancelVibrateLocked(); 237 if (repeat >= 0) { 238 mVibrations.addFirst(vib); 239 startNextVibrationLocked(); 240 } else { 241 // A negative repeat means that this pattern is not meant 242 // to repeat. Treat it like a simple vibration. 243 mCurrentVibration = vib; 244 startVibrationLocked(vib); 245 } 246 } 247 } 248 finally { 249 Binder.restoreCallingIdentity(identity); 250 } 251 } 252 253 public void cancelVibrate(IBinder token) { 254 mContext.enforceCallingOrSelfPermission( 255 android.Manifest.permission.VIBRATE, 256 "cancelVibrate"); 257 258 // so wakelock calls will succeed 259 long identity = Binder.clearCallingIdentity(); 260 try { 261 synchronized (mVibrations) { 262 final Vibration vib = removeVibrationLocked(token); 263 if (vib == mCurrentVibration) { 264 doCancelVibrateLocked(); 265 startNextVibrationLocked(); 266 } 267 } 268 } 269 finally { 270 Binder.restoreCallingIdentity(identity); 271 } 272 } 273 274 private final Runnable mVibrationRunnable = new Runnable() { 275 public void run() { 276 synchronized (mVibrations) { 277 doCancelVibrateLocked(); 278 startNextVibrationLocked(); 279 } 280 } 281 }; 282 283 // Lock held on mVibrations 284 private void doCancelVibrateLocked() { 285 if (mThread != null) { 286 synchronized (mThread) { 287 mThread.mDone = true; 288 mThread.notify(); 289 } 290 mThread = null; 291 } 292 doVibratorOff(); 293 mH.removeCallbacks(mVibrationRunnable); 294 } 295 296 // Lock held on mVibrations 297 private void startNextVibrationLocked() { 298 if (mVibrations.size() <= 0) { 299 mCurrentVibration = null; 300 return; 301 } 302 mCurrentVibration = mVibrations.getFirst(); 303 startVibrationLocked(mCurrentVibration); 304 } 305 306 // Lock held on mVibrations 307 private void startVibrationLocked(final Vibration vib) { 308 if (vib.mTimeout != 0) { 309 doVibratorOn(vib.mTimeout); 310 mH.postDelayed(mVibrationRunnable, vib.mTimeout); 311 } else { 312 // mThread better be null here. doCancelVibrate should always be 313 // called before startNextVibrationLocked or startVibrationLocked. 314 mThread = new VibrateThread(vib); 315 mThread.start(); 316 } 317 } 318 319 // Lock held on mVibrations 320 private Vibration removeVibrationLocked(IBinder token) { 321 ListIterator<Vibration> iter = mVibrations.listIterator(0); 322 while (iter.hasNext()) { 323 Vibration vib = iter.next(); 324 if (vib.mToken == token) { 325 iter.remove(); 326 unlinkVibration(vib); 327 return vib; 328 } 329 } 330 // We might be looking for a simple vibration which is only stored in 331 // mCurrentVibration. 332 if (mCurrentVibration != null && mCurrentVibration.mToken == token) { 333 unlinkVibration(mCurrentVibration); 334 return mCurrentVibration; 335 } 336 return null; 337 } 338 339 private void unlinkVibration(Vibration vib) { 340 if (vib.mPattern != null) { 341 // If Vibration object has a pattern, 342 // the Vibration object has also been linkedToDeath. 343 vib.mToken.unlinkToDeath(vib, 0); 344 } 345 } 346 347 private void updateInputDeviceVibrators() { 348 synchronized (mVibrations) { 349 doCancelVibrateLocked(); 350 351 synchronized (mInputDeviceVibrators) { 352 mVibrateInputDevicesSetting = false; 353 try { 354 mVibrateInputDevicesSetting = Settings.System.getIntForUser( 355 mContext.getContentResolver(), 356 Settings.System.VIBRATE_INPUT_DEVICES, UserHandle.USER_CURRENT) > 0; 357 } catch (SettingNotFoundException snfe) { 358 } 359 360 if (mVibrateInputDevicesSetting) { 361 if (!mInputDeviceListenerRegistered) { 362 mInputDeviceListenerRegistered = true; 363 mIm.registerInputDeviceListener(this, mH); 364 } 365 } else { 366 if (mInputDeviceListenerRegistered) { 367 mInputDeviceListenerRegistered = false; 368 mIm.unregisterInputDeviceListener(this); 369 } 370 } 371 372 mInputDeviceVibrators.clear(); 373 if (mVibrateInputDevicesSetting) { 374 int[] ids = mIm.getInputDeviceIds(); 375 for (int i = 0; i < ids.length; i++) { 376 InputDevice device = mIm.getInputDevice(ids[i]); 377 Vibrator vibrator = device.getVibrator(); 378 if (vibrator.hasVibrator()) { 379 mInputDeviceVibrators.add(vibrator); 380 } 381 } 382 } 383 } 384 385 startNextVibrationLocked(); 386 } 387 } 388 389 @Override 390 public void onInputDeviceAdded(int deviceId) { 391 updateInputDeviceVibrators(); 392 } 393 394 @Override 395 public void onInputDeviceChanged(int deviceId) { 396 updateInputDeviceVibrators(); 397 } 398 399 @Override 400 public void onInputDeviceRemoved(int deviceId) { 401 updateInputDeviceVibrators(); 402 } 403 404 private boolean doVibratorExists() { 405 // For now, we choose to ignore the presence of input devices that have vibrators 406 // when reporting whether the device has a vibrator. Applications often use this 407 // information to decide whether to enable certain features so they expect the 408 // result of hasVibrator() to be constant. For now, just report whether 409 // the device has a built-in vibrator. 410 //synchronized (mInputDeviceVibrators) { 411 // return !mInputDeviceVibrators.isEmpty() || vibratorExists(); 412 //} 413 return vibratorExists(); 414 } 415 416 private void doVibratorOn(long millis) { 417 synchronized (mInputDeviceVibrators) { 418 final int vibratorCount = mInputDeviceVibrators.size(); 419 if (vibratorCount != 0) { 420 for (int i = 0; i < vibratorCount; i++) { 421 mInputDeviceVibrators.get(i).vibrate(millis); 422 } 423 } else { 424 vibratorOn(millis); 425 } 426 } 427 } 428 429 private void doVibratorOff() { 430 synchronized (mInputDeviceVibrators) { 431 final int vibratorCount = mInputDeviceVibrators.size(); 432 if (vibratorCount != 0) { 433 for (int i = 0; i < vibratorCount; i++) { 434 mInputDeviceVibrators.get(i).cancel(); 435 } 436 } else { 437 vibratorOff(); 438 } 439 } 440 } 441 442 private class VibrateThread extends Thread { 443 final Vibration mVibration; 444 boolean mDone; 445 446 VibrateThread(Vibration vib) { 447 mVibration = vib; 448 mTmpWorkSource.set(vib.mUid); 449 mWakeLock.setWorkSource(mTmpWorkSource); 450 mWakeLock.acquire(); 451 } 452 453 private void delay(long duration) { 454 if (duration > 0) { 455 long bedtime = duration + SystemClock.uptimeMillis(); 456 do { 457 try { 458 this.wait(duration); 459 } 460 catch (InterruptedException e) { 461 } 462 if (mDone) { 463 break; 464 } 465 duration = bedtime - SystemClock.uptimeMillis(); 466 } while (duration > 0); 467 } 468 } 469 470 public void run() { 471 Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_DISPLAY); 472 synchronized (this) { 473 int index = 0; 474 long[] pattern = mVibration.mPattern; 475 int len = pattern.length; 476 int repeat = mVibration.mRepeat; 477 long duration = 0; 478 479 while (!mDone) { 480 // add off-time duration to any accumulated on-time duration 481 if (index < len) { 482 duration += pattern[index++]; 483 } 484 485 // sleep until it is time to start the vibrator 486 delay(duration); 487 if (mDone) { 488 break; 489 } 490 491 if (index < len) { 492 // read on-time duration and start the vibrator 493 // duration is saved for delay() at top of loop 494 duration = pattern[index++]; 495 if (duration > 0) { 496 VibratorService.this.doVibratorOn(duration); 497 } 498 } else { 499 if (repeat < 0) { 500 break; 501 } else { 502 index = repeat; 503 duration = 0; 504 } 505 } 506 } 507 mWakeLock.release(); 508 } 509 synchronized (mVibrations) { 510 if (mThread == this) { 511 mThread = null; 512 } 513 if (!mDone) { 514 // If this vibration finished naturally, start the next 515 // vibration. 516 mVibrations.remove(mVibration); 517 unlinkVibration(mVibration); 518 startNextVibrationLocked(); 519 } 520 } 521 } 522 }; 523 524 BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { 525 public void onReceive(Context context, Intent intent) { 526 if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) { 527 synchronized (mVibrations) { 528 doCancelVibrateLocked(); 529 530 int size = mVibrations.size(); 531 for(int i = 0; i < size; i++) { 532 unlinkVibration(mVibrations.get(i)); 533 } 534 535 mVibrations.clear(); 536 } 537 } 538 } 539 }; 540 }
其中,VibratorService實際上是通過“本地方法”去控制馬達的。例如,hasVibratora()最終是通過vibratorExists()來判斷馬達是否存在的。
4 Vibrator.java
frameworks/base/core/java/android/os/Vibrator.java源碼如下:
1 package android.os; 2 3 import android.content.Context; 4 5 public abstract class Vibrator { 6 7 public Vibrator() { 8 } 9 10 public abstract boolean hasVibrator(); 11 12 public abstract void vibrate(long milliseconds); 13 14 public abstract void vibrate(long[] pattern, int repeat); 15 16 public abstract void cancel(); 17 }
5 SystemVibrator.java
frameworks/base/core/java/android/os/SystemVibrator.java源碼如下:
1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.os; 18 19 import android.util.Log; 20 21 /** 22 * Vibrator implementation that controls the main system vibrator. 23 * 24 * @hide 25 */ 26 public class SystemVibrator extends Vibrator { 27 private static final String TAG = "Vibrator"; 28 29 private final IVibratorService mService; 30 private final Binder mToken = new Binder(); 31 32 public SystemVibrator() { 33 mService = IVibratorService.Stub.asInterface( 34 ServiceManager.getService("vibrator")); 35 } 36 37 @Override 38 public boolean hasVibrator() { 39 if (mService == null) { 40 Log.w(TAG, "Failed to vibrate; no vibrator service."); 41 return false; 42 } 43 try { 44 return mService.hasVibrator(); 45 } catch (RemoteException e) { 46 } 47 return false; 48 } 49 50 @Override 51 public void vibrate(long milliseconds) { 52 if (mService == null) { 53 Log.w(TAG, "Failed to vibrate; no vibrator service."); 54 return; 55 } 56 try { 57 mService.vibrate(milliseconds, mToken); 58 } catch (RemoteException e) { 59 Log.w(TAG, "Failed to vibrate.", e); 60 } 61 } 62 63 @Override 64 public void vibrate(long[] pattern, int repeat) { 65 if (mService == null) { 66 Log.w(TAG, "Failed to vibrate; no vibrator service."); 67 return; 68 } 69 // catch this here because the server will do nothing. pattern may 70 // not be null, let that be checked, because the server will drop it 71 // anyway 72 if (repeat < pattern.length) { 73 try { 74 mService.vibratePattern(pattern, repeat, mToken); 75 } catch (RemoteException e) { 76 Log.w(TAG, "Failed to vibrate.", e); 77 } 78 } else { 79 throw new ArrayIndexOutOfBoundsException(); 80 } 81 } 82 83 @Override 84 public void cancel() { 85 if (mService == null) { 86 return; 87 } 88 try { 89 mService.cancelVibrate(mToken); 90 } catch (RemoteException e) { 91 Log.w(TAG, "Failed to cancel vibration.", e); 92 } 93 } 94 }
說明:
(01) 在構造函數SystemVibrator()中,我們通過 IVibratorService.Stub.asInterface(ServiceManager.getService("vibrator")) 獲取馬達服務,實際上獲取的是VibratorService對象。
(02) SystemVibrator的接口都是調用VibratorService接口實現的。
在講解“應用層如何通過getSystemService(VIBRATOR_SERVICE)獲取馬達服務,然后進一步的操作馬達”之前,我們先看看應用層的馬達操作示例!
Part 6 馬達的應用示例
1 權限
調用馬達服務,需要在manifest中添加相應的權限:
<!-- 震動馬達權限 --> <uses-permission android:name="android.permission.VIBRATE"/>
2 源碼
源碼如下:
1 package com.test; 2 3 import android.app.Activity; 4 import android.os.Bundle; 5 import android.os.Vibrator; 6 import android.view.View; 7 import android.view.View.OnClickListener; 8 import android.widget.Button; 9 import android.widget.ToggleButton; 10 import android.util.Log; 11 12 public class VibratorTest extends Activity { 13 private static final String TAG = "skywang-->VibratorTest"; 14 15 private Vibrator mVibrator; 16 private Button mOnce = null; 17 private ToggleButton mEndless = null; 18 19 @Override 20 protected void onCreate(Bundle savedInstanceState) { 21 super.onCreate(savedInstanceState); 22 setContentView(R.layout.main); 23 24 // 獲取震動馬達服務 25 mVibrator= (Vibrator) getSystemService(VIBRATOR_SERVICE); 26 27 mOnce = (Button) findViewById(R.id.vib_once); 28 mOnce.setOnClickListener(new View.OnClickListener() { 29 30 @Override 31 public void onClick(View view) { 32 //震動指定時間 33 mVibrator.vibrate(100); 34 } 35 }); 36 37 mEndless = (ToggleButton) findViewById(R.id.vib_endless); 38 mEndless.setOnClickListener(new OnClickListener() { 39 @Override 40 public void onClick(View v) { 41 if (mEndless.isChecked()) { 42 //等待100ms后,按數組所給數值間隔震動;其后為重復次數,-1為不重復,0一直震動 43 mVibrator.vibrate(new long[]{100,20,100,40,100,60}, 0); 44 } else { 45 // 取消震動 46 mVibrator.cancel(); 47 } 48 } 49 }); 50 51 } 52 53 @Override 54 protected void onStop() { 55 super.onStop(); 56 if (mVibrator != null) 57 mVibrator= null; 58 } 59 }
點擊下載:Android馬達應用代碼
Part 7 馬達的應用如何調用到馬達服務的
接下來,我們分析一下如何獲取馬達服務的:即 mVibrator= (Vibrator) getSystemService(VIBRATOR_SERVICE) 的工作原理。
1. Context.java中的getSystemService()
getSystemService()定義在frameworks/base/core/java/android/content/Context.java中,源碼如下:
public abstract Object getSystemService(String name);
Context.java中的getSystemService() 是個抽象方法,它的實現在ContextImpl.java中。
2. ContextImpl.java中的getSystemService()
frameworks/base/core/java/android/app/ContextImpl.java中的 getSystemService() 源碼如下:
1 @Override 2 public Object getSystemService(String name) { 3 ServiceFetcher fetcher = SYSTEM_SERVICE_MAP.get(name); 4 return fetcher == null ? null : fetcher.getService(this); 5 }
3. ContextImpl.java中的SYSTEM_SERVICE_MAP
SYSTEM_SERVICE_MAP是一個HashMap對象,它的相關代碼如下:
1 private static final HashMap<String, ServiceFetcher> SYSTEM_SERVICE_MAP = 2 new HashMap<String, ServiceFetcher>(); 3 4 SYSTEM_SERVICE_MAP的初始化,是在ContextImpl.java通過static靜態模塊完成的。源碼如下: 5 static { 6 7 ... 8 9 // 注冊“傳感器服務” 10 registerService(SENSOR_SERVICE, new ServiceFetcher() { 11 public Object createService(ContextImpl ctx) { 12 return new SystemSensorManager(ctx.mMainThread.getHandler().getLooper()); 13 }}); 14 15 // 注冊其它服務 ... 16 17 // 注冊馬達服務 18 registerService(VIBRATOR_SERVICE, new ServiceFetcher() { 19 public Object createService(ContextImpl ctx) { 20 return new SystemVibrator(); 21 }}); 22 23 ... 24 }
說明:在上面的static靜態模塊中,會通過registerService()注冊一系列的服務,包括馬達服務。注冊服務是通過registerService()實現的,下面我們看看registerService()的定義。
1 private static int sNextPerContextServiceCacheIndex = 0; 2 private static void registerService(String serviceName, ServiceFetcher fetcher) { 3 if (!(fetcher instanceof StaticServiceFetcher)) { 4 fetcher.mContextCacheIndex = sNextPerContextServiceCacheIndex++; 5 } 6 SYSTEM_SERVICE_MAP.put(serviceName, fetcher); 7 }
從中,我們知道,在registerService()中,會通過 SYSTEM_SERVICE_MAP.put(serviceName, fetcher) 將serviceName和fetcher添加到哈希表SYSTEM_SERVICE_MAP中。
對馬達服務而言,添加到哈希表SYSTEM_SERVICE_MAP中的key-value中的key是VIBRATOR_SERVICE,value則是ServiceFetcher對象;而且該匿名ServiceFetcher對象的createService()方法會“通過new SystemVibrator()”返回SystemVibrator對象。而SystemVibrator我們在前面已經介紹過了,它是馬達服務對外提供接口的類。
OK,接着往下看。
3. ContextImpl.java中的fetcher.getService(this)
1 public Object getSystemService(String name) { 2 ServiceFetcher fetcher = SYSTEM_SERVICE_MAP.get(name); 3 return fetcher == null ? null : fetcher.getService(this); 4 }
我們已經知道SYSTEM_SERVICE_MAP是哈希表,通過SYSTEM_SERVICE_MAP.get(name)返回的是ServiceFetcher對象。
由於fetcher不為null,所以,getSystemService()會返回fetcher.getService(this)。我們看看ServiceFetcher中getService()源碼:
1 static class ServiceFetcher { 2 int mContextCacheIndex = -1; 3 4 public Object getService(ContextImpl ctx) { 5 ArrayList<Object> cache = ctx.mServiceCache; 6 Object service; 7 synchronized (cache) { 8 if (cache.size() == 0) { 9 10 // “服務對象”緩沖 11 for (int i = 0; i < sNextPerContextServiceCacheIndex; i++) { 12 cache.add(null); 13 } 14 } else { 15 service = cache.get(mContextCacheIndex); 16 if (service != null) { 17 return service; 18 } 19 } 20 service = createService(ctx); 21 cache.set(mContextCacheIndex, service); 22 return service; 23 } 24 } 25 26 public Object createService(ContextImpl ctx) { 27 throw new RuntimeException("Not implemented"); 28 } 29 }
從中,我們發現,getService()實際上返回的是“通過createService(ctx)創建的service對象”。
而在registerService()注冊馬達服務時,我們匿名實現了createService()方法:它實際上是通過 new SystemVibrator() 返回SystemVibrator對象。
至此,我們知道:getSystemService(VIBRATOR_SERVICE) 返回的是 SystemVibrator對象!SystemVibrator前面已經分析過,這里就不再說明了。
