summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java116
-rw-r--r--services/core/java/com/android/server/pm/Settings.java10
-rw-r--r--tests/AutoVerify/app1/Android.bp11
-rw-r--r--tests/AutoVerify/app1/AndroidManifest.xml43
-rw-r--r--tests/AutoVerify/app1/res/values/strings.xml21
-rw-r--r--tests/AutoVerify/app1/src/com/android/test/autoverify/MainActivity.java15
-rw-r--r--tests/AutoVerify/app2/Android.bp11
-rw-r--r--tests/AutoVerify/app2/AndroidManifest.xml44
-rw-r--r--tests/AutoVerify/app2/res/values/strings.xml21
-rw-r--r--tests/AutoVerify/app2/src/com/android/test/autoverify/MainActivity.java15
-rw-r--r--tests/AutoVerify/app3/Android.bp11
-rw-r--r--tests/AutoVerify/app3/AndroidManifest.xml44
-rw-r--r--tests/AutoVerify/app3/res/values/strings.xml21
-rw-r--r--tests/AutoVerify/app3/src/com/android/test/autoverify/MainActivity.java15
-rw-r--r--tests/AutoVerify/app4/Android.bp11
-rw-r--r--tests/AutoVerify/app4/AndroidManifest.xml45
-rw-r--r--tests/AutoVerify/app4/res/values/strings.xml21
-rw-r--r--tests/AutoVerify/app4/src/com/android/test/autoverify/MainActivity.java15
18 files changed, 454 insertions, 36 deletions
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index e4b4bfd7e188..f0da25eaf10c 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -1346,13 +1346,6 @@ public class PackageManagerService extends IPackageManager.Stub
int updatedStatus = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
boolean needUpdate = false;
- if (DEBUG_DOMAIN_VERIFICATION) {
- Slog.d(TAG,
- "Updating IntentFilterVerificationInfo for package " + packageName
- + " verificationId:" + verificationId
- + " verified=" + verified);
- }
-
// In a success case, we promote from undefined or ASK to ALWAYS. This
// supports a flow where the app fails validation but then ships an updated
// APK that passes, and therefore deserves to be in ALWAYS.
@@ -17632,65 +17625,120 @@ public class PackageManagerService extends IPackageManager.Stub
+ " Activities needs verification ...");
int count = 0;
-
+ boolean handlesWebUris = false;
+ ArraySet<String> domains = new ArraySet<>();
+ final boolean previouslyVerified;
+ boolean hostSetExpanded = false;
+ boolean needToRunVerify = false;
synchronized (mLock) {
// If this is a new install and we see that we've already run verification for this
// package, we have nothing to do: it means the state was restored from backup.
- if (!replacing) {
- IntentFilterVerificationInfo ivi =
- mSettings.getIntentFilterVerificationLPr(packageName);
- if (ivi != null) {
- if (DEBUG_DOMAIN_VERIFICATION) {
- Slog.i(TAG, "Package " + packageName+ " already verified: status="
- + ivi.getStatusString());
- }
- return;
+ IntentFilterVerificationInfo ivi =
+ mSettings.getIntentFilterVerificationLPr(packageName);
+ previouslyVerified = (ivi != null);
+ if (!replacing && previouslyVerified) {
+ if (DEBUG_DOMAIN_VERIFICATION) {
+ Slog.i(TAG, "Package " + packageName + " already verified: status="
+ + ivi.getStatusString());
}
+ return;
+ }
+
+ if (DEBUG_DOMAIN_VERIFICATION) {
+ Slog.i(TAG, " Previous verified hosts: "
+ + (ivi == null ? "[none]" : ivi.getDomainsString()));
}
- // If any filters need to be verified, then all need to be.
- boolean needToVerify = false;
+ // If any filters need to be verified, then all need to be. In addition, we need to
+ // know whether an updating app has any web navigation intent filters, to re-
+ // examine handling policy even if not re-verifying.
+ final boolean needsVerification = needsNetworkVerificationLPr(packageName);
for (ParsedActivity a : activities) {
for (ParsedIntentInfo filter : a.getIntents()) {
- if (filter.needsVerification()
- && needsNetworkVerificationLPr(a.getPackageName())) {
+ if (filter.handlesWebUris(true)) {
+ handlesWebUris = true;
+ }
+ if (needsVerification && filter.needsVerification()) {
if (DEBUG_DOMAIN_VERIFICATION) {
- Slog.d(TAG,
- "Intent filter needs verification, so processing all filters");
+ Slog.d(TAG, "autoVerify requested, processing all filters");
}
- needToVerify = true;
+ needToRunVerify = true;
+ // It's safe to break out here because filter.needsVerification()
+ // can only be true if filter.handlesWebUris(true) returned true, so
+ // we've already noted that.
break;
}
}
}
- if (needToVerify) {
- final boolean needsVerification = needsNetworkVerificationLPr(packageName);
+ // Compare the new set of recognized hosts if the app is either requesting
+ // autoVerify or has previously used autoVerify but no longer does.
+ if (needToRunVerify || previouslyVerified) {
final int verificationId = mIntentFilterVerificationToken++;
for (ParsedActivity a : activities) {
for (ParsedIntentInfo filter : a.getIntents()) {
// Run verification against hosts mentioned in any web-nav intent filter,
// even if the filter matches non-web schemes as well
- if (needsVerification && filter.handlesWebUris(false)) {
+ if (filter.handlesWebUris(false /*onlyWebSchemes*/)) {
if (DEBUG_DOMAIN_VERIFICATION) Slog.d(TAG,
"Verification needed for IntentFilter:" + filter.toString());
mIntentFilterVerifier.addOneIntentFilterVerification(
verifierUid, userId, verificationId, filter, packageName);
+ domains.addAll(filter.getHostsList());
count++;
}
}
}
}
+
+ if (DEBUG_DOMAIN_VERIFICATION) {
+ Slog.i(TAG, " Update published hosts: " + domains.toString());
+ }
+
+ // If we've previously verified this same host set (or a subset), we can trust that
+ // a current ALWAYS policy is still applicable. If this is the case, we're done.
+ // (If we aren't in ALWAYS, we want to reverify to allow for apps that had failing
+ // hosts in their intent filters, then pushed a new apk that removed them and now
+ // passes.)
+ //
+ // Cases:
+ // + still autoVerify (needToRunVerify):
+ // - preserve current state if all of: unexpanded, in always
+ // - otherwise rerun as usual (fall through)
+ // + no longer autoVerify (alreadyVerified && !needToRunVerify)
+ // - wipe verification history always
+ // - preserve current state if all of: unexpanded, in always
+ hostSetExpanded = !previouslyVerified
+ || (ivi != null && !ivi.getDomains().containsAll(domains));
+ final int currentPolicy =
+ mSettings.getIntentFilterVerificationStatusLPr(packageName, userId);
+ final boolean keepCurState = !hostSetExpanded
+ && currentPolicy == INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS;
+
+ if (needToRunVerify && keepCurState) {
+ if (DEBUG_DOMAIN_VERIFICATION) {
+ Slog.i(TAG, "Host set not expanding + ALWAYS -> no need to reverify");
+ }
+ ivi.setDomains(domains);
+ scheduleWriteSettingsLocked();
+ return;
+ } else if (previouslyVerified && !needToRunVerify) {
+ // Prior autoVerify state but not requesting it now. Clear autoVerify history,
+ // and preserve the always policy iff the host set is not expanding.
+ clearIntentFilterVerificationsLPw(packageName, userId, !keepCurState);
+ return;
+ }
}
- if (count > 0) {
+ if (needToRunVerify && count > 0) {
+ // app requested autoVerify and has at least one matching intent filter
if (DEBUG_DOMAIN_VERIFICATION) Slog.d(TAG, "Starting " + count
+ " IntentFilter verification" + (count > 1 ? "s" : "")
+ " for userId:" + userId);
mIntentFilterVerifier.startVerifications(userId);
} else {
if (DEBUG_DOMAIN_VERIFICATION) {
- Slog.d(TAG, "No filters or not all autoVerify for " + packageName);
+ Slog.d(TAG, "No web filters or no new host policy for " + packageName);
}
}
}
@@ -18395,7 +18443,7 @@ public class PackageManagerService extends IPackageManager.Stub
if ((flags & PackageManager.DELETE_KEEP_DATA) == 0) {
final SparseBooleanArray changedUsers = new SparseBooleanArray();
synchronized (mLock) {
- clearIntentFilterVerificationsLPw(deletedPs.name, UserHandle.USER_ALL);
+ clearIntentFilterVerificationsLPw(deletedPs.name, UserHandle.USER_ALL, true);
clearDefaultBrowserIfNeeded(packageName);
mSettings.mKeySetManagerService.removeAppKeySetDataLPw(packageName);
removedAppId = mSettings.removePackageLPw(packageName);
@@ -19488,13 +19536,14 @@ public class PackageManagerService extends IPackageManager.Stub
final int packageCount = mPackages.size();
for (int i = 0; i < packageCount; i++) {
AndroidPackage pkg = mPackages.valueAt(i);
- clearIntentFilterVerificationsLPw(pkg.getPackageName(), userId);
+ clearIntentFilterVerificationsLPw(pkg.getPackageName(), userId, true);
}
}
/** This method takes a specific user id as well as UserHandle.USER_ALL. */
@GuardedBy("mLock")
- void clearIntentFilterVerificationsLPw(String packageName, int userId) {
+ void clearIntentFilterVerificationsLPw(String packageName, int userId,
+ boolean alsoResetStatus) {
if (userId == UserHandle.USER_ALL) {
if (mSettings.removeIntentFilterVerificationLPw(packageName,
mUserManager.getUserIds())) {
@@ -19503,7 +19552,8 @@ public class PackageManagerService extends IPackageManager.Stub
}
}
} else {
- if (mSettings.removeIntentFilterVerificationLPw(packageName, userId)) {
+ if (mSettings.removeIntentFilterVerificationLPw(packageName, userId,
+ alsoResetStatus)) {
scheduleWritePackageRestrictionsLocked(userId);
}
}
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 53c057a58a15..44a61d895be5 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -1282,7 +1282,8 @@ public final class Settings {
return result;
}
- boolean removeIntentFilterVerificationLPw(String packageName, int userId) {
+ boolean removeIntentFilterVerificationLPw(String packageName, int userId,
+ boolean alsoResetStatus) {
PackageSetting ps = mPackages.get(packageName);
if (ps == null) {
if (DEBUG_DOMAIN_VERIFICATION) {
@@ -1290,14 +1291,17 @@ public final class Settings {
}
return false;
}
- ps.clearDomainVerificationStatusForUser(userId);
+ if (alsoResetStatus) {
+ ps.clearDomainVerificationStatusForUser(userId);
+ }
+ ps.setIntentFilterVerificationInfo(null);
return true;
}
boolean removeIntentFilterVerificationLPw(String packageName, int[] userIds) {
boolean result = false;
for (int userId : userIds) {
- result |= removeIntentFilterVerificationLPw(packageName, userId);
+ result |= removeIntentFilterVerificationLPw(packageName, userId, true);
}
return result;
}
diff --git a/tests/AutoVerify/app1/Android.bp b/tests/AutoVerify/app1/Android.bp
new file mode 100644
index 000000000000..548519fa653b
--- /dev/null
+++ b/tests/AutoVerify/app1/Android.bp
@@ -0,0 +1,11 @@
+android_app {
+ name: "AutoVerifyTest",
+ srcs: ["src/**/*.java"],
+ resource_dirs: ["res"],
+ platform_apis: true,
+ min_sdk_version: "26",
+ target_sdk_version: "26",
+ optimize: {
+ enabled: false,
+ },
+}
diff --git a/tests/AutoVerify/app1/AndroidManifest.xml b/tests/AutoVerify/app1/AndroidManifest.xml
new file mode 100644
index 000000000000..d9caad490d82
--- /dev/null
+++ b/tests/AutoVerify/app1/AndroidManifest.xml
@@ -0,0 +1,43 @@
+<?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.test.autoverify" >
+
+ <uses-sdk android:targetSdkVersion="26" />
+
+ <application
+ android:label="@string/app_name" >
+ <activity
+ android:name=".MainActivity"
+ android:label="@string/app_name" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+
+ <intent-filter android:autoVerify="true">
+ <action android:name="android.intent.action.VIEW" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.BROWSABLE" />
+ <data android:scheme="http" />
+ <data android:scheme="https" />
+ <data android:host="explicit.example.com" />
+ </intent-filter>
+ </activity>
+ </application>
+</manifest>
diff --git a/tests/AutoVerify/app1/res/values/strings.xml b/tests/AutoVerify/app1/res/values/strings.xml
new file mode 100644
index 000000000000..e234355041c6
--- /dev/null
+++ b/tests/AutoVerify/app1/res/values/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright 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.
+-->
+
+<resources>
+ <!-- app icon label, do not translate -->
+ <string name="app_name" translatable="false">AutoVerify Test</string>
+</resources>
diff --git a/tests/AutoVerify/app1/src/com/android/test/autoverify/MainActivity.java b/tests/AutoVerify/app1/src/com/android/test/autoverify/MainActivity.java
new file mode 100644
index 000000000000..09ef47212622
--- /dev/null
+++ b/tests/AutoVerify/app1/src/com/android/test/autoverify/MainActivity.java
@@ -0,0 +1,15 @@
+/*
+ * 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.
+ */
diff --git a/tests/AutoVerify/app2/Android.bp b/tests/AutoVerify/app2/Android.bp
new file mode 100644
index 000000000000..1c6c97bdf350
--- /dev/null
+++ b/tests/AutoVerify/app2/Android.bp
@@ -0,0 +1,11 @@
+android_app {
+ name: "AutoVerifyTest2",
+ srcs: ["src/**/*.java"],
+ resource_dirs: ["res"],
+ platform_apis: true,
+ min_sdk_version: "26",
+ target_sdk_version: "26",
+ optimize: {
+ enabled: false,
+ },
+}
diff --git a/tests/AutoVerify/app2/AndroidManifest.xml b/tests/AutoVerify/app2/AndroidManifest.xml
new file mode 100644
index 000000000000..a00807883cfc
--- /dev/null
+++ b/tests/AutoVerify/app2/AndroidManifest.xml
@@ -0,0 +1,44 @@
+<?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.test.autoverify" >
+
+ <uses-sdk android:targetSdkVersion="26" />
+
+ <application
+ android:label="@string/app_name" >
+ <activity
+ android:name=".MainActivity"
+ android:label="@string/app_name" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+
+ <intent-filter android:autoVerify="true">
+ <action android:name="android.intent.action.VIEW" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.BROWSABLE" />
+ <data android:scheme="http" />
+ <data android:scheme="https" />
+ <data android:host="explicit.example.com" />
+ <data android:host="*.wildcard.tld" />
+ </intent-filter>
+ </activity>
+ </application>
+</manifest>
diff --git a/tests/AutoVerify/app2/res/values/strings.xml b/tests/AutoVerify/app2/res/values/strings.xml
new file mode 100644
index 000000000000..e234355041c6
--- /dev/null
+++ b/tests/AutoVerify/app2/res/values/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright 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.
+-->
+
+<resources>
+ <!-- app icon label, do not translate -->
+ <string name="app_name" translatable="false">AutoVerify Test</string>
+</resources>
diff --git a/tests/AutoVerify/app2/src/com/android/test/autoverify/MainActivity.java b/tests/AutoVerify/app2/src/com/android/test/autoverify/MainActivity.java
new file mode 100644
index 000000000000..09ef47212622
--- /dev/null
+++ b/tests/AutoVerify/app2/src/com/android/test/autoverify/MainActivity.java
@@ -0,0 +1,15 @@
+/*
+ * 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.
+ */
diff --git a/tests/AutoVerify/app3/Android.bp b/tests/AutoVerify/app3/Android.bp
new file mode 100644
index 000000000000..70a2b77d1000
--- /dev/null
+++ b/tests/AutoVerify/app3/Android.bp
@@ -0,0 +1,11 @@
+android_app {
+ name: "AutoVerifyTest3",
+ srcs: ["src/**/*.java"],
+ resource_dirs: ["res"],
+ platform_apis: true,
+ min_sdk_version: "26",
+ target_sdk_version: "26",
+ optimize: {
+ enabled: false,
+ },
+}
diff --git a/tests/AutoVerify/app3/AndroidManifest.xml b/tests/AutoVerify/app3/AndroidManifest.xml
new file mode 100644
index 000000000000..efaabc9a38d3
--- /dev/null
+++ b/tests/AutoVerify/app3/AndroidManifest.xml
@@ -0,0 +1,44 @@
+<?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.test.autoverify" >
+
+ <uses-sdk android:targetSdkVersion="26" />
+
+ <application
+ android:label="@string/app_name" >
+ <activity
+ android:name=".MainActivity"
+ android:label="@string/app_name" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+
+ <!-- does not request autoVerify -->
+ <intent-filter>
+ <action android:name="android.intent.action.VIEW" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.BROWSABLE" />
+ <data android:scheme="http" />
+ <data android:scheme="https" />
+ <data android:host="explicit.example.com" />
+ </intent-filter>
+ </activity>
+ </application>
+</manifest>
diff --git a/tests/AutoVerify/app3/res/values/strings.xml b/tests/AutoVerify/app3/res/values/strings.xml
new file mode 100644
index 000000000000..e234355041c6
--- /dev/null
+++ b/tests/AutoVerify/app3/res/values/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright 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.
+-->
+
+<resources>
+ <!-- app icon label, do not translate -->
+ <string name="app_name" translatable="false">AutoVerify Test</string>
+</resources>
diff --git a/tests/AutoVerify/app3/src/com/android/test/autoverify/MainActivity.java b/tests/AutoVerify/app3/src/com/android/test/autoverify/MainActivity.java
new file mode 100644
index 000000000000..09ef47212622
--- /dev/null
+++ b/tests/AutoVerify/app3/src/com/android/test/autoverify/MainActivity.java
@@ -0,0 +1,15 @@
+/*
+ * 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.
+ */
diff --git a/tests/AutoVerify/app4/Android.bp b/tests/AutoVerify/app4/Android.bp
new file mode 100644
index 000000000000..fbdae1181a7a
--- /dev/null
+++ b/tests/AutoVerify/app4/Android.bp
@@ -0,0 +1,11 @@
+android_app {
+ name: "AutoVerifyTest4",
+ srcs: ["src/**/*.java"],
+ resource_dirs: ["res"],
+ platform_apis: true,
+ min_sdk_version: "26",
+ target_sdk_version: "26",
+ optimize: {
+ enabled: false,
+ },
+}
diff --git a/tests/AutoVerify/app4/AndroidManifest.xml b/tests/AutoVerify/app4/AndroidManifest.xml
new file mode 100644
index 000000000000..1c975f8336c9
--- /dev/null
+++ b/tests/AutoVerify/app4/AndroidManifest.xml
@@ -0,0 +1,45 @@
+<?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.test.autoverify" >
+
+ <uses-sdk android:targetSdkVersion="26" />
+
+ <application
+ android:label="@string/app_name" >
+ <activity
+ android:name=".MainActivity"
+ android:label="@string/app_name" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+
+ <!-- intentionally does not autoVerify -->
+ <intent-filter>
+ <action android:name="android.intent.action.VIEW" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.BROWSABLE" />
+ <data android:scheme="http" />
+ <data android:scheme="https" />
+ <data android:host="explicit.example.com" />
+ <data android:host="*.wildcard.tld" />
+ </intent-filter>
+ </activity>
+ </application>
+</manifest>
diff --git a/tests/AutoVerify/app4/res/values/strings.xml b/tests/AutoVerify/app4/res/values/strings.xml
new file mode 100644
index 000000000000..e234355041c6
--- /dev/null
+++ b/tests/AutoVerify/app4/res/values/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright 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.
+-->
+
+<resources>
+ <!-- app icon label, do not translate -->
+ <string name="app_name" translatable="false">AutoVerify Test</string>
+</resources>
diff --git a/tests/AutoVerify/app4/src/com/android/test/autoverify/MainActivity.java b/tests/AutoVerify/app4/src/com/android/test/autoverify/MainActivity.java
new file mode 100644
index 000000000000..09ef47212622
--- /dev/null
+++ b/tests/AutoVerify/app4/src/com/android/test/autoverify/MainActivity.java
@@ -0,0 +1,15 @@
+/*
+ * 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.
+ */