Loading services/core/java/com/android/server/StorageManagerService.java +17 −59 Original line number Diff line number Diff line Loading @@ -80,6 +80,7 @@ import android.os.IBinder; import android.os.IStoraged; import android.os.IVold; import android.os.IVoldListener; import android.os.IVoldMountCallback; import android.os.IVoldTaskListener; import android.os.Looper; import android.os.Message; Loading Loading @@ -348,10 +349,6 @@ class StorageManagerService extends IStorageManager.Stub @GuardedBy("mLock") private ArrayMap<String, CountDownLatch> mDiskScanLatches = new ArrayMap<>(); /** Map from volume ID to latches */ @GuardedBy("mLock") private ArrayMap<String, CountDownLatch> mFuseVolumeReadyLatches = new ArrayMap<>(); @GuardedBy("mLock") private IPackageMoveObserver mMoveCallback; @GuardedBy("mLock") Loading Loading @@ -464,17 +461,6 @@ class StorageManagerService extends IStorageManager.Stub } } private CountDownLatch findOrCreateFuseVolumeReadyLatch(String volId) { synchronized (mLock) { CountDownLatch latch = mFuseVolumeReadyLatches.get(volId); if (latch == null) { latch = new CountDownLatch(1); mFuseVolumeReadyLatches.put(volId, latch); } return latch; } } /** List of crypto types. * These must match CRYPT_TYPE_XXX in cryptfs.h AND their * corresponding commands in CommandListener.cpp */ Loading Loading @@ -612,7 +598,6 @@ class StorageManagerService extends IStorageManager.Stub private static final int H_ABORT_IDLE_MAINT = 12; private static final int H_BOOT_COMPLETED = 13; private static final int H_COMPLETE_UNLOCK_USER = 14; private static final int H_VOLUME_READY = 15; class StorageManagerServiceHandler extends Handler { public StorageManagerServiceHandler(Looper looper) { Loading Loading @@ -673,22 +658,6 @@ class StorageManagerService extends IStorageManager.Stub } break; } case H_VOLUME_READY: { final VolumeInfo vol = (VolumeInfo) msg.obj; try { mStorageSessionController.onVolumeReady(vol); synchronized (mLock) { CountDownLatch latch = mFuseVolumeReadyLatches.remove(vol.id); if (latch != null) { latch.countDown(); } } } catch (IllegalStateException | ExternalStorageServiceException e) { Slog.i(TAG, "Failed to initialise volume " + vol, e); } break; } case H_VOLUME_MOUNT: { final VolumeInfo vol = (VolumeInfo) msg.obj; if (isMountDisallowed(vol)) { Loading Loading @@ -1431,13 +1400,6 @@ class StorageManagerService extends IStorageManager.Stub writeSettingsLocked(); } if (mIsFuseEnabled && newState == VolumeInfo.STATE_MOUNTED && (vol.type == VolumeInfo.TYPE_PUBLIC || vol.type == VolumeInfo.TYPE_EMULATED)) { Slog.i(TAG, "Initialising volume " + vol + " ..."); // TODO(b/144275217): Delay broadcasts till mount is really ready mHandler.obtainMessage(H_VOLUME_READY, vol).sendToTarget(); } mCallbacks.notifyVolumeStateChanged(vol, oldState, newState); // Do not broadcast before boot has completed to avoid launching the Loading Loading @@ -1912,33 +1874,29 @@ class StorageManagerService extends IStorageManager.Stub throw new SecurityException("Mounting " + volId + " restricted by policy"); } CountDownLatch latch = null; if (mIsFuseEnabled && StorageSessionController.isEmulatedOrPublic(vol)) { latch = findOrCreateFuseVolumeReadyLatch(volId); } mount(vol); if (latch != null) { try { waitForLatch(latch, "mount " + volId, 3 * DateUtils.MINUTE_IN_MILLIS); } catch (TimeoutException e) { Slog.wtf(TAG, e); } finally { synchronized (mLock) { mFuseVolumeReadyLatches.remove(volId); } } } } private void mount(VolumeInfo vol) { try { // TODO(b/135341433): Remove paranoid logging when FUSE is stable Slog.i(TAG, "Mounting volume " + vol); FileDescriptor fd = mVold.mount(vol.id, vol.mountFlags, vol.mountUserId); mVold.mount(vol.id, vol.mountFlags, vol.mountUserId, new IVoldMountCallback.Stub() { @Override public boolean onVolumeChecking(FileDescriptor deviceFd, String path, String internalPath) { vol.path = path; vol.internalPath = internalPath; try { mStorageSessionController.onVolumeMount(deviceFd, vol); return true; } catch (ExternalStorageServiceException e) { Slog.i(TAG, "Failed to mount volume " + vol, e); return false; } } }); Slog.i(TAG, "Mounted volume " + vol); mStorageSessionController.onVolumeMount(fd, vol); } catch (Exception e) { Slog.wtf(TAG, e); } Loading Loading @@ -3643,7 +3601,7 @@ class StorageManagerService extends IStorageManager.Stub try { mObbState.volId = mVold.createObb(mObbState.canonicalPath, binderKey, mObbState.ownerGid); mVold.mount(mObbState.volId, 0, -1); mVold.mount(mObbState.volId, 0, -1, null); if (DEBUG_OBB) Slog.d(TAG, "Successfully mounted OBB " + mObbState.canonicalPath); Loading services/core/java/com/android/server/storage/StorageSessionController.java +24 −82 Original line number Diff line number Diff line Loading @@ -69,15 +69,21 @@ public final class StorageSessionController { } /** * Creates a storage session associated with {@code deviceFd} for {@code vol}. Sessions can be * started with {@link #onVolumeReady} and removed with {@link #onVolumeUnmount} or * {@link #onVolumeRemove}. * Creates and starts a storage session associated with {@code deviceFd} for {@code vol}. * Sessions can be started with {@link #onVolumeReady} and removed with {@link #onVolumeUnmount} * or {@link #onVolumeRemove}. * * Throws an {@link IllegalStateException} if a session for {@code vol} has already been created * * Does nothing if {@link #shouldHandle} is {@code false} * * Blocks until the session is started or fails * * @throws ExternalStorageServiceException if the session fails to start * @throws IllegalStateException if a session has already been created for {@code vol} */ public void onVolumeMount(FileDescriptor deviceFd, VolumeInfo vol) { public void onVolumeMount(FileDescriptor deviceFd, VolumeInfo vol) throws ExternalStorageServiceException { if (!shouldHandle(vol)) { return; } Loading @@ -87,71 +93,22 @@ public final class StorageSessionController { String sessionId = vol.getId(); int userId = vol.getMountUserId(); if (deviceFd == null) { Slog.w(TAG, "Null fd. Session not started for vol: " + vol); return; } // Get realpath for the fd, paths that are not /dev/null need additional // setup by the ExternalStorageService before they can be ready String realPath; try { realPath = ParcelFileDescriptor.getFile(deviceFd).getPath(); } catch (IOException e) { Slog.wtf(TAG, "Could not get real path from fd: " + deviceFd, e); return; } if ("/dev/null".equals(realPath)) { Slog.i(TAG, "Volume ready for use with id: " + sessionId); return; } StorageUserConnection connection = null; synchronized (mLock) { StorageUserConnection connection = mConnections.get(userId); connection = mConnections.get(userId); if (connection == null) { Slog.i(TAG, "Creating connection for user: " + userId); connection = new StorageUserConnection(mContext, userId, this); mConnections.put(userId, connection); } Slog.i(TAG, "Creating session with id: " + sessionId); connection.createSession(sessionId, new ParcelFileDescriptor(deviceFd)); } connection.createSession(sessionId, new ParcelFileDescriptor(deviceFd), vol.getPath().getPath(), vol.getInternalPath().getPath()); } /** * Starts a storage session associated with {@code vol} after {@link #onVolumeMount}. * * Subsequent calls will attempt to start the storage session, but does nothing if already * started. If the user associated with {@code vol} is not yet ready, all pending sesssions * can be restarted with {@link onUnlockUser}. * * Does nothing if {@link #shouldHandle} is {@code false} * * Blocks until the session is started or fails * * @throws ExternalStorageServiceException if the session fails to start */ public void onVolumeReady(VolumeInfo vol) throws ExternalStorageServiceException { if (!shouldHandle(vol)) { return; } Slog.i(TAG, "On volume ready " + vol); String sessionId = vol.getId(); StorageUserConnection connection = null; synchronized (mLock) { connection = mConnections.get(vol.getMountUserId()); if (connection == null) { Slog.i(TAG, "Volume ready but no associated connection"); return; } } connection.initSession(sessionId, vol.getPath().getPath(), vol.getInternalPath().getPath()); if (isReady()) { // At boot, a volume can be mounted before user is unlocked, in that case, we create it // above and save it so that we can restart all sessions when the user is unlocked if (mExternalStorageServiceComponent != null) { connection.startSession(sessionId); } else { Slog.i(TAG, "Controller not initialised, session not started " + sessionId); Loading Loading @@ -205,15 +162,11 @@ public final class StorageSessionController { if (connection != null) { String sessionId = vol.getId(); if (isReady()) { try { connection.removeSessionAndWait(sessionId); } catch (ExternalStorageServiceException e) { Slog.e(TAG, "Failed to end session for vol with id: " + sessionId, e); } } else { Slog.i(TAG, "Controller not initialised, session not ended " + sessionId); } } } Loading @@ -232,7 +185,7 @@ public final class StorageSessionController { Slog.i(TAG, "On user unlock " + userId); if (userId == 0) { init(); initExternalStorageServiceComponent(); } StorageUserConnection connection = null; Loading @@ -259,13 +212,6 @@ public final class StorageSessionController { return; } if (!isReady()) { synchronized (mLock) { mConnections.clear(); } return; } SparseArray<StorageUserConnection> connections = new SparseArray(); synchronized (mLock) { mIsResetting = true; Loading Loading @@ -311,7 +257,7 @@ public final class StorageSessionController { } } private void init() throws ExternalStorageServiceException { private void initExternalStorageServiceComponent() throws ExternalStorageServiceException { Slog.i(TAG, "Initialialising..."); ProviderInfo provider = mContext.getPackageManager().resolveContentProvider( MediaStore.AUTHORITY, PackageManager.MATCH_DIRECT_BOOT_AWARE Loading Loading @@ -415,8 +361,4 @@ public final class StorageSessionController { private boolean shouldHandle(@Nullable VolumeInfo vol) { return mIsFuseEnabled && !mIsResetting && (vol == null || isEmulatedOrPublic(vol)); } private boolean isReady() { return mExternalStorageServiceComponent != null; } } services/core/java/com/android/server/storage/StorageUserConnection.java +10 −36 Original line number Diff line number Diff line Loading @@ -75,46 +75,20 @@ public final class StorageUserConnection { /** * Creates and stores a storage {@link Session}. * * Created sessions must be initialised with {@link #initSession} before starting with * {@link #startSession}. * * They must also be cleaned up with {@link #removeSession}. * * @throws IllegalArgumentException if a {@code Session} with {@code sessionId} already exists */ public void createSession(String sessionId, ParcelFileDescriptor pfd) { public void createSession(String sessionId, ParcelFileDescriptor pfd, String upperPath, String lowerPath) { Preconditions.checkNotNull(sessionId); Preconditions.checkNotNull(pfd); Preconditions.checkNotNull(upperPath); Preconditions.checkNotNull(lowerPath); synchronized (mLock) { Preconditions.checkArgument(!mSessions.containsKey(sessionId)); mSessions.put(sessionId, new Session(sessionId, pfd)); } } /** * Initialise a storage {@link Session}. * * Initialised sessions can be started with {@link #startSession}. * * They must also be cleaned up with {@link #removeSession}. * * @throws IllegalArgumentException if {@code sessionId} does not exist or is initialised */ public void initSession(String sessionId, String upperPath, String lowerPath) { synchronized (mLock) { Session session = mSessions.get(sessionId); if (session == null) { throw new IllegalStateException("Failed to initialise non existent session. Id: " + sessionId + ". Upper path: " + upperPath + ". Lower path: " + lowerPath); } else if (session.isInitialisedLocked()) { throw new IllegalStateException("Already initialised session. Id: " + sessionId + ". Upper path: " + upperPath + ". Lower path: " + lowerPath); } else { session.upperPath = upperPath; session.lowerPath = lowerPath; Slog.i(TAG, "Initialised session: " + session); } mSessions.put(sessionId, new Session(sessionId, pfd, upperPath, lowerPath)); } } Loading Loading @@ -440,14 +414,14 @@ public final class StorageUserConnection { private static final class Session implements AutoCloseable { public final String sessionId; public final ParcelFileDescriptor pfd; @GuardedBy("mLock") public String lowerPath; @GuardedBy("mLock") public String upperPath; public final String lowerPath; public final String upperPath; Session(String sessionId, ParcelFileDescriptor pfd) { Session(String sessionId, ParcelFileDescriptor pfd, String upperPath, String lowerPath) { this.sessionId = sessionId; this.pfd = pfd; this.upperPath = upperPath; this.lowerPath = lowerPath; } @Override Loading Loading
services/core/java/com/android/server/StorageManagerService.java +17 −59 Original line number Diff line number Diff line Loading @@ -80,6 +80,7 @@ import android.os.IBinder; import android.os.IStoraged; import android.os.IVold; import android.os.IVoldListener; import android.os.IVoldMountCallback; import android.os.IVoldTaskListener; import android.os.Looper; import android.os.Message; Loading Loading @@ -348,10 +349,6 @@ class StorageManagerService extends IStorageManager.Stub @GuardedBy("mLock") private ArrayMap<String, CountDownLatch> mDiskScanLatches = new ArrayMap<>(); /** Map from volume ID to latches */ @GuardedBy("mLock") private ArrayMap<String, CountDownLatch> mFuseVolumeReadyLatches = new ArrayMap<>(); @GuardedBy("mLock") private IPackageMoveObserver mMoveCallback; @GuardedBy("mLock") Loading Loading @@ -464,17 +461,6 @@ class StorageManagerService extends IStorageManager.Stub } } private CountDownLatch findOrCreateFuseVolumeReadyLatch(String volId) { synchronized (mLock) { CountDownLatch latch = mFuseVolumeReadyLatches.get(volId); if (latch == null) { latch = new CountDownLatch(1); mFuseVolumeReadyLatches.put(volId, latch); } return latch; } } /** List of crypto types. * These must match CRYPT_TYPE_XXX in cryptfs.h AND their * corresponding commands in CommandListener.cpp */ Loading Loading @@ -612,7 +598,6 @@ class StorageManagerService extends IStorageManager.Stub private static final int H_ABORT_IDLE_MAINT = 12; private static final int H_BOOT_COMPLETED = 13; private static final int H_COMPLETE_UNLOCK_USER = 14; private static final int H_VOLUME_READY = 15; class StorageManagerServiceHandler extends Handler { public StorageManagerServiceHandler(Looper looper) { Loading Loading @@ -673,22 +658,6 @@ class StorageManagerService extends IStorageManager.Stub } break; } case H_VOLUME_READY: { final VolumeInfo vol = (VolumeInfo) msg.obj; try { mStorageSessionController.onVolumeReady(vol); synchronized (mLock) { CountDownLatch latch = mFuseVolumeReadyLatches.remove(vol.id); if (latch != null) { latch.countDown(); } } } catch (IllegalStateException | ExternalStorageServiceException e) { Slog.i(TAG, "Failed to initialise volume " + vol, e); } break; } case H_VOLUME_MOUNT: { final VolumeInfo vol = (VolumeInfo) msg.obj; if (isMountDisallowed(vol)) { Loading Loading @@ -1431,13 +1400,6 @@ class StorageManagerService extends IStorageManager.Stub writeSettingsLocked(); } if (mIsFuseEnabled && newState == VolumeInfo.STATE_MOUNTED && (vol.type == VolumeInfo.TYPE_PUBLIC || vol.type == VolumeInfo.TYPE_EMULATED)) { Slog.i(TAG, "Initialising volume " + vol + " ..."); // TODO(b/144275217): Delay broadcasts till mount is really ready mHandler.obtainMessage(H_VOLUME_READY, vol).sendToTarget(); } mCallbacks.notifyVolumeStateChanged(vol, oldState, newState); // Do not broadcast before boot has completed to avoid launching the Loading Loading @@ -1912,33 +1874,29 @@ class StorageManagerService extends IStorageManager.Stub throw new SecurityException("Mounting " + volId + " restricted by policy"); } CountDownLatch latch = null; if (mIsFuseEnabled && StorageSessionController.isEmulatedOrPublic(vol)) { latch = findOrCreateFuseVolumeReadyLatch(volId); } mount(vol); if (latch != null) { try { waitForLatch(latch, "mount " + volId, 3 * DateUtils.MINUTE_IN_MILLIS); } catch (TimeoutException e) { Slog.wtf(TAG, e); } finally { synchronized (mLock) { mFuseVolumeReadyLatches.remove(volId); } } } } private void mount(VolumeInfo vol) { try { // TODO(b/135341433): Remove paranoid logging when FUSE is stable Slog.i(TAG, "Mounting volume " + vol); FileDescriptor fd = mVold.mount(vol.id, vol.mountFlags, vol.mountUserId); mVold.mount(vol.id, vol.mountFlags, vol.mountUserId, new IVoldMountCallback.Stub() { @Override public boolean onVolumeChecking(FileDescriptor deviceFd, String path, String internalPath) { vol.path = path; vol.internalPath = internalPath; try { mStorageSessionController.onVolumeMount(deviceFd, vol); return true; } catch (ExternalStorageServiceException e) { Slog.i(TAG, "Failed to mount volume " + vol, e); return false; } } }); Slog.i(TAG, "Mounted volume " + vol); mStorageSessionController.onVolumeMount(fd, vol); } catch (Exception e) { Slog.wtf(TAG, e); } Loading Loading @@ -3643,7 +3601,7 @@ class StorageManagerService extends IStorageManager.Stub try { mObbState.volId = mVold.createObb(mObbState.canonicalPath, binderKey, mObbState.ownerGid); mVold.mount(mObbState.volId, 0, -1); mVold.mount(mObbState.volId, 0, -1, null); if (DEBUG_OBB) Slog.d(TAG, "Successfully mounted OBB " + mObbState.canonicalPath); Loading
services/core/java/com/android/server/storage/StorageSessionController.java +24 −82 Original line number Diff line number Diff line Loading @@ -69,15 +69,21 @@ public final class StorageSessionController { } /** * Creates a storage session associated with {@code deviceFd} for {@code vol}. Sessions can be * started with {@link #onVolumeReady} and removed with {@link #onVolumeUnmount} or * {@link #onVolumeRemove}. * Creates and starts a storage session associated with {@code deviceFd} for {@code vol}. * Sessions can be started with {@link #onVolumeReady} and removed with {@link #onVolumeUnmount} * or {@link #onVolumeRemove}. * * Throws an {@link IllegalStateException} if a session for {@code vol} has already been created * * Does nothing if {@link #shouldHandle} is {@code false} * * Blocks until the session is started or fails * * @throws ExternalStorageServiceException if the session fails to start * @throws IllegalStateException if a session has already been created for {@code vol} */ public void onVolumeMount(FileDescriptor deviceFd, VolumeInfo vol) { public void onVolumeMount(FileDescriptor deviceFd, VolumeInfo vol) throws ExternalStorageServiceException { if (!shouldHandle(vol)) { return; } Loading @@ -87,71 +93,22 @@ public final class StorageSessionController { String sessionId = vol.getId(); int userId = vol.getMountUserId(); if (deviceFd == null) { Slog.w(TAG, "Null fd. Session not started for vol: " + vol); return; } // Get realpath for the fd, paths that are not /dev/null need additional // setup by the ExternalStorageService before they can be ready String realPath; try { realPath = ParcelFileDescriptor.getFile(deviceFd).getPath(); } catch (IOException e) { Slog.wtf(TAG, "Could not get real path from fd: " + deviceFd, e); return; } if ("/dev/null".equals(realPath)) { Slog.i(TAG, "Volume ready for use with id: " + sessionId); return; } StorageUserConnection connection = null; synchronized (mLock) { StorageUserConnection connection = mConnections.get(userId); connection = mConnections.get(userId); if (connection == null) { Slog.i(TAG, "Creating connection for user: " + userId); connection = new StorageUserConnection(mContext, userId, this); mConnections.put(userId, connection); } Slog.i(TAG, "Creating session with id: " + sessionId); connection.createSession(sessionId, new ParcelFileDescriptor(deviceFd)); } connection.createSession(sessionId, new ParcelFileDescriptor(deviceFd), vol.getPath().getPath(), vol.getInternalPath().getPath()); } /** * Starts a storage session associated with {@code vol} after {@link #onVolumeMount}. * * Subsequent calls will attempt to start the storage session, but does nothing if already * started. If the user associated with {@code vol} is not yet ready, all pending sesssions * can be restarted with {@link onUnlockUser}. * * Does nothing if {@link #shouldHandle} is {@code false} * * Blocks until the session is started or fails * * @throws ExternalStorageServiceException if the session fails to start */ public void onVolumeReady(VolumeInfo vol) throws ExternalStorageServiceException { if (!shouldHandle(vol)) { return; } Slog.i(TAG, "On volume ready " + vol); String sessionId = vol.getId(); StorageUserConnection connection = null; synchronized (mLock) { connection = mConnections.get(vol.getMountUserId()); if (connection == null) { Slog.i(TAG, "Volume ready but no associated connection"); return; } } connection.initSession(sessionId, vol.getPath().getPath(), vol.getInternalPath().getPath()); if (isReady()) { // At boot, a volume can be mounted before user is unlocked, in that case, we create it // above and save it so that we can restart all sessions when the user is unlocked if (mExternalStorageServiceComponent != null) { connection.startSession(sessionId); } else { Slog.i(TAG, "Controller not initialised, session not started " + sessionId); Loading Loading @@ -205,15 +162,11 @@ public final class StorageSessionController { if (connection != null) { String sessionId = vol.getId(); if (isReady()) { try { connection.removeSessionAndWait(sessionId); } catch (ExternalStorageServiceException e) { Slog.e(TAG, "Failed to end session for vol with id: " + sessionId, e); } } else { Slog.i(TAG, "Controller not initialised, session not ended " + sessionId); } } } Loading @@ -232,7 +185,7 @@ public final class StorageSessionController { Slog.i(TAG, "On user unlock " + userId); if (userId == 0) { init(); initExternalStorageServiceComponent(); } StorageUserConnection connection = null; Loading @@ -259,13 +212,6 @@ public final class StorageSessionController { return; } if (!isReady()) { synchronized (mLock) { mConnections.clear(); } return; } SparseArray<StorageUserConnection> connections = new SparseArray(); synchronized (mLock) { mIsResetting = true; Loading Loading @@ -311,7 +257,7 @@ public final class StorageSessionController { } } private void init() throws ExternalStorageServiceException { private void initExternalStorageServiceComponent() throws ExternalStorageServiceException { Slog.i(TAG, "Initialialising..."); ProviderInfo provider = mContext.getPackageManager().resolveContentProvider( MediaStore.AUTHORITY, PackageManager.MATCH_DIRECT_BOOT_AWARE Loading Loading @@ -415,8 +361,4 @@ public final class StorageSessionController { private boolean shouldHandle(@Nullable VolumeInfo vol) { return mIsFuseEnabled && !mIsResetting && (vol == null || isEmulatedOrPublic(vol)); } private boolean isReady() { return mExternalStorageServiceComponent != null; } }
services/core/java/com/android/server/storage/StorageUserConnection.java +10 −36 Original line number Diff line number Diff line Loading @@ -75,46 +75,20 @@ public final class StorageUserConnection { /** * Creates and stores a storage {@link Session}. * * Created sessions must be initialised with {@link #initSession} before starting with * {@link #startSession}. * * They must also be cleaned up with {@link #removeSession}. * * @throws IllegalArgumentException if a {@code Session} with {@code sessionId} already exists */ public void createSession(String sessionId, ParcelFileDescriptor pfd) { public void createSession(String sessionId, ParcelFileDescriptor pfd, String upperPath, String lowerPath) { Preconditions.checkNotNull(sessionId); Preconditions.checkNotNull(pfd); Preconditions.checkNotNull(upperPath); Preconditions.checkNotNull(lowerPath); synchronized (mLock) { Preconditions.checkArgument(!mSessions.containsKey(sessionId)); mSessions.put(sessionId, new Session(sessionId, pfd)); } } /** * Initialise a storage {@link Session}. * * Initialised sessions can be started with {@link #startSession}. * * They must also be cleaned up with {@link #removeSession}. * * @throws IllegalArgumentException if {@code sessionId} does not exist or is initialised */ public void initSession(String sessionId, String upperPath, String lowerPath) { synchronized (mLock) { Session session = mSessions.get(sessionId); if (session == null) { throw new IllegalStateException("Failed to initialise non existent session. Id: " + sessionId + ". Upper path: " + upperPath + ". Lower path: " + lowerPath); } else if (session.isInitialisedLocked()) { throw new IllegalStateException("Already initialised session. Id: " + sessionId + ". Upper path: " + upperPath + ". Lower path: " + lowerPath); } else { session.upperPath = upperPath; session.lowerPath = lowerPath; Slog.i(TAG, "Initialised session: " + session); } mSessions.put(sessionId, new Session(sessionId, pfd, upperPath, lowerPath)); } } Loading Loading @@ -440,14 +414,14 @@ public final class StorageUserConnection { private static final class Session implements AutoCloseable { public final String sessionId; public final ParcelFileDescriptor pfd; @GuardedBy("mLock") public String lowerPath; @GuardedBy("mLock") public String upperPath; public final String lowerPath; public final String upperPath; Session(String sessionId, ParcelFileDescriptor pfd) { Session(String sessionId, ParcelFileDescriptor pfd, String upperPath, String lowerPath) { this.sessionId = sessionId; this.pfd = pfd; this.upperPath = upperPath; this.lowerPath = lowerPath; } @Override Loading