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