Add test for permission APEX.

Bug: 152055112
Test: atest PermissionApexTests
Change-Id: I4201501d586fe62df7a04d0e2da955d6d873d3df
diff --git a/apex/permission/TEST_MAPPING b/apex/permission/TEST_MAPPING
new file mode 100644
index 0000000..6e67ce9
--- /dev/null
+++ b/apex/permission/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "presubmit" : [
+    {
+      "name" : "PermissionApexTests"
+    }
+  ]
+}
diff --git a/apex/permission/tests/Android.bp b/apex/permission/tests/Android.bp
new file mode 100644
index 0000000..a1f7a54
--- /dev/null
+++ b/apex/permission/tests/Android.bp
@@ -0,0 +1,37 @@
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+android_test {
+    name: "PermissionApexTests",
+    sdk_version: "test_current",
+    srcs: [
+        "java/**/*.kt",
+    ],
+    static_libs: [
+        "service-permission",
+        "androidx.test.rules",
+        "androidx.test.ext.junit",
+        "androidx.test.ext.truth",
+        "mockito-target-extended-minus-junit4",
+    ],
+    jni_libs: [
+        "libdexmakerjvmtiagent",
+        "libstaticjvmtiagent",
+    ],
+    compile_multilib: "both",
+    test_suites: [
+        "general-tests",
+        "mts",
+    ],
+}
diff --git a/apex/permission/tests/AndroidManifest.xml b/apex/permission/tests/AndroidManifest.xml
new file mode 100644
index 0000000..57ee641
--- /dev/null
+++ b/apex/permission/tests/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  ~ Copyright (C) 2020 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.permission.test">
+
+    <!-- The application has to be debuggable for static mocking to work. -->
+    <application android:debuggable="true">
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation
+        android:name="androidx.test.runner.AndroidJUnitRunner"
+        android:targetPackage="com.android.permission.test"
+        android:label="Permission APEX Tests" />
+</manifest>
diff --git a/apex/permission/tests/java/com/android/permission/persistence/RuntimePermissionsPersistenceTest.kt b/apex/permission/tests/java/com/android/permission/persistence/RuntimePermissionsPersistenceTest.kt
new file mode 100644
index 0000000..2987da0
--- /dev/null
+++ b/apex/permission/tests/java/com/android/permission/persistence/RuntimePermissionsPersistenceTest.kt
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.permission.persistence
+
+import android.content.ApexEnvironment
+import android.content.Context
+import android.os.Process
+import android.os.UserHandle
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.platform.app.InstrumentationRegistry
+import com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession
+import com.google.common.truth.Truth.assertThat
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.any
+import org.mockito.ArgumentMatchers.eq
+import org.mockito.Mock
+import org.mockito.Mockito.`when`
+import org.mockito.MockitoAnnotations.initMocks
+import org.mockito.MockitoSession
+import org.mockito.quality.Strictness
+import java.io.File
+
+@RunWith(AndroidJUnit4::class)
+class RuntimePermissionsPersistenceTest {
+    private val context = InstrumentationRegistry.getInstrumentation().context
+
+    private lateinit var mockDataDirectory: File
+
+    private lateinit var mockitoSession: MockitoSession
+    @Mock
+    lateinit var apexEnvironment: ApexEnvironment
+
+    private val persistence = RuntimePermissionsPersistence.createInstance()
+    private val permissionState = RuntimePermissionsState.PermissionState("permission", true, 3)
+    private val state = RuntimePermissionsState(
+        1, "fingerprint", mapOf("package" to listOf(permissionState)),
+        mapOf("sharedUser" to listOf(permissionState))
+    )
+    private val user = Process.myUserHandle()
+
+    @Before
+    fun createMockDataDirectory() {
+        mockDataDirectory = context.getDir("mock_data", Context.MODE_PRIVATE)
+        mockDataDirectory.listFiles()!!.forEach { assertThat(it.deleteRecursively()).isTrue() }
+    }
+
+    @Before
+    fun mockApexEnvironment() {
+        initMocks(this)
+        mockitoSession = mockitoSession()
+            .mockStatic(ApexEnvironment::class.java)
+            .strictness(Strictness.LENIENT)
+            .startMocking()
+        `when`(ApexEnvironment.getApexEnvironment(eq(APEX_MODULE_NAME))).thenReturn(apexEnvironment)
+        `when`(apexEnvironment.getDeviceProtectedDataDirForUser(any(UserHandle::class.java))).then {
+            File(mockDataDirectory, it.arguments[0].toString()).also { it.mkdirs() }
+        }
+    }
+
+    @After
+    fun finishMockingApexEnvironment() {
+        mockitoSession.finishMocking()
+    }
+
+    @Test
+    fun testReadWrite() {
+        persistence.writeForUser(state, user)
+        val persistedState = persistence.readForUser(user)
+
+        assertThat(persistedState).isEqualTo(state)
+        assertThat(persistedState!!.version).isEqualTo(state.version)
+        assertThat(persistedState.fingerprint).isEqualTo(state.fingerprint)
+        assertThat(persistedState.packagePermissions).isEqualTo(state.packagePermissions)
+        val persistedPermissionState = persistedState.packagePermissions.values.first().first()
+        assertThat(persistedPermissionState.name).isEqualTo(permissionState.name)
+        assertThat(persistedPermissionState.isGranted).isEqualTo(permissionState.isGranted)
+        assertThat(persistedPermissionState.flags).isEqualTo(permissionState.flags)
+        assertThat(persistedState.sharedUserPermissions).isEqualTo(state.sharedUserPermissions)
+    }
+
+    @Test
+    fun testDelete() {
+        persistence.writeForUser(state, user)
+        persistence.deleteForUser(user)
+        val persistedState = persistence.readForUser(user)
+
+        assertThat(persistedState).isNull()
+    }
+
+    companion object {
+        private const val APEX_MODULE_NAME = "com.android.permission"
+    }
+}
diff --git a/apex/permission/tests/java/com/android/role/persistence/RolesPersistenceTest.kt b/apex/permission/tests/java/com/android/role/persistence/RolesPersistenceTest.kt
new file mode 100644
index 0000000..f9d9d5a
--- /dev/null
+++ b/apex/permission/tests/java/com/android/role/persistence/RolesPersistenceTest.kt
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.role.persistence
+
+import android.content.ApexEnvironment
+import android.content.Context
+import android.os.Process
+import android.os.UserHandle
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.platform.app.InstrumentationRegistry
+import com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession
+import com.google.common.truth.Truth.assertThat
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.any
+import org.mockito.ArgumentMatchers.eq
+import org.mockito.Mock
+import org.mockito.Mockito.`when`
+import org.mockito.MockitoAnnotations.initMocks
+import org.mockito.MockitoSession
+import org.mockito.quality.Strictness
+import java.io.File
+
+@RunWith(AndroidJUnit4::class)
+class RolesPersistenceTest {
+    private val context = InstrumentationRegistry.getInstrumentation().context
+
+    private lateinit var mockDataDirectory: File
+
+    private lateinit var mockitoSession: MockitoSession
+    @Mock
+    lateinit var apexEnvironment: ApexEnvironment
+
+    private val persistence = RolesPersistence.createInstance()
+    private val state = RolesState(1, "packagesHash", mapOf("role" to setOf("holder1", "holder2")))
+    private val user = Process.myUserHandle()
+
+    @Before
+    fun createMockDataDirectory() {
+        mockDataDirectory = context.getDir("mock_data", Context.MODE_PRIVATE)
+        mockDataDirectory.listFiles()!!.forEach { assertThat(it.deleteRecursively()).isTrue() }
+    }
+
+    @Before
+    fun mockApexEnvironment() {
+        initMocks(this)
+        mockitoSession = mockitoSession()
+            .mockStatic(ApexEnvironment::class.java)
+            .strictness(Strictness.LENIENT)
+            .startMocking()
+        `when`(ApexEnvironment.getApexEnvironment(eq(APEX_MODULE_NAME))).thenReturn(apexEnvironment)
+        `when`(apexEnvironment.getDeviceProtectedDataDirForUser(any(UserHandle::class.java))).then {
+            File(mockDataDirectory, it.arguments[0].toString()).also { it.mkdirs() }
+        }
+    }
+
+    @After
+    fun finishMockingApexEnvironment() {
+        mockitoSession.finishMocking()
+    }
+
+    @Test
+    fun testReadWrite() {
+        persistence.writeForUser(state, user)
+        val persistedState = persistence.readForUser(user)
+
+        assertThat(persistedState).isEqualTo(state)
+        assertThat(persistedState!!.version).isEqualTo(state.version)
+        assertThat(persistedState.packagesHash).isEqualTo(state.packagesHash)
+        assertThat(persistedState.roles).isEqualTo(state.roles)
+    }
+
+    @Test
+    fun testDelete() {
+        persistence.writeForUser(state, user)
+        persistence.deleteForUser(user)
+        val persistedState = persistence.readForUser(user)
+
+        assertThat(persistedState).isNull()
+    }
+
+    companion object {
+        private const val APEX_MODULE_NAME = "com.android.permission"
+    }
+}
diff --git a/api/test-current.txt b/api/test-current.txt
index a163dea..d681dc2 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -793,6 +793,13 @@
 
 package android.content {
 
+  public class ApexEnvironment {
+    method @NonNull public static android.content.ApexEnvironment getApexEnvironment(@NonNull String);
+    method @NonNull public java.io.File getCredentialProtectedDataDirForUser(@NonNull android.os.UserHandle);
+    method @NonNull public java.io.File getDeviceProtectedDataDir();
+    method @NonNull public java.io.File getDeviceProtectedDataDirForUser(@NonNull android.os.UserHandle);
+  }
+
   public final class AutofillOptions implements android.os.Parcelable {
     ctor public AutofillOptions(int, boolean);
     method public int describeContents();
diff --git a/core/java/android/content/ApexEnvironment.java b/core/java/android/content/ApexEnvironment.java
index b4cc3c2..9f15a42 100644
--- a/core/java/android/content/ApexEnvironment.java
+++ b/core/java/android/content/ApexEnvironment.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
+import android.annotation.TestApi;
 import android.os.Environment;
 import android.os.UserHandle;
 
@@ -30,6 +31,7 @@
  * @hide
  */
 @SystemApi
+@TestApi
 public class ApexEnvironment {
 
     private static final String APEX_DATA = "apexdata";