Loading core/java/android/widget/Toast.java +14 −69 Original line number Diff line number Diff line Loading @@ -31,9 +31,7 @@ import android.compat.annotation.ChangeId; import android.compat.annotation.EnabledAfter; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.content.res.Configuration; import android.content.res.Resources; import android.graphics.PixelFormat; import android.os.Binder; import android.os.Build; import android.os.Handler; Loading @@ -43,11 +41,8 @@ import android.os.Message; import android.os.RemoteException; import android.os.ServiceManager; import android.util.Log; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.WindowManager; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityManager; import com.android.internal.annotations.GuardedBy; Loading Loading @@ -122,6 +117,7 @@ public class Toast { private final Binder mToken; private final Context mContext; private final Handler mHandler; private final ToastPresenter mPresenter; @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) final TN mTN; @UnsupportedAppUsage Loading Loading @@ -172,7 +168,8 @@ public class Toast { looper = getLooper(looper); mHandler = new Handler(looper); mCallbacks = new ArrayList<>(); mTN = new TN(context.getPackageName(), mToken, mCallbacks, looper); mPresenter = new ToastPresenter(context, AccessibilityManager.getInstance(context)); mTN = new TN(mPresenter, context.getPackageName(), mToken, mCallbacks, looper); mTN.mY = context.getResources().getDimensionPixelSize( com.android.internal.R.dimen.toast_y_offset); mTN.mGravity = context.getResources().getInteger( Loading Loading @@ -504,13 +501,7 @@ public class Toast { return result; } else { Toast result = new Toast(context, looper); LayoutInflater inflate = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); View v = inflate.inflate(com.android.internal.R.layout.transient_notification, null); TextView tv = (TextView) v.findViewById(com.android.internal.R.id.message); tv.setText(text); View v = result.mPresenter.getTextToastView(text); result.mNextView = v; result.mDuration = duration; Loading Loading @@ -611,34 +602,20 @@ public class Toast { final String mPackageName; final Binder mToken; private final ToastPresenter mPresenter; @GuardedBy("mCallbacks") private final List<Callback> mCallbacks; static final long SHORT_DURATION_TIMEOUT = 4000; static final long LONG_DURATION_TIMEOUT = 7000; /** * Creates a {@link ITransientNotification} object. * * The parameter {@code callbacks} is not copied and is accessed with itself as its own * lock. */ TN(String packageName, Binder token, List<Callback> callbacks, @Nullable Looper looper) { // XXX This should be changed to use a Dialog, with a Theme.Toast // defined that sets up the layout params appropriately. final WindowManager.LayoutParams params = mParams; params.height = WindowManager.LayoutParams.WRAP_CONTENT; params.width = WindowManager.LayoutParams.WRAP_CONTENT; params.format = PixelFormat.TRANSLUCENT; params.windowAnimations = com.android.internal.R.style.Animation_Toast; params.type = WindowManager.LayoutParams.TYPE_TOAST; params.setFitInsetsIgnoringVisibility(true); params.setTitle("Toast"); params.flags = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; TN(ToastPresenter presenter, String packageName, Binder token, List<Callback> callbacks, @Nullable Looper looper) { mPresenter = presenter; mPackageName = packageName; mToken = token; mCallbacks = callbacks; Loading Loading @@ -673,6 +650,8 @@ public class Toast { } } }; presenter.startLayoutParams(mParams); } private List<Callback> getCallbacks() { Loading Loading @@ -718,30 +697,12 @@ public class Toast { handleHide(); mView = mNextView; Context context = mView.getContext().getApplicationContext(); String packageName = mView.getContext().getOpPackageName(); if (context == null) { context = mView.getContext(); } mWM = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); // We can resolve the Gravity here by using the Locale for getting // the layout direction final Configuration config = mView.getContext().getResources().getConfiguration(); final int gravity = Gravity.getAbsoluteGravity(mGravity, config.getLayoutDirection()); mParams.gravity = gravity; if ((gravity & Gravity.HORIZONTAL_GRAVITY_MASK) == Gravity.FILL_HORIZONTAL) { mParams.horizontalWeight = 1.0f; } if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == Gravity.FILL_VERTICAL) { mParams.verticalWeight = 1.0f; } mParams.x = mX; mParams.y = mY; mParams.verticalMargin = mVerticalMargin; mParams.horizontalMargin = mHorizontalMargin; mParams.packageName = packageName; mParams.hideTimeoutMilliseconds = mDuration == Toast.LENGTH_LONG ? LONG_DURATION_TIMEOUT : SHORT_DURATION_TIMEOUT; mParams.token = windowToken; mPresenter.adjustLayoutParams(mParams, windowToken, mDuration, mGravity, mX, mY, mHorizontalMargin, mVerticalMargin); if (mView.getParent() != null) { if (localLOGV) Log.v(TAG, "REMOVE! " + mView + " in " + this); mWM.removeView(mView); Loading @@ -753,7 +714,7 @@ public class Toast { // invalidated. Let us hedge against that. try { mWM.addView(mView, mParams); trySendAccessibilityEvent(); mPresenter.trySendAccessibilityEvent(mView, mPackageName); for (Callback callback : getCallbacks()) { callback.onToastShown(); } Loading @@ -763,22 +724,6 @@ public class Toast { } } private void trySendAccessibilityEvent() { AccessibilityManager accessibilityManager = AccessibilityManager.getInstance(mView.getContext()); if (!accessibilityManager.isEnabled()) { return; } // treat toasts as notifications since they are used to // announce a transient piece of information to the user AccessibilityEvent event = AccessibilityEvent.obtain( AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED); event.setClassName(getClass().getName()); event.setPackageName(mView.getContext().getPackageName()); mView.dispatchPopulateAccessibilityEvent(event); accessibilityManager.sendAccessibilityEvent(event); } @UnsupportedAppUsage public void handleHide() { if (localLOGV) Log.v(TAG, "HANDLE HIDE: " + this + " mView=" + mView); Loading core/java/android/widget/ToastPresenter.java 0 → 100644 +117 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 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 android.widget; import android.content.Context; import android.content.res.Configuration; import android.graphics.PixelFormat; import android.os.IBinder; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.WindowManager; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityManager; import com.android.internal.R; /** * Class responsible for toast presentation inside app's process and in system UI. * * @hide */ public class ToastPresenter { private static final long SHORT_DURATION_TIMEOUT = 4000; private static final long LONG_DURATION_TIMEOUT = 7000; private final Context mContext; private final AccessibilityManager mAccessibilityManager; public ToastPresenter(Context context, AccessibilityManager accessibilityManager) { mContext = context; mAccessibilityManager = accessibilityManager; } /** * Initializes {@code params} with default values for toasts. */ public void startLayoutParams(WindowManager.LayoutParams params) { params.height = WindowManager.LayoutParams.WRAP_CONTENT; params.width = WindowManager.LayoutParams.WRAP_CONTENT; params.format = PixelFormat.TRANSLUCENT; params.windowAnimations = R.style.Animation_Toast; params.type = WindowManager.LayoutParams.TYPE_TOAST; params.setFitInsetsIgnoringVisibility(true); params.setTitle("Toast"); params.flags = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; } /** * Customizes {@code params} according to other parameters, ready to be passed to {@link * WindowManager#addView(View, ViewGroup.LayoutParams)}. */ public void adjustLayoutParams(WindowManager.LayoutParams params, IBinder windowToken, int duration, int gravity, int xOffset, int yOffset, float horizontalMargin, float verticalMargin) { Configuration config = mContext.getResources().getConfiguration(); int absGravity = Gravity.getAbsoluteGravity(gravity, config.getLayoutDirection()); params.gravity = absGravity; if ((absGravity & Gravity.HORIZONTAL_GRAVITY_MASK) == Gravity.FILL_HORIZONTAL) { params.horizontalWeight = 1.0f; } if ((absGravity & Gravity.VERTICAL_GRAVITY_MASK) == Gravity.FILL_VERTICAL) { params.verticalWeight = 1.0f; } params.x = xOffset; params.y = yOffset; params.horizontalMargin = horizontalMargin; params.verticalMargin = verticalMargin; params.packageName = mContext.getPackageName(); params.hideTimeoutMilliseconds = (duration == Toast.LENGTH_LONG) ? LONG_DURATION_TIMEOUT : SHORT_DURATION_TIMEOUT; params.token = windowToken; } /** * Returns the default text toast view for message {@code text}. */ public View getTextToastView(CharSequence text) { View view = LayoutInflater.from(mContext).inflate( R.layout.transient_notification, null); TextView textView = view.findViewById(com.android.internal.R.id.message); textView.setText(text); return view; } /** * Sends {@link AccessibilityEvent#TYPE_NOTIFICATION_STATE_CHANGED} event if accessibility is * enabled. */ public void trySendAccessibilityEvent(View view, String packageName) { if (!mAccessibilityManager.isEnabled()) { return; } AccessibilityEvent event = AccessibilityEvent.obtain( AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED); event.setClassName(Toast.class.getName()); event.setPackageName(packageName); view.dispatchPopulateAccessibilityEvent(event); mAccessibilityManager.sendAccessibilityEvent(event); } } packages/SystemUI/src/com/android/systemui/toast/ToastUI.java +9 −55 Original line number Diff line number Diff line Loading @@ -21,21 +21,16 @@ import android.annotation.Nullable; import android.app.INotificationManager; import android.app.ITransientNotificationCallback; import android.content.Context; import android.content.res.Configuration; import android.graphics.PixelFormat; import android.os.IBinder; import android.os.RemoteException; import android.os.ServiceManager; import android.util.Log; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup.LayoutParams; import android.view.WindowManager; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityManager; import android.widget.TextView; import android.widget.Toast; import android.widget.ToastPresenter; import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; Loading Loading @@ -64,6 +59,7 @@ public class ToastUI extends SystemUI implements CommandQueue.Callbacks { private final WindowManager mWindowManager; private final INotificationManager mNotificationManager; private final AccessibilityManager mAccessibilityManager; private final ToastPresenter mPresenter; private ToastEntry mCurrentToast; @Inject Loading @@ -83,6 +79,7 @@ public class ToastUI extends SystemUI implements CommandQueue.Callbacks { mWindowManager = windowManager; mNotificationManager = notificationManager; mAccessibilityManager = accessibilityManager; mPresenter = new ToastPresenter(context, accessibilityManager); } @Override Loading @@ -97,7 +94,7 @@ public class ToastUI extends SystemUI implements CommandQueue.Callbacks { if (mCurrentToast != null) { hideCurrentToast(); } View view = getView(text); View view = mPresenter.getTextToastView(text); LayoutParams params = getLayoutParams(windowToken, duration); mCurrentToast = new ToastEntry(packageName, token, view, windowToken, callback); try { Loading @@ -106,7 +103,7 @@ public class ToastUI extends SystemUI implements CommandQueue.Callbacks { Log.w(TAG, "Error while attempting to show toast from " + packageName, e); return; } trySendAccessibilityEvent(view, packageName); mPresenter.trySendAccessibilityEvent(view, packageName); if (callback != null) { try { callback.onToastShown(); Loading Loading @@ -148,56 +145,13 @@ public class ToastUI extends SystemUI implements CommandQueue.Callbacks { mCurrentToast = null; } private void trySendAccessibilityEvent(View view, String packageName) { if (!mAccessibilityManager.isEnabled()) { return; } AccessibilityEvent event = AccessibilityEvent.obtain( AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED); event.setClassName(Toast.class.getName()); event.setPackageName(packageName); view.dispatchPopulateAccessibilityEvent(event); mAccessibilityManager.sendAccessibilityEvent(event); } private View getView(CharSequence text) { View view = LayoutInflater.from(mContext).inflate( R.layout.transient_notification, null); TextView textView = view.findViewById(com.android.internal.R.id.message); textView.setText(text); return view; } private LayoutParams getLayoutParams(IBinder windowToken, int duration) { WindowManager.LayoutParams params = new WindowManager.LayoutParams(); params.height = WindowManager.LayoutParams.WRAP_CONTENT; params.width = WindowManager.LayoutParams.WRAP_CONTENT; params.format = PixelFormat.TRANSLUCENT; params.windowAnimations = com.android.internal.R.style.Animation_Toast; params.type = WindowManager.LayoutParams.TYPE_TOAST; params.setTitle("Toast"); params.flags = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; Configuration config = mContext.getResources().getConfiguration(); int specificGravity = mContext.getResources().getInteger( mPresenter.startLayoutParams(params); int gravity = mContext.getResources().getInteger( com.android.internal.R.integer.config_toastDefaultGravity); int gravity = Gravity.getAbsoluteGravity(specificGravity, config.getLayoutDirection()); params.gravity = gravity; if ((gravity & Gravity.HORIZONTAL_GRAVITY_MASK) == Gravity.FILL_HORIZONTAL) { params.horizontalWeight = 1.0f; } if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == Gravity.FILL_VERTICAL) { params.verticalWeight = 1.0f; } params.x = 0; params.y = mContext.getResources().getDimensionPixelSize(R.dimen.toast_y_offset); params.verticalMargin = 0; params.horizontalMargin = 0; params.packageName = mContext.getPackageName(); params.hideTimeoutMilliseconds = (duration == Toast.LENGTH_LONG) ? DURATION_LONG : DURATION_SHORT; params.token = windowToken; int yOffset = mContext.getResources().getDimensionPixelSize(R.dimen.toast_y_offset); mPresenter.adjustLayoutParams(params, windowToken, duration, gravity, 0, yOffset, 0, 0); return params; } Loading Loading
core/java/android/widget/Toast.java +14 −69 Original line number Diff line number Diff line Loading @@ -31,9 +31,7 @@ import android.compat.annotation.ChangeId; import android.compat.annotation.EnabledAfter; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.content.res.Configuration; import android.content.res.Resources; import android.graphics.PixelFormat; import android.os.Binder; import android.os.Build; import android.os.Handler; Loading @@ -43,11 +41,8 @@ import android.os.Message; import android.os.RemoteException; import android.os.ServiceManager; import android.util.Log; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.WindowManager; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityManager; import com.android.internal.annotations.GuardedBy; Loading Loading @@ -122,6 +117,7 @@ public class Toast { private final Binder mToken; private final Context mContext; private final Handler mHandler; private final ToastPresenter mPresenter; @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) final TN mTN; @UnsupportedAppUsage Loading Loading @@ -172,7 +168,8 @@ public class Toast { looper = getLooper(looper); mHandler = new Handler(looper); mCallbacks = new ArrayList<>(); mTN = new TN(context.getPackageName(), mToken, mCallbacks, looper); mPresenter = new ToastPresenter(context, AccessibilityManager.getInstance(context)); mTN = new TN(mPresenter, context.getPackageName(), mToken, mCallbacks, looper); mTN.mY = context.getResources().getDimensionPixelSize( com.android.internal.R.dimen.toast_y_offset); mTN.mGravity = context.getResources().getInteger( Loading Loading @@ -504,13 +501,7 @@ public class Toast { return result; } else { Toast result = new Toast(context, looper); LayoutInflater inflate = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); View v = inflate.inflate(com.android.internal.R.layout.transient_notification, null); TextView tv = (TextView) v.findViewById(com.android.internal.R.id.message); tv.setText(text); View v = result.mPresenter.getTextToastView(text); result.mNextView = v; result.mDuration = duration; Loading Loading @@ -611,34 +602,20 @@ public class Toast { final String mPackageName; final Binder mToken; private final ToastPresenter mPresenter; @GuardedBy("mCallbacks") private final List<Callback> mCallbacks; static final long SHORT_DURATION_TIMEOUT = 4000; static final long LONG_DURATION_TIMEOUT = 7000; /** * Creates a {@link ITransientNotification} object. * * The parameter {@code callbacks} is not copied and is accessed with itself as its own * lock. */ TN(String packageName, Binder token, List<Callback> callbacks, @Nullable Looper looper) { // XXX This should be changed to use a Dialog, with a Theme.Toast // defined that sets up the layout params appropriately. final WindowManager.LayoutParams params = mParams; params.height = WindowManager.LayoutParams.WRAP_CONTENT; params.width = WindowManager.LayoutParams.WRAP_CONTENT; params.format = PixelFormat.TRANSLUCENT; params.windowAnimations = com.android.internal.R.style.Animation_Toast; params.type = WindowManager.LayoutParams.TYPE_TOAST; params.setFitInsetsIgnoringVisibility(true); params.setTitle("Toast"); params.flags = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; TN(ToastPresenter presenter, String packageName, Binder token, List<Callback> callbacks, @Nullable Looper looper) { mPresenter = presenter; mPackageName = packageName; mToken = token; mCallbacks = callbacks; Loading Loading @@ -673,6 +650,8 @@ public class Toast { } } }; presenter.startLayoutParams(mParams); } private List<Callback> getCallbacks() { Loading Loading @@ -718,30 +697,12 @@ public class Toast { handleHide(); mView = mNextView; Context context = mView.getContext().getApplicationContext(); String packageName = mView.getContext().getOpPackageName(); if (context == null) { context = mView.getContext(); } mWM = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); // We can resolve the Gravity here by using the Locale for getting // the layout direction final Configuration config = mView.getContext().getResources().getConfiguration(); final int gravity = Gravity.getAbsoluteGravity(mGravity, config.getLayoutDirection()); mParams.gravity = gravity; if ((gravity & Gravity.HORIZONTAL_GRAVITY_MASK) == Gravity.FILL_HORIZONTAL) { mParams.horizontalWeight = 1.0f; } if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == Gravity.FILL_VERTICAL) { mParams.verticalWeight = 1.0f; } mParams.x = mX; mParams.y = mY; mParams.verticalMargin = mVerticalMargin; mParams.horizontalMargin = mHorizontalMargin; mParams.packageName = packageName; mParams.hideTimeoutMilliseconds = mDuration == Toast.LENGTH_LONG ? LONG_DURATION_TIMEOUT : SHORT_DURATION_TIMEOUT; mParams.token = windowToken; mPresenter.adjustLayoutParams(mParams, windowToken, mDuration, mGravity, mX, mY, mHorizontalMargin, mVerticalMargin); if (mView.getParent() != null) { if (localLOGV) Log.v(TAG, "REMOVE! " + mView + " in " + this); mWM.removeView(mView); Loading @@ -753,7 +714,7 @@ public class Toast { // invalidated. Let us hedge against that. try { mWM.addView(mView, mParams); trySendAccessibilityEvent(); mPresenter.trySendAccessibilityEvent(mView, mPackageName); for (Callback callback : getCallbacks()) { callback.onToastShown(); } Loading @@ -763,22 +724,6 @@ public class Toast { } } private void trySendAccessibilityEvent() { AccessibilityManager accessibilityManager = AccessibilityManager.getInstance(mView.getContext()); if (!accessibilityManager.isEnabled()) { return; } // treat toasts as notifications since they are used to // announce a transient piece of information to the user AccessibilityEvent event = AccessibilityEvent.obtain( AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED); event.setClassName(getClass().getName()); event.setPackageName(mView.getContext().getPackageName()); mView.dispatchPopulateAccessibilityEvent(event); accessibilityManager.sendAccessibilityEvent(event); } @UnsupportedAppUsage public void handleHide() { if (localLOGV) Log.v(TAG, "HANDLE HIDE: " + this + " mView=" + mView); Loading
core/java/android/widget/ToastPresenter.java 0 → 100644 +117 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 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 android.widget; import android.content.Context; import android.content.res.Configuration; import android.graphics.PixelFormat; import android.os.IBinder; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.WindowManager; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityManager; import com.android.internal.R; /** * Class responsible for toast presentation inside app's process and in system UI. * * @hide */ public class ToastPresenter { private static final long SHORT_DURATION_TIMEOUT = 4000; private static final long LONG_DURATION_TIMEOUT = 7000; private final Context mContext; private final AccessibilityManager mAccessibilityManager; public ToastPresenter(Context context, AccessibilityManager accessibilityManager) { mContext = context; mAccessibilityManager = accessibilityManager; } /** * Initializes {@code params} with default values for toasts. */ public void startLayoutParams(WindowManager.LayoutParams params) { params.height = WindowManager.LayoutParams.WRAP_CONTENT; params.width = WindowManager.LayoutParams.WRAP_CONTENT; params.format = PixelFormat.TRANSLUCENT; params.windowAnimations = R.style.Animation_Toast; params.type = WindowManager.LayoutParams.TYPE_TOAST; params.setFitInsetsIgnoringVisibility(true); params.setTitle("Toast"); params.flags = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; } /** * Customizes {@code params} according to other parameters, ready to be passed to {@link * WindowManager#addView(View, ViewGroup.LayoutParams)}. */ public void adjustLayoutParams(WindowManager.LayoutParams params, IBinder windowToken, int duration, int gravity, int xOffset, int yOffset, float horizontalMargin, float verticalMargin) { Configuration config = mContext.getResources().getConfiguration(); int absGravity = Gravity.getAbsoluteGravity(gravity, config.getLayoutDirection()); params.gravity = absGravity; if ((absGravity & Gravity.HORIZONTAL_GRAVITY_MASK) == Gravity.FILL_HORIZONTAL) { params.horizontalWeight = 1.0f; } if ((absGravity & Gravity.VERTICAL_GRAVITY_MASK) == Gravity.FILL_VERTICAL) { params.verticalWeight = 1.0f; } params.x = xOffset; params.y = yOffset; params.horizontalMargin = horizontalMargin; params.verticalMargin = verticalMargin; params.packageName = mContext.getPackageName(); params.hideTimeoutMilliseconds = (duration == Toast.LENGTH_LONG) ? LONG_DURATION_TIMEOUT : SHORT_DURATION_TIMEOUT; params.token = windowToken; } /** * Returns the default text toast view for message {@code text}. */ public View getTextToastView(CharSequence text) { View view = LayoutInflater.from(mContext).inflate( R.layout.transient_notification, null); TextView textView = view.findViewById(com.android.internal.R.id.message); textView.setText(text); return view; } /** * Sends {@link AccessibilityEvent#TYPE_NOTIFICATION_STATE_CHANGED} event if accessibility is * enabled. */ public void trySendAccessibilityEvent(View view, String packageName) { if (!mAccessibilityManager.isEnabled()) { return; } AccessibilityEvent event = AccessibilityEvent.obtain( AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED); event.setClassName(Toast.class.getName()); event.setPackageName(packageName); view.dispatchPopulateAccessibilityEvent(event); mAccessibilityManager.sendAccessibilityEvent(event); } }
packages/SystemUI/src/com/android/systemui/toast/ToastUI.java +9 −55 Original line number Diff line number Diff line Loading @@ -21,21 +21,16 @@ import android.annotation.Nullable; import android.app.INotificationManager; import android.app.ITransientNotificationCallback; import android.content.Context; import android.content.res.Configuration; import android.graphics.PixelFormat; import android.os.IBinder; import android.os.RemoteException; import android.os.ServiceManager; import android.util.Log; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup.LayoutParams; import android.view.WindowManager; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityManager; import android.widget.TextView; import android.widget.Toast; import android.widget.ToastPresenter; import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; Loading Loading @@ -64,6 +59,7 @@ public class ToastUI extends SystemUI implements CommandQueue.Callbacks { private final WindowManager mWindowManager; private final INotificationManager mNotificationManager; private final AccessibilityManager mAccessibilityManager; private final ToastPresenter mPresenter; private ToastEntry mCurrentToast; @Inject Loading @@ -83,6 +79,7 @@ public class ToastUI extends SystemUI implements CommandQueue.Callbacks { mWindowManager = windowManager; mNotificationManager = notificationManager; mAccessibilityManager = accessibilityManager; mPresenter = new ToastPresenter(context, accessibilityManager); } @Override Loading @@ -97,7 +94,7 @@ public class ToastUI extends SystemUI implements CommandQueue.Callbacks { if (mCurrentToast != null) { hideCurrentToast(); } View view = getView(text); View view = mPresenter.getTextToastView(text); LayoutParams params = getLayoutParams(windowToken, duration); mCurrentToast = new ToastEntry(packageName, token, view, windowToken, callback); try { Loading @@ -106,7 +103,7 @@ public class ToastUI extends SystemUI implements CommandQueue.Callbacks { Log.w(TAG, "Error while attempting to show toast from " + packageName, e); return; } trySendAccessibilityEvent(view, packageName); mPresenter.trySendAccessibilityEvent(view, packageName); if (callback != null) { try { callback.onToastShown(); Loading Loading @@ -148,56 +145,13 @@ public class ToastUI extends SystemUI implements CommandQueue.Callbacks { mCurrentToast = null; } private void trySendAccessibilityEvent(View view, String packageName) { if (!mAccessibilityManager.isEnabled()) { return; } AccessibilityEvent event = AccessibilityEvent.obtain( AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED); event.setClassName(Toast.class.getName()); event.setPackageName(packageName); view.dispatchPopulateAccessibilityEvent(event); mAccessibilityManager.sendAccessibilityEvent(event); } private View getView(CharSequence text) { View view = LayoutInflater.from(mContext).inflate( R.layout.transient_notification, null); TextView textView = view.findViewById(com.android.internal.R.id.message); textView.setText(text); return view; } private LayoutParams getLayoutParams(IBinder windowToken, int duration) { WindowManager.LayoutParams params = new WindowManager.LayoutParams(); params.height = WindowManager.LayoutParams.WRAP_CONTENT; params.width = WindowManager.LayoutParams.WRAP_CONTENT; params.format = PixelFormat.TRANSLUCENT; params.windowAnimations = com.android.internal.R.style.Animation_Toast; params.type = WindowManager.LayoutParams.TYPE_TOAST; params.setTitle("Toast"); params.flags = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; Configuration config = mContext.getResources().getConfiguration(); int specificGravity = mContext.getResources().getInteger( mPresenter.startLayoutParams(params); int gravity = mContext.getResources().getInteger( com.android.internal.R.integer.config_toastDefaultGravity); int gravity = Gravity.getAbsoluteGravity(specificGravity, config.getLayoutDirection()); params.gravity = gravity; if ((gravity & Gravity.HORIZONTAL_GRAVITY_MASK) == Gravity.FILL_HORIZONTAL) { params.horizontalWeight = 1.0f; } if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == Gravity.FILL_VERTICAL) { params.verticalWeight = 1.0f; } params.x = 0; params.y = mContext.getResources().getDimensionPixelSize(R.dimen.toast_y_offset); params.verticalMargin = 0; params.horizontalMargin = 0; params.packageName = mContext.getPackageName(); params.hideTimeoutMilliseconds = (duration == Toast.LENGTH_LONG) ? DURATION_LONG : DURATION_SHORT; params.token = windowToken; int yOffset = mContext.getResources().getDimensionPixelSize(R.dimen.toast_y_offset); mPresenter.adjustLayoutParams(params, windowToken, duration, gravity, 0, yOffset, 0, 0); return params; } Loading