请逐行分析下AudioService.java中setMode函数
时间: 2023-06-13 16:05:05 浏览: 179
好的,我来分析一下AudioService.java中setMode函数的代码。首先,这个函数的作用是设置音频模式,具体而言,就是设置音频流的使用场景(比如是听音乐、打电话、玩游戏等),这会影响到音频系统的参数设置,比如音量、音效等。下面是这个函数的代码:
```
public int setMode(int mode, IBinder cb, String callingPackageName) {
if (DEBUG_MODE) {
Log.d(TAG, "setMode(" + mode + ")");
}
// Ensure the calling package name is valid, if specified.
if (callingPackageName != null) {
final int oldUid = Binder.getCallingUid();
final int newUid = getUidForPackage(callingPackageName);
if (newUid != oldUid && !isPrivileged(Binder.getCallingPid(), oldUid)) {
Log.e(TAG, "Cannot set mode from non privileged app: " + callingPackageName);
return AudioManager.MODE_INVALID;
}
}
// Permission check.
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_AUDIO_SETTINGS)
!= PackageManager.PERMISSION_GRANTED) {
Log.w(TAG, "MODIFY_AUDIO_SETTINGS Permission Denial: setMode()");
return AudioManager.MODE_INVALID;
}
if (mode == AudioManager.MODE_INVALID) {
return AudioManager.MODE_INVALID;
}
int newModeOwnerPid = Binder.getCallingPid();
int newModeOwnerUid = Binder.getCallingUid();
synchronized (mSetModeDeathHandlers) {
if (cb == null) {
// synchronous call, clear death handler
mSetModeDeathHandlers.remove(newModeOwnerPid);
} else {
// asynchronous call, set death handler
try {
cb.linkToDeath(new SetModeDeathHandler(newModeOwnerPid, newModeOwnerUid, cb),
0 /* flags */);
} catch (RemoteException e) {
Log.w(TAG, "setMode() could not link to " + cb + " binder death");
return AudioManager.MODE_INVALID;
}
mSetModeDeathHandlers.put(newModeOwnerPid,
new SetModeDeathHandler(newModeOwnerPid, newModeOwnerUid, cb));
}
}
return onSetMode(mode, newModeOwnerPid, newModeOwnerUid, callingPackageName);
}
```
接下来逐行解释:
1. `if (DEBUG_MODE) { Log.d(TAG, "setMode(" + mode + ")"); }`
这个if语句判断是否需要打印调试信息。如果需要,则调用Log.d()函数输出调试信息,包括当前设置的音频模式(mode)。
2. `if (callingPackageName != null) { ... }`
这个if语句判断是否提供了调用者的包名。如果提供了,则检查调用者是否有足够的权限进行操作。具体而言,如果调用者不是系统特权应用程序(privileged app),则不允许设置音频模式,会返回错误码AudioManager.MODE_INVALID。
3. `if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_AUDIO_SETTINGS) != PackageManager.PERMISSION_GRANTED) { ... }`
这个if语句检查当前调用者是否有修改音频设置的权限。如果没有,则返回错误码AudioManager.MODE_INVALID。
4. `if (mode == AudioManager.MODE_INVALID) { return AudioManager.MODE_INVALID; }`
这个if语句检查传入的音频模式是否合法。如果不合法,则直接返回错误码AudioManager.MODE_INVALID。
5. `int newModeOwnerPid = Binder.getCallingPid(); int newModeOwnerUid = Binder.getCallingUid();`
这两行代码获取当前调用者的进程ID和用户ID。
6. `synchronized (mSetModeDeathHandlers) { ... }`
这个synchronized语句块用于对mSetModeDeathHandlers对象加锁,保证多线程安全。mSetModeDeathHandlers是一个HashMap对象,用于存储SetModeDeathHandler对象(一个自定义的类,用于处理音频模式设置时Binder线程的死亡通知),以PID为键值。
7. `if (cb == null) { mSetModeDeathHandlers.remove(newModeOwnerPid); } else { ... }`
这个if语句判断是否需要设置死亡通知。如果不需要,则从mSetModeDeathHandlers中移除对应的SetModeDeathHandler对象。否则,需要将该对象添加到mSetModeDeathHandlers中,并且注册Binder线程的死亡通知。
8. `return onSetMode(mode, newModeOwnerPid, newModeOwnerUid, callingPackageName);`
最后,调用onSetMode函数处理音频模式设置。具体的实现在AudioService的子类AudioServiceInternal中。
阅读全文