|
[上接 android linux基礎(chǔ)知識(shí)總結(jié)[上]] ================================================= 5. 設(shè)置模塊流程分析 rild 流程分析 5.1 設(shè)置 pin 狀態(tài),pin認(rèn)證 5.1.1 設(shè)置pin狀態(tài) 5.1.2 修改sim卡pin 5.1.3 pin認(rèn)證流程 5.2 網(wǎng)絡(luò)設(shè)置 5.3 屏幕背光設(shè)置 5.4 獲取,顯示電池狀態(tài) ================ EditPinPreference.java (packages\apps\settings\src\com\android\settings) private OnPinEnteredListener mPinListener; protected void onDialogClosed(boolean positiveResult) mPinListener.onPinEntered(this, positiveResult); 執(zhí)行 SimLockSettings.java (packages\apps\settings\src\com\android\settings)中函數(shù): public void onPinEntered(EditPinPreference preference, boolean positiveResult) 修改pin狀態(tài): tryChangeSimLockState(); 修改pin: tryChangePin(); 5.1.1 設(shè)置pin狀態(tài) private void tryChangeSimLockState() Message callback = Message.obtain(mHandler, ENABLE_SIM_PIN_COMPLETE); mPhone.getSimCard().setSimLockEnabled(mToState, mPin, callback); 進(jìn)入sim lock 菜單會(huì)顯示初始化pin狀態(tài),是通過(guò)下面語(yǔ)句得到: mPinToggle.setChecked(mPhone.getSimCard().getSimLockEnabled()); mPhone.getSimCard().setSimLockEnabled(mToState, mPin, callback)調(diào)用的是文件: GsmSimCard.java (frameworks\base\telephony\java\com\android\internal\telephony\gsm)中的函數(shù): public void setSimLockEnabled (boolean enabled,String password, Message onComplete) { int serviceClassX; serviceClassX = CommandsInterface.SERVICE_CLASS_VOICE + CommandsInterface.SERVICE_CLASS_DATA + CommandsInterface.SERVICE_CLASS_FAX; mDesiredPinLocked = enabled; phone.mCM.setFacilityLock(CommandsInterface.CB_FACILITY_BA_SIM, enabled, password, serviceClassX, obtainMessage(EVENT_CHANGE_FACILITY_LOCK_DONE, onComplete)); phone.mCM.setFacilityLock 調(diào)用的是文件: RIL.java (frameworks\base\telephony\java\com\android\internal\telephony\gsm)中的函數(shù): public void setFacilityLock (String facility, boolean lockState, String password, int serviceClass, Message response) { String lockString; RILRequest rr = RILRequest.obtain(RIL_REQUEST_SET_FACILITY_LOCK, response); if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); // count strings rr.mp.writeInt(4); rr.mp.writeString(facility); lockString = (lockState)?"1":"0"; rr.mp.writeString(lockString); rr.mp.writeString(password); rr.mp.writeString(Integer.toString(serviceClass)); send(rr); } 設(shè)置應(yīng)用程序向 rild 發(fā)送 RIL_REQUEST_SET_FACILITY_LOCK 請(qǐng)求的 socket消息, android的初始源代碼中 RIL_REQUEST_SET_FACILITY_LOCK 請(qǐng)求,在參考實(shí)現(xiàn) Reference-ril.c (hardware\ril\reference-ril) 中沒(méi)有實(shí)現(xiàn)。 我們需要做得工作是: ========== 5.1.2 修改sim卡pin private void tryChangePin() mPhone.getSimCard().changeSimLockPassword(mOldPin,mNewPin, callback); mPhone.getSimCard 調(diào)用的是文件: GsmSimCard.java (frameworks\base\telephony\java\com\android\internal\telephony\gsm)中的函數(shù): public void changeSimLockPassword(String oldPassword, String newPassword, Message onComplete) phone.mCM.changeSimPin(oldPassword, newPassword, obtainMessage(EVENT_CHANGE_SIM_PASSWORD_DONE, onComplete)); phone.mCM.changeSimPin 調(diào)用的是文件: RIL.java (frameworks\base\telephony\java\com\android\internal\telephony\gsm)中的函數(shù): public void changeSimPin(String oldPin, String newPin, Message result) { RILRequest rr = RILRequest.obtain(RIL_REQUEST_CHANGE_SIM_PIN, result); if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); rr.mp.writeInt(2); rr.mp.writeString(oldPin); rr.mp.writeString(newPin); send(rr); } rild端處理流程: 5.1.3 pin認(rèn)證流程 ======== 5.2 網(wǎng)絡(luò)設(shè)置 ======= 5.3 屏幕背光設(shè)置 packages/apps/Settings/src/com/android/settings/BrightnessPreference.java 背光設(shè)置滾動(dòng)條和關(guān)閉按鈕都會(huì)調(diào)用 setBrightness(mOldBrightness); public void onProgressChanged(SeekBar seekBar, int progress,boolean fromTouch) protected void onDialogClosed(boolean positiveResult) private void setBrightness(int brightness) { try { IHardwareService hardware = IHardwareService.Stub.asInterface( ServiceManager.getService("hardware")); if (hardware != null) { hardware.setBacklights(brightness); } } catch (RemoteException doe) { } } 調(diào)用硬件服務(wù)器 HardwareService 的 setBacklights 函數(shù) HardwareService.java (frameworks\base\services\java\com\android\server): public void setBacklights(int brightness) { . . . // Don't let applications turn the screen all the way off brightness = Math.max(brightness, Power.BRIGHTNESS_DIM); setLightBrightness_UNCHECKED(LIGHT_ID_BACKLIGHT, brightness); setLightBrightness_UNCHECKED(LIGHT_ID_KEYBOARD, brightness); setLightBrightness_UNCHECKED(LIGHT_ID_BUTTONS, brightness); . . . } void setLightOff_UNCHECKED(int light) { //本地調(diào)用 setLight_native setLight_native(mNativePointer, light, 0, LIGHT_FLASH_NONE, 0, 0); } void setLightBrightness_UNCHECKED(int light, int brightness) { int b = brightness & 0x000000ff; b = 0xff000000 | (b = LIGHT_COUNT || devices->lights[light] == NULL) { return ; } memset(&state, 0, sizeof(light_state_t)); state.color = colorARGB; state.flashMode = flashMode; state.flashOnMS = onMS; state.flashOffMS = offMS; devices->lights[light]->set_light(devices->lights[light], &state); } Lights.h (hardware\libhardware\include\hardware):#define LIGHTS_HARDWARE_MODULE_ID "lights" com_android_server_HardwareService.cpp (frameworks\base\services\jni) err = hw_get_module(LIGHTS_HARDWARE_MODULE_ID, (hw_module_t const**)&module); static const char *variant_keys[] = { "ro.hardware", /* This goes first so that it can pick up a different file on the emulator. */ "ro.product.board", "ro.board.platform", "ro.arch" }; int hw_get_module(const char *id, const struct hw_module_t **module) status = load(id, prop, &hmi); status = load(id, HAL_DEFAULT_VARIANT, &hmi); static int load(const char *id, const char *variant,const struct hw_module_t **pHmi) snprintf(path, sizeof(path), "%s/%s.%s.so", HAL_LIBRARY_PATH, id, variant); #define HAL_DEFAULT_VARIANT "default" #define HAL_LIBRARY_PATH "/system/lib/hw" 所以path等于: /system/lib/hw/light.marvell.so /system/lib/hw/light.default.so 我們編譯的light模塊放在 /system/lib/hw/light.default.so 所以初始化成功。 property_get(variant_keys, prop, NULL) 只有 ro.hardware 存在 [ro.hardware]: [marvell] static int lights_device_open(const struct hw_module_t* module, const char* name,struct hw_device_t** device) dev->set_light = set_light_backlight; static struct hw_module_methods_t lights_module_methods = { open: lights_device_open }; hardware/libhardware/modules/lights/Android.mk LOCAL_MODULE:= lights.default err = module->methods->open(module, name, &device); 執(zhí)行的是 : lights_device_open const char * const brightness_file = "/sys/class/backlight/micco-bl/brightness"; static int set_light_backlight(struct light_device_t* dev, struct light_state_t const* state) { . . . color = state->color; tmp = ((77*((color>>16)&0x00ff)) + (150*((color>>8)&0x00ff)) + (29*(color&0x00ff))) >> 8; brightness = tmp/16; LOGD("---->calling %s(),line=%d state->color=%d,brightness=%d\n",__FUNCTION__,__LINE__,state->color,brightness); len = sprintf(buf,"%d",brightness); len = write(fd, buf, len); . . . } 上面的函數(shù)完成了與內(nèi)核的交互 綜上所述,程序調(diào)用流程如下,上層應(yīng)用通過(guò) /sys/class/leds/lcd-backlight/brightnes 于內(nèi)核打交道 設(shè)置模塊 -> 硬件服務(wù)器 -> 本地調(diào)用 ->功能庫(kù) -> 讀寫(xiě) /sys/class/leds/lcd-backlight/brightness 函數(shù)與內(nèi)核交互 Init.rc (vendor\marvell\littleton): chown system system /sys/class/leds/keyboard-backlight/brightness Init.rc (vendor\marvell\littleton): chown system system /sys/class/leds/lcd-backlight/brightness Init.rc (vendor\marvell\littleton): chown system system /sys/class/leds/button-backlight/brightness 5.4 獲取,顯示電池狀態(tài) 電池狀態(tài)(正在充電(AC)): Status.java String statusString; mBatteryStatus.setSummary(statusString); public static final int BATTERY_STATUS_UNKNOWN = 1; public static final int BATTERY_STATUS_CHARGING = 2; public static final int BATTERY_STATUS_DISCHARGING = 3; public static final int BATTERY_STATUS_NOT_CHARGING = 4; public static final int BATTERY_STATUS_FULL = 5; // values for "health" field in the ACTION_BATTERY_CHANGED Intent public static final int BATTERY_HEALTH_UNKNOWN = 1; public static final int BATTERY_HEALTH_GOOD = 2; public static final int BATTERY_HEALTH_OVERHEAT = 3; public static final int BATTERY_HEALTH_DEAD = 4; public static final int BATTERY_HEALTH_OVER_VOLTAGE = 5; public static final int BATTERY_HEALTH_UNSPECIFIED_FAILURE = 6; public static final int BATTERY_PLUGGED_AC = 1; 電源充電 public static final int BATTERY_PLUGGED_USB = 2; USB充電 BatteryInfo.java (packages\apps\settings\src\com\android\settings) 電池級(jí)別(50%) BatteryService.java (frameworks\base\services\java\com\android\server) 電池服務(wù)器: 構(gòu)造函數(shù): public BatteryService(Context context) mUEventObserver.startObserving("SUBSYSTEM=power_supply"); ---------- UEventObserver.java (frameworks\base\core\java\android\os) void startObserving(String match) ensureThreadStarted(); sThread = new UEventThread(); sThread.start(); sThread.addObserver(match, this); ----------- update() native_update(); sendIntent(); private final void sendIntent() Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); ... intent.putExtra("status", mBatteryStatus); intent.putExtra("health", mBatteryHealth); intent.putExtra("present", mBatteryPresent); intent.putExtra("level", mBatteryLevel); intent.putExtra("scale", BATTERY_SCALE); intent.putExtra("icon-small", icon); intent.putExtra("plugged", mPlugType); intent.putExtra("voltage", mBatteryVoltage); intent.putExtra("temperature", mBatteryTemperature); intent.putExtra("technology", mBatteryTechnology); ActivityManagerNative.broadcastStickyIntent(intent, null); 把讀取的電池信息通過(guò)廣播信息發(fā)送給所有的應(yīng)用程序。 native_update 本地調(diào)用的是文件 com_android_server_BatteryService.cpp (frameworks\base\services\jni) 中的函數(shù): static void android_server_BatteryService_update(JNIEnv* env, jobject obj) { setBooleanField(env, obj, AC_ONLINE_PATH, gFieldIds.mAcOnline); setBooleanField(env, obj, USB_ONLINE_PATH, gFieldIds.mUsbOnline); setBooleanField(env, obj, BATTERY_PRESENT_PATH, gFieldIds.mBatteryPresent); setIntField(env, obj, BATTERY_CAPACITY_PATH, gFieldIds.mBatteryLevel); setIntField(env, obj, BATTERY_VOLTAGE_PATH, gFieldIds.mBatteryVoltage); setIntField(env, obj, BATTERY_TEMPERATURE_PATH, gFieldIds.mBatteryTemperature); const int SIZE = 128; char buf[SIZE]; if (readFromFile(BATTERY_STATUS_PATH, buf, SIZE) > 0) env->SetIntField(obj, gFieldIds.mBatteryStatus, getBatteryStatus(buf)); if (readFromFile(BATTERY_HEALTH_PATH, buf, SIZE) > 0) env->SetIntField(obj, gFieldIds.mBatteryHealth, getBatteryHealth(buf)); if (readFromFile(BATTERY_TECHNOLOGY_PATH, buf, SIZE) > 0) env->SetObjectField(obj, gFieldIds.mBatteryTechnology, env->NewStringUTF(buf)); } #define AC_ONLINE_PATH "/sys/class/power_supply/ac/online" #define USB_ONLINE_PATH "/sys/class/power_supply/usb/online" #define BATTERY_STATUS_PATH "/sys/class/power_supply/battery/status" #define BATTERY_HEALTH_PATH "/sys/class/power_supply/battery/health" #define BATTERY_PRESENT_PATH "/sys/class/power_supply/battery/present" #define BATTERY_CAPACITY_PATH "/sys/class/power_supply/battery/capacity" #define BATTERY_VOLTAGE_PATH "/sys/class/power_supply/battery/batt_vol" #define BATTERY_TEMPERATURE_PATH "/sys/class/power_supply/battery/batt_temp" #define BATTERY_TECHNOLOGY_PATH "/sys/class/power_supply/battery/technology" ================================================= ================================================= 6. linux系統(tǒng)啟動(dòng)流程分析 6.1 桌面操作系統(tǒng)啟動(dòng)流程(redhat,federa,ubuntu) 6.2 小型嵌入式系統(tǒng)啟動(dòng)流程 6.3 android 系統(tǒng)啟動(dòng)流程 ============== 6.1 桌面操作系統(tǒng)啟動(dòng)流程(redhat,federa,ubuntu) ubuntu從6.10開(kāi)始逐步用upstart代替原來(lái)的sysinit,進(jìn)行服務(wù)進(jìn)程的管理。為了對(duì)原有的init實(shí)現(xiàn)向后兼容, 目前ubuntu中與init相關(guān)的幾個(gè)目錄和應(yīng)用程序,可以方便后面的論述。這些目錄和程序包括: init telinit //字面理解 tell init runlevel /etc/event.d/ /etc/init.d/ /etc/rcX.d/ 首先是/etc/event.d/目錄,這是upstart的核心,upstart不同于原有的init的地方就在于它引入了event機(jī)制。Event 機(jī)制通俗的 講就是將所有進(jìn)程的觸發(fā)、停止等等都看作event(事件)。/etc/event.d/中就存放了目前upstart需要識(shí)別的event。這其中主要有三種 rc-default, rcX(x=0,1,...6,S)以及ttyX。這rc-default就類似于 inittab文件,它就是設(shè)置默認(rèn)運(yùn)行級(jí)別的 ,需要運(yùn)行程序的 腳本,而ttyX則是設(shè)置偽終端數(shù)目的,也就是你Ctrl+Alt+F(1~6)調(diào)出的那個(gè)Console。我們以rc2為例,cat rc2: rc-default start on stopped rcS telinit 2 所以會(huì)依次執(zhí)行 /etc/event.d/rcS /etc/event.d/rc2 它們又會(huì)分別執(zhí)行: exec /etc/init.d/rc S exec /etc/init.d/rc 2 這樣,我們就可以自然地過(guò)渡到下一個(gè)重要的目錄,/etc/init.d/了。 /etc/init.d/中存放的是服務(wù)(services)或者任務(wù)(tasks)的執(zhí)行腳本。可以這么說(shuō),只要你安裝了一個(gè)程序(特別是服務(wù)程序daemon), 它可以在系統(tǒng)啟動(dòng)的時(shí)候運(yùn)行,那么它必定會(huì)在/etc/init.d/中有一個(gè)腳本文件。 執(zhí)行了一個(gè)exec /etc/init.d/rc 2的命令。也就是說(shuō),給/etc/init.d/rc腳本傳遞了一個(gè)參數(shù)"2",讓它執(zhí)行。 rc腳本(很長(zhǎng),耐心點(diǎn)),能看到這樣的一段: # Now run the START scripts for this runlevel. # Run all scripts with the same level in parallel ....... for s in /etc/rc$runlevel.d/S* ....... 將會(huì)開(kāi)始執(zhí)行/etc/rc2.d/下S開(kāi)頭的腳本。這就過(guò)渡到下一個(gè)目錄/etc/rc2.d/了。 /etc/rc2.d 都是一些到/etc/init.d/中腳本的符號(hào)鏈接。不同的是在開(kāi)頭加上了S和一個(gè)數(shù)字,S表示在啟動(dòng)時(shí)運(yùn)行,數(shù)字則表示執(zhí)行的先后順序。 /etc/rcS.d/S35mountall.sh K08vmware S19vmware S20nfs-common |
|
|
來(lái)自: shaobin0604@1... > 《Android》