Skip to content

Commit 7005e0c

Browse files
delphijGerrit Code Review
authored andcommitted
Merge "DO NOT MERGE - Merge Android 13"
2 parents a9786e8 + 2012c03 commit 7005e0c

7 files changed

Lines changed: 150 additions & 59 deletions

File tree

java/src/com/android/inputmethod/dictionarypack/UpdateHandler.java

Lines changed: 0 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,6 @@
1919
import android.app.DownloadManager;
2020
import android.app.DownloadManager.Query;
2121
import android.app.DownloadManager.Request;
22-
import android.app.Notification;
23-
import android.app.NotificationManager;
24-
import android.app.PendingIntent;
2522
import android.content.ContentValues;
2623
import android.content.Context;
2724
import android.content.Intent;
@@ -36,10 +33,7 @@
3633
import android.text.TextUtils;
3734
import android.util.Log;
3835

39-
import com.android.inputmethod.compat.ConnectivityManagerCompatUtils;
40-
import com.android.inputmethod.compat.NotificationCompatUtils;
4136
import com.android.inputmethod.latin.R;
42-
import com.android.inputmethod.latin.common.LocaleUtils;
4337
import com.android.inputmethod.latin.makedict.FormatSpec;
4438
import com.android.inputmethod.latin.utils.ApplicationUtils;
4539
import com.android.inputmethod.latin.utils.DebugLogUtils;
@@ -843,54 +837,6 @@ public static ActionBatch computeUpgradeTo(final Context context, final String c
843837
return compareMetadataForUpgrade(context, clientId, currentMetadata, newMetadata);
844838
}
845839

846-
/**
847-
* Shows the notification that informs the user a dictionary is available.
848-
*
849-
* When this notification is clicked, the dialog for downloading the dictionary
850-
* over a metered connection is shown.
851-
*/
852-
private static void showDictionaryAvailableNotification(final Context context,
853-
final String clientId, final ContentValues installCandidate) {
854-
final String localeString = installCandidate.getAsString(MetadataDbHelper.LOCALE_COLUMN);
855-
final Intent intent = new Intent();
856-
intent.setClass(context, DownloadOverMeteredDialog.class);
857-
intent.putExtra(DownloadOverMeteredDialog.CLIENT_ID_KEY, clientId);
858-
intent.putExtra(DownloadOverMeteredDialog.WORDLIST_TO_DOWNLOAD_KEY,
859-
installCandidate.getAsString(MetadataDbHelper.WORDLISTID_COLUMN));
860-
intent.putExtra(DownloadOverMeteredDialog.SIZE_KEY,
861-
installCandidate.getAsInteger(MetadataDbHelper.FILESIZE_COLUMN));
862-
intent.putExtra(DownloadOverMeteredDialog.LOCALE_KEY, localeString);
863-
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
864-
final PendingIntent notificationIntent = PendingIntent.getActivity(context,
865-
0 /* requestCode */, intent,
866-
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_ONE_SHOT);
867-
final NotificationManager notificationManager =
868-
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
869-
// None of those are expected to happen, but just in case...
870-
if (null == notificationIntent || null == notificationManager) return;
871-
872-
final String language = (null == localeString) ? ""
873-
: LocaleUtils.constructLocaleFromString(localeString).getDisplayLanguage();
874-
final String titleFormat = context.getString(R.string.dict_available_notification_title);
875-
final String notificationTitle = String.format(titleFormat, language);
876-
final Notification.Builder builder = new Notification.Builder(context)
877-
.setAutoCancel(true)
878-
.setContentIntent(notificationIntent)
879-
.setContentTitle(notificationTitle)
880-
.setContentText(context.getString(R.string.dict_available_notification_description))
881-
.setTicker(notificationTitle)
882-
.setOngoing(false)
883-
.setOnlyAlertOnce(true)
884-
.setSmallIcon(R.drawable.ic_notify_dictionary);
885-
NotificationCompatUtils.setColor(builder,
886-
context.getResources().getColor(R.color.notification_accent_color));
887-
NotificationCompatUtils.setPriorityToLow(builder);
888-
NotificationCompatUtils.setVisibilityToSecret(builder);
889-
NotificationCompatUtils.setCategoryToRecommendation(builder);
890-
final Notification notification = NotificationCompatUtils.build(builder);
891-
notificationManager.notify(DICT_AVAILABLE_NOTIFICATION_ID, notification);
892-
}
893-
894840
/**
895841
* Installs a word list if it has never been requested.
896842
*

java/src/com/android/inputmethod/latin/AudioAndHapticFeedbackManager.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,8 +119,7 @@ public void performHapticFeedback(final View viewToPerformHapticFeedbackOn) {
119119
// Go ahead with the system default
120120
if (viewToPerformHapticFeedbackOn != null) {
121121
viewToPerformHapticFeedbackOn.performHapticFeedback(
122-
HapticFeedbackConstants.KEYBOARD_TAP,
123-
HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING);
122+
HapticFeedbackConstants.KEYBOARD_TAP);
124123
}
125124
}
126125

tools/EditTextVariations/AndroidManifest.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,12 @@
1818
package="com.android.inputmethod.tools.edittextvariations"
1919
android:versionName="0.67"
2020
android:versionCode="67">
21+
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
22+
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
2123
<supports-screens android:resizeable="true"/>
2224
<uses-sdk android:targetSdkVersion="27"
2325
android:minSdkVersion="11"/>
26+
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
2427
<application android:icon="@drawable/ic_launcher"
2528
android:label="@string/app_name"
2629
android:allowBackup="false">
@@ -34,6 +37,10 @@
3437
<category android:name="android.intent.category.LAUNCHER"/>
3538
</intent-filter>
3639
</activity>
40+
<activity android:name=".EditorActivity"
41+
android:windowSoftInputMode="stateHidden|adjustPan"
42+
android:theme="@style/defaultActivityTheme"
43+
android:label="@string/app_name"/>
3744
<receiver android:name=".NotificationBroadcastReceiver"
3845
android:exported="false"/>
3946
</application>

tools/EditTextVariations/res/values/strings.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@
3535
<string name="menu_softinput_hidden" translatable="false">Keyboard Hidden</string>
3636
<!-- The menu title to send a notification to test direct reply. [CHAR LIMIT=20] -->
3737
<string name="menu_direct_reply">Direct Reply</string>
38+
<!-- The menu title to show a application overlay with NOT_FOCUSABLE | ALT_FOCUSABLE_IM. [CHAR LIMIT=26] -->
39+
<string name="menu_show_ime_focusable_overlay">Show IME focusable overlay</string>
40+
<!-- The menu title to hide a application overlay with NOT_FOCUSABLE | ALT_FOCUSABLE_IM. [CHAR LIMIT=26] -->
41+
<string name="menu_hide_ime_focusable_overlay">Hide IME focusable overlay</string>
3842
<!-- The example of custom action key label. Must be short to fit on key. 5 chars or less is preferable. [CHAR LIMIT=7] -->
3943
<string name="custom_action_label">Custom</string>
4044
</resources>

tools/EditTextVariations/src/com/android/inputmethod/tools/edittextvariations/EditTextVariations.java

Lines changed: 99 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,31 @@
1616

1717
package com.android.inputmethod.tools.edittextvariations;
1818

19+
import static android.graphics.Color.BLUE;
20+
import static android.view.Gravity.LEFT;
21+
import static android.view.Gravity.TOP;
22+
import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
23+
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
24+
import static android.view.WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
25+
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
26+
27+
import android.Manifest;
1928
import android.annotation.SuppressLint;
2029
import android.app.Activity;
2130
import android.app.AlertDialog;
31+
import android.content.Context;
2232
import android.content.DialogInterface;
2333
import android.content.Intent;
2434
import android.content.SharedPreferences;
2535
import android.content.pm.ApplicationInfo;
2636
import android.content.pm.PackageInfo;
37+
import android.content.pm.PackageManager;
2738
import android.content.pm.PackageManager.NameNotFoundException;
39+
import android.graphics.Rect;
2840
import android.os.Build;
2941
import android.os.Bundle;
3042
import android.preference.PreferenceManager;
43+
import android.provider.Settings;
3144
import android.text.InputType;
3245
import android.text.TextUtils;
3346
import android.util.Log;
@@ -45,7 +58,9 @@
4558
import android.widget.AutoCompleteTextView;
4659
import android.widget.EditText;
4760
import android.widget.TextView;
61+
import android.widget.Toast;
4862

63+
import java.lang.reflect.Field;
4964
import java.util.ArrayList;
5065
import java.util.List;
5166

@@ -61,9 +76,11 @@ public final class EditTextVariations extends Activity implements TextView.OnEdi
6176
private static final int MENU_SOFTINPUT_VISIBLE = 4;
6277
private static final int MENU_SOFTINPUT_HIDDEN = 5;
6378
private static final int MENU_DIRECT_REPLY = 6;
79+
private static final int MENU_TOGGLE_IME_FOCUSABLE_OVERLAY = 7;
6480
private static final String PREF_THEME = "theme";
6581
private static final String PREF_NAVIGATE = "navigate";
6682
private static final String PREF_SOFTINPUT = "softinput";
83+
private static final int NOTIFICATION_PERMISSION_REQUEST_CODE = 0;
6784

6885
private SharedPreferences prefs;
6986
private View[] fields;
@@ -80,6 +97,9 @@ public final class EditTextVariations extends Activity implements TextView.OnEdi
8097

8198
private ArrayAdapter<String> mAutoCompleteAdapter;
8299

100+
private TextView mOverlayTextView;
101+
private boolean mShowOverlay = true;
102+
83103
/** Called when the activity is first created. */
84104
@SuppressLint("SetJavaScriptEnabled")
85105
@Override
@@ -166,9 +186,12 @@ public boolean onCreateOptionsMenu(final Menu menu) {
166186
if (NotificationUtils.DIRECT_REPLY_SUPPORTED) {
167187
menu.add(Menu.NONE, MENU_DIRECT_REPLY, 5, R.string.menu_direct_reply);
168188
}
189+
menu.add(Menu.NONE, MENU_TOGGLE_IME_FOCUSABLE_OVERLAY, 6,
190+
mShowOverlay ? getString(R.string.menu_show_ime_focusable_overlay)
191+
: getString(R.string.menu_hide_ime_focusable_overlay));
169192
try {
170193
final PackageInfo pinfo = getPackageManager().getPackageInfo(getPackageName(), 0);
171-
menu.add(Menu.NONE, MENU_VERSION, 6,
194+
menu.add(Menu.NONE, MENU_VERSION, 7,
172195
getString(R.string.menu_version, pinfo.versionName))
173196
.setEnabled(false);
174197
} catch (NameNotFoundException e) {
@@ -199,11 +222,53 @@ public boolean onOptionsItemSelected(final MenuItem item) {
199222
saveSoftInputMode(itemId == MENU_SOFTINPUT_VISIBLE);
200223
restartActivity();
201224
} else if (itemId == MENU_DIRECT_REPLY) {
202-
NotificationUtils.sendDirectReplyNotification(this);
225+
final boolean needPermissionCheck = isNeedNotificationPermission()
226+
&& checkSelfPermission(Manifest.permission.POST_NOTIFICATIONS) !=
227+
PackageManager.PERMISSION_GRANTED;
228+
if (needPermissionCheck) {
229+
requestPermissions(new String[] { Manifest.permission.POST_NOTIFICATIONS },
230+
NOTIFICATION_PERMISSION_REQUEST_CODE);
231+
} else {
232+
NotificationUtils.sendDirectReplyNotification(this);
233+
}
234+
} else if (itemId == MENU_TOGGLE_IME_FOCUSABLE_OVERLAY) {
235+
if (!Settings.canDrawOverlays(this)) {
236+
Toast.makeText(this,
237+
"Not allowed to show overlay.\nCheck \"Settings > "
238+
+ "Display over other apps\"", Toast.LENGTH_LONG).show();
239+
} else {
240+
toggleOverlayView(true /* needsIme */);
241+
item.setTitle(mShowOverlay ? getString(R.string.menu_show_ime_focusable_overlay)
242+
: getString(R.string.menu_hide_ime_focusable_overlay));
243+
}
203244
}
204245
return true;
205246
}
206247

248+
@Override
249+
public void onRequestPermissionsResult(int requestCode, String[] permissions,
250+
int[] grantResults) {
251+
if (requestCode == NOTIFICATION_PERMISSION_REQUEST_CODE) {
252+
if (grantResults.length == 1 &&
253+
grantResults[0] == PackageManager.PERMISSION_GRANTED) {
254+
// Permission is granted. Continue to send the notification.
255+
NotificationUtils.sendDirectReplyNotification(this);
256+
} else {
257+
Log.d(TAG, "POST_NOTIFICATIONS Permissions denied.");
258+
Toast.makeText(this, "Required permission has denied",
259+
Toast.LENGTH_LONG).show();
260+
}
261+
}
262+
}
263+
264+
@Override
265+
protected void onDestroy() {
266+
if (mOverlayTextView != null) {
267+
getWindowManager().removeView(mOverlayTextView);
268+
mOverlayTextView = null;
269+
}
270+
}
271+
207272
@Override
208273
public void onClick(final DialogInterface dialog, final int which) {
209274
saveTheme(ThemeItem.THEME_LIST.get(which));
@@ -476,4 +541,36 @@ private static String appendFlagText(final String text, final boolean flag, fina
476541
}
477542
return text;
478543
}
544+
545+
private static boolean isNeedNotificationPermission() {
546+
for(Field field : Manifest.permission.class.getFields()) {
547+
if (field.getName().equals("POST_NOTIFICATIONS")) {
548+
Log.d(TAG, "Need notification permission.");
549+
return true;
550+
}
551+
}
552+
return false;
553+
}
554+
555+
private void toggleOverlayView(boolean needsIme) {
556+
if (mOverlayTextView == null) {
557+
Context overlayContext = createDisplayContext(getDisplay())
558+
.createWindowContext(TYPE_APPLICATION_OVERLAY, null /* options */);
559+
int focusableFlags = FLAG_NOT_FOCUSABLE | (needsIme ? FLAG_ALT_FOCUSABLE_IM : 0);
560+
final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
561+
TYPE_APPLICATION_OVERLAY, FLAG_WATCH_OUTSIDE_TOUCH | focusableFlags);
562+
final Rect windowBounds = getWindowManager().getCurrentWindowMetrics().getBounds();
563+
params.width = windowBounds.width() / 3;
564+
params.height = windowBounds.height() / 3;
565+
params.gravity = TOP | LEFT;
566+
567+
mOverlayTextView = new TextView(overlayContext);
568+
mOverlayTextView.setText("I'm an IME focusable overlay");
569+
mOverlayTextView.setBackgroundColor(BLUE);
570+
getWindowManager().addView(mOverlayTextView, params);
571+
}
572+
mOverlayTextView.setVisibility(mShowOverlay ? View.VISIBLE : View.GONE);
573+
// Toggle the overlay visibility after the call.
574+
mShowOverlay = !mShowOverlay;
575+
}
479576
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
* Copyright (C) 2021 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.inputmethod.tools.edittextvariations;
18+
19+
import android.app.Activity;
20+
import android.os.Bundle;
21+
import android.widget.EditText;
22+
import android.widget.LinearLayout;
23+
24+
public final class EditorActivity extends Activity {
25+
@Override
26+
protected void onCreate(Bundle savedInstanceState) {
27+
super.onCreate(savedInstanceState);
28+
LinearLayout layout = new LinearLayout(this);
29+
layout.setOrientation(LinearLayout.VERTICAL);
30+
EditText editText = new EditText(this);
31+
editText.setHint("reply the message");
32+
layout.addView(editText);
33+
setContentView(layout);
34+
}
35+
}

tools/EditTextVariations/src/com/android/inputmethod/tools/edittextvariations/NotificationUtils.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ private static Notification.Builder createNotificationBuilder(Context context) {
5757
synchronized (sLock) {
5858
if (!sNotificationChannelInitialized) {
5959
final NotificationChannel channel = new NotificationChannel(CHANNEL_ID,
60-
CHANNEL_NAME, NotificationManager.IMPORTANCE_DEFAULT);
60+
CHANNEL_NAME, NotificationManager.IMPORTANCE_HIGH);
6161
channel.setDescription(CHANNEL_DESCRIPTION);
6262
context.getSystemService(NotificationManager.class)
6363
.createNotificationChannel(channel);
@@ -79,12 +79,15 @@ static void sendDirectReplyNotification(Context context) {
7979

8080
final int notificationId = sNextNotificationId.getAndIncrement();
8181
final PendingIntent pendingIntent = getReplyPendingIntent(context, notificationId);
82+
final PendingIntent activityIntent = PendingIntent.getActivity(context, 0,
83+
new Intent(context, EditorActivity.class), 0);
8284
final Notification.Action action =
8385
new Notification.Action.Builder(null, "Direct Reply Test", pendingIntent)
8486
.addRemoteInput(remoteInput)
8587
.build();
8688
final Notification notification = createNotificationBuilder(context)
8789
.setContentText("Content Title")
90+
.setContentIntent(activityIntent)
8891
.setSmallIcon(R.drawable.ic_launcher)
8992
.setContentText("Message from " + UserHandle.getUserHandleForUid(Process.myUid()))
9093
.setShowWhen(true)

0 commit comments

Comments
 (0)