Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d5b24870 authored by Abhijeet Kaur's avatar Abhijeet Kaur Committed by Android (Google) Code Review
Browse files

Merge "Delay volume state changed broadcasts until the Storage Service processes it" into rvc-dev

parents 5d9a21a5 29dc0896
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -10183,6 +10183,7 @@ package android.service.storage {
    method @NonNull public final android.os.IBinder onBind(@NonNull android.content.Intent);
    method public abstract void onEndSession(@NonNull String) throws java.io.IOException;
    method public abstract void onStartSession(@NonNull String, int, @NonNull android.os.ParcelFileDescriptor, @NonNull java.io.File, @NonNull java.io.File) throws java.io.IOException;
    method public abstract void onVolumeStateChanged(@NonNull android.os.storage.StorageVolume) throws java.io.IOException;
    field public static final int FLAG_SESSION_ATTRIBUTE_INDEXABLE = 2; // 0x2
    field public static final int FLAG_SESSION_TYPE_FUSE = 1; // 0x1
    field public static final String SERVICE_INTERFACE = "android.service.storage.ExternalStorageService";
+31 −2
Original line number Diff line number Diff line
@@ -25,11 +25,13 @@ import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.ParcelFileDescriptor;
import android.os.ParcelableException;
import android.os.RemoteCallback;
import android.os.RemoteException;
import android.os.storage.StorageVolume;

import com.android.internal.os.BackgroundThread;

import java.io.File;
import java.io.IOException;
@@ -97,7 +99,7 @@ public abstract class ExternalStorageService extends Service {
    public @interface SessionFlag {}

    private final ExternalStorageServiceWrapper mWrapper = new ExternalStorageServiceWrapper();
    private final Handler mHandler = new Handler(Looper.getMainLooper(), null, true);
    private final Handler mHandler = BackgroundThread.getHandler();

    /**
     * Called when the system starts a session associated with {@code deviceFd}
@@ -131,6 +133,20 @@ public abstract class ExternalStorageService extends Service {
     */
    public abstract void onEndSession(@NonNull String sessionId) throws IOException;

    /**
     * Called when any volume's state changes.
     *
     * <p> This is required to communicate volume state changes with the Storage Service before
     * broadcasting to other apps. The Storage Service needs to process any change in the volume
     * state (before other apps receive a broadcast for the same) to update the database so that
     * other apps have the correct view of the volume.
     *
     * <p> Blocks until the Storage Service processes/scans the volume or fails in doing so.
     *
     * @param vol name of the volume that was changed
     */
    public abstract void onVolumeStateChanged(@NonNull StorageVolume vol) throws IOException;

    @Override
    @NonNull
    public final IBinder onBind(@NonNull Intent intent) {
@@ -153,6 +169,19 @@ public abstract class ExternalStorageService extends Service {
            });
        }

        @Override
        public void notifyVolumeStateChanged(String sessionId, StorageVolume vol,
                RemoteCallback callback) {
            mHandler.post(() -> {
                try {
                    onVolumeStateChanged(vol);
                    sendResult(sessionId, null /* throwable */, callback);
                } catch (Throwable t) {
                    sendResult(sessionId, t, callback);
                }
            });
        }

        @Override
        public void endSession(String sessionId, RemoteCallback callback) throws RemoteException {
            mHandler.post(() -> {
+3 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package android.service.storage;

import android.os.ParcelFileDescriptor;
import android.os.RemoteCallback;
import android.os.storage.StorageVolume;

/**
 * @hide
@@ -27,4 +28,6 @@ oneway interface IExternalStorageService
    void startSession(@utf8InCpp String sessionId, int type, in ParcelFileDescriptor deviceFd,
         @utf8InCpp String upperPath, @utf8InCpp String lowerPath, in RemoteCallback callback);
    void endSession(@utf8InCpp String sessionId, in RemoteCallback callback);
    void notifyVolumeStateChanged(@utf8InCpp String sessionId, in StorageVolume vol,
        in RemoteCallback callback);
}
 No newline at end of file
+84 −63
Original line number Diff line number Diff line
@@ -682,6 +682,7 @@ 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_STATE_CHANGED = 15;

    class StorageManagerServiceHandler extends Handler {
        public StorageManagerServiceHandler(Looper looper) {
@@ -805,6 +806,11 @@ class StorageManagerService extends IStorageManager.Stub
                    completeUnlockUser((int) msg.obj);
                    break;
                }
                case H_VOLUME_STATE_CHANGED: {
                    final SomeArgs args = (SomeArgs) msg.obj;
                    onVolumeStateChangedInternal((VolumeInfo) args.arg1, (int) args.arg2,
                            (int) args.arg3);
                }
            }
        }
    }
@@ -1323,7 +1329,11 @@ class StorageManagerService extends IStorageManager.Stub
                    final int oldState = vol.state;
                    final int newState = state;
                    vol.state = newState;
                    onVolumeStateChangedLocked(vol, oldState, newState);
                    final SomeArgs args = SomeArgs.obtain();
                    args.arg1 = vol;
                    args.arg2 = oldState;
                    args.arg3 = newState;
                    mHandler.obtainMessage(H_VOLUME_STATE_CHANGED, args).sendToTarget();
                }
            }
        }
@@ -1496,8 +1506,8 @@ class StorageManagerService extends IStorageManager.Stub
        return true;
    }

    @GuardedBy("mLock")
    private void onVolumeStateChangedLocked(VolumeInfo vol, int oldState, int newState) {
    private void onVolumeStateChangedInternal(VolumeInfo vol, int oldState, int newState) {
        synchronized (mLock) {
            if (vol.type == VolumeInfo.TYPE_EMULATED && newState != VolumeInfo.STATE_MOUNTED) {
                mFuseMountedUser.remove(vol.getMountUserId());
            }
@@ -1523,7 +1533,16 @@ class StorageManagerService extends IStorageManager.Stub
                rec.lastSeenMillis = System.currentTimeMillis();
                writeSettingsLocked();
            }

        }
        // This is a blocking call to Storage Service which needs to process volume state changed
        // before notifying other listeners.
        // Intentionally called without the mLock to avoid deadlocking from the Storage Service.
        try {
            mStorageSessionController.notifyVolumeStateChanged(vol);
        } catch (ExternalStorageServiceException e) {
            Log.e(TAG, "Failed to notify volume state changed to the Storage Service", e);
        }
        synchronized (mLock) {
            mCallbacks.notifyVolumeStateChanged(vol, oldState, newState);

            // Do not broadcast before boot has completed to avoid launching the
@@ -1547,7 +1566,8 @@ class StorageManagerService extends IStorageManager.Stub
                // user-specific broadcasts.
                for (int userId : mSystemUnlockedUsers) {
                    if (vol.isVisibleForRead(userId)) {
                    final StorageVolume userVol = vol.buildStorageVolume(mContext, userId, false);
                        final StorageVolume userVol = vol.buildStorageVolume(mContext, userId,
                                false);
                        mHandler.obtainMessage(H_VOLUME_BROADCAST, userVol).sendToTarget();

                        mCallbacks.notifyStorageStateChanged(userVol.getPath(), oldStateEnv,
@@ -1569,6 +1589,7 @@ class StorageManagerService extends IStorageManager.Stub
            }
            maybeLogMediaMount(vol, newState);
        }
    }

    private void maybeLogMediaMount(VolumeInfo vol, int newState) {
        if (!SecurityLog.isLoggingEnabled()) {
+32 −0
Original line number Diff line number Diff line
@@ -105,6 +105,38 @@ public final class StorageSessionController {
        }
    }

    /**
     * Notifies the Storage Service that volume state for {@code vol} is changed.
     * A session may already be created for this volume if it is mounted before or the volume state
     * has changed to mounted.
     *
     * Does nothing if {@link #shouldHandle} is {@code false}
     *
     * Blocks until the Storage Service processes/scans the volume or fails in doing so.
     *
     * @throws ExternalStorageServiceException if it fails to connect to ExternalStorageService
     */
    public void notifyVolumeStateChanged(VolumeInfo vol) throws ExternalStorageServiceException {
        if (!shouldHandle(vol)) {
            return;
        }
        String sessionId = vol.getId();
        int userId = vol.getMountUserId();

        StorageUserConnection connection = null;
        synchronized (mLock) {
            connection = mConnections.get(userId);
            if (connection != null) {
                Slog.i(TAG, "Notifying volume state changed for session with id: " + sessionId);
                connection.notifyVolumeStateChanged(sessionId,
                        vol.buildStorageVolume(mContext, userId, false));
            } else {
                Slog.w(TAG, "No available storage user connection for userId : " + userId);
            }
        }
    }


    /**
     * Removes and returns the {@link StorageUserConnection} for {@code vol}.
     *
Loading