From 4b12569b61754780aae992931890ed2941e66256 Mon Sep 17 00:00:00 2001 From: Adrian Roos Date: Mon, 15 Feb 2021 16:38:14 +0000 Subject: [PATCH 1/7] Fix broken liblatinime_unittests Change-Id: I95021965ecc2699fbce01ed0552dd28fed7f8fe4 Fixes: 180014759 Test: atest liblatinime_unittests --host --- .../jni/tests/dictionary/utils/format_utils_test.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/native/jni/tests/dictionary/utils/format_utils_test.cpp b/native/jni/tests/dictionary/utils/format_utils_test.cpp index 3561bda30..34defe78c 100644 --- a/native/jni/tests/dictionary/utils/format_utils_test.cpp +++ b/native/jni/tests/dictionary/utils/format_utils_test.cpp @@ -57,7 +57,13 @@ TEST(FormatUtilsTest, TestDetectFormatVersion) { { const std::vector buffer = getBuffer(FormatUtils::MAGIC_NUMBER, FormatUtils::VERSION_2, 0, 0); - EXPECT_EQ(FormatUtils::VERSION_2, FormatUtils::detectFormatVersion( + EXPECT_EQ(FormatUtils::UNKNOWN_VERSION, FormatUtils::detectFormatVersion( + ReadOnlyByteArrayView(buffer.data(), buffer.size()))); + } + { + const std::vector buffer = + getBuffer(FormatUtils::MAGIC_NUMBER, FormatUtils::VERSION_202, 0, 0); + EXPECT_EQ(FormatUtils::VERSION_202, FormatUtils::detectFormatVersion( ReadOnlyByteArrayView(buffer.data(), buffer.size()))); } { @@ -75,7 +81,7 @@ TEST(FormatUtilsTest, TestDetectFormatVersion) { { const std::vector buffer = - getBuffer(FormatUtils::MAGIC_NUMBER - 1, FormatUtils::VERSION_2, 0, 0); + getBuffer(FormatUtils::MAGIC_NUMBER - 1, FormatUtils::VERSION_402, 0, 0); EXPECT_EQ(FormatUtils::UNKNOWN_VERSION, FormatUtils::detectFormatVersion( ReadOnlyByteArrayView(buffer.data(), buffer.size()))); } @@ -87,7 +93,7 @@ TEST(FormatUtilsTest, TestDetectFormatVersion) { } { const std::vector buffer = - getBuffer(FormatUtils::MAGIC_NUMBER, FormatUtils::VERSION_2, 0, 0); + getBuffer(FormatUtils::MAGIC_NUMBER, FormatUtils::VERSION_402, 0, 0); EXPECT_EQ(FormatUtils::UNKNOWN_VERSION, FormatUtils::detectFormatVersion( ReadOnlyByteArrayView(buffer.data(), buffer.size() - 1))); } From ed13b1971d5f7c93bb36f30872f1b10cd0a9b310 Mon Sep 17 00:00:00 2001 From: Ming-Shin Lu Date: Mon, 7 Jun 2021 00:24:41 +0800 Subject: [PATCH 2/7] Make direct-reply notification as HUN in EditTextVariations Also, set the content intent to launch an editorActivity as the message notifiation when tapping the notification. Bug: 190057993 Test: make EditTextVariations, manual test by using EditTextVariations app to simulate the issue step. Change-Id: I1a4463dc44031eaebb286ad2a289870e97a1c475 --- tools/EditTextVariations/AndroidManifest.xml | 4 +++ .../edittextvariations/EditorActivity.java | 35 +++++++++++++++++++ .../edittextvariations/NotificationUtils.java | 5 ++- 3 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 tools/EditTextVariations/src/com/android/inputmethod/tools/edittextvariations/EditorActivity.java diff --git a/tools/EditTextVariations/AndroidManifest.xml b/tools/EditTextVariations/AndroidManifest.xml index b5a27b9c8..b283b3a01 100644 --- a/tools/EditTextVariations/AndroidManifest.xml +++ b/tools/EditTextVariations/AndroidManifest.xml @@ -34,6 +34,10 @@ + diff --git a/tools/EditTextVariations/src/com/android/inputmethod/tools/edittextvariations/EditorActivity.java b/tools/EditTextVariations/src/com/android/inputmethod/tools/edittextvariations/EditorActivity.java new file mode 100644 index 000000000..4fc947bff --- /dev/null +++ b/tools/EditTextVariations/src/com/android/inputmethod/tools/edittextvariations/EditorActivity.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.inputmethod.tools.edittextvariations; + +import android.app.Activity; +import android.os.Bundle; +import android.widget.EditText; +import android.widget.LinearLayout; + +public final class EditorActivity extends Activity { + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + LinearLayout layout = new LinearLayout(this); + layout.setOrientation(LinearLayout.VERTICAL); + EditText editText = new EditText(this); + editText.setHint("reply the message"); + layout.addView(editText); + setContentView(layout); + } +} diff --git a/tools/EditTextVariations/src/com/android/inputmethod/tools/edittextvariations/NotificationUtils.java b/tools/EditTextVariations/src/com/android/inputmethod/tools/edittextvariations/NotificationUtils.java index a9b7132eb..78d52bb00 100644 --- a/tools/EditTextVariations/src/com/android/inputmethod/tools/edittextvariations/NotificationUtils.java +++ b/tools/EditTextVariations/src/com/android/inputmethod/tools/edittextvariations/NotificationUtils.java @@ -57,7 +57,7 @@ final class NotificationUtils { synchronized (sLock) { if (!sNotificationChannelInitialized) { final NotificationChannel channel = new NotificationChannel(CHANNEL_ID, - CHANNEL_NAME, NotificationManager.IMPORTANCE_DEFAULT); + CHANNEL_NAME, NotificationManager.IMPORTANCE_HIGH); channel.setDescription(CHANNEL_DESCRIPTION); context.getSystemService(NotificationManager.class) .createNotificationChannel(channel); @@ -79,12 +79,15 @@ final class NotificationUtils { final int notificationId = sNextNotificationId.getAndIncrement(); final PendingIntent pendingIntent = getReplyPendingIntent(context, notificationId); + final PendingIntent activityIntent = PendingIntent.getActivity(context, 0, + new Intent(context, EditorActivity.class), 0); final Notification.Action action = new Notification.Action.Builder(null, "Direct Reply Test", pendingIntent) .addRemoteInput(remoteInput) .build(); final Notification notification = createNotificationBuilder(context) .setContentText("Content Title") + .setContentIntent(activityIntent) .setSmallIcon(R.drawable.ic_launcher) .setContentText("Message from " + UserHandle.getUserHandleForUid(Process.myUid())) .setShowWhen(true) From a5ed00d252a7c806e58dd7662d4713d60fce3ff8 Mon Sep 17 00:00:00 2001 From: Steve Elliott Date: Fri, 3 Dec 2021 16:36:34 -0500 Subject: [PATCH 3/7] add post_notification permission to manifest so the package can send notifications on T+ Bug: 194833441 Change-Id: Iafb56ebd788f1dcd98320dc6c250ca8f585fcab3 --- tools/EditTextVariations/AndroidManifest.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/EditTextVariations/AndroidManifest.xml b/tools/EditTextVariations/AndroidManifest.xml index b283b3a01..55b774452 100644 --- a/tools/EditTextVariations/AndroidManifest.xml +++ b/tools/EditTextVariations/AndroidManifest.xml @@ -21,6 +21,7 @@ + From 97a3132c95f88a1f5d4451caf92326af37130639 Mon Sep 17 00:00:00 2001 From: Lais Andrade Date: Mon, 17 Jan 2022 19:16:47 +0000 Subject: [PATCH 4/7] Remove flag to ignore user settings from haptic feedback The keyboard key-press haptic feedback should follow the user settings for "Touch feedback". Bug: 185351540 Test: manual Change-Id: I718d3bf15b1ef841a869a898038d0eca1eca78f0 --- .../inputmethod/latin/AudioAndHapticFeedbackManager.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/java/src/com/android/inputmethod/latin/AudioAndHapticFeedbackManager.java b/java/src/com/android/inputmethod/latin/AudioAndHapticFeedbackManager.java index 60d257362..5e6e4ab25 100644 --- a/java/src/com/android/inputmethod/latin/AudioAndHapticFeedbackManager.java +++ b/java/src/com/android/inputmethod/latin/AudioAndHapticFeedbackManager.java @@ -119,8 +119,7 @@ public final class AudioAndHapticFeedbackManager { // Go ahead with the system default if (viewToPerformHapticFeedbackOn != null) { viewToPerformHapticFeedbackOn.performHapticFeedback( - HapticFeedbackConstants.KEYBOARD_TAP, - HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); + HapticFeedbackConstants.KEYBOARD_TAP); } } From 75f77d6666455e01b69dedda97c61bf36f75bd85 Mon Sep 17 00:00:00 2001 From: Wilson Wu Date: Thu, 13 Jan 2022 17:32:41 +0800 Subject: [PATCH 5/7] Add Notification Permission for T From T, apps need POST_NOTIFICATION permission to send the notification. -. Add the permission into Manifest. -. Request runtime permission when it's needed. Bug: 209479751 Test: Manual test as following steps: 1. Open EditTextVariations at T device. 2. Tap direct reply to send notification. 3. Verify the permission dialog show up. 4. Send the notification if permission granted. Change-Id: Iadae00f635ee556d1d1de9abbb9da0498b4070f1 --- tools/EditTextVariations/AndroidManifest.xml | 1 + .../EditTextVariations.java | 41 ++++++++++++++++++- 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/tools/EditTextVariations/AndroidManifest.xml b/tools/EditTextVariations/AndroidManifest.xml index b283b3a01..4520ec4b3 100644 --- a/tools/EditTextVariations/AndroidManifest.xml +++ b/tools/EditTextVariations/AndroidManifest.xml @@ -18,6 +18,7 @@ package="com.android.inputmethod.tools.edittextvariations" android:versionName="0.67" android:versionCode="67"> + diff --git a/tools/EditTextVariations/src/com/android/inputmethod/tools/edittextvariations/EditTextVariations.java b/tools/EditTextVariations/src/com/android/inputmethod/tools/edittextvariations/EditTextVariations.java index 6eb85a528..31a0025ec 100644 --- a/tools/EditTextVariations/src/com/android/inputmethod/tools/edittextvariations/EditTextVariations.java +++ b/tools/EditTextVariations/src/com/android/inputmethod/tools/edittextvariations/EditTextVariations.java @@ -16,6 +16,7 @@ package com.android.inputmethod.tools.edittextvariations; +import android.Manifest; import android.annotation.SuppressLint; import android.app.Activity; import android.app.AlertDialog; @@ -24,6 +25,7 @@ import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.os.Build; import android.os.Bundle; @@ -45,7 +47,9 @@ import android.widget.ArrayAdapter; import android.widget.AutoCompleteTextView; import android.widget.EditText; import android.widget.TextView; +import android.widget.Toast; +import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; @@ -64,6 +68,7 @@ public final class EditTextVariations extends Activity implements TextView.OnEdi private static final String PREF_THEME = "theme"; private static final String PREF_NAVIGATE = "navigate"; private static final String PREF_SOFTINPUT = "softinput"; + private static final int NOTIFICATION_PERMISSION_REQUEST_CODE = 0; private SharedPreferences prefs; private View[] fields; @@ -199,11 +204,35 @@ public final class EditTextVariations extends Activity implements TextView.OnEdi saveSoftInputMode(itemId == MENU_SOFTINPUT_VISIBLE); restartActivity(); } else if (itemId == MENU_DIRECT_REPLY) { - NotificationUtils.sendDirectReplyNotification(this); + final boolean needPermissionCheck = isNeedNotificationPermission() + && checkSelfPermission(Manifest.permission.POST_NOTIFICATIONS) != + PackageManager.PERMISSION_GRANTED; + if (needPermissionCheck) { + requestPermissions(new String[] { Manifest.permission.POST_NOTIFICATIONS }, + NOTIFICATION_PERMISSION_REQUEST_CODE); + } else { + NotificationUtils.sendDirectReplyNotification(this); + } } return true; } + @Override + public void onRequestPermissionsResult(int requestCode, String[] permissions, + int[] grantResults) { + if (requestCode == NOTIFICATION_PERMISSION_REQUEST_CODE) { + if (grantResults.length == 1 && + grantResults[0] == PackageManager.PERMISSION_GRANTED) { + // Permission is granted. Continue to send the notification. + NotificationUtils.sendDirectReplyNotification(this); + } else { + Log.d(TAG, "POST_NOTIFICATIONS Permissions denied."); + Toast.makeText(this, "Required permission has denied", + Toast.LENGTH_LONG).show(); + } + } + } + @Override public void onClick(final DialogInterface dialog, final int which) { saveTheme(ThemeItem.THEME_LIST.get(which)); @@ -476,4 +505,14 @@ public final class EditTextVariations extends Activity implements TextView.OnEdi } return text; } + + private static boolean isNeedNotificationPermission() { + for(Field field : Manifest.permission.class.getFields()) { + if (field.getName().equals("POST_NOTIFICATIONS")) { + Log.d(TAG, "Need notification permission."); + return true; + } + } + return false; + } } From 0d93961d858bb0cba234212bcd74dbe537c0529d Mon Sep 17 00:00:00 2001 From: Wilson Wu Date: Wed, 23 Feb 2022 14:58:06 +0800 Subject: [PATCH 6/7] Remove unused method for dictionarypack Remove the showDictionaryAvailableNotification method since there is no module use it. Bug: 209479751 Test: presubmit Change-Id: I4c88b4a2d0cb36761d9102ce35260f93303625d9 --- .../dictionarypack/UpdateHandler.java | 54 ------------------- 1 file changed, 54 deletions(-) diff --git a/java/src/com/android/inputmethod/dictionarypack/UpdateHandler.java b/java/src/com/android/inputmethod/dictionarypack/UpdateHandler.java index 0517bc814..bdea3e919 100644 --- a/java/src/com/android/inputmethod/dictionarypack/UpdateHandler.java +++ b/java/src/com/android/inputmethod/dictionarypack/UpdateHandler.java @@ -19,9 +19,6 @@ package com.android.inputmethod.dictionarypack; import android.app.DownloadManager; import android.app.DownloadManager.Query; import android.app.DownloadManager.Request; -import android.app.Notification; -import android.app.NotificationManager; -import android.app.PendingIntent; import android.content.ContentValues; import android.content.Context; import android.content.Intent; @@ -36,10 +33,7 @@ import android.provider.Settings; import android.text.TextUtils; import android.util.Log; -import com.android.inputmethod.compat.ConnectivityManagerCompatUtils; -import com.android.inputmethod.compat.NotificationCompatUtils; import com.android.inputmethod.latin.R; -import com.android.inputmethod.latin.common.LocaleUtils; import com.android.inputmethod.latin.makedict.FormatSpec; import com.android.inputmethod.latin.utils.ApplicationUtils; import com.android.inputmethod.latin.utils.DebugLogUtils; @@ -843,54 +837,6 @@ public final class UpdateHandler { return compareMetadataForUpgrade(context, clientId, currentMetadata, newMetadata); } - /** - * Shows the notification that informs the user a dictionary is available. - * - * When this notification is clicked, the dialog for downloading the dictionary - * over a metered connection is shown. - */ - private static void showDictionaryAvailableNotification(final Context context, - final String clientId, final ContentValues installCandidate) { - final String localeString = installCandidate.getAsString(MetadataDbHelper.LOCALE_COLUMN); - final Intent intent = new Intent(); - intent.setClass(context, DownloadOverMeteredDialog.class); - intent.putExtra(DownloadOverMeteredDialog.CLIENT_ID_KEY, clientId); - intent.putExtra(DownloadOverMeteredDialog.WORDLIST_TO_DOWNLOAD_KEY, - installCandidate.getAsString(MetadataDbHelper.WORDLISTID_COLUMN)); - intent.putExtra(DownloadOverMeteredDialog.SIZE_KEY, - installCandidate.getAsInteger(MetadataDbHelper.FILESIZE_COLUMN)); - intent.putExtra(DownloadOverMeteredDialog.LOCALE_KEY, localeString); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); - final PendingIntent notificationIntent = PendingIntent.getActivity(context, - 0 /* requestCode */, intent, - PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_ONE_SHOT); - final NotificationManager notificationManager = - (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); - // None of those are expected to happen, but just in case... - if (null == notificationIntent || null == notificationManager) return; - - final String language = (null == localeString) ? "" - : LocaleUtils.constructLocaleFromString(localeString).getDisplayLanguage(); - final String titleFormat = context.getString(R.string.dict_available_notification_title); - final String notificationTitle = String.format(titleFormat, language); - final Notification.Builder builder = new Notification.Builder(context) - .setAutoCancel(true) - .setContentIntent(notificationIntent) - .setContentTitle(notificationTitle) - .setContentText(context.getString(R.string.dict_available_notification_description)) - .setTicker(notificationTitle) - .setOngoing(false) - .setOnlyAlertOnce(true) - .setSmallIcon(R.drawable.ic_notify_dictionary); - NotificationCompatUtils.setColor(builder, - context.getResources().getColor(R.color.notification_accent_color)); - NotificationCompatUtils.setPriorityToLow(builder); - NotificationCompatUtils.setVisibilityToSecret(builder); - NotificationCompatUtils.setCategoryToRecommendation(builder); - final Notification notification = NotificationCompatUtils.build(builder); - notificationManager.notify(DICT_AVAILABLE_NOTIFICATION_ID, notification); - } - /** * Installs a word list if it has never been requested. * From f134ea3848c60862a78653e3bd23070531a4b3fc Mon Sep 17 00:00:00 2001 From: Ming-Shin Lu Date: Fri, 15 Apr 2022 01:42:35 +0800 Subject: [PATCH 7/7] EditTextVariations: create a IME focusable overlay for test Bug: 228766370 Test: manual by using EditorTextVariations tool 1) make and install EditTextVariations 2) Enable "Settings > Display over other apps" for EditTextVariations 3) Launch EditTextVariations from all apps 4) Menu -> Show IME focuable overlay 5) Go to home screen by gesture or pressing home key 6) Launch any app (e.g. Chrome) and tap the editor 7) Expect IME can show up Change-Id: Ib4b72e0a277d8b2fb78837bed5d2e9cccd819a07 --- tools/EditTextVariations/AndroidManifest.xml | 1 + .../EditTextVariations/res/values/strings.xml | 4 ++ .../EditTextVariations.java | 60 ++++++++++++++++++- 3 files changed, 64 insertions(+), 1 deletion(-) diff --git a/tools/EditTextVariations/AndroidManifest.xml b/tools/EditTextVariations/AndroidManifest.xml index ecfe764da..0cf6d4fcc 100644 --- a/tools/EditTextVariations/AndroidManifest.xml +++ b/tools/EditTextVariations/AndroidManifest.xml @@ -19,6 +19,7 @@ android:versionName="0.67" android:versionCode="67"> + diff --git a/tools/EditTextVariations/res/values/strings.xml b/tools/EditTextVariations/res/values/strings.xml index cb896e8b6..1b42dc787 100644 --- a/tools/EditTextVariations/res/values/strings.xml +++ b/tools/EditTextVariations/res/values/strings.xml @@ -35,6 +35,10 @@ Keyboard Hidden Direct Reply + + Show IME focusable overlay + + Hide IME focusable overlay Custom diff --git a/tools/EditTextVariations/src/com/android/inputmethod/tools/edittextvariations/EditTextVariations.java b/tools/EditTextVariations/src/com/android/inputmethod/tools/edittextvariations/EditTextVariations.java index 31a0025ec..53d08b6c9 100644 --- a/tools/EditTextVariations/src/com/android/inputmethod/tools/edittextvariations/EditTextVariations.java +++ b/tools/EditTextVariations/src/com/android/inputmethod/tools/edittextvariations/EditTextVariations.java @@ -16,10 +16,19 @@ package com.android.inputmethod.tools.edittextvariations; +import static android.graphics.Color.BLUE; +import static android.view.Gravity.LEFT; +import static android.view.Gravity.TOP; +import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; +import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; +import static android.view.WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH; +import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; + import android.Manifest; import android.annotation.SuppressLint; import android.app.Activity; import android.app.AlertDialog; +import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; @@ -27,9 +36,11 @@ import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; +import android.graphics.Rect; import android.os.Build; import android.os.Bundle; import android.preference.PreferenceManager; +import android.provider.Settings; import android.text.InputType; import android.text.TextUtils; import android.util.Log; @@ -65,6 +76,7 @@ public final class EditTextVariations extends Activity implements TextView.OnEdi private static final int MENU_SOFTINPUT_VISIBLE = 4; private static final int MENU_SOFTINPUT_HIDDEN = 5; private static final int MENU_DIRECT_REPLY = 6; + private static final int MENU_TOGGLE_IME_FOCUSABLE_OVERLAY = 7; private static final String PREF_THEME = "theme"; private static final String PREF_NAVIGATE = "navigate"; private static final String PREF_SOFTINPUT = "softinput"; @@ -85,6 +97,9 @@ public final class EditTextVariations extends Activity implements TextView.OnEdi private ArrayAdapter mAutoCompleteAdapter; + private TextView mOverlayTextView; + private boolean mShowOverlay = true; + /** Called when the activity is first created. */ @SuppressLint("SetJavaScriptEnabled") @Override @@ -171,9 +186,12 @@ public final class EditTextVariations extends Activity implements TextView.OnEdi if (NotificationUtils.DIRECT_REPLY_SUPPORTED) { menu.add(Menu.NONE, MENU_DIRECT_REPLY, 5, R.string.menu_direct_reply); } + menu.add(Menu.NONE, MENU_TOGGLE_IME_FOCUSABLE_OVERLAY, 6, + mShowOverlay ? getString(R.string.menu_show_ime_focusable_overlay) + : getString(R.string.menu_hide_ime_focusable_overlay)); try { final PackageInfo pinfo = getPackageManager().getPackageInfo(getPackageName(), 0); - menu.add(Menu.NONE, MENU_VERSION, 6, + menu.add(Menu.NONE, MENU_VERSION, 7, getString(R.string.menu_version, pinfo.versionName)) .setEnabled(false); } catch (NameNotFoundException e) { @@ -213,6 +231,16 @@ public final class EditTextVariations extends Activity implements TextView.OnEdi } else { NotificationUtils.sendDirectReplyNotification(this); } + } else if (itemId == MENU_TOGGLE_IME_FOCUSABLE_OVERLAY) { + if (!Settings.canDrawOverlays(this)) { + Toast.makeText(this, + "Not allowed to show overlay.\nCheck \"Settings > " + + "Display over other apps\"", Toast.LENGTH_LONG).show(); + } else { + toggleOverlayView(true /* needsIme */); + item.setTitle(mShowOverlay ? getString(R.string.menu_show_ime_focusable_overlay) + : getString(R.string.menu_hide_ime_focusable_overlay)); + } } return true; } @@ -233,6 +261,14 @@ public final class EditTextVariations extends Activity implements TextView.OnEdi } } + @Override + protected void onDestroy() { + if (mOverlayTextView != null) { + getWindowManager().removeView(mOverlayTextView); + mOverlayTextView = null; + } + } + @Override public void onClick(final DialogInterface dialog, final int which) { saveTheme(ThemeItem.THEME_LIST.get(which)); @@ -515,4 +551,26 @@ public final class EditTextVariations extends Activity implements TextView.OnEdi } return false; } + + private void toggleOverlayView(boolean needsIme) { + if (mOverlayTextView == null) { + Context overlayContext = createDisplayContext(getDisplay()) + .createWindowContext(TYPE_APPLICATION_OVERLAY, null /* options */); + int focusableFlags = FLAG_NOT_FOCUSABLE | (needsIme ? FLAG_ALT_FOCUSABLE_IM : 0); + final WindowManager.LayoutParams params = new WindowManager.LayoutParams( + TYPE_APPLICATION_OVERLAY, FLAG_WATCH_OUTSIDE_TOUCH | focusableFlags); + final Rect windowBounds = getWindowManager().getCurrentWindowMetrics().getBounds(); + params.width = windowBounds.width() / 3; + params.height = windowBounds.height() / 3; + params.gravity = TOP | LEFT; + + mOverlayTextView = new TextView(overlayContext); + mOverlayTextView.setText("I'm an IME focusable overlay"); + mOverlayTextView.setBackgroundColor(BLUE); + getWindowManager().addView(mOverlayTextView, params); + } + mOverlayTextView.setVisibility(mShowOverlay ? View.VISIBLE : View.GONE); + // Toggle the overlay visibility after the call. + mShowOverlay = !mShowOverlay; + } }