diff options
author | 2019-05-14 18:51:32 +0100 | |
---|---|---|
committer | 2019-05-19 19:39:29 +0100 | |
commit | 0d70a6ac49aaecfd94ccfe84cf735243acc0f1a1 (patch) | |
tree | 6d8f44a4c02569854829785b2866fa012840b98f | |
parent | 0ab517141f1828ec14a5b0071bdea0a60b873f71 (diff) |
Add ExplicitHealthCheckServiceImplTest
Test: atest
android.ext.services.watchdog.ExplicitHealthCheckServiceImplTest
Bug: 132640467
Change-Id: I2d1820a38adce238a157e925512898c184dadec0
4 files changed, 208 insertions, 2 deletions
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml index b96c59ab83a7..0ebaa40e4cd5 100644 --- a/data/etc/privapp-permissions-platform.xml +++ b/data/etc/privapp-permissions-platform.xml @@ -313,6 +313,8 @@ applications that come with the platform <permission name="android.permission.SET_WALLPAPER" /> <permission name="android.permission.SET_WALLPAPER_COMPONENT" /> <permission name="android.permission.REQUEST_NOTIFICATION_ASSISTANT_SERVICE" /> + <!-- Permission required to test ExplicitHealthCheckServiceImpl. --> + <permission name="android.permission.BIND_EXPLICIT_HEALTH_CHECK_SERVICE"/> </privapp-permissions> <privapp-permissions package="com.android.statementservice"> diff --git a/packages/ExtServices/src/android/ext/services/watchdog/ExplicitHealthCheckServiceImpl.java b/packages/ExtServices/src/android/ext/services/watchdog/ExplicitHealthCheckServiceImpl.java index 765e9f95216d..670b419a8aa3 100644 --- a/packages/ExtServices/src/android/ext/services/watchdog/ExplicitHealthCheckServiceImpl.java +++ b/packages/ExtServices/src/android/ext/services/watchdog/ExplicitHealthCheckServiceImpl.java @@ -39,9 +39,9 @@ public final class ExplicitHealthCheckServiceImpl extends ExplicitHealthCheckSer // TODO: Add build dependency on NetworkStack stable AIDL so we can stop hard coding class name private static final String NETWORK_STACK_CONNECTOR_CLASS = "android.net.INetworkStackConnector"; - private static final String PROPERTY_WATCHDOG_REQUEST_TIMEOUT_MILLIS = + public static final String PROPERTY_WATCHDOG_REQUEST_TIMEOUT_MILLIS = "watchdog_request_timeout_millis"; - private static final long DEFAULT_REQUEST_TIMEOUT_MILLIS = + public static final long DEFAULT_REQUEST_TIMEOUT_MILLIS = TimeUnit.HOURS.toMillis(1); // Modified only #onCreate, using concurrent collection to ensure thread visibility private final Map<String, ExplicitHealthChecker> mSupportedCheckers = new ConcurrentHashMap<>(); diff --git a/packages/ExtServices/tests/src/android/ext/services/watchdog/ExplicitHealthCheckServiceImplTest.java b/packages/ExtServices/tests/src/android/ext/services/watchdog/ExplicitHealthCheckServiceImplTest.java new file mode 100644 index 000000000000..a9cb63e2a200 --- /dev/null +++ b/packages/ExtServices/tests/src/android/ext/services/watchdog/ExplicitHealthCheckServiceImplTest.java @@ -0,0 +1,201 @@ +/* + * Copyright (C) 2019 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.ext.services.watchdog; + +import static android.service.watchdog.ExplicitHealthCheckService.EXTRA_REQUESTED_PACKAGES; +import static android.service.watchdog.ExplicitHealthCheckService.EXTRA_SUPPORTED_PACKAGES; +import static android.service.watchdog.ExplicitHealthCheckService.PackageConfig; + +import static com.google.common.truth.Truth.assertThat; + +import static org.junit.Assert.fail; +import static org.junit.Assume.assumeFalse; + +import android.Manifest; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.content.pm.ServiceInfo; +import android.os.RemoteCallback; +import android.service.watchdog.ExplicitHealthCheckService; +import android.service.watchdog.IExplicitHealthCheckService; + +import androidx.test.InstrumentationRegistry; +import androidx.test.rule.ServiceTestRule; + +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CountDownLatch; + +/** + * Contains the base tests that does not rely on the specific algorithm implementation. + */ +public class ExplicitHealthCheckServiceImplTest { + private static final String NETWORK_STACK_CONNECTOR_CLASS = + "android.net.INetworkStackConnector"; + + private final Context mContext = InstrumentationRegistry.getContext(); + private IExplicitHealthCheckService mService; + private String mNetworkStackPackageName; + + @Rule + public ServiceTestRule mServiceTestRule; + + @Before + public void setUp() throws Exception { + InstrumentationRegistry + .getInstrumentation() + .getUiAutomation() + .adoptShellPermissionIdentity( + Manifest.permission.BIND_EXPLICIT_HEALTH_CHECK_SERVICE); + + mServiceTestRule = new ServiceTestRule(); + mService = IExplicitHealthCheckService.Stub.asInterface( + mServiceTestRule.bindService(getExtServiceIntent())); + mNetworkStackPackageName = getNetworkStackPackage(); + assumeFalse(mNetworkStackPackageName == null); + } + + @After + public void tearDown() { + InstrumentationRegistry + .getInstrumentation() + .getUiAutomation() + .dropShellPermissionIdentity(); + } + + @Test + public void testHealthCheckSupportedPackage() throws Exception { + List<PackageConfig> supportedPackages = new ArrayList<>(); + CountDownLatch latch = new CountDownLatch(1); + + mService.getSupportedPackages(new RemoteCallback(result -> { + supportedPackages.addAll(result.getParcelableArrayList(EXTRA_SUPPORTED_PACKAGES)); + latch.countDown(); + })); + latch.await(); + + // TODO: Support DeviceConfig changes for the health check timeout + assertThat(supportedPackages).hasSize(1); + assertThat(supportedPackages.get(0).getPackageName()) + .isEqualTo(mNetworkStackPackageName); + assertThat(supportedPackages.get(0).getHealthCheckTimeoutMillis()) + .isEqualTo(ExplicitHealthCheckServiceImpl.DEFAULT_REQUEST_TIMEOUT_MILLIS); + } + + @Test + public void testHealthCheckRequests() throws Exception { + List<String> requestedPackages = new ArrayList<>(); + CountDownLatch latch1 = new CountDownLatch(1); + CountDownLatch latch2 = new CountDownLatch(1); + CountDownLatch latch3 = new CountDownLatch(1); + + // Initially, no health checks requested + mService.getRequestedPackages(new RemoteCallback(result -> { + requestedPackages.addAll(result.getParcelableArrayList(EXTRA_REQUESTED_PACKAGES)); + latch1.countDown(); + })); + + // Verify that no health checks requested + latch1.await(); + assertThat(requestedPackages).isEmpty(); + + // Then request health check + mService.request(mNetworkStackPackageName); + + // Verify that health check is requested for network stack + mService.getRequestedPackages(new RemoteCallback(result -> { + requestedPackages.addAll(result.getParcelableArrayList(EXTRA_REQUESTED_PACKAGES)); + latch2.countDown(); + })); + latch2.await(); + assertThat(requestedPackages).hasSize(1); + assertThat(requestedPackages.get(0)).isEqualTo(mNetworkStackPackageName); + + // Then cancel health check + requestedPackages.clear(); + mService.cancel(mNetworkStackPackageName); + + // Verify that health check is cancelled for network stack + mService.getRequestedPackages(new RemoteCallback(result -> { + requestedPackages.addAll(result.getParcelableArrayList(EXTRA_REQUESTED_PACKAGES)); + latch3.countDown(); + })); + latch3.await(); + assertThat(requestedPackages).isEmpty(); + } + + private String getNetworkStackPackage() { + Intent intent = new Intent(NETWORK_STACK_CONNECTOR_CLASS); + ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); + if (comp != null) { + return comp.getPackageName(); + } else { + // On Go devices, or any device that does not ship the network stack module. + // The network stack will live in system_server process, so no need to monitor. + return null; + } + } + + private Intent getExtServiceIntent() { + ComponentName component = getExtServiceComponentNameLocked(); + if (component == null) { + fail("Health check service not found"); + } + Intent intent = new Intent(); + intent.setComponent(component); + return intent; + } + + private ComponentName getExtServiceComponentNameLocked() { + ServiceInfo serviceInfo = getExtServiceInfoLocked(); + if (serviceInfo == null) { + return null; + } + + final ComponentName name = new ComponentName(serviceInfo.packageName, serviceInfo.name); + if (!Manifest.permission.BIND_EXPLICIT_HEALTH_CHECK_SERVICE + .equals(serviceInfo.permission)) { + return null; + } + return name; + } + + private ServiceInfo getExtServiceInfoLocked() { + final String packageName = + mContext.getPackageManager().getServicesSystemSharedLibraryPackageName(); + if (packageName == null) { + return null; + } + + final Intent intent = new Intent(ExplicitHealthCheckService.SERVICE_INTERFACE); + intent.setPackage(packageName); + final ResolveInfo resolveInfo = mContext.getPackageManager().resolveService(intent, + PackageManager.GET_SERVICES | PackageManager.GET_META_DATA); + if (resolveInfo == null || resolveInfo.serviceInfo == null) { + return null; + } + return resolveInfo.serviceInfo; + } +} diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml index 16fce89e0c13..00e8890d60e4 100644 --- a/packages/Shell/AndroidManifest.xml +++ b/packages/Shell/AndroidManifest.xml @@ -199,6 +199,9 @@ <!-- Permission required to test ContentResolver caching. --> <uses-permission android:name="android.permission.CACHE_CONTENT" /> + <!-- Permission required to test ExplicitHealthCheckServiceImpl. --> + <uses-permission android:name="android.permission.BIND_EXPLICIT_HEALTH_CHECK_SERVICE" /> + <application android:label="@string/app_label" android:defaultToDeviceProtectedStorage="true" android:directBootAware="true"> |