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

Commit 4005dd8a authored by Zimuzo Ezeozue's avatar Zimuzo Ezeozue
Browse files

resolve merge conflicts of 7df4e1c5

resolve merge conflicts of
"Add API to notify the system_server when app is blocked on I/O"
to master

Change-Id: Ie7a7be2a5b8557a2cdd3fbc1a6a37622b29535be
parents 0eb0175e 7df4e1c5
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -214,6 +214,16 @@ package android.os {

}

package android.os.storage {

  public class StorageManager {
    method public void notifyAppIoBlocked(@NonNull String, int, int, int);
    method public void notifyAppIoResumed(@NonNull String, int, int, int);
    field public static final int APP_IO_BLOCKED_REASON_TRANSCODING = 0; // 0x0
  }

}

package android.provider {

  public final class DeviceConfig {
+2 −0
Original line number Diff line number Diff line
@@ -199,4 +199,6 @@ interface IStorageManager {
    void fixupAppDir(in String path) = 89;
    void disableAppDataIsolation(in String pkgName, int pid, int userId) = 90;
    PendingIntent getManageSpaceActivityIntent(in String packageName, int requestCode) = 91;
    void notifyAppIoBlocked(in String volumeUuid, int uid, int tid, int reason) = 92;
    void notifyAppIoResumed(in String volumeUuid, int uid, int tid, int reason) = 93;
}
+74 −0
Original line number Diff line number Diff line
@@ -2727,6 +2727,80 @@ public class StorageManager {
        }
    }

    /**
     * Reason to provide if app IO is blocked/resumed because of transcoding
     *
     * @hide
     */
    @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
    public static final int APP_IO_BLOCKED_REASON_TRANSCODING = 0;

    /**
     * Constants for use with
     * {@link #notifyAppIoBlocked} and {@link notifyAppIoResumed}, to specify the reason an app's
     * IO is blocked/resumed.
     *
     * @hide
     */
    @Retention(RetentionPolicy.SOURCE)
    @IntDef(prefix = { "APP_IO_BLOCKED_REASON_" }, value = {
            APP_IO_BLOCKED_REASON_TRANSCODING
    })
    public @interface AppIoBlockedReason {}

    /**
     * Notify the system that an app with {@code uid} and {@code tid} is blocked on an IO request on
     * {@code volumeUuid} for {@code reason}.
     *
     * This blocked state can be used to modify the ANR behavior for the app while it's blocked.
     * For example during transcoding.
     *
     * This can only be called by the {@link ExternalStorageService} holding the
     * {@link android.Manifest.permission#WRITE_MEDIA_STORAGE} permission.
     *
     * @param volumeUuid the UUID of the storage volume that the app IO is blocked on
     * @param uid the UID of the app blocked on IO
     * @param tid the tid of the app blocked on IO
     * @param reason the reason the app is blocked on IO
     *
     * @hide
     */
    @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
    public void notifyAppIoBlocked(@NonNull String volumeUuid, int uid, int tid,
            @AppIoBlockedReason int reason) {
        try {
            mStorageManager.notifyAppIoBlocked(volumeUuid, uid, tid, reason);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Notify the system that an app with {@code uid} and {@code tid} has resmued a previously
     * blocked IO request on {@code volumeUuid} for {@code reason}.
     *
     * All app IO will be automatically marked as unblocked if {@code volumeUuid} is unmounted.
     *
     * This can only be called by the {@link ExternalStorageService} holding the
     * {@link android.Manifest.permission#WRITE_MEDIA_STORAGE} permission.
     *
     * @param volumeUuid the UUID of the storage volume that the app IO is resumed on
     * @param uid the UID of the app resuming IO
     * @param tid the tid of the app resuming IO
     * @param reason the reason the app is resuming IO
     *
     * @hide
     */
    @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
    public void notifyAppIoResumed(@NonNull String volumeUuid, int uid, int tid,
            @AppIoBlockedReason int reason) {
        try {
            mStorageManager.notifyAppIoResumed(volumeUuid, uid, tid, reason);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    private final Object mFuseAppLoopLock = new Object();

    @GuardedBy("mFuseAppLoopLock")
+33 −0
Original line number Diff line number Diff line
@@ -3391,6 +3391,39 @@ class StorageManagerService extends IStorageManager.Stub
        }
    }
    
    @Override
    public void notifyAppIoBlocked(String volumeUuid, int uid, int tid, int reason) {
        enforceExternalStorageService();

        mStorageSessionController.notifyAppIoBlocked(volumeUuid, uid, tid, reason);
    }

    @Override
    public void notifyAppIoResumed(String volumeUuid, int uid, int tid, int reason) {
        enforceExternalStorageService();

        mStorageSessionController.notifyAppIoResumed(volumeUuid, uid, tid, reason);
    }

    private boolean isAppIoBlocked(int uid) {
        return mStorageSessionController.isAppIoBlocked(uid);
    }

    /**
     * Enforces that the caller is the {@link ExternalStorageService}
     *
     * @throws SecurityException if the caller doesn't have the
     * {@link android.Manifest.permission.WRITE_MEDIA_STORAGE} permission or is not the
     * {@link ExternalStorageService}
     */
    private void enforceExternalStorageService() {
        enforcePermission(android.Manifest.permission.WRITE_MEDIA_STORAGE);
        int callingAppId = UserHandle.getAppId(Binder.getCallingUid());
        if (callingAppId != mMediaStoreAuthorityAppId) {
            throw new SecurityException("Only the ExternalStorageService is permitted");
        }
    }

    /** Not thread safe */
    class AppFuseMountScope extends AppFuseBridge.MountScope {
        private boolean mMounted = false;
+55 −0
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.os.ServiceSpecificException;
import android.os.UserHandle;
import android.os.storage.StorageManager;
import android.os.storage.StorageVolume;
import android.os.storage.VolumeInfo;
import android.provider.MediaStore;
@@ -371,6 +372,60 @@ public final class StorageSessionController {
        return mExternalStorageServiceComponent;
    }

    /**
     * Notify the controller that an app with {@code uid} and {@code tid} is blocked on an IO
     * request on {@code volumeUuid} for {@code reason}.
     *
     * This blocked state can be queried with {@link #isAppIoBlocked}
     *
     * @hide
     */
    public void notifyAppIoBlocked(String volumeUuid, int uid, int tid,
            @StorageManager.AppIoBlockedReason int reason) {
        final int userId = UserHandle.getUserId(uid);
        final StorageUserConnection connection;
        synchronized (mLock) {
            connection = mConnections.get(userId);
        }

        if (connection != null) {
            connection.notifyAppIoBlocked(volumeUuid, uid, tid, reason);
        }
    }

    /**
     * Notify the controller that an app with {@code uid} and {@code tid} has resmed a previously
     * blocked IO request on {@code volumeUuid} for {@code reason}.
     *
     * All app IO will be automatically marked as unblocked if {@code volumeUuid} is unmounted.
     */
    public void notifyAppIoResumed(String volumeUuid, int uid, int tid,
            @StorageManager.AppIoBlockedReason int reason) {
        final int userId = UserHandle.getUserId(uid);
        final StorageUserConnection connection;
        synchronized (mLock) {
            connection = mConnections.get(userId);
        }

        if (connection != null) {
            connection.notifyAppIoResumed(volumeUuid, uid, tid, reason);
        }
    }

    /** Returns {@code true} if {@code uid} is blocked on IO, {@code false} otherwise */
    public boolean isAppIoBlocked(int uid) {
        final int userId = UserHandle.getUserId(uid);
        final StorageUserConnection connection;
        synchronized (mLock) {
            connection = mConnections.get(userId);
        }

        if (connection != null) {
            return connection.isAppIoBlocked(uid);
        }
        return false;
    }

    private void killExternalStorageService(int userId) {
        IActivityManager am = ActivityManager.getService();
        try {
Loading