[置頂] Android之基礎建設之IWindow和IWindowSession
阿新 • • 發佈:2019-01-09
private final class Session extends IWindowSession.Stub implements IBinder.DeathRecipient { final IInputMethodClient mClient; final IInputContext mInputContext; final int mUid; final int mPid; final String mStringName; SurfaceSession mSurfaceSession; int mNumWindow = 0; boolean mClientDead = false; public Session(IInputMethodClient client, IInputContext inputContext) { mClient = client; mInputContext = inputContext; mUid = Binder.getCallingUid(); mPid = Binder.getCallingPid(); StringBuilder sb = new StringBuilder(); sb.append("Session{"); sb.append(Integer.toHexString(System.identityHashCode(this))); sb.append(" uid "); sb.append(mUid); sb.append("}"); mStringName = sb.toString(); synchronized (mWindowMap) { if (mInputMethodManager == null && mHaveInputMethods) { IBinder b = ServiceManager.getService( Context.INPUT_METHOD_SERVICE); mInputMethodManager = IInputMethodManager.Stub.asInterface(b); } } long ident = Binder.clearCallingIdentity(); try { // Note: it is safe to call in to the input method manager // here because we are not holding our lock. if (mInputMethodManager != null) { mInputMethodManager.addClient(client, inputContext, mUid, mPid); } else { client.setUsingInputMethod(false); } client.asBinder().linkToDeath(this, 0); } catch (RemoteException e) { // The caller has died, so we can just forget about this. try { if (mInputMethodManager != null) { mInputMethodManager.removeClient(client); } } catch (RemoteException ee) { } } finally { Binder.restoreCallingIdentity(ident); } } @Override public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { try { return super.onTransact(code, data, reply, flags); } catch (RuntimeException e) { // Log all 'real' exceptions thrown to the caller if (!(e instanceof SecurityException)) { Slog.e(TAG, "Window Session Crash", e); } throw e; } } public void binderDied() { // Note: it is safe to call in to the input method manager // here because we are not holding our lock. try { if (mInputMethodManager != null) { mInputMethodManager.removeClient(mClient); } } catch (RemoteException e) { } synchronized(mWindowMap) { mClient.asBinder().unlinkToDeath(this, 0); mClientDead = true; killSessionLocked(); } } public int add(IWindow window, WindowManager.LayoutParams attrs, int viewVisibility, Rect outContentInsets, InputChannel outInputChannel) { return addWindow(this, window, attrs, viewVisibility, outContentInsets, outInputChannel); } public int addWithoutInputChannel(IWindow window, WindowManager.LayoutParams attrs, int viewVisibility, Rect outContentInsets) { return addWindow(this, window, attrs, viewVisibility, outContentInsets, null); } public void remove(IWindow window) { removeWindow(this, window); } public int relayout(IWindow window, WindowManager.LayoutParams attrs, int requestedWidth, int requestedHeight, int viewFlags, boolean insetsPending, Rect outFrame, Rect outContentInsets, Rect outVisibleInsets, Configuration outConfig, Surface outSurface) { //Log.d(TAG, ">>>>>> ENTERED relayout from " + Binder.getCallingPid()); int res = relayoutWindow(this, window, attrs, requestedWidth, requestedHeight, viewFlags, insetsPending, outFrame, outContentInsets, outVisibleInsets, outConfig, outSurface); //Log.d(TAG, "<<<<<< EXITING relayout to " + Binder.getCallingPid()); return res; } public void setTransparentRegion(IWindow window, Region region) { setTransparentRegionWindow(this, window, region); } public void setInsets(IWindow window, int touchableInsets, Rect contentInsets, Rect visibleInsets) { setInsetsWindow(this, window, touchableInsets, contentInsets, visibleInsets); } public void getDisplayFrame(IWindow window, Rect outDisplayFrame) { getWindowDisplayFrame(this, window, outDisplayFrame); } public void finishDrawing(IWindow window) { if (localLOGV) Slog.v( TAG, "IWindow finishDrawing called for " + window); finishDrawingWindow(this, window); } public void setInTouchMode(boolean mode) { synchronized(mWindowMap) { mInTouchMode = mode; } } public boolean getInTouchMode() { synchronized(mWindowMap) { return mInTouchMode; } } public boolean performHapticFeedback(IWindow window, int effectId, boolean always) { synchronized(mWindowMap) { long ident = Binder.clearCallingIdentity(); try { return mPolicy.performHapticFeedbackLw( windowForClientLocked(this, window, true), effectId, always); } finally { Binder.restoreCallingIdentity(ident); } } } public void setWallpaperPosition(IBinder window, float x, float y, float xStep, float yStep) { synchronized(mWindowMap) { long ident = Binder.clearCallingIdentity(); try { setWindowWallpaperPositionLocked( windowForClientLocked(this, window, true), x, y, xStep, yStep); } finally { Binder.restoreCallingIdentity(ident); } } } public void wallpaperOffsetsComplete(IBinder window) { WindowManagerService.this.wallpaperOffsetsComplete(window); } public Bundle sendWallpaperCommand(IBinder window, String action, int x, int y, int z, Bundle extras, boolean sync) { synchronized(mWindowMap) { long ident = Binder.clearCallingIdentity(); try { return sendWindowWallpaperCommandLocked( windowForClientLocked(this, window, true), action, x, y, z, extras, sync); } finally { Binder.restoreCallingIdentity(ident); } } } public void wallpaperCommandComplete(IBinder window, Bundle result) { WindowManagerService.this.wallpaperCommandComplete(window, result); } void windowAddedLocked() { if (mSurfaceSession == null) { if (localLOGV) Slog.v( TAG, "First window added to " + this + ", creating SurfaceSession"); mSurfaceSession = new SurfaceSession(); if (SHOW_TRANSACTIONS) Slog.i( TAG, " NEW SURFACE SESSION " + mSurfaceSession); mSessions.add(this); } mNumWindow++; } void windowRemovedLocked() { mNumWindow--; killSessionLocked(); } void killSessionLocked() { if (mNumWindow <= 0 && mClientDead) { mSessions.remove(this); if (mSurfaceSession != null) { if (localLOGV) Slog.v( TAG, "Last window removed from " + this + ", destroying " + mSurfaceSession); if (SHOW_TRANSACTIONS) Slog.i( TAG, " KILL SURFACE SESSION " + mSurfaceSession); try { mSurfaceSession.kill(); } catch (Exception e) { Slog.w(TAG, "Exception thrown when killing surface session " + mSurfaceSession + " in session " + this + ": " + e.toString()); } mSurfaceSession = null; } } } void dump(PrintWriter pw, String prefix) { pw.print(prefix); pw.print("mNumWindow="); pw.print(mNumWindow); pw.print(" mClientDead="); pw.print(mClientDead); pw.print(" mSurfaceSession="); pw.println(mSurfaceSession); } @Override public String toString() { return mStringName; } }