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