blob: b4cf2ae768f15e025869407e096c2da487121341 [file] [log] [blame]
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08001/*
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
Dianne Hackborne3f23a32013-03-01 13:25:35 -080019import android.view.IWindowId;
Dianne Hackborneb94fa72014-06-03 17:48:12 -070020import android.view.IWindowSessionCallback;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080021import com.android.internal.view.IInputContext;
22import com.android.internal.view.IInputMethodClient;
23import com.android.internal.view.IInputMethodManager;
24import com.android.server.wm.WindowManagerService.H;
25
26import android.content.ClipData;
27import android.content.Context;
28import android.content.res.Configuration;
29import android.graphics.Rect;
30import android.graphics.Region;
31import android.os.Binder;
32import android.os.Bundle;
33import android.os.IBinder;
34import android.os.Parcel;
Dianne Hackborn5fe7e2a2012-10-04 11:58:16 -070035import android.os.Process;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080036import android.os.RemoteException;
37import android.os.ServiceManager;
Dianne Hackborn5fe7e2a2012-10-04 11:58:16 -070038import android.os.UserHandle;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080039import android.util.Slog;
Craig Mautner6881a102012-07-27 13:04:51 -070040import android.view.Display;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080041import android.view.IWindow;
42import android.view.IWindowSession;
43import android.view.InputChannel;
44import android.view.Surface;
Mathias Agopian3866f0d2013-02-11 22:08:48 -080045import android.view.SurfaceControl;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080046import android.view.SurfaceSession;
47import android.view.WindowManager;
48
49import java.io.PrintWriter;
50
51/**
52 * This class represents an active client session. There is generally one
53 * Session object per process that is interacting with the window manager.
54 */
55final class Session extends IWindowSession.Stub
56 implements IBinder.DeathRecipient {
57 final WindowManagerService mService;
Dianne Hackborneb94fa72014-06-03 17:48:12 -070058 final IWindowSessionCallback mCallback;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080059 final IInputMethodClient mClient;
60 final IInputContext mInputContext;
61 final int mUid;
62 final int mPid;
63 final String mStringName;
64 SurfaceSession mSurfaceSession;
65 int mNumWindow = 0;
66 boolean mClientDead = false;
Dianne Hackborneb94fa72014-06-03 17:48:12 -070067 float mLastReportedAnimatorScale;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080068
Dianne Hackborneb94fa72014-06-03 17:48:12 -070069 public Session(WindowManagerService service, IWindowSessionCallback callback,
70 IInputMethodClient client, IInputContext inputContext) {
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080071 mService = service;
Dianne Hackborneb94fa72014-06-03 17:48:12 -070072 mCallback = callback;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080073 mClient = client;
74 mInputContext = inputContext;
75 mUid = Binder.getCallingUid();
76 mPid = Binder.getCallingPid();
Dianne Hackborneb94fa72014-06-03 17:48:12 -070077 mLastReportedAnimatorScale = service.getCurrentAnimatorScale();
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080078 StringBuilder sb = new StringBuilder();
79 sb.append("Session{");
80 sb.append(Integer.toHexString(System.identityHashCode(this)));
Dianne Hackborn5fe7e2a2012-10-04 11:58:16 -070081 sb.append(" ");
82 sb.append(mPid);
83 if (mUid < Process.FIRST_APPLICATION_UID) {
84 sb.append(":");
85 sb.append(mUid);
86 } else {
87 sb.append(":u");
88 sb.append(UserHandle.getUserId(mUid));
89 sb.append('a');
90 sb.append(UserHandle.getAppId(mUid));
91 }
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080092 sb.append("}");
93 mStringName = sb.toString();
94
95 synchronized (mService.mWindowMap) {
96 if (mService.mInputMethodManager == null && mService.mHaveInputMethods) {
97 IBinder b = ServiceManager.getService(
98 Context.INPUT_METHOD_SERVICE);
99 mService.mInputMethodManager = IInputMethodManager.Stub.asInterface(b);
100 }
101 }
102 long ident = Binder.clearCallingIdentity();
103 try {
104 // Note: it is safe to call in to the input method manager
105 // here because we are not holding our lock.
106 if (mService.mInputMethodManager != null) {
107 mService.mInputMethodManager.addClient(client, inputContext,
108 mUid, mPid);
109 } else {
110 client.setUsingInputMethod(false);
111 }
112 client.asBinder().linkToDeath(this, 0);
113 } catch (RemoteException e) {
114 // The caller has died, so we can just forget about this.
115 try {
116 if (mService.mInputMethodManager != null) {
117 mService.mInputMethodManager.removeClient(client);
118 }
119 } catch (RemoteException ee) {
120 }
121 } finally {
122 Binder.restoreCallingIdentity(ident);
123 }
124 }
125
126 @Override
127 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
128 throws RemoteException {
129 try {
130 return super.onTransact(code, data, reply, flags);
131 } catch (RuntimeException e) {
132 // Log all 'real' exceptions thrown to the caller
133 if (!(e instanceof SecurityException)) {
Dianne Hackborn164371f2013-10-01 19:10:13 -0700134 Slog.wtf(WindowManagerService.TAG, "Window Session Crash", e);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800135 }
136 throw e;
137 }
138 }
139
140 public void binderDied() {
141 // Note: it is safe to call in to the input method manager
142 // here because we are not holding our lock.
143 try {
144 if (mService.mInputMethodManager != null) {
145 mService.mInputMethodManager.removeClient(mClient);
146 }
147 } catch (RemoteException e) {
148 }
149 synchronized(mService.mWindowMap) {
150 mClient.asBinder().unlinkToDeath(this, 0);
151 mClientDead = true;
152 killSessionLocked();
153 }
154 }
155
Craig Mautner6881a102012-07-27 13:04:51 -0700156 @Override
Dianne Hackborn9a230e02011-10-06 11:51:27 -0700157 public int add(IWindow window, int seq, WindowManager.LayoutParams attrs,
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800158 int viewVisibility, Rect outContentInsets, InputChannel outInputChannel) {
Craig Mautner6881a102012-07-27 13:04:51 -0700159 return addToDisplay(window, seq, attrs, viewVisibility, Display.DEFAULT_DISPLAY,
160 outContentInsets, outInputChannel);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800161 }
Craig Mautner6881a102012-07-27 13:04:51 -0700162
163 @Override
164 public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs,
165 int viewVisibility, int displayId, Rect outContentInsets,
166 InputChannel outInputChannel) {
167 return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId,
168 outContentInsets, outInputChannel);
169 }
170
171 @Override
Dianne Hackborn9a230e02011-10-06 11:51:27 -0700172 public int addWithoutInputChannel(IWindow window, int seq, WindowManager.LayoutParams attrs,
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800173 int viewVisibility, Rect outContentInsets) {
Craig Mautner6881a102012-07-27 13:04:51 -0700174 return addToDisplayWithoutInputChannel(window, seq, attrs, viewVisibility,
175 Display.DEFAULT_DISPLAY, outContentInsets);
176 }
177
178 @Override
179 public int addToDisplayWithoutInputChannel(IWindow window, int seq, WindowManager.LayoutParams attrs,
180 int viewVisibility, int displayId, Rect outContentInsets) {
181 return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId,
182 outContentInsets, null);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800183 }
184
185 public void remove(IWindow window) {
186 mService.removeWindow(this, window);
187 }
188
Dianne Hackborn9a230e02011-10-06 11:51:27 -0700189 public int relayout(IWindow window, int seq, WindowManager.LayoutParams attrs,
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800190 int requestedWidth, int requestedHeight, int viewFlags,
Dianne Hackbornc4aad012013-02-22 15:05:25 -0800191 int flags, Rect outFrame, Rect outOverscanInsets, Rect outContentInsets,
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800192 Rect outVisibleInsets, Configuration outConfig, Surface outSurface) {
Dianne Hackbornb961cd22011-06-21 12:13:37 -0700193 if (false) Slog.d(WindowManagerService.TAG, ">>>>>> ENTERED relayout from "
194 + Binder.getCallingPid());
Dianne Hackborn9a230e02011-10-06 11:51:27 -0700195 int res = mService.relayoutWindow(this, window, seq, attrs,
Dianne Hackborn6d05fd32011-11-19 14:36:15 -0800196 requestedWidth, requestedHeight, viewFlags, flags,
Dianne Hackbornc4aad012013-02-22 15:05:25 -0800197 outFrame, outOverscanInsets, outContentInsets, outVisibleInsets,
Dianne Hackborn5c58de32012-04-28 19:52:37 -0700198 outConfig, outSurface);
Dianne Hackbornb961cd22011-06-21 12:13:37 -0700199 if (false) Slog.d(WindowManagerService.TAG, "<<<<<< EXITING relayout to "
200 + Binder.getCallingPid());
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800201 return res;
202 }
203
Dianne Hackborn6d05fd32011-11-19 14:36:15 -0800204 public void performDeferredDestroy(IWindow window) {
205 mService.performDeferredDestroyWindow(this, window);
206 }
207
Dianne Hackborn64825172011-03-02 21:32:58 -0800208 public boolean outOfMemory(IWindow window) {
209 return mService.outOfMemoryWindow(this, window);
210 }
211
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800212 public void setTransparentRegion(IWindow window, Region region) {
213 mService.setTransparentRegionWindow(this, window, region);
214 }
215
216 public void setInsets(IWindow window, int touchableInsets,
217 Rect contentInsets, Rect visibleInsets, Region touchableArea) {
218 mService.setInsetsWindow(this, window, touchableInsets, contentInsets,
219 visibleInsets, touchableArea);
220 }
221
222 public void getDisplayFrame(IWindow window, Rect outDisplayFrame) {
223 mService.getWindowDisplayFrame(this, window, outDisplayFrame);
224 }
225
226 public void finishDrawing(IWindow window) {
227 if (WindowManagerService.localLOGV) Slog.v(
228 WindowManagerService.TAG, "IWindow finishDrawing called for " + window);
229 mService.finishDrawingWindow(this, window);
230 }
231
232 public void setInTouchMode(boolean mode) {
233 synchronized(mService.mWindowMap) {
234 mService.mInTouchMode = mode;
235 }
236 }
237
238 public boolean getInTouchMode() {
239 synchronized(mService.mWindowMap) {
240 return mService.mInTouchMode;
241 }
242 }
243
244 public boolean performHapticFeedback(IWindow window, int effectId,
245 boolean always) {
246 synchronized(mService.mWindowMap) {
247 long ident = Binder.clearCallingIdentity();
248 try {
249 return mService.mPolicy.performHapticFeedbackLw(
250 mService.windowForClientLocked(this, window, true),
251 effectId, always);
252 } finally {
253 Binder.restoreCallingIdentity(ident);
254 }
255 }
256 }
257
258 /* Drag/drop */
259 public IBinder prepareDrag(IWindow window, int flags,
260 int width, int height, Surface outSurface) {
261 return mService.prepareDragSurface(window, mSurfaceSession, flags,
262 width, height, outSurface);
263 }
264
265 public boolean performDrag(IWindow window, IBinder dragToken,
266 float touchX, float touchY, float thumbCenterX, float thumbCenterY,
267 ClipData data) {
268 if (WindowManagerService.DEBUG_DRAG) {
269 Slog.d(WindowManagerService.TAG, "perform drag: win=" + window + " data=" + data);
270 }
271
272 synchronized (mService.mWindowMap) {
273 if (mService.mDragState == null) {
274 Slog.w(WindowManagerService.TAG, "No drag prepared");
275 throw new IllegalStateException("performDrag() without prepareDrag()");
276 }
277
278 if (dragToken != mService.mDragState.mToken) {
279 Slog.w(WindowManagerService.TAG, "Performing mismatched drag");
280 throw new IllegalStateException("performDrag() does not match prepareDrag()");
281 }
282
283 WindowState callingWin = mService.windowForClientLocked(null, window, false);
284 if (callingWin == null) {
285 Slog.w(WindowManagerService.TAG, "Bad requesting window " + window);
286 return false; // !!! TODO: throw here?
287 }
288
289 // !!! TODO: if input is not still focused on the initiating window, fail
290 // the drag initiation (e.g. an alarm window popped up just as the application
291 // called performDrag()
292
293 mService.mH.removeMessages(H.DRAG_START_TIMEOUT, window.asBinder());
294
295 // !!! TODO: extract the current touch (x, y) in screen coordinates. That
296 // will let us eliminate the (touchX,touchY) parameters from the API.
297
298 // !!! FIXME: put all this heavy stuff onto the mH looper, as well as
299 // the actual drag event dispatch stuff in the dragstate
300
Craig Mautnerdf88d732014-01-27 09:21:32 -0800301 final DisplayContent displayContent = callingWin.getDisplayContent();
302 if (displayContent == null) {
303 return false;
304 }
305 Display display = displayContent.getDisplay();
Jeff Brown14a9f2b2012-09-24 14:36:44 -0700306 mService.mDragState.register(display);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800307 mService.mInputMonitor.updateInputWindowsLw(true /*force*/);
308 if (!mService.mInputManager.transferTouchFocus(callingWin.mInputChannel,
309 mService.mDragState.mServerChannel)) {
310 Slog.e(WindowManagerService.TAG, "Unable to transfer touch focus");
311 mService.mDragState.unregister();
312 mService.mDragState = null;
313 mService.mInputMonitor.updateInputWindowsLw(true /*force*/);
314 return false;
315 }
316
317 mService.mDragState.mData = data;
318 mService.mDragState.mCurrentX = touchX;
319 mService.mDragState.mCurrentY = touchY;
320 mService.mDragState.broadcastDragStartedLw(touchX, touchY);
321
322 // remember the thumb offsets for later
323 mService.mDragState.mThumbOffsetX = thumbCenterX;
324 mService.mDragState.mThumbOffsetY = thumbCenterY;
325
326 // Make the surface visible at the proper location
Mathias Agopian29479eb2013-02-14 14:36:04 -0800327 final SurfaceControl surfaceControl = mService.mDragState.mSurfaceControl;
Dianne Hackborn36991742011-10-11 21:35:26 -0700328 if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS) Slog.i(
329 WindowManagerService.TAG, ">>> OPEN TRANSACTION performDrag");
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800330 SurfaceControl.openTransaction();
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800331 try {
Mathias Agopian29479eb2013-02-14 14:36:04 -0800332 surfaceControl.setPosition(touchX - thumbCenterX,
Dianne Hackbornd040edb2011-08-31 12:47:58 -0700333 touchY - thumbCenterY);
Mathias Agopian29479eb2013-02-14 14:36:04 -0800334 surfaceControl.setAlpha(.7071f);
335 surfaceControl.setLayer(mService.mDragState.getDragLayerLw());
336 surfaceControl.setLayerStack(display.getLayerStack());
337 surfaceControl.show();
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800338 } finally {
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800339 SurfaceControl.closeTransaction();
Dianne Hackborn36991742011-10-11 21:35:26 -0700340 if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS) Slog.i(
341 WindowManagerService.TAG, "<<< CLOSE TRANSACTION performDrag");
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800342 }
343 }
344
345 return true; // success!
346 }
347
348 public void reportDropResult(IWindow window, boolean consumed) {
349 IBinder token = window.asBinder();
350 if (WindowManagerService.DEBUG_DRAG) {
351 Slog.d(WindowManagerService.TAG, "Drop result=" + consumed + " reported by " + token);
352 }
353
354 synchronized (mService.mWindowMap) {
355 long ident = Binder.clearCallingIdentity();
356 try {
Christopher Tate05e9c652011-10-20 12:34:36 -0700357 if (mService.mDragState == null) {
358 // Most likely the drop recipient ANRed and we ended the drag
359 // out from under it. Log the issue and move on.
360 Slog.w(WindowManagerService.TAG, "Drop result given but no drag in progress");
361 return;
362 }
363
364 if (mService.mDragState.mToken != token) {
365 // We're in a drag, but the wrong window has responded.
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800366 Slog.w(WindowManagerService.TAG, "Invalid drop-result claim by " + window);
367 throw new IllegalStateException("reportDropResult() by non-recipient");
368 }
369
370 // The right window has responded, even if it's no longer around,
371 // so be sure to halt the timeout even if the later WindowState
372 // lookup fails.
373 mService.mH.removeMessages(H.DRAG_END_TIMEOUT, window.asBinder());
374 WindowState callingWin = mService.windowForClientLocked(null, window, false);
375 if (callingWin == null) {
376 Slog.w(WindowManagerService.TAG, "Bad result-reporting window " + window);
377 return; // !!! TODO: throw here?
378 }
379
380 mService.mDragState.mDragResult = consumed;
381 mService.mDragState.endDragLw();
382 } finally {
383 Binder.restoreCallingIdentity(ident);
384 }
385 }
386 }
387
388 public void dragRecipientEntered(IWindow window) {
389 if (WindowManagerService.DEBUG_DRAG) {
390 Slog.d(WindowManagerService.TAG, "Drag into new candidate view @ " + window.asBinder());
391 }
392 }
393
394 public void dragRecipientExited(IWindow window) {
395 if (WindowManagerService.DEBUG_DRAG) {
396 Slog.d(WindowManagerService.TAG, "Drag from old candidate view @ " + window.asBinder());
397 }
398 }
399
400 public void setWallpaperPosition(IBinder window, float x, float y, float xStep, float yStep) {
401 synchronized(mService.mWindowMap) {
402 long ident = Binder.clearCallingIdentity();
403 try {
404 mService.setWindowWallpaperPositionLocked(
405 mService.windowForClientLocked(this, window, true),
406 x, y, xStep, yStep);
407 } finally {
408 Binder.restoreCallingIdentity(ident);
409 }
410 }
411 }
412
413 public void wallpaperOffsetsComplete(IBinder window) {
414 mService.wallpaperOffsetsComplete(window);
415 }
416
417 public Bundle sendWallpaperCommand(IBinder window, String action, int x, int y,
418 int z, Bundle extras, boolean sync) {
419 synchronized(mService.mWindowMap) {
420 long ident = Binder.clearCallingIdentity();
421 try {
422 return mService.sendWindowWallpaperCommandLocked(
423 mService.windowForClientLocked(this, window, true),
424 action, x, y, z, extras, sync);
425 } finally {
426 Binder.restoreCallingIdentity(ident);
427 }
428 }
429 }
430
431 public void wallpaperCommandComplete(IBinder window, Bundle result) {
432 mService.wallpaperCommandComplete(window, result);
433 }
434
Dianne Hackborna4b7f2f2012-05-21 11:28:41 -0700435 public void setUniverseTransform(IBinder window, float alpha, float offx, float offy,
436 float dsdx, float dtdx, float dsdy, float dtdy) {
437 synchronized(mService.mWindowMap) {
438 long ident = Binder.clearCallingIdentity();
439 try {
440 mService.setUniverseTransformLocked(
441 mService.windowForClientLocked(this, window, true),
442 alpha, offx, offy, dsdx, dtdx, dsdy, dtdy);
443 } finally {
444 Binder.restoreCallingIdentity(ident);
445 }
446 }
447 }
448
Svetoslavf7174e82014-06-12 11:29:35 -0700449 public void onRectangleOnScreenRequested(IBinder token, Rect rectangle) {
Svetoslav Ganov1cf70bb2012-08-06 10:53:34 -0700450 synchronized(mService.mWindowMap) {
451 final long identity = Binder.clearCallingIdentity();
452 try {
Svetoslavf7174e82014-06-12 11:29:35 -0700453 mService.onRectangleOnScreenRequested(token, rectangle);
Svetoslav Ganov1cf70bb2012-08-06 10:53:34 -0700454 } finally {
455 Binder.restoreCallingIdentity(identity);
456 }
457 }
458 }
459
Dianne Hackborne3f23a32013-03-01 13:25:35 -0800460 public IWindowId getWindowId(IBinder window) {
461 return mService.getWindowId(window);
462 }
463
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800464 void windowAddedLocked() {
465 if (mSurfaceSession == null) {
466 if (WindowManagerService.localLOGV) Slog.v(
467 WindowManagerService.TAG, "First window added to " + this + ", creating SurfaceSession");
468 mSurfaceSession = new SurfaceSession();
469 if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(
470 WindowManagerService.TAG, " NEW SURFACE SESSION " + mSurfaceSession);
471 mService.mSessions.add(this);
Dianne Hackborneb94fa72014-06-03 17:48:12 -0700472 if (mLastReportedAnimatorScale != mService.getCurrentAnimatorScale()) {
473 mService.dispatchNewAnimatorScaleLocked(this);
474 }
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800475 }
476 mNumWindow++;
477 }
478
479 void windowRemovedLocked() {
480 mNumWindow--;
481 killSessionLocked();
482 }
483
484 void killSessionLocked() {
485 if (mNumWindow <= 0 && mClientDead) {
486 mService.mSessions.remove(this);
487 if (mSurfaceSession != null) {
488 if (WindowManagerService.localLOGV) Slog.v(
489 WindowManagerService.TAG, "Last window removed from " + this
490 + ", destroying " + mSurfaceSession);
491 if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(
492 WindowManagerService.TAG, " KILL SURFACE SESSION " + mSurfaceSession);
493 try {
494 mSurfaceSession.kill();
495 } catch (Exception e) {
496 Slog.w(WindowManagerService.TAG, "Exception thrown when killing surface session "
497 + mSurfaceSession + " in session " + this
498 + ": " + e.toString());
499 }
500 mSurfaceSession = null;
501 }
502 }
503 }
504
505 void dump(PrintWriter pw, String prefix) {
506 pw.print(prefix); pw.print("mNumWindow="); pw.print(mNumWindow);
507 pw.print(" mClientDead="); pw.print(mClientDead);
508 pw.print(" mSurfaceSession="); pw.println(mSurfaceSession);
509 }
510
511 @Override
512 public String toString() {
513 return mStringName;
514 }
515}