blob: 0b12603faa24028448d7ef4faeb566a1c5335d2a [file] [log] [blame]
/*
* Copyright (C) 2016 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.cts.ephemeralapp1;
import static android.media.AudioFormat.CHANNEL_IN_MONO;
import static android.media.AudioFormat.ENCODING_PCM_16BIT;
import static android.media.MediaRecorder.AudioSource.MIC;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.hasItems;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
import static org.testng.Assert.assertThrows;
import android.Manifest;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.SearchManager;
import android.app.SearchableInfo;
import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ProviderInfo;
import android.content.pm.ResolveInfo;
import android.database.Cursor;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.location.Criteria;
import android.location.LocationManager;
import android.media.AudioRecord;
import android.net.ConnectivityManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.os.VibrationEffect;
import android.os.Vibrator;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
import android.platform.test.annotations.AsbSecurityTest;
import com.android.cts.util.TestResult;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.io.IOException;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.TimeUnit;
@RunWith(AndroidJUnit4.class)
public class ClientTest {
/** Action to start normal test activities */
private static final String ACTION_START_NORMAL =
"com.android.cts.ephemeraltest.START_NORMAL";
/** Action to start normal, exposed test activities */
private static final String ACTION_START_EXPOSED =
"com.android.cts.ephemeraltest.START_EXPOSED";
/** Action to start ephemeral test activities */
private static final String ACTION_START_EPHEMERAL =
"com.android.cts.ephemeraltest.START_EPHEMERAL";
/** Action to start private ephemeral test activities */
private static final String ACTION_START_EPHEMERAL_PRIVATE =
"com.android.cts.ephemeraltest.START_EPHEMERAL_PRIVATE";
private static final String ACTION_START_EPHEMERAL_ACTIVITY =
"com.android.cts.ephemeraltest.START_OTHER_EPHEMERAL";
/** Action to query for test activities */
private static final String ACTION_QUERY =
"com.android.cts.ephemeraltest.QUERY";
private static final String EXTRA_ACTIVITY_NAME =
"com.android.cts.ephemeraltest.EXTRA_ACTIVITY_NAME";
private static final String EXTRA_ACTIVITY_RESULT =
"com.android.cts.ephemeraltest.EXTRA_ACTIVITY_RESULT";
private BroadcastReceiver mReceiver;
private PhoneStateListener mPhoneStateListener;
private final SynchronousQueue<TestResult> mResultQueue = new SynchronousQueue<>();
@Before
public void setUp() throws Exception {
final IntentFilter filter =
new IntentFilter("com.android.cts.ephemeraltest.START_ACTIVITY");
filter.addCategory(Intent.CATEGORY_DEFAULT);
mReceiver = new ActivityBroadcastReceiver(mResultQueue);
InstrumentationRegistry.getContext()
.registerReceiver(mReceiver, filter, Context.RECEIVER_VISIBLE_TO_INSTANT_APPS);
}
@After
public void tearDown() throws Exception {
InstrumentationRegistry.getContext().unregisterReceiver(mReceiver);
}
@Test
public void testQuery() throws Exception {
// query normal activities
{
final Intent queryIntent = new Intent(ACTION_QUERY);
final List<ResolveInfo> resolveInfo = InstrumentationRegistry.getContext()
.getPackageManager().queryIntentActivities(queryIntent, 0 /*flags*/);
if (resolveInfo == null || resolveInfo.size() == 0) {
fail("didn't resolve any intents");
}
assertThat(resolveInfo.size(), is(2));
assertThat(resolveInfo.get(0).activityInfo.packageName,
is("com.android.cts.ephemeralapp1"));
assertThat(resolveInfo.get(0).activityInfo.name,
is("com.android.cts.ephemeralapp1.EphemeralActivity"));
assertThat(resolveInfo.get(0).isInstantAppAvailable,
is(true));
assertThat(resolveInfo.get(1).activityInfo.packageName,
is("com.android.cts.normalapp"));
assertThat(resolveInfo.get(1).activityInfo.name,
is("com.android.cts.normalapp.ExposedActivity"));
assertThat(resolveInfo.get(1).isInstantAppAvailable,
is(false));
}
// query normal activities; directed package
{
final Intent queryIntent = new Intent(ACTION_QUERY);
final List<ResolveInfo> resolveInfo = InstrumentationRegistry.getContext()
.getPackageManager().queryIntentActivities(queryIntent, 0 /*flags*/);
if (resolveInfo == null || resolveInfo.size() == 0) {
fail("didn't resolve any intents");
}
assertThat(resolveInfo.size(), is(2));
assertThat(resolveInfo.get(0).activityInfo.packageName,
is("com.android.cts.ephemeralapp1"));
assertThat(resolveInfo.get(0).activityInfo.name,
is("com.android.cts.ephemeralapp1.EphemeralActivity"));
assertThat(resolveInfo.get(0).isInstantAppAvailable,
is(true));
assertThat(resolveInfo.get(1).activityInfo.packageName,
is("com.android.cts.normalapp"));
assertThat(resolveInfo.get(1).activityInfo.name,
is("com.android.cts.normalapp.ExposedActivity"));
assertThat(resolveInfo.get(1).isInstantAppAvailable,
is(false));
}
// query normal activities; directed component
{
final Intent queryIntent = new Intent(ACTION_QUERY);
final List<ResolveInfo> resolveInfo = InstrumentationRegistry.getContext()
.getPackageManager().queryIntentActivities(queryIntent, 0 /*flags*/);
if (resolveInfo == null || resolveInfo.size() == 0) {
fail("didn't resolve any intents");
}
assertThat(resolveInfo.size(), is(2));
assertThat(resolveInfo.get(0).activityInfo.packageName,
is("com.android.cts.ephemeralapp1"));
assertThat(resolveInfo.get(0).activityInfo.name,
is("com.android.cts.ephemeralapp1.EphemeralActivity"));
assertThat(resolveInfo.get(0).isInstantAppAvailable,
is(true));
assertThat(resolveInfo.get(1).activityInfo.packageName,
is("com.android.cts.normalapp"));
assertThat(resolveInfo.get(1).activityInfo.name,
is("com.android.cts.normalapp.ExposedActivity"));
assertThat(resolveInfo.get(1).isInstantAppAvailable,
is(false));
}
// query own ephemeral application activities with a web URI
{
final Intent queryIntent = new Intent(Intent.ACTION_VIEW);
queryIntent.addCategory(Intent.CATEGORY_BROWSABLE);
queryIntent.setData(Uri.parse("https://cts.google.com/ephemeral"));
final List<ResolveInfo> resolveInfo = InstrumentationRegistry.getContext()
.getPackageManager().queryIntentActivities(
queryIntent, PackageManager.GET_RESOLVED_FILTER);
if (resolveInfo == null || resolveInfo.size() == 0) {
fail("didn't resolve any intents");
}
for (ResolveInfo info: resolveInfo) {
assertThat(info.filter, is(notNullValue()));
if (handlesAllWebData(info.filter)) {
continue;
}
assertThat(info.activityInfo.packageName,
is("com.android.cts.ephemeralapp1"));
assertThat(info.activityInfo.name,
is("com.android.cts.ephemeralapp1.EphemeralActivity"));
assertThat(info.isInstantAppAvailable,
is(true));
}
}
// query other ephemeral application activities with a web URI
{
final Intent queryIntent = new Intent(Intent.ACTION_VIEW);
queryIntent.addCategory(Intent.CATEGORY_BROWSABLE);
queryIntent.setData(Uri.parse("https://cts.google.com/other"));
final List<ResolveInfo> resolveInfo = InstrumentationRegistry.getContext()
.getPackageManager().queryIntentActivities(
queryIntent, PackageManager.GET_RESOLVED_FILTER);
if (resolveInfo == null || resolveInfo.size() == 0) {
fail("didn't resolve any intents");
}
for (ResolveInfo info: resolveInfo) {
assertThat(info.filter, is(notNullValue()));
if (handlesAllWebData(info.filter)) {
continue;
}
fail("resolution should have only matched browsers");
}
}
// query services
{
final Intent queryIntent = new Intent(ACTION_QUERY);
final List<ResolveInfo> resolveInfo = InstrumentationRegistry
.getContext().getPackageManager().queryIntentServices(queryIntent, 0 /*flags*/);
if (resolveInfo == null || resolveInfo.size() == 0) {
fail("didn't resolve any intents");
}
assertThat(resolveInfo.size(), is(2));
assertThat(resolveInfo.get(0).serviceInfo.packageName,
is("com.android.cts.ephemeralapp1"));
assertThat(resolveInfo.get(0).serviceInfo.name,
is("com.android.cts.ephemeralapp1.EphemeralService"));
assertThat(resolveInfo.get(1).serviceInfo.packageName,
is("com.android.cts.normalapp"));
assertThat(resolveInfo.get(1).serviceInfo.name,
is("com.android.cts.normalapp.ExposedService"));
assertThat(resolveInfo.get(1).isInstantAppAvailable,
is(false));
}
// query services; directed package
{
final Intent queryIntent = new Intent(ACTION_QUERY);
queryIntent.setPackage("com.android.cts.ephemeralapp1");
final List<ResolveInfo> resolveInfo = InstrumentationRegistry
.getContext().getPackageManager().queryIntentServices(queryIntent, 0 /*flags*/);
if (resolveInfo == null || resolveInfo.size() == 0) {
fail("didn't resolve any intents");
}
assertThat(resolveInfo.size(), is(1));
assertThat(resolveInfo.get(0).serviceInfo.packageName,
is("com.android.cts.ephemeralapp1"));
assertThat(resolveInfo.get(0).serviceInfo.name,
is("com.android.cts.ephemeralapp1.EphemeralService"));
}
// query services; directed component
{
final Intent queryIntent = new Intent(ACTION_QUERY);
queryIntent.setComponent(
new ComponentName("com.android.cts.ephemeralapp1",
"com.android.cts.ephemeralapp1.EphemeralService"));
final List<ResolveInfo> resolveInfo = InstrumentationRegistry
.getContext().getPackageManager().queryIntentServices(queryIntent, 0 /*flags*/);
if (resolveInfo == null || resolveInfo.size() == 0) {
fail("didn't resolve any intents");
}
assertThat(resolveInfo.size(), is(1));
assertThat(resolveInfo.get(0).serviceInfo.packageName,
is("com.android.cts.ephemeralapp1"));
assertThat(resolveInfo.get(0).serviceInfo.name,
is("com.android.cts.ephemeralapp1.EphemeralService"));
}
// query instant application provider
{
final Intent queryIntent = new Intent(ACTION_QUERY);
final List<ResolveInfo> resolveInfo = InstrumentationRegistry
.getContext().getPackageManager().queryIntentContentProviders(
queryIntent, 0 /*flags*/);
if (resolveInfo == null || resolveInfo.size() == 0) {
fail("didn't resolve any intents");
}
assertThat(resolveInfo.size(), is(2));
assertThat(resolveInfo.get(0).providerInfo.packageName,
is("com.android.cts.ephemeralapp1"));
assertThat(resolveInfo.get(0).providerInfo.name,
is("com.android.cts.ephemeralapp1.EphemeralProvider"));
assertThat(resolveInfo.get(1).providerInfo.packageName,
is("com.android.cts.normalapp"));
assertThat(resolveInfo.get(1).providerInfo.name,
is("com.android.cts.normalapp.ExposedProvider"));
assertThat(resolveInfo.get(1).isInstantAppAvailable,
is(false));
}
// query instant application provider ; directed package
{
final Intent queryIntent = new Intent(ACTION_QUERY);
queryIntent.setPackage("com.android.cts.ephemeralapp1");
final List<ResolveInfo> resolveInfo = InstrumentationRegistry
.getContext().getPackageManager().queryIntentContentProviders(
queryIntent, 0 /*flags*/);
if (resolveInfo == null || resolveInfo.size() == 0) {
fail("didn't resolve any intents");
}
assertThat(resolveInfo.size(), is(1));
assertThat(resolveInfo.get(0).providerInfo.packageName,
is("com.android.cts.ephemeralapp1"));
assertThat(resolveInfo.get(0).providerInfo.name,
is("com.android.cts.ephemeralapp1.EphemeralProvider"));
}
// query instant application provider ; directed component
{
final Intent queryIntent = new Intent(ACTION_QUERY);
queryIntent.setComponent(
new ComponentName("com.android.cts.ephemeralapp1",
"com.android.cts.ephemeralapp1.EphemeralProvider"));
final List<ResolveInfo> resolveInfo = InstrumentationRegistry
.getContext().getPackageManager().queryIntentContentProviders(
queryIntent, 0 /*flags*/);
if (resolveInfo == null || resolveInfo.size() == 0) {
fail("didn't resolve any intents");
}
assertThat(resolveInfo.size(), is(1));
assertThat(resolveInfo.get(0).providerInfo.packageName,
is("com.android.cts.ephemeralapp1"));
assertThat(resolveInfo.get(0).providerInfo.name,
is("com.android.cts.ephemeralapp1.EphemeralProvider"));
}
// resolve normal provider
{
final ProviderInfo providerInfo = InstrumentationRegistry
.getContext().getPackageManager().resolveContentProvider(
"com.android.cts.normalapp.provider", 0 /*flags*/);
assertThat(providerInfo, is(nullValue()));
}
// resolve exposed provider
{
final ProviderInfo providerInfo = InstrumentationRegistry
.getContext().getPackageManager().resolveContentProvider(
"com.android.cts.normalapp.exposed.provider", 0 /*flags*/);
assertThat(providerInfo, is(notNullValue()));
assertThat(providerInfo.packageName,
is("com.android.cts.normalapp"));
assertThat(providerInfo.name,
is("com.android.cts.normalapp.ExposedProvider"));
}
// resolve instant application provider
{
final ProviderInfo providerInfo = InstrumentationRegistry
.getContext().getPackageManager().resolveContentProvider(
"com.android.cts.ephemeralapp1.provider", 0 /*flags*/);
assertThat(providerInfo, is(notNullValue()));
assertThat(providerInfo.packageName,
is("com.android.cts.ephemeralapp1"));
assertThat(providerInfo.name,
is("com.android.cts.ephemeralapp1.EphemeralProvider"));
}
}
@Test
public void testStartNormal() throws Exception {
// start the normal activity
try {
final Intent startNormalIntent = new Intent(ACTION_START_NORMAL)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
InstrumentationRegistry
.getContext().startActivity(startNormalIntent, null /*options*/);
final TestResult testResult = getResult();
fail();
} catch (ActivityNotFoundException expected) {
}
// start the normal activity; directed package
try {
final Intent startNormalIntent = new Intent(ACTION_START_NORMAL)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startNormalIntent.setPackage("com.android.cts.normalapp");
InstrumentationRegistry
.getContext().startActivity(startNormalIntent, null /*options*/);
final TestResult testResult = getResult();
fail();
} catch (ActivityNotFoundException expected) {
}
// start the normal activity; directed component
try {
final Intent startNormalIntent = new Intent(ACTION_START_NORMAL)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startNormalIntent.setComponent(new ComponentName(
"com.android.cts.normalapp", "com.android.cts.normalapp.NormalActivity"));
InstrumentationRegistry
.getContext().startActivity(startNormalIntent, null /*options*/);
final TestResult testResult = getResult();
fail();
} catch (ActivityNotFoundException expected) {
}
// TODO: Ideally we should have a test for this. However, it shows a disambig between the
// the normal app and chrome; for which there is no easy solution.
// // start the normal activity; using VIEW/BROWSABLE
// {
// final Intent startViewIntent = new Intent(Intent.ACTION_VIEW)
// .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// startViewIntent.addCategory(Intent.CATEGORY_BROWSABLE);
// startViewIntent.setData(Uri.parse("https://cts.google.com/normal"));
// InstrumentationRegistry.getContext().startActivity(startViewIntent, null /*options*/);
// final TestResult testResult = getResult();
// assertThat(testResult.getPackageName(),
// is("com.android.cts.normalapp"));
// assertThat(testResult.getComponentName(),
// is("NormalWebActivity"));
// assertThat(testResult.getStatus(),
// is("PASS"));
// assertThat(testResult.getEphemeralPackageInfoExposed(),
// is(false));
// assertThat(testResult.getException(),
// is(nullValue()));
// }
// We don't attempt to start the service since it will merely return and not
// provide any feedback. The alternative is to wait for the broadcast timeout
// but it's silly to artificially slow down CTS. We'll rely on queryIntentService
// to check whether or not the service is actually exposed
// bind to the normal service; directed package
{
final Intent startNormalIntent = new Intent(ACTION_START_NORMAL);
startNormalIntent.setPackage("com.android.cts.normalapp");
final TestServiceConnection connection = new TestServiceConnection();
try {
assertThat(InstrumentationRegistry.getContext().bindService(
startNormalIntent, connection, Context.BIND_AUTO_CREATE /*flags*/),
is(false));
} finally {
InstrumentationRegistry.getContext().unbindService(connection);
}
}
// bind to the normal service; directed component
{
final Intent startNormalIntent = new Intent(ACTION_START_NORMAL);
startNormalIntent.setComponent(new ComponentName(
"com.android.cts.normalapp", "com.android.cts.normalapp.NormalService"));
final TestServiceConnection connection = new TestServiceConnection();
try {
assertThat(InstrumentationRegistry.getContext().bindService(
startNormalIntent, connection, Context.BIND_AUTO_CREATE /*flags*/),
is(false));
} finally {
InstrumentationRegistry.getContext().unbindService(connection);
}
}
// connect to the normal provider
{
final String provider = "content://com.android.cts.normalapp.provider/table";
final Cursor testCursor = InstrumentationRegistry
.getContext().getContentResolver().query(
Uri.parse(provider),
null /*projection*/,
null /*selection*/,
null /*selectionArgs*/,
null /*sortOrder*/);
assertThat(testCursor, is(nullValue()));
}
}
@Test
public void testStartExposed01() throws Exception {
// start the explicitly exposed activity
final Intent startExposedIntent = new Intent(ACTION_START_EXPOSED)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
InstrumentationRegistry
.getContext().startActivity(startExposedIntent, null /*options*/);
final TestResult testResult = getResult();
assertThat(testResult.getPackageName(),
is("com.android.cts.normalapp"));
assertThat(testResult.getComponentName(),
is("ExposedActivity"));
assertThat(testResult.getStatus(),
is("PASS"));
assertThat(testResult.getEphemeralPackageInfoExposed(),
is(false));
assertThat(testResult.getException(),
is(PackageManager.NameNotFoundException.class.getName()));
}
@Test
public void testStartExposed02() throws Exception {
// start the explicitly exposed activity; directed package
final Intent startExposedIntent = new Intent(ACTION_START_EXPOSED)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startExposedIntent.setPackage("com.android.cts.normalapp");
InstrumentationRegistry
.getContext().startActivity(startExposedIntent, null /*options*/);
final TestResult testResult = getResult();
assertThat(testResult.getPackageName(),
is("com.android.cts.normalapp"));
assertThat(testResult.getComponentName(),
is("ExposedActivity"));
assertThat(testResult.getStatus(),
is("PASS"));
assertThat(testResult.getEphemeralPackageInfoExposed(),
is(false));
assertThat(testResult.getException(),
is(PackageManager.NameNotFoundException.class.getName()));
}
@Test
public void testStartExposed03() throws Exception {
// start the explicitly exposed activity; directed component
final Intent startExposedIntent = new Intent(ACTION_START_EXPOSED)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startExposedIntent.setComponent(new ComponentName(
"com.android.cts.normalapp", "com.android.cts.normalapp.ExposedActivity"));
InstrumentationRegistry
.getContext().startActivity(startExposedIntent, null /*options*/);
final TestResult testResult = getResult();
assertThat(testResult.getPackageName(),
is("com.android.cts.normalapp"));
assertThat(testResult.getComponentName(),
is("ExposedActivity"));
assertThat(testResult.getStatus(),
is("PASS"));
assertThat(testResult.getEphemeralPackageInfoExposed(),
is(false));
assertThat(testResult.getException(),
is(PackageManager.NameNotFoundException.class.getName()));
}
@Test
public void testStartExposed04() throws Exception {
// start the implicitly exposed activity; directed package
try {
final Intent startExposedIntent = new Intent(Intent.ACTION_VIEW)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startExposedIntent.setPackage("com.android.cts.implicitapp");
startExposedIntent.addCategory(Intent.CATEGORY_BROWSABLE);
startExposedIntent.setData(Uri.parse("https://cts.google.com/implicit"));
InstrumentationRegistry
.getContext().startActivity(startExposedIntent, null /*options*/);
fail("activity started");
} catch (ActivityNotFoundException expected) { }
}
@Test
public void testStartExposed05() throws Exception {
// start the implicitly exposed activity; directed component
try {
final Intent startExposedIntent = new Intent(Intent.ACTION_VIEW)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startExposedIntent.setComponent(new ComponentName(
"com.android.cts.implicitapp",
"com.android.cts.implicitapp.ImplicitActivity"));
startExposedIntent.addCategory(Intent.CATEGORY_BROWSABLE);
startExposedIntent.setData(Uri.parse("https://cts.google.com/implicit"));
InstrumentationRegistry
.getContext().startActivity(startExposedIntent, null /*options*/);
fail("activity started");
} catch (ActivityNotFoundException expected) { }
}
@Test
public void testStartExposed06() throws Exception {
// start the exposed service; directed package
final Intent startExposedIntent = new Intent(ACTION_START_EXPOSED)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startExposedIntent.setPackage("com.android.cts.normalapp");
InstrumentationRegistry.getContext().startForegroundService(startExposedIntent);
final TestResult testResult = getResult();
assertThat(testResult.getPackageName(),
is("com.android.cts.normalapp"));
assertThat(testResult.getComponentName(),
is("ExposedService"));
assertThat(testResult.getStatus(),
is("PASS"));
assertThat(testResult.getEphemeralPackageInfoExposed(),
is(true));
assertThat(testResult.getException(),
is(nullValue()));
}
@Test
public void testStartExposed07() throws Exception {
// start the exposed service; directed component
final Intent startExposedIntent = new Intent(ACTION_START_EXPOSED);
startExposedIntent.setComponent(new ComponentName(
"com.android.cts.normalapp", "com.android.cts.normalapp.ExposedService"));
InstrumentationRegistry.getContext().startForegroundService(startExposedIntent);
final TestResult testResult = getResult();
assertThat(testResult.getPackageName(),
is("com.android.cts.normalapp"));
assertThat(testResult.getComponentName(),
is("ExposedService"));
assertThat(testResult.getMethodName(),
is("onStartCommand"));
assertThat(testResult.getStatus(),
is("PASS"));
assertThat(testResult.getEphemeralPackageInfoExposed(),
is(true));
assertThat(testResult.getException(),
is(nullValue()));
}
@Test
public void testStartExposed08() throws Exception {
// bind to the exposed service; directed package
final Intent startExposedIntent = new Intent(ACTION_START_EXPOSED);
startExposedIntent.setPackage("com.android.cts.normalapp");
final TestServiceConnection connection = new TestServiceConnection();
try {
assertThat(InstrumentationRegistry.getContext().bindService(
startExposedIntent, connection, Context.BIND_AUTO_CREATE /*flags*/),
is(true));
final TestResult testResult = getResult();
assertThat(testResult.getPackageName(),
is("com.android.cts.normalapp"));
assertThat(testResult.getComponentName(),
is("ExposedService"));
assertThat(testResult.getMethodName(),
is("onBind"));
assertThat(testResult.getStatus(),
is("PASS"));
assertThat(testResult.getEphemeralPackageInfoExposed(),
is(true));
assertThat(testResult.getException(),
is(nullValue()));
} finally {
InstrumentationRegistry.getContext().unbindService(connection);
}
}
@Test
public void testStartExposed09() throws Exception {
// bind to the exposed service; directed component
final Intent startExposedIntent = new Intent(ACTION_START_EXPOSED);
startExposedIntent.setComponent(new ComponentName(
"com.android.cts.normalapp", "com.android.cts.normalapp.ExposedService"));
final TestServiceConnection connection = new TestServiceConnection();
try {
assertThat(InstrumentationRegistry.getContext().bindService(
startExposedIntent, connection, Context.BIND_AUTO_CREATE /*flags*/),
is(true));
final TestResult testResult = getResult();
assertThat(testResult.getPackageName(),
is("com.android.cts.normalapp"));
assertThat(testResult.getComponentName(),
is("ExposedService"));
assertThat(testResult.getMethodName(),
is("onBind"));
assertThat(testResult.getStatus(),
is("PASS"));
assertThat(testResult.getEphemeralPackageInfoExposed(),
is(true));
assertThat(testResult.getException(),
is(nullValue()));
} finally {
InstrumentationRegistry.getContext().unbindService(connection);
}
}
@Test
public void testStartExposed10() throws Exception {
// connect to exposed provider
final String provider = "content://com.android.cts.normalapp.exposed.provider/table";
final Cursor testCursor = InstrumentationRegistry
.getContext().getContentResolver().query(
Uri.parse(provider),
null /*projection*/,
null /*selection*/,
null /*selectionArgs*/,
null /*sortOrder*/);
assertThat(testCursor, is(notNullValue()));
assertThat(testCursor.getCount(), is(1));
assertThat(testCursor.getColumnCount(), is(2));
assertThat(testCursor.moveToFirst(), is(true));
assertThat(testCursor.getInt(0), is(1));
assertThat(testCursor.getString(1), is("ExposedProvider"));
final TestResult testResult = getResult();
assertThat(testResult.getPackageName(),
is("com.android.cts.normalapp"));
assertThat(testResult.getComponentName(),
is("ExposedProvider"));
assertThat(testResult.getStatus(),
is("PASS"));
assertThat(testResult.getEphemeralPackageInfoExposed(),
is(true));
assertThat(testResult.getException(),
is(nullValue()));
}
@Test
public void testStartExposed11() throws Exception {
// start the explicitly exposed activity
final Intent startExposedIntent = new Intent(ACTION_START_EXPOSED)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
final Context context = InstrumentationRegistry.getContext();
context.startActivity(startExposedIntent.setComponent(
new ComponentName(context, StartForResultActivity.class)));
final TestResult testResult = getResult();
assertThat(testResult.getPackageName(),
is("com.android.cts.normalapp"));
assertThat(testResult.getComponentName(),
is("ExposedActivity"));
assertThat(testResult.getStatus(),
is("PASS"));
assertThat(testResult.getEphemeralPackageInfoExposed(),
is(true));
assertThat(testResult.getException(),
is(nullValue()));
}
@Test
public void testStartEphemeral() throws Exception {
// start the ephemeral activity
{
final Intent startEphemeralIntent = new Intent(ACTION_START_EPHEMERAL)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
InstrumentationRegistry
.getContext().startActivity(startEphemeralIntent, null /*options*/);
final TestResult testResult = getResult();
assertThat(testResult.getPackageName(),
is("com.android.cts.ephemeralapp1"));
assertThat(testResult.getComponentName(),
is("EphemeralActivity"));
assertThat(testResult.getStatus(),
is("PASS"));
assertThat(testResult.getException(),
is(nullValue()));
}
// start the ephemeral activity; directed package
{
final Intent startEphemeralIntent = new Intent(ACTION_START_EPHEMERAL)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startEphemeralIntent.setPackage("com.android.cts.ephemeralapp1");
InstrumentationRegistry
.getContext().startActivity(startEphemeralIntent, null /*options*/);
final TestResult testResult = getResult();
assertThat(testResult.getPackageName(),
is("com.android.cts.ephemeralapp1"));
assertThat(testResult.getComponentName(),
is("EphemeralActivity"));
assertThat(testResult.getStatus(),
is("PASS"));
assertThat(testResult.getException(),
is(nullValue()));
}
// start the ephemeral activity; directed component
{
final Intent startEphemeralIntent = new Intent(ACTION_START_EPHEMERAL)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startEphemeralIntent.setComponent(
new ComponentName("com.android.cts.ephemeralapp1",
"com.android.cts.ephemeralapp1.EphemeralActivity"));
InstrumentationRegistry
.getContext().startActivity(startEphemeralIntent, null /*options*/);
final TestResult testResult = getResult();
assertThat(testResult.getPackageName(),
is("com.android.cts.ephemeralapp1"));
assertThat(testResult.getComponentName(),
is("EphemeralActivity"));
assertThat(testResult.getStatus(),
is("PASS"));
assertThat(testResult.getException(),
is(nullValue()));
}
// start a private ephemeral activity
{
final Intent startEphemeralIntent = new Intent(ACTION_START_EPHEMERAL_PRIVATE)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
InstrumentationRegistry
.getContext().startActivity(startEphemeralIntent, null /*options*/);
final TestResult testResult = getResult();
assertThat(testResult.getPackageName(),
is("com.android.cts.ephemeralapp1"));
assertThat(testResult.getComponentName(),
is("EphemeralActivity2"));
assertThat(testResult.getStatus(),
is("PASS"));
assertThat(testResult.getException(),
is(nullValue()));
}
// start a private ephemeral activity; directed package
{
final Intent startEphemeralIntent = new Intent(ACTION_START_EPHEMERAL_PRIVATE)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startEphemeralIntent.setPackage("com.android.cts.ephemeralapp1");
InstrumentationRegistry
.getContext().startActivity(startEphemeralIntent, null /*options*/);
final TestResult testResult = getResult();
assertThat(testResult.getPackageName(),
is("com.android.cts.ephemeralapp1"));
assertThat(testResult.getComponentName(),
is("EphemeralActivity2"));
assertThat(testResult.getStatus(),
is("PASS"));
assertThat(testResult.getException(),
is(nullValue()));
}
// start a private ephemeral activity; directed component
{
final Intent startEphemeralIntent = new Intent(ACTION_START_EPHEMERAL_PRIVATE)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startEphemeralIntent.setComponent(
new ComponentName("com.android.cts.ephemeralapp1",
"com.android.cts.ephemeralapp1.EphemeralActivity2"));
InstrumentationRegistry
.getContext().startActivity(startEphemeralIntent, null /*options*/);
final TestResult testResult = getResult();
assertThat(testResult.getPackageName(),
is("com.android.cts.ephemeralapp1"));
assertThat(testResult.getComponentName(),
is("EphemeralActivity2"));
assertThat(testResult.getStatus(),
is("PASS"));
assertThat(testResult.getException(),
is(nullValue()));
}
// start a private ephemeral activity; directed component
{
final Intent startEphemeralIntent = new Intent()
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startEphemeralIntent.setComponent(
new ComponentName("com.android.cts.ephemeralapp1",
"com.android.cts.ephemeralapp1.EphemeralActivity3"));
InstrumentationRegistry
.getContext().startActivity(startEphemeralIntent, null /*options*/);
final TestResult testResult = getResult();
assertThat(testResult.getPackageName(),
is("com.android.cts.ephemeralapp1"));
assertThat(testResult.getComponentName(),
is("EphemeralActivity3"));
assertThat(testResult.getStatus(),
is("PASS"));
assertThat(testResult.getException(),
is(nullValue()));
}
// start an ephemeral activity; VIEW / BROWSABLE intent
{
final Intent startEphemeralIntent = new Intent(Intent.ACTION_VIEW)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startEphemeralIntent.addCategory(Intent.CATEGORY_BROWSABLE);
startEphemeralIntent.setData(Uri.parse("https://cts.google.com/other"));
InstrumentationRegistry
.getContext().startActivity(startEphemeralIntent, null /*options*/);
final TestResult testResult = getResult();
assertThat(testResult.getPackageName(),
is("com.android.cts.ephemeralapp2"));
assertThat(testResult.getComponentName(),
is("EphemeralActivity"));
assertThat(testResult.getIntent().getAction(),
is(Intent.ACTION_VIEW));
assertThat(testResult.getIntent().getCategories(),
hasItems(Intent.CATEGORY_BROWSABLE));
assertThat(testResult.getIntent().getData().toString(),
is("https://cts.google.com/other"));
assertThat(testResult.getStatus(),
is("PASS"));
assertThat(testResult.getException(),
is(nullValue()));
}
// start an ephemeral activity; EXTERNAL flag
{
final Intent startEphemeralIntent = new Intent(ACTION_START_EPHEMERAL_ACTIVITY)
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MATCH_EXTERNAL);
InstrumentationRegistry.getContext().startActivity(
startEphemeralIntent, null /*options*/);
final TestResult testResult = getResult();
assertThat(testResult.getPackageName(),
is("com.android.cts.ephemeralapp2"));
assertThat(testResult.getComponentName(),
is("EphemeralActivity"));
assertThat(testResult.getIntent().getAction(),
is(ACTION_START_EPHEMERAL_ACTIVITY));
assertThat(testResult.getIntent().getData(),
is(nullValue()));
assertThat(testResult.getStatus(),
is("PASS"));
assertThat(testResult.getException(),
is(nullValue()));
}
// start the ephemeral service; directed package
{
final Intent startEphemeralIntent = new Intent(ACTION_START_EPHEMERAL);
startEphemeralIntent.setPackage("com.android.cts.ephemeralapp1");
try {
InstrumentationRegistry.getContext().startService(startEphemeralIntent);
final TestResult testResult = getResult();
assertThat(testResult.getPackageName(),
is("com.android.cts.ephemeralapp1"));
assertThat(testResult.getComponentName(),
is("EphemeralService"));
assertThat(testResult.getMethodName(),
is("onStartCommand"));
assertThat(testResult.getStatus(),
is("PASS"));
assertThat(testResult.getException(),
is(nullValue()));
} finally {
InstrumentationRegistry.getContext().stopService(startEphemeralIntent);
}
}
// start the ephemeral service; directed component
{
final Intent startEphemeralIntent = new Intent(ACTION_START_EPHEMERAL);
startEphemeralIntent.setComponent(
new ComponentName("com.android.cts.ephemeralapp1",
"com.android.cts.ephemeralapp1.EphemeralService"));
try {
assertThat(InstrumentationRegistry.getContext().startService(startEphemeralIntent),
is(notNullValue()));
final TestResult testResult = getResult();
assertThat(testResult.getPackageName(),
is("com.android.cts.ephemeralapp1"));
assertThat(testResult.getComponentName(),
is("EphemeralService"));
assertThat(testResult.getMethodName(),
is("onStartCommand"));
assertThat(testResult.getStatus(),
is("PASS"));
assertThat(testResult.getException(),
is(nullValue()));
} finally {
InstrumentationRegistry.getContext().stopService(startEphemeralIntent);
}
}
// bind to the ephemeral service; directed package
{
final Intent startEphemeralIntent = new Intent(ACTION_START_EPHEMERAL);
startEphemeralIntent.setPackage("com.android.cts.ephemeralapp1");
final TestServiceConnection connection = new TestServiceConnection();
try {
assertThat(InstrumentationRegistry.getContext().bindService(
startEphemeralIntent, connection, Context.BIND_AUTO_CREATE /*flags*/),
is(true));
final TestResult testResult = getResult();
assertThat(testResult.getPackageName(),
is("com.android.cts.ephemeralapp1"));
assertThat(testResult.getComponentName(),
is("EphemeralService"));
assertThat(testResult.getMethodName(),
is("onBind"));
assertThat(testResult.getStatus(),
is("PASS"));
assertThat(testResult.getException(),
is(nullValue()));
} finally {
InstrumentationRegistry.getContext().unbindService(connection);
}
}
// bind to the ephemeral service; directed component
{
final Intent startEphemeralIntent = new Intent(ACTION_START_EPHEMERAL);
startEphemeralIntent.setComponent(
new ComponentName("com.android.cts.ephemeralapp1",
"com.android.cts.ephemeralapp1.EphemeralService"));
final TestServiceConnection connection = new TestServiceConnection();
try {
assertThat(InstrumentationRegistry.getContext().bindService(
startEphemeralIntent, connection, Context.BIND_AUTO_CREATE /*flags*/),
is(true));
final TestResult testResult = getResult();
assertThat(testResult.getPackageName(),
is("com.android.cts.ephemeralapp1"));
assertThat(testResult.getComponentName(),
is("EphemeralService"));
assertThat(testResult.getMethodName(),
is("onBind"));
assertThat(testResult.getStatus(),
is("PASS"));
assertThat(testResult.getException(),
is(nullValue()));
} finally {
InstrumentationRegistry.getContext().unbindService(connection);
}
}
// connect to the instant app provider
{
final String provider = "content://com.android.cts.ephemeralapp1.provider/table";
final Cursor testCursor = InstrumentationRegistry
.getContext().getContentResolver().query(
Uri.parse(provider),
null /*projection*/,
null /*selection*/,
null /*selectionArgs*/,
null /*sortOrder*/);
assertThat(testCursor, is(notNullValue()));
assertThat(testCursor.getCount(), is(1));
assertThat(testCursor.getColumnCount(), is(2));
assertThat(testCursor.moveToFirst(), is(true));
assertThat(testCursor.getInt(0), is(1));
assertThat(testCursor.getString(1), is("InstantAppProvider"));
}
}
@Test
public void testBuildSerialUnknown() throws Exception {
assertThat(Build.SERIAL, is(Build.UNKNOWN));
}
@Test
public void testPackageInfo() throws Exception {
PackageInfo info;
// own package info
info = InstrumentationRegistry.getContext().getPackageManager()
.getPackageInfo("com.android.cts.ephemeralapp1", 0);
assertThat(info.packageName,
is("com.android.cts.ephemeralapp1"));
// exposed application package info
info = InstrumentationRegistry.getContext().getPackageManager()
.getPackageInfo("com.android.cts.normalapp", 0);
assertThat(info.packageName,
is("com.android.cts.normalapp"));
// implicitly exposed application package info not accessible
try {
info = InstrumentationRegistry.getContext().getPackageManager()
.getPackageInfo("com.android.cts.implicitapp", 0);
fail("Instant apps should not be able to access PackageInfo for an app that does not" +
" expose itself to Instant Apps.");
} catch (PackageManager.NameNotFoundException expected) {
}
// unexposed application package info not accessible
try {
info = InstrumentationRegistry.getContext().getPackageManager()
.getPackageInfo("com.android.cts.unexposedapp", 0);
fail("Instant apps should not be able to access PackageInfo for an app that does not" +
" expose itself to Instant Apps.");
} catch (PackageManager.NameNotFoundException expected) {
}
// instant application (with visibleToInstantApp component) package info not accessible
try {
info = InstrumentationRegistry.getContext().getPackageManager()
.getPackageInfo("com.android.cts.ephemeralapp2", 0);
fail("Instant apps should not be able to access PackageInfo for another Instant App.");
} catch (PackageManager.NameNotFoundException expected) {
}
}
@Test
public void testActivityInfo() throws Exception {
// own package info
{
final ComponentName component = new ComponentName(
"com.android.cts.ephemeralapp1",
"com.android.cts.ephemeralapp1.EphemeralActivity");
final ActivityInfo info = InstrumentationRegistry.getContext().getPackageManager()
.getActivityInfo(component, 0);
assertThat(info.packageName,
is("com.android.cts.ephemeralapp1"));
}
// exposed application package info
{
final ComponentName component = new ComponentName(
"com.android.cts.normalapp",
"com.android.cts.normalapp.ExposedActivity");
final ActivityInfo info = InstrumentationRegistry.getContext().getPackageManager()
.getActivityInfo(component, 0);
assertThat(info.packageName,
is("com.android.cts.normalapp"));
}
// implicitly exposed application package info not accessible
{
try {
final ComponentName component = new ComponentName(
"com.android.cts.normalapp",
"com.android.cts.normalapp.NormalWebActivity");
final ActivityInfo info = InstrumentationRegistry.getContext().getPackageManager()
.getActivityInfo(component, 0);
fail("Instant apps should not be able to access ActivityInfo for"
+ " an activity that implicitly exposes itself to Instant Apps.");
} catch (PackageManager.NameNotFoundException expected) {
}
}
// unexposed application package info not accessible
{
try {
final ComponentName component = new ComponentName(
"com.android.cts.normalapp",
"com.android.cts.normalapp.NormalActivity");
final ActivityInfo info = InstrumentationRegistry.getContext().getPackageManager()
.getActivityInfo(component, 0);
fail("Instant apps should not be able to access ActivityInfo for"
+ " an activity that does not expose itself to Instant Apps.");
} catch (PackageManager.NameNotFoundException expected) {
}
}
// instant application (with visibleToInstantApp component) package info not accessible
{
try {
final ComponentName component = new ComponentName(
"com.android.cts.ephemeralapp2",
"com.android.cts.ephemeralapp2.ExposedActivity");
final ActivityInfo info = InstrumentationRegistry.getContext().getPackageManager()
.getActivityInfo(component, 0);
fail("Instant apps should not be able to access ActivityInfo for"
+ " another Instant App.");
} catch (PackageManager.NameNotFoundException expected) {
}
}
}
@Test
public void testInstallPermissionNotGranted() throws Exception {
assertThat(InstrumentationRegistry.getContext()
.checkCallingOrSelfPermission(Manifest.permission.SET_ALARM),
is(PackageManager.PERMISSION_DENIED));
}
@Test
public void testInstallPermissionGranted() throws Exception {
assertThat(InstrumentationRegistry.getContext()
.checkCallingOrSelfPermission(Manifest.permission.INTERNET),
is(PackageManager.PERMISSION_GRANTED));
}
@Test
@AsbSecurityTest(cveBugId = 140256621)
public void testInstallPermissionNotGrantedInPackageInfo() throws Exception {
assertThat(isPermissionGrantedInPackageInfo(Manifest.permission.SET_ALARM), is(false));
}
@Test
@AsbSecurityTest(cveBugId = 140256621)
public void testInstallPermissionGrantedInPackageInfo() throws Exception {
assertThat(isPermissionGrantedInPackageInfo(Manifest.permission.INTERNET), is(true));
}
private static boolean isPermissionGrantedInPackageInfo(String permissionName)
throws Exception {
final Context context = InstrumentationRegistry.getContext();
final PackageInfo packageInfo = context.getPackageManager().getPackageInfo(
context.getPackageName(), PackageManager.GET_PERMISSIONS);
final int permissionIndex = Arrays.asList(packageInfo.requestedPermissions).indexOf(
permissionName);
assertThat(permissionIndex, is(not(-1)));
return (packageInfo.requestedPermissionsFlags[permissionIndex]
& PackageInfo.REQUESTED_PERMISSION_GRANTED) != 0;
}
@Test
public void testExposedActivity() throws Exception {
final Bundle testArgs = InstrumentationRegistry.getArguments();
assertThat(testArgs, is(notNullValue()));
final String action = testArgs.getString("action");
final String category = testArgs.getString("category");
final String mimeType = testArgs.getString("mime_type");
assertThat(action, is(notNullValue()));
final Intent queryIntent = makeIntent(action, category, mimeType);
final List<ResolveInfo> resolveInfo = InstrumentationRegistry.getContext()
.getPackageManager().queryIntentActivities(queryIntent, 0 /*flags*/);
if (resolveInfo == null || resolveInfo.size() == 0) {
fail("No activies found for Intent: " + queryIntent);
}
}
@Test
public void testGetInstaller01() throws Exception {
// test we can read our own installer
final String installerPackageName = InstrumentationRegistry.getContext().getPackageManager()
.getInstallerPackageName("com.android.cts.ephemeralapp1");
assertThat(installerPackageName, is("com.android.cts.normalapp"));
}
@Test
public void testGetInstaller02() throws Exception {
// test we can read someone else's installer if they're exposed to instant applications
final String installerPackageName = InstrumentationRegistry.getContext().getPackageManager()
.getInstallerPackageName("com.android.cts.normalapp");
assertThat(installerPackageName, is("com.android.cts.normalapp"));
}
@Test
public void testGetInstaller03() throws Exception {
// test we can't read installer if they're not exposed to instant applications
final PackageManager pm = InstrumentationRegistry.getContext().getPackageManager();
assertThrows(IllegalArgumentException.class,
() -> pm.getInstallerPackageName("com.android.cts.unexposedapp"));
}
@Test
public void testStartForegroundService() throws Exception {
final Context context = InstrumentationRegistry.getContext();
final Intent intent = new Intent(context, SomeService.class);
// Create a notification channel for the foreground notification
final NotificationChannel channel = new NotificationChannel("foo", "foo",
NotificationManager.IMPORTANCE_DEFAULT);
final NotificationManager notificationManager = context.getSystemService(
NotificationManager.class);
notificationManager.createNotificationChannel(channel);
// Shouldn't be able to start without a permission
final CountDownLatch latch1 = new CountDownLatch(1);
SomeService.setOnStartCommandCallback((int result) -> {
assertSame("Shouldn't be able to start without "
+ " INSTANT_APP_FOREGROUND_SERVICE permission", 0, result);
latch1.countDown();
});
context.startForegroundService(intent);
latch1.await(5, TimeUnit.SECONDS);
// Now grant ourselves INSTANT_APP_FOREGROUND_SERVICE
grantInstantAppForegroundServicePermission();
// Should be able to start with a permission
final CountDownLatch latch2 = new CountDownLatch(1);
SomeService.setOnStartCommandCallback((int result) -> {
assertSame("Should be able to start with "
+ " INSTANT_APP_FOREGROUND_SERVICE permission", 1, result);
latch2.countDown();
});
context.startForegroundService(intent);
latch2.await(5, TimeUnit.SECONDS);
}
@Test
public void testRecordAudioPermission() throws Throwable {
final AudioRecord record =
new AudioRecord(MIC, 8000, CHANNEL_IN_MONO, ENCODING_PCM_16BIT, 4096);
try {
assertThat("audio record not initialized",
record.getState(), is(AudioRecord.STATE_INITIALIZED));
} finally {
record.release();
}
}
@Test
public void testReadPhoneNumbersPermission() throws Throwable {
final Context context = InstrumentationRegistry.getContext();
if (!context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
return;
}
try {
final TelephonyManager telephonyManager =
(TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
final String nmbr = telephonyManager.getLine1Number();
} catch (SecurityException e) {
fail("Permission not granted");
}
}
@Test
public void testAccessCoarseLocationPermission() {
final Context context = InstrumentationRegistry.getContext();
final LocationManager locationManager =
(LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
final Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_COARSE);
final String bestProvider = locationManager.getBestProvider(criteria, false);
try {
final String provider =
bestProvider == null ? LocationManager.NETWORK_PROVIDER : bestProvider;
locationManager.getLastKnownLocation(provider);
} catch (SecurityException e) {
fail("Permission not granted.");
}
}
@Test
public void testCameraPermission() throws Throwable {
final Context context = InstrumentationRegistry.getContext();
final CameraManager manager =
(CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
final String[] cameraIds = manager.getCameraIdList();
if (cameraIds.length == 0) {
return;
}
final CountDownLatch latch = new CountDownLatch(1);
final HandlerThread backgroundThread = new HandlerThread("camera_bg");
backgroundThread.start();
final CameraDevice.StateCallback callback = new CameraDevice.StateCallback() {
@Override
public void onOpened(CameraDevice camera) {
latch.countDown();
camera.close();
}
@Override
public void onDisconnected(CameraDevice camera) {
camera.close();
}
@Override
public void onError(CameraDevice camera, int error) {
camera.close();
}
};
manager.openCamera(cameraIds[0], callback, new Handler(backgroundThread.getLooper()));
assertThat(latch.await(1000, TimeUnit.MILLISECONDS), is(true));
}
@Test
public void testInternetPermission() throws Throwable {
final ConnectivityManager manager = (ConnectivityManager) InstrumentationRegistry.getContext()
.getSystemService(Context.CONNECTIVITY_SERVICE);
manager.reportNetworkConnectivity(null, false);
}
@Test
public void testVibratePermission() throws Throwable {
final Vibrator vibrator = (Vibrator) InstrumentationRegistry.getContext()
.getSystemService(Context.VIBRATOR_SERVICE);
final VibrationEffect effect =
VibrationEffect.createOneShot(100, VibrationEffect.DEFAULT_AMPLITUDE);
vibrator.vibrate(effect);
}
@Test
public void testWakeLockPermission() throws Throwable {
WakeLock wakeLock = null;
try {
final PowerManager powerManager = (PowerManager) InstrumentationRegistry.getContext()
.getSystemService(Context.POWER_SERVICE);
wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "test");
wakeLock.acquire();
}
finally {
if (wakeLock != null && wakeLock.isHeld()) {
wakeLock.release();
}
}
}
@Test
public void testGetSearchableInfo() throws Throwable {
final SearchManager searchManager = (SearchManager) InstrumentationRegistry.getContext()
.getSystemService(Context.SEARCH_SERVICE);
if (searchManager == null) {
return;
}
// get searchable info for a component in ourself; pass
{
final SearchableInfo info = searchManager.getSearchableInfo(
new ComponentName("com.android.cts.ephemeralapp1",
"com.android.cts.ephemeralapp1.EphemeralActivity"));
assertThat(info, is(notNullValue()));
assertThat(info.getSearchActivity(),
is(equalTo(
new ComponentName("com.android.cts.ephemeralapp1",
"com.android.cts.ephemeralapp1.EphemeralActivity"))));
}
// get searchable info for a component in a different instant application; fail
{
final SearchableInfo info = searchManager.getSearchableInfo(
new ComponentName("com.android.cts.ephemeralapp2",
"com.android.cts.ephemeralapp2.EphemeralActivity"));
assertThat(info, is(nullValue()));
}
// get searchable info for an exposed in a full application; pass
{
final SearchableInfo info = searchManager.getSearchableInfo(
new ComponentName("com.android.cts.normalapp",
"com.android.cts.normalapp.ExposedActivity"));
assertThat(info, is(notNullValue()));
assertThat(info.getSearchActivity(),
is(equalTo(
new ComponentName("com.android.cts.normalapp",
"com.android.cts.normalapp.ExposedActivity"))));
}
// get searchable info for an unexposed component in a full application; fail
{
final SearchableInfo info = searchManager.getSearchableInfo(
new ComponentName("com.android.cts.normalapp",
"com.android.cts.normalapp.NormalActivity"));
assertThat(info, is(nullValue()));
}
}
/** Returns {@code true} if the given filter handles all web URLs, regardless of host. */
private boolean handlesAllWebData(IntentFilter filter) {
return filter.hasCategory(Intent.CATEGORY_APP_BROWSER) ||
(handlesWebUris(filter) && filter.countDataAuthorities() == 0);
}
/** Returns {@code true} if the given filter handles at least one web URL. */
private boolean handlesWebUris(IntentFilter filter) {
// Require ACTION_VIEW, CATEGORY_BROWSEABLE, and at least one scheme
if (!filter.hasAction(Intent.ACTION_VIEW)
|| !filter.hasCategory(Intent.CATEGORY_BROWSABLE)
|| filter.countDataSchemes() == 0) {
return false;
}
// Now allow only the schemes "http" and "https"
final Iterator<String> schemesIterator = filter.schemesIterator();
while (schemesIterator.hasNext()) {
final String scheme = schemesIterator.next();
final boolean isWebScheme = "http".equals(scheme) || "https".equals(scheme);
if (isWebScheme) {
return true;
}
}
return false;
}
private TestResult getResult() {
final TestResult result;
try {
result = mResultQueue.poll(5, TimeUnit.SECONDS);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
if (result == null) {
throw new IllegalStateException("Activity didn't receive a Result in 5 seconds");
}
return result;
}
private static void grantInstantAppForegroundServicePermission() throws IOException {
InstrumentationRegistry.getInstrumentation().getUiAutomation().grantRuntimePermission(
InstrumentationRegistry.getContext().getPackageName(),
android.Manifest.permission.INSTANT_APP_FOREGROUND_SERVICE);
}
private static Intent makeIntent(String action, String category, String mimeType) {
Intent intent = new Intent(action);
if (category != null) {
intent.addCategory(category);
}
if (mimeType != null) {
intent.setType(mimeType);
}
return intent;
}
private static class ActivityBroadcastReceiver extends BroadcastReceiver {
private final SynchronousQueue<TestResult> mQueue;
public ActivityBroadcastReceiver(SynchronousQueue<TestResult> queue) {
mQueue = queue;
}
@Override
public void onReceive(Context context, Intent intent) {
try {
mQueue.offer(intent.getParcelableExtra(TestResult.EXTRA_TEST_RESULT),
5, TimeUnit.SECONDS);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
private static class TestServiceConnection implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
}
}