分享

下接 android linux 基础知识总结[下]4

 shaobin0604@163.com 2011-09-06
[上接 android linux基础知识总结[上]]
=================================================
5. 设置模块流程分析
rild 流程分析
5.1 设置 pin 状态,pin认证
5.1.1 设置pin状态
5.1.2 修改sim卡pin
5.1.3 pin认证流程
5.2 网络设置
5.3 屏幕背光设置
5.4 获取,显示电池状态
================
EditPinPreference.java (packages\apps\settings\src\com\android\settings)
private OnPinEnteredListener mPinListener;
protected void onDialogClosed(boolean positiveResult)
mPinListener.onPinEntered(this, positiveResult);
执行 SimLockSettings.java (packages\apps\settings\src\com\android\settings)中函数:
public void onPinEntered(EditPinPreference preference, boolean positiveResult)
修改pin状态: tryChangeSimLockState();
修改pin: tryChangePin();
5.1.1 设置pin状态
private void tryChangeSimLockState()
Message callback = Message.obtain(mHandler, ENABLE_SIM_PIN_COMPLETE);
mPhone.getSimCard().setSimLockEnabled(mToState, mPin, callback);
进入sim lock 菜单会显示初始化pin状态,是通过下面语句得到:
mPinToggle.setChecked(mPhone.getSimCard().getSimLockEnabled());
mPhone.getSimCard().setSimLockEnabled(mToState, mPin, callback)调用的是文件:
GsmSimCard.java (frameworks\base\telephony\java\com\android\internal\telephony\gsm)中的函数:
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 调用的是文件:
RIL.java (frameworks\base\telephony\java\com\android\internal\telephony\gsm)中的函数:
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);
}
设置应用程序向 rild 发送 RIL_REQUEST_SET_FACILITY_LOCK 请求的 socket消息,
android的初始源代码中 RIL_REQUEST_SET_FACILITY_LOCK 请求,在参考实现 Reference-ril.c 
(hardware\ril\reference-ril) 中没有实现。
我们需要做得工作是:
==========
5.1.2 修改sim卡pin
private void tryChangePin()
mPhone.getSimCard().changeSimLockPassword(mOldPin,mNewPin, callback);
mPhone.getSimCard 调用的是文件:
GsmSimCard.java (frameworks\base\telephony\java\com\android\internal\telephony\gsm)中的函数:
public void changeSimLockPassword(String oldPassword, String newPassword,
Message onComplete)
phone.mCM.changeSimPin(oldPassword, newPassword,
obtainMessage(EVENT_CHANGE_SIM_PASSWORD_DONE, onComplete));
phone.mCM.changeSimPin 调用的是文件:
RIL.java (frameworks\base\telephony\java\com\android\internal\telephony\gsm)中的函数:
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认证流程
========
5.2 网络设置
=======
5.3 屏幕背光设置
packages/apps/Settings/src/com/android/settings/BrightnessPreference.java
背光设置滚动条和关闭按钮都会调用 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) { 

}
调用硬件服务器 HardwareService 的 setBacklights 函数
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) 

//本地调用 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);
执行的是 : 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);
. . .

上面的函数完成了与内核的交互
综上所述,程序调用流程如下,上层应用通过 /sys/class/leds/lcd-backlight/brightnes 于内核打交道
设置模块 -> 硬件服务器 -> 本地调用 ->功能库 -> 读写 /sys/class/leds/lcd-backlight/brightness 函数与内核交互
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 获取,显示电池状态
电池状态(正在充电(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)
电池级别(50%)
BatteryService.java (frameworks\base\services\java\com\android\server)
电池服务器:
构造函数:
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);
把读取的电池信息通过广播信息发送给所有的应用程序。
native_update 本地调用的是文件 com_android_server_BatteryService.cpp (frameworks\base\services\jni) 中的函数:
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系统启动流程分析
6.1 桌面操作系统启动流程(redhat,federa,ubuntu)
6.2 小型嵌入式系统启动流程
6.3 android 系统启动流程
==============
6.1 桌面操作系统启动流程(redhat,federa,ubuntu)
ubuntu从6.10开始逐步用upstart代替原来的sysinit,进行服务进程的管理。为了对原有的init实现向后兼容,
目前ubuntu中与init相关的几个目录和应用程序,可以方便后面的论述。这些目录和程序包括:
init
telinit //字面理解 tell init
runlevel
/etc/event.d/
/etc/init.d/
/etc/rcX.d/
首先是/etc/event.d/目录,这是upstart的核心,upstart不同于原有的init的地方就在于它引入了event机制。Event 机制通俗的
讲就是将所有进程的触发、停止等等都看作event(事件)。/etc/event.d/中就存放了目前upstart需要识别的event。这其中主要有三种
rc-default, rcX(x=0,1,...6,S)以及ttyX。这rc-default就类似于 inittab文件,它就是设置默认运行级别的 ,需要运行程序的
脚本,而ttyX则是设置伪终端数目的,也就是你Ctrl+Alt+F(1~6)调出的那个Console。我们以rc2为例,cat rc2:
rc-default
start on stopped rcS
telinit 2
所以会依次执行 /etc/event.d/rcS /etc/event.d/rc2
它们又会分别执行:
exec /etc/init.d/rc S
exec /etc/init.d/rc 2
这样,我们就可以自然地过渡到下一个重要的目录,/etc/init.d/了。
/etc/init.d/中存放的是服务(services)或者任务(tasks)的执行脚本。可以这么说,只要你安装了一个程序(特别是服务程序daemon),
它可以在系统启动的时候运行,那么它必定会在/etc/init.d/中有一个脚本文件。
执行了一个exec /etc/init.d/rc 2的命令。也就是说,给/etc/init.d/rc脚本传递了一个参数"2",让它执行。
rc脚本(很长,耐心点),能看到这样的一段:
# 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*
.......
将会开始执行/etc/rc2.d/下S开头的脚本。这就过渡到下一个目录/etc/rc2.d/了。
/etc/rc2.d 都是一些到/etc/init.d/中脚本的符号链接。不同的是在开头加上了S和一个数字,S表示在启动时运行,数字则表示执行的先后顺序。
/etc/rcS.d/S35mountall.sh
K08vmware
S19vmware
S20nfs-common

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多