Android frameworks 开发总结之十一
1.查看android关机前的log
有时候我们在没有连接电脑的情况下,会在测试的时候突然机器关机. 这个时候如果查看 log信息就看不到了。测试前可以执行下面的命令,之后再进行测试.
$ adb shell
$ nohup logcat > /sdcard/xxx.log
2.android日期时间同步
关于android请求日期时间同步的具体方法在frameworks/base/core/java/android/util/NtpTrustedTime.java文件中的forceSync方法中
3.SD card mount 和unmount以及notification
关于sdcard mount和unmount的代码: frameworks/base/services/core/java/com/android/server/StorageManagerService.java.
SD card在mount或之unmount成功之后发送的通知:
frameworks/base/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
在arashi的测试过程中要求在多用户的情况下,sdcard不能被认到,解决办法是从两个部分处理。
A.在外置sdcard成功mount之后,检测如果是外置sdcard,则进行unmount的操作。
private void mount(VolumeInfo vol) {
try {
// TODO(b/135341433): Remove paranoid logging when FUSE is stable
Slog.i(TAG, "Mounting volume " + vol);
mVold.mount(vol.id, vol.mountFlags, vol.mountUserId, new IVoldMountCallback.Stub() {
@Override
public boolean onVolumeChecking(FileDescriptor fd, String path,
String internalPath) {
vol.path = path;
vol.internalPath = internalPath;
ParcelFileDescriptor pfd = new ParcelFileDescriptor(fd);
try {
mStorageSessionController.onVolumeMount(pfd, vol);
return true;
} catch (ExternalStorageServiceException e) {
Slog.e(TAG, "Failed to mount volume " + vol, e);
int nextResetSeconds = FAILED_MOUNT_RESET_TIMEOUT_SECONDS;
Slog.i(TAG, "Scheduling reset in " + nextResetSeconds + "s");
mHandler.removeMessages(H_RESET);
mHandler.sendMessageDelayed(mHandler.obtainMessage(H_RESET),
TimeUnit.SECONDS.toMillis(nextResetSeconds));
return false;
} finally {
try {
pfd.close();
} catch (Exception e) {
Slog.e(TAG, "Failed to close FUSE device fd", e);
}
}
}
});
Slog.i(TAG, "Mounted volume " + vol);
if(!vol.path.contains("emulated")){
UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
mExternalVolumeId = vol.getId();
if(userManager.getUserCount() > 1){ //检测当且用户个数是否是两个或以上
unmount(vol); //进行unmount操作
mExternalVolumeId = null;
}
}
} catch (Exception e) {
Slog.wtf(TAG, e);
}
}
在settings → storage中如果unmount之后会显示enject, 这个时候需要在packages/apps/Settings/src/com/android/settings/deviceinfo/StorageSettings.java文件中隐藏外置sdcard的显示
private synchronized void refresh() {
...
mInternalCategory.addPreference(mInternalSummary);
UserManager userManager = (UserManager)getPrefContext().getSystemService(Context.USER_SERVICE);
....
for (VolumeInfo vol : volumes) {
if (vol.getType() == VolumeInfo.TYPE_PRIVATE) {
....
} else if (vol.getType() == VolumeInfo.TYPE_PUBLIC
|| vol.getType() == VolumeInfo.TYPE_STUB) {
if(userManager.getUserCount() <= 1) {
mExternalCategory.addPreference(
new StorageVolumePreference(context, vol, 0));
}
}
}
....
// Show unsupported disks to give a chance to init
final List<DiskInfo> disks = mStorageManager.getDisks();
for (DiskInfo disk : disks) {
if (disk.volumeCount == 0 && disk.size > 0) {
....
if(userManager.getUserCount() <= 1) {
mExternalCategory.addPreference(pref);
}
}
}
...
if (mExternalCategory.getPreferenceCount() > 0 && userManager.getUserCount() <= 1) {
getPreferenceScreen().addPreference(mExternalCategory);
}
...
}
B.在创建user或者Guest完成之后,如果外置sdcard已经mount, 则进行unmount操作,通过广播的方式通知StorageManagerService.java。
package/apps/src/com/android/settings/users/UserSettings.java
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MESSAGE_UPDATE_LIST:
updateUserList();
break;
case MESSAGE_USER_CREATED:
sendUnmountBroadcast(); //user 创建完成发送广播
onUserCreated(msg.arg1);
break;
}
}
};
…
@Override
public boolean onPreferenceClick(Preference pref) {
if (pref == mMePreference) {
…...
} else if (pref == mAddGuest) {
mAddGuest.setEnabled(false); // prevent multiple tap issue
UserInfo guest = mUserManager.createGuest(
getContext(), getString(com.android.settingslib.R.string.user_guest));
sendUnmountBroadcast();//Guest 创建完成发送广播
openUserDetails(guest, true);
return true;
}
return false;
}