643e6d0a8553105223945a508d60ad1f1d540050
[platform/core/csapi/tizenfx.git] / src / Tizen.System.Storage / Storage / Storage.cs
1 /*
2 * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
3 *
4 * Licensed under the Apache License, Version 2.0 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an AS IS BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 using System;
18
19 namespace Tizen.System
20 {
21     /// <summary>
22     /// The class to access the storage device information.
23     /// </summary>
24     /// <since_tizen> 3 </since_tizen>
25     public class Storage
26     {
27         private const string LogTag = "Tizen.System";
28         private Interop.Storage.StorageState _state;
29         private Interop.Storage.StorageDevice _devicetype;
30         private Interop.Storage.StorageArea _storagetype;
31         private string _fstype;
32         private string _fsuuid;
33         private ulong _totalSpace;
34         private bool _primary;
35         private int _flags;
36         private bool information_set = false;
37
38         internal Storage(int storageID, Interop.Storage.StorageArea storageType, Interop.Storage.StorageState storagestate, string rootDirectory)
39         {
40             Id = storageID;
41             _storagetype = storageType;
42             RootDirectory = rootDirectory;
43             _state = storagestate;
44
45
46             Interop.Storage.ErrorCode err = Interop.Storage.StorageGetTotalSpace(Id, out _totalSpace);
47             if (err != Interop.Storage.ErrorCode.None)
48             {
49                 Log.Warn(LogTag, string.Format("Failed to get total storage space for storage Id: {0}. err = {1}", Id, err));
50             }
51
52             s_stateChangedEventCallback = (id, state, userData) =>
53             {
54                 if (id == Id)
55                 {
56                     _state = state;
57                     s_stateChangedEventHandler?.Invoke(this, EventArgs.Empty);
58                 }
59             };
60         }
61
62         internal Storage(int storageID, Interop.Storage.StorageArea storageType, Interop.Storage.StorageState storagestate, string rootDirectory, Interop.Storage.StorageDevice devicetype, string fstype, string fsuuid, bool primary, int flags)
63         {
64             Id = storageID;
65             _storagetype = storageType;
66             RootDirectory = rootDirectory;
67             _state = storagestate;
68             _devicetype = devicetype;
69             _fstype = fstype;
70             _fsuuid = fsuuid;
71             _primary = primary;
72             _flags = flags;
73             information_set = true;
74
75             Interop.Storage.ErrorCode err = Interop.Storage.StorageGetTotalSpace(Id, out _totalSpace);
76             if (err != Interop.Storage.ErrorCode.None)
77             {
78                 Log.Warn(LogTag, string.Format("Failed to get total storage space for storage Id: {0}. err = {1}", Id, err));
79             }
80
81             s_stateChangedEventCallback = (id, state, userData) =>
82             {
83                 if (id == Id)
84                 {
85                     _state = state;
86                     s_stateChangedEventHandler?.Invoke(this, EventArgs.Empty);
87                 }
88             };
89         }
90
91         private EventHandler s_stateChangedEventHandler;
92         private Interop.Storage.StorageStateChangedCallback s_stateChangedEventCallback;
93
94         private void RegisterStateChangedEvent()
95         {
96             Interop.Storage.ErrorCode err = Interop.Storage.StorageSetStateChanged(Id, s_stateChangedEventCallback, IntPtr.Zero);
97             if (err != Interop.Storage.ErrorCode.None)
98             {
99                 Log.Warn(LogTag, string.Format("Failed to Register state changed event callback for storage Id: {0}. err = {1}", Id, err));
100             }
101         }
102
103         private void UnregisterStateChangedEvent()
104         {
105             Interop.Storage.ErrorCode err = Interop.Storage.StorageUnsetStateChanged(Id, s_stateChangedEventCallback);
106             if (err != Interop.Storage.ErrorCode.None)
107             {
108                 Log.Warn(LogTag, string.Format("Failed to Register state changed event callback for storage Id: {0}. err = {1}", Id, err));
109             }
110         }
111
112         /// <summary>
113         /// StorageStateChanged event. This event is occurred when a storage state changes.
114         /// </summary>
115         /// <remarks>
116         /// The storage state will be updated before calling the event handler.
117         /// </remarks>
118         /// <since_tizen> 3 </since_tizen>
119         /// <feature> http://tizen.org/feature/storage.external </feature>
120         /// <example>
121         /// <code>
122         /// myStorage.StorageStateChanged += (s, e) =>
123         /// {
124         ///     var storage = s as Storage;
125         ///     Console.WriteLine(string.Format("State Changed to {0}", storage.State));
126         /// }
127         /// </code>
128         /// </example>
129         public event EventHandler StorageStateChanged
130         {
131             add
132             {
133                 if (s_stateChangedEventHandler == null)
134                 {
135                     _state = (Interop.Storage.StorageState)State;
136                     RegisterStateChangedEvent();
137                 }
138                 s_stateChangedEventHandler += value;
139             }
140             remove
141             {
142                 if (s_stateChangedEventHandler != null)
143                 {
144                     s_stateChangedEventHandler -= value;
145                     if (s_stateChangedEventHandler == null)
146                     {
147                         UnregisterStateChangedEvent();
148                     }
149                 }
150             }
151         }
152
153         /// <summary>
154         /// The storage ID.
155         /// </summary>
156         /// <since_tizen> 3 </since_tizen>
157         /// <feature> http://tizen.org/feature/storage.external </feature>
158         public int Id { get; }
159         /// <summary>
160         /// The type of storage.
161         /// </summary>
162         /// <since_tizen> 3 </since_tizen>
163         /// <feature> http://tizen.org/feature/storage.external </feature>
164         public StorageArea StorageType { get { return (StorageArea)_storagetype; } }
165         /// <summary>
166         /// The root directory for the storage.
167         /// </summary>
168         /// <since_tizen> 3 </since_tizen>
169         /// <feature> http://tizen.org/feature/storage.external </feature>
170         public string RootDirectory { get; }
171         /// <summary>
172         /// The total storage size in bytes.
173         /// </summary>
174         /// <since_tizen> 3 </since_tizen>
175         /// <feature> http://tizen.org/feature/storage.external </feature>
176         public ulong TotalSpace { get { return _totalSpace; } }
177
178         /// <summary>
179         /// The StorageState.
180         /// </summary>
181         /// <since_tizen> 3 </since_tizen>
182         /// <feature> http://tizen.org/feature/storage.external </feature>
183         public StorageState State
184         {
185             get
186             {
187                 if (s_stateChangedEventHandler == null)
188                 {
189                     Interop.Storage.ErrorCode err = Interop.Storage.StorageGetState(Id, out _state);
190                     if (err != Interop.Storage.ErrorCode.None)
191                     {
192                         Log.Warn(LogTag, string.Format("Failed to get storage state for storage Id: {0}. err = {1}", Id, err));
193                     }
194                 }
195                 return (StorageState)_state;
196             }
197         }
198
199         /// <summary>
200         /// The StorageDevice.
201         /// </summary>
202         /// <since_tizen> 5 </since_tizen>
203         /// <feature> http://tizen.org/feature/storage.external </feature>
204         /// <exception cref="InvalidOperationException">Thrown when DeviceType is not initialized.</exception>
205         public StorageDevice DeviceType
206         {
207             get
208             {
209                 Interop.Storage.ErrorCode err = Interop.Storage.StorageGetTypeDev(Id, out _storagetype, out _devicetype);
210                 if (err != Interop.Storage.ErrorCode.None)
211                 {
212                     Log.Warn(LogTag, string.Format("Failed to get storage device type for storage Id: {0}. err = {1}", Id, err));
213                 }
214                 return (StorageDevice)_devicetype;
215             }
216         }
217
218         /// <summary>
219         /// The type of file system.
220         /// </summary>
221         /// <since_tizen> 5 </since_tizen>
222         /// <feature> http://tizen.org/feature/storage.external </feature>
223         /// <exception cref="InvalidOperationException">Thrown when Fstype is not initialized.</exception>
224         public string Fstype
225         {
226             get
227             {
228                 if (!information_set)
229                 {
230                     Log.Error(LogTag, string.Format("Doesn't know fstype."));
231                     throw new InvalidOperationException("Doesn't know type of file system");
232                 }
233                 return _fstype;
234             }
235         }
236
237         /// <summary>
238         /// The UUID of the file system.
239         /// </summary>
240         /// <since_tizen> 5 </since_tizen>
241         /// <feature> http://tizen.org/feature/storage.external </feature>
242         /// <exception cref="InvalidOperationException">Thrown when Fsuuid is not initialized.</exception>
243         public string Fsuuid
244         {
245             get
246             {
247                 if (!information_set)
248                 {
249                     Log.Error(LogTag, string.Format("Doesn't know fsuuid."));
250                     throw new InvalidOperationException("Doesn't know uuid of file system");
251                 }
252                 return _fsuuid;
253             }
254         }
255
256         /// <summary>
257         /// Information whether this is a primary partition.
258         /// </summary>
259         /// <since_tizen> 5 </since_tizen>
260         /// <feature> http://tizen.org/feature/storage.external </feature>
261         /// <exception cref="InvalidOperationException">Thrown when primary is not initialized.</exception>
262         public bool Primary
263         {
264             get
265             {
266                 if (!information_set)
267                 {
268                     Log.Error(LogTag, string.Format("Doesn't know primary information."));
269                     throw new InvalidOperationException("Doesn't know primary information");
270                 }
271                 return _primary;
272             }
273         }
274
275         /// <summary>
276         /// The flags for the storage status.
277         /// </summary>
278         /// <since_tizen> 5 </since_tizen>
279         /// <feature> http://tizen.org/feature/storage.external </feature>
280         /// <exception cref="InvalidOperationException">Thrown when flags are not initialized.</exception>
281         public int Flags
282         {
283             get
284             {
285                 if (!information_set)
286                 {
287                     Log.Error(LogTag, string.Format("Doesn't know flags."));
288                     throw new InvalidOperationException("Doesn't know flags");
289                 }
290                 return _flags;
291             }
292         }
293
294         /// <summary>
295         /// [Obsolete("Please do not use! this will be deprecated")]
296         /// </summary>
297         /// <since_tizen> 3 </since_tizen>
298         /// Please do not use! this will be deprecated!
299         /// Instead please use AvailableSpace.
300         [Obsolete("Please do not use! This will be deprecated! Please use AvailableSpace instead!")]
301         public ulong AvaliableSpace
302         {
303             get
304             {
305                 ulong available;
306                 Interop.Storage.ErrorCode err = Interop.Storage.StorageGetAvailableSpace(Id, out available);
307                 if (err != Interop.Storage.ErrorCode.None)
308                 {
309                     Log.Warn(LogTag, string.Format("Failed to get available storage stace for storage Id: {0}. err = {1}", Id, err));
310                 }
311
312                 return available;
313             }
314         }
315
316         /// <summary>
317         /// The available storage size in bytes.
318         /// </summary>
319         /// <since_tizen> 5 </since_tizen>
320         /// <feature> http://tizen.org/feature/storage.external </feature>
321         public ulong AvailableSpace
322         {
323             get
324             {
325                 ulong available;
326                 Interop.Storage.ErrorCode err = Interop.Storage.StorageGetAvailableSpace(Id, out available);
327                 if (err != Interop.Storage.ErrorCode.None)
328                 {
329                     Log.Warn(LogTag, string.Format("Failed to get available storage stace for storage Id: {0}. err = {1}", Id, err));
330                 }
331
332                 return available;
333             }
334         }
335
336         /// <summary>
337         /// Absolute path for a given directory type in the storage.
338         /// </summary>
339         /// <remarks>
340         /// The returned directory path may not exist, so you must make sure that it exists before using it.
341         /// For accessing internal storage except the ringtones directory, the application should have http://tizen.org/privilege/mediastorage privilege.
342         /// For accessing ringtones directory, the application should have http://tizen.org/privilege/systemsettings privilege.
343         /// For accessing external storage, the application should have http://tizen.org/privilege/externalstorage privilege.
344         /// </remarks>
345         /// <since_tizen> 3 </since_tizen>
346         /// <param name="dirType">Directory type.</param>
347         /// <returns>Absolute path for a given directory type in the storage.</returns>
348         /// <feature> http://tizen.org/feature/storage.external </feature>
349         /// <exception cref="ArgumentException">Thrown when failed because of an invalid argument.</exception>
350         /// <exception cref="OutOfMemoryException">Thrown when failed due to out of memory exception.</exception>
351         /// <exception cref="NotSupportedException">Thrown when the storage is not supported or the application does not have the permission to access the directory path.</exception>
352         /// <privilege>http://tizen.org/privilege/mediastorage</privilege>
353         /// <privilege>http://tizen.org/privilege/systemsettings</privilege>
354         /// <privilege>http://tizen.org/privilege/externalstorage</privilege>
355         /// <example>
356         /// <code>
357         /// // To get the video directories for all the supported storage,
358         /// var storageList = StorageManager.Storages as List&lt;Storage&gt;;
359         /// foreach (var storage in storageList)
360         /// {
361         ///     string pathForVideoDir = storage.GetAbsolutePath(DirectoryType.Videos);
362         /// }
363         /// </code>
364         /// </example>
365         public string GetAbsolutePath(DirectoryType dirType)
366         {
367             string path;
368             Interop.Storage.ErrorCode err = Interop.Storage.StorageGetAbsoluteDirectory(Id, (Interop.Storage.DirectoryType)dirType, out path);
369             if (err != Interop.Storage.ErrorCode.None)
370             {
371                 Log.Warn(LogTag, string.Format("Failed to get package Id. err = {0}", err));
372                 switch (err)
373                 {
374                     case Interop.Storage.ErrorCode.InvalidParameter:
375                         throw new ArgumentException("Invalid Arguments");
376                     case Interop.Storage.ErrorCode.OutOfMemory:
377                         throw new OutOfMemoryException("Out of Memory");
378                     case Interop.Storage.ErrorCode.NotSupported:
379                         throw new NotSupportedException("Storage Not Supported");
380                     default:
381                         throw new InvalidOperationException("Error = " + err);
382                 }
383             }
384             return path;
385         }
386     }
387 }