1 /*
2  * Copyright (C) 2013 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 android.text.method.cts;
18 
19 import static android.provider.Settings.System.TEXT_AUTO_CAPS;
20 
21 import android.Manifest;
22 import android.app.AppOpsManager;
23 import android.app.Instrumentation;
24 import android.content.ContentResolver;
25 import android.content.Context;
26 import android.provider.Settings;
27 import android.text.cts.R;
28 import android.text.method.KeyListener;
29 import android.util.Log;
30 import android.view.KeyEvent;
31 import android.view.View;
32 import android.widget.EditText;
33 
34 import androidx.test.platform.app.InstrumentationRegistry;
35 import androidx.test.rule.ActivityTestRule;
36 
37 import com.android.compatibility.common.util.AdoptShellPermissionsRule;
38 import com.android.compatibility.common.util.CtsKeyEventUtil;
39 import com.android.compatibility.common.util.SystemUtil;
40 import com.android.compatibility.common.util.WindowUtil;
41 
42 import org.junit.Before;
43 import org.junit.Rule;
44 
45 import java.io.IOException;
46 
47 /**
48  * Base class for various KeyListener tests.
49  */
50 public abstract class KeyListenerTestCase {
51     private static final String TAG = "KeyListenerTestCase";
52 
53     protected KeyListenerCtsActivity mActivity;
54     protected Instrumentation mInstrumentation;
55     private Context mContext;
56     private CtsKeyEventUtil mCtsKeyEventUtil;
57     protected EditText mTextView;
58     private int mAutoCapSetting;
59 
60     @Rule(order = 0)
61     public AdoptShellPermissionsRule mAdoptShellPermissionsRule = new AdoptShellPermissionsRule(
62             InstrumentationRegistry.getInstrumentation().getUiAutomation(),
63             Manifest.permission.START_ACTIVITIES_FROM_SDK_SANDBOX);
64 
65     @Rule(order = 1)
66     public ActivityTestRule<KeyListenerCtsActivity> mActivityRule =
67             new ActivityTestRule<>(KeyListenerCtsActivity.class);
68 
69     @Before
setup()70     public void setup() throws IOException {
71         mInstrumentation = InstrumentationRegistry.getInstrumentation();
72         mContext = mInstrumentation.getTargetContext();
73         mCtsKeyEventUtil = new CtsKeyEventUtil(mContext);
74         mActivity = mActivityRule.getActivity();
75         WindowUtil.waitForFocus(mActivity);
76         mTextView = mActivity.findViewById(R.id.keylistener_textview);
77     }
78 
enableAutoCapSettings()79     protected void enableAutoCapSettings() throws IOException {
80         grantWriteSettingsPermission();
81         final Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
82         final Context context = instrumentation.getContext();
83         instrumentation.runOnMainSync(() -> {
84             final ContentResolver resolver = context.getContentResolver();
85             mAutoCapSetting = Settings.System.getInt(resolver, TEXT_AUTO_CAPS, 1);
86             try {
87                 Settings.System.putInt(resolver, TEXT_AUTO_CAPS, 1);
88             } catch (SecurityException e) {
89                 Log.e(TAG, "Cannot set TEXT_AUTO_CAPS to 1", e);
90                 // ignore
91             }
92         });
93         instrumentation.waitForIdleSync();
94     }
95 
resetAutoCapSettings()96     protected void resetAutoCapSettings() throws IOException {
97         grantWriteSettingsPermission();
98         final Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
99         final Context context = instrumentation.getContext();
100         instrumentation.runOnMainSync(() -> {
101             final ContentResolver resolver = context.getContentResolver();
102             try {
103                 Settings.System.putInt(resolver, TEXT_AUTO_CAPS, mAutoCapSetting);
104             } catch (SecurityException e) {
105                 Log.e(TAG, "Cannot set TEXT_AUTO_CAPS to previous value", e);
106                 // ignore
107             }
108         });
109         instrumentation.waitForIdleSync();
110     }
111 
112     /**
113      * Synchronously sets mTextView's key listener on the UI thread.
114      */
setKeyListenerSync(final KeyListener keyListener)115     protected void setKeyListenerSync(final KeyListener keyListener) {
116         mInstrumentation.runOnMainSync(() -> mTextView.setKeyListener(keyListener));
117         mInstrumentation.waitForIdleSync();
118     }
119 
getKey(int keycode, int metaState)120     protected static KeyEvent getKey(int keycode, int metaState) {
121         long currentTime = System.currentTimeMillis();
122         return new KeyEvent(currentTime, currentTime, KeyEvent.ACTION_DOWN, keycode,
123                 0 /* repeat */, metaState);
124     }
125 
grantWriteSettingsPermission()126     private void grantWriteSettingsPermission() throws IOException {
127         SystemUtil.runShellCommand(InstrumentationRegistry.getInstrumentation(),
128                 "appops set --user " + mContext.getUser().getIdentifier()
129                 + " " + mActivity.getPackageName()
130                 + " " + AppOpsManager.OPSTR_WRITE_SETTINGS + " allow");
131     }
132 
sendKeys(View targetView, int...keys)133     protected final void sendKeys(View targetView, int...keys) {
134         mCtsKeyEventUtil.sendKeys(mInstrumentation, targetView, keys);
135     }
136 
sendKeys(View targetView, String keysSequence)137     protected final void sendKeys(View targetView, String keysSequence) {
138         mCtsKeyEventUtil.sendKeys(mInstrumentation, targetView, keysSequence);
139     }
140 
sendKey(View targetView, KeyEvent event)141     protected final void sendKey(View targetView, KeyEvent event) {
142         mCtsKeyEventUtil.sendKey(mInstrumentation, targetView, event);
143     }
144 
sendKeyDownUp(View targetView, int key)145     protected final void sendKeyDownUp(View targetView, int key) {
146         mCtsKeyEventUtil.sendKeyDownUp(mInstrumentation, targetView, key);
147     }
148 
sendKeyWhileHoldingModifier(View targetView, int keyCodeToSend, int modifierKeyCodeToHold)149     protected void sendKeyWhileHoldingModifier(View targetView, int keyCodeToSend,
150             int modifierKeyCodeToHold) {
151         mCtsKeyEventUtil.sendKeyWhileHoldingModifier(mInstrumentation, targetView, keyCodeToSend,
152                 modifierKeyCodeToHold);
153     }
154 
sendString(View targetView, String text)155     protected final void sendString(View targetView, String text) {
156         mCtsKeyEventUtil.sendString(mInstrumentation, targetView, text);
157     }
158 }
159