diff options
author | ThiƩbaud Weksteen <tweek@google.com> | 2023-03-14 04:28:25 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2023-03-14 04:28:25 +0000 |
commit | 0b79c1e4a8907f2538c16b828a760f67137430dd (patch) | |
tree | 7a31d86858be71b57f6985d1f8f6eca79405f46e | |
parent | ebe1328c7a6f3d6e4853023203b34f60a67c2599 (diff) | |
parent | cdac5de216d5ea78f1080ed1ea0854f4f17f3341 (diff) | |
download | base-temp_273316506_tm-qpr2.tar.gz |
Merge "Add end-to-end tests for @EnforcePermission" am: cdac5de216temp_273316506_tm-qpr2
Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/2486756
Change-Id: I838015c65392febe5044cfac37e3a5f133b7203f
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
11 files changed, 525 insertions, 0 deletions
diff --git a/tests/EnforcePermission/Android.bp b/tests/EnforcePermission/Android.bp new file mode 100644 index 000000000000..719a89817a9d --- /dev/null +++ b/tests/EnforcePermission/Android.bp @@ -0,0 +1,22 @@ +// Copyright (C) 2023 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 { + default_applicable_licenses: ["frameworks_base_license"], +} + +filegroup { + name: "frameworks-enforce-permission-test-aidl", + srcs: ["aidl/**/*.aidl"], +} diff --git a/tests/EnforcePermission/aidl/android/tests/enforcepermission/INested.aidl b/tests/EnforcePermission/aidl/android/tests/enforcepermission/INested.aidl new file mode 100644 index 000000000000..1eb773dc19b8 --- /dev/null +++ b/tests/EnforcePermission/aidl/android/tests/enforcepermission/INested.aidl @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2023 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 android.tests.enforcepermission; + +interface INested { + @EnforcePermission("ACCESS_NETWORK_STATE") + void ProtectedByAccessNetworkState(); + + @EnforcePermission("READ_SYNC_SETTINGS") + void ProtectedByReadSyncSettings(); +} diff --git a/tests/EnforcePermission/aidl/android/tests/enforcepermission/IProtected.aidl b/tests/EnforcePermission/aidl/android/tests/enforcepermission/IProtected.aidl new file mode 100644 index 000000000000..18e3aecfa832 --- /dev/null +++ b/tests/EnforcePermission/aidl/android/tests/enforcepermission/IProtected.aidl @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2023 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 android.tests.enforcepermission; + +interface IProtected { + @EnforcePermission("INTERNET") + void ProtectedByInternet(); + + @EnforcePermission("VIBRATE") + void ProtectedByVibrate(); + + @EnforcePermission("INTERNET") + void ProtectedByInternetAndVibrateImplicitly(); + + @EnforcePermission("INTERNET") + void ProtectedByInternetAndAccessNetworkStateImplicitly(); + + @EnforcePermission("INTERNET") + void ProtectedByInternetAndReadSyncSettingsImplicitly(); +} diff --git a/tests/EnforcePermission/service-app/Android.bp b/tests/EnforcePermission/service-app/Android.bp new file mode 100644 index 000000000000..226d9ba892e3 --- /dev/null +++ b/tests/EnforcePermission/service-app/Android.bp @@ -0,0 +1,23 @@ +// Copyright (C) 2023 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_helper_app { + name: "EnforcePermissionTestHelper", + srcs: [ + "src/**/*.java", + ":frameworks-enforce-permission-test-aidl", + ], + platform_apis: true, + certificate: "platform", +} diff --git a/tests/EnforcePermission/service-app/AndroidManifest.xml b/tests/EnforcePermission/service-app/AndroidManifest.xml new file mode 100644 index 000000000000..ddafe15ab88f --- /dev/null +++ b/tests/EnforcePermission/service-app/AndroidManifest.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2023 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="android.tests.enforcepermission.service"> + <application> + <service + android:name=".TestService" + android:exported="true" /> + + <service + android:name=".NestedTestService" + android:exported="true" /> + </application> +</manifest> diff --git a/tests/EnforcePermission/service-app/src/android/tests/enforcepermission/service/NestedTestService.java b/tests/EnforcePermission/service-app/src/android/tests/enforcepermission/service/NestedTestService.java new file mode 100644 index 000000000000..7879a1214c01 --- /dev/null +++ b/tests/EnforcePermission/service-app/src/android/tests/enforcepermission/service/NestedTestService.java @@ -0,0 +1,48 @@ +/** + * Copyright (C) 2023 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 android.tests.enforcepermission.service; + +import android.annotation.EnforcePermission; +import android.app.Service; +import android.content.Intent; +import android.os.IBinder; +import android.tests.enforcepermission.INested; +import android.util.Log; + +public class NestedTestService extends Service { + private static final String TAG = "EnforcePermission.NestedTestService"; + + @Override + public IBinder onBind(Intent intent) { + Log.i(TAG, "onBind"); + return mBinder; + } + + private final INested.Stub mBinder = new INested.Stub() { + @Override + @EnforcePermission(android.Manifest.permission.ACCESS_NETWORK_STATE) + public void ProtectedByAccessNetworkState() { + ProtectedByAccessNetworkState_enforcePermission(); + } + + @Override + @EnforcePermission(android.Manifest.permission.READ_SYNC_SETTINGS) + public void ProtectedByReadSyncSettings() { + ProtectedByReadSyncSettings_enforcePermission(); + } + }; +} diff --git a/tests/EnforcePermission/service-app/src/android/tests/enforcepermission/service/TestService.java b/tests/EnforcePermission/service-app/src/android/tests/enforcepermission/service/TestService.java new file mode 100644 index 000000000000..e9b897db1294 --- /dev/null +++ b/tests/EnforcePermission/service-app/src/android/tests/enforcepermission/service/TestService.java @@ -0,0 +1,119 @@ +/** + * Copyright (C) 2023 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 android.tests.enforcepermission.service; + +import android.annotation.EnforcePermission; +import android.app.Service; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.os.IBinder; +import android.os.RemoteException; +import android.tests.enforcepermission.INested; +import android.tests.enforcepermission.IProtected; +import android.util.Log; + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +public class TestService extends Service { + + private static final String TAG = "EnforcePermission.TestService"; + private volatile ServiceConnection mNestedServiceConnection; + + @Override + public void onCreate() { + mNestedServiceConnection = new ServiceConnection(); + Intent intent = new Intent(this, NestedTestService.class); + boolean bound = bindService(intent, mNestedServiceConnection, Context.BIND_AUTO_CREATE); + if (!bound) { + Log.wtf(TAG, "bindService() on NestedTestService failed"); + } + } + + @Override + public void onDestroy() { + unbindService(mNestedServiceConnection); + } + + private static final class ServiceConnection implements android.content.ServiceConnection { + private volatile CompletableFuture<INested> mFuture = new CompletableFuture<>(); + + public INested get() { + try { + return mFuture.get(1, TimeUnit.SECONDS); + } catch (ExecutionException | InterruptedException | TimeoutException e) { + throw new RuntimeException("Unable to reach NestedTestService: " + e.getMessage()); + } + } + + public void onServiceConnected(ComponentName className, IBinder service) { + mFuture.complete(INested.Stub.asInterface(service)); + } + + public void onServiceDisconnected(ComponentName className) { + mFuture = new CompletableFuture<>(); + } + }; + + + @Override + public IBinder onBind(Intent intent) { + return mBinder; + } + + private final IProtected.Stub mBinder = new IProtected.Stub() { + @Override + @EnforcePermission(android.Manifest.permission.INTERNET) + public void ProtectedByInternet() { + ProtectedByInternet_enforcePermission(); + } + + @Override + @EnforcePermission(android.Manifest.permission.VIBRATE) + public void ProtectedByVibrate() { + ProtectedByVibrate_enforcePermission(); + } + + @Override + @EnforcePermission(android.Manifest.permission.INTERNET) + public void ProtectedByInternetAndVibrateImplicitly() { + ProtectedByInternetAndVibrateImplicitly_enforcePermission(); + + ProtectedByVibrate(); + } + + @Override + @EnforcePermission(android.Manifest.permission.INTERNET) + public void ProtectedByInternetAndAccessNetworkStateImplicitly() throws RemoteException { + ProtectedByInternetAndAccessNetworkStateImplicitly_enforcePermission(); + + mNestedServiceConnection.get().ProtectedByAccessNetworkState(); + + } + + @Override + @EnforcePermission(android.Manifest.permission.INTERNET) + public void ProtectedByInternetAndReadSyncSettingsImplicitly() throws RemoteException { + ProtectedByInternetAndReadSyncSettingsImplicitly_enforcePermission(); + + mNestedServiceConnection.get().ProtectedByReadSyncSettings(); + } + }; +} diff --git a/tests/EnforcePermission/test-app/Android.bp b/tests/EnforcePermission/test-app/Android.bp new file mode 100644 index 000000000000..305ed8f0dadc --- /dev/null +++ b/tests/EnforcePermission/test-app/Android.bp @@ -0,0 +1,38 @@ +// Copyright (C) 2023 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 { + default_applicable_licenses: ["frameworks_base_license"], +} + +android_test { + name: "EnforcePermissionTests", + srcs: [ + "src/**/*.java", + ":frameworks-enforce-permission-test-aidl", + ], + static_libs: [ + "androidx.test.rules", + ], + libs: [ + "android.test.base", + "android.test.runner", + ], + data: [ + ":EnforcePermissionTestHelper", + ], + platform_apis: true, + certificate: "platform", + test_suites: ["general-tests"], +} diff --git a/tests/EnforcePermission/test-app/AndroidManifest.xml b/tests/EnforcePermission/test-app/AndroidManifest.xml new file mode 100644 index 000000000000..4a0c6a86628f --- /dev/null +++ b/tests/EnforcePermission/test-app/AndroidManifest.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2023 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="android.tests.enforcepermission.tests"> + + <!-- Expected for the tests (not actually used) --> + <uses-permission android:name="android.permission.INTERNET" /> + <uses-permission android:name="android.permission.READ_SYNC_SETTINGS" /> + + <queries> + <package android:name="android.tests.enforcepermission.service" /> + </queries> + + <application> + <uses-library android:name="android.test.runner" /> + </application> + <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner" + android:targetPackage="android.tests.enforcepermission.tests"/> +</manifest> diff --git a/tests/EnforcePermission/test-app/AndroidTest.xml b/tests/EnforcePermission/test-app/AndroidTest.xml new file mode 100644 index 000000000000..120381a7fb83 --- /dev/null +++ b/tests/EnforcePermission/test-app/AndroidTest.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2023 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. +--> +<configuration description="Runs EnforcePermission End-to-End Tests"> + <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup"> + <option name="test-file-name" value="EnforcePermissionTestHelper.apk"/> + <option name="test-file-name" value="EnforcePermissionTests.apk"/> + <option name="cleanup-apks" value="true" /> + </target_preparer> + + <option name="test-tag" value="EnforcePermissionTests"/> + <test class="com.android.tradefed.testtype.AndroidJUnitTest"> + <option name="package" value="android.tests.enforcepermission.tests"/> + <option name="runner" value="androidx.test.runner.AndroidJUnitRunner"/> + </test> +</configuration> diff --git a/tests/EnforcePermission/test-app/src/android/tests/enforcepermission/tests/ServiceTest.java b/tests/EnforcePermission/test-app/src/android/tests/enforcepermission/tests/ServiceTest.java new file mode 100644 index 000000000000..d2a4a037f125 --- /dev/null +++ b/tests/EnforcePermission/test-app/src/android/tests/enforcepermission/tests/ServiceTest.java @@ -0,0 +1,129 @@ +/** + * Copyright (C) 2023 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 android.tests.enforcepermission.tests; + +import static org.hamcrest.CoreMatchers.containsString; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertThrows; +import static org.junit.Assert.assertTrue; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.IBinder; +import android.os.RemoteException; +import android.tests.enforcepermission.IProtected; +import android.util.Log; + +import androidx.test.InstrumentationRegistry; +import androidx.test.runner.AndroidJUnit4; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +@RunWith(AndroidJUnit4.class) +public class ServiceTest { + + private static final String TAG = "EnforcePermission.Tests"; + private static final String SERVICE_NAME = "android.tests.enforcepermission.service"; + private static final int SERVICE_TIMEOUT_SEC = 5; + + private Context mContext; + private volatile ServiceConnection mServiceConnection; + + @Before + public void bindTestService() throws Exception { + Log.d(TAG, "bindTestService"); + mContext = InstrumentationRegistry.getTargetContext(); + mServiceConnection = new ServiceConnection(); + Intent intent = new Intent(); + intent.setClassName(SERVICE_NAME, SERVICE_NAME + ".TestService"); + assertTrue(mContext.bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE)); + } + + @After + public void unbindTestService() throws Exception { + mContext.unbindService(mServiceConnection); + } + + private static final class ServiceConnection implements android.content.ServiceConnection { + private volatile CompletableFuture<IProtected> mFuture = new CompletableFuture<>(); + + @Override + public void onServiceConnected(ComponentName className, IBinder service) { + mFuture.complete(IProtected.Stub.asInterface(service)); + } + + @Override + public void onServiceDisconnected(ComponentName className) { + mFuture = new CompletableFuture<>(); + } + + public IProtected get() { + try { + return mFuture.get(SERVICE_TIMEOUT_SEC, TimeUnit.SECONDS); + } catch (ExecutionException | InterruptedException | TimeoutException e) { + throw new RuntimeException("Unable to reach TestService: " + e.toString()); + } + } + } + + @Test + public void testImmediatePermissionGranted_succeeds() + throws RemoteException { + mServiceConnection.get().ProtectedByInternet(); + } + + @Test + public void testImmediatePermissionNotGranted_fails() + throws RemoteException { + final Exception ex = assertThrows(SecurityException.class, + () -> mServiceConnection.get().ProtectedByVibrate()); + assertThat(ex.getMessage(), containsString("VIBRATE")); + } + + @Test + public void testImmediatePermissionGrantedButImplicitLocalNotGranted_fails() + throws RemoteException { + final Exception ex = assertThrows(SecurityException.class, + () -> mServiceConnection.get().ProtectedByInternetAndVibrateImplicitly()); + assertThat(ex.getMessage(), containsString("VIBRATE")); + } + + @Test + public void testImmediatePermissionGrantedButImplicitNestedNotGranted_fails() + throws RemoteException { + final Exception ex = assertThrows(SecurityException.class, + () -> mServiceConnection.get() + .ProtectedByInternetAndAccessNetworkStateImplicitly()); + assertThat(ex.getMessage(), containsString("ACCESS_NETWORK_STATE")); + } + + @Test + public void testImmediatePermissionGrantedAndImplicitNestedGranted_succeeds() + throws RemoteException { + mServiceConnection.get().ProtectedByInternetAndReadSyncSettingsImplicitly(); + } +} |