1 /* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
2 /* vim: set ts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
5  * You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #include "MozMtpStorage.h"
8 #include "MozMtpDatabase.h"
9 #include "MozMtpServer.h"
10 
11 #include "base/message_loop.h"
12 #include "nsXULAppAPI.h"
13 
14 BEGIN_MTP_NAMESPACE
15 using namespace android;
16 
MozMtpStorage(Volume * aVolume,MozMtpServer * aMozMtpServer)17 MozMtpStorage::MozMtpStorage(Volume* aVolume, MozMtpServer* aMozMtpServer)
18   : mMozMtpServer(aMozMtpServer),
19     mVolume(aVolume)
20 {
21   MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
22 
23   // The MtpStorageID has the physical volume in the top 16 bits, and the
24   // logical volumein the lower 16 bits. We treat each volume as a separate
25   // phsyical storage;
26   mStorageID = mVolume->Id() << 16 | 1;
27 
28   MTP_LOG("Storage constructed for Volume %s mStorageID 0x%08x",
29           aVolume->NameStr(), mStorageID);
30 
31   Volume::RegisterVolumeObserver(this, "MozMtpStorage");
32 
33   // Get things in sync
34   Notify(mVolume);
35 }
36 
~MozMtpStorage()37 MozMtpStorage::~MozMtpStorage()
38 {
39   MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
40 
41   MTP_LOG("Storage destructed for Volume %s mStorageID 0x%08x",
42           mVolume->NameStr(), mStorageID);
43 
44   Volume::UnregisterVolumeObserver(this, "MozMtpStorage");
45   if (mMtpStorage) {
46     StorageUnavailable();
47   }
48 }
49 
50 // virtual
51 void
Notify(Volume * const & aVolume)52 MozMtpStorage::Notify(Volume* const& aVolume)
53 {
54   MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
55 
56   if (aVolume != mVolume) {
57     // Not our volume
58     return;
59   }
60   Volume::STATE volState = aVolume->State();
61 
62   MTP_LOG("Volume %s mStorageID 0x%08x state changed to %s SharingEnabled: %d",
63           aVolume->NameStr(), mStorageID, aVolume->StateStr(),
64           aVolume->IsSharingEnabled());
65 
66   // vol->IsSharingEnabled really only applies to UMS volumes. We assume that
67   // that as long as MTP is enabled, then all volumes will be shared. The UI
68   // currently doesn't give us anything more granular than on/off.
69 
70   if (mMtpStorage) {
71     if (volState != nsIVolume::STATE_MOUNTED) {
72       // The volume is no longer accessible. We need to remove this storage
73       // from the MTP server
74       StorageUnavailable();
75     }
76   } else {
77     if (volState == nsIVolume::STATE_MOUNTED) {
78       // The volume is accessible. Tell the MTP server.
79       StorageAvailable();
80     }
81   }
82 }
83 
84 void
StorageAvailable()85 MozMtpStorage::StorageAvailable()
86 {
87   MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
88 
89   nsCString mountPoint = mVolume->MountPoint();
90 
91   MTP_LOG("Adding Volume %s mStorageID 0x%08x mountPoint %s to MozMtpDatabase",
92           mVolume->NameStr(), mStorageID, mountPoint.get());
93 
94   RefPtr<MozMtpDatabase> db = mMozMtpServer->GetMozMtpDatabase();
95   db->AddStorage(mStorageID, mountPoint.get(), mVolume->NameStr());
96 
97   MOZ_ASSERT(!mMtpStorage);
98 
99   //TODO: Figure out what to do about maxFileSize.
100 
101   mMtpStorage.reset(new MtpStorage(mStorageID,                           // id
102                                    mountPoint.get(),                     // filePath
103                                    mVolume->NameStr(),                   // description
104                                    1024uLL * 1024uLL,                    // reserveSpace
105                                    mVolume->IsHotSwappable(),            // removable
106                                    2uLL * 1024uLL * 1024uLL * 1024uLL)); // maxFileSize
107   RefPtr<RefCountedMtpServer> server = mMozMtpServer->GetMtpServer();
108 
109   MTP_LOG("Adding Volume %s mStorageID 0x%08x mountPoint %s to MtpServer",
110           mVolume->NameStr(), mStorageID, mountPoint.get());
111   server->addStorage(mMtpStorage.get());
112 }
113 
114 void
StorageUnavailable()115 MozMtpStorage::StorageUnavailable()
116 {
117   MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
118   MOZ_ASSERT(mMtpStorage);
119 
120   MTP_LOG("Removing mStorageID 0x%08x from MtpServer", mStorageID);
121 
122   RefPtr<RefCountedMtpServer> server = mMozMtpServer->GetMtpServer();
123   server->removeStorage(mMtpStorage.get());
124 
125   MTP_LOG("Removing mStorageID 0x%08x from MozMtpDatabse", mStorageID);
126 
127   RefPtr<MozMtpDatabase> db = mMozMtpServer->GetMozMtpDatabase();
128   db->RemoveStorage(mStorageID);
129 
130   mMtpStorage = nullptr;
131 }
132 
133 END_MTP_NAMESPACE
134 
135 
136