選擇MTP,PTP,UMS的選項介面就定義在UsbSettings.java,選擇其中一個選項時會執行以下代碼。
packages/apps/Settings/src/com/android/settings/deviceinfo/UsbSettings.java
if (preference == mMtp) { mUsbManager.setCurrentFunction(UsbManager.USB_FUNCTION_MTP, true); updateToggles(UsbManager.USB_FUNCTION_MTP); } else if (preference == mPtp) { mUsbManager.setCurrentFunction(UsbManager.USB_FUNCTION_PTP, true); updateToggles(UsbManager.USB_FUNCTION_PTP); } else if(preference == mUms) { mUsbManager.setCurrentFunction(UsbManager.USB_FUNCTION_MASS_STORAGE, true); updateToggles(UsbManager.USB_FUNCTION_MASS_STORAGE); }
updateToggle就是去讓執行某些選項的選中與取消工作。
其中最重要的是mUsbManager.setCurrentFunction(),mUsbManger是這樣得到的:
@Override public void onCreate(Bundle icicle) { super.onCreate(icicle); mUsbManager = (UsbManager)getSystemService(Context.USB_SERVICE); }
它的實現在frameworks/base/core/java/android/hardware/usb/UsbManager.java。
它的介面實現在frameworks/base/core/java/android/hardware/usb/IUsbManager.aidl
frameworks/base/services/java/com/android/server/usb/UsbService.java
/** * UsbService manages all USB related state, including both host and device support. * Host related events and calls are delegated to UsbHostManager, and device related * support is delegated to UsbDeviceManager. */ public class UsbService extends IUsbManager.Stub { private final Context mContext; private UsbDeviceManager mDeviceManager; private UsbHostManager mHostManager; private final UsbSettingsManager mSettingsManager;
這個介面就是"com.android.settings.UsbSettings" Activity。在frameworks/base/services/java/com/android/server/usb/UsbDeviceManager.java中被調用。
如果你選擇了USB調試功能,還會彈出"com.android.settings.DevelopmentSettings" Activity,也是在UsbDeviceManager.java中被調用。關於UsbDevcieManager,我們以後再細看。
如果你選擇了UMS,還會彈出"com.android.systemui.usb.UsbStorageActivity" Activity,就是“開啟USB存放裝置”的介面。它就義在定義在:
frameworks/base/packages/SystemUI/src/com/android/systemui/usb/UsbStorageActivity.java。
這些介面只有在插入USB時才會有通知顯示。在沒有插USB的情況下,有些介面是沒有入口的。我們就以UsbStorageActivity為例,介紹一下這些通知是怎麼彈出來的。
通知是怎麼彈出來的
frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
// storage mStorageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE); mStorageManager.registerListener( new com.android.systemui.usb.StorageNotification(context));
這裡註冊了監聽函數com.android.systemui.usb.StorageNotification,這個只是針對Phone,對於平板,有tablet/TabletStatusBarPolicy.java
我們來看一下註冊的com.android.systemui.usb.StorageNotification
frameworks/base/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
public class StorageNotification extends StorageEventListener { private static final String TAG = "StorageNotification"; public StorageNotification(Context context) { mContext = context; mStorageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE); final boolean connected = mStorageManager.isUsbMassStorageConnected(); Slog.d(TAG, String.format( "Startup with UMS connection %s (media state %s)", mUmsAvailable, Environment.getExternalStorageState())); HandlerThread thr = new HandlerThread("SystemUI StorageNotification"); thr.start(); mAsyncEventHandler = new Handler(thr.getLooper()); onUsbMassStorageConnectionChanged(connected); }
在建構函式裡就調用了onUsbMassStorageConnectionChanged函數,它最終會調到updateUsbMassStorageNotification(),
/** * Update the state of the USB mass storage notification */ void updateUsbMassStorageNotification(boolean available) { if (available) { Intent intent = new Intent(); intent.setClass(mContext, com.android.systemui.usb.UsbStorageActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); PendingIntent pi = PendingIntent.getActivity(mContext, 0, intent, 0); setUsbStorageNotification( com.android.internal.R.string.usb_storage_notification_title, com.android.internal.R.string.usb_storage_notification_message, com.android.internal.R.drawable.stat_sys_data_usb, false, true, pi); } else { setUsbStorageNotification(0, 0, 0, false, false, null); } }
也就是說UsbStorageActivity和StorageNotification綁定在了一起,什麼時候彈出這個通知,就可以進入這個Activity了。
如果串連了USB,就會在通知欄裡顯示USB選項的通知。如果沒有串連,就會把這個通知給取消掉。那我們看一下,這個通知是怎麼彈出來的。
StorageManager
frameworks/base/core/java/android/os/storage/StorageManager.java
public void registerListener(StorageEventListener listener) { if (listener == null) { return; } synchronized (mListeners) { mListeners.add(new ListenerDelegate(listener)); } }
mListeners會被私人成員MountServiceBinderListener用到,而MountServiceBinderListener又是繼承自IMountServiceListener.Stub,在建構函式裡被註冊。
public StorageManager(Looper tgtLooper) throws RemoteException { mMountService = IMountService.Stub.asInterface(ServiceManager.getService("mount")); if (mMountService == null) { Log.e(TAG, "Unable to connect to mount service! - is it running yet?"); return; } mTgtLooper = tgtLooper; mBinderListener = new MountServiceBinderListener(); mMountService.registerListener(mBinderListener); }
所以關鍵還是在mMountService。