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

Commit b3562f43 authored by Martijn Coenen's avatar Martijn Coenen
Browse files

Fixup OBB directories correctly after package install.

The installer may pre-create OBB directories for packages that it is
installing on external storage, in locations like
/storage/emulated/0/data/obb/com.foo . The permissions on this directory
is never explicitly setup; instead, sdcardfs magically fixed up the
permissions to match the package name "com.foo".

With sdcardfs going away in devices launching with R, we need to set
the permissions for these paths up explicitly. Since only vold can do
that, have PackageManager call into StorageManager after an app
install/upgrade to do the correct setup.

Bug: 146419093
Test: manually verify directories are setup correctly
Change-Id: I530c8de196011b1dc97c7a9ab612e5d6dc9403a1
parent 46d77cf7
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package android.os.storage;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.IVold;

@@ -124,4 +125,14 @@ public abstract class StorageManagerInternal {
     * legacy storage, {@code false} otherwise.
     */
    public abstract boolean hasLegacyExternalStorage(int uid);

    /**
     * Makes sure app-private data directories on external storage are setup correctly
     * after an application is installed or upgraded. The main use for this is OBB dirs,
     * which can be created/modified by the installer.
     *
     * @param packageName the package name of the package
     * @param uid the uid of the package
     */
    public abstract void prepareAppDataAfterInstall(@NonNull String packageName, int uid);
}
+19 −0
Original line number Diff line number Diff line
@@ -4409,6 +4409,25 @@ class StorageManagerService extends IStorageManager.Stub
            }
        }

        @Override
        public void prepareAppDataAfterInstall(String packageName, int uid) {
            int userId = UserHandle.getUserId(uid);
            final Environment.UserEnvironment userEnv = new Environment.UserEnvironment(userId);

            // The installer may have downloaded OBBs for this newly installed application;
            // make sure the OBB dir for the application is setup correctly, if it exists.
            File[] packageObbDirs = userEnv.buildExternalStorageAppObbDirs(packageName);
            for (File packageObbDir : packageObbDirs) {
                try {
                    mVold.fixupAppDir(packageObbDir.getCanonicalPath() + "/", uid);
                } catch (IOException e) {
                    Log.e(TAG, "Failed to get canonical path for " + packageName);
                } catch (RemoteException e) {
                    Log.e(TAG, "Failed to fixup app dir for " + packageName);
                }
            }
        }

        public boolean hasExternalStorage(int uid, String packageName) {
            // No need to check for system uid. This avoids a deadlock between
            // PackageManagerService and AppOpsService.
+8 −0
Original line number Diff line number Diff line
@@ -21785,6 +21785,7 @@ public class PackageManagerService extends IPackageManager.Stub
        }
        UserManagerInternal umInternal = mInjector.getUserManagerInternal();
        StorageManagerInternal smInternal = mInjector.getStorageManagerInternal();
        for (UserInfo user : mUserManager.getUsers(false /*excludeDying*/)) {
            final int flags;
            if (umInternal.isUserUnlockingOrUnlocked(user.id)) {
@@ -21798,6 +21799,13 @@ public class PackageManagerService extends IPackageManager.Stub
            if (ps.getInstalled(user.id)) {
                // TODO: when user data is locked, mark that we're still dirty
                prepareAppDataLIF(pkg, user.id, flags);
                if (umInternal.isUserUnlockingOrUnlocked(user.id)) {
                    // Prepare app data on external storage; currently this is used to
                    // setup any OBB dirs that were created by the installer correctly.
                    int uid = UserHandle.getUid(user.id, UserHandle.getAppId(pkg.getUid()));
                    smInternal.prepareAppDataAfterInstall(pkg.getPackageName(), uid);
                }
            }
        }
    }