1 /* 2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.systemui.toast; 18 19 import android.annotation.MainThread; 20 import android.annotation.Nullable; 21 import android.app.INotificationManager; 22 import android.app.ITransientNotificationCallback; 23 import android.content.Context; 24 import android.content.res.Resources; 25 import android.os.IBinder; 26 import android.os.ServiceManager; 27 import android.os.UserHandle; 28 import android.util.Log; 29 import android.view.View; 30 import android.view.accessibility.IAccessibilityManager; 31 import android.widget.ToastPresenter; 32 33 import com.android.internal.R; 34 import com.android.internal.annotations.VisibleForTesting; 35 import com.android.systemui.SystemUI; 36 import com.android.systemui.statusbar.CommandQueue; 37 38 import java.util.Objects; 39 40 import javax.inject.Inject; 41 import javax.inject.Singleton; 42 43 /** 44 * Controls display of text toasts. 45 */ 46 @Singleton 47 public class ToastUI extends SystemUI implements CommandQueue.Callbacks { 48 private static final String TAG = "ToastUI"; 49 50 private final CommandQueue mCommandQueue; 51 private final INotificationManager mNotificationManager; 52 private final IAccessibilityManager mAccessibilityManager; 53 private final int mGravity; 54 private final int mY; 55 @Nullable private ToastPresenter mPresenter; 56 @Nullable private ITransientNotificationCallback mCallback; 57 58 @Inject ToastUI(Context context, CommandQueue commandQueue)59 public ToastUI(Context context, CommandQueue commandQueue) { 60 this(context, commandQueue, 61 INotificationManager.Stub.asInterface( 62 ServiceManager.getService(Context.NOTIFICATION_SERVICE)), 63 IAccessibilityManager.Stub.asInterface( 64 ServiceManager.getService(Context.ACCESSIBILITY_SERVICE))); 65 } 66 67 @VisibleForTesting ToastUI(Context context, CommandQueue commandQueue, INotificationManager notificationManager, @Nullable IAccessibilityManager accessibilityManager)68 ToastUI(Context context, CommandQueue commandQueue, INotificationManager notificationManager, 69 @Nullable IAccessibilityManager accessibilityManager) { 70 super(context); 71 mCommandQueue = commandQueue; 72 mNotificationManager = notificationManager; 73 mAccessibilityManager = accessibilityManager; 74 Resources resources = mContext.getResources(); 75 mGravity = resources.getInteger(R.integer.config_toastDefaultGravity); 76 mY = resources.getDimensionPixelSize(R.dimen.toast_y_offset); 77 } 78 79 @Override start()80 public void start() { 81 mCommandQueue.addCallback(this); 82 } 83 84 @Override 85 @MainThread showToast(int uid, String packageName, IBinder token, CharSequence text, IBinder windowToken, int duration, @Nullable ITransientNotificationCallback callback)86 public void showToast(int uid, String packageName, IBinder token, CharSequence text, 87 IBinder windowToken, int duration, @Nullable ITransientNotificationCallback callback) { 88 if (mPresenter != null) { 89 hideCurrentToast(); 90 } 91 Context context = mContext.createContextAsUser(UserHandle.getUserHandleForUid(uid), 0); 92 View view = ToastPresenter.getTextToastView(context, text); 93 mCallback = callback; 94 mPresenter = new ToastPresenter(context, mAccessibilityManager, mNotificationManager, 95 packageName); 96 mPresenter.show(view, token, windowToken, duration, mGravity, 0, mY, 0, 0, mCallback); 97 } 98 99 @Override 100 @MainThread hideToast(String packageName, IBinder token)101 public void hideToast(String packageName, IBinder token) { 102 if (mPresenter == null || !Objects.equals(mPresenter.getPackageName(), packageName) 103 || !Objects.equals(mPresenter.getToken(), token)) { 104 Log.w(TAG, "Attempt to hide non-current toast from package " + packageName); 105 return; 106 } 107 hideCurrentToast(); 108 } 109 110 @MainThread hideCurrentToast()111 private void hideCurrentToast() { 112 mPresenter.hide(mCallback); 113 mPresenter = null; 114 } 115 } 116