1 /* 2 * Copyright (C) 2011 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.server.wm; 18 19 import static android.Manifest.permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS; 20 import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW; 21 import static android.content.pm.PackageManager.PERMISSION_GRANTED; 22 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; 23 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; 24 import static android.view.WindowManager.LayoutParams.isSystemAlertWindowType; 25 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DRAG; 26 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_POSITIONING; 27 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS; 28 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS; 29 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; 30 31 import android.content.ClipData; 32 import android.content.Context; 33 import android.graphics.Rect; 34 import android.graphics.Region; 35 import android.os.Binder; 36 import android.os.Bundle; 37 import android.os.IBinder; 38 import android.os.Parcel; 39 import android.os.Process; 40 import android.os.RemoteException; 41 import android.os.ServiceManager; 42 import android.os.Trace; 43 import android.os.UserHandle; 44 import android.util.MergedConfiguration; 45 import android.util.Slog; 46 import android.view.Display; 47 import android.view.IWindow; 48 import android.view.IWindowId; 49 import android.view.IWindowSession; 50 import android.view.IWindowSessionCallback; 51 import android.view.InputChannel; 52 import android.view.Surface; 53 import android.view.SurfaceControl; 54 import android.view.SurfaceSession; 55 import android.view.WindowManager; 56 57 import com.android.internal.view.IInputContext; 58 import com.android.internal.view.IInputMethodClient; 59 import com.android.internal.view.IInputMethodManager; 60 import com.android.server.wm.WindowManagerService.H; 61 62 import java.io.PrintWriter; 63 import java.util.HashSet; 64 import java.util.Set; 65 66 /** 67 * This class represents an active client session. There is generally one 68 * Session object per process that is interacting with the window manager. 69 */ 70 // Needs to be public and not final so we can mock during tests...sucks I know :( 71 public class Session extends IWindowSession.Stub 72 implements IBinder.DeathRecipient { 73 final WindowManagerService mService; 74 final IWindowSessionCallback mCallback; 75 final IInputMethodClient mClient; 76 final int mUid; 77 final int mPid; 78 private final String mStringName; 79 SurfaceSession mSurfaceSession; 80 private int mNumWindow = 0; 81 // Set of visible application overlay window surfaces connected to this session. 82 private final Set<WindowSurfaceController> mAppOverlaySurfaces = new HashSet<>(); 83 // Set of visible alert window surfaces connected to this session. 84 private final Set<WindowSurfaceController> mAlertWindowSurfaces = new HashSet<>(); 85 final boolean mCanAddInternalSystemWindow; 86 final boolean mCanHideNonSystemOverlayWindows; 87 private AlertWindowNotification mAlertWindowNotification; 88 private boolean mShowingAlertWindowNotificationAllowed; 89 private boolean mClientDead = false; 90 private float mLastReportedAnimatorScale; 91 private String mPackageName; 92 private String mRelayoutTag; 93 Session(WindowManagerService service, IWindowSessionCallback callback, IInputMethodClient client, IInputContext inputContext)94 public Session(WindowManagerService service, IWindowSessionCallback callback, 95 IInputMethodClient client, IInputContext inputContext) { 96 mService = service; 97 mCallback = callback; 98 mClient = client; 99 mUid = Binder.getCallingUid(); 100 mPid = Binder.getCallingPid(); 101 mLastReportedAnimatorScale = service.getCurrentAnimatorScale(); 102 mCanAddInternalSystemWindow = service.mContext.checkCallingOrSelfPermission( 103 INTERNAL_SYSTEM_WINDOW) == PERMISSION_GRANTED; 104 mCanHideNonSystemOverlayWindows = service.mContext.checkCallingOrSelfPermission( 105 HIDE_NON_SYSTEM_OVERLAY_WINDOWS) == PERMISSION_GRANTED; 106 mShowingAlertWindowNotificationAllowed = mService.mShowAlertWindowNotifications; 107 StringBuilder sb = new StringBuilder(); 108 sb.append("Session{"); 109 sb.append(Integer.toHexString(System.identityHashCode(this))); 110 sb.append(" "); 111 sb.append(mPid); 112 if (mUid < Process.FIRST_APPLICATION_UID) { 113 sb.append(":"); 114 sb.append(mUid); 115 } else { 116 sb.append(":u"); 117 sb.append(UserHandle.getUserId(mUid)); 118 sb.append('a'); 119 sb.append(UserHandle.getAppId(mUid)); 120 } 121 sb.append("}"); 122 mStringName = sb.toString(); 123 124 synchronized (mService.mWindowMap) { 125 if (mService.mInputMethodManager == null && mService.mHaveInputMethods) { 126 IBinder b = ServiceManager.getService( 127 Context.INPUT_METHOD_SERVICE); 128 mService.mInputMethodManager = IInputMethodManager.Stub.asInterface(b); 129 } 130 } 131 long ident = Binder.clearCallingIdentity(); 132 try { 133 // Note: it is safe to call in to the input method manager 134 // here because we are not holding our lock. 135 if (mService.mInputMethodManager != null) { 136 mService.mInputMethodManager.addClient(client, inputContext, 137 mUid, mPid); 138 } else { 139 client.setUsingInputMethod(false); 140 } 141 client.asBinder().linkToDeath(this, 0); 142 } catch (RemoteException e) { 143 // The caller has died, so we can just forget about this. 144 try { 145 if (mService.mInputMethodManager != null) { 146 mService.mInputMethodManager.removeClient(client); 147 } 148 } catch (RemoteException ee) { 149 } 150 } finally { 151 Binder.restoreCallingIdentity(ident); 152 } 153 } 154 155 @Override onTransact(int code, Parcel data, Parcel reply, int flags)156 public boolean onTransact(int code, Parcel data, Parcel reply, int flags) 157 throws RemoteException { 158 try { 159 return super.onTransact(code, data, reply, flags); 160 } catch (RuntimeException e) { 161 // Log all 'real' exceptions thrown to the caller 162 if (!(e instanceof SecurityException)) { 163 Slog.wtf(TAG_WM, "Window Session Crash", e); 164 } 165 throw e; 166 } 167 } 168 binderDied()169 public void binderDied() { 170 // Note: it is safe to call in to the input method manager 171 // here because we are not holding our lock. 172 try { 173 if (mService.mInputMethodManager != null) { 174 mService.mInputMethodManager.removeClient(mClient); 175 } 176 } catch (RemoteException e) { 177 } 178 synchronized(mService.mWindowMap) { 179 mClient.asBinder().unlinkToDeath(this, 0); 180 mClientDead = true; 181 killSessionLocked(); 182 } 183 } 184 185 @Override add(IWindow window, int seq, WindowManager.LayoutParams attrs, int viewVisibility, Rect outContentInsets, Rect outStableInsets, InputChannel outInputChannel)186 public int add(IWindow window, int seq, WindowManager.LayoutParams attrs, 187 int viewVisibility, Rect outContentInsets, Rect outStableInsets, 188 InputChannel outInputChannel) { 189 return addToDisplay(window, seq, attrs, viewVisibility, Display.DEFAULT_DISPLAY, 190 outContentInsets, outStableInsets, null /* outOutsets */, outInputChannel); 191 } 192 193 @Override addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs, int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets, Rect outOutsets, InputChannel outInputChannel)194 public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs, 195 int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets, 196 Rect outOutsets, InputChannel outInputChannel) { 197 return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId, 198 outContentInsets, outStableInsets, outOutsets, outInputChannel); 199 } 200 201 @Override addWithoutInputChannel(IWindow window, int seq, WindowManager.LayoutParams attrs, int viewVisibility, Rect outContentInsets, Rect outStableInsets)202 public int addWithoutInputChannel(IWindow window, int seq, WindowManager.LayoutParams attrs, 203 int viewVisibility, Rect outContentInsets, Rect outStableInsets) { 204 return addToDisplayWithoutInputChannel(window, seq, attrs, viewVisibility, 205 Display.DEFAULT_DISPLAY, outContentInsets, outStableInsets); 206 } 207 208 @Override addToDisplayWithoutInputChannel(IWindow window, int seq, WindowManager.LayoutParams attrs, int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets)209 public int addToDisplayWithoutInputChannel(IWindow window, int seq, WindowManager.LayoutParams attrs, 210 int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets) { 211 return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId, 212 outContentInsets, outStableInsets, null /* outOutsets */, null); 213 } 214 remove(IWindow window)215 public void remove(IWindow window) { 216 mService.removeWindow(this, window); 217 } 218 219 @Override prepareToReplaceWindows(IBinder appToken, boolean childrenOnly)220 public void prepareToReplaceWindows(IBinder appToken, boolean childrenOnly) { 221 mService.setWillReplaceWindows(appToken, childrenOnly); 222 } 223 relayout(IWindow window, int seq, WindowManager.LayoutParams attrs, int requestedWidth, int requestedHeight, int viewFlags, int flags, Rect outFrame, Rect outOverscanInsets, Rect outContentInsets, Rect outVisibleInsets, Rect outStableInsets, Rect outsets, Rect outBackdropFrame, MergedConfiguration mergedConfiguration, Surface outSurface)224 public int relayout(IWindow window, int seq, WindowManager.LayoutParams attrs, 225 int requestedWidth, int requestedHeight, int viewFlags, 226 int flags, Rect outFrame, Rect outOverscanInsets, Rect outContentInsets, 227 Rect outVisibleInsets, Rect outStableInsets, Rect outsets, Rect outBackdropFrame, 228 MergedConfiguration mergedConfiguration, Surface outSurface) { 229 if (false) Slog.d(TAG_WM, ">>>>>> ENTERED relayout from " 230 + Binder.getCallingPid()); 231 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, mRelayoutTag); 232 int res = mService.relayoutWindow(this, window, seq, attrs, 233 requestedWidth, requestedHeight, viewFlags, flags, 234 outFrame, outOverscanInsets, outContentInsets, outVisibleInsets, 235 outStableInsets, outsets, outBackdropFrame, mergedConfiguration, outSurface); 236 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); 237 if (false) Slog.d(TAG_WM, "<<<<<< EXITING relayout to " 238 + Binder.getCallingPid()); 239 return res; 240 } 241 outOfMemory(IWindow window)242 public boolean outOfMemory(IWindow window) { 243 return mService.outOfMemoryWindow(this, window); 244 } 245 setTransparentRegion(IWindow window, Region region)246 public void setTransparentRegion(IWindow window, Region region) { 247 mService.setTransparentRegionWindow(this, window, region); 248 } 249 setInsets(IWindow window, int touchableInsets, Rect contentInsets, Rect visibleInsets, Region touchableArea)250 public void setInsets(IWindow window, int touchableInsets, 251 Rect contentInsets, Rect visibleInsets, Region touchableArea) { 252 mService.setInsetsWindow(this, window, touchableInsets, contentInsets, 253 visibleInsets, touchableArea); 254 } 255 getDisplayFrame(IWindow window, Rect outDisplayFrame)256 public void getDisplayFrame(IWindow window, Rect outDisplayFrame) { 257 mService.getWindowDisplayFrame(this, window, outDisplayFrame); 258 } 259 finishDrawing(IWindow window)260 public void finishDrawing(IWindow window) { 261 if (WindowManagerService.localLOGV) Slog.v( 262 TAG_WM, "IWindow finishDrawing called for " + window); 263 mService.finishDrawingWindow(this, window); 264 } 265 setInTouchMode(boolean mode)266 public void setInTouchMode(boolean mode) { 267 synchronized(mService.mWindowMap) { 268 mService.mInTouchMode = mode; 269 } 270 } 271 getInTouchMode()272 public boolean getInTouchMode() { 273 synchronized(mService.mWindowMap) { 274 return mService.mInTouchMode; 275 } 276 } 277 performHapticFeedback(IWindow window, int effectId, boolean always)278 public boolean performHapticFeedback(IWindow window, int effectId, 279 boolean always) { 280 synchronized(mService.mWindowMap) { 281 long ident = Binder.clearCallingIdentity(); 282 try { 283 return mService.mPolicy.performHapticFeedbackLw( 284 mService.windowForClientLocked(this, window, true), 285 effectId, always); 286 } finally { 287 Binder.restoreCallingIdentity(ident); 288 } 289 } 290 } 291 292 /* Drag/drop */ prepareDrag(IWindow window, int flags, int width, int height, Surface outSurface)293 public IBinder prepareDrag(IWindow window, int flags, 294 int width, int height, Surface outSurface) { 295 return mService.prepareDragSurface(window, mSurfaceSession, flags, 296 width, height, outSurface); 297 } 298 performDrag(IWindow window, IBinder dragToken, int touchSource, float touchX, float touchY, float thumbCenterX, float thumbCenterY, ClipData data)299 public boolean performDrag(IWindow window, IBinder dragToken, 300 int touchSource, float touchX, float touchY, float thumbCenterX, float thumbCenterY, 301 ClipData data) { 302 if (DEBUG_DRAG) { 303 Slog.d(TAG_WM, "perform drag: win=" + window + " data=" + data); 304 } 305 306 synchronized (mService.mWindowMap) { 307 if (mService.mDragState == null) { 308 Slog.w(TAG_WM, "No drag prepared"); 309 throw new IllegalStateException("performDrag() without prepareDrag()"); 310 } 311 312 if (dragToken != mService.mDragState.mToken) { 313 Slog.w(TAG_WM, "Performing mismatched drag"); 314 throw new IllegalStateException("performDrag() does not match prepareDrag()"); 315 } 316 317 WindowState callingWin = mService.windowForClientLocked(null, window, false); 318 if (callingWin == null) { 319 Slog.w(TAG_WM, "Bad requesting window " + window); 320 return false; // !!! TODO: throw here? 321 } 322 323 // !!! TODO: if input is not still focused on the initiating window, fail 324 // the drag initiation (e.g. an alarm window popped up just as the application 325 // called performDrag() 326 327 mService.mH.removeMessages(H.DRAG_START_TIMEOUT, window.asBinder()); 328 329 // !!! TODO: extract the current touch (x, y) in screen coordinates. That 330 // will let us eliminate the (touchX,touchY) parameters from the API. 331 332 // !!! FIXME: put all this heavy stuff onto the mH looper, as well as 333 // the actual drag event dispatch stuff in the dragstate 334 335 final DisplayContent displayContent = callingWin.getDisplayContent(); 336 if (displayContent == null) { 337 return false; 338 } 339 Display display = displayContent.getDisplay(); 340 mService.mDragState.register(display); 341 if (!mService.mInputManager.transferTouchFocus(callingWin.mInputChannel, 342 mService.mDragState.getInputChannel())) { 343 Slog.e(TAG_WM, "Unable to transfer touch focus"); 344 mService.mDragState.unregister(); 345 mService.mDragState.reset(); 346 mService.mDragState = null; 347 return false; 348 } 349 350 mService.mDragState.mDisplayContent = displayContent; 351 mService.mDragState.mData = data; 352 mService.mDragState.broadcastDragStartedLw(touchX, touchY); 353 mService.mDragState.overridePointerIconLw(touchSource); 354 355 // remember the thumb offsets for later 356 mService.mDragState.mThumbOffsetX = thumbCenterX; 357 mService.mDragState.mThumbOffsetY = thumbCenterY; 358 359 // Make the surface visible at the proper location 360 final SurfaceControl surfaceControl = mService.mDragState.mSurfaceControl; 361 if (SHOW_LIGHT_TRANSACTIONS) Slog.i( 362 TAG_WM, ">>> OPEN TRANSACTION performDrag"); 363 mService.openSurfaceTransaction(); 364 try { 365 surfaceControl.setPosition(touchX - thumbCenterX, 366 touchY - thumbCenterY); 367 surfaceControl.setLayer(mService.mDragState.getDragLayerLw()); 368 surfaceControl.setLayerStack(display.getLayerStack()); 369 surfaceControl.show(); 370 } finally { 371 mService.closeSurfaceTransaction(); 372 if (SHOW_LIGHT_TRANSACTIONS) Slog.i( 373 TAG_WM, "<<< CLOSE TRANSACTION performDrag"); 374 } 375 376 mService.mDragState.notifyLocationLw(touchX, touchY); 377 } 378 379 return true; // success! 380 } 381 startMovingTask(IWindow window, float startX, float startY)382 public boolean startMovingTask(IWindow window, float startX, float startY) { 383 if (DEBUG_TASK_POSITIONING) Slog.d( 384 TAG_WM, "startMovingTask: {" + startX + "," + startY + "}"); 385 386 long ident = Binder.clearCallingIdentity(); 387 try { 388 return mService.startMovingTask(window, startX, startY); 389 } finally { 390 Binder.restoreCallingIdentity(ident); 391 } 392 } 393 reportDropResult(IWindow window, boolean consumed)394 public void reportDropResult(IWindow window, boolean consumed) { 395 IBinder token = window.asBinder(); 396 if (DEBUG_DRAG) { 397 Slog.d(TAG_WM, "Drop result=" + consumed + " reported by " + token); 398 } 399 400 synchronized (mService.mWindowMap) { 401 long ident = Binder.clearCallingIdentity(); 402 try { 403 if (mService.mDragState == null) { 404 // Most likely the drop recipient ANRed and we ended the drag 405 // out from under it. Log the issue and move on. 406 Slog.w(TAG_WM, "Drop result given but no drag in progress"); 407 return; 408 } 409 410 if (mService.mDragState.mToken != token) { 411 // We're in a drag, but the wrong window has responded. 412 Slog.w(TAG_WM, "Invalid drop-result claim by " + window); 413 throw new IllegalStateException("reportDropResult() by non-recipient"); 414 } 415 416 // The right window has responded, even if it's no longer around, 417 // so be sure to halt the timeout even if the later WindowState 418 // lookup fails. 419 mService.mH.removeMessages(H.DRAG_END_TIMEOUT, window.asBinder()); 420 WindowState callingWin = mService.windowForClientLocked(null, window, false); 421 if (callingWin == null) { 422 Slog.w(TAG_WM, "Bad result-reporting window " + window); 423 return; // !!! TODO: throw here? 424 } 425 426 mService.mDragState.mDragResult = consumed; 427 mService.mDragState.endDragLw(); 428 } finally { 429 Binder.restoreCallingIdentity(ident); 430 } 431 } 432 } 433 cancelDragAndDrop(IBinder dragToken)434 public void cancelDragAndDrop(IBinder dragToken) { 435 if (DEBUG_DRAG) { 436 Slog.d(TAG_WM, "cancelDragAndDrop"); 437 } 438 439 synchronized (mService.mWindowMap) { 440 long ident = Binder.clearCallingIdentity(); 441 try { 442 if (mService.mDragState == null) { 443 Slog.w(TAG_WM, "cancelDragAndDrop() without prepareDrag()"); 444 throw new IllegalStateException("cancelDragAndDrop() without prepareDrag()"); 445 } 446 447 if (mService.mDragState.mToken != dragToken) { 448 Slog.w(TAG_WM, 449 "cancelDragAndDrop() does not match prepareDrag()"); 450 throw new IllegalStateException( 451 "cancelDragAndDrop() does not match prepareDrag()"); 452 } 453 454 mService.mDragState.mDragResult = false; 455 mService.mDragState.cancelDragLw(); 456 } finally { 457 Binder.restoreCallingIdentity(ident); 458 } 459 } 460 } 461 dragRecipientEntered(IWindow window)462 public void dragRecipientEntered(IWindow window) { 463 if (DEBUG_DRAG) { 464 Slog.d(TAG_WM, "Drag into new candidate view @ " + window.asBinder()); 465 } 466 } 467 dragRecipientExited(IWindow window)468 public void dragRecipientExited(IWindow window) { 469 if (DEBUG_DRAG) { 470 Slog.d(TAG_WM, "Drag from old candidate view @ " + window.asBinder()); 471 } 472 } 473 setWallpaperPosition(IBinder window, float x, float y, float xStep, float yStep)474 public void setWallpaperPosition(IBinder window, float x, float y, float xStep, float yStep) { 475 synchronized(mService.mWindowMap) { 476 long ident = Binder.clearCallingIdentity(); 477 try { 478 mService.mRoot.mWallpaperController.setWindowWallpaperPosition( 479 mService.windowForClientLocked(this, window, true), 480 x, y, xStep, yStep); 481 } finally { 482 Binder.restoreCallingIdentity(ident); 483 } 484 } 485 } 486 wallpaperOffsetsComplete(IBinder window)487 public void wallpaperOffsetsComplete(IBinder window) { 488 synchronized (mService.mWindowMap) { 489 mService.mRoot.mWallpaperController.wallpaperOffsetsComplete(window); 490 } 491 } 492 setWallpaperDisplayOffset(IBinder window, int x, int y)493 public void setWallpaperDisplayOffset(IBinder window, int x, int y) { 494 synchronized(mService.mWindowMap) { 495 long ident = Binder.clearCallingIdentity(); 496 try { 497 mService.mRoot.mWallpaperController.setWindowWallpaperDisplayOffset( 498 mService.windowForClientLocked(this, window, true), x, y); 499 } finally { 500 Binder.restoreCallingIdentity(ident); 501 } 502 } 503 } 504 sendWallpaperCommand(IBinder window, String action, int x, int y, int z, Bundle extras, boolean sync)505 public Bundle sendWallpaperCommand(IBinder window, String action, int x, int y, 506 int z, Bundle extras, boolean sync) { 507 synchronized(mService.mWindowMap) { 508 long ident = Binder.clearCallingIdentity(); 509 try { 510 return mService.mRoot.mWallpaperController.sendWindowWallpaperCommand( 511 mService.windowForClientLocked(this, window, true), 512 action, x, y, z, extras, sync); 513 } finally { 514 Binder.restoreCallingIdentity(ident); 515 } 516 } 517 } 518 wallpaperCommandComplete(IBinder window, Bundle result)519 public void wallpaperCommandComplete(IBinder window, Bundle result) { 520 synchronized (mService.mWindowMap) { 521 mService.mRoot.mWallpaperController.wallpaperCommandComplete(window); 522 } 523 } 524 onRectangleOnScreenRequested(IBinder token, Rect rectangle)525 public void onRectangleOnScreenRequested(IBinder token, Rect rectangle) { 526 synchronized(mService.mWindowMap) { 527 final long identity = Binder.clearCallingIdentity(); 528 try { 529 mService.onRectangleOnScreenRequested(token, rectangle); 530 } finally { 531 Binder.restoreCallingIdentity(identity); 532 } 533 } 534 } 535 getWindowId(IBinder window)536 public IWindowId getWindowId(IBinder window) { 537 return mService.getWindowId(window); 538 } 539 540 @Override pokeDrawLock(IBinder window)541 public void pokeDrawLock(IBinder window) { 542 final long identity = Binder.clearCallingIdentity(); 543 try { 544 mService.pokeDrawLock(this, window); 545 } finally { 546 Binder.restoreCallingIdentity(identity); 547 } 548 } 549 550 @Override updatePointerIcon(IWindow window)551 public void updatePointerIcon(IWindow window) { 552 final long identity = Binder.clearCallingIdentity(); 553 try { 554 mService.updatePointerIcon(window); 555 } finally { 556 Binder.restoreCallingIdentity(identity); 557 } 558 } 559 windowAddedLocked(String packageName)560 void windowAddedLocked(String packageName) { 561 mPackageName = packageName; 562 mRelayoutTag = "relayoutWindow: " + mPackageName; 563 if (mSurfaceSession == null) { 564 if (WindowManagerService.localLOGV) Slog.v( 565 TAG_WM, "First window added to " + this + ", creating SurfaceSession"); 566 mSurfaceSession = new SurfaceSession(); 567 if (SHOW_TRANSACTIONS) Slog.i( 568 TAG_WM, " NEW SURFACE SESSION " + mSurfaceSession); 569 mService.mSessions.add(this); 570 if (mLastReportedAnimatorScale != mService.getCurrentAnimatorScale()) { 571 mService.dispatchNewAnimatorScaleLocked(this); 572 } 573 } 574 mNumWindow++; 575 } 576 windowRemovedLocked()577 void windowRemovedLocked() { 578 mNumWindow--; 579 killSessionLocked(); 580 } 581 582 onWindowSurfaceVisibilityChanged(WindowSurfaceController surfaceController, boolean visible, int type)583 void onWindowSurfaceVisibilityChanged(WindowSurfaceController surfaceController, 584 boolean visible, int type) { 585 586 if (!isSystemAlertWindowType(type)) { 587 return; 588 } 589 590 boolean changed; 591 592 if (!mCanAddInternalSystemWindow) { 593 // We want to track non-system signature apps adding alert windows so we can post an 594 // on-going notification for the user to control their visibility. 595 if (visible) { 596 changed = mAlertWindowSurfaces.add(surfaceController); 597 } else { 598 changed = mAlertWindowSurfaces.remove(surfaceController); 599 } 600 601 if (changed) { 602 if (mAlertWindowSurfaces.isEmpty()) { 603 cancelAlertWindowNotification(); 604 } else if (mAlertWindowNotification == null){ 605 mAlertWindowNotification = new AlertWindowNotification(mService, mPackageName); 606 if (mShowingAlertWindowNotificationAllowed) { 607 mAlertWindowNotification.post(); 608 } 609 } 610 } 611 } 612 613 if (type != TYPE_APPLICATION_OVERLAY) { 614 return; 615 } 616 617 if (visible) { 618 changed = mAppOverlaySurfaces.add(surfaceController); 619 } else { 620 changed = mAppOverlaySurfaces.remove(surfaceController); 621 } 622 623 if (changed) { 624 // Notify activity manager of changes to app overlay windows so it can adjust the 625 // importance score for the process. 626 setHasOverlayUi(!mAppOverlaySurfaces.isEmpty()); 627 } 628 } 629 setShowingAlertWindowNotificationAllowed(boolean allowed)630 void setShowingAlertWindowNotificationAllowed(boolean allowed) { 631 mShowingAlertWindowNotificationAllowed = allowed; 632 if (mAlertWindowNotification != null) { 633 if (allowed) { 634 mAlertWindowNotification.post(); 635 } else { 636 mAlertWindowNotification.cancel(); 637 } 638 } 639 } 640 killSessionLocked()641 private void killSessionLocked() { 642 if (mNumWindow > 0 || !mClientDead) { 643 return; 644 } 645 646 mService.mSessions.remove(this); 647 if (mSurfaceSession == null) { 648 return; 649 } 650 651 if (WindowManagerService.localLOGV) Slog.v(TAG_WM, "Last window removed from " + this 652 + ", destroying " + mSurfaceSession); 653 if (SHOW_TRANSACTIONS) Slog.i(TAG_WM, " KILL SURFACE SESSION " + mSurfaceSession); 654 try { 655 mSurfaceSession.kill(); 656 } catch (Exception e) { 657 Slog.w(TAG_WM, "Exception thrown when killing surface session " + mSurfaceSession 658 + " in session " + this + ": " + e.toString()); 659 } 660 mSurfaceSession = null; 661 mAlertWindowSurfaces.clear(); 662 mAppOverlaySurfaces.clear(); 663 setHasOverlayUi(false); 664 cancelAlertWindowNotification(); 665 } 666 setHasOverlayUi(boolean hasOverlayUi)667 private void setHasOverlayUi(boolean hasOverlayUi) { 668 mService.mH.obtainMessage(H.SET_HAS_OVERLAY_UI, mPid, hasOverlayUi ? 1 : 0).sendToTarget(); 669 } 670 cancelAlertWindowNotification()671 private void cancelAlertWindowNotification() { 672 if (mAlertWindowNotification == null) { 673 return; 674 } 675 mAlertWindowNotification.cancel(); 676 mAlertWindowNotification = null; 677 } 678 dump(PrintWriter pw, String prefix)679 void dump(PrintWriter pw, String prefix) { 680 pw.print(prefix); pw.print("mNumWindow="); pw.print(mNumWindow); 681 pw.print(" mCanAddInternalSystemWindow="); pw.print(mCanAddInternalSystemWindow); 682 pw.print(" mAppOverlaySurfaces="); pw.print(mAppOverlaySurfaces); 683 pw.print(" mAlertWindowSurfaces="); pw.print(mAlertWindowSurfaces); 684 pw.print(" mClientDead="); pw.print(mClientDead); 685 pw.print(" mSurfaceSession="); pw.println(mSurfaceSession); 686 pw.print(prefix); pw.print("mPackageName="); pw.println(mPackageName); 687 } 688 689 @Override toString()690 public String toString() { 691 return mStringName; 692 } 693 } 694