上海单位网站建设,nginx wordpress 主题,谷歌seo营销,注册公司费用多少钱1、WindowContainerTransaction是什么#xff1a;
windowContainerTransaction类的对象是用来存储对windowContainer的修改的一个集合#xff0c;windowContainer。因为应用侧是无法直接操作windowContainer的#xff0c;如果应用侧需要修改windowContainer的话#xff0c…1、WindowContainerTransaction是什么
windowContainerTransaction类的对象是用来存储对windowContainer的修改的一个集合windowContainer。因为应用侧是无法直接操作windowContainer的如果应用侧需要修改windowContainer的话需要通过系统侧对windowContainer进行修改这就涉及了信息的跨进程传输了。所以首先WindowContainerTransaction类应该是一个磕跨进程传输的类。看到定义 public final class WindowContainerTransaction implements Parcelable 也证实了这个猜测其实现了Parcelable接口。然后就是另一个问题应用通过系统侧修改WindowContainer的话必定会告诉他修改窗口的什么属性然后进去这个类找找代码 * Sets whether a container or its children should be hidden. When {code false}, the existing* visibility of the container applies, but when {code true} the container will be forced* to be hidden.*/
NonNull
public WindowContainerTransaction setHidden(NonNull WindowContainerToken container, boolean hidden) {Change chg getOrCreateChange(container.asBinder());chg.mHidden hidden;chg.mChangeMask | Change.CHANGE_HIDDEN;return this;
}这里可以看到一个设置窗口及其子窗口是否被隐藏的接口暂时不详细叙述这个方法的实现。这里可以看到修改这个hidden属性是通过一个Change类的对象实现的Change类是WindowContainerTransaction的内部类也是实现了Parcelable接口的。而且WindowContainerTransaction类内部也维护了一个包含Change类的Map private final ArrayMapIBinder, Change mChanges new ArrayMap(); 所以可以大概知道对窗口的修改应该是通过Change类的对象去描述的。
所以目前可以得知WindowContainerTransaction类的作用他的对象就是应用侧需要对窗口进行的修改的集合。而这个修改则是通过Change类的对象描述的。 这里通过一个例子来展示下WindowContainerTransaction类的使用例子引用自博客https://blog.csdn.net/ukynho/article/details/126747771
public boolean splitPrimaryTask() {......final WindowContainerTransaction wct new WindowContainerTransaction();// Clear out current windowing mode before reparenting to split task.wct.setWindowingMode(topRunningTask.token, WINDOWING_MODE_UNDEFINED);wct.reparent(topRunningTask.token, mSplits.mPrimary.token, true /* onTop */);mWindowManagerProxy.applySyncTransaction(wct);return true;
}由上述示例可见这个WindowContainerTransaction类的使用过程为1.创建一个WindowContainerTransaction对象2.通过该对象设置你需要修改的属性3.提交步骤2设置的修改。
2、如何通过WindowContainerTransaction修改窗口属性
前面已经讲到了WindowContainerTransaction中的setHidden方法那就继续分析这个方法public WindowContainerTransaction setHidden(NonNull WindowContainerToken container, boolean hidden) {Change chg getOrCreateChange(container.asBinder());chg.mHidden hidden;chg.mChangeMask | Change.CHANGE_HIDDEN;return this;
}1、看参数列表
参数列表第一个是一个WindowContainerToken对象看一下定义这个类是什么含义
public final class WindowContainerToken implements Parcelable {private final IWindowContainerToken mRealToken;/** hide */public WindowContainerToken(IWindowContainerToken realToken) {mRealToken realToken;}private WindowContainerToken(Parcel in) {mRealToken IWindowContainerToken.Stub.asInterface(in.readStrongBinder());}/** hide */public IBinder asBinder() {return mRealToken.asBinder();}…………………………………
}从代码上看这个类也是实现了Parcelable然后主要是包装了一个IWindowContainerToken类型的对象。因为系统侧的WMS里要管理所有的WindowContainer那么WMS中该如何区分每一个WindowContainer呢那就得用唯一的身份标识即这个IWindowContainerToken通过这个TokenWMS可以区分不同的WindowContainer可以简单理解成我们每个人其实在国家的户籍管理的制度里就是用一个身份证号进行辨识的在人口管理的系统中我们是以身份证号进行区分的所以身份证号就是这个Token。而WMS也可以通过WindowContainerToken的asBinder方法访问到对应WindowContainer的方法。 而我们怎么获取到这个WindowContainerToken方法呢从示例代码中可见 wct.setWindowingMode(topRunningTask.token, WINDOWING_MODE_UNDEFINED); 可以通过TaskInfo类的token属性获取。看到TaskInfo类的token属性正是WindowContainerToken类型的对象。那问题又来了我们的这个token属性是在什么时候进行的赋值操作的呢 这里得找到Task.java中的fillTaskInfo()方法了这里可见info.token的赋值
void fillTaskInfo(TaskInfo info, boolean stripExtras, Nullable TaskDisplayArea tda) {
………………………………………………………………info.token mRemoteToken.toWindowContainerToken();
………………………………………………………………}这里再提一个小小的疑问mRemoteToken又是什么看到Task类中没有定义于是找到其父类中最后在WindowContainer类中发现如下定义 首先他实现了一个aidl接口的Stub类所以其实RemoteToken就是一个binder的server端的抽象类Stub的子类的实现 。他包含了对WindowContainer的引用和WindowContainerToken。
static class RemoteToken extends IWindowContainerToken.Stub {final WeakReferenceWindowContainer mWeakRef;private WindowContainerToken mWindowContainerToken;RemoteToken(WindowContainer container) {mWeakRef new WeakReference(container);}NullableWindowContainer getContainer() {return mWeakRef.get();}static RemoteToken fromBinder(IBinder binder) {return (RemoteToken) binder;}WindowContainerToken toWindowContainerToken() {if (mWindowContainerToken null) {mWindowContainerToken new WindowContainerToken(this);}return mWindowContainerToken;}Overridepublic String toString() {StringBuilder sb new StringBuilder(128);sb.append(RemoteToken{);sb.append(Integer.toHexString(System.identityHashCode(this)));sb.append( );sb.append(mWeakRef.get());sb.append(});return sb.toString();}
}而且在WindowContainerToken中的mRealToken其实就是IWindowContainerToken的对象也就是说mRealToken其实就是一个RemoteToken类型的对象他才是能够通过弱引用真正的指向WindowContainer同时还包含WindowContainerToken属性。这里再多说一个点就是WindowContainerToken只有Task和DisplayArea才会有。
然后第二个参数就是需要设置的属性了就不再多说
2、setHidden方法的实现
public WindowContainerTransaction setHidden(NonNull WindowContainerToken container, boolean hidden) {Change chg getOrCreateChange(container.asBinder());chg.mHidden hidden;chg.mChangeMask | Change.CHANGE_HIDDEN;return this;
}该方法第一步定义一个Change对象chg定义后通过getOrCreateChange方法对chg进行赋值。继续查看该方法的实现。
private Change getOrCreateChange(IBinder token) {Change out mChanges.get(token);if (out null) {out new Change();mChanges.put(token, out);}return out;
}定义一个Change类型的对象out然后在mChanges中去get一个Change看下mChanges的定义发现这是一个ArrayMap。Key是IBinder这个IBinder的对象就是一个WindowContainerToken的对象对应唯一的WindowContainervalue是Change。 private final ArrayMapIBinder, Change mChanges new ArrayMap(); 那就知道了肯定有有地方会把这个键值对IBinder和Change组成的键值对放进mChanges中。这里如果是刚初始化的WindowContainerTransaction对象mChanges肯定是空的所以out null则会将token和out放进mChanges并返回out。注意这里out只是一个默认的Change方法构造出来的对象。
public static class Change implements Parcelable {public static final int CHANGE_FOCUSABLE 1;public static final int CHANGE_BOUNDS_TRANSACTION 1 1;public static final int CHANGE_PIP_CALLBACK 1 2;public static final int CHANGE_HIDDEN 1 3;public static final int CHANGE_BOUNDS_TRANSACTION_RECT 1 4;public static final int CHANGE_IGNORE_ORIENTATION_REQUEST 1 5;public static final int CHANGE_FORCE_NO_PIP 1 6;public static final int CHANGE_FORCE_TRANSLUCENT 1 7;public static final int CHANGE_DRAG_RESIZING 1 8;private final Configuration mConfiguration new Configuration();private boolean mFocusable true;private boolean mHidden false;private boolean mIgnoreOrientationRequest false;private boolean mForceTranslucent false;private boolean mDragResizing false;private int mChangeMask 0;private ActivityInfo.Config int mConfigSetMask 0;private WindowConfiguration.WindowConfig int mWindowSetMask 0;private Rect mPinnedBounds null;private SurfaceControl.Transaction mBoundsChangeTransaction null;private Rect mBoundsChangeSurfaceBounds null;private int mActivityWindowingMode -1;private int mWindowingMode -1;public Change() {}
…………………………………………………………………………………………………
}所以Out的属性都是默认值接下来就是对这个Change进行赋值了我们看的是setHidden方法所以需要修改Hidden相关的属性。首先是修改chg.mHidden属性然后修改chg.mChangeMask。 mHidden属性就可以简单的认为是否需要隐藏下面的mChangeMask就是一个标志位通过这个属性能得知提交的WindowContainerTransaction进行了哪些属性的修改。 通过Change的初始值可知mChangeMask 0是int类型。CHANGE_HIDDEN 13; 通过将二者进行异或运算就能将标志着HIDDEN属性变化的第三位设置为1.
于是在系统侧应用WindowContainerTransaction的时候可以看到这里就会通过mChangeMask属性与标志位的结果进行判断后再对修改进行应用。
private int applyTaskChanges(Task tr, WindowContainerTransaction.Change c) {int effects applyChanges(tr, c, null /* errorCallbackToken */);final SurfaceControl.Transaction t c.getBoundsChangeTransaction();if ((c.getChangeMask() WindowContainerTransaction.Change.CHANGE_HIDDEN) ! 0) {if (tr.setForceHidden(FLAG_FORCE_HIDDEN_FOR_TASK_ORG, c.getHidden())) {effects TRANSACT_EFFECTS_LIFECYCLE;}}if ((c.getChangeMask() WindowContainerTransaction.Change.CHANGE_FORCE_TRANSLUCENT) ! 0) {tr.setForceTranslucent(c.getForceTranslucent());effects TRANSACT_EFFECTS_LIFECYCLE;}
…………………………………………………………………………………………
}3reparent方法的实现
public WindowContainerTransaction reparent(NonNull WindowContainerToken child,Nullable WindowContainerToken parent, boolean onTop) {mHierarchyOps.add(HierarchyOp.createForReparent(child.asBinder(),parent null ? null : parent.asBinder(),onTop));return this;
}这里不是通过Change保存reparent操作而是通过mHierarchyOps来保存修改的。看下定义mHierarchyOps 是一个ArrayList类型的对象。里面存储的是HierarchyOp类型的变量。
private final ArrayListHierarchyOp mHierarchyOps new ArrayList();然后再看到HierarchyOp的构造方法这里container就是需要重新设置parent的WindowContainer然后reparent就是新的parenttoTop代表reparent操作后是否需要将子WindowContainer移动到父
WindowContainer的Top。
public static HierarchyOp createForReparent(NonNull IBinder container, Nullable IBinder reparent, boolean toTop) {return new HierarchyOp.Builder(HIERARCHY_OP_TYPE_REPARENT).setContainer(container).setReparentContainer(reparent).setToTop(toTop).build();
}