diff options
37 files changed, 358 insertions, 119 deletions
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg index 2fd2e33bbc37..9b290c6a4760 100644 --- a/PREUPLOAD.cfg +++ b/PREUPLOAD.cfg @@ -12,8 +12,6 @@ clang_format = --commit ${PREUPLOAD_COMMIT} --style file --extensions c,h,cc,cpp services/incremental/ [Hook Scripts] -checkstyle_hook = ${REPO_ROOT}/prebuilts/checkstyle/checkstyle.py --sha ${PREUPLOAD_COMMIT} - strings_lint_hook = ${REPO_ROOT}/frameworks/base/tools/stringslint/stringslint_sha.sh ${PREUPLOAD_COMMIT} hidden_api_txt_checksorted_hook = ${REPO_ROOT}/frameworks/base/tools/hiddenapi/checksorted_sha.sh ${PREUPLOAD_COMMIT} ${REPO_ROOT} diff --git a/core/java/android/app/ApplicationExitInfo.java b/core/java/android/app/ApplicationExitInfo.java index cfe0aff05d4a..e7b3e14bfda7 100644 --- a/core/java/android/app/ApplicationExitInfo.java +++ b/core/java/android/app/ApplicationExitInfo.java @@ -502,7 +502,7 @@ public final class ApplicationExitInfo implements Parcelable { * Return the defining kernel user identifier, maybe different from {@link #getRealUid} and * {@link #getPackageUid}, if an external service has the * {@link android.R.styleable#AndroidManifestService_useAppZygote android:useAppZygote} set - * to <code>true<code> and was bound with the flag + * to <code>true</code> and was bound with the flag * {@link android.content.Context#BIND_EXTERNAL_SERVICE} - in this case, this field here will * be the kernel user identifier of the external service provider. */ diff --git a/core/java/android/content/IntentFilter.java b/core/java/android/content/IntentFilter.java index 79da1f6ab282..ee9bd3d259fb 100644 --- a/core/java/android/content/IntentFilter.java +++ b/core/java/android/content/IntentFilter.java @@ -1168,7 +1168,12 @@ public class IntentFilter implements Parcelable { public int match(Uri data, boolean wildcardSupported) { String host = data.getHost(); if (host == null) { - return NO_MATCH_DATA; + if (wildcardSupported && mWild) { + // special case, if no host is provided, but the Authority is wildcard, match + return MATCH_CATEGORY_HOST; + } else { + return NO_MATCH_DATA; + } } if (false) Log.v("IntentFilter", "Match host " + host + ": " + mHost); diff --git a/core/java/android/content/pm/parsing/ParsingPackageUtils.java b/core/java/android/content/pm/parsing/ParsingPackageUtils.java index bc9c71e7a68e..ab0ed51fb909 100644 --- a/core/java/android/content/pm/parsing/ParsingPackageUtils.java +++ b/core/java/android/content/pm/parsing/ParsingPackageUtils.java @@ -1510,7 +1510,7 @@ public class ParsingPackageUtils { Uri data = null; String dataType = null; - String host = IntentFilter.WILDCARD; + String host = null; final int numActions = intentInfo.countActions(); final int numSchemes = intentInfo.countDataSchemes(); final int numTypes = intentInfo.countDataTypes(); diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java index 5647bf90d2fb..c5a11abe1136 100644 --- a/core/java/android/inputmethodservice/InputMethodService.java +++ b/core/java/android/inputmethodservice/InputMethodService.java @@ -605,9 +605,6 @@ public class InputMethodService extends AbstractInputMethodService { if (DEBUG) Log.v(TAG, "unbindInput(): binding=" + mInputBinding + " ic=" + mInputConnection); // Unbind input is per process per display. - // TODO(b/150902448): free-up IME surface when target is changing. - // e.g. DisplayContent#setInputMethodTarget() - removeImeSurface(); onUnbindInput(); mInputBinding = null; mInputConnection = null; diff --git a/core/java/android/net/MacAddress.java b/core/java/android/net/MacAddress.java index 0e10c42e61db..0eb3c1e8ad01 100644 --- a/core/java/android/net/MacAddress.java +++ b/core/java/android/net/MacAddress.java @@ -38,7 +38,9 @@ import java.util.Arrays; * Representation of a MAC address. * * This class only supports 48 bits long addresses and does not support 64 bits long addresses. - * Instances of this class are immutable. + * Instances of this class are immutable. This class provides implementations of hashCode() + * and equals() that make it suitable for use as keys in standard implementations of + * {@link java.util.Map}. */ public final class MacAddress implements Parcelable { @@ -122,12 +124,22 @@ public final class MacAddress implements Parcelable { } /** + * Convert this MacAddress to a byte array. + * + * The returned array is in network order. For example, if this MacAddress is 1:2:3:4:5:6, + * the returned array is [1, 2, 3, 4, 5, 6]. + * * @return a byte array representation of this MacAddress. */ public @NonNull byte[] toByteArray() { return byteAddrFromLongAddr(mAddr); } + /** + * Returns a human-readable representation of this MacAddress. + * The exact format is implementation-dependent and should not be assumed to have any + * particular format. + */ @Override public @NonNull String toString() { return stringAddrFromLongAddr(mAddr); diff --git a/core/java/android/view/ImeInsetsSourceConsumer.java b/core/java/android/view/ImeInsetsSourceConsumer.java index ef9d990168d2..c1998c6009cf 100644 --- a/core/java/android/view/ImeInsetsSourceConsumer.java +++ b/core/java/android/view/ImeInsetsSourceConsumer.java @@ -119,11 +119,11 @@ public final class ImeInsetsSourceConsumer extends InsetsSourceConsumer { // If we had a request before to show from IME (tracked with mImeRequestedShow), reaching // this code here means that we now got control, so we can start the animation immediately. // If client window is trying to control IME and IME is already visible, it is immediate. - if (fromIme || mState.getSource(getType()).isVisible()) { + if (fromIme || mState.getSource(getType()).isVisible() && getControl() != null) { return ShowResult.SHOW_IMMEDIATELY; } - return getImm().requestImeShow(null /* resultReceiver */) + return getImm().requestImeShow(mController.getHost().getWindowToken()) ? ShowResult.IME_SHOW_DELAYED : ShowResult.IME_SHOW_FAILED; } @@ -132,12 +132,15 @@ public final class ImeInsetsSourceConsumer extends InsetsSourceConsumer { */ @Override void notifyHidden() { - getImm().notifyImeHidden(); + getImm().notifyImeHidden(mController.getHost().getWindowToken()); } @Override public void removeSurface() { - getImm().removeImeSurface(); + final IBinder window = mController.getHost().getWindowToken(); + if (window != null) { + getImm().removeImeSurface(window); + } } @Override @@ -146,6 +149,7 @@ public final class ImeInsetsSourceConsumer extends InsetsSourceConsumer { super.setControl(control, showTypes, hideTypes); if (control == null && !mIsRequestedVisibleAwaitingControl) { hide(); + removeSurface(); } } diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java index c6be91fa1bf5..a679b3740fd9 100644 --- a/core/java/android/view/InsetsController.java +++ b/core/java/android/view/InsetsController.java @@ -737,7 +737,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation } } - final boolean hasControl = mTmpControlArray.size() > 0; + boolean requestedStateStale = false; final int[] showTypes = new int[1]; final int[] hideTypes = new int[1]; @@ -754,9 +754,26 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation // Ensure to create source consumers if not available yet. for (int i = mTmpControlArray.size() - 1; i >= 0; i--) { final InsetsSourceControl control = mTmpControlArray.valueAt(i); - InsetsSourceConsumer consumer = getSourceConsumer(control.getType()); + final @InternalInsetsType int type = control.getType(); + final InsetsSourceConsumer consumer = getSourceConsumer(type); consumer.setControl(control, showTypes, hideTypes); + if (!requestedStateStale) { + final boolean requestedVisible = consumer.isRequestedVisible(); + + // We might have changed our requested visibilities while we don't have the control, + // so we need to update our requested state once we have control. Otherwise, our + // requested state at the server side might be incorrect. + final boolean requestedVisibilityChanged = + requestedVisible != mRequestedState.getSourceOrDefaultVisibility(type); + + // The IME client visibility will be reset by insets source provider while updating + // control, so if IME is requested visible, we need to send the request to server. + final boolean imeRequestedVisible = type == ITYPE_IME && requestedVisible; + + requestedStateStale = requestedVisibilityChanged || imeRequestedVisible; + } + } mTmpControlArray.clear(); @@ -772,10 +789,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation if (hideTypes[0] != 0) { applyAnimation(hideTypes[0], false /* show */, false /* fromIme */); } - if (hasControl && mRequestedState.hasSources()) { - // We might have changed our requested visibilities while we don't have the control, - // so we need to update our requested state once we have control. Otherwise, our - // requested state at the server side might be incorrect. + if (requestedStateStale) { updateRequestedState(); } } diff --git a/core/java/android/view/InsetsSourceConsumer.java b/core/java/android/view/InsetsSourceConsumer.java index 40e6f4b2fce8..700dc66fab55 100644 --- a/core/java/android/view/InsetsSourceConsumer.java +++ b/core/java/android/view/InsetsSourceConsumer.java @@ -153,6 +153,9 @@ public class InsetsSourceConsumer { if (oldLeash == null || newLeash == null || !oldLeash.isSameSurface(newLeash)) { applyHiddenToControl(); } + if (!requestedVisible && !mIsAnimationPending) { + removeSurface(); + } } } if (lastControl != null) { diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index a58642517a20..2b7044d0c67e 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -2725,7 +2725,6 @@ public final class ViewRootImpl implements ViewParent, mAttachInfo.mThreadedRenderer.isEnabled()) { mAttachInfo.mThreadedRenderer.destroy(); } - notifySurfaceDestroyed(); } else if ((surfaceReplaced || surfaceSizeChanged || windowRelayoutWasForced || colorModeChanged) && mSurfaceHolder == null @@ -2956,6 +2955,10 @@ public final class ViewRootImpl implements ViewParent, } } + if (surfaceDestroyed) { + notifySurfaceDestroyed(); + } + if (triggerGlobalLayoutListener) { mAttachInfo.mRecomputeGlobalAttributes = false; mAttachInfo.mTreeObserver.dispatchOnGlobalLayout(); @@ -9377,6 +9380,11 @@ public final class ViewRootImpl implements ViewParent, return mInputEventReceiver.getToken(); } + @NonNull + public IBinder getWindowToken() { + return mAttachInfo.mWindowToken; + } + /** * Class for managing the accessibility interaction connection * based on the global accessibility state. diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java index aedb59bfee42..3be0a4d39a56 100644 --- a/core/java/android/view/inputmethod/InputMethodManager.java +++ b/core/java/android/view/inputmethod/InputMethodManager.java @@ -2109,28 +2109,36 @@ public final class InputMethodManager { /** * Call showSoftInput with currently focused view. - * @return {@code true} if IME can be shown. + * + * @param windowToken the window from which this request originates. If this doesn't match the + * currently served view, the request is ignored and returns {@code false}. + * + * @return {@code true} if IME can (eventually) be shown, {@code false} otherwise. * @hide */ - public boolean requestImeShow(ResultReceiver resultReceiver) { + public boolean requestImeShow(IBinder windowToken) { synchronized (mH) { final View servedView = getServedViewLocked(); - if (servedView == null) { + if (servedView == null || servedView.getWindowToken() != windowToken) { return false; } - showSoftInput(servedView, 0 /* flags */, resultReceiver); + showSoftInput(servedView, 0 /* flags */, null /* resultReceiver */); return true; } } /** * Notify IME directly that it is no longer visible. + * + * @param windowToken the window from which this request originates. If this doesn't match the + * currently served view, the request is ignored. * @hide */ - public void notifyImeHidden() { + public void notifyImeHidden(IBinder windowToken) { synchronized (mH) { try { - if (mCurMethod != null) { + if (mCurMethod != null && mCurRootView != null + && mCurRootView.getWindowToken() == windowToken) { mCurMethod.notifyImeHidden(); } } catch (RemoteException re) { @@ -2140,15 +2148,15 @@ public final class InputMethodManager { /** * Notify IME directly to remove surface as it is no longer visible. + * @param windowToken The client window token that requests the IME to remove its surface. * @hide */ - public void removeImeSurface() { + public void removeImeSurface(IBinder windowToken) { synchronized (mH) { try { - if (mCurMethod != null) { - mCurMethod.removeImeSurface(); - } - } catch (RemoteException re) { + mService.removeImeSurfaceFromWindow(windowToken); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); } } } diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java index c5729b05c587..046981cf2e8f 100644 --- a/core/java/com/android/internal/policy/PhoneWindow.java +++ b/core/java/com/android/internal/policy/PhoneWindow.java @@ -21,8 +21,6 @@ import static android.provider.Settings.Global.DEVELOPMENT_RENDER_SHADOWS_IN_COM import static android.view.View.SYSTEM_UI_LAYOUT_FLAGS; import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; -import static android.view.WindowInsets.Type.ime; -import static android.view.WindowInsets.Type.systemBars; import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; import static android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN; import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR; @@ -34,8 +32,6 @@ import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS; import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS; -import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE; -import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST; import android.annotation.NonNull; import android.annotation.Nullable; @@ -146,17 +142,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { if ((view.getWindowSystemUiVisibility() & SYSTEM_UI_LAYOUT_FLAGS) != 0) { return new Pair<>(Insets.NONE, insets); } - - boolean includeIme = (view.getViewRootImpl().mWindowAttributes.softInputMode - & SOFT_INPUT_MASK_ADJUST) - == SOFT_INPUT_ADJUST_RESIZE; - Insets insetsToApply; - if (ViewRootImpl.sNewInsetsMode == 0) { - insetsToApply = insets.getSystemWindowInsets(); - } else { - insetsToApply = insets.getInsets(systemBars() | (includeIme ? ime() : 0)); - } - insets = insets.inset(insetsToApply); + Insets insetsToApply = insets.getSystemWindowInsets(); return new Pair<>(insetsToApply, insets.inset(insetsToApply).consumeSystemWindowInsets()); }; diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl index 8ec51b89d240..a1cbd3fcae79 100644 --- a/core/java/com/android/internal/view/IInputMethodManager.aidl +++ b/core/java/com/android/internal/view/IInputMethodManager.aidl @@ -73,5 +73,8 @@ interface IInputMethodManager { in float[] matrixValues); oneway void reportPerceptible(in IBinder windowToken, boolean perceptible); + /** Remove the IME surface. Requires INTERNAL_SYSTEM_WINDOW permission. */ void removeImeSurface(); + /** Remove the IME surface. Requires passing the currently focused window. */ + void removeImeSurfaceFromWindow(in IBinder windowToken); } diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml index 4640e4b699d6..5e245de3376e 100644 --- a/core/res/res/values-es/strings.xml +++ b/core/res/res/values-es/strings.xml @@ -1149,7 +1149,7 @@ <string name="whichImageCaptureApplicationNamed" msgid="8820702441847612202">"Capturar imagen con %1$s"</string> <string name="whichImageCaptureApplicationLabel" msgid="6505433734824988277">"Capturar imagen"</string> <string name="alwaysUse" msgid="3153558199076112903">"Usar siempre para esta acción"</string> - <string name="use_a_different_app" msgid="4987790276170972776">"Utiliza otra aplicación"</string> + <string name="use_a_different_app" msgid="4987790276170972776">"Usar otra aplicación"</string> <string name="clearDefaultHintMsg" msgid="1325866337702524936">"Para borrar los valores predeterminados, accede a Ajustes del sistema > Aplicaciones > Descargadas."</string> <string name="chooseActivity" msgid="8563390197659779956">"Selecciona una acción"</string> <string name="chooseUsbActivity" msgid="2096269989990986612">"Elegir una aplicación para el dispositivo USB"</string> diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml index c26cc66dbab4..cf08d242e635 100644 --- a/core/res/res/values-eu/strings.xml +++ b/core/res/res/values-eu/strings.xml @@ -1926,7 +1926,7 @@ <string name="time_picker_header_text" msgid="9073802285051516688">"Ezarri ordua"</string> <string name="time_picker_input_error" msgid="8386271930742451034">"Idatzi balio duen ordu bat"</string> <string name="time_picker_prompt_label" msgid="303588544656363889">"Idatzi ordua"</string> - <string name="time_picker_text_input_mode_description" msgid="4761160667516611576">"Aldatu testu modura ordua zehazteko."</string> + <string name="time_picker_text_input_mode_description" msgid="4761160667516611576">"Ordua idazteko, aldatu testua idazteko metodora."</string> <string name="time_picker_radial_mode_description" msgid="1222342577115016953">"Aldatu erloju modura ordua zehazteko."</string> <string name="autofill_picker_accessibility_title" msgid="4425806874792196599">"Betetze automatikoaren aukerak"</string> <string name="autofill_save_accessibility_title" msgid="1523225776218450005">"Gorde betetze automatikoarekin erabiltzeko"</string> diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml index 77a1fec768d7..1732d0846961 100644 --- a/core/res/res/values-gl/strings.xml +++ b/core/res/res/values-gl/strings.xml @@ -854,7 +854,7 @@ <string name="emergency_calls_only" msgid="3057351206678279851">"Só chamadas de emerxencia"</string> <string name="lockscreen_network_locked_message" msgid="2814046965899249635">"Bloqueada pola rede"</string> <string name="lockscreen_sim_puk_locked_message" msgid="6618356415831082174">"A tarxeta SIM está bloqueada con código PUK."</string> - <string name="lockscreen_sim_puk_locked_instructions" msgid="5307979043730860995">"Consulta a guía do usuario ou ponte en contacto co servizo de asistencia ao cliente."</string> + <string name="lockscreen_sim_puk_locked_instructions" msgid="5307979043730860995">"Consulta a guía para usuarios ou ponte en contacto co servizo de asistencia ao cliente."</string> <string name="lockscreen_sim_locked_message" msgid="3160196135801185938">"A tarxeta SIM está bloqueada."</string> <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="2286497117428409709">"Desbloqueando tarxeta SIM…"</string> <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="6458790975898594240">"Debuxaches incorrectamente o padrón de desbloqueo <xliff:g id="NUMBER_0">%1$d</xliff:g> veces. \n\nTéntao de novo en <xliff:g id="NUMBER_1">%2$d</xliff:g> segundos."</string> diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml index f5686c2ec12d..1604bea1e763 100644 --- a/core/res/res/values-ja/strings.xml +++ b/core/res/res/values-ja/strings.xml @@ -1149,7 +1149,7 @@ <string name="whichImageCaptureApplicationNamed" msgid="8820702441847612202">"「%1$s」を使用して画像をキャプチャ"</string> <string name="whichImageCaptureApplicationLabel" msgid="6505433734824988277">"画像をキャプチャ"</string> <string name="alwaysUse" msgid="3153558199076112903">"常にこの操作で使用する"</string> - <string name="use_a_different_app" msgid="4987790276170972776">"別のアプリの使用"</string> + <string name="use_a_different_app" msgid="4987790276170972776">"別のアプリを使用"</string> <string name="clearDefaultHintMsg" msgid="1325866337702524936">"[システム設定]>[アプリ]>[ダウンロード済み]でデフォルト設定をクリアします。"</string> <string name="chooseActivity" msgid="8563390197659779956">"操作の選択"</string> <string name="chooseUsbActivity" msgid="2096269989990986612">"USBデバイス用アプリを選択"</string> diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml index 28409e019a59..c55946e88ae9 100644 --- a/core/res/res/values-kk/strings.xml +++ b/core/res/res/values-kk/strings.xml @@ -1547,7 +1547,7 @@ <string name="sending" msgid="206925243621664438">"Жіберілуде..."</string> <string name="launchBrowserDefault" msgid="6328349989932924119">"Браузер қосылсын ба?"</string> <string name="SetupCallDefault" msgid="5581740063237175247">"Қоңырауды қабылдау?"</string> - <string name="activity_resolver_use_always" msgid="5575222334666843269">"Үнемі"</string> + <string name="activity_resolver_use_always" msgid="5575222334666843269">"Әрқашан"</string> <string name="activity_resolver_use_once" msgid="948462794469672658">"Бір рет қана"</string> <string name="activity_resolver_work_profiles_support" msgid="4071345609235361269">"%1$s жұмыс профилін қолдамайды"</string> <string name="default_audio_route_name" product="tablet" msgid="367936735632195517">"Планшет"</string> diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml index a86636218292..5908475eec04 100644 --- a/core/res/res/values-ky/strings.xml +++ b/core/res/res/values-ky/strings.xml @@ -536,7 +536,7 @@ <string name="permdesc_imagesWrite" msgid="5195054463269193317">"Колдонмого сүрөт жыйнагыңызды өзгөртүүгө мүмкүнчүлүк берет."</string> <string name="permlab_mediaLocation" msgid="7368098373378598066">"медиа жыйнагыңыз сакталган жерлерди окуу"</string> <string name="permdesc_mediaLocation" msgid="597912899423578138">"Колдонмого медиа жыйнагыңыз сакталган жерлерди окууга мүмкүнчүлүк берет."</string> - <string name="biometric_dialog_default_title" msgid="55026799173208210">"Сиз экениңизди ырастаңыз"</string> + <string name="biometric_dialog_default_title" msgid="55026799173208210">"Өзүңүздү ырастаңыз"</string> <string name="biometric_error_hw_unavailable" msgid="2494077380540615216">"Биометрикалык аппарат жеткиликсиз"</string> <string name="biometric_error_user_canceled" msgid="6732303949695293730">"Аныктыгын текшерүү жокко чыгарылды"</string> <string name="biometric_not_recognized" msgid="5106687642694635888">"Таанылган жок"</string> @@ -1547,7 +1547,7 @@ <string name="sending" msgid="206925243621664438">"Жөнөтүлүүдө…"</string> <string name="launchBrowserDefault" msgid="6328349989932924119">"Серепчи иштетилсинби?"</string> <string name="SetupCallDefault" msgid="5581740063237175247">"Чалуу кабыл алынсынбы?"</string> - <string name="activity_resolver_use_always" msgid="5575222334666843269">"Дайыма"</string> + <string name="activity_resolver_use_always" msgid="5575222334666843269">"Ар дайым"</string> <string name="activity_resolver_use_once" msgid="948462794469672658">"Бир жолу гана"</string> <string name="activity_resolver_work_profiles_support" msgid="4071345609235361269">"%1$s жумуш профилин колдоого албайт"</string> <string name="default_audio_route_name" product="tablet" msgid="367936735632195517">"Планшет"</string> diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml index 05337584d774..e07a81d5892a 100644 --- a/core/res/res/values-uz/strings.xml +++ b/core/res/res/values-uz/strings.xml @@ -1090,7 +1090,7 @@ <string name="elapsed_time_short_format_mm_ss" msgid="8689459651807876423">"<xliff:g id="MINUTES">%1$02d</xliff:g>:<xliff:g id="SECONDS">%2$02d</xliff:g>"</string> <string name="elapsed_time_short_format_h_mm_ss" msgid="2302144714803345056">"<xliff:g id="HOURS">%1$d</xliff:g>:<xliff:g id="MINUTES">%2$02d</xliff:g>:<xliff:g id="SECONDS">%3$02d</xliff:g>"</string> <string name="selectAll" msgid="1532369154488982046">"Hammasini belgilash"</string> - <string name="cut" msgid="2561199725874745819">"Kesish"</string> + <string name="cut" msgid="2561199725874745819">"Kesib olish"</string> <string name="copy" msgid="5472512047143665218">"Nusxa olish"</string> <string name="failed_to_copy_to_clipboard" msgid="725919885138539875">"Vaqtinchalik xotiraga nusxalab bo‘lmadi"</string> <string name="paste" msgid="461843306215520225">"Joylash"</string> diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml index 69358d44d737..72dd4581e8fe 100644 --- a/core/res/res/values-zh-rTW/strings.xml +++ b/core/res/res/values-zh-rTW/strings.xml @@ -1792,8 +1792,8 @@ <string name="package_updated_device_owner" msgid="7560272363805506941">"已由你的管理員更新"</string> <string name="package_deleted_device_owner" msgid="2292335928930293023">"已由你的管理員刪除"</string> <string name="confirm_battery_saver" msgid="5247976246208245754">"確定"</string> - <string name="battery_saver_description_with_learn_more" msgid="5997766757551917769">"為了延長電池續航力,節約耗電量功能會執行以下動作:\n\n•開啟深色主題\n•關閉或限制背景活動、部分視覺效果和其他功能,例如「Hey Google」啟動字詞\n\n"<annotation id="url">"瞭解詳情"</annotation></string> - <string name="battery_saver_description" msgid="8587408568232177204">"為了延長電池續航力,節約耗電量功能會執行以下動作:\n\n•開啟深色主題\n•關閉或限制背景活動、部分視覺效果和其他功能,例如「Hey Google」啟動字詞"</string> + <string name="battery_saver_description_with_learn_more" msgid="5997766757551917769">"為了延長電池續航力,省電模式會執行以下動作:\n\n•開啟深色主題\n•關閉或限制背景活動、部分視覺效果和其他功能,例如「Hey Google」啟動字詞\n\n"<annotation id="url">"瞭解詳情"</annotation></string> + <string name="battery_saver_description" msgid="8587408568232177204">"為了延長電池續航力,省電模式會執行以下動作:\n\n•開啟深色主題\n•關閉或限制背景活動、部分視覺效果和其他功能,例如「Hey Google」啟動字詞"</string> <string name="data_saver_description" msgid="4995164271550590517">"「數據節省模式」可防止部分應用程式在背景收發資料,以節省數據用量。你目前使用的應用程式可以存取資料,但存取頻率可能不如平時高。舉例來說,圖片可能不會自動顯示,在你輕觸後才會顯示。"</string> <string name="data_saver_enable_title" msgid="7080620065745260137">"要開啟數據節省模式嗎?"</string> <string name="data_saver_enable_button" msgid="4399405762586419726">"開啟"</string> @@ -1999,9 +1999,9 @@ <string name="notification_appops_overlay_active" msgid="5571732753262836481">"顯示在畫面上的其他應用程式上層"</string> <string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"日常安排模式資訊通知"</string> <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"電池電力可能會在你平常的充電時間前耗盡"</string> - <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"已啟用節約耗電量模式以延長電池續航力"</string> - <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"節約耗電量"</string> - <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"節約耗電量模式已關閉"</string> + <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"已啟用省電模式以延長電池續航力"</string> + <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"省電模式"</string> + <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"省電模式已關閉"</string> <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"手機電力充足,各項功能不再受到限制。"</string> <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"平板電腦電力充足,各項功能不再受到限制。"</string> <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"裝置電力充足,各項功能不再受到限制。"</string> diff --git a/core/tests/coretests/src/android/view/InsetsControllerTest.java b/core/tests/coretests/src/android/view/InsetsControllerTest.java index 702f2fa65487..c36f1067149e 100644 --- a/core/tests/coretests/src/android/view/InsetsControllerTest.java +++ b/core/tests/coretests/src/android/view/InsetsControllerTest.java @@ -691,18 +691,57 @@ public class InsetsControllerTest { @Test public void testRequestedState() { InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> { + + // The modified state can be controlled when we have control. mController.onControlsChanged(createSingletonControl(ITYPE_STATUS_BAR)); mController.hide(statusBars()); assertFalse(mTestHost.getModifiedState().peekSource(ITYPE_STATUS_BAR).isVisible()); - mController.onControlsChanged(new InsetsSourceControl[0]); + + // The modified state won't be changed while losing control. + mController.onControlsChanged(null /* activeControls */); assertFalse(mTestHost.getModifiedState().peekSource(ITYPE_STATUS_BAR).isVisible()); + + // The modified state won't be changed while state changed while we don't have control. InsetsState newState = new InsetsState(mController.getState(), true /* copySource */); mController.onStateChanged(newState); assertFalse(mTestHost.getModifiedState().peekSource(ITYPE_STATUS_BAR).isVisible()); + + // The modified state won't be changed while controlling an insets without having the + // control. mController.show(statusBars()); assertFalse(mTestHost.getModifiedState().peekSource(ITYPE_STATUS_BAR).isVisible()); + + // The modified state can be updated while gaining control. mController.onControlsChanged(createSingletonControl(ITYPE_STATUS_BAR)); assertTrue(mTestHost.getModifiedState().peekSource(ITYPE_STATUS_BAR).isVisible()); + + // The modified state can still be updated if the local state and the requested state + // are the same. + mController.onControlsChanged(null /* activeControls */); + mController.hide(statusBars()); + newState = new InsetsState(mController.getState(), true /* copySource */); + newState.getSource(ITYPE_STATUS_BAR).setVisible(false); + mController.onStateChanged(newState); + mController.onControlsChanged(createSingletonControl(ITYPE_STATUS_BAR)); + assertFalse(mTestHost.getModifiedState().peekSource(ITYPE_STATUS_BAR).isVisible()); + + // The modified state will always be updated while receiving IME control if IME is + // requested visible. + mController.getSourceConsumer(ITYPE_IME).show(false /* fromIme */); + newState = new InsetsState(mController.getState(), true /* copySource */); + newState.getSource(ITYPE_IME).setVisible(true); + newState.getSource(ITYPE_IME).setFrame(1, 2, 3, 4); + mController.onStateChanged(newState); + mController.onControlsChanged(createSingletonControl(ITYPE_IME)); + assertEquals(newState.getSource(ITYPE_IME), + mTestHost.getModifiedState().peekSource(ITYPE_IME)); + newState = new InsetsState(mController.getState(), true /* copySource */); + newState.getSource(ITYPE_IME).setVisible(true); + newState.getSource(ITYPE_IME).setFrame(5, 6, 7, 8); + mController.onStateChanged(newState); + mController.onControlsChanged(createSingletonControl(ITYPE_IME)); + assertEquals(newState.getSource(ITYPE_IME), + mTestHost.getModifiedState().peekSource(ITYPE_IME)); }); } diff --git a/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java b/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java index 1b3272572db0..7efd616c5607 100644 --- a/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java +++ b/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java @@ -71,6 +71,9 @@ public class InsetsSourceConsumerTest { private SurfaceControl mLeash; @Mock Transaction mMockTransaction; private InsetsSource mSpyInsetsSource; + private boolean mRemoveSurfaceCalled = false; + private InsetsController mController; + private InsetsState mState; @Before public void setup() { @@ -89,13 +92,19 @@ public class InsetsSourceConsumerTest { } catch (BadTokenException e) { // activity isn't running, lets ignore BadTokenException. } - InsetsState state = new InsetsState(); + mState = new InsetsState(); mSpyInsetsSource = Mockito.spy(new InsetsSource(ITYPE_STATUS_BAR)); - state.addSource(mSpyInsetsSource); - - mConsumer = new InsetsSourceConsumer(ITYPE_STATUS_BAR, state, - () -> mMockTransaction, - new InsetsController(new ViewRootInsetsControllerHost(viewRootImpl))); + mState.addSource(mSpyInsetsSource); + + mController = new InsetsController(new ViewRootInsetsControllerHost(viewRootImpl)); + mConsumer = new InsetsSourceConsumer(ITYPE_STATUS_BAR, mState, + () -> mMockTransaction, mController) { + @Override + public void removeSurface() { + super.removeSurface(); + mRemoveSurfaceCalled = true; + } + }; }); instrumentation.waitForIdleSync(); @@ -171,6 +180,25 @@ public class InsetsSourceConsumerTest { mConsumer.setControl(new InsetsSourceControl(ITYPE_STATUS_BAR, mLeash, new Point()), new int[1], hideTypes); assertEquals(statusBars(), hideTypes[0]); + assertFalse(mRemoveSurfaceCalled); + }); + } + + @Test + public void testRestore_noAnimation() { + InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> { + mConsumer.hide(); + mController.onStateChanged(mState); + mConsumer.setControl(null, new int[1], new int[1]); + reset(mMockTransaction); + verifyZeroInteractions(mMockTransaction); + mRemoveSurfaceCalled = false; + int[] hideTypes = new int[1]; + mConsumer.setControl(new InsetsSourceControl(ITYPE_STATUS_BAR, mLeash, new Point()), + new int[1], hideTypes); + assertTrue(mRemoveSurfaceCalled); + assertEquals(0, hideTypes[0]); }); + } } diff --git a/packages/SystemUI/src/com/android/systemui/wm/DisplayImeController.java b/packages/SystemUI/src/com/android/systemui/wm/DisplayImeController.java index 8ba5b9951c54..c0089e53f8b6 100644 --- a/packages/SystemUI/src/com/android/systemui/wm/DisplayImeController.java +++ b/packages/SystemUI/src/com/android/systemui/wm/DisplayImeController.java @@ -226,6 +226,8 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged if (!activeControl.getSurfacePosition().equals(lastSurfacePosition) && mAnimation != null) { startAnimation(mImeShowing, true /* forceRestart */); + } else if (!mImeShowing) { + removeImeSurface(); } }); } @@ -370,16 +372,7 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged dispatchEndPositioning(mDisplayId, mCancelled, t); if (mAnimationDirection == DIRECTION_HIDE && !mCancelled) { t.hide(mImeSourceControl.getLeash()); - final IInputMethodManager imms = getImms(); - if (imms != null) { - try { - // Remove the IME surface to make the insets invisible for - // non-client controlled insets. - imms.removeImeSurface(); - } catch (RemoteException e) { - Slog.e(TAG, "Failed to remove IME surface.", e); - } - } + removeImeSurface(); } t.apply(); mTransactionPool.release(t); @@ -402,6 +395,19 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged } } + void removeImeSurface() { + final IInputMethodManager imms = getImms(); + if (imms != null) { + try { + // Remove the IME surface to make the insets invisible for + // non-client controlled insets. + imms.removeImeSurface(); + } catch (RemoteException e) { + Slog.e(TAG, "Failed to remove IME surface.", e); + } + } + } + /** * Allows other things to synchronize with the ime position */ diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java index 5124c4a4797e..a2eea1348d5c 100644 --- a/services/core/java/com/android/server/am/BroadcastQueue.java +++ b/services/core/java/com/android/server/am/BroadcastQueue.java @@ -470,22 +470,23 @@ public final class BroadcastQueue { // if this receiver was slow, impose deferral policy on the app. This will kick in // when processNextBroadcastLocked() next finds this uid as a receiver identity. if (!r.timeoutExempt) { - if (mConstants.SLOW_TIME > 0 && elapsed > mConstants.SLOW_TIME) { + // r.curApp can be null if finish has raced with process death - benign + // edge case, and we just ignore it because we're already cleaning up + // as expected. + if (r.curApp != null + && mConstants.SLOW_TIME > 0 && elapsed > mConstants.SLOW_TIME) { // Core system packages are exempt from deferral policy if (!UserHandle.isCore(r.curApp.uid)) { if (DEBUG_BROADCAST_DEFERRAL) { Slog.i(TAG_BROADCAST, "Broadcast receiver " + (r.nextReceiver - 1) + " was slow: " + receiver + " br=" + r); } - if (r.curApp != null) { - mDispatcher.startDeferring(r.curApp.uid); - } else { - Slog.d(TAG_BROADCAST, "finish receiver curApp is null? " + r); - } + mDispatcher.startDeferring(r.curApp.uid); } else { if (DEBUG_BROADCAST_DEFERRAL) { Slog.i(TAG_BROADCAST, "Core uid " + r.curApp.uid - + " receiver was slow but not deferring: " + receiver + " br=" + r); + + " receiver was slow but not deferring: " + + receiver + " br=" + r); } } } diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerInternal.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerInternal.java index 70f0399d1070..05cf40a091b6 100644 --- a/services/core/java/com/android/server/inputmethod/InputMethodManagerInternal.java +++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerInternal.java @@ -120,6 +120,11 @@ public abstract class InputMethodManagerInternal { public abstract void reportImeControl(@Nullable IBinder windowToken); /** + * Destroys the IME surface. + */ + public abstract void removeImeSurface(); + + /** * Fake implementation of {@link InputMethodManagerInternal}. All the methods do nothing. */ private static final InputMethodManagerInternal NOP = @@ -166,6 +171,10 @@ public abstract class InputMethodManagerInternal { @Override public void reportImeControl(@Nullable IBinder windowToken) { } + + @Override + public void removeImeSurface() { + } }; /** diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java index c027ebcfd568..d8ee32e7bd74 100644 --- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java +++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java @@ -211,6 +211,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub static final int MSG_INITIALIZE_IME = 1040; static final int MSG_CREATE_SESSION = 1050; static final int MSG_REMOVE_IME_SURFACE = 1060; + static final int MSG_REMOVE_IME_SURFACE_FROM_WINDOW = 1061; static final int MSG_START_INPUT = 2000; @@ -4005,6 +4006,13 @@ public class InputMethodManagerService extends IInputMethodManager.Stub mHandler.sendMessage(mHandler.obtainMessage(MSG_REMOVE_IME_SURFACE)); } + @Override + public void removeImeSurfaceFromWindow(IBinder windowToken) { + // No permission check, because we'll only execute the request if the calling window is + // also the current IME client. + mHandler.obtainMessage(MSG_REMOVE_IME_SURFACE_FROM_WINDOW, windowToken).sendToTarget(); + } + @BinderThread private void notifyUserAction(@NonNull IBinder token) { if (DEBUG) { @@ -4278,11 +4286,27 @@ public class InputMethodManagerService extends IInputMethodManager.Stub return true; } case MSG_REMOVE_IME_SURFACE: { - try { - if (mEnabledSession != null && mEnabledSession.session != null) { - mEnabledSession.session.removeImeSurface(); + synchronized (mMethodMap) { + try { + if (mEnabledSession != null && mEnabledSession.session != null + && !mShowRequested) { + mEnabledSession.session.removeImeSurface(); + } + } catch (RemoteException e) { + } + } + return true; + } + case MSG_REMOVE_IME_SURFACE_FROM_WINDOW: { + IBinder windowToken = (IBinder) msg.obj; + synchronized (mMethodMap) { + try { + if (windowToken == mCurFocusedWindow + && mEnabledSession != null && mEnabledSession.session != null) { + mEnabledSession.session.removeImeSurface(); + } + } catch (RemoteException e) { } - } catch (RemoteException e) { } return true; } @@ -5116,6 +5140,11 @@ public class InputMethodManagerService extends IInputMethodManager.Stub public void reportImeControl(@Nullable IBinder windowToken) { mService.reportImeControl(windowToken); } + + @Override + public void removeImeSurface() { + mService.mHandler.sendMessage(mService.mHandler.obtainMessage(MSG_REMOVE_IME_SURFACE)); + } } @BinderThread diff --git a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java index 2e3d3963c9df..19dff9807075 100644 --- a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java +++ b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java @@ -225,6 +225,11 @@ public final class MultiClientInputMethodManagerService { @Override public void reportImeControl(@Nullable IBinder windowToken) { } + + @Override + public void removeImeSurface() { + reportNotSupported(); + } }); } @@ -1473,6 +1478,12 @@ public final class MultiClientInputMethodManagerService { @BinderThread @Override + public void removeImeSurfaceFromWindow(IBinder windowToken) { + reportNotSupported(); + } + + @BinderThread + @Override public boolean showSoftInput( IInputMethodClient client, IBinder token, int flags, ResultReceiver resultReceiver) { diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java index 91b2ea1853fa..08cdd8f05292 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerService.java +++ b/services/core/java/com/android/server/pm/PackageInstallerService.java @@ -589,12 +589,12 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements } } - if (mBypassNextStagedInstallerCheck) { - mBypassNextStagedInstallerCheck = false; - } else if (params.isStaged - && !isCalledBySystemOrShell(callingUid) - && !isWhitelistedStagedInstaller(requestedInstallerPackageName)) { - throw new SecurityException("Installer not allowed to commit staged install"); + if (params.isStaged && !isCalledBySystemOrShell(callingUid)) { + if (mBypassNextStagedInstallerCheck) { + mBypassNextStagedInstallerCheck = false; + } else if (!isStagedInstallerAllowed(requestedInstallerPackageName)) { + throw new SecurityException("Installer not allowed to commit staged install"); + } } if (!params.isMultiPackage) { @@ -725,7 +725,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements || callingUid == Process.SHELL_UID; } - private boolean isWhitelistedStagedInstaller(String installerName) { + private boolean isStagedInstallerAllowed(String installerName) { return SystemConfig.getInstance().getWhitelistedStagedInstallers().contains(installerName); } diff --git a/services/core/java/com/android/server/uri/UriGrantsManagerService.java b/services/core/java/com/android/server/uri/UriGrantsManagerService.java index c38d649ada9b..4b3ddd856c61 100644 --- a/services/core/java/com/android/server/uri/UriGrantsManagerService.java +++ b/services/core/java/com/android/server/uri/UriGrantsManagerService.java @@ -114,7 +114,7 @@ public class UriGrantsManagerService extends IUriGrantsManager.Stub { private static final boolean DEBUG = false; private static final String TAG = "UriGrantsManagerService"; // Maximum number of persisted Uri grants a package is allowed - private static final int MAX_PERSISTED_URI_GRANTS = 128; + private static final int MAX_PERSISTED_URI_GRANTS = 512; private static final boolean ENABLE_DYNAMIC_PERMISSIONS = false; private final Object mLock = new Object(); diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index e8a4234f44a7..b94fb0471af4 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -3574,12 +3574,11 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo } } - private void updateImeControlTarget() { + void updateImeControlTarget() { mInputMethodControlTarget = computeImeControlTarget(); mInsetsStateController.onImeControlTargetChanged(mInputMethodControlTarget); - final WindowState win = mInputMethodControlTarget != null - ? mInputMethodControlTarget.getWindow() : null; + final WindowState win = InsetsControlTarget.asWindowOrNull(mInputMethodControlTarget); final IBinder token = win != null ? win.mClient.asBinder() : null; // Note: not allowed to call into IMMS with the WM lock held, hence the post. mWmService.mH.post(() -> @@ -3603,6 +3602,17 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo if (!isImeControlledByApp() && mRemoteInsetsControlTarget != null) { return mRemoteInsetsControlTarget; } else { + // Now, a special case -- if the last target's window is in the process of exiting, but + // not removed, keep on the last target to avoid IME flicker. + final WindowState cur = InsetsControlTarget.asWindowOrNull(mInputMethodControlTarget); + if (cur != null && !cur.mRemoved && cur.isDisplayedLw() && cur.isClosing() + && !cur.isActivityTypeHome()) { + if (DEBUG_INPUT_METHOD) { + Slog.v(TAG_WM, "Not changing control while current window" + + " is closing and not removed"); + } + return cur; + } // Otherwise, we just use the ime target as received from IME. return mInputMethodInputTarget; } diff --git a/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java b/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java index 8298763c1392..99ee5e121b7a 100644 --- a/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java +++ b/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java @@ -18,13 +18,14 @@ package com.android.server.wm; import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_IME; -import android.graphics.PixelFormat; import android.view.InsetsSource; import android.view.WindowInsets; import com.android.internal.annotations.VisibleForTesting; import com.android.server.protolog.common.ProtoLog; +import java.io.PrintWriter; + /** * Controller for IME inset source on the server. It's called provider as it provides the * {@link InsetsSource} to the client that uses it in {@link InsetsSourceConsumer}. @@ -132,8 +133,17 @@ class ImeInsetsSourceProvider extends InsetsSourceProvider { || (mImeTargetFromIme != null && dcTarget.getParentWindow() == mImeTargetFromIme && dcTarget.mSubLayer > mImeTargetFromIme.mSubLayer) || mImeTargetFromIme == mDisplayContent.getImeFallback() - // If IME target is transparent but control target matches requesting window. - || (controlTarget == mImeTargetFromIme - && PixelFormat.formatHasAlpha(dcTarget.mAttrs.format)); + || (!mImeTargetFromIme.isClosing() && controlTarget == mImeTargetFromIme); + } + + @Override + public void dump(PrintWriter pw, String prefix) { + super.dump(pw, prefix); + if (mImeTargetFromIme != null) { + pw.print(prefix); + pw.print("showImePostLayout pending for mImeTargetFromIme="); + pw.print(mImeTargetFromIme); + pw.println(); + } } } diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java index 8734b5efa45d..0216db471843 100644 --- a/services/core/java/com/android/server/wm/InputMonitor.java +++ b/services/core/java/com/android/server/wm/InputMonitor.java @@ -16,13 +16,14 @@ package com.android.server.wm; -import static android.os.Process.myPid; -import static android.os.Process.myUid; import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; +import static android.view.Display.INVALID_DISPLAY; import static android.view.WindowManager.INPUT_CONSUMER_NAVIGATION; import static android.view.WindowManager.INPUT_CONSUMER_PIP; import static android.view.WindowManager.INPUT_CONSUMER_RECENTS_ANIMATION; import static android.view.WindowManager.INPUT_CONSUMER_WALLPAPER; +import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; +import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL; import static android.view.WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_DISABLE_WALLPAPER_TOUCH_EVENTS; @@ -477,12 +478,18 @@ final class InputMonitor { mService.getRecentsAnimationController(); final boolean shouldApplyRecentsInputConsumer = recentsAnimationController != null && recentsAnimationController.shouldApplyInputConsumer(w.mActivityRecord); + final int type = w.mAttrs.type; + final boolean isVisible = w.isVisibleLw(); if (inputChannel == null || inputWindowHandle == null || w.mRemoved || (w.cantReceiveTouchInput() && !shouldApplyRecentsInputConsumer)) { if (w.mWinAnimator.hasSurface()) { + // Assign an InputInfo with type to the overlay window which can't receive input + // event. This is used to omit Surfaces from occlusion detection. + populateOverlayInputInfo(mInvalidInputWindow, w.getName(), type, isVisible); mInputTransaction.setInputWindowInfo( - w.mWinAnimator.mSurfaceController.getClientViewRootSurface(), - mInvalidInputWindow); + w.mWinAnimator.mSurfaceController.getClientViewRootSurface(), + mInvalidInputWindow); + return; } // Skip this window because it cannot possibly receive input. return; @@ -490,9 +497,7 @@ final class InputMonitor { final int flags = w.mAttrs.flags; final int privateFlags = w.mAttrs.privateFlags; - final int type = w.mAttrs.type; final boolean hasFocus = w.isFocused(); - final boolean isVisible = w.isVisibleLw(); if (mAddRecentsAnimationInputConsumerHandle && shouldApplyRecentsInputConsumer) { if (recentsAnimationController.updateInputConsumerForApp( @@ -555,6 +560,26 @@ final class InputMonitor { } } + // This would reset InputWindowHandle fields to prevent it could be found by input event. + // We need to check if any new field of InputWindowHandle could impact the result. + private static void populateOverlayInputInfo(final InputWindowHandle inputWindowHandle, + final String name, final int type, final boolean isVisible) { + inputWindowHandle.name = name; + inputWindowHandle.layoutParamsType = type; + inputWindowHandle.dispatchingTimeoutNanos = + WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS; + inputWindowHandle.visible = isVisible; + inputWindowHandle.canReceiveKeys = false; + inputWindowHandle.hasFocus = false; + inputWindowHandle.inputFeatures = INPUT_FEATURE_NO_INPUT_CHANNEL; + inputWindowHandle.scaleFactor = 1; + inputWindowHandle.layoutParamsFlags = + FLAG_NOT_TOUCH_MODAL | FLAG_NOT_TOUCHABLE | FLAG_NOT_FOCUSABLE; + inputWindowHandle.portalToDisplayId = INVALID_DISPLAY; + inputWindowHandle.touchableRegion.setEmpty(); + inputWindowHandle.setTouchableRegionCrop(null); + } + /** * Helper function to generate an InputInfo with type SECURE_SYSTEM_OVERLAY. This input * info will not have an input channel or be touchable, but is used to omit Surfaces @@ -564,16 +589,7 @@ final class InputMonitor { static void setTrustedOverlayInputInfo(SurfaceControl sc, SurfaceControl.Transaction t, int displayId, String name) { InputWindowHandle inputWindowHandle = new InputWindowHandle(null, displayId); - inputWindowHandle.name = name; - inputWindowHandle.layoutParamsType = TYPE_SECURE_SYSTEM_OVERLAY; - inputWindowHandle.dispatchingTimeoutNanos = -1; - inputWindowHandle.visible = true; - inputWindowHandle.canReceiveKeys = false; - inputWindowHandle.hasFocus = false; - inputWindowHandle.ownerPid = myPid(); - inputWindowHandle.ownerUid = myUid(); - inputWindowHandle.inputFeatures = INPUT_FEATURE_NO_INPUT_CHANNEL; - inputWindowHandle.scaleFactor = 1; + populateOverlayInputInfo(inputWindowHandle, name, TYPE_SECURE_SYSTEM_OVERLAY, true); t.setInputWindowInfo(sc, inputWindowHandle); } } diff --git a/services/core/java/com/android/server/wm/InsetsControlTarget.java b/services/core/java/com/android/server/wm/InsetsControlTarget.java index c50f296504fc..3ffc26a7a8ad 100644 --- a/services/core/java/com/android/server/wm/InsetsControlTarget.java +++ b/services/core/java/com/android/server/wm/InsetsControlTarget.java @@ -62,4 +62,8 @@ interface InsetsControlTarget { return false; } + /** Returns {@code target.getWindow()}, or null if {@code target} is {@code null}. */ + static WindowState asWindowOrNull(InsetsControlTarget target) { + return target != null ? target.getWindow() : null; + } } diff --git a/services/core/java/com/android/server/wm/InsetsStateController.java b/services/core/java/com/android/server/wm/InsetsStateController.java index 63083faaddb1..77bd4a47a884 100644 --- a/services/core/java/com/android/server/wm/InsetsStateController.java +++ b/services/core/java/com/android/server/wm/InsetsStateController.java @@ -44,6 +44,7 @@ import android.view.InsetsState; import android.view.InsetsState.InternalInsetsType; import android.view.WindowManager; +import com.android.server.inputmethod.InputMethodManagerInternal; import com.android.server.protolog.common.ProtoLog; import java.io.PrintWriter; @@ -74,7 +75,21 @@ class InsetsStateController { w.notifyInsetsChanged(); } }; - private final InsetsControlTarget mEmptyImeControlTarget = new InsetsControlTarget() { }; + private final InsetsControlTarget mEmptyImeControlTarget = new InsetsControlTarget() { + @Override + public void notifyInsetsControlChanged() { + InsetsSourceControl[] controls = getControlsForDispatch(this); + if (controls == null) { + return; + } + for (InsetsSourceControl control : controls) { + if (control.getType() == ITYPE_IME) { + mDisplayContent.mWmService.mH.post(() -> + InputMethodManagerInternal.get().removeImeSurface()); + } + } + } + }; InsetsStateController(DisplayContent displayContent) { mDisplayContent = displayContent; diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 837fafec1634..00be75fddf04 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -2170,6 +2170,9 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP if (isInputMethodTarget()) { dc.computeImeTarget(true /* updateImeTarget */); } + if (dc.mInputMethodControlTarget == this) { + dc.updateImeControlTarget(); + } final int type = mAttrs.type; if (WindowManagerService.excludeWindowTypeFromTapOutTask(type)) { diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java index 77e3c597311c..d64fdb81107c 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java @@ -898,6 +898,26 @@ public class DisplayContentTests extends WindowTestsBase { } @Test + public void testComputeImeControlTarget_exitingApp() throws Exception { + final DisplayContent dc = createNewDisplay(); + + WindowState exitingWin = createWindow(null, TYPE_BASE_APPLICATION, "exiting app"); + makeWindowVisible(exitingWin); + exitingWin.mWinAnimator.mDrawState = WindowStateAnimator.HAS_DRAWN; + exitingWin.mAnimatingExit = true; + + dc.mInputMethodControlTarget = exitingWin; + dc.mInputMethodTarget = dc.mInputMethodInputTarget = + createWindow(null, TYPE_BASE_APPLICATION, "starting app"); + + assertEquals(exitingWin, dc.computeImeControlTarget()); + + exitingWin.removeImmediately(); + + assertEquals(dc.mInputMethodInputTarget, dc.computeImeControlTarget()); + } + + @Test public void testComputeImeControlTarget_splitscreen() throws Exception { final DisplayContent dc = createNewDisplay(); dc.mInputMethodInputTarget = createWindow(null, TYPE_BASE_APPLICATION, "app"); |