1 /* 2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.cts.appcompat; 18 19 import static com.google.common.truth.Truth.assertThat; 20 import static com.google.common.truth.Truth.assertWithMessage; 21 22 import android.compat.cts.Change; 23 import android.compat.cts.CompatChangeGatingTestCase; 24 25 import com.google.common.collect.ImmutableSet; 26 27 import org.w3c.dom.Document; 28 import org.w3c.dom.Element; 29 import org.w3c.dom.NodeList; 30 31 import java.util.ArrayList; 32 import java.util.Iterator; 33 import java.util.List; 34 import java.util.Set; 35 36 import javax.xml.parsers.DocumentBuilder; 37 import javax.xml.parsers.DocumentBuilderFactory; 38 39 public final class CompatChangesValidConfigTest extends CompatChangeGatingTestCase { 40 41 private static final long RESTRICT_STORAGE_ACCESS_FRAMEWORK = 141600225L; 42 private static final long SPLIT_AS_STREAM_RETURNS_SINGLE_EMPTY_STRING = 288845345L; 43 private static final String FEATURE_WATCH = "android.hardware.type.watch"; 44 45 private static final Set<String> OVERRIDES_ALLOWLIST = ImmutableSet.of( 46 // This change id will sometimes remain enabled if an instrumentation test fails. 47 "ALLOW_TEST_API_ACCESS" 48 ); 49 50 private static final Set<String> OVERRIDABLE_CHANGES = ImmutableSet.of( 51 "ALWAYS_SANDBOX_DISPLAY_APIS", 52 "CTS_SYSTEM_API_OVERRIDABLE_CHANGEID", 53 "DEFER_BOOT_COMPLETED_BROADCAST_CHANGE_ID", 54 "DOWNSCALED", 55 "DOWNSCALED_INVERSE", 56 "DOWNSCALE_30", 57 "DOWNSCALE_35", 58 "DOWNSCALE_40", 59 "DOWNSCALE_45", 60 "DOWNSCALE_50", 61 "DOWNSCALE_55", 62 "DOWNSCALE_60", 63 "DOWNSCALE_65", 64 "DOWNSCALE_70", 65 "DOWNSCALE_75", 66 "DOWNSCALE_80", 67 "DOWNSCALE_85", 68 "DOWNSCALE_90", 69 "DO_NOT_DOWNSCALE_TO_1080P_ON_TV", 70 "FGS_BG_START_RESTRICTION_CHANGE_ID", 71 "FGS_TYPE_DATA_SYNC_DEPRECATION_CHANGE_ID", 72 "FGS_TYPE_DATA_SYNC_DISABLED_CHANGE_ID", 73 "FGS_TYPE_NONE_DEPRECATION_CHANGE_ID", 74 "FGS_TYPE_NONE_DISABLED_CHANGE_ID", 75 "FGS_TYPE_PERMISSION_CHANGE_ID", 76 "FORCE_NON_RESIZE_APP", 77 "FORCE_RESIZE_APP", 78 "OVERRIDE_CAMERA_ROTATE_AND_CROP_DEFAULTS", 79 "OVERRIDE_CAMERA_RESIZABLE_AND_SDK_CHECK", 80 "OVERRIDE_CAMERA_ROTATE_AND_CROP", 81 "OVERRIDE_CAMERA_LANDSCAPE_TO_PORTRAIT", 82 "IGNORE_ALLOW_BACKUP_IN_D2D", 83 "IGNORE_FULL_BACKUP_CONTENT_IN_D2D", 84 "NEVER_SANDBOX_DISPLAY_APIS", 85 "OVERRIDE_MIN_ASPECT_RATIO", 86 "OVERRIDE_MIN_ASPECT_RATIO_EXCLUDE_PORTRAIT_FULLSCREEN", 87 "OVERRIDE_MIN_ASPECT_RATIO_PORTRAIT_ONLY", 88 "OVERRIDE_MIN_ASPECT_RATIO_LARGE", 89 "OVERRIDE_MIN_ASPECT_RATIO_MEDIUM", 90 "OVERRIDE_MIN_ASPECT_RATIO_TO_ALIGN_WITH_SPLIT_SCREEN", 91 "IMPLICIT_INTENTS_ONLY_MATCH_EXPORTED_COMPONENTS", 92 "BLOCK_MUTABLE_IMPLICIT_PENDING_INTENT", 93 "OVERRIDE_ENABLE_COMPAT_FAKE_FOCUS", 94 "OVERRIDE_UNDEFINED_ORIENTATION_TO_PORTRAIT", 95 "OVERRIDE_UNDEFINED_ORIENTATION_TO_NOSENSOR", 96 "OVERRIDE_LANDSCAPE_ORIENTATION_TO_REVERSE_LANDSCAPE", 97 "OVERRIDE_ANY_ORIENTATION", 98 "OVERRIDE_USE_DISPLAY_LANDSCAPE_NATURAL_ORIENTATION", 99 "OVERRIDE_ENABLE_COMPAT_IGNORE_REQUESTED_ORIENTATION", 100 "OVERRIDE_ORIENTATION_ONLY_FOR_CAMERA", 101 "OVERRIDE_CAMERA_COMPAT_DISABLE_FORCE_ROTATION", 102 "OVERRIDE_CAMERA_COMPAT_DISABLE_REFRESH", 103 "OVERRIDE_CAMERA_COMPAT_ENABLE_REFRESH_VIA_PAUSE", 104 "OVERRIDE_ENABLE_COMPAT_IGNORE_REQUESTED_ORIENTATION", 105 "OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED", 106 "OVERRIDE_RESPECT_REQUESTED_ORIENTATION", 107 "OVERRIDE_SANDBOX_VIEW_BOUNDS_APIS", 108 "DEFAULT_RESCIND_BAL_FG_PRIVILEGES_BOUND_SERVICE", 109 "DEFAULT_RESCIND_BAL_PRIVILEGES_FROM_PENDING_INTENT_SENDER", 110 "RETURN_DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_ADJUST_ONLY" 111 ); 112 113 /** 114 * Check that there are no overrides. 115 */ testNoOverrides()116 public void testNoOverrides() throws Exception { 117 for (Change c : getOnDeviceCompatConfig()) { 118 if (!OVERRIDES_ALLOWLIST.contains(c.changeName) && !c.overridable) { 119 assertWithMessage("Change should not have overrides: " + c) 120 .that(c.hasOverrides).isFalse(); 121 } 122 } 123 } 124 125 /** 126 * Check that only approved changes are overridable. 127 */ testOnlyAllowedlistedChangesAreOverridable()128 public void testOnlyAllowedlistedChangesAreOverridable() throws Exception { 129 for (Change c : getOnDeviceCompatConfig()) { 130 if (c.overridable) { 131 assertWithMessage("Please contact compat-team@google.com for approval") 132 .that(OVERRIDABLE_CHANGES).contains(c.changeName); 133 } 134 } 135 } 136 137 /** 138 * Check that the on device config contains all the expected change ids defined in the platform. 139 * The device may contain extra changes, but none may be removed. 140 */ testDeviceContainsExpectedConfig()141 public void testDeviceContainsExpectedConfig() throws Exception { 142 assertThat(getOnDeviceCompatConfig()).containsAtLeastElementsIn(getExpectedCompatConfig()); 143 } 144 145 146 /** 147 * Parse the expected (i.e. defined in platform) config xml. 148 */ getExpectedCompatConfig()149 private List<Change> getExpectedCompatConfig() throws Exception { 150 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 151 DocumentBuilder db = dbf.newDocumentBuilder(); 152 Document dom = db.parse(getClass().getResourceAsStream("/cts_all_compat_config.xml")); 153 Element root = dom.getDocumentElement(); 154 NodeList changeNodes = root.getElementsByTagName("compat-change"); 155 List<Change> changes = new ArrayList<>(); 156 for (int nodeIdx = 0; nodeIdx < changeNodes.getLength(); ++nodeIdx) { 157 Change change = Change.fromNode(changeNodes.item(nodeIdx)); 158 // Exclude logging only changes from the expected config. See b/155264388. 159 if (!change.loggingOnly) { 160 changes.add(change); 161 } 162 } 163 164 // RESTRICT_STORAGE_ACCESS_FRAMEWORK not supported on wear 165 if (getDevice().hasFeature(FEATURE_WATCH)) { 166 for (Iterator<Change> it = changes.iterator(); it.hasNext();) { 167 if (it.next().changeId == RESTRICT_STORAGE_ACCESS_FRAMEWORK) { 168 it.remove(); 169 } 170 } 171 } 172 173 // Exclude SPLIT_AS_STREAM_RETURNS_SINGLE_EMPTY_STRING 174 // This feature is enabled only from U for apps targeting SDK 34+, see b/288845345 175 changes.removeIf(c -> c.changeId == SPLIT_AS_STREAM_RETURNS_SINGLE_EMPTY_STRING); 176 177 return changes; 178 } 179 180 } 181