Merge "Revert "Prevent apps to overlay other apps via toast windows"" into nyc-mr1-dev

This commit is contained in:
Svetoslav Ganov
2016-08-02 01:56:09 +00:00
committed by Android (Google) Code Review
8 changed files with 40 additions and 209 deletions

View File

@@ -19,7 +19,7 @@ package android.app;
/** @hide */
oneway interface ITransientNotification {
void show(IBinder windowToken);
void show();
void hide();
}

View File

@@ -233,7 +233,6 @@ public class SurfaceView extends View {
mSession = getWindowSession();
mLayout.token = getWindowToken();
mLayout.setTitle("SurfaceView - " + getViewRootImpl().getTitle());
mLayout.packageName = mContext.getOpPackageName();
mViewVisibility = getVisibility() == VISIBLE;
if (!mGlobalListenersAdded) {

View File

@@ -1734,18 +1734,14 @@ public interface WindowManager extends ViewManager {
public CharSequence accessibilityTitle;
/**
* Sets a timeout in milliseconds before which the window will be hidden
* Sets a timeout in milliseconds before which the window will be removed
* by the window manager. Useful for transient notifications like toasts
* so we don't have to rely on client cooperation to ensure the window
* is hidden. Must be specified at window creation time. Note that apps
* are not prepared to handle their windows being removed without their
* explicit request and may try to interact with the removed window
* resulting in undefined behavior and crashes. Therefore, we do hide
* such windows to prevent them from overlaying other apps.
* is removed. Must be specified at window creation time.
*
* @hide
*/
public long hideTimeoutMilliseconds = -1;
public long removeTimeoutMilliseconds = -1;
public LayoutParams() {
super(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
@@ -1881,7 +1877,7 @@ public interface WindowManager extends ViewManager {
out.writeInt(needsMenuKey);
out.writeInt(accessibilityIdOfAnchor);
TextUtils.writeToParcel(accessibilityTitle, out, parcelableFlags);
out.writeLong(hideTimeoutMilliseconds);
out.writeLong(removeTimeoutMilliseconds);
}
public static final Parcelable.Creator<LayoutParams> CREATOR
@@ -1935,7 +1931,7 @@ public interface WindowManager extends ViewManager {
needsMenuKey = in.readInt();
accessibilityIdOfAnchor = in.readInt();
accessibilityTitle = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
hideTimeoutMilliseconds = in.readLong();
removeTimeoutMilliseconds = in.readLong();
}
@SuppressWarnings({"PointlessBitwiseExpression"})
@@ -2157,7 +2153,7 @@ public interface WindowManager extends ViewManager {
}
// This can't change, it's only set at window creation time.
hideTimeoutMilliseconds = o.hideTimeoutMilliseconds;
removeTimeoutMilliseconds = o.removeTimeoutMilliseconds;
return changes;
}

View File

@@ -25,8 +25,6 @@ import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.PixelFormat;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.Log;
@@ -328,6 +326,13 @@ public class Toast {
}
private static class TN extends ITransientNotification.Stub {
final Runnable mShow = new Runnable() {
@Override
public void run() {
handleShow();
}
};
final Runnable mHide = new Runnable() {
@Override
public void run() {
@@ -338,13 +343,7 @@ public class Toast {
};
private final WindowManager.LayoutParams mParams = new WindowManager.LayoutParams();
final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
IBinder token = (IBinder) msg.obj;
handleShow(token);
}
};
final Handler mHandler = new Handler();
int mGravity;
int mX, mY;
@@ -380,9 +379,9 @@ public class Toast {
* schedule handleShow into the right thread
*/
@Override
public void show(IBinder windowToken) {
public void show() {
if (localLOGV) Log.v(TAG, "SHOW: " + this);
mHandler.obtainMessage(0, windowToken).sendToTarget();
mHandler.post(mShow);
}
/**
@@ -394,7 +393,7 @@ public class Toast {
mHandler.post(mHide);
}
public void handleShow(IBinder windowToken) {
public void handleShow() {
if (localLOGV) Log.v(TAG, "HANDLE SHOW: " + this + " mView=" + mView
+ " mNextView=" + mNextView);
if (mView != mNextView) {
@@ -423,9 +422,8 @@ public class Toast {
mParams.verticalMargin = mVerticalMargin;
mParams.horizontalMargin = mHorizontalMargin;
mParams.packageName = packageName;
mParams.hideTimeoutMilliseconds = mDuration ==
mParams.removeTimeoutMilliseconds = mDuration ==
Toast.LENGTH_LONG ? LONG_DURATION_TIMEOUT : SHORT_DURATION_TIMEOUT;
mParams.token = windowToken;
if (mView.getParent() != null) {
if (localLOGV) Log.v(TAG, "REMOVE! " + mView + " in " + this);
mWM.removeView(mView);

View File

@@ -58,6 +58,7 @@ import android.app.Notification;
import android.app.NotificationManager;
import android.app.NotificationManager.Policy;
import android.app.PendingIntent;
import android.app.RemoteInput;
import android.app.StatusBarManager;
import android.app.backup.BackupManager;
import android.app.usage.UsageEvents;
@@ -92,6 +93,7 @@ import android.os.IBinder;
import android.os.IInterface;
import android.os.Looper;
import android.os.Message;
import android.os.Parcelable;
import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
@@ -120,8 +122,6 @@ import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
import android.util.Xml;
import android.view.WindowManager;
import android.view.WindowManagerInternal;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import android.widget.Toast;
@@ -138,7 +138,6 @@ import com.android.server.SystemService;
import com.android.server.lights.Light;
import com.android.server.lights.LightsManager;
import com.android.server.notification.ManagedServices.ManagedServiceInfo;
import com.android.server.policy.PhoneWindowManager;
import com.android.server.statusbar.StatusBarManagerInternal;
import com.android.server.vr.VrManagerInternal;
import com.android.server.notification.ManagedServices.UserProfiles;
@@ -194,7 +193,7 @@ public class NotificationManagerService extends SystemService {
private static final int MESSAGE_RECONSIDER_RANKING = 1000;
private static final int MESSAGE_RANKING_SORT = 1001;
static final int LONG_DELAY = PhoneWindowManager.TOAST_WINDOW_TIMEOUT;
static final int LONG_DELAY = 3500; // 3.5 seconds
static final int SHORT_DELAY = 2000; // 2 seconds
static final long[] DEFAULT_VIBRATE_PATTERN = {0, 250, 250, 250};
@@ -233,7 +232,6 @@ public class NotificationManagerService extends SystemService {
@Nullable StatusBarManagerInternal mStatusBar;
Vibrator mVibrator;
private VrManagerInternal mVrManagerInternal;
private WindowManagerInternal mWindowManagerInternal;
final IBinder mForegroundToken = new Binder();
private Handler mHandler;
@@ -454,15 +452,13 @@ public class NotificationManagerService extends SystemService {
final String pkg;
final ITransientNotification callback;
int duration;
Binder token;
ToastRecord(int pid, String pkg, ITransientNotification callback, int duration,
Binder token) {
ToastRecord(int pid, String pkg, ITransientNotification callback, int duration)
{
this.pid = pid;
this.pkg = pkg;
this.callback = callback;
this.duration = duration;
this.token = token;
}
void update(int duration) {
@@ -1129,7 +1125,6 @@ public class NotificationManagerService extends SystemService {
mAudioManager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
mAudioManagerInternal = getLocalService(AudioManagerInternal.class);
mVrManagerInternal = getLocalService(VrManagerInternal.class);
mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
mZenModeHelper.onSystemReady();
} else if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) {
// This observer will force an update when observe is called, causing us to
@@ -1330,13 +1325,10 @@ public class NotificationManagerService extends SystemService {
}
}
Binder token = new Binder();
mWindowManagerInternal.addWindowToken(token,
WindowManager.LayoutParams.TYPE_TOAST);
record = new ToastRecord(callingPid, pkg, callback, duration, token);
record = new ToastRecord(callingPid, pkg, callback, duration);
mToastQueue.add(record);
index = mToastQueue.size() - 1;
keepProcessAliveIfNeededLocked(callingPid);
keepProcessAliveLocked(callingPid);
}
// If it's at index 0, it's the current toast. It doesn't matter if it's
// new or just been updated. Call back and tell it to show itself.
@@ -2995,7 +2987,7 @@ public class NotificationManagerService extends SystemService {
while (record != null) {
if (DBG) Slog.d(TAG, "Show pkg=" + record.pkg + " callback=" + record.callback);
try {
record.callback.show(record.token);
record.callback.show();
scheduleTimeoutLocked(record);
return;
} catch (RemoteException e) {
@@ -3006,7 +2998,7 @@ public class NotificationManagerService extends SystemService {
if (index >= 0) {
mToastQueue.remove(index);
}
keepProcessAliveIfNeededLocked(record.pid);
keepProcessAliveLocked(record.pid);
if (mToastQueue.size() > 0) {
record = mToastQueue.get(0);
} else {
@@ -3026,11 +3018,8 @@ public class NotificationManagerService extends SystemService {
// don't worry about this, we're about to remove it from
// the list anyway
}
ToastRecord lastToast = mToastQueue.remove(index);
mWindowManagerInternal.removeWindowToken(lastToast.token, true);
keepProcessAliveIfNeededLocked(record.pid);
mToastQueue.remove(index);
keepProcessAliveLocked(record.pid);
if (mToastQueue.size() > 0) {
// Show the next one. If the callback fails, this will remove
// it from the list, so don't assume that the list hasn't changed
@@ -3074,7 +3063,7 @@ public class NotificationManagerService extends SystemService {
}
// lock on mToastQueue
void keepProcessAliveIfNeededLocked(int pid)
void keepProcessAliveLocked(int pid)
{
int toastCount = 0; // toasts from this pid
ArrayList<ToastRecord> list = mToastQueue;

View File

@@ -301,9 +301,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
/** Amount of time (in milliseconds) to wait for windows drawn before powering on. */
static final int WAITING_FOR_DRAWN_TIMEOUT = 1000;
/** Amount of time (in milliseconds) a toast window can be shown. */
public static final int TOAST_WINDOW_TIMEOUT = 3500; // 3.5 seconds
/**
* Lock protecting internal state. Must not call out into window
* manager with lock held. (This lock will be acquired in places
@@ -2232,18 +2229,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
attrs.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
}
break;
case TYPE_TOAST:
// While apps should use the dedicated toast APIs to add such windows
// it possible legacy apps to add the window directly. Therefore, we
// make windows added directly by the app behave as a toast as much
// as possible in terms of timeout and animation.
if (attrs.hideTimeoutMilliseconds < 0
|| attrs.hideTimeoutMilliseconds > TOAST_WINDOW_TIMEOUT) {
attrs.hideTimeoutMilliseconds = TOAST_WINDOW_TIMEOUT;
}
attrs.windowAnimations = com.android.internal.R.style.Animation_Toast;
break;
}
if (attrs.type != TYPE_STATUS_BAR) {

View File

@@ -35,7 +35,6 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
@@ -201,7 +200,6 @@ import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
import static android.view.WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION;
import static android.view.WindowManager.LayoutParams.TYPE_QS_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
import static android.view.WindowManagerGlobal.RELAYOUT_DEFER_SURFACE_DESTROY;
@@ -1869,7 +1867,6 @@ public class WindowManagerService extends IWindowManager.Stub
boolean reportNewConfig = false;
WindowState attachedWindow = null;
long origId;
final int callingUid = Binder.getCallingUid();
final int type = attrs.type;
synchronized(mWindowMap) {
@@ -1917,8 +1914,6 @@ public class WindowManagerService extends IWindowManager.Stub
boolean addToken = false;
WindowToken token = mTokenMap.get(attrs.token);
AppWindowToken atoken = null;
boolean addToastWindowRequiresToken = false;
if (token == null) {
if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
Slog.w(TAG_WM, "Attempted to add application window with unknown token "
@@ -1955,15 +1950,6 @@ public class WindowManagerService extends IWindowManager.Stub
+ attrs.token + ". Aborting.");
return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
}
if (type == TYPE_TOAST) {
// Apps targeting SDK above N MR1 cannot arbitrary add toast windows.
if (doesAddToastWindowRequireToken(attrs.packageName, callingUid,
attachedWindow)) {
Slog.w(TAG_WM, "Attempted to add a toast window with unknown token "
+ attrs.token + ". Aborting.");
return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
}
}
token = new WindowToken(this, attrs.token, -1, false);
addToken = true;
} else if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
@@ -2013,15 +1999,6 @@ public class WindowManagerService extends IWindowManager.Stub
+ attrs.token + ". Aborting.");
return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
}
} else if (type == TYPE_TOAST) {
// Apps targeting SDK above N MR1 cannot arbitrary add toast windows.
addToastWindowRequiresToken = doesAddToastWindowRequireToken(attrs.packageName,
callingUid, attachedWindow);
if (addToastWindowRequiresToken && token.windowType != TYPE_TOAST) {
Slog.w(TAG_WM, "Attempted to add a toast window with bad token "
+ attrs.token + ". Aborting.");
return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
}
} else if (type == TYPE_QS_DIALOG) {
if (token.windowType != TYPE_QS_DIALOG) {
Slog.w(TAG_WM, "Attempted to add QS dialog window with bad token "
@@ -2066,35 +2043,6 @@ public class WindowManagerService extends IWindowManager.Stub
win.openInputChannel(outInputChannel);
}
// If adding a toast requires a token for this app we always schedule hiding
// toast windows to make sure they don't stick around longer then necessary.
// We hide instead of remove such windows as apps aren't prepared to handle
// windows being removed under them.
// If the app is older it can add toasts without a token and hence overlay
// other apps. To be maximally compatible with these apps we will hide the
// window after the toast timeout only if the focused window is from another
// UID, otherwise we allow unlimited duration. When a UID looses focus we
// schedule hiding all of its toast windows.
if (type == TYPE_TOAST) {
if (!canAddToastWindowForUid(getDefaultDisplayContentLocked(), callingUid)) {
Slog.w(TAG_WM, "Adding more than one toast window for UID at a time.");
return WindowManagerGlobal.ADD_DUPLICATE_ADD;
}
// Make sure this happens before we moved focus as one can make the
// toast focusable to force it not being hidden after the timeout.
// Focusable toasts are always timed out to prevent a focused app to
// show a focusable toasts while it has focus which will be kept on
// the screen after the activity goes away.
if (addToastWindowRequiresToken
|| (attrs.flags & LayoutParams.FLAG_NOT_FOCUSABLE) == 0
|| mCurrentFocus == null
|| mCurrentFocus.mOwnerUid != callingUid) {
mH.sendMessageDelayed(
mH.obtainMessage(H.WINDOW_HIDE_TIMEOUT, win),
win.mAttrs.hideTimeoutMilliseconds);
}
}
// From now on, no exceptions or errors allowed!
res = WindowManagerGlobal.ADD_OKAY;
@@ -2233,6 +2181,11 @@ public class WindowManagerService extends IWindowManager.Stub
if (win.isVisibleOrAdding() && updateOrientationFromAppTokensLocked(false)) {
reportNewConfig = true;
}
if (attrs.removeTimeoutMilliseconds > 0) {
mH.sendMessageDelayed(
mH.obtainMessage(H.WINDOW_REMOVE_TIMEOUT, win),
attrs.removeTimeoutMilliseconds);
}
}
if (reportNewConfig) {
@@ -2244,73 +2197,6 @@ public class WindowManagerService extends IWindowManager.Stub
return res;
}
private boolean canAddToastWindowForUid(DisplayContent displayContent, int uid) {
// We allow one toast window per UID being shown at a time.
WindowList windows = displayContent.getWindowList();
final int windowCount = windows.size();
for (int i = 0; i < windowCount; i++) {
WindowState window = windows.get(i);
if (window.mAttrs.type == TYPE_TOAST && window.mOwnerUid == uid
&& !window.mPermanentlyHidden) {
return false;
}
}
return true;
}
private boolean doesAddToastWindowRequireToken(String packageName, int callingUid,
WindowState attachedWindow) {
// Try using the target SDK of the root window
if (attachedWindow != null) {
WindowState currentWindow = attachedWindow;
while (currentWindow != null) {
if (currentWindow.mAppToken != null
&& currentWindow.mAppToken.targetSdk > Build.VERSION_CODES.N_MR1) {
return true;
}
currentWindow = currentWindow.mAttachedWindow;
}
} else {
// Otherwise, look at the package
try {
ApplicationInfo appInfo = mContext.getPackageManager()
.getApplicationInfoAsUser(packageName, 0,
UserHandle.getUserId(callingUid));
if (appInfo.uid != callingUid) {
throw new SecurityException("Package " + packageName + " not in UID "
+ callingUid);
}
if (appInfo.targetSdkVersion > Build.VERSION_CODES.N_MR1) {
return true;
}
} catch (PackageManager.NameNotFoundException e) {
/* ignore */
}
}
return false;
}
private void scheduleToastWindowsTimeoutIfNeededLocked(WindowState oldFocus,
WindowState newFocus) {
if (oldFocus == null || (newFocus != null && newFocus.mOwnerUid == oldFocus.mOwnerUid)) {
return;
}
final int lostFocusUid = oldFocus.mOwnerUid;
DisplayContent displayContent = oldFocus.getDisplayContent();
WindowList windows = displayContent.getWindowList();
final int windowCount = windows.size();
for (int i = 0; i < windowCount; i++) {
WindowState window = windows.get(i);
if (window.mAttrs.type == TYPE_TOAST && window.mOwnerUid == lostFocusUid) {
if (!mH.hasMessages(H.WINDOW_HIDE_TIMEOUT, window)) {
mH.sendMessageDelayed(
mH.obtainMessage(H.WINDOW_HIDE_TIMEOUT, window),
window.mAttrs.hideTimeoutMilliseconds);
}
}
}
}
/**
* Returns true if we're done setting up any transitions.
*/
@@ -8238,7 +8124,7 @@ public class WindowManagerService extends IWindowManager.Stub
public static final int NOTIFY_APP_TRANSITION_FINISHED = 49;
public static final int NOTIFY_STARTING_WINDOW_DRAWN = 50;
public static final int UPDATE_ANIMATION_SCALE = 51;
public static final int WINDOW_HIDE_TIMEOUT = 52;
public static final int WINDOW_REMOVE_TIMEOUT = 52;
public static final int NOTIFY_DOCKED_STACK_MINIMIZED_CHANGED = 53;
public static final int SEAMLESS_ROTATION_TIMEOUT = 54;
@@ -8858,7 +8744,7 @@ public class WindowManagerService extends IWindowManager.Stub
mAmInternal.notifyStartingWindowDrawn();
}
break;
case WINDOW_HIDE_TIMEOUT: {
case WINDOW_REMOVE_TIMEOUT: {
final WindowState window = (WindowState) msg.obj;
synchronized(mWindowMap) {
// TODO: This is all about fixing b/21693547
@@ -8869,11 +8755,8 @@ public class WindowManagerService extends IWindowManager.Stub
// running under debugger) to crash (b/29105388). The windows will
// eventually be removed when the client process finishes.
// The best we can do for now is remove the FLAG_KEEP_SCREEN_ON
// and prevent the symptoms of b/21693547. Since apps don't
// support windows being removed under them we hide the window
// and it will be removed when the app dies.
// and prevent the symptoms of b/21693547.
window.mAttrs.flags &= ~FLAG_KEEP_SCREEN_ON;
window.markPermanentlyHiddenLw();
window.setDisplayLayoutNeeded();
mWindowPlacerLocked.performSurfacePlacement();
}
@@ -9903,11 +9786,6 @@ public class WindowManagerService extends IWindowManager.Stub
adjustForImeIfNeeded(displayContent);
// We may need to schedule some toast windows to be removed. The
// toasts for an app that does not have input focus are removed
// within a timeout to prevent apps to redress other apps' UI.
scheduleToastWindowsTimeoutIfNeededLocked(oldFocus, newFocus);
Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
return true;
}

View File

@@ -165,7 +165,6 @@ final class WindowState implements WindowManagerPolicy.WindowState {
boolean mPolicyVisibility = true;
boolean mPolicyVisibilityAfterAnim = true;
boolean mAppOpVisibility = true;
boolean mPermanentlyHidden;
boolean mAppFreezing;
boolean mAttachedHidden; // is our parent window hidden?
boolean mWallpaperVisible; // for wallpaper, what was last vis report?
@@ -1874,11 +1873,6 @@ final class WindowState implements WindowManagerPolicy.WindowState {
// Being hidden due to app op request.
return false;
}
if (mPermanentlyHidden) {
// Permanently hidden until the app exists as apps aren't prepared
// to handle their windows being removed from under them.
return false;
}
if (mPolicyVisibility && mPolicyVisibilityAfterAnim) {
// Already showing.
return false;
@@ -1969,13 +1963,6 @@ final class WindowState implements WindowManagerPolicy.WindowState {
}
}
public void markPermanentlyHiddenLw() {
if (!mPermanentlyHidden) {
mPermanentlyHidden = true;
hideLw(true, true);
}
}
public void pokeDrawLockLw(long timeout) {
if (isVisibleOrAdding()) {
if (mDrawLock == null) {
@@ -2625,7 +2612,7 @@ final class WindowState implements WindowManagerPolicy.WindowState {
pw.println(Integer.toHexString(mSystemUiVisibility));
}
if (!mPolicyVisibility || !mPolicyVisibilityAfterAnim || !mAppOpVisibility
|| mAttachedHidden || mPermanentlyHidden) {
|| mAttachedHidden) {
pw.print(prefix); pw.print("mPolicyVisibility=");
pw.print(mPolicyVisibility);
pw.print(" mPolicyVisibilityAfterAnim=");
@@ -2633,7 +2620,6 @@ final class WindowState implements WindowManagerPolicy.WindowState {
pw.print(" mAppOpVisibility=");
pw.print(mAppOpVisibility);
pw.print(" mAttachedHidden="); pw.println(mAttachedHidden);
pw.print(" mPermanentlyHidden="); pw.println(mPermanentlyHidden);
}
if (!mRelayoutCalled || mLayoutNeeded) {
pw.print(prefix); pw.print("mRelayoutCalled="); pw.print(mRelayoutCalled);