本文接上一篇SD卡挂载之后,上层处理,主要是创建通知,提示用户.涉及
xref: /frameworks/base/services/core/java/com/android/server/StorageManagerService.java
xref: /frameworks/base/core/java/android/os/storage/StorageManager.java
xref: /frameworks/base/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
先看下流程图:
当SD卡挂载成功,vold服务会通过binder通信通知StorageManagerService当前卷轴状态改变,从check->mount.即走到onVolumeStateChanged.
xref: /frameworks/base/services/core/java/com/android/server/StorageManagerService.java
private final IVoldListener mListener = new IVoldListener.Stub() {
......
@Override
public void onVolumeStateChanged(String volId, int state) {
synchronized (mLock) {
final VolumeInfo vol = mVolumes.get(volId);
if (vol != null) {
final int oldState = vol.state;
final int newState = state;
vol.state = newState;
onVolumeStateChangedLocked(vol, oldState, newState);
}
}
}
IStorageEventListener注册在RemoteCallbackList中,从而mCallbacks调用notifyVolumeStateChanged就是调用
IStorageEventListener里面的notifyVolumeStateChanged.这里其实是对binder机制的一种封装.跨进程通信还是靠的binder.
RemoteCallbackList.java的定义
负责维护远程接口列表,特别是用于执行service 跟 clients之间回调的。
具体的讲
1. 保持跟踪 注册的IInterface 回调,通过这些回调的 unique IBindler(通过调用IInterface.asBindler())。
2. 将每一个注册的借口通过IBindler.DeathRecipient绑定,这样若进程被清楚就可以清除list。
3. 锁定 interfaces列表处理多线程的调用,然后不需要持有lock的方式,用线程安全的方式遍历列表
用这个类,可以简单的创建一个实例,通过其register(E)和unregister(E)函数注册或注销clients。
通过beginBroadcast(), getBroadcastItem(int), finishBroadcast().回调给client。
如果一个注册了callback的进程消失了,这个类会自动将其从list中清除。
可以通过onCallbackDied(E)对这个注册的callback进行额外处理。
@GuardedBy("mLock")
private void onVolumeStateChangedLocked(VolumeInfo vol, int oldState, int newState) {
......
//省略部分代码
//这个mCallbacks是Callbacks对象,是StorageManagerService的内部类,所以这里调用的是Callbacks里面的notifyVolumeStateChanged.
mCallbacks.notifyVolumeStateChanged(vol, oldState, newState);
......
}
再看下Callbacks这个类.new了一个RemoteCallbackList,并注册了IStorageEventListener这个binder,也就是mCallbacks关联了IStorageEventListener,相当于拿到了这个对象.可以调用里面的方法onVolumeStateChanged
private static class Callbacks extends Handler {
......
private final RemoteCallbackList
mCallbacks = new RemoteCallbackList<>();
public Callbacks(Looper looper) {
super(looper);
}
public void register(IStorageEventListener callback) {
mCallbacks.register(callback);
}
public void unregister(IStorageEventListener callback) {
mCallbacks.unregister(callback);
}
@Override
public void handleMessage(Message msg) {
final SomeArgs args = (SomeArgs) msg.obj;
final int n = mCallbacks.beginBroadcast();
for (int i = 0; i < n; i++) {
//这里拿到的callback就是IStorageEventListener对象了.可以调用里面的方法.
final IStorageEventListener callback = mCallbacks.getBroadcastItem(i);
try {
invokeCallback(callback, msg.what, args);
} catch (RemoteException ignored) {
}
}
mCallbacks.finishBroadcast();
args.recycle();
}
private void invokeCallback(IStorageEventListener callback, int what, SomeArgs args)
throws RemoteException {
switch (what) {
case MSG_STORAGE_STATE_CHANGED: {
callback.onStorageStateChanged((String) args.arg1, (String) args.arg2,
(String) args.arg3);
break;
}
case MSG_VOLUME_STATE_CHANGED: {
//调用IStorageEventListener的方法.这里通过binder机制跨进程调到了StorageManager.
callback.onVolumeStateChanged((VolumeInfo) args.arg1, args.argi2, args.argi3);
break;
}
case MSG_VOLUME_RECORD_CHANGED: {
callback.onVolumeRecordChanged((VolumeRecord) args.arg1);
break;
}
case MSG_VOLUME_FORGOTTEN: {
callback.onVolumeForgotten((String) args.arg1);
break;
}
case MSG_DISK_SCANNED: {
callback.onDiskScanned((DiskInfo) args.arg1, args.argi2);
break;
}
case MSG_DISK_DESTROYED: {
callback.onDiskDestroyed((DiskInfo) args.arg1);
break;
}
}
}
private void notifyStorageStateChanged(String path, String oldState, String newState) {
final SomeArgs args = SomeArgs.obtain();
args.arg1 = path;
args.arg2 = oldState;
args.arg3 = newState;
obtainMessage(MSG_STORAGE_STATE_CHANGED, args).sendToTarget();
}
private void notifyVolumeStateChanged(VolumeInfo vol, int oldState, int newState) {
final SomeArgs args = SomeArgs.obtain();
args.arg1 = vol.clone();
args.argi2 = oldState;
args.argi3 = newState;
obtainMessage(MSG_VOLUME_STATE_CHANGED, args).sendToTarget();
}
......
}
StorageManagerService通过binder机制,调用IStorageEventListener的onVolumeStateChanged.而IStorageEventListener的
真正实现在StorageManager中,可以看到StorageEventListenerDelegate实现了IStorageEventListener.Stub
xref: /frameworks/base/core/java/android/os/storage/StorageManager.java
private static class StorageEventListenerDelegate extends IStorageEventListener.Stub implements
Handler.Callback {
......
public StorageEventListenerDelegate(StorageEventListener callback, Looper looper) {
//传进来的callback就是StorageEventListener,而StorageNotification通过getService拿到StorageManager对象,在通过
//registerListener(mListener);这样mCallback.onVolumeStateChanged就调到了StorageEventListener的onVolumeStateChanged.
mCallback = callback;
mHandler = new Handler(looper, this);
}
@Override
public boolean handleMessage(Message msg) {
final SomeArgs args = (SomeArgs) msg.obj;
switch (msg.what) {
case MSG_STORAGE_STATE_CHANGED:
mCallback.onStorageStateChanged((String) args.arg1, (String) args.arg2,
(String) args.arg3);
args.recycle();
return true;
case MSG_VOLUME_STATE_CHANGED:
mCallback.onVolumeStateChanged((VolumeInfo) args.arg1, args.argi2, args.argi3);
args.recycle();
return true;
......
args.recycle();
return false;
}
//StorageManagerService调用的是此处的onVolumeStateChanged,通过发送消息MSG_VOLUME_STATE_CHANGED,在handleMessage调用
//StorageNotification的onVolumeStateChanged.
@Override
public void onVolumeStateChanged(VolumeInfo vol, int oldState, int newState) {
final SomeArgs args = SomeArgs.obtain();
args.arg1 = vol;
args.argi2 = oldState;
args.argi3 = newState;
mHandler.obtainMessage(MSG_VOLUME_STATE_CHANGED, args).sendToTarget();
}
}
xref: /frameworks/base/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
@Override
public void start() {
mNotificationManager = mContext.getSystemService(NotificationManager.class);
mStorageManager = mContext.getSystemService(StorageManager.class);
//把StorageEventListener的实现,注册到StorageManager.
mStorageManager.registerListener(mListener);
......
}
private final StorageEventListener mListener = new StorageEventListener() {
@Override
public void onVolumeStateChanged(VolumeInfo vol, int oldState, int newState) {
onVolumeStateChangedInternal(vol);
}
private void onVolumeStateChangedInternal(VolumeInfo vol) {
switch (vol.getType()) {
case VolumeInfo.TYPE_PRIVATE:
onPrivateVolumeStateChangedInternal(vol);
break;
case VolumeInfo.TYPE_PUBLIC:
onPublicVolumeStateChangedInternal(vol);
break;
}
}
//当StorageManager那边接收到StorageManagerService的消息,会回调此处.从而根据不同的类型创建不同的通知.
private void onPublicVolumeStateChangedInternal(VolumeInfo vol) {
Log.d(TAG, "Notifying about public volume: " + vol.toString());
final Notification notif;
switch (vol.getState()) {
......
case VolumeInfo.STATE_MOUNTED:
case VolumeInfo.STATE_MOUNTED_READ_ONLY:
notif = onVolumeMounted(vol);
break;
......
default:
notif = null;
break;
}
if (notif != null) {
mNotificationManager.notifyAsUser(vol.getId(), SystemMessage.NOTE_STORAGE_PUBLIC,
notif, UserHandle.of(vol.getMountUserId()));
} else {
mNotificationManager.cancelAsUser(vol.getId(), SystemMessage.NOTE_STORAGE_PUBLIC,
UserHandle.of(vol.getMountUserId()));
}
}
//这里只列出挂载的实现.至此,通知就创建完毕了.在通知栏就可以显示相关通知了.
private Notification onVolumeMounted(VolumeInfo vol) {
final VolumeRecord rec = mStorageManager.findRecordByUuid(vol.getFsUuid());
final DiskInfo disk = vol.getDisk();
// Don't annoy when user dismissed in past. (But make sure the disk is adoptable; we
// used to allow snoozing non-adoptable disks too.)
if (rec.isSnoozed() && disk.isAdoptable()) {
return null;
}
if (disk.isAdoptable() && !rec.isInited()) {
final CharSequence title = disk.getDescription();
final CharSequence text = mContext.getString(
R.string.ext_media_new_notification_message, disk.getDescription());
final PendingIntent initIntent = buildInitPendingIntent(vol);
return buildNotificationBuilder(vol, title, text)
.addAction(new Action(R.drawable.ic_settings_24dp,
mContext.getString(R.string.ext_media_init_action), initIntent))
.addAction(new Action(R.drawable.ic_eject_24dp,
mContext.getString(R.string.ext_media_unmount_action),
buildUnmountPendingIntent(vol)))
.setContentIntent(initIntent)
.setDeleteIntent(buildSnoozeIntent(vol.getFsUuid()))
.build();
} else {
final CharSequence title = disk.getDescription();
final CharSequence text = mContext.getString(
R.string.ext_media_ready_notification_message, disk.getDescription());
final PendingIntent browseIntent = buildBrowsePendingIntent(vol);
final Notification.Builder builder = buildNotificationBuilder(vol, title, text)
.addAction(new Action(R.drawable.ic_folder_24dp,
mContext.getString(R.string.ext_media_browse_action),
browseIntent))
.addAction(new Action(R.drawable.ic_eject_24dp,
mContext.getString(R.string.ext_media_unmount_action),
buildUnmountPendingIntent(vol)))
.setContentIntent(browseIntent)
.setCategory(Notification.CATEGORY_SYSTEM);
// Non-adoptable disks can't be snoozed.
if (disk.isAdoptable()) {
builder.setDeleteIntent(buildSnoozeIntent(vol.getFsUuid()));
}
return builder.build();
}
}
以上就是vold服务挂载完毕后通知上层的处理流程.从StorageManagerService到StorageManager在到StorageNotification,利用IStorageEventListener.aidl和StorageEventListener.java,谷歌巧妙的实现了跨进程通信,还是值得看下的.
参考:
https://blog.csdn.net/wangxueming/article/details/51189751