1 /*
2  * Copyright (C) 2018 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 package android.contentcaptureservice.cts;
17 
18 import static android.content.Context.CONTENT_CAPTURE_MANAGER_SERVICE;
19 import static android.contentcaptureservice.cts.Helper.MY_PACKAGE;
20 import static android.contentcaptureservice.cts.Helper.resetService;
21 import static android.contentcaptureservice.cts.Helper.sContext;
22 import static android.contentcaptureservice.cts.Helper.sUserSettings;
23 import static android.contentcaptureservice.cts.Helper.setService;
24 import static android.contentcaptureservice.cts.Helper.toSet;
25 import static android.provider.Settings.Secure.CONTENT_CAPTURE_ENABLED;
26 
27 import static com.android.compatibility.common.util.ShellUtils.runShellCommand;
28 
29 import android.content.ComponentName;
30 import android.content.ContentCaptureOptions;
31 import android.contentcaptureservice.cts.CtsContentCaptureService.ServiceWatcher;
32 import android.provider.DeviceConfig;
33 import android.util.Log;
34 import android.util.Pair;
35 import android.view.contentcapture.ContentCaptureManager;
36 
37 import androidx.annotation.NonNull;
38 import androidx.annotation.Nullable;
39 import androidx.test.ext.junit.runners.AndroidJUnit4;
40 
41 import com.android.compatibility.common.util.DeviceConfigStateChangerRule;
42 import com.android.compatibility.common.util.DeviceConfigStateManager;
43 import com.android.compatibility.common.util.RequiredServiceRule;
44 import com.android.compatibility.common.util.SafeCleanerRule;
45 import com.android.compatibility.common.util.SettingsStateChangerRule;
46 
47 import org.junit.After;
48 import org.junit.AfterClass;
49 import org.junit.Before;
50 import org.junit.BeforeClass;
51 import org.junit.Rule;
52 import org.junit.rules.RuleChain;
53 import org.junit.rules.TestRule;
54 import org.junit.runner.RunWith;
55 import org.junit.runners.model.Statement;
56 
57 import java.util.Set;
58 
59 /**
60  * Base class for all (or most :-) integration tests in this CTS suite.
61  */
62 @RunWith(AndroidJUnit4.class)
63 public abstract class AbstractContentCaptureIntegrationTest {
64 
65     private static final String TAG = AbstractContentCaptureIntegrationTest.class.getSimpleName();
66 
67     protected static final DeviceConfigStateManager sKillSwitchManager =
68             new DeviceConfigStateManager(sContext, DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
69             ContentCaptureManager.DEVICE_CONFIG_PROPERTY_SERVICE_EXPLICITLY_ENABLED);
70 
71     protected final String mTag = getClass().getSimpleName();
72 
73     private final RequiredServiceRule mRequiredServiceRule =
74             new RequiredServiceRule(CONTENT_CAPTURE_MANAGER_SERVICE);
75 
76     private final DeviceConfigStateChangerRule mVerboseLoggingRule =
77             new DeviceConfigStateChangerRule(
78             sContext, DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
79             ContentCaptureManager.DEVICE_CONFIG_PROPERTY_LOGGING_LEVEL,
80             Integer.toString(ContentCaptureManager.LOGGING_LEVEL_VERBOSE));
81 
82     private final ContentCaptureLoggingTestRule mLoggingRule = new ContentCaptureLoggingTestRule();
83 
84     /**
85      * Watcher set on {@link #enableService()} and used to wait until it's gone after the test
86      * finishes.
87      */
88     private ServiceWatcher mServiceWatcher;
89 
90     protected final SafeCleanerRule mSafeCleanerRule = new SafeCleanerRule()
91             .setDumper(mLoggingRule)
92             .add(() -> {
93                 return CtsContentCaptureService.getExceptions();
94             });
95 
96     private final TestRule mServiceDisablerRule = (base, description) -> {
97         return new Statement() {
98             @Override
99             public void evaluate() throws Throwable {
100                 try {
101                     base.evaluate();
102                 } finally {
103                     Log.v(mTag, "@mServiceDisablerRule: safelyDisableService()");
104                     safelyDisableService();
105                 }
106             }
107         };
108     };
109 
safelyDisableService()110     private void safelyDisableService() {
111         try {
112             resetService();
113 
114             if (mServiceWatcher != null) {
115                 mServiceWatcher.waitOnDestroy();
116             }
117         } catch (Throwable t) {
118             Log.e(TAG, "error disabling service", t);
119         }
120     }
121 
122     private final DeviceConfigStateChangerRule mKillSwitchKillerRule =
123             new DeviceConfigStateChangerRule(sKillSwitchManager, "true");
124 
125     private final SettingsStateChangerRule mFeatureEnablerRule = new SettingsStateChangerRule(
126             sContext, CONTENT_CAPTURE_ENABLED, "1");
127 
128     @Rule
129     public final RuleChain mLookAllTheseRules = RuleChain
130             // mRequiredServiceRule should be first so the test can be skipped right away
131             .outerRule(mRequiredServiceRule)
132 
133             // service must be disable at the last step, otherwise it's contents are not dump in
134             // case of error
135             .around(mServiceDisablerRule)
136 
137             // log everything
138             .around(mVerboseLoggingRule)
139 
140             // enable it as soon as possible, as it have to wait for the listener
141             .around(mKillSwitchKillerRule)
142             .around(mFeatureEnablerRule)
143 
144             // mLoggingRule wraps the test but doesn't interfere with it
145             .around(mLoggingRule)
146 
147             // mSafeCleanerRule will catch errors
148             .around(mSafeCleanerRule)
149 
150             // Finally, let subclasses set their own rule
151             .around(getMainTestRule());
152 
153     /**
154      * Hack to make sure ContentCapture is available for the CTS test package.
155      *
156      * <p>It must be set here because when the application starts it queries the server, at which
157      * point our service is not set yet.
158      */
159     // TODO: remove this hack if we ever split the CTS module in multiple APKs
160     @BeforeClass
whitelistSelf()161     public static void whitelistSelf() {
162         final ContentCaptureOptions options = ContentCaptureOptions.forWhitelistingItself();
163         Log.v(TAG, "@BeforeClass: whitelistSelf(): options=" + options);
164         sContext.getApplicationContext().setContentCaptureOptions(options);
165     }
166 
167     @AfterClass
unWhitelistSelf()168     public static void unWhitelistSelf() {
169         Log.v(TAG, "@afterClass: unWhitelistSelf()");
170         sContext.getApplicationContext().setContentCaptureOptions(null);
171     }
172 
173     @BeforeClass
disableDefaultService()174     public static void disableDefaultService() {
175         Log.v(TAG, "@BeforeClass: disableDefaultService()");
176         Helper.setDefaultServiceEnabled(false);
177     }
178 
179     @AfterClass
enableDefaultService()180     public static void enableDefaultService() {
181         Log.v(TAG, "@AfterClass: enableDefaultService()");
182         Helper.setDefaultServiceEnabled(true);
183     }
184 
185     @Before
prepareDevice()186     public void prepareDevice() throws Exception {
187         Log.v(mTag, "@Before: prepareDevice()");
188 
189         // Unlock screen.
190         runShellCommand("input keyevent KEYCODE_WAKEUP");
191 
192         // Dismiss keyguard, in case it's set as "Swipe to unlock".
193         runShellCommand("wm dismiss-keyguard");
194 
195         // Collapse notifications.
196         runShellCommand("cmd statusbar collapse");
197     }
198 
199     @Before
clearState()200     public void clearState() {
201         Log.v(mTag, "@Before: clearState()");
202         CtsContentCaptureService.resetStaticState();
203     }
204 
205     @After
clearServiceWatcher()206     public void clearServiceWatcher() {
207         Log.v(mTag, "@After: clearServiceWatcher()");
208         CtsContentCaptureService.clearServiceWatcher();
209     }
210 
211     @Nullable
setFeatureEnabledBySettings(@ullable boolean enabled)212     public static void setFeatureEnabledBySettings(@Nullable boolean enabled) {
213         sUserSettings.syncSet(CONTENT_CAPTURE_ENABLED, enabled ? "1" : "0");
214     }
215 
216     /**
217      * Sets {@link CtsContentCaptureService} as the service for the current user and waits until
218      * its created, then allowlist the CTS test package.
219      */
enableService()220     public CtsContentCaptureService enableService() throws InterruptedException {
221         return enableService(toSet(MY_PACKAGE), /* whitelistedComponents= */ null);
222     }
223 
enableService(@ullable Set<String> whitelistedPackages, @Nullable Set<ComponentName> whitelistedComponents)224     public CtsContentCaptureService enableService(@Nullable Set<String> whitelistedPackages,
225             @Nullable Set<ComponentName> whitelistedComponents) throws InterruptedException {
226         return enableService(new Pair<>(whitelistedPackages, whitelistedComponents));
227     }
228 
enableService( @ullable Pair<Set<String>, Set<ComponentName>> whitelist)229     public CtsContentCaptureService enableService(
230             @Nullable Pair<Set<String>, Set<ComponentName>> whitelist) throws InterruptedException {
231         if (mServiceWatcher != null) {
232             throw new IllegalStateException("There Can Be Only One!");
233         }
234         mServiceWatcher = CtsContentCaptureService.setServiceWatcher();
235         setService(CtsContentCaptureService.SERVICE_NAME);
236 
237         mServiceWatcher.whitelist(whitelist);
238 
239         return mServiceWatcher.waitOnCreate();
240     }
241 
242     /**
243      * Gets the test-specific {@link Rule}.
244      */
245     @NonNull
getMainTestRule()246     protected abstract TestRule getMainTestRule();
247 }
248