зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-c to fx-team a=merge
This commit is contained in:
Коммит
ba352466f1
|
@ -19,13 +19,13 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="de7235e41f36a23a31c5e47218473c0cc471b019"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="df39c463259d348396ef7f143c2c780eeb8f02d8"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3bb61a27cd2941b2ba9b616a11aaa44269210396"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
|
||||
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="f0592d4814d738e3f8d840915ef799c13601bdef"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="dbc46f0bc269791c52becbef22f84c63469ee8be"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="0688d2e417602961fec3847db1d0788cd0bd49a4"/>
|
||||
<!-- Stock Android things -->
|
||||
<project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
|
||||
<project name="platform/bionic" path="bionic" revision="c72b8f6359de7ed17c11ddc9dfdde3f615d188a9"/>
|
||||
|
|
|
@ -17,10 +17,10 @@
|
|||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="de7235e41f36a23a31c5e47218473c0cc471b019"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="df39c463259d348396ef7f143c2c780eeb8f02d8"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3bb61a27cd2941b2ba9b616a11aaa44269210396"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="dbc46f0bc269791c52becbef22f84c63469ee8be"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="0688d2e417602961fec3847db1d0788cd0bd49a4"/>
|
||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
||||
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
|
||||
<!-- Stock Android things -->
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="1865c6639c51f0290d5778adef146147d5d6a5f0">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="de7235e41f36a23a31c5e47218473c0cc471b019"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="df39c463259d348396ef7f143c2c780eeb8f02d8"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3bb61a27cd2941b2ba9b616a11aaa44269210396"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
|
@ -23,7 +23,7 @@
|
|||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
||||
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="dbc46f0bc269791c52becbef22f84c63469ee8be"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="0688d2e417602961fec3847db1d0788cd0bd49a4"/>
|
||||
<!-- Stock Android things -->
|
||||
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="f92a936f2aa97526d4593386754bdbf02db07a12"/>
|
||||
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="6e47ff2790f5656b5b074407829ceecf3e6188c4"/>
|
||||
|
|
|
@ -19,13 +19,13 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="de7235e41f36a23a31c5e47218473c0cc471b019"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="df39c463259d348396ef7f143c2c780eeb8f02d8"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3bb61a27cd2941b2ba9b616a11aaa44269210396"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
|
||||
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="f0592d4814d738e3f8d840915ef799c13601bdef"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="dbc46f0bc269791c52becbef22f84c63469ee8be"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="0688d2e417602961fec3847db1d0788cd0bd49a4"/>
|
||||
<!-- Stock Android things -->
|
||||
<project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
|
||||
<project name="platform/bionic" path="bionic" revision="c72b8f6359de7ed17c11ddc9dfdde3f615d188a9"/>
|
||||
|
|
|
@ -17,10 +17,10 @@
|
|||
</project>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="de7235e41f36a23a31c5e47218473c0cc471b019"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="df39c463259d348396ef7f143c2c780eeb8f02d8"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3bb61a27cd2941b2ba9b616a11aaa44269210396"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="dbc46f0bc269791c52becbef22f84c63469ee8be"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="0688d2e417602961fec3847db1d0788cd0bd49a4"/>
|
||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
||||
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
|
||||
<!-- Stock Android things -->
|
||||
|
|
|
@ -4,6 +4,6 @@
|
|||
"remote": "",
|
||||
"branch": ""
|
||||
},
|
||||
"revision": "f97d63cd9df3ebafe6baffea6b6d79c50a66fa94",
|
||||
"revision": "0aa0d2ae3f0ee2215c18808c88d9366666536e9b",
|
||||
"repo_path": "/integration/gaia-central"
|
||||
}
|
||||
|
|
|
@ -17,12 +17,12 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="de7235e41f36a23a31c5e47218473c0cc471b019"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="df39c463259d348396ef7f143c2c780eeb8f02d8"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3bb61a27cd2941b2ba9b616a11aaa44269210396"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="dbc46f0bc269791c52becbef22f84c63469ee8be"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="0688d2e417602961fec3847db1d0788cd0bd49a4"/>
|
||||
<!-- Stock Android things -->
|
||||
<project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
|
||||
<project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="de7235e41f36a23a31c5e47218473c0cc471b019"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="df39c463259d348396ef7f143c2c780eeb8f02d8"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3bb61a27cd2941b2ba9b616a11aaa44269210396"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
|
|
|
@ -17,10 +17,10 @@
|
|||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="de7235e41f36a23a31c5e47218473c0cc471b019"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="df39c463259d348396ef7f143c2c780eeb8f02d8"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3bb61a27cd2941b2ba9b616a11aaa44269210396"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="dbc46f0bc269791c52becbef22f84c63469ee8be"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="0688d2e417602961fec3847db1d0788cd0bd49a4"/>
|
||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
||||
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
|
||||
<!-- Stock Android things -->
|
||||
|
|
|
@ -17,12 +17,12 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="de7235e41f36a23a31c5e47218473c0cc471b019"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="df39c463259d348396ef7f143c2c780eeb8f02d8"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3bb61a27cd2941b2ba9b616a11aaa44269210396"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="dbc46f0bc269791c52becbef22f84c63469ee8be"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="0688d2e417602961fec3847db1d0788cd0bd49a4"/>
|
||||
<project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
|
||||
<!-- Stock Android things -->
|
||||
<project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include <android/log.h>
|
||||
#include <cutils/properties.h>
|
||||
|
||||
#include "AutoMounter.h"
|
||||
#include "nsVolumeService.h"
|
||||
|
@ -26,7 +27,9 @@
|
|||
#include "mozilla/Hal.h"
|
||||
#include "mozilla/StaticPtr.h"
|
||||
#include "MozMtpServer.h"
|
||||
#include "MozMtpStorage.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsCharSeparatedTokenizer.h"
|
||||
#include "nsMemory.h"
|
||||
#include "nsString.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
@ -90,6 +93,13 @@ USING_MTP_NAMESPACE
|
|||
namespace mozilla {
|
||||
namespace system {
|
||||
|
||||
#define SYS_USB_CONFIG "sys.usb.config"
|
||||
#define PERSIST_SYS_USB_CONFIG "persist.sys.usb.config"
|
||||
|
||||
#define USB_FUNC_ADB "adb"
|
||||
#define USB_FUNC_MTP "mtp"
|
||||
#define USB_FUNC_UMS "mass_storage"
|
||||
|
||||
class AutoMounter;
|
||||
|
||||
static void SetAutoMounterStatus(int32_t aStatus);
|
||||
|
@ -115,7 +125,9 @@ IsUsbCablePluggedIn()
|
|||
if (access(ICS_SYS_USB_STATE, F_OK) == 0) {
|
||||
char usbState[20];
|
||||
if (ReadSysFile(ICS_SYS_USB_STATE, usbState, sizeof(usbState))) {
|
||||
return strcmp(usbState, "CONFIGURED") == 0;
|
||||
DBG("IsUsbCablePluggedIn: state = '%s'", usbState);
|
||||
return strcmp(usbState, "CONFIGURED") == 0 ||
|
||||
strcmp(usbState, "CONNECTED") == 0;
|
||||
}
|
||||
ERR("Error reading file '%s': %s", ICS_SYS_USB_STATE, strerror(errno));
|
||||
return false;
|
||||
|
@ -129,6 +141,26 @@ IsUsbCablePluggedIn()
|
|||
#endif
|
||||
}
|
||||
|
||||
static bool
|
||||
IsUsbConfigured()
|
||||
{
|
||||
if (access(ICS_SYS_USB_STATE, F_OK) == 0) {
|
||||
char usbState[20];
|
||||
if (ReadSysFile(ICS_SYS_USB_STATE, usbState, sizeof(usbState))) {
|
||||
DBG("IsUsbConfigured: state = '%s'", usbState);
|
||||
return strcmp(usbState, "CONFIGURED") == 0;
|
||||
}
|
||||
ERR("Error reading file '%s': %s", ICS_SYS_USB_STATE, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
bool configured;
|
||||
if (ReadSysFile(GB_SYS_USB_CONFIGURED, &configured)) {
|
||||
return configured;
|
||||
}
|
||||
ERR("Error reading file '%s': %s", GB_SYS_USB_CONFIGURED, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
// The AutoVolumeManagerStateObserver allows the AutoMounter to know when
|
||||
|
@ -144,7 +176,7 @@ public:
|
|||
class AutoVolumeEventObserver : public Volume::EventObserver
|
||||
{
|
||||
public:
|
||||
virtual void Notify(Volume * const & aEvent);
|
||||
virtual void Notify(Volume* const& aEvent);
|
||||
};
|
||||
|
||||
class AutoMounterResponseCallback : public VolumeResponseCallback
|
||||
|
@ -174,7 +206,8 @@ public:
|
|||
typedef nsTArray<RefPtr<Volume>> VolumeArray;
|
||||
|
||||
AutoMounter()
|
||||
: mResponseCallback(new AutoMounterResponseCallback),
|
||||
: mState(STATE_IDLE),
|
||||
mResponseCallback(new AutoMounterResponseCallback),
|
||||
mMode(AUTOMOUNTER_DISABLE)
|
||||
{
|
||||
VolumeManager::RegisterStateObserver(&mVolumeManagerStateObserver);
|
||||
|
@ -232,21 +265,34 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
void UpdateState();
|
||||
|
||||
void ConfigureUsbFunction(const char* aUsbFunc);
|
||||
|
||||
void StartMtpServer();
|
||||
void StopMtpServer();
|
||||
|
||||
void UpdateState();
|
||||
void StartUmsSharing();
|
||||
void StopUmsSharing();
|
||||
|
||||
|
||||
const char* ModeStr(int32_t aMode)
|
||||
{
|
||||
switch (aMode) {
|
||||
case AUTOMOUNTER_DISABLE: return "Disable";
|
||||
case AUTOMOUNTER_ENABLE: return "Enable";
|
||||
case AUTOMOUNTER_ENABLE_UMS: return "Enable-UMS";
|
||||
case AUTOMOUNTER_DISABLE_WHEN_UNPLUGGED: return "DisableWhenUnplugged";
|
||||
case AUTOMOUNTER_ENABLE_MTP: return "Enable-MTP";
|
||||
}
|
||||
return "??? Unknown ???";
|
||||
}
|
||||
|
||||
bool IsModeEnabled(int32_t aMode)
|
||||
{
|
||||
return aMode == AUTOMOUNTER_ENABLE_MTP ||
|
||||
aMode == AUTOMOUNTER_ENABLE_UMS;
|
||||
}
|
||||
|
||||
void SetMode(int32_t aMode)
|
||||
{
|
||||
if ((aMode == AUTOMOUNTER_DISABLE_WHEN_UNPLUGGED) &&
|
||||
|
@ -256,8 +302,8 @@ public:
|
|||
aMode = AUTOMOUNTER_DISABLE;
|
||||
}
|
||||
|
||||
if ((aMode == AUTOMOUNTER_DISABLE) &&
|
||||
(mMode == AUTOMOUNTER_ENABLE) && IsUsbCablePluggedIn()) {
|
||||
if (aMode == AUTOMOUNTER_DISABLE &&
|
||||
mMode == AUTOMOUNTER_ENABLE_UMS && IsUsbCablePluggedIn()) {
|
||||
// On many devices (esp non-Samsung), we can't force the disable, so we
|
||||
// need to defer until the USB cable is actually unplugged.
|
||||
// See bug 777043.
|
||||
|
@ -346,10 +392,64 @@ public:
|
|||
|
||||
private:
|
||||
|
||||
enum STATE
|
||||
{
|
||||
// IDLE - Nothing is being shared
|
||||
STATE_IDLE,
|
||||
|
||||
// We've detected that conditions are right to enable mtp. So we've
|
||||
// set sys.usb.config to include mtp, and we're waiting for the USB
|
||||
// subsystem to be "configured". Once mtp shows up in
|
||||
// then we know
|
||||
// that its been configured and we can open /dev/mtp_usb
|
||||
STATE_MTP_CONFIGURING,
|
||||
|
||||
// mtp has been configured (i.e. mtp now shows up in
|
||||
// /sys/devices/virtual/android_usb/android0/functions so we can start
|
||||
// the mtp server.
|
||||
STATE_MTP_STARTED,
|
||||
|
||||
// The mtp server has reported sessionStarted. We'll leave this state
|
||||
// when we receive sessionEnded.
|
||||
STATE_MTP_CONNECTED,
|
||||
|
||||
// We've added mass_storage (aka UMS) to sys.usb.config and we're waiting for
|
||||
// mass_storage to appear in /sys/devices/virtual/android_usb/android0/functions
|
||||
STATE_UMS_CONFIGURING,
|
||||
|
||||
// mass_storage has been configured and we can start sharing once the user
|
||||
// enables it.
|
||||
STATE_UMS_CONFIGURED,
|
||||
};
|
||||
|
||||
const char *StateStr(STATE aState)
|
||||
{
|
||||
switch (aState) {
|
||||
case STATE_IDLE: return "IDLE";
|
||||
case STATE_MTP_CONFIGURING: return "MTP_CONFIGURING";
|
||||
case STATE_MTP_CONNECTED: return "MTP_CONNECTED";
|
||||
case STATE_MTP_STARTED: return "MTP_STARTED";
|
||||
case STATE_UMS_CONFIGURING: return "UMS_CONFIGURING";
|
||||
case STATE_UMS_CONFIGURED: return "UMS_CONFIGURED";
|
||||
}
|
||||
return "STATE_???";
|
||||
}
|
||||
|
||||
void SetState(STATE aState)
|
||||
{
|
||||
const char *oldStateStr = StateStr(mState);
|
||||
mState = aState;
|
||||
const char *newStateStr = StateStr(mState);
|
||||
LOG("AutoMounter state changed from %s to %s", oldStateStr, newStateStr);
|
||||
}
|
||||
|
||||
STATE mState;
|
||||
|
||||
AutoVolumeEventObserver mVolumeEventObserver;
|
||||
AutoVolumeManagerStateObserver mVolumeManagerStateObserver;
|
||||
RefPtr<VolumeResponseCallback> mResponseCallback;
|
||||
int32_t mMode;
|
||||
MozMtpStorage::Array mMozMtpStorage;
|
||||
};
|
||||
|
||||
static StaticRefPtr<AutoMounter> sAutoMounter;
|
||||
|
@ -405,6 +505,78 @@ AutoMounterResponseCallback::ResponseReceived(const VolumeCommand* aCommand)
|
|||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
IsUsbFunctionEnabled(const char* aConfig, const char* aUsbFunc)
|
||||
{
|
||||
nsAutoCString config(aConfig);
|
||||
nsCCharSeparatedTokenizer tokenizer(config, ',');
|
||||
|
||||
while (tokenizer.hasMoreTokens()) {
|
||||
nsAutoCString token(tokenizer.nextToken());
|
||||
if (token.Equals(aUsbFunc)) {
|
||||
DBG("IsUsbFunctionEnabled('%s', '%s'): returning true", aConfig, aUsbFunc);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
DBG("IsUsbFunctionEnabled('%s', '%s'): returning false", aConfig, aUsbFunc);
|
||||
return false;
|
||||
}
|
||||
|
||||
static void
|
||||
SetUsbFunction(const char* aUsbFunc)
|
||||
{
|
||||
char oldSysUsbConfig[PROPERTY_VALUE_MAX];
|
||||
property_get(SYS_USB_CONFIG, oldSysUsbConfig, "");
|
||||
|
||||
if (IsUsbFunctionEnabled(oldSysUsbConfig, aUsbFunc)) {
|
||||
// The function is already configured. Nothing else to do.
|
||||
DBG("SetUsbFunction('%s') - already set - nothing to do", aUsbFunc);
|
||||
return;
|
||||
}
|
||||
|
||||
char newSysUsbConfig[PROPERTY_VALUE_MAX];
|
||||
|
||||
if (strcmp(aUsbFunc, USB_FUNC_MTP) == 0) {
|
||||
// We're enabling MTP. For this we'll wind up using mtp, or mtp,adb
|
||||
strlcpy(newSysUsbConfig, USB_FUNC_MTP, sizeof(newSysUsbConfig));
|
||||
} else if (strcmp(aUsbFunc, USB_FUNC_UMS) == 0) {
|
||||
// We're enabling UMS. For this we make the assumption that the persisted
|
||||
// property has mass_storage enabled.
|
||||
property_get(PERSIST_SYS_USB_CONFIG, newSysUsbConfig, "");
|
||||
} else {
|
||||
printf_stderr("AutoMounter::SetUsbFunction Unrecognized aUsbFunc '%s'\n", aUsbFunc);
|
||||
MOZ_ASSERT(0);
|
||||
return;
|
||||
}
|
||||
|
||||
// Make sure the new value that we write into sys.usb.config keeps the adb
|
||||
// (or non-adb) of the current string.
|
||||
|
||||
if (IsUsbFunctionEnabled(oldSysUsbConfig, USB_FUNC_ADB)) {
|
||||
// ADB was turned on - keep it on.
|
||||
if (!IsUsbFunctionEnabled(newSysUsbConfig, USB_FUNC_ADB)) {
|
||||
// Add adb to the new string
|
||||
strlcat(newSysUsbConfig, ",", sizeof(newSysUsbConfig));
|
||||
strlcat(newSysUsbConfig, USB_FUNC_ADB, sizeof(newSysUsbConfig));
|
||||
}
|
||||
} else {
|
||||
// ADB was turned off - keep it off
|
||||
if (IsUsbFunctionEnabled(newSysUsbConfig, USB_FUNC_ADB)) {
|
||||
// Remove ADB from the new string.
|
||||
if (strcmp(newSysUsbConfig, USB_FUNC_ADB) == 0) {
|
||||
newSysUsbConfig[0] = '\0';
|
||||
} else {
|
||||
nsAutoCString withoutAdb(newSysUsbConfig);
|
||||
withoutAdb.ReplaceSubstring( "," USB_FUNC_ADB, "");
|
||||
strlcpy(newSysUsbConfig, withoutAdb.get(), sizeof(newSysUsbConfig));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LOG("SetUsbFunction(%s) %s to '%s'", aUsbFunc, SYS_USB_CONFIG, newSysUsbConfig);
|
||||
property_set(SYS_USB_CONFIG, newSysUsbConfig);
|
||||
}
|
||||
|
||||
void
|
||||
AutoMounter::StartMtpServer()
|
||||
{
|
||||
|
@ -415,12 +587,22 @@ AutoMounter::StartMtpServer()
|
|||
LOG("Starting MtpServer");
|
||||
sMozMtpServer = new MozMtpServer();
|
||||
sMozMtpServer->Run();
|
||||
|
||||
VolumeArray::index_type volIndex;
|
||||
VolumeArray::size_type numVolumes = VolumeManager::NumVolumes();
|
||||
for (volIndex = 0; volIndex < numVolumes; volIndex++) {
|
||||
RefPtr<Volume> vol = VolumeManager::GetVolume(volIndex);
|
||||
nsRefPtr<MozMtpStorage> storage = new MozMtpStorage(vol, sMozMtpServer);
|
||||
mMozMtpStorage.AppendElement(storage);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AutoMounter::StopMtpServer()
|
||||
{
|
||||
LOG("Stopping MtpServer");
|
||||
|
||||
mMozMtpStorage.Clear();
|
||||
sMozMtpServer = nullptr;
|
||||
}
|
||||
|
||||
|
@ -465,10 +647,20 @@ AutoMounter::UpdateState()
|
|||
return;
|
||||
}
|
||||
|
||||
bool umsAvail = false;
|
||||
bool umsEnabled = false;
|
||||
bool mtpAvail = false;
|
||||
bool mtpEnabled = false;
|
||||
// Calling setprop sys.usb.config mtp,adb (or adding mass_storage) will
|
||||
// cause /sys/devices/virtual/android_usb/android0/state to go:
|
||||
// CONFIGURED -> DISCONNECTED -> CONNECTED -> CONFIGURED
|
||||
//
|
||||
// Since IsUsbCablePluggedIn returns state == CONFIGURED, it will look
|
||||
// like a cable pull and replugin.
|
||||
|
||||
bool umsAvail = false;
|
||||
bool umsConfigured = false;
|
||||
bool umsEnabled = false;
|
||||
bool mtpAvail = false;
|
||||
bool mtpConfigured = false;
|
||||
bool mtpEnabled = false;
|
||||
bool usbCablePluggedIn = IsUsbCablePluggedIn();
|
||||
|
||||
if (access(ICS_SYS_USB_FUNCTIONS, F_OK) == 0) {
|
||||
char functionsStr[60];
|
||||
|
@ -476,40 +668,149 @@ AutoMounter::UpdateState()
|
|||
ERR("Error reading file '%s': %s", ICS_SYS_USB_FUNCTIONS, strerror(errno));
|
||||
functionsStr[0] = '\0';
|
||||
}
|
||||
DBG("UpdateState: USB functions: '%s'", functionsStr);
|
||||
|
||||
bool usbConfigured = IsUsbConfigured();
|
||||
umsAvail = (access(ICS_SYS_UMS_DIRECTORY, F_OK) == 0);
|
||||
if (umsAvail) {
|
||||
umsEnabled = strstr(functionsStr, "mass_storage") != nullptr;
|
||||
umsConfigured = usbConfigured && strstr(functionsStr, USB_FUNC_UMS) != nullptr;
|
||||
umsEnabled = (mMode == AUTOMOUNTER_ENABLE_UMS) ||
|
||||
(mMode == AUTOMOUNTER_DISABLE_WHEN_UNPLUGGED) && umsConfigured;
|
||||
} else {
|
||||
umsConfigured = false;
|
||||
umsEnabled = false;
|
||||
}
|
||||
|
||||
mtpAvail = (access(ICS_SYS_MTP_DIRECTORY, F_OK) == 0);
|
||||
if (mtpAvail) {
|
||||
mtpEnabled = strstr(functionsStr, "mtp") != nullptr;
|
||||
mtpConfigured = usbConfigured && strstr(functionsStr, USB_FUNC_MTP) != nullptr;
|
||||
mtpEnabled = (mMode == AUTOMOUNTER_ENABLE_MTP) ||
|
||||
(mMode == AUTOMOUNTER_DISABLE_WHEN_UNPLUGGED) && mtpConfigured;
|
||||
} else {
|
||||
mtpConfigured = false;
|
||||
mtpEnabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool usbCablePluggedIn = IsUsbCablePluggedIn();
|
||||
bool enabled = (mMode == AUTOMOUNTER_ENABLE);
|
||||
bool enabled = mtpEnabled || umsEnabled;
|
||||
|
||||
if (mMode == AUTOMOUNTER_DISABLE_WHEN_UNPLUGGED) {
|
||||
// DISABLE_WHEN_UNPLUGGED implies already enabled.
|
||||
enabled = usbCablePluggedIn;
|
||||
if (!usbCablePluggedIn) {
|
||||
mMode = AUTOMOUNTER_DISABLE;
|
||||
mtpEnabled = false;
|
||||
umsEnabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool tryToShare = (((umsAvail && umsEnabled) || (mtpAvail && mtpEnabled))
|
||||
&& enabled && usbCablePluggedIn);
|
||||
LOG("UpdateState: ums:%d%d mtp:%d%d mode:%d usbCablePluggedIn:%d tryToShare:%d",
|
||||
umsAvail, umsEnabled, mtpAvail, mtpEnabled, mMode, usbCablePluggedIn, tryToShare);
|
||||
DBG("UpdateState: ums:A%dC%dE%d mtp:A%dC%dE%d mode:%d usb:%d mState:%s",
|
||||
umsAvail, umsConfigured, umsEnabled,
|
||||
mtpAvail, mtpConfigured, mtpEnabled,
|
||||
mMode, usbCablePluggedIn, StateStr(mState));
|
||||
|
||||
if (mtpAvail && mtpEnabled) {
|
||||
if (enabled && usbCablePluggedIn) {
|
||||
StartMtpServer();
|
||||
} else {
|
||||
StopMtpServer();
|
||||
}
|
||||
return;
|
||||
switch (mState) {
|
||||
|
||||
case STATE_IDLE:
|
||||
if (!usbCablePluggedIn) {
|
||||
// Stay in the IDLE state. We'll get a CONNECTED or CONFIGURED
|
||||
// UEvent when the usb cable is plugged in.
|
||||
break;
|
||||
}
|
||||
if (mtpEnabled) {
|
||||
if (mtpConfigured) {
|
||||
// The USB layer has already been configured. Now we can go ahead
|
||||
// and start the MTP server. This particular codepath will not
|
||||
// normally be taken, but it could happen if you stop and restart
|
||||
// b2g while sys.usb.config is set to enable mtp.
|
||||
StartMtpServer();
|
||||
SetState(STATE_MTP_STARTED);
|
||||
} else {
|
||||
// The MTP USB layer is configuring. Wait for it to finish
|
||||
// before we start the MTP server.
|
||||
SetUsbFunction(USB_FUNC_MTP);
|
||||
SetState(STATE_MTP_CONFIGURING);
|
||||
}
|
||||
} else if (umsConfigured) {
|
||||
// UMS is already configured.
|
||||
SetState(STATE_UMS_CONFIGURED);
|
||||
} else if (umsAvail) {
|
||||
// We do this whether or not UMS is enabled. With UMS, it's the
|
||||
// sharing of the volume which is significant. What is important
|
||||
// is that we don't leave it in MTP mode when MTP isn't enabled.
|
||||
SetUsbFunction(USB_FUNC_UMS);
|
||||
SetState(STATE_UMS_CONFIGURING);
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE_MTP_CONFIGURING:
|
||||
// While configuring, the USB configuration state will change from
|
||||
// CONFIGURED -> CONNECTED -> DISCONNECTED -> CONNECTED -> CONFIGURED
|
||||
// so we don't check for cable unplugged here.
|
||||
if (mtpEnabled && mtpConfigured) {
|
||||
// The USB layer has been configured. Now we can go ahead and start
|
||||
// the MTP server.
|
||||
StartMtpServer();
|
||||
SetState(STATE_MTP_STARTED);
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE_MTP_STARTED:
|
||||
if (usbCablePluggedIn) {
|
||||
if (mtpConfigured && mtpEnabled) {
|
||||
// Everything is still good. Leave the MTP server running
|
||||
break;
|
||||
}
|
||||
DBG("STATE_MTP_STARTED: About to StopMtpServer "
|
||||
"mtpConfigured = %d mtpEnabled = %d usbCablePluggedIn: %d",
|
||||
mtpConfigured, mtpEnabled, usbCablePluggedIn);
|
||||
StopMtpServer();
|
||||
if (umsAvail) {
|
||||
// Switch back to UMS
|
||||
SetUsbFunction(USB_FUNC_UMS);
|
||||
SetState(STATE_UMS_CONFIGURING);
|
||||
break;
|
||||
}
|
||||
}
|
||||
SetState(STATE_IDLE);
|
||||
break;
|
||||
|
||||
case STATE_UMS_CONFIGURING:
|
||||
// While configuring, the USB configuration state will change from
|
||||
// CONFIGURED -> CONNECTED -> DISCONNECTED -> CONNECTED -> CONFIGURED
|
||||
// so we don't check for cable unplugged here.
|
||||
if (umsConfigured) {
|
||||
SetState(STATE_UMS_CONFIGURED);
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE_UMS_CONFIGURED:
|
||||
if (usbCablePluggedIn) {
|
||||
if (mtpEnabled) {
|
||||
// MTP was enabled. Start reconfiguring.
|
||||
SetState(STATE_MTP_CONFIGURING);
|
||||
SetUsbFunction(USB_FUNC_MTP);
|
||||
break;
|
||||
}
|
||||
if (umsConfigured && umsEnabled) {
|
||||
// This is the normal state when UMS is enabled.
|
||||
break;
|
||||
}
|
||||
}
|
||||
SetState(STATE_IDLE);
|
||||
break;
|
||||
|
||||
default:
|
||||
SetState(STATE_IDLE);
|
||||
break;
|
||||
}
|
||||
|
||||
bool tryToShare = umsEnabled && usbCablePluggedIn;
|
||||
LOG("UpdateState: ums:A%dC%dE%d mtp:A%dC%dE%d mode:%d usb:%d tryToShare:%d state:%s",
|
||||
umsAvail, umsConfigured, umsEnabled,
|
||||
mtpAvail, mtpConfigured, mtpEnabled,
|
||||
mMode, usbCablePluggedIn, tryToShare, StateStr(mState));
|
||||
|
||||
bool filesOpen = false;
|
||||
static unsigned filesOpenDelayCount = 0;
|
||||
VolumeArray::index_type volIndex;
|
||||
|
@ -524,7 +825,8 @@ AutoMounter::UpdateState()
|
|||
vol->MediaPresent() ? "inserted" : "missing",
|
||||
vol->MountPoint().get(), vol->MountGeneration(),
|
||||
(int)vol->IsMountLocked(),
|
||||
vol->CanBeShared() ? (vol->IsSharingEnabled() ? (vol->IsSharing() ? "en-y" : "en-n") : "dis") : "x");
|
||||
vol->CanBeShared() ? (vol->IsSharingEnabled() ?
|
||||
(vol->IsSharing() ? "en-y" : "en-n") : "dis") : "x");
|
||||
if (vol->IsSharing() && !usbCablePluggedIn) {
|
||||
// We call SetIsSharing(true) below to indicate intent to share. This
|
||||
// causes a state change which notifys apps, and they'll close any
|
||||
|
@ -940,6 +1242,7 @@ void
|
|||
ShutdownAutoMounter()
|
||||
{
|
||||
if (sAutoMounter) {
|
||||
DBG("ShutdownAutoMounter: About to StopMtpServer");
|
||||
sAutoMounter->StopMtpServer();
|
||||
}
|
||||
sAutoMounterSetting = nullptr;
|
||||
|
|
|
@ -14,8 +14,9 @@ namespace system {
|
|||
|
||||
// AutoMounter modes
|
||||
#define AUTOMOUNTER_DISABLE 0
|
||||
#define AUTOMOUNTER_ENABLE 1
|
||||
#define AUTOMOUNTER_ENABLE_UMS 1
|
||||
#define AUTOMOUNTER_DISABLE_WHEN_UNPLUGGED 2
|
||||
#define AUTOMOUNTER_ENABLE_MTP 3
|
||||
|
||||
// Automounter statuses
|
||||
#define AUTOMOUNTER_STATUS_DISABLED 0
|
||||
|
|
|
@ -40,9 +40,9 @@ ObjectPropertyAsStr(MtpObjectProperty aProperty)
|
|||
return "MTP_PROPERTY_???";
|
||||
}
|
||||
|
||||
MozMtpDatabase::MozMtpDatabase(const char *aDir)
|
||||
MozMtpDatabase::MozMtpDatabase()
|
||||
{
|
||||
MTP_LOG("");
|
||||
MTP_LOG("constructed");
|
||||
|
||||
// We use the index into the array as the handle. Since zero isn't a valid
|
||||
// index, we stick a dummy entry there.
|
||||
|
@ -50,14 +50,12 @@ MozMtpDatabase::MozMtpDatabase(const char *aDir)
|
|||
RefPtr<DbEntry> dummy;
|
||||
|
||||
mDb.AppendElement(dummy);
|
||||
|
||||
ReadVolume("sdcard", aDir);
|
||||
}
|
||||
|
||||
//virtual
|
||||
MozMtpDatabase::~MozMtpDatabase()
|
||||
{
|
||||
MTP_LOG("");
|
||||
MTP_LOG("destructed");
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -67,7 +65,7 @@ MozMtpDatabase::AddEntry(DbEntry *entry)
|
|||
MOZ_ASSERT(mDb.Length() == entry->mHandle);
|
||||
mDb.AppendElement(entry);
|
||||
|
||||
MTP_LOG("AddEntry: Handle: 0x%08x Parent: 0x%08x Path:'%s'",
|
||||
MTP_LOG("Handle: 0x%08x Parent: 0x%08x Path:'%s'",
|
||||
entry->mHandle, entry->mParent, entry->mPath.get());
|
||||
}
|
||||
|
||||
|
@ -120,18 +118,20 @@ GetPathWithoutFileName(const nsCString& aFullPath)
|
|||
}
|
||||
|
||||
void
|
||||
MozMtpDatabase::ParseDirectory(const char *aDir, MtpObjectHandle aParent)
|
||||
MozMtpDatabase::AddDirectory(MtpStorageID aStorageID,
|
||||
const char* aPath,
|
||||
MtpObjectHandle aParent)
|
||||
{
|
||||
ScopedCloseDir dir;
|
||||
|
||||
if (!(dir = PR_OpenDir(aDir))) {
|
||||
MTP_ERR("Unable to open directory '%s'", aDir);
|
||||
if (!(dir = PR_OpenDir(aPath))) {
|
||||
MTP_ERR("Unable to open directory '%s'", aPath);
|
||||
return;
|
||||
}
|
||||
|
||||
PRDirEntry* dirEntry;
|
||||
while ((dirEntry = PR_ReadDir(dir, PR_SKIP_BOTH))) {
|
||||
nsPrintfCString filename("%s/%s", aDir, dirEntry->name);
|
||||
nsPrintfCString filename("%s/%s", aPath, dirEntry->name);
|
||||
PRFileInfo64 fileInfo;
|
||||
if (PR_GetFileInfo64(filename.get(), &fileInfo) != PR_SUCCESS) {
|
||||
MTP_ERR("Unable to retrieve file information for '%s'", filename.get());
|
||||
|
@ -140,7 +140,7 @@ MozMtpDatabase::ParseDirectory(const char *aDir, MtpObjectHandle aParent)
|
|||
|
||||
RefPtr<DbEntry> entry = new DbEntry;
|
||||
|
||||
entry->mStorageID = MTP_STORAGE_FIXED_RAM;
|
||||
entry->mStorageID = aStorageID;
|
||||
entry->mParent = aParent;
|
||||
entry->mObjectName = dirEntry->name;
|
||||
entry->mDisplayName = dirEntry->name;
|
||||
|
@ -157,40 +157,59 @@ MozMtpDatabase::ParseDirectory(const char *aDir, MtpObjectHandle aParent)
|
|||
entry->mObjectFormat = MTP_FORMAT_ASSOCIATION;
|
||||
entry->mObjectSize = 0;
|
||||
AddEntry(entry);
|
||||
ParseDirectory(filename.get(), entry->mHandle);
|
||||
AddDirectory(aStorageID, filename.get(), entry->mHandle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MozMtpDatabase::ReadVolume(const char *volumeName, const char *aDir)
|
||||
MozMtpDatabase::AddStorage(MtpStorageID aStorageID,
|
||||
const char* aPath,
|
||||
const char* aName)
|
||||
{
|
||||
//TODO: Add an assert re thread being run on
|
||||
|
||||
PRFileInfo fileInfo;
|
||||
|
||||
if (PR_GetFileInfo(aDir, &fileInfo) != PR_SUCCESS) {
|
||||
MTP_ERR("'%s' doesn't exist", aDir);
|
||||
if (PR_GetFileInfo(aPath, &fileInfo) != PR_SUCCESS) {
|
||||
MTP_ERR("'%s' doesn't exist", aPath);
|
||||
return;
|
||||
}
|
||||
if (fileInfo.type != PR_FILE_DIRECTORY) {
|
||||
MTP_ERR("'%s' isn't a directory", aDir);
|
||||
MTP_ERR("'%s' isn't a directory", aPath);
|
||||
return;
|
||||
}
|
||||
|
||||
#if 0
|
||||
RefPtr<DbEntry> entry = new DbEntry;
|
||||
|
||||
entry->mStorageID = MTP_STORAGE_FIXED_RAM;
|
||||
entry->mStorageID = aStorageID;
|
||||
entry->mParent = MTP_PARENT_ROOT;
|
||||
entry->mObjectName = volumeName;
|
||||
entry->mDisplayName = volumeName;
|
||||
entry->mPath = aDir;
|
||||
entry->mObjectName = aName;
|
||||
entry->mDisplayName = aName;
|
||||
entry->mPath = aPath;
|
||||
entry->mObjectFormat = MTP_FORMAT_ASSOCIATION;
|
||||
entry->mObjectSize = 0;
|
||||
|
||||
AddEntry(entry);
|
||||
|
||||
ParseDirectory(aDir, entry->mHandle);
|
||||
AddDirectory(aStorageID, aPath, entry->mHandle);
|
||||
#else
|
||||
AddDirectory(aStorageID, aPath, MTP_PARENT_ROOT);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
MozMtpDatabase::RemoveStorage(MtpStorageID aStorageID)
|
||||
{
|
||||
DbArray::size_type numEntries = mDb.Length();
|
||||
DbArray::index_type entryIndex;
|
||||
for (entryIndex = 1; entryIndex < numEntries; entryIndex++) {
|
||||
RefPtr<DbEntry> entry = mDb[entryIndex];
|
||||
if (entry && entry->mStorageID == aStorageID) {
|
||||
mDb[entryIndex] = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// called from SendObjectInfo to reserve a database entry for the incoming file
|
||||
|
@ -232,12 +251,12 @@ MozMtpDatabase::beginSendObject(const char* aPath,
|
|||
//virtual
|
||||
void
|
||||
MozMtpDatabase::endSendObject(const char* aPath,
|
||||
MtpObjectHandle aHandle,
|
||||
MtpObjectFormat aFormat,
|
||||
bool succeeded)
|
||||
MtpObjectHandle aHandle,
|
||||
MtpObjectFormat aFormat,
|
||||
bool aSucceeded)
|
||||
{
|
||||
MTP_LOG("Handle: 0x%08x Path: '%s'", aHandle, aPath);
|
||||
if (!succeeded) {
|
||||
if (!aSucceeded) {
|
||||
RemoveEntry(aHandle);
|
||||
}
|
||||
}
|
||||
|
@ -245,8 +264,8 @@ MozMtpDatabase::endSendObject(const char* aPath,
|
|||
//virtual
|
||||
MtpObjectHandleList*
|
||||
MozMtpDatabase::getObjectList(MtpStorageID aStorageID,
|
||||
MtpObjectFormat aFormat,
|
||||
MtpObjectHandle aParent)
|
||||
MtpObjectFormat aFormat,
|
||||
MtpObjectHandle aParent)
|
||||
{
|
||||
MTP_LOG("StorageID: 0x%08x Format: 0x%04x Parent: 0x%08x",
|
||||
aStorageID, aFormat, aParent);
|
||||
|
@ -257,11 +276,14 @@ MozMtpDatabase::getObjectList(MtpStorageID aStorageID,
|
|||
|
||||
list = new MtpObjectHandleList();
|
||||
|
||||
// Note: objects in the topmost directory of each storage area have a parent
|
||||
// of MTP_PARENT_ROOT. So we need to filter on storage ID as well.
|
||||
|
||||
DbArray::size_type numEntries = mDb.Length();
|
||||
DbArray::index_type entryIndex;
|
||||
for (entryIndex = 1; entryIndex < numEntries; entryIndex++) {
|
||||
RefPtr<DbEntry> entry = mDb[entryIndex];
|
||||
if (entry && entry->mParent == aParent) {
|
||||
if (entry && entry->mStorageID == aStorageID && entry->mParent == aParent) {
|
||||
list->push(entry->mHandle);
|
||||
}
|
||||
}
|
||||
|
@ -271,12 +293,23 @@ MozMtpDatabase::getObjectList(MtpStorageID aStorageID,
|
|||
//virtual
|
||||
int
|
||||
MozMtpDatabase::getNumObjects(MtpStorageID aStorageID,
|
||||
MtpObjectFormat aFormat,
|
||||
MtpObjectHandle aParent)
|
||||
MtpObjectFormat aFormat,
|
||||
MtpObjectHandle aParent)
|
||||
{
|
||||
MTP_LOG("");
|
||||
|
||||
return mDb.Length() - 1;
|
||||
int count = 0;
|
||||
|
||||
DbArray::size_type numEntries = mDb.Length();
|
||||
DbArray::index_type entryIndex;
|
||||
for (entryIndex = 1; entryIndex < numEntries; entryIndex++) {
|
||||
RefPtr<DbEntry> entry = mDb[entryIndex];
|
||||
if (entry && entry->mStorageID == aStorageID) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
//virtual
|
||||
|
@ -344,8 +377,8 @@ MozMtpDatabase::getSupportedDeviceProperties()
|
|||
//virtual
|
||||
MtpResponseCode
|
||||
MozMtpDatabase::getObjectPropertyValue(MtpObjectHandle aHandle,
|
||||
MtpObjectProperty aProperty,
|
||||
MtpDataPacket& aPacket)
|
||||
MtpObjectProperty aProperty,
|
||||
MtpDataPacket& aPacket)
|
||||
{
|
||||
RefPtr<DbEntry> entry = GetEntry(aHandle);
|
||||
if (!entry) {
|
||||
|
@ -417,8 +450,8 @@ GetTypeOfObjectProp(MtpObjectProperty aProperty)
|
|||
//virtual
|
||||
MtpResponseCode
|
||||
MozMtpDatabase::setObjectPropertyValue(MtpObjectHandle aHandle,
|
||||
MtpObjectProperty aProperty,
|
||||
MtpDataPacket& aPacket)
|
||||
MtpObjectProperty aProperty,
|
||||
MtpDataPacket& aPacket)
|
||||
{
|
||||
MTP_LOG("Handle: 0x%08x Property: 0x%08x", aHandle, aProperty);
|
||||
|
||||
|
@ -463,7 +496,7 @@ MozMtpDatabase::setObjectPropertyValue(MtpObjectHandle aHandle,
|
|||
//virtual
|
||||
MtpResponseCode
|
||||
MozMtpDatabase::getDevicePropertyValue(MtpDeviceProperty aProperty,
|
||||
MtpDataPacket& aPacket)
|
||||
MtpDataPacket& aPacket)
|
||||
{
|
||||
MTP_LOG("(GENERAL ERROR)");
|
||||
return MTP_RESPONSE_GENERAL_ERROR;
|
||||
|
@ -472,7 +505,7 @@ MozMtpDatabase::getDevicePropertyValue(MtpDeviceProperty aProperty,
|
|||
//virtual
|
||||
MtpResponseCode
|
||||
MozMtpDatabase::setDevicePropertyValue(MtpDeviceProperty aProperty,
|
||||
MtpDataPacket& aPacket)
|
||||
MtpDataPacket& aPacket)
|
||||
{
|
||||
MTP_LOG("(NOT SUPPORTED)");
|
||||
return MTP_RESPONSE_OPERATION_NOT_SUPPORTED;
|
||||
|
@ -567,13 +600,13 @@ MozMtpDatabase::QueryEntries(MozMtpDatabase::MatchType aMatchType,
|
|||
//virtual
|
||||
MtpResponseCode
|
||||
MozMtpDatabase::getObjectPropertyList(MtpObjectHandle aHandle,
|
||||
uint32_t aFormat,
|
||||
uint32_t aProperty,
|
||||
int aGroupCode,
|
||||
int aDepth,
|
||||
MtpDataPacket& aPacket)
|
||||
uint32_t aFormat,
|
||||
uint32_t aProperty,
|
||||
int aGroupCode,
|
||||
int aDepth,
|
||||
MtpDataPacket& aPacket)
|
||||
{
|
||||
MTP_LOG("Handle: 0x%08x Format: 0x%08x aProperty: 0x%08x aGroupCode: %d aDepth %d (NOT SUPPORTED)",
|
||||
MTP_LOG("Handle: 0x%08x Format: 0x%08x aProperty: 0x%08x aGroupCode: %d aDepth %d",
|
||||
aHandle, aFormat, aProperty, aGroupCode, aDepth);
|
||||
|
||||
if (aDepth > 1) {
|
||||
|
@ -726,7 +759,7 @@ MozMtpDatabase::getObjectPropertyList(MtpObjectHandle aHandle,
|
|||
//virtual
|
||||
MtpResponseCode
|
||||
MozMtpDatabase::getObjectInfo(MtpObjectHandle aHandle,
|
||||
MtpObjectInfo& aInfo)
|
||||
MtpObjectInfo& aInfo)
|
||||
{
|
||||
RefPtr<DbEntry> entry = GetEntry(aHandle);
|
||||
if (!entry) {
|
||||
|
@ -780,9 +813,9 @@ MozMtpDatabase::getThumbnail(MtpObjectHandle aHandle, size_t& aOutThumbSize)
|
|||
//virtual
|
||||
MtpResponseCode
|
||||
MozMtpDatabase::getObjectFilePath(MtpObjectHandle aHandle,
|
||||
MtpString& aOutFilePath,
|
||||
int64_t& aOutFileLength,
|
||||
MtpObjectFormat& aOutFormat)
|
||||
MtpString& aOutFilePath,
|
||||
int64_t& aOutFileLength,
|
||||
MtpObjectFormat& aOutFormat)
|
||||
{
|
||||
RefPtr<DbEntry> entry = GetEntry(aHandle);
|
||||
if (!entry) {
|
||||
|
@ -811,6 +844,10 @@ MozMtpDatabase::deleteFile(MtpObjectHandle aHandle)
|
|||
|
||||
MTP_LOG("Handle: 0x%08x '%s'", aHandle, entry->mPath.get());
|
||||
|
||||
//TODO: MtpServer::doDeleteObject calls us, and then calls a private
|
||||
// method (deletePath) which recursively deletes the path.
|
||||
// We need to tell device storage that these files are gone
|
||||
|
||||
// File deletion will happen in lower level implementation.
|
||||
// The only thing we need to do is removing the entry from the db.
|
||||
RemoveEntry(aHandle);
|
||||
|
@ -854,7 +891,7 @@ MozMtpDatabase::getObjectReferences(MtpObjectHandle aHandle)
|
|||
//virtual
|
||||
MtpResponseCode
|
||||
MozMtpDatabase::setObjectReferences(MtpObjectHandle aHandle,
|
||||
MtpObjectHandleList* aReferences)
|
||||
MtpObjectHandleList* aReferences)
|
||||
{
|
||||
MTP_LOG("Handle: 0x%08x (NOT SUPPORTED)", aHandle);
|
||||
return MTP_RESPONSE_OPERATION_NOT_SUPPORTED;
|
||||
|
|
|
@ -22,7 +22,9 @@ using namespace android;
|
|||
class MozMtpDatabase : public MtpDatabase
|
||||
{
|
||||
public:
|
||||
MozMtpDatabase(const char *aDir);
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MozMtpDatabase)
|
||||
|
||||
MozMtpDatabase();
|
||||
virtual ~MozMtpDatabase();
|
||||
|
||||
// called from SendObjectInfo to reserve a database entry for the incoming file
|
||||
|
@ -106,11 +108,14 @@ public:
|
|||
|
||||
virtual void sessionEnded();
|
||||
|
||||
void AddStorage(MtpStorageID aStorageID, const char* aPath, const char *aName);
|
||||
void RemoveStorage(MtpStorageID aStorageID);
|
||||
|
||||
private:
|
||||
|
||||
struct DbEntry
|
||||
{
|
||||
NS_INLINE_DECL_REFCOUNTING(DbEntry)
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DbEntry)
|
||||
|
||||
MtpObjectHandle mHandle; // uint32_t
|
||||
MtpStorageID mStorageID; // uint32_t
|
||||
|
@ -152,8 +157,7 @@ private:
|
|||
return mDb.Length();
|
||||
}
|
||||
|
||||
void ParseDirectory(const char *aDir, MtpObjectHandle aParent);
|
||||
void ReadVolume(const char *aVolumeName, const char *aDir);
|
||||
void AddDirectory(MtpStorageID aStorageID, const char *aPath, MtpObjectHandle aParent);
|
||||
};
|
||||
|
||||
END_MTP_NAMESPACE
|
||||
|
|
|
@ -16,46 +16,34 @@
|
|||
#include <unistd.h>
|
||||
|
||||
#include <cutils/properties.h>
|
||||
#include <private/android_filesystem_config.h>
|
||||
|
||||
#include "base/message_loop.h"
|
||||
#include "mozilla/FileUtils.h"
|
||||
#include "mozilla/Scoped.h"
|
||||
#include "mozilla/StaticPtr.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsXULAppAPI.h"
|
||||
|
||||
#include "Volume.h"
|
||||
|
||||
using namespace android;
|
||||
using namespace mozilla;
|
||||
USING_MTP_NAMESPACE
|
||||
BEGIN_MTP_NAMESPACE
|
||||
|
||||
class MtpServerRunnable : public nsRunnable
|
||||
{
|
||||
public:
|
||||
MtpServerRunnable(int aMtpUsbFd, MozMtpServer* aMozMtpServer)
|
||||
: mMozMtpServer(aMozMtpServer),
|
||||
mMtpUsbFd(aMtpUsbFd)
|
||||
{
|
||||
}
|
||||
|
||||
nsresult Run()
|
||||
{
|
||||
const char *mtpUsbFilename = "/dev/mtp_usb";
|
||||
const char *productName = "FirefoxOS";
|
||||
const char *storageDir = "/storage/sdcard";
|
||||
|
||||
mFd = open(mtpUsbFilename, O_RDWR);
|
||||
if (mFd.get() < 0) {
|
||||
MTP_LOG("open of '%s' failed", mtpUsbFilename);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
MTP_LOG("MozMtpServer open done, fd: %d. Start reading.", mFd.get());
|
||||
|
||||
ScopedDeletePtr<MozMtpDatabase> database;
|
||||
ScopedDeletePtr<MtpServer> server;
|
||||
ScopedDeletePtr<MtpStorage> storage;
|
||||
|
||||
database = new MozMtpDatabase(storageDir);
|
||||
server = new MtpServer(mFd.get(), database, false, 1023, 0664, 0775);
|
||||
storage = new MtpStorage(MTP_STORAGE_FIXED_RAM, // id
|
||||
storageDir, // filePath
|
||||
productName, // description
|
||||
100uLL * 1024uLL * 1024uLL, // reserveSpace
|
||||
false, // removable
|
||||
2uLL * 1024uLL * 1024uLL * 1024uLL); // maxFileSize
|
||||
|
||||
server->addStorage(storage);
|
||||
nsRefPtr<RefCountedMtpServer> server = mMozMtpServer->GetMtpServer();
|
||||
|
||||
MTP_LOG("MozMtpServer started");
|
||||
server->run();
|
||||
|
@ -65,16 +53,51 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
ScopedClose mFd;
|
||||
nsRefPtr<MozMtpServer> mMozMtpServer;
|
||||
ScopedClose mMtpUsbFd; // We want to hold this open while the server runs
|
||||
};
|
||||
|
||||
already_AddRefed<RefCountedMtpServer>
|
||||
MozMtpServer::GetMtpServer()
|
||||
{
|
||||
nsRefPtr<RefCountedMtpServer> server = mMtpServer;
|
||||
return server.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<MozMtpDatabase>
|
||||
MozMtpServer::GetMozMtpDatabase()
|
||||
{
|
||||
nsRefPtr<MozMtpDatabase> db = mMozMtpDatabase;
|
||||
return db.forget();
|
||||
}
|
||||
|
||||
void
|
||||
MozMtpServer::Run()
|
||||
{
|
||||
MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
|
||||
|
||||
const char *mtpUsbFilename = "/dev/mtp_usb";
|
||||
ScopedClose mtpUsbFd(open(mtpUsbFilename, O_RDWR));
|
||||
if (mtpUsbFd.get() < 0) {
|
||||
MTP_ERR("open of '%s' failed", mtpUsbFilename);
|
||||
return;
|
||||
}
|
||||
MTP_LOG("Opened '%s' fd %d", mtpUsbFilename, mtpUsbFd.get());
|
||||
|
||||
mMozMtpDatabase = new MozMtpDatabase();
|
||||
mMtpServer = new RefCountedMtpServer(mtpUsbFd.get(), // fd
|
||||
mMozMtpDatabase.get(), // MtpDatabase
|
||||
false, // ptp?
|
||||
AID_MEDIA_RW, // file group
|
||||
0664, // file permissions
|
||||
0775); // dir permissions
|
||||
|
||||
nsresult rv = NS_NewNamedThread("MtpServer", getter_AddRefs(mServerThread));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return;
|
||||
}
|
||||
MOZ_ASSERT(mServerThread);
|
||||
mServerThread->Dispatch(new MtpServerRunnable(), 0);
|
||||
mServerThread->Dispatch(new MtpServerRunnable(mtpUsbFd.forget(), this), NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
END_MTP_NAMESPACE
|
||||
|
|
|
@ -8,20 +8,48 @@
|
|||
#define mozilla_system_mozmtpserver_h__
|
||||
|
||||
#include "MozMtpCommon.h"
|
||||
#include "MozMtpDatabase.h"
|
||||
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIThread.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace system {
|
||||
class Volume;
|
||||
}
|
||||
}
|
||||
|
||||
BEGIN_MTP_NAMESPACE
|
||||
using namespace android;
|
||||
|
||||
class RefCountedMtpServer : public MtpServer
|
||||
{
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RefCountedMtpServer)
|
||||
|
||||
RefCountedMtpServer(int aFd, MtpDatabase* aDatabase, bool aPtp,
|
||||
int aFileGroup, int aFilePerm, int aDirectoryPerm)
|
||||
: MtpServer(aFd, aDatabase, aPtp, aFileGroup, aFilePerm, aDirectoryPerm)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class MozMtpServer
|
||||
{
|
||||
public:
|
||||
NS_INLINE_DECL_REFCOUNTING(MozMtpServer)
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MozMtpServer)
|
||||
|
||||
void Run();
|
||||
|
||||
// void UpdateStorage(android::MtpStorageID id, Volume *vol);
|
||||
|
||||
already_AddRefed<RefCountedMtpServer> GetMtpServer();
|
||||
already_AddRefed<MozMtpDatabase> GetMozMtpDatabase();
|
||||
|
||||
private:
|
||||
nsRefPtr<RefCountedMtpServer> mMtpServer;
|
||||
nsRefPtr<MozMtpDatabase> mMozMtpDatabase;
|
||||
nsCOMPtr<nsIThread> mServerThread;
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,133 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "MozMtpStorage.h"
|
||||
#include "MozMtpDatabase.h"
|
||||
#include "MozMtpServer.h"
|
||||
|
||||
#include "base/message_loop.h"
|
||||
#include "nsXULAppAPI.h"
|
||||
|
||||
BEGIN_MTP_NAMESPACE
|
||||
using namespace android;
|
||||
|
||||
MozMtpStorage::MozMtpStorage(Volume* aVolume, MozMtpServer* aMozMtpServer)
|
||||
: mMozMtpServer(aMozMtpServer),
|
||||
mVolume(aVolume)
|
||||
{
|
||||
MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
|
||||
|
||||
// The MtpStorageID has the physical volume in the top 16 bits, and the
|
||||
// logical volumein the lower 16 bits. We treat each volume as a separate
|
||||
// phsyical storage;
|
||||
mStorageID = mVolume->Id() << 16 | 1;
|
||||
|
||||
MTP_LOG("Storage constructed for Volume %s mStorageID 0x%08x",
|
||||
aVolume->NameStr(), mStorageID);
|
||||
|
||||
Volume::RegisterObserver(this);
|
||||
|
||||
// Get things in sync
|
||||
Notify(mVolume);
|
||||
}
|
||||
|
||||
MozMtpStorage::~MozMtpStorage()
|
||||
{
|
||||
MTP_LOG("Storage destructed for Volume %s mStorageID 0x%08x",
|
||||
mVolume->NameStr(), mStorageID);
|
||||
|
||||
Volume::UnregisterObserver(this);
|
||||
if (mMtpStorage) {
|
||||
StorageUnavailable();
|
||||
}
|
||||
}
|
||||
|
||||
// virtual
|
||||
void
|
||||
MozMtpStorage::Notify(Volume* const& aVolume)
|
||||
{
|
||||
MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
|
||||
|
||||
if (aVolume != mVolume) {
|
||||
// Not our volume
|
||||
return;
|
||||
}
|
||||
Volume::STATE volState = aVolume->State();
|
||||
|
||||
MTP_LOG("Volume %s mStorageID 0x%08x state changed to %s SharingEnabled: %d",
|
||||
aVolume->NameStr(), mStorageID, aVolume->StateStr(),
|
||||
aVolume->IsSharingEnabled());
|
||||
|
||||
if (mMtpStorage) {
|
||||
if (volState != nsIVolume::STATE_MOUNTED || !aVolume->IsSharingEnabled()) {
|
||||
// The volume is no longer accessible. We need to remove this storage
|
||||
// from the MTP server
|
||||
StorageUnavailable();
|
||||
}
|
||||
} else {
|
||||
if (volState == nsIVolume::STATE_MOUNTED && aVolume->IsSharingEnabled()) {
|
||||
// The volume is accessible. Tell the MTP server.
|
||||
StorageAvailable();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MozMtpStorage::StorageAvailable()
|
||||
{
|
||||
MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
|
||||
|
||||
nsCString mountPoint = mVolume->MountPoint();
|
||||
|
||||
MTP_LOG("Adding Volume %s mStorageID 0x%08x mountPoint %s to MozMtpDatabase",
|
||||
mVolume->NameStr(), mStorageID, mountPoint.get());
|
||||
|
||||
nsRefPtr<MozMtpDatabase> db = mMozMtpServer->GetMozMtpDatabase();
|
||||
db->AddStorage(mStorageID, mountPoint.get(), mVolume->NameStr());
|
||||
|
||||
MOZ_ASSERT(!mMtpStorage);
|
||||
|
||||
//TODO: For now we assume that the storage removable unless we're sure it's
|
||||
// not. Bug 1033952 will add an isRemovable attribute to the Volume
|
||||
// and then we'll know properly.
|
||||
|
||||
//TODO: Figure out what to do about maxFileSize.
|
||||
|
||||
mMtpStorage.reset(new MtpStorage(mStorageID, // id
|
||||
mountPoint.get(), // filePath
|
||||
mVolume->NameStr(), // description
|
||||
1024uLL * 1024uLL, // reserveSpace
|
||||
true, // removable
|
||||
2uLL * 1024uLL * 1024uLL * 1024uLL)); // maxFileSize
|
||||
nsRefPtr<RefCountedMtpServer> server = mMozMtpServer->GetMtpServer();
|
||||
|
||||
MTP_LOG("Adding Volume %s mStorageID 0x%08x mountPoint %s to MtpServer",
|
||||
mVolume->NameStr(), mStorageID, mountPoint.get());
|
||||
server->addStorage(mMtpStorage.get());
|
||||
}
|
||||
|
||||
void
|
||||
MozMtpStorage::StorageUnavailable()
|
||||
{
|
||||
MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
|
||||
MOZ_ASSERT(mMtpStorage);
|
||||
|
||||
MTP_LOG("Removing mStorageID 0x%08x from MtpServer", mStorageID);
|
||||
|
||||
nsRefPtr<RefCountedMtpServer> server = mMozMtpServer->GetMtpServer();
|
||||
server->removeStorage(mMtpStorage.get());
|
||||
|
||||
MTP_LOG("Removing mStorageID 0x%08x from MozMtpDatabse", mStorageID);
|
||||
|
||||
nsRefPtr<MozMtpDatabase> db = mMozMtpServer->GetMozMtpDatabase();
|
||||
db->RemoveStorage(mStorageID);
|
||||
|
||||
mMtpStorage = nullptr;
|
||||
}
|
||||
|
||||
END_MTP_NAMESPACE
|
||||
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_system_mozmtpstorage_h__
|
||||
#define mozilla_system_mozmtpstorage_h__
|
||||
|
||||
#include "MozMtpCommon.h"
|
||||
|
||||
#include "nsAutoPtr.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
|
||||
#include "Volume.h"
|
||||
|
||||
BEGIN_MTP_NAMESPACE
|
||||
using namespace android;
|
||||
|
||||
class MozMtpServer;
|
||||
|
||||
class MozMtpStorage : public Volume::EventObserver
|
||||
{
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MozMtpStorage)
|
||||
|
||||
MozMtpStorage(Volume* aVolume, MozMtpServer* aMozMtpServer);
|
||||
|
||||
typedef nsTArray<nsRefPtr<MozMtpStorage> > Array;
|
||||
|
||||
private:
|
||||
virtual ~MozMtpStorage();
|
||||
virtual void Notify(Volume* const& aEvent);
|
||||
|
||||
void StorageAvailable();
|
||||
void StorageUnavailable();
|
||||
|
||||
nsRefPtr<MozMtpServer> mMozMtpServer;
|
||||
UniquePtr<MtpStorage> mMtpStorage;
|
||||
RefPtr<Volume> mVolume;
|
||||
MtpStorageID mStorageID;
|
||||
};
|
||||
|
||||
END_MTP_NAMESPACE
|
||||
|
||||
#endif // mozilla_system_mozmtpstorage_h__
|
||||
|
||||
|
|
@ -50,6 +50,8 @@ Volume::EventObserverList Volume::mEventObserverList;
|
|||
// be locked until we get our first update from nsVolume (MainThread).
|
||||
static int32_t sMountGeneration = 0;
|
||||
|
||||
static uint32_t sNextId = 1;
|
||||
|
||||
// We don't get media inserted/removed events at startup. So we
|
||||
// assume it's present, and we'll be told that it's missing.
|
||||
Volume::Volume(const nsCSubstring& aName)
|
||||
|
@ -64,7 +66,8 @@ Volume::Volume(const nsCSubstring& aName)
|
|||
mUnmountRequested(false),
|
||||
mCanBeShared(true),
|
||||
mIsSharing(false),
|
||||
mIsFormatting(false)
|
||||
mIsFormatting(false),
|
||||
mId(sNextId++)
|
||||
{
|
||||
DBG("Volume %s: created", NameStr());
|
||||
}
|
||||
|
@ -140,6 +143,7 @@ Volume::SetSharingEnabled(bool aSharingEnabled)
|
|||
|
||||
LOG("SetSharingMode for volume %s to %d canBeShared = %d",
|
||||
NameStr(), (int)mSharingEnabled, (int)mCanBeShared);
|
||||
mEventObserverList.Broadcast(this);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -179,14 +183,14 @@ Volume::SetState(Volume::STATE aNewState)
|
|||
}
|
||||
if (aNewState == nsIVolume::STATE_MOUNTED) {
|
||||
mMountGeneration = ++sMountGeneration;
|
||||
LOG("Volume %s: changing state from %s to %s @ '%s' (%d observers) "
|
||||
LOG("Volume %s (%u): changing state from %s to %s @ '%s' (%d observers) "
|
||||
"mountGeneration = %d, locked = %d",
|
||||
NameStr(), StateStr(mState),
|
||||
NameStr(), mId, StateStr(mState),
|
||||
StateStr(aNewState), mMountPoint.get(), mEventObserverList.Length(),
|
||||
mMountGeneration, (int)mMountLocked);
|
||||
} else {
|
||||
LOG("Volume %s: changing state from %s to %s (%d observers)",
|
||||
NameStr(), StateStr(mState),
|
||||
LOG("Volume %s (%u): changing state from %s to %s (%d observers)",
|
||||
NameStr(), mId, StateStr(mState),
|
||||
StateStr(aNewState), mEventObserverList.Length());
|
||||
}
|
||||
|
||||
|
|
|
@ -44,6 +44,8 @@ public:
|
|||
// (i.e. path that leads to the files stored on the volume).
|
||||
const nsCString& MountPoint() const { return mMountPoint; }
|
||||
|
||||
uint32_t Id() const { return mId; }
|
||||
|
||||
int32_t MountGeneration() const { return mMountGeneration; }
|
||||
bool IsMountLocked() const { return mMountLocked; }
|
||||
bool MediaPresent() const { return mMediaPresent; }
|
||||
|
@ -110,6 +112,7 @@ private:
|
|||
bool mCanBeShared;
|
||||
bool mIsSharing;
|
||||
bool mIsFormatting;
|
||||
uint32_t mId; // Unique ID (used by MTP)
|
||||
|
||||
static EventObserverList mEventObserverList;
|
||||
};
|
||||
|
|
|
@ -43,6 +43,7 @@ SOURCES += [
|
|||
'GonkGPSGeolocationProvider.cpp',
|
||||
'MozMtpDatabase.cpp',
|
||||
'MozMtpServer.cpp',
|
||||
'MozMtpStorage.cpp',
|
||||
'NetworkUtils.cpp',
|
||||
'NetworkWorker.cpp',
|
||||
'nsVolume.cpp',
|
||||
|
|
Загрузка…
Ссылка в новой задаче