make adb install --incremental work

With a simple Java apk (flipboard.app).

BUG: 133435829
Test: manual
Change-Id: If702afffc0e01cbb03f88560c0569fd23dda2350
diff --git a/core/java/android/os/incremental/IncrementalFileStorages.java b/core/java/android/os/incremental/IncrementalFileStorages.java
index a0bfc1b..4a66879 100644
--- a/core/java/android/os/incremental/IncrementalFileStorages.java
+++ b/core/java/android/os/incremental/IncrementalFileStorages.java
@@ -31,17 +31,10 @@
  * @throws IllegalStateException the session is not an Incremental installation session.
  */
 
-import static dalvik.system.VMRuntime.getInstructionSet;
-
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.pm.DataLoaderParams;
 import android.content.pm.InstallationFile;
-import android.os.IVold;
-import android.os.Process;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.util.ArraySet;
 import android.util.Slog;
 
 import java.io.File;
@@ -58,26 +51,14 @@
 public final class IncrementalFileStorages {
     private static final String TAG = "IncrementalFileStorages";
     private @Nullable IncrementalStorage mDefaultStorage;
-    private @Nullable IncrementalStorage mApkStorage;
-    private @Nullable IncrementalStorage mObbStorage;
     private @Nullable String mDefaultDir;
-    private @Nullable String mObbDir;
     private @NonNull IncrementalManager mIncrementalManager;
-    private @Nullable ArraySet<String> mLibDirs;
-    private @NonNull String mPackageName;
     private @NonNull File mStageDir;
 
     /**
-     * Set up files and directories used in an installation session.
-     * Currently only used by Incremental Installation.
-     * For Incremental installation, the expected outcome of this function is:
-     * 0) All the files are in defaultStorage
-     * 1) All APK files are in the same directory, bound to mApkStorage, and bound to the
-     * InstallerSession's stage dir. The files are linked from mApkStorage to defaultStorage.
-     * 2) All lib files are in the sub directories as their names suggest, and in the same parent
-     * directory as the APK files. The files are linked from mApkStorage to defaultStorage.
-     * 3) OBB files are in another directory that is different from APK files and lib files, bound
-     * to mObbStorage. The files are linked from mObbStorage to defaultStorage.
+     * Set up files and directories used in an installation session. Only used by Incremental.
+     * All the files will be created in defaultStorage.
+     * TODO(b/133435829): code clean up
      *
      * @throws IllegalStateException the session is not an Incremental installation session.
      */
@@ -85,7 +66,6 @@
             @NonNull File stageDir,
             @NonNull IncrementalManager incrementalManager,
             @NonNull DataLoaderParams dataLoaderParams) {
-        mPackageName = packageName;
         mStageDir = stageDir;
         mIncrementalManager = incrementalManager;
         if (dataLoaderParams.getComponentName().getPackageName().equals("local")) {
@@ -114,83 +94,23 @@
         }
         if (file.getFileType() == InstallationFile.FILE_TYPE_APK) {
             addApkFile(file);
-        } else if (file.getFileType() == InstallationFile.FILE_TYPE_OBB) {
-            addObbFile(file);
-        } else if (file.getFileType() == InstallationFile.FILE_TYPE_LIB) {
-            addLibFile(file);
         } else {
             throw new IOException("Unknown file type: " + file.getFileType());
         }
     }
 
     private void addApkFile(@NonNull InstallationFile apk) throws IOException {
-        // Create a storage for APK files and lib files
         final String stageDirPath = mStageDir.getAbsolutePath();
-        if (mApkStorage == null) {
-            mApkStorage = mIncrementalManager.createStorage(stageDirPath, mDefaultStorage,
-                    IncrementalManager.CREATE_MODE_CREATE
-                            | IncrementalManager.CREATE_MODE_TEMPORARY_BIND);
-            mApkStorage.bind(stageDirPath);
-        }
-
-        if (!new File(mDefaultDir, apk.getName()).exists()) {
-            mDefaultStorage.makeFile(apk.getName(), apk.getSize(), null,
+        mDefaultStorage.bind(stageDirPath);
+        String apkName = apk.getName();
+        File targetFile = Paths.get(stageDirPath, apkName).toFile();
+        if (!targetFile.exists()) {
+            mDefaultStorage.makeFile(apkName, apk.getSize(), null,
                     apk.getMetadata(), 0, null, null, null);
         }
-        // Assuming APK files are already named properly, e.g., "base.apk"
-        mDefaultStorage.makeLink(apk.getName(), mApkStorage, apk.getName());
-    }
-
-    private void addLibFile(@NonNull InstallationFile lib) throws IOException {
-        // TODO(b/136132412): remove this after we have incfs support for lib file mapping
-        if (mApkStorage == null) {
-            throw new IOException("Cannot add lib file without adding an apk file first");
+        if (targetFile.exists()) {
+            Slog.i(TAG, "!!! created: " + targetFile.getAbsolutePath());
         }
-        if (mLibDirs == null) {
-            mLibDirs = new ArraySet<>();
-        }
-        String current = "";
-        final Path libDirPath = Paths.get(lib.getName()).getParent();
-        final int numDirComponents = libDirPath.getNameCount();
-        for (int i = 0; i < numDirComponents; i++) {
-            String dirName = libDirPath.getName(i).toString();
-            try {
-                dirName = getInstructionSet(dirName);
-            } catch (IllegalArgumentException ignored) {
-            }
-            current += dirName;
-            if (!mLibDirs.contains(current)) {
-                mDefaultStorage.makeDirectory(current);
-                mApkStorage.makeDirectory(current);
-                mLibDirs.add(current);
-            }
-            current += '/';
-        }
-        String libFilePath = current + Paths.get(lib.getName()).getFileName();
-        mDefaultStorage.makeFile(libFilePath, lib.getSize(), null, lib.getMetadata(), 0, null, null,
-                                 null);
-        mDefaultStorage.makeLink(libFilePath, mApkStorage, libFilePath);
-    }
-
-    private void addObbFile(@NonNull InstallationFile obb) throws IOException {
-        if (mObbStorage == null) {
-            // Create a storage for OBB files
-            mObbDir = getTempDir();
-            if (mObbDir == null) {
-                throw new IOException("Failed to create obb storage directory.");
-            }
-            mObbStorage = mIncrementalManager.createStorage(
-                    mObbDir, mDefaultStorage,
-                    IncrementalManager.CREATE_MODE_CREATE
-                            | IncrementalManager.CREATE_MODE_TEMPORARY_BIND);
-        }
-        mDefaultStorage.makeFile(obb.getName(), obb.getSize(), null, obb.getMetadata(), 0, null,
-                                 null, null);
-        mDefaultStorage.makeLink(obb.getName(), mObbStorage, obb.getName());
-    }
-
-    private boolean hasObb() {
-        return (mObbStorage != null && mObbDir != null);
     }
 
     /**
@@ -208,35 +128,6 @@
      * Sets up obb storage directory and create bindings.
      */
     public void finishSetUp() {
-        if (!hasObb()) {
-            return;
-        }
-        final String obbDir = "/storage/emulated/0/Android/obb";
-        final String packageObbDir = String.format("%s/%s", obbDir, mPackageName);
-        final String packageObbDirRoot =
-                String.format("/mnt/runtime/%s/emulated/0/Android/obb/", mPackageName);
-        final String[] obbDirs = {
-                packageObbDirRoot + "read",
-                packageObbDirRoot + "write",
-                packageObbDirRoot + "full",
-                packageObbDirRoot + "default",
-                String.format("/data/media/0/Android/obb/%s", mPackageName),
-                packageObbDir,
-        };
-        try {
-            Slog.i(TAG, "Creating obb directory '" + packageObbDir + "'");
-            final IVold vold = IVold.Stub.asInterface(ServiceManager.getServiceOrThrow("vold"));
-            vold.setupAppDir(packageObbDir, obbDir, Process.ROOT_UID);
-            for (String d : obbDirs) {
-                mObbStorage.bindPermanent(d);
-            }
-        } catch (ServiceManager.ServiceNotFoundException ex) {
-            Slog.e(TAG, "vold service is not found.");
-            cleanUp();
-        } catch (IOException | RemoteException ex) {
-            Slog.e(TAG, "Failed to create obb dir at: " + packageObbDir, ex);
-            cleanUp();
-        }
     }
 
     /**
@@ -247,26 +138,12 @@
         if (mDefaultStorage != null && mDefaultDir != null) {
             try {
                 mDefaultStorage.unBind(mDefaultDir);
+                mDefaultStorage.unBind(mStageDir.getAbsolutePath());
             } catch (IOException ignored) {
             }
             mDefaultDir = null;
             mDefaultStorage = null;
         }
-        if (mApkStorage != null && mStageDir != null) {
-            try {
-                mApkStorage.unBind(mStageDir.getAbsolutePath());
-            } catch (IOException ignored) {
-            }
-            mApkStorage = null;
-        }
-        if (mObbStorage != null && mObbDir != null) {
-            try {
-                mObbStorage.unBind(mObbDir);
-            } catch (IOException ignored) {
-            }
-            mObbDir = null;
-            mObbStorage = null;
-        }
     }
 
     private String getTempDir() {
diff --git a/core/java/android/os/incremental/IncrementalStorage.java b/core/java/android/os/incremental/IncrementalStorage.java
index 91dda08..e5d1b43 100644
--- a/core/java/android/os/incremental/IncrementalStorage.java
+++ b/core/java/android/os/incremental/IncrementalStorage.java
@@ -174,9 +174,12 @@
             @Nullable byte[] metadata, int hashAlgorithm, @Nullable byte[] rootHash,
             @Nullable byte[] additionalData, @Nullable byte[] signature) throws IOException {
         try {
+            if (id == null && metadata == null) {
+                throw new IOException("File ID and metadata cannot both be null");
+            }
             final IncrementalNewFileParams params = new IncrementalNewFileParams();
             params.size = size;
-            params.metadata = metadata;
+            params.metadata = (metadata == null ? new byte[0] : metadata);
             params.fileId = idToBytes(id);
             if (hashAlgorithm != 0 || signature != null) {
                 params.signature = new IncrementalSignature();
@@ -354,9 +357,10 @@
      * @param id The id to convert
      * @return Byte array that contains the same ID.
      */
-    public static byte[] idToBytes(UUID id) {
+    @NonNull
+    public static byte[] idToBytes(@Nullable UUID id) {
         if (id == null) {
-            return null;
+            return new byte[0];
         }
         final ByteBuffer buf = ByteBuffer.wrap(new byte[UUID_BYTE_SIZE]);
         buf.putLong(id.getMostSignificantBits());
@@ -370,7 +374,8 @@
      * @param bytes The id in byte array format, 16 bytes long
      * @return UUID constructed from the byte array.
      */
-    public static UUID bytesToId(byte[] bytes) {
+    @NonNull
+    public static UUID bytesToId(byte[] bytes) throws IllegalArgumentException {
         if (bytes.length != UUID_BYTE_SIZE) {
             throw new IllegalArgumentException("Expected array of size " + UUID_BYTE_SIZE
                                                + ", got " + bytes.length);
diff --git a/services/incremental/BinderIncrementalService.cpp b/services/incremental/BinderIncrementalService.cpp
index f1b637f..91d0572 100644
--- a/services/incremental/BinderIncrementalService.cpp
+++ b/services/incremental/BinderIncrementalService.cpp
@@ -111,10 +111,9 @@
 binder::Status BinderIncrementalService::createStorage(const std::string& path,
                                                        const DataLoaderParamsParcel& params,
                                                        int32_t createMode, int32_t* _aidl_return) {
-    *_aidl_return =
-            mImpl.createStorage(path, const_cast<DataLoaderParamsParcel&&>(params),
-                                android::incremental::IncrementalService::CreateOptions(
-                                        createMode));
+    *_aidl_return = mImpl.createStorage(path, const_cast<DataLoaderParamsParcel&&>(params),
+                                        android::incremental::IncrementalService::CreateOptions(
+                                                createMode));
     return ok();
 }
 
@@ -195,7 +194,7 @@
         return ok();
     }
 
-    *_aidl_return = mImpl.makeFile(storageId, path, 0555, fileId, nfp);
+    *_aidl_return = mImpl.makeFile(storageId, path, 0777, fileId, nfp);
     return ok();
 }
 binder::Status BinderIncrementalService::makeFileFromRange(int32_t storageId,
diff --git a/services/incremental/IncrementalService.cpp b/services/incremental/IncrementalService.cpp
index 414c66c..e4a37dde 100644
--- a/services/incremental/IncrementalService.cpp
+++ b/services/incremental/IncrementalService.cpp
@@ -30,7 +30,6 @@
 #include <binder/BinderService.h>
 #include <binder/ParcelFileDescriptor.h>
 #include <binder/Status.h>
-
 #include <openssl/sha.h>
 #include <sys/stat.h>
 #include <uuid/uuid.h>
@@ -612,13 +611,18 @@
     if (!ifs) {
         return -EINVAL;
     }
-    auto normSource = path::normalize(source);
 
     std::unique_lock l(ifs->lock);
     const auto storageInfo = ifs->storages.find(storage);
     if (storageInfo == ifs->storages.end()) {
         return -EINVAL;
     }
+    std::string normSource;
+    if (path::isAbsolute(source)) {
+        normSource = path::normalize(source);
+    } else {
+        normSource = path::normalize(path::join(storageInfo->second.name, source));
+    }
     if (!path::startsWith(normSource, storageInfo->second.name)) {
         return -EINVAL;
     }
@@ -673,7 +677,20 @@
 int IncrementalService::makeFile(StorageId storage, std::string_view path, int mode, FileId id,
                                  incfs::NewFileParams params) {
     if (auto ifs = getIfs(storage)) {
-        auto err = mIncFs->makeFile(ifs->control, path, mode, id, params);
+        const auto storageInfo = ifs->storages.find(storage);
+        if (storageInfo == ifs->storages.end()) {
+            return -EINVAL;
+        }
+        std::string normPath;
+        if (path::isAbsolute(path)) {
+            normPath = path::normalize(path);
+        } else {
+            normPath = path::normalize(path::join(storageInfo->second.name, path));
+        }
+        if (!path::startsWith(normPath, storageInfo->second.name)) {
+            return -EINVAL;
+        }
+        auto err = mIncFs->makeFile(ifs->control, normPath, mode, id, params);
         if (err) {
             return err;
         }