Create sdk sandbox data when starting instrumentation

If a client package of the sdk sandbox process we are instrumenting
doesn't depend on any SDKs (i.e. doesn't have <uses-sdk-library> tags),
then we won't create sdk sandbox data directories for the sdk sandbox
process.

This changes fixes it by manually calling reconcileSdkData during
notifyInstrumentationStarted

Bug: 209061624
Test: atest SdkSandboxManagerServiceUnitTests
Test: atest SdkSandboxInprocessTests
Change-Id: Iebeabb96dc218f7c0b67339d5ae31fdc61a3e76c
diff --git a/sdksandbox/SdkSandbox/tests_inprocess/src/com/android/sdksandbox/inprocess/SdkSandboxConfigurationTest.java b/sdksandbox/SdkSandbox/tests_inprocess/src/com/android/sdksandbox/inprocess/SdkSandboxConfigurationTest.java
index 636a8d6..7654aaf 100644
--- a/sdksandbox/SdkSandbox/tests_inprocess/src/com/android/sdksandbox/inprocess/SdkSandboxConfigurationTest.java
+++ b/sdksandbox/SdkSandbox/tests_inprocess/src/com/android/sdksandbox/inprocess/SdkSandboxConfigurationTest.java
@@ -16,6 +16,8 @@
 
 package com.android.sdksandbox.inprocess;
 
+import static android.content.Context.MODE_PRIVATE;
+
 import static com.google.common.truth.Truth.assertThat;
 import static com.google.common.truth.Truth.assertWithMessage;
 
@@ -31,7 +33,10 @@
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
 
+import java.io.BufferedReader;
 import java.io.File;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
 
 /**
  * Tests to check some basic properties of the Sdk Sandbox processes.
@@ -97,4 +102,41 @@
         assertThat(dir.getAbsolutePath()).isEqualTo(
                 "/data/misc_de/0/sdksandbox/" + TEST_PKG + "/shared");
     }
+
+    /**
+     * Tests that sdk sandbox process can write to it's CE storage.
+     */
+    @Test
+    public void testCanWriteToDataDir_CE() throws Exception {
+        final Context ctx = InstrumentationRegistry.getInstrumentation().getTargetContext();
+        try (OutputStreamWriter writer = new OutputStreamWriter(
+                ctx.openFileOutput("random_ce_file", MODE_PRIVATE))) {
+            writer.write("I am an sdk sandbox");
+        }
+        try (BufferedReader reader = new BufferedReader(
+                new InputStreamReader(ctx.openFileInput("random_ce_file")))) {
+            String line = reader.readLine();
+            assertThat(line).isEqualTo("I am an sdk sandbox");
+        }
+    }
+
+    /**
+     * Tests that sdk sandbox process can write to it's DE storage.
+     */
+    @Test
+    public void testCanWriteToDataDir_DE() throws Exception {
+        final Context ctx =
+                InstrumentationRegistry.getInstrumentation()
+                        .getTargetContext()
+                        .createDeviceProtectedStorageContext();
+        try (OutputStreamWriter writer = new OutputStreamWriter(
+                ctx.openFileOutput("random_de_file", MODE_PRIVATE))) {
+            writer.write("I am also an sdk sandbox");
+        }
+        try (BufferedReader reader = new BufferedReader(
+                new InputStreamReader(ctx.openFileInput("random_de_file")))) {
+            String line = reader.readLine();
+            assertThat(line).isEqualTo("I am also an sdk sandbox");
+        }
+    }
 }
diff --git a/sdksandbox/service/java/com/android/server/sdksandbox/SdkSandboxManagerService.java b/sdksandbox/service/java/com/android/server/sdksandbox/SdkSandboxManagerService.java
index 1682e27..0cb13eb 100644
--- a/sdksandbox/service/java/com/android/server/sdksandbox/SdkSandboxManagerService.java
+++ b/sdksandbox/service/java/com/android/server/sdksandbox/SdkSandboxManagerService.java
@@ -151,7 +151,8 @@
                 final int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
                 // TODO(b/223386213): We could miss broadcast or app might be started before we
                 // handle broadcast.
-                mHandler.post(() -> reconcileSdkData(packageName, uid));
+                mHandler.post(
+                        () -> reconcileSdkData(packageName, uid, /* forInstrumentation= */ false));
             }
         };
         mContext.registerReceiver(packageAddedIntentReceiver, packageAddedIntentFilter,
@@ -209,12 +210,21 @@
         return Base64.encodeToString(bytes, Base64.URL_SAFE | Base64.NO_WRAP);
     }
 
-    private void reconcileSdkData(String packageName, int uid) {
+    private void reconcileSdkData(String packageName, int uid, boolean forInstrumentation) {
         final List<SharedLibraryInfo> sdksUsed = getSdksUsed(packageName);
         if (sdksUsed.isEmpty()) {
-            return;
+            if (forInstrumentation) {
+                Log.w(TAG,
+                        "Running instrumentation for the sdk-sandbox process belonging to client "
+                                + "app "
+                                + packageName + " (uid = " + uid
+                                + "). However client app doesn't depend on any SDKs. Only "
+                                + "creating \"shared\" sdk sandbox data sub directory");
+            } else {
+                return;
+            }
         }
-        final List<String> subDirNames = new ArrayList();
+        final List<String> subDirNames = new ArrayList<>();
         subDirNames.add("shared");
         for (int i = 0; i < sdksUsed.size(); i++) {
             final SharedLibraryInfo sdk = sdksUsed.get(i);
@@ -689,6 +699,9 @@
             mActivityManager.killUid(sdkSandboxUid, "instrumentation started");
             mRunningInstrumentations.add(clientAppUid);
         }
+        // TODO(b/223386213): we need to check if there is reconcileSdkData task already enqueued
+        //  because the instrumented client app was just installed.
+        reconcileSdkData(clientAppPackageName, clientAppUid, /* forInstrumentation= */ true);
     }
 
     private void notifyInstrumentationFinished(