System Server是Android系统的核心,他在Dalvik虚拟机启动后立即开始初始化和运行。其它的系统服务在System Server进程的环境中运行。
在main函数中,首先检查系统时间设置和SamplingProfiler。然后加载一个叫android_servers的本地库,他提供本地方法的接口(源程序在framework/base/services/jni/目录中)。
然后调用本地方法设置服务。然后执行一个死循环线程,该线程中启动了很多服务。
public static void main(String[] args) {
... ...
Environment.setUserRequired(true);
System.loadLibrary("android_servers");
Slog.i(TAG, "Entered the Android system server!");
// Initialize native services.
nativeInit();
// This used to be its own separate thread, but now it is
// just the loop we run on the main thread.
ServerThread thr = new ServerThread();
thr.initAndLoop();
}
}
在ServerThread中启动了监听有线耳机接入的服务。
if (!disableMedia) {
try {
Slog.i(TAG, "Wired Accessory Manager");
// Listen for wired headset changes
inputManager.setWiredAccessoryCallbacks(
new WiredAccessoryManager(context, inputManager));
} catch (Throwable e) {
reportWtf("starting WiredAccessoryManager", e);
}
}
在base/services/java/com/android/server/WiredAccessoryManager.java中
WiredAccessoryManager中使用了两种方式监听耳机的状态
在构造函数中获得mUseDevInputEventForAudioJack的状态,配置为false。
public WiredAccessoryManager(Context context, InputManagerService inputManager) {
PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
mWakeLock = pm.newWakeLock(
PowerManager.PARTIAL_WAKE_LOCK, "WiredAccessoryManager");
mWakeLock.setReferenceCounted(false);
mAudioManager = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
mInputManager = inputManager;
mContext= context;
mUseDevInputEventForAudioJack =
context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack);
//构造监听耳机状态的对象
mObserver = new WiredAccessoryObserver();
context.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context ctx, Intent intent) {
bootCompleted();
}
},
new IntentFilter(Intent.ACTION_BOOT_COMPLETED), null, null);
}
在启动完成后就开启监听,注册了开机广播,开机后,会开始所有相关的UEvent,并且开始监听。在private void bootCompleted()中
private void bootCompleted() {
if (mUseDevInputEventForAudioJack) {
int switchValues = 0;
if (mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY, SW_HEADPHONE_INSERT) == 1) {
switchValues |= SW_HEADPHONE_INSERT_BIT;
}
if (mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY, SW_MICROPHONE_INSERT) == 1) {
switchValues |= SW_MICROPHONE_INSERT_BIT;
}
notifyWiredAccessoryChanged(0, switchValues,
SW_HEADPHONE_INSERT_BIT | SW_MICROPHONE_INSERT_BIT);
}
mObserver.init();
}
在WiredAccessoryManager中实例化了一个WiredAccessoryObserver,其就是通过UEvent方式来检测耳机的插入拔出状态,
public WiredAccessoryObserver() {
mUEventInfo = makeObservedUEventList();
}
private List<UEventInfo> makeObservedUEventList() {
List<UEventInfo> retVal = new ArrayList<UEventInfo>();
UEventInfo uei;
// Monitor h2w
if (!mUseDevInputEventForAudioJack) {
uei = new UEventInfo(NAME_H2W, BIT_HEADSET, BIT_HEADSET_NO_MIC);
if (uei.checkSwitchExists()) {
retVal.add(uei);
} else {
Slog.w(TAG, "This kernel does not have wired headset support");
}
}
// Monitor USB
uei = new UEventInfo(NAME_USB_AUDIO, BIT_USB_HEADSET_ANLG, BIT_USB_HEADSET_DGTL);
if (uei.checkSwitchExists()) {
retVal.add(uei);
} else {
Slog.w(TAG, "This kernel does not have usb audio support");
}
// Monitor HDMI
uei = new UEventInfo(NAME_HDMI_AUDIO, BIT_HDMI_AUDIO, 0);
if (uei.checkSwitchExists()) {
retVal.add(uei);
} else {
uei = new UEventInfo(NAME_HDMI, BIT_HDMI_AUDIO, 0);
if (uei.checkSwitchExists()) {
retVal.add(uei);
} else {
Slog.w(TAG, "This kernel does not have HDMI audio support");
}
}
return retVal;
}
在WiredAccessoryObserver 的init中
void init() {
synchronized (mLock) {
if (LOG) Slog.v(TAG, "init()");
char[] buffer = new char[1024];
for (int i = 0; i < mUEventInfo.size(); ++i) {
UEventInfo uei = mUEventInfo.get(i);
try {
int curState;
FileReader file = new FileReader(uei.getSwitchStatePath());
int len = file.read(buffer, 0, 1024);
file.close();
curState = Integer.valueOf((new String(buffer, 0, len)).trim());
if (curState > 0) {
updateStateLocked(uei.getDevPath(), uei.getDevName(), curState);
}
} catch (FileNotFoundException e) {
Slog.w(TAG, uei.getSwitchStatePath() +
" not found while attempting to determine initial switch state");
} catch (Exception e) {
Slog.e(TAG, "" , e);
}
}
}
// At any given time accessories could be inserted
// one on the board, one on the dock and one on HDMI:
// observe three UEVENTs
// 设置监听节点,开始进行监听
for (int i = 0; i < mUEventInfo.size(); ++i) {
UEventInfo uei = mUEventInfo.get(i);
startObserving("DEVPATH="+uei.getDevPath());
}
}
public String getDevPath() {
return String.format(Locale.US, "/devices/virtual/switch/%s", mDevName);
}
通过startObserving("DEVPATH="+uei.getDevPath()); 来进行监听,监听的节点是:
shell@hammerhead:/ $ ls sys/class/switch/ -l
lrwxrwxrwx root root 2014-05-06 09:44 h2w -> ../../devices/virtual/switch/h2w
/**
* Begin observation of UEvent's.<p>
* This method will cause the UEvent thread to start if this is the first
* invocation of startObserving in this process.<p>
* Once called, the UEvent thread will call onUEvent() when an incoming
* UEvent matches the specified string.<p>
* This method can be called multiple times to register multiple matches.
* Only one call to stopObserving is required even with multiple registered
* matches.
*
* @param match A substring of the UEvent to match. Try to be as specific
* as possible to avoid incurring unintended additional cost from processing
* irrelevant messages. Netlink messages can be moderately high bandwidth and
* are expensive to parse. For example, some devices may send one netlink message
* for each vsync period.
*/
public final void startObserving(String match) {
if (match == null || match.isEmpty()) {
throw new IllegalArgumentException("match substring must be non-empty");
}
final UEventThread t = getThread();
t.addObserver(match, this);
}
在onUEvent时间到来的时候更新state
@Override
public void onUEvent(UEventObserver.UEvent event) {
if (LOG) Slog.v(TAG, "Headset UEVENT: " + event.toString());
try {
String devPath = event.get("DEVPATH");
String name = event.get("SWITCH_NAME");
int state = Integer.parseInt(event.get("SWITCH_STATE"));
synchronized (mLock) {
updateStateLocked(devPath, name, state);
}
} catch (NumberFormatException e) {
Slog.e(TAG, "Could not parse switch state from event " + event);
}
}
updateStateLocked(devPath, name, state)
-> updateLocked(String newName, int newState)
-> setDevicesState(int headsetState, int prevHeadsetState, String headsetName)
-> setDeviceStateLocked()
-> mAudioManager.setWiredDeviceConnectionState(device, state, headsetName);在setDeviceStateLocked中会更新device的状态,并最终调用mAudioManager.setWiredDeviceConnectionState
private void setDevicesState(
int headsetState, int prevHeadsetState, String headsetName) {
synchronized (mLock) {
int allHeadsets = SUPPORTED_HEADSETS;
for (int curHeadset = 1; allHeadsets != 0; curHeadset <<= 1) {
if ((curHeadset & allHeadsets) != 0) {
setDeviceStateLocked(curHeadset, headsetState, prevHeadsetState, headsetName);
allHeadsets &= ~curHeadset;
}
}
}
}
private void setDeviceStateLocked(int headset,
int headsetState, int prevHeadsetState, String headsetName) {
if ((headsetState & headset) != (prevHeadsetState & headset)) {
int device;
int state;
if ((headsetState & headset) != 0) {
state = 1;
} else {
state = 0;
}
if (hea