1/*
2 * Copyright (C) 2010 The Android Open Source Project
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
17package android.os.storage;
18
19import android.os.Binder;
20import android.os.IBinder;
21import android.os.IInterface;
22import android.os.Parcel;
23import android.os.Parcelable;
24import android.os.RemoteException;
25import android.os.storage.StorageVolume;
26
27/**
28 * WARNING! Update IMountService.h and IMountService.cpp if you change this
29 * file. In particular, the ordering of the methods below must match the
30 * _TRANSACTION enum in IMountService.cpp
31 *
32 * @hide - Applications should use android.os.storage.StorageManager to access
33 *       storage functions.
34 */
35public interface IMountService extends IInterface {
36    /** Local-side IPC implementation stub class. */
37    public static abstract class Stub extends Binder implements IMountService {
38        private static class Proxy implements IMountService {
39            private final IBinder mRemote;
40
41            Proxy(IBinder remote) {
42                mRemote = remote;
43            }
44
45            public IBinder asBinder() {
46                return mRemote;
47            }
48
49            public String getInterfaceDescriptor() {
50                return DESCRIPTOR;
51            }
52
53            /**
54             * Registers an IMountServiceListener for receiving async
55             * notifications.
56             */
57            public void registerListener(IMountServiceListener listener) throws RemoteException {
58                Parcel _data = Parcel.obtain();
59                Parcel _reply = Parcel.obtain();
60                try {
61                    _data.writeInterfaceToken(DESCRIPTOR);
62                    _data.writeStrongBinder((listener != null ? listener.asBinder() : null));
63                    mRemote.transact(Stub.TRANSACTION_registerListener, _data, _reply, 0);
64                    _reply.readException();
65                } finally {
66                    _reply.recycle();
67                    _data.recycle();
68                }
69            }
70
71            /**
72             * Unregisters an IMountServiceListener
73             */
74            public void unregisterListener(IMountServiceListener listener) throws RemoteException {
75                Parcel _data = Parcel.obtain();
76                Parcel _reply = Parcel.obtain();
77                try {
78                    _data.writeInterfaceToken(DESCRIPTOR);
79                    _data.writeStrongBinder((listener != null ? listener.asBinder() : null));
80                    mRemote.transact(Stub.TRANSACTION_unregisterListener, _data, _reply, 0);
81                    _reply.readException();
82                } finally {
83                    _reply.recycle();
84                    _data.recycle();
85                }
86            }
87
88            /**
89             * Returns true if a USB mass storage host is connected
90             */
91            public boolean isUsbMassStorageConnected() throws RemoteException {
92                Parcel _data = Parcel.obtain();
93                Parcel _reply = Parcel.obtain();
94                boolean _result;
95                try {
96                    _data.writeInterfaceToken(DESCRIPTOR);
97                    mRemote.transact(Stub.TRANSACTION_isUsbMassStorageConnected, _data, _reply, 0);
98                    _reply.readException();
99                    _result = 0 != _reply.readInt();
100                } finally {
101                    _reply.recycle();
102                    _data.recycle();
103                }
104                return _result;
105            }
106
107            /**
108             * Enables / disables USB mass storage. The caller should check
109             * actual status of enabling/disabling USB mass storage via
110             * StorageEventListener.
111             */
112            public void setUsbMassStorageEnabled(boolean enable) throws RemoteException {
113                Parcel _data = Parcel.obtain();
114                Parcel _reply = Parcel.obtain();
115                try {
116                    _data.writeInterfaceToken(DESCRIPTOR);
117                    _data.writeInt((enable ? 1 : 0));
118                    mRemote.transact(Stub.TRANSACTION_setUsbMassStorageEnabled, _data, _reply, 0);
119                    _reply.readException();
120                } finally {
121                    _reply.recycle();
122                    _data.recycle();
123                }
124            }
125
126            /**
127             * Returns true if a USB mass storage host is enabled (media is
128             * shared)
129             */
130            public boolean isUsbMassStorageEnabled() throws RemoteException {
131                Parcel _data = Parcel.obtain();
132                Parcel _reply = Parcel.obtain();
133                boolean _result;
134                try {
135                    _data.writeInterfaceToken(DESCRIPTOR);
136                    mRemote.transact(Stub.TRANSACTION_isUsbMassStorageEnabled, _data, _reply, 0);
137                    _reply.readException();
138                    _result = 0 != _reply.readInt();
139                } finally {
140                    _reply.recycle();
141                    _data.recycle();
142                }
143                return _result;
144            }
145
146            /**
147             * Mount external storage at given mount point. Returns an int
148             * consistent with MountServiceResultCode
149             */
150            public int mountVolume(String mountPoint) throws RemoteException {
151                Parcel _data = Parcel.obtain();
152                Parcel _reply = Parcel.obtain();
153                int _result;
154                try {
155                    _data.writeInterfaceToken(DESCRIPTOR);
156                    _data.writeString(mountPoint);
157                    mRemote.transact(Stub.TRANSACTION_mountVolume, _data, _reply, 0);
158                    _reply.readException();
159                    _result = _reply.readInt();
160                } finally {
161                    _reply.recycle();
162                    _data.recycle();
163                }
164                return _result;
165            }
166
167            /**
168             * Safely unmount external storage at given mount point. The unmount
169             * is an asynchronous operation. Applications should register
170             * StorageEventListener for storage related status changes.
171             */
172            public void unmountVolume(String mountPoint, boolean force, boolean removeEncryption)
173                    throws RemoteException {
174                Parcel _data = Parcel.obtain();
175                Parcel _reply = Parcel.obtain();
176                try {
177                    _data.writeInterfaceToken(DESCRIPTOR);
178                    _data.writeString(mountPoint);
179                    _data.writeInt((force ? 1 : 0));
180                    _data.writeInt((removeEncryption ? 1 : 0));
181                    mRemote.transact(Stub.TRANSACTION_unmountVolume, _data, _reply, 0);
182                    _reply.readException();
183                } finally {
184                    _reply.recycle();
185                    _data.recycle();
186                }
187            }
188
189            /**
190             * Format external storage given a mount point. Returns an int
191             * consistent with MountServiceResultCode
192             */
193            public int formatVolume(String mountPoint) throws RemoteException {
194                Parcel _data = Parcel.obtain();
195                Parcel _reply = Parcel.obtain();
196                int _result;
197                try {
198                    _data.writeInterfaceToken(DESCRIPTOR);
199                    _data.writeString(mountPoint);
200                    mRemote.transact(Stub.TRANSACTION_formatVolume, _data, _reply, 0);
201                    _reply.readException();
202                    _result = _reply.readInt();
203                } finally {
204                    _reply.recycle();
205                    _data.recycle();
206                }
207                return _result;
208            }
209
210            /**
211             * Returns an array of pids with open files on the specified path.
212             */
213            public int[] getStorageUsers(String path) throws RemoteException {
214                Parcel _data = Parcel.obtain();
215                Parcel _reply = Parcel.obtain();
216                int[] _result;
217                try {
218                    _data.writeInterfaceToken(DESCRIPTOR);
219                    _data.writeString(path);
220                    mRemote.transact(Stub.TRANSACTION_getStorageUsers, _data, _reply, 0);
221                    _reply.readException();
222                    _result = _reply.createIntArray();
223                } finally {
224                    _reply.recycle();
225                    _data.recycle();
226                }
227                return _result;
228            }
229
230            /**
231             * Gets the state of a volume via its mountpoint.
232             */
233            public String getVolumeState(String mountPoint) throws RemoteException {
234                Parcel _data = Parcel.obtain();
235                Parcel _reply = Parcel.obtain();
236                String _result;
237                try {
238                    _data.writeInterfaceToken(DESCRIPTOR);
239                    _data.writeString(mountPoint);
240                    mRemote.transact(Stub.TRANSACTION_getVolumeState, _data, _reply, 0);
241                    _reply.readException();
242                    _result = _reply.readString();
243                } finally {
244                    _reply.recycle();
245                    _data.recycle();
246                }
247                return _result;
248            }
249
250            /*
251             * Creates a secure container with the specified parameters. Returns
252             * an int consistent with MountServiceResultCode
253             */
254            public int createSecureContainer(String id, int sizeMb, String fstype, String key,
255                    int ownerUid) throws RemoteException {
256                Parcel _data = Parcel.obtain();
257                Parcel _reply = Parcel.obtain();
258                int _result;
259                try {
260                    _data.writeInterfaceToken(DESCRIPTOR);
261                    _data.writeString(id);
262                    _data.writeInt(sizeMb);
263                    _data.writeString(fstype);
264                    _data.writeString(key);
265                    _data.writeInt(ownerUid);
266                    mRemote.transact(Stub.TRANSACTION_createSecureContainer, _data, _reply, 0);
267                    _reply.readException();
268                    _result = _reply.readInt();
269                } finally {
270                    _reply.recycle();
271                    _data.recycle();
272                }
273                return _result;
274            }
275
276            /*
277             * Destroy a secure container, and free up all resources associated
278             * with it. NOTE: Ensure all references are released prior to
279             * deleting. Returns an int consistent with MountServiceResultCode
280             */
281            public int destroySecureContainer(String id, boolean force) throws RemoteException {
282                Parcel _data = Parcel.obtain();
283                Parcel _reply = Parcel.obtain();
284                int _result;
285                try {
286                    _data.writeInterfaceToken(DESCRIPTOR);
287                    _data.writeString(id);
288                    _data.writeInt((force ? 1 : 0));
289                    mRemote.transact(Stub.TRANSACTION_destroySecureContainer, _data, _reply, 0);
290                    _reply.readException();
291                    _result = _reply.readInt();
292                } finally {
293                    _reply.recycle();
294                    _data.recycle();
295                }
296                return _result;
297            }
298
299            /*
300             * Finalize a container which has just been created and populated.
301             * After finalization, the container is immutable. Returns an int
302             * consistent with MountServiceResultCode
303             */
304            public int finalizeSecureContainer(String id) throws RemoteException {
305                Parcel _data = Parcel.obtain();
306                Parcel _reply = Parcel.obtain();
307                int _result;
308                try {
309                    _data.writeInterfaceToken(DESCRIPTOR);
310                    _data.writeString(id);
311                    mRemote.transact(Stub.TRANSACTION_finalizeSecureContainer, _data, _reply, 0);
312                    _reply.readException();
313                    _result = _reply.readInt();
314                } finally {
315                    _reply.recycle();
316                    _data.recycle();
317                }
318                return _result;
319            }
320
321            /*
322             * Mount a secure container with the specified key and owner UID.
323             * Returns an int consistent with MountServiceResultCode
324             */
325            public int mountSecureContainer(String id, String key, int ownerUid)
326                    throws RemoteException {
327                Parcel _data = Parcel.obtain();
328                Parcel _reply = Parcel.obtain();
329                int _result;
330                try {
331                    _data.writeInterfaceToken(DESCRIPTOR);
332                    _data.writeString(id);
333                    _data.writeString(key);
334                    _data.writeInt(ownerUid);
335                    mRemote.transact(Stub.TRANSACTION_mountSecureContainer, _data, _reply, 0);
336                    _reply.readException();
337                    _result = _reply.readInt();
338                } finally {
339                    _reply.recycle();
340                    _data.recycle();
341                }
342                return _result;
343            }
344
345            /*
346             * Unount a secure container. Returns an int consistent with
347             * MountServiceResultCode
348             */
349            public int unmountSecureContainer(String id, boolean force) throws RemoteException {
350                Parcel _data = Parcel.obtain();
351                Parcel _reply = Parcel.obtain();
352                int _result;
353                try {
354                    _data.writeInterfaceToken(DESCRIPTOR);
355                    _data.writeString(id);
356                    _data.writeInt((force ? 1 : 0));
357                    mRemote.transact(Stub.TRANSACTION_unmountSecureContainer, _data, _reply, 0);
358                    _reply.readException();
359                    _result = _reply.readInt();
360                } finally {
361                    _reply.recycle();
362                    _data.recycle();
363                }
364                return _result;
365            }
366
367            /*
368             * Returns true if the specified container is mounted
369             */
370            public boolean isSecureContainerMounted(String id) throws RemoteException {
371                Parcel _data = Parcel.obtain();
372                Parcel _reply = Parcel.obtain();
373                boolean _result;
374                try {
375                    _data.writeInterfaceToken(DESCRIPTOR);
376                    _data.writeString(id);
377                    mRemote.transact(Stub.TRANSACTION_isSecureContainerMounted, _data, _reply, 0);
378                    _reply.readException();
379                    _result = 0 != _reply.readInt();
380                } finally {
381                    _reply.recycle();
382                    _data.recycle();
383                }
384                return _result;
385            }
386
387            /*
388             * Rename an unmounted secure container. Returns an int consistent
389             * with MountServiceResultCode
390             */
391            public int renameSecureContainer(String oldId, String newId) throws RemoteException {
392                Parcel _data = Parcel.obtain();
393                Parcel _reply = Parcel.obtain();
394                int _result;
395                try {
396                    _data.writeInterfaceToken(DESCRIPTOR);
397                    _data.writeString(oldId);
398                    _data.writeString(newId);
399                    mRemote.transact(Stub.TRANSACTION_renameSecureContainer, _data, _reply, 0);
400                    _reply.readException();
401                    _result = _reply.readInt();
402                } finally {
403                    _reply.recycle();
404                    _data.recycle();
405                }
406                return _result;
407            }
408
409            /*
410             * Returns the filesystem path of a mounted secure container.
411             */
412            public String getSecureContainerPath(String id) throws RemoteException {
413                Parcel _data = Parcel.obtain();
414                Parcel _reply = Parcel.obtain();
415                String _result;
416                try {
417                    _data.writeInterfaceToken(DESCRIPTOR);
418                    _data.writeString(id);
419                    mRemote.transact(Stub.TRANSACTION_getSecureContainerPath, _data, _reply, 0);
420                    _reply.readException();
421                    _result = _reply.readString();
422                } finally {
423                    _reply.recycle();
424                    _data.recycle();
425                }
426                return _result;
427            }
428
429            /**
430             * Gets an Array of currently known secure container IDs
431             */
432            public String[] getSecureContainerList() throws RemoteException {
433                Parcel _data = Parcel.obtain();
434                Parcel _reply = Parcel.obtain();
435                String[] _result;
436                try {
437                    _data.writeInterfaceToken(DESCRIPTOR);
438                    mRemote.transact(Stub.TRANSACTION_getSecureContainerList, _data, _reply, 0);
439                    _reply.readException();
440                    _result = _reply.createStringArray();
441                } finally {
442                    _reply.recycle();
443                    _data.recycle();
444                }
445                return _result;
446            }
447
448            /**
449             * Shuts down the MountService and gracefully unmounts all external
450             * media. Invokes call back once the shutdown is complete.
451             */
452            public void shutdown(IMountShutdownObserver observer)
453                    throws RemoteException {
454                Parcel _data = Parcel.obtain();
455                Parcel _reply = Parcel.obtain();
456                try {
457                    _data.writeInterfaceToken(DESCRIPTOR);
458                    _data.writeStrongBinder((observer != null ? observer.asBinder() : null));
459                    mRemote.transact(Stub.TRANSACTION_shutdown, _data, _reply, 0);
460                    _reply.readException();
461                } finally {
462                    _reply.recycle();
463                    _data.recycle();
464                }
465            }
466
467            /**
468             * Call into MountService by PackageManager to notify that its done
469             * processing the media status update request.
470             */
471            public void finishMediaUpdate() throws RemoteException {
472                Parcel _data = Parcel.obtain();
473                Parcel _reply = Parcel.obtain();
474                try {
475                    _data.writeInterfaceToken(DESCRIPTOR);
476                    mRemote.transact(Stub.TRANSACTION_finishMediaUpdate, _data, _reply, 0);
477                    _reply.readException();
478                } finally {
479                    _reply.recycle();
480                    _data.recycle();
481                }
482            }
483
484            /**
485             * Mounts an Opaque Binary Blob (OBB) with the specified decryption
486             * key and only allows the calling process's UID access to the
487             * contents. MountService will call back to the supplied
488             * IObbActionListener to inform it of the terminal state of the
489             * call.
490             */
491            public void mountObb(String filename, String key, IObbActionListener token, int nonce)
492                    throws RemoteException {
493                Parcel _data = Parcel.obtain();
494                Parcel _reply = Parcel.obtain();
495                try {
496                    _data.writeInterfaceToken(DESCRIPTOR);
497                    _data.writeString(filename);
498                    _data.writeString(key);
499                    _data.writeStrongBinder((token != null ? token.asBinder() : null));
500                    _data.writeInt(nonce);
501                    mRemote.transact(Stub.TRANSACTION_mountObb, _data, _reply, 0);
502                    _reply.readException();
503                } finally {
504                    _reply.recycle();
505                    _data.recycle();
506                }
507            }
508
509            /**
510             * Unmounts an Opaque Binary Blob (OBB). When the force flag is
511             * specified, any program using it will be forcibly killed to
512             * unmount the image. MountService will call back to the supplied
513             * IObbActionListener to inform it of the terminal state of the
514             * call.
515             */
516            public void unmountObb(String filename, boolean force, IObbActionListener token,
517                    int nonce) throws RemoteException {
518                Parcel _data = Parcel.obtain();
519                Parcel _reply = Parcel.obtain();
520                try {
521                    _data.writeInterfaceToken(DESCRIPTOR);
522                    _data.writeString(filename);
523                    _data.writeInt((force ? 1 : 0));
524                    _data.writeStrongBinder((token != null ? token.asBinder() : null));
525                    _data.writeInt(nonce);
526                    mRemote.transact(Stub.TRANSACTION_unmountObb, _data, _reply, 0);
527                    _reply.readException();
528                } finally {
529                    _reply.recycle();
530                    _data.recycle();
531                }
532            }
533
534            /**
535             * Checks whether the specified Opaque Binary Blob (OBB) is mounted
536             * somewhere.
537             */
538            public boolean isObbMounted(String filename) throws RemoteException {
539                Parcel _data = Parcel.obtain();
540                Parcel _reply = Parcel.obtain();
541                boolean _result;
542                try {
543                    _data.writeInterfaceToken(DESCRIPTOR);
544                    _data.writeString(filename);
545                    mRemote.transact(Stub.TRANSACTION_isObbMounted, _data, _reply, 0);
546                    _reply.readException();
547                    _result = 0 != _reply.readInt();
548                } finally {
549                    _reply.recycle();
550                    _data.recycle();
551                }
552                return _result;
553            }
554
555            /**
556             * Gets the path to the mounted Opaque Binary Blob (OBB).
557             */
558            public String getMountedObbPath(String filename) throws RemoteException {
559                Parcel _data = Parcel.obtain();
560                Parcel _reply = Parcel.obtain();
561                String _result;
562                try {
563                    _data.writeInterfaceToken(DESCRIPTOR);
564                    _data.writeString(filename);
565                    mRemote.transact(Stub.TRANSACTION_getMountedObbPath, _data, _reply, 0);
566                    _reply.readException();
567                    _result = _reply.readString();
568                } finally {
569                    _reply.recycle();
570                    _data.recycle();
571                }
572                return _result;
573            }
574
575            /**
576             * Returns whether the external storage is emulated.
577             */
578            public boolean isExternalStorageEmulated() throws RemoteException {
579                Parcel _data = Parcel.obtain();
580                Parcel _reply = Parcel.obtain();
581                boolean _result;
582                try {
583                    _data.writeInterfaceToken(DESCRIPTOR);
584                    mRemote.transact(Stub.TRANSACTION_isExternalStorageEmulated, _data, _reply, 0);
585                    _reply.readException();
586                    _result = 0 != _reply.readInt();
587                } finally {
588                    _reply.recycle();
589                    _data.recycle();
590                }
591                return _result;
592            }
593
594            public int getEncryptionState() throws RemoteException {
595                Parcel _data = Parcel.obtain();
596                Parcel _reply = Parcel.obtain();
597                int _result;
598                try {
599                    _data.writeInterfaceToken(DESCRIPTOR);
600                    mRemote.transact(Stub.TRANSACTION_getEncryptionState, _data, _reply, 0);
601                    _reply.readException();
602                    _result = _reply.readInt();
603                } finally {
604                    _reply.recycle();
605                    _data.recycle();
606                }
607                return _result;
608            }
609
610            public int decryptStorage(String password) throws RemoteException {
611                Parcel _data = Parcel.obtain();
612                Parcel _reply = Parcel.obtain();
613                int _result;
614                try {
615                    _data.writeInterfaceToken(DESCRIPTOR);
616                    _data.writeString(password);
617                    mRemote.transact(Stub.TRANSACTION_decryptStorage, _data, _reply, 0);
618                    _reply.readException();
619                    _result = _reply.readInt();
620                } finally {
621                    _reply.recycle();
622                    _data.recycle();
623                }
624                return _result;
625            }
626
627            public int encryptStorage(String password) throws RemoteException {
628                Parcel _data = Parcel.obtain();
629                Parcel _reply = Parcel.obtain();
630                int _result;
631                try {
632                    _data.writeInterfaceToken(DESCRIPTOR);
633                    _data.writeString(password);
634                    mRemote.transact(Stub.TRANSACTION_encryptStorage, _data, _reply, 0);
635                    _reply.readException();
636                    _result = _reply.readInt();
637                } finally {
638                    _reply.recycle();
639                    _data.recycle();
640                }
641                return _result;
642            }
643
644            public int changeEncryptionPassword(String password) throws RemoteException {
645                Parcel _data = Parcel.obtain();
646                Parcel _reply = Parcel.obtain();
647                int _result;
648                try {
649                    _data.writeInterfaceToken(DESCRIPTOR);
650                    _data.writeString(password);
651                    mRemote.transact(Stub.TRANSACTION_changeEncryptionPassword, _data, _reply, 0);
652                    _reply.readException();
653                    _result = _reply.readInt();
654                } finally {
655                    _reply.recycle();
656                    _data.recycle();
657                }
658                return _result;
659            }
660
661            @Override
662            public int verifyEncryptionPassword(String password) throws RemoteException {
663                Parcel _data = Parcel.obtain();
664                Parcel _reply = Parcel.obtain();
665                int _result;
666                try {
667                    _data.writeInterfaceToken(DESCRIPTOR);
668                    _data.writeString(password);
669                    mRemote.transact(Stub.TRANSACTION_verifyEncryptionPassword, _data, _reply, 0);
670                    _reply.readException();
671                    _result = _reply.readInt();
672                } finally {
673                    _reply.recycle();
674                    _data.recycle();
675                }
676                return _result;
677            }
678
679            public Parcelable[] getVolumeList() throws RemoteException {
680                Parcel _data = Parcel.obtain();
681                Parcel _reply = Parcel.obtain();
682                Parcelable[] _result;
683                try {
684                    _data.writeInterfaceToken(DESCRIPTOR);
685                    mRemote.transact(Stub.TRANSACTION_getVolumeList, _data, _reply, 0);
686                    _reply.readException();
687                    _result = _reply.readParcelableArray(StorageVolume.class.getClassLoader());
688                } finally {
689                    _reply.recycle();
690                    _data.recycle();
691                }
692                return _result;
693            }
694
695            /*
696             * Returns the filesystem path of a mounted secure container.
697             */
698            public String getSecureContainerFilesystemPath(String id) throws RemoteException {
699                Parcel _data = Parcel.obtain();
700                Parcel _reply = Parcel.obtain();
701                String _result;
702                try {
703                    _data.writeInterfaceToken(DESCRIPTOR);
704                    _data.writeString(id);
705                    mRemote.transact(Stub.TRANSACTION_getSecureContainerFilesystemPath, _data, _reply, 0);
706                    _reply.readException();
707                    _result = _reply.readString();
708                } finally {
709                    _reply.recycle();
710                    _data.recycle();
711                }
712                return _result;
713            }
714        }
715
716        private static final String DESCRIPTOR = "IMountService";
717
718        static final int TRANSACTION_registerListener = IBinder.FIRST_CALL_TRANSACTION + 0;
719
720        static final int TRANSACTION_unregisterListener = IBinder.FIRST_CALL_TRANSACTION + 1;
721
722        static final int TRANSACTION_isUsbMassStorageConnected = IBinder.FIRST_CALL_TRANSACTION + 2;
723
724        static final int TRANSACTION_setUsbMassStorageEnabled = IBinder.FIRST_CALL_TRANSACTION + 3;
725
726        static final int TRANSACTION_isUsbMassStorageEnabled = IBinder.FIRST_CALL_TRANSACTION + 4;
727
728        static final int TRANSACTION_mountVolume = IBinder.FIRST_CALL_TRANSACTION + 5;
729
730        static final int TRANSACTION_unmountVolume = IBinder.FIRST_CALL_TRANSACTION + 6;
731
732        static final int TRANSACTION_formatVolume = IBinder.FIRST_CALL_TRANSACTION + 7;
733
734        static final int TRANSACTION_getStorageUsers = IBinder.FIRST_CALL_TRANSACTION + 8;
735
736        static final int TRANSACTION_getVolumeState = IBinder.FIRST_CALL_TRANSACTION + 9;
737
738        static final int TRANSACTION_createSecureContainer = IBinder.FIRST_CALL_TRANSACTION + 10;
739
740        static final int TRANSACTION_finalizeSecureContainer = IBinder.FIRST_CALL_TRANSACTION + 11;
741
742        static final int TRANSACTION_destroySecureContainer = IBinder.FIRST_CALL_TRANSACTION + 12;
743
744        static final int TRANSACTION_mountSecureContainer = IBinder.FIRST_CALL_TRANSACTION + 13;
745
746        static final int TRANSACTION_unmountSecureContainer = IBinder.FIRST_CALL_TRANSACTION + 14;
747
748        static final int TRANSACTION_isSecureContainerMounted = IBinder.FIRST_CALL_TRANSACTION + 15;
749
750        static final int TRANSACTION_renameSecureContainer = IBinder.FIRST_CALL_TRANSACTION + 16;
751
752        static final int TRANSACTION_getSecureContainerPath = IBinder.FIRST_CALL_TRANSACTION + 17;
753
754        static final int TRANSACTION_getSecureContainerList = IBinder.FIRST_CALL_TRANSACTION + 18;
755
756        static final int TRANSACTION_shutdown = IBinder.FIRST_CALL_TRANSACTION + 19;
757
758        static final int TRANSACTION_finishMediaUpdate = IBinder.FIRST_CALL_TRANSACTION + 20;
759
760        static final int TRANSACTION_mountObb = IBinder.FIRST_CALL_TRANSACTION + 21;
761
762        static final int TRANSACTION_unmountObb = IBinder.FIRST_CALL_TRANSACTION + 22;
763
764        static final int TRANSACTION_isObbMounted = IBinder.FIRST_CALL_TRANSACTION + 23;
765
766        static final int TRANSACTION_getMountedObbPath = IBinder.FIRST_CALL_TRANSACTION + 24;
767
768        static final int TRANSACTION_isExternalStorageEmulated = IBinder.FIRST_CALL_TRANSACTION + 25;
769
770        static final int TRANSACTION_decryptStorage = IBinder.FIRST_CALL_TRANSACTION + 26;
771
772        static final int TRANSACTION_encryptStorage = IBinder.FIRST_CALL_TRANSACTION + 27;
773
774        static final int TRANSACTION_changeEncryptionPassword = IBinder.FIRST_CALL_TRANSACTION + 28;
775
776        static final int TRANSACTION_getVolumeList = IBinder.FIRST_CALL_TRANSACTION + 29;
777
778        static final int TRANSACTION_getSecureContainerFilesystemPath = IBinder.FIRST_CALL_TRANSACTION + 30;
779
780        static final int TRANSACTION_getEncryptionState = IBinder.FIRST_CALL_TRANSACTION + 31;
781
782        static final int TRANSACTION_verifyEncryptionPassword = IBinder.FIRST_CALL_TRANSACTION + 32;
783
784        /**
785         * Cast an IBinder object into an IMountService interface, generating a
786         * proxy if needed.
787         */
788        public static IMountService asInterface(IBinder obj) {
789            if (obj == null) {
790                return null;
791            }
792            IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
793            if (iin != null && iin instanceof IMountService) {
794                return (IMountService) iin;
795            }
796            return new IMountService.Stub.Proxy(obj);
797        }
798
799        /** Construct the stub at attach it to the interface. */
800        public Stub() {
801            attachInterface(this, DESCRIPTOR);
802        }
803
804        public IBinder asBinder() {
805            return this;
806        }
807
808        @Override
809        public boolean onTransact(int code, Parcel data, Parcel reply,
810                int flags) throws RemoteException {
811            switch (code) {
812                case INTERFACE_TRANSACTION: {
813                    reply.writeString(DESCRIPTOR);
814                    return true;
815                }
816                case TRANSACTION_registerListener: {
817                    data.enforceInterface(DESCRIPTOR);
818                    IMountServiceListener listener;
819                    listener = IMountServiceListener.Stub.asInterface(data.readStrongBinder());
820                    registerListener(listener);
821                    reply.writeNoException();
822                    return true;
823                }
824                case TRANSACTION_unregisterListener: {
825                    data.enforceInterface(DESCRIPTOR);
826                    IMountServiceListener listener;
827                    listener = IMountServiceListener.Stub.asInterface(data.readStrongBinder());
828                    unregisterListener(listener);
829                    reply.writeNoException();
830                    return true;
831                }
832                case TRANSACTION_isUsbMassStorageConnected: {
833                    data.enforceInterface(DESCRIPTOR);
834                    boolean result = isUsbMassStorageConnected();
835                    reply.writeNoException();
836                    reply.writeInt((result ? 1 : 0));
837                    return true;
838                }
839                case TRANSACTION_setUsbMassStorageEnabled: {
840                    data.enforceInterface(DESCRIPTOR);
841                    boolean enable;
842                    enable = 0 != data.readInt();
843                    setUsbMassStorageEnabled(enable);
844                    reply.writeNoException();
845                    return true;
846                }
847                case TRANSACTION_isUsbMassStorageEnabled: {
848                    data.enforceInterface(DESCRIPTOR);
849                    boolean result = isUsbMassStorageEnabled();
850                    reply.writeNoException();
851                    reply.writeInt((result ? 1 : 0));
852                    return true;
853                }
854                case TRANSACTION_mountVolume: {
855                    data.enforceInterface(DESCRIPTOR);
856                    String mountPoint;
857                    mountPoint = data.readString();
858                    int resultCode = mountVolume(mountPoint);
859                    reply.writeNoException();
860                    reply.writeInt(resultCode);
861                    return true;
862                }
863                case TRANSACTION_unmountVolume: {
864                    data.enforceInterface(DESCRIPTOR);
865                    String mountPoint;
866                    mountPoint = data.readString();
867                    boolean force = 0 != data.readInt();
868                    boolean removeEncrypt = 0 != data.readInt();
869                    unmountVolume(mountPoint, force, removeEncrypt);
870                    reply.writeNoException();
871                    return true;
872                }
873                case TRANSACTION_formatVolume: {
874                    data.enforceInterface(DESCRIPTOR);
875                    String mountPoint;
876                    mountPoint = data.readString();
877                    int result = formatVolume(mountPoint);
878                    reply.writeNoException();
879                    reply.writeInt(result);
880                    return true;
881                }
882                case TRANSACTION_getStorageUsers: {
883                    data.enforceInterface(DESCRIPTOR);
884                    String path;
885                    path = data.readString();
886                    int[] pids = getStorageUsers(path);
887                    reply.writeNoException();
888                    reply.writeIntArray(pids);
889                    return true;
890                }
891                case TRANSACTION_getVolumeState: {
892                    data.enforceInterface(DESCRIPTOR);
893                    String mountPoint;
894                    mountPoint = data.readString();
895                    String state = getVolumeState(mountPoint);
896                    reply.writeNoException();
897                    reply.writeString(state);
898                    return true;
899                }
900                case TRANSACTION_createSecureContainer: {
901                    data.enforceInterface(DESCRIPTOR);
902                    String id;
903                    id = data.readString();
904                    int sizeMb;
905                    sizeMb = data.readInt();
906                    String fstype;
907                    fstype = data.readString();
908                    String key;
909                    key = data.readString();
910                    int ownerUid;
911                    ownerUid = data.readInt();
912                    int resultCode = createSecureContainer(id, sizeMb, fstype, key, ownerUid);
913                    reply.writeNoException();
914                    reply.writeInt(resultCode);
915                    return true;
916                }
917                case TRANSACTION_finalizeSecureContainer: {
918                    data.enforceInterface(DESCRIPTOR);
919                    String id;
920                    id = data.readString();
921                    int resultCode = finalizeSecureContainer(id);
922                    reply.writeNoException();
923                    reply.writeInt(resultCode);
924                    return true;
925                }
926                case TRANSACTION_destroySecureContainer: {
927                    data.enforceInterface(DESCRIPTOR);
928                    String id;
929                    id = data.readString();
930                    boolean force;
931                    force = 0 != data.readInt();
932                    int resultCode = destroySecureContainer(id, force);
933                    reply.writeNoException();
934                    reply.writeInt(resultCode);
935                    return true;
936                }
937                case TRANSACTION_mountSecureContainer: {
938                    data.enforceInterface(DESCRIPTOR);
939                    String id;
940                    id = data.readString();
941                    String key;
942                    key = data.readString();
943                    int ownerUid;
944                    ownerUid = data.readInt();
945                    int resultCode = mountSecureContainer(id, key, ownerUid);
946                    reply.writeNoException();
947                    reply.writeInt(resultCode);
948                    return true;
949                }
950                case TRANSACTION_unmountSecureContainer: {
951                    data.enforceInterface(DESCRIPTOR);
952                    String id;
953                    id = data.readString();
954                    boolean force;
955                    force = 0 != data.readInt();
956                    int resultCode = unmountSecureContainer(id, force);
957                    reply.writeNoException();
958                    reply.writeInt(resultCode);
959                    return true;
960                }
961                case TRANSACTION_isSecureContainerMounted: {
962                    data.enforceInterface(DESCRIPTOR);
963                    String id;
964                    id = data.readString();
965                    boolean status = isSecureContainerMounted(id);
966                    reply.writeNoException();
967                    reply.writeInt((status ? 1 : 0));
968                    return true;
969                }
970                case TRANSACTION_renameSecureContainer: {
971                    data.enforceInterface(DESCRIPTOR);
972                    String oldId;
973                    oldId = data.readString();
974                    String newId;
975                    newId = data.readString();
976                    int resultCode = renameSecureContainer(oldId, newId);
977                    reply.writeNoException();
978                    reply.writeInt(resultCode);
979                    return true;
980                }
981                case TRANSACTION_getSecureContainerPath: {
982                    data.enforceInterface(DESCRIPTOR);
983                    String id;
984                    id = data.readString();
985                    String path = getSecureContainerPath(id);
986                    reply.writeNoException();
987                    reply.writeString(path);
988                    return true;
989                }
990                case TRANSACTION_getSecureContainerList: {
991                    data.enforceInterface(DESCRIPTOR);
992                    String[] ids = getSecureContainerList();
993                    reply.writeNoException();
994                    reply.writeStringArray(ids);
995                    return true;
996                }
997                case TRANSACTION_shutdown: {
998                    data.enforceInterface(DESCRIPTOR);
999                    IMountShutdownObserver observer;
1000                    observer = IMountShutdownObserver.Stub.asInterface(data
1001                            .readStrongBinder());
1002                    shutdown(observer);
1003                    reply.writeNoException();
1004                    return true;
1005                }
1006                case TRANSACTION_finishMediaUpdate: {
1007                    data.enforceInterface(DESCRIPTOR);
1008                    finishMediaUpdate();
1009                    reply.writeNoException();
1010                    return true;
1011                }
1012                case TRANSACTION_mountObb: {
1013                    data.enforceInterface(DESCRIPTOR);
1014                    String filename;
1015                    filename = data.readString();
1016                    String key;
1017                    key = data.readString();
1018                    IObbActionListener observer;
1019                    observer = IObbActionListener.Stub.asInterface(data.readStrongBinder());
1020                    int nonce;
1021                    nonce = data.readInt();
1022                    mountObb(filename, key, observer, nonce);
1023                    reply.writeNoException();
1024                    return true;
1025                }
1026                case TRANSACTION_unmountObb: {
1027                    data.enforceInterface(DESCRIPTOR);
1028                    String filename;
1029                    filename = data.readString();
1030                    boolean force;
1031                    force = 0 != data.readInt();
1032                    IObbActionListener observer;
1033                    observer = IObbActionListener.Stub.asInterface(data.readStrongBinder());
1034                    int nonce;
1035                    nonce = data.readInt();
1036                    unmountObb(filename, force, observer, nonce);
1037                    reply.writeNoException();
1038                    return true;
1039                }
1040                case TRANSACTION_isObbMounted: {
1041                    data.enforceInterface(DESCRIPTOR);
1042                    String filename;
1043                    filename = data.readString();
1044                    boolean status = isObbMounted(filename);
1045                    reply.writeNoException();
1046                    reply.writeInt((status ? 1 : 0));
1047                    return true;
1048                }
1049                case TRANSACTION_getMountedObbPath: {
1050                    data.enforceInterface(DESCRIPTOR);
1051                    String filename;
1052                    filename = data.readString();
1053                    String mountedPath = getMountedObbPath(filename);
1054                    reply.writeNoException();
1055                    reply.writeString(mountedPath);
1056                    return true;
1057                }
1058                case TRANSACTION_isExternalStorageEmulated: {
1059                    data.enforceInterface(DESCRIPTOR);
1060                    boolean emulated = isExternalStorageEmulated();
1061                    reply.writeNoException();
1062                    reply.writeInt(emulated ? 1 : 0);
1063                    return true;
1064                }
1065                case TRANSACTION_decryptStorage: {
1066                    data.enforceInterface(DESCRIPTOR);
1067                    String password = data.readString();
1068                    int result = decryptStorage(password);
1069                    reply.writeNoException();
1070                    reply.writeInt(result);
1071                    return true;
1072                }
1073                case TRANSACTION_encryptStorage: {
1074                    data.enforceInterface(DESCRIPTOR);
1075                    String password = data.readString();
1076                    int result = encryptStorage(password);
1077                    reply.writeNoException();
1078                    reply.writeInt(result);
1079                    return true;
1080                }
1081                case TRANSACTION_changeEncryptionPassword: {
1082                    data.enforceInterface(DESCRIPTOR);
1083                    String password = data.readString();
1084                    int result = changeEncryptionPassword(password);
1085                    reply.writeNoException();
1086                    reply.writeInt(result);
1087                    return true;
1088                }
1089                case TRANSACTION_getVolumeList: {
1090                    data.enforceInterface(DESCRIPTOR);
1091                    Parcelable[] result = getVolumeList();
1092                    reply.writeNoException();
1093                    reply.writeParcelableArray(result, 0);
1094                    return true;
1095                }
1096                case TRANSACTION_getSecureContainerFilesystemPath: {
1097                    data.enforceInterface(DESCRIPTOR);
1098                    String id;
1099                    id = data.readString();
1100                    String path = getSecureContainerFilesystemPath(id);
1101                    reply.writeNoException();
1102                    reply.writeString(path);
1103                    return true;
1104                }
1105                case TRANSACTION_getEncryptionState: {
1106                    data.enforceInterface(DESCRIPTOR);
1107                    int result = getEncryptionState();
1108                    reply.writeNoException();
1109                    reply.writeInt(result);
1110                    return true;
1111                }
1112            }
1113            return super.onTransact(code, data, reply, flags);
1114        }
1115    }
1116
1117    /*
1118     * Creates a secure container with the specified parameters. Returns an int
1119     * consistent with MountServiceResultCode
1120     */
1121    public int createSecureContainer(String id, int sizeMb, String fstype, String key, int ownerUid)
1122            throws RemoteException;
1123
1124    /*
1125     * Destroy a secure container, and free up all resources associated with it.
1126     * NOTE: Ensure all references are released prior to deleting. Returns an
1127     * int consistent with MountServiceResultCode
1128     */
1129    public int destroySecureContainer(String id, boolean force) throws RemoteException;
1130
1131    /*
1132     * Finalize a container which has just been created and populated. After
1133     * finalization, the container is immutable. Returns an int consistent with
1134     * MountServiceResultCode
1135     */
1136    public int finalizeSecureContainer(String id) throws RemoteException;
1137
1138    /**
1139     * Call into MountService by PackageManager to notify that its done
1140     * processing the media status update request.
1141     */
1142    public void finishMediaUpdate() throws RemoteException;
1143
1144    /**
1145     * Format external storage given a mount point. Returns an int consistent
1146     * with MountServiceResultCode
1147     */
1148    public int formatVolume(String mountPoint) throws RemoteException;
1149
1150    /**
1151     * Gets the path to the mounted Opaque Binary Blob (OBB).
1152     */
1153    public String getMountedObbPath(String filename) throws RemoteException;
1154
1155    /**
1156     * Gets an Array of currently known secure container IDs
1157     */
1158    public String[] getSecureContainerList() throws RemoteException;
1159
1160    /*
1161     * Returns the filesystem path of a mounted secure container.
1162     */
1163    public String getSecureContainerPath(String id) throws RemoteException;
1164
1165    /**
1166     * Returns an array of pids with open files on the specified path.
1167     */
1168    public int[] getStorageUsers(String path) throws RemoteException;
1169
1170    /**
1171     * Gets the state of a volume via its mountpoint.
1172     */
1173    public String getVolumeState(String mountPoint) throws RemoteException;
1174
1175    /**
1176     * Checks whether the specified Opaque Binary Blob (OBB) is mounted
1177     * somewhere.
1178     */
1179    public boolean isObbMounted(String filename) throws RemoteException;
1180
1181    /*
1182     * Returns true if the specified container is mounted
1183     */
1184    public boolean isSecureContainerMounted(String id) throws RemoteException;
1185
1186    /**
1187     * Returns true if a USB mass storage host is connected
1188     */
1189    public boolean isUsbMassStorageConnected() throws RemoteException;
1190
1191    /**
1192     * Returns true if a USB mass storage host is enabled (media is shared)
1193     */
1194    public boolean isUsbMassStorageEnabled() throws RemoteException;
1195
1196    /**
1197     * Mounts an Opaque Binary Blob (OBB) with the specified decryption key and
1198     * only allows the calling process's UID access to the contents.
1199     * MountService will call back to the supplied IObbActionListener to inform
1200     * it of the terminal state of the call.
1201     */
1202    public void mountObb(String filename, String key, IObbActionListener token, int nonce)
1203            throws RemoteException;
1204
1205    /*
1206     * Mount a secure container with the specified key and owner UID. Returns an
1207     * int consistent with MountServiceResultCode
1208     */
1209    public int mountSecureContainer(String id, String key, int ownerUid) throws RemoteException;
1210
1211    /**
1212     * Mount external storage at given mount point. Returns an int consistent
1213     * with MountServiceResultCode
1214     */
1215    public int mountVolume(String mountPoint) throws RemoteException;
1216
1217    /**
1218     * Registers an IMountServiceListener for receiving async notifications.
1219     */
1220    public void registerListener(IMountServiceListener listener) throws RemoteException;
1221
1222    /*
1223     * Rename an unmounted secure container. Returns an int consistent with
1224     * MountServiceResultCode
1225     */
1226    public int renameSecureContainer(String oldId, String newId) throws RemoteException;
1227
1228    /**
1229     * Enables / disables USB mass storage. The caller should check actual
1230     * status of enabling/disabling USB mass storage via StorageEventListener.
1231     */
1232    public void setUsbMassStorageEnabled(boolean enable) throws RemoteException;
1233
1234    /**
1235     * Shuts down the MountService and gracefully unmounts all external media.
1236     * Invokes call back once the shutdown is complete.
1237     */
1238    public void shutdown(IMountShutdownObserver observer) throws RemoteException;
1239
1240    /**
1241     * Unmounts an Opaque Binary Blob (OBB). When the force flag is specified,
1242     * any program using it will be forcibly killed to unmount the image.
1243     * MountService will call back to the supplied IObbActionListener to inform
1244     * it of the terminal state of the call.
1245     */
1246    public void unmountObb(String filename, boolean force, IObbActionListener token, int nonce)
1247            throws RemoteException;
1248
1249    /*
1250     * Unount a secure container. Returns an int consistent with
1251     * MountServiceResultCode
1252     */
1253    public int unmountSecureContainer(String id, boolean force) throws RemoteException;
1254
1255    /**
1256     * Safely unmount external storage at given mount point. The unmount is an
1257     * asynchronous operation. Applications should register StorageEventListener
1258     * for storage related status changes.
1259     * @param mountPoint the mount point
1260     * @param force whether or not to forcefully unmount it (e.g. even if programs are using this
1261     *     data currently)
1262     * @param removeEncryption whether or not encryption mapping should be removed from the volume.
1263     *     This value implies {@code force}.
1264     */
1265    public void unmountVolume(String mountPoint, boolean force, boolean removeEncryption)
1266            throws RemoteException;
1267
1268    /**
1269     * Unregisters an IMountServiceListener
1270     */
1271    public void unregisterListener(IMountServiceListener listener) throws RemoteException;
1272
1273    /**
1274     * Returns whether or not the external storage is emulated.
1275     */
1276    public boolean isExternalStorageEmulated() throws RemoteException;
1277
1278    /** The volume is not encrypted. */
1279    static final int ENCRYPTION_STATE_NONE = 1;
1280    /** The volume has been encrypted succesfully. */
1281    static final int ENCRYPTION_STATE_OK = 0;
1282    /** The volume is in a bad state. */
1283    static final int ENCRYPTION_STATE_ERROR_UNKNOWN = -1;
1284    /** The volume is in a bad state - partially encrypted. Data is likely irrecoverable. */
1285    static final int ENCRYPTION_STATE_ERROR_INCOMPLETE = -2;
1286
1287    /**
1288     * Determines the encryption state of the volume.
1289     * @return a numerical value. See {@code ENCRYPTION_STATE_*} for possible values.
1290     */
1291    public int getEncryptionState() throws RemoteException;
1292
1293    /**
1294     * Decrypts any encrypted volumes.
1295     */
1296    public int decryptStorage(String password) throws RemoteException;
1297
1298    /**
1299     * Encrypts storage.
1300     */
1301    public int encryptStorage(String password) throws RemoteException;
1302
1303    /**
1304     * Changes the encryption password.
1305     */
1306    public int changeEncryptionPassword(String password) throws RemoteException;
1307
1308    /**
1309     * Verify the encryption password against the stored volume.  This method
1310     * may only be called by the system process.
1311     */
1312    public int verifyEncryptionPassword(String password) throws RemoteException;
1313
1314    /**
1315     * Returns list of all mountable volumes.
1316     */
1317    public Parcelable[] getVolumeList() throws RemoteException;
1318
1319    public String getSecureContainerFilesystemPath(String id) throws RemoteException;
1320}
1321