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 package android.view.inputmethod.ctstestapp;
17 
18 import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
19 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN;
20 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
21 
22 import android.app.Activity;
23 import android.app.AlertDialog;
24 import android.content.BroadcastReceiver;
25 import android.content.Context;
26 import android.content.Intent;
27 import android.content.IntentFilter;
28 import android.net.Uri;
29 import android.os.Bundle;
30 import android.os.Handler;
31 import android.os.Looper;
32 import android.os.RemoteCallback;
33 import android.view.Gravity;
34 import android.view.inputmethod.EditorInfo;
35 import android.view.inputmethod.InputConnection;
36 import android.view.inputmethod.InputMethodManager;
37 import android.view.inputmethod.cts.util.MockTestActivityUtil;
38 import android.widget.EditText;
39 import android.widget.LinearLayout;
40 import android.widget.TextView;
41 
42 import androidx.annotation.Nullable;
43 
44 /**
45  * A test {@link Activity} that automatically shows the input method.
46  */
47 public final class MainActivity extends Activity {
48 
49     private AlertDialog mDialog;
50     private EditText mEditor;
51     private final Handler mHandler = new Handler(Looper.myLooper());
52 
53     private BroadcastReceiver mBroadcastReceiver;
54 
55     @Nullable
getStringIntentExtra(String key)56     private String getStringIntentExtra(String key) {
57         if (getPackageManager().isInstantApp()) {
58             final Uri uri = getIntent().getData();
59             if (uri == null || !uri.isHierarchical()) {
60                 return null;
61             }
62             return uri.getQueryParameter(key);
63         }
64         return getIntent().getStringExtra(key);
65     }
66 
getIntegerIntentExtra(String key)67     private Integer getIntegerIntentExtra(String key) {
68         String value = getIntent().getStringExtra(key);
69         if (value != null) {
70             return Integer.parseInt(value);
71         }
72         return null;
73     }
74 
getBooleanIntentExtra(String key)75     private boolean getBooleanIntentExtra(String key) {
76         if (getPackageManager().isInstantApp()) {
77             final Uri uri = getIntent().getData();
78             if (uri == null || !uri.isHierarchical()) {
79                 return false;
80             }
81             return uri.getBooleanQueryParameter(key, false);
82         }
83         return getIntent().getBooleanExtra(key, false) || "true".equals(
84                 getIntent().getStringExtra(key));
85     }
86 
87     @Override
onCreate(Bundle savedInstanceState)88     protected void onCreate(Bundle savedInstanceState) {
89         super.onCreate(savedInstanceState);
90         final LinearLayout layout = new LinearLayout(this);
91         layout.setOrientation(LinearLayout.VERTICAL);
92         final boolean needShowDialog =
93                 getBooleanIntentExtra(MockTestActivityUtil.EXTRA_KEY_SHOW_DIALOG);
94 
95         if (needShowDialog) {
96             layout.setOrientation(LinearLayout.VERTICAL);
97             layout.setGravity(Gravity.BOTTOM);
98             getWindow().setSoftInputMode(SOFT_INPUT_ADJUST_RESIZE);
99 
100             final TextView textView = new TextView(this);
101             textView.setText("This is DialogActivity");
102             layout.addView(textView);
103 
104             mDialog = new AlertDialog.Builder(this).setView(new LinearLayout(this)).create();
105             mDialog.getWindow().addFlags(FLAG_ALT_FOCUSABLE_IM);
106             mDialog.getWindow().setSoftInputMode(SOFT_INPUT_ADJUST_PAN);
107             mDialog.show();
108         } else {
109             RemoteCallback remoteCallback = getIntent().getParcelableExtra(
110                     MockTestActivityUtil.EXTRA_ON_CREATE_INPUT_CONNECTION_CALLBACK,
111                     RemoteCallback.class);
112             String sessionId = getIntent().getStringExtra(
113                     MockTestActivityUtil.EXTRA_ON_CREATE_USER_HANDLE_SESSION_ID);
114             if (remoteCallback == null || sessionId == null) {
115                 mEditor = new EditText(this);
116             } else {
117                 mEditor = new EditText(this) {
118                     @Override
119                     public InputConnection onCreateInputConnection(EditorInfo editorInfo) {
120                         final InputConnection original = super.onCreateInputConnection(editorInfo);
121                         if (editorInfo.extras == null) {
122                             editorInfo.extras = new Bundle();
123                         }
124                         editorInfo.extras.putString(
125                                 ReplyReceivingInputConnection
126                                         .EDITOR_INFO_KEY_REPLY_USER_HANDLE_SESSION_ID,
127                                 sessionId);
128                         return new ReplyReceivingInputConnection(original, sessionId,
129                                 remoteCallback);
130                     }
131                 };
132             }
133             mEditor.setHint("editText");
134             final String privateImeOptions =
135                     getStringIntentExtra(MockTestActivityUtil.EXTRA_KEY_PRIVATE_IME_OPTIONS);
136             if (privateImeOptions != null) {
137                 mEditor.setPrivateImeOptions(privateImeOptions);
138             }
139             if (getBooleanIntentExtra(MockTestActivityUtil.EXTRA_HANDWRITING_DELEGATE)) {
140                 mEditor.setIsHandwritingDelegate(true);
141                 mEditor.setAllowedHandwritingDelegatorPackage("android.view.inputmethod.cts");
142             }
143             if (getBooleanIntentExtra(
144                     MockTestActivityUtil.EXTRA_HOME_HANDWRITING_DELEGATOR_ALLOWED)) {
145                 mEditor.setHandwritingDelegateFlags(
146                         InputMethodManager.HANDWRITING_DELEGATE_FLAG_HOME_DELEGATOR_ALLOWED);
147             }
148             Integer softInputMode = getIntegerIntentExtra(
149                     MockTestActivityUtil.EXTRA_SOFT_INPUT_MODE);
150             if (softInputMode != null) {
151                 getWindow().setSoftInputMode(softInputMode);
152             }
153             mEditor.requestFocus();
154             layout.addView(mEditor);
155         }
156 
157         layout.setFitsSystemWindows(true);
158         setContentView(layout);
159     }
160 
161     @Override
onStart()162     protected void onStart() {
163         super.onStart();
164         mBroadcastReceiver = new BroadcastReceiver() {
165             @Override
166             public void onReceive(Context context, Intent intent) {
167                 final Bundle extras = intent.getExtras();
168                 if (extras == null) {
169                     return;
170                 }
171 
172                 if (extras.containsKey(MockTestActivityUtil.EXTRA_SHOW_SOFT_INPUT)) {
173                     getSystemService(InputMethodManager.class).showSoftInput(mEditor, 0);
174                 }
175 
176                 if (extras.getBoolean(MockTestActivityUtil.EXTRA_DISMISS_DIALOG, false)) {
177                     if (mDialog != null) {
178                         mDialog.dismiss();
179                         mDialog = null;
180                     }
181                     mHandler.postDelayed(() -> finish(), 100);
182                 }
183             }
184         };
185         registerReceiver(mBroadcastReceiver, new IntentFilter(MockTestActivityUtil.ACTION_TRIGGER),
186                 Context.RECEIVER_EXPORTED);
187     }
188 
189     @Override
onStop()190     protected void onStop() {
191         super.onStop();
192         if (mBroadcastReceiver != null) {
193             unregisterReceiver(mBroadcastReceiver);
194             mBroadcastReceiver = null;
195         }
196     }
197 }
198