• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 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.documentclient;
18 
19 import static com.android.compatibility.common.util.SystemUtil.runShellCommand;
20 
21 import android.app.Activity;
22 import android.content.ContentResolver;
23 import android.content.Intent;
24 import android.content.pm.PackageManager;
25 import android.content.pm.ResolveInfo;
26 import android.content.res.AssetFileDescriptor;
27 import android.content.res.AssetFileDescriptor.AutoCloseInputStream;
28 import android.database.Cursor;
29 import android.net.Uri;
30 import android.test.InstrumentationTestCase;
31 import android.text.format.DateUtils;
32 import android.util.Log;
33 import android.view.MotionEvent;
34 
35 import androidx.test.uiautomator.Configurator;
36 import androidx.test.uiautomator.UiDevice;
37 
38 import com.android.cts.documentclient.MyActivity.Result;
39 
40 import java.io.ByteArrayOutputStream;
41 import java.io.IOException;
42 import java.io.InputStream;
43 import java.io.OutputStream;
44 
45 /**
46  * Base class for DocumentsUI test cases.
47  */
48 abstract class DocumentsClientTestCase extends InstrumentationTestCase {
49     protected static final long TIMEOUT = 30 * DateUtils.SECOND_IN_MILLIS;
50     protected static final int REQUEST_CODE = 42;
51 
52     static final String PROVIDER_PACKAGE = "com.android.cts.documentprovider";
53 
54     private static final String TAG = "DocumentsClientTestCase";
55 
56     protected UiDevice mDevice;
57     protected MyActivity mActivity;
58 
59     private String mDocumentsUiPackageId;
60 
61     private static final String COMPONENT_NAME_DUMMY_IME = "com.android.cts.dummyime/.CtsDummyIme";
62 
63     @Override
setUp()64     public void setUp() throws Exception {
65         if (!supportedHardware()) return;
66         super.setUp();
67 
68         final PackageManager pm = getInstrumentation().getContext().getPackageManager();
69 
70         final Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
71         intent.addCategory(Intent.CATEGORY_OPENABLE);
72         intent.setType("*/*");
73         final ResolveInfo ri = pm.resolveActivity(intent, 0);
74         mDocumentsUiPackageId = ri.activityInfo.packageName;
75 
76 
77         // Wake up the device and dismiss the keyguard before the test starts.
78         executeShellCommand("input keyevent KEYCODE_WAKEUP");
79         executeShellCommand("wm dismiss-keyguard");
80 
81         Configurator.getInstance().setToolType(MotionEvent.TOOL_TYPE_FINGER);
82 
83         // Disable IME's to avoid virtual keyboards from showing up. Occasionally IME draws some UI
84         // controls out of its boundary for some first time setup that obscures the text edit and/or
85         // save/select button. This will constantly fail some of our tests.
86         enableDummyIme();
87 
88         mDevice = UiDevice.getInstance(getInstrumentation());
89         mActivity = launchActivity(getInstrumentation().getTargetContext().getPackageName(),
90                 MyActivity.class, null);
91         mDevice.waitForIdle();
92     }
93 
94     @Override
tearDown()95     public void tearDown() throws Exception {
96         if (!supportedHardware()) return;
97         super.tearDown();
98         mActivity.finish();
99 
100         executeShellCommand("ime reset");
101     }
102 
getDocumentsUiPackageId()103     protected String getDocumentsUiPackageId() {
104         return mDocumentsUiPackageId;
105     }
106 
getColumn(Uri uri, String column)107     protected String getColumn(Uri uri, String column) {
108         final ContentResolver resolver = getInstrumentation().getContext().getContentResolver();
109         final Cursor cursor = resolver.query(uri, new String[] { column }, null, null, null);
110         try {
111             assertTrue(cursor.moveToFirst());
112             return cursor.getString(0);
113         } finally {
114             cursor.close();
115         }
116     }
117 
readFully(Uri uri)118     protected byte[] readFully(Uri uri) throws IOException {
119         final InputStream in = getInstrumentation().getContext().getContentResolver()
120                 .openInputStream(uri);
121         return readFully(in);
122     }
123 
readTypedFully(Uri uri, String mimeType)124     protected byte[] readTypedFully(Uri uri, String mimeType) throws IOException {
125         final AssetFileDescriptor descriptor =
126                 getInstrumentation().getContext().getContentResolver()
127                         .openTypedAssetFileDescriptor(uri, mimeType, null, null);
128         try (AutoCloseInputStream in = new AutoCloseInputStream(descriptor)) {
129             return readFully(in);
130         }
131     }
132 
readFully(InputStream in)133     protected byte[] readFully(InputStream in) throws IOException {
134         try {
135             ByteArrayOutputStream bytes = new ByteArrayOutputStream();
136             byte[] buffer = new byte[1024];
137             int count;
138             while ((count = in.read(buffer)) != -1) {
139                 bytes.write(buffer, 0, count);
140             }
141             return bytes.toByteArray();
142         } finally {
143             in.close();
144         }
145     }
146 
writeFully(Uri uri, byte[] data)147     protected void writeFully(Uri uri, byte[] data) throws IOException {
148         OutputStream out = getInstrumentation().getContext().getContentResolver()
149                 .openOutputStream(uri);
150         try {
151             out.write(data);
152         } finally {
153             out.close();
154         }
155     }
156 
supportedHardware()157     protected boolean supportedHardware() {
158         final PackageManager pm = getInstrumentation().getContext().getPackageManager();
159         if (pm.hasSystemFeature("android.hardware.type.television")
160                 || pm.hasSystemFeature("android.hardware.type.watch")
161                 || pm.hasSystemFeature("android.hardware.type.automotive")) {
162             return false;
163         }
164         return true;
165     }
166 
supportedHardwareForScopedDirectoryAccess()167     protected boolean supportedHardwareForScopedDirectoryAccess() {
168         final PackageManager pm = getInstrumentation().getContext().getPackageManager();
169         if (pm.hasSystemFeature("android.hardware.type.television")
170                 || pm.hasSystemFeature("android.hardware.type.watch")
171                 || pm.hasSystemFeature("android.hardware.type.automotive")) {
172             return false;
173         }
174         return true;
175     }
176 
isTelevision()177     protected boolean isTelevision() {
178         final PackageManager pm = getInstrumentation().getContext().getPackageManager();
179         return pm.hasSystemFeature("android.hardware.type.television");
180     }
181 
assertActivityFailed()182     protected void assertActivityFailed() {
183         final Result result = mActivity.getResult();
184         assertEquals(REQUEST_CODE, result.requestCode);
185         assertEquals(Activity.RESULT_CANCELED, result.resultCode);
186         assertNull(result.data);
187     }
188 
assertActivitySucceeded(String prefix)189     protected Intent assertActivitySucceeded(String prefix) {
190         final Result result = mActivity.getResult();
191         assertEquals(prefix + ": invalid request code", REQUEST_CODE, result.requestCode);
192         assertEquals(prefix + ": invalid result code", Activity.RESULT_OK, result.resultCode);
193         assertNotNull(prefix + ": null data on result", result.data);
194         return result.data;
195     }
196 
executeShellCommand(String command)197     protected String executeShellCommand(String command) throws Exception {
198         final String result = runShellCommand(getInstrumentation(), command).trim();
199         Log.d(TAG, "Command '" + command + "' returned '" + result + "'");
200         return result;
201     }
202 
203     /**
204      * Clears the DocumentsUI package data, unless test name ends on {@code DoNotClear}.
205      */
clearDocumentsUi()206     protected void clearDocumentsUi() throws Exception {
207         final String testName = getName();
208         if (testName.endsWith("DoNotClear")) {
209             Log.d(TAG, "Not clearing DocumentsUI due to test name: " + testName);
210             return;
211         }
212         executeShellCommand("pm clear " + getDocumentsUiPackageId());
213     }
214 
enableDummyIme()215     private void enableDummyIme() throws Exception {
216         String enableDummyCommand = "ime enable " + COMPONENT_NAME_DUMMY_IME;
217         executeShellCommand(enableDummyCommand);
218 
219         String setDummyCommand = "ime set " + COMPONENT_NAME_DUMMY_IME;
220         executeShellCommand(setDummyCommand);
221     }
222 }
223