安卓窗口相关&动画

android动画 开发者选项中动画时长原理分析

android动画 开发者选项中动画时长原理分析(Android M)_wangyang55555的博客-优快云博客_android 动画程序时长

开发者选项中提供了“窗口动画缩放”、“过渡动画缩放”、“动画程序时长缩放”三个可供调整动画时长的菜单项。单从名字上很难分辨出这三个选项作用目标是啥,我们先把系统语言调整为English,对应于“Window animation scale”、"Transition animation scale"、"Animator duration scale",从名字可以看出这三个选项是一个缩放因子,是动画时长duration的乘积因子(new_Duration = old_duration*scale),只是作用的目标各不相同。

    我们知道Android系统根据动画目标可划分为Window动画、Activity动画、View动画,很明显上面那三个缩放因子就对应于此。

    "Window animation scale",作用于非Activity窗口。比如,Dialog、toast、自定义浮窗、输入法等窗口都是该选项的作用目标

    "Transition animation scale",作用于Activity窗口。Activity窗口是该选项作用目标

    "Animator duration scale",作用于View。比如View属性动画、水波纹背景动画等

ViewRootImpl 里面建立了两个binder 通讯,client 通过IWindowSession 跟 WMS 通讯;

WMS 通过IWindow 响应client请求;

 

Activity展示视图元素通过window来实现,window可以理解为一个容器,盛放着一个个的view,用来执行具体的展示工作

ViewRootImpl 是wms 跟DectorView 纽带

为了实现Activity 跟View 的解耦,Activity 将视图的全部工作交给Weindow 来处理


WindowManagerGlobal中实现了ViewManager中addView、removeView、updateViewLayout这个三个view相关的方法
WindowManager是一个接口类,对应的实现类是WindowManagerImpl,该实现类中持有mGlobal对象,这个mGlobal对象就是WindowManagerGlobal,具体的实现交给了WindowManagerGlobal,WindowManagerImpl相当于WindowManagerGlobal的代理类
WindowManagerPolicy提供所有和UI有关的接口,PhoneWindowManager实现了该接口。需要注意的是PhoneWindowManager并不是WindowManager的子类。WindowManagerService中持有mPolicy对象,这个mPolicy就是PhoneWindowManager
 

Window 对象

每一个Activity 中有一个Window 类型成员mWindow

class Activity {

private Window mWindow;

private WindowManager mWindowManager;

}

/**
 * Abstract base class for a top-level window look and behavior policy.  An
 * instance of this class should be used as the top-level view added to the
 * window manager. It provides standard UI policies such as a background, title
 * area, default key processing, etc.
 *
 * <p>The only existing implementation of this abstract class is
 * android.view.PhoneWindow, which you should instantiate when needing a
 * Window.
 */
public abstract class Window {

...

}

Windwo 是一个抽象类

Window 对象在应用看来是一个窗口,是一快矩形区域。在WMS角度,不关心各个view关系,最终呈现的是一个window图像。

public class PhoneWindow extends Window implements MenuBuilder.Callback {

}

android phone special widow

/**
 * The interface that apps use to talk to the window manager.
 * <p>
 * Use <code>Context.getSystemService(Context.WINDOW_SERVICE)</code> to get one of these.
 * </p><p>
 * Each window manager instance is bound to a particular {@link Display}.
 * To obtain a {@link WindowManager} for a different display, use
 * {@link Context#createDisplayContext} to obtain a {@link Context} for that
 * display, then use <code>Context.getSystemService(Context.WINDOW_SERVICE)</code>
 * to get the WindowManager.
 * </p><p>
 * The simplest way to show a window on another display is to create a
 * {@link Presentation}.  The presentation will automatically obtain a
 * {@link WindowManager} and {@link Context} for that display.
 * </p>
 *
 * @see android.content.Context#getSystemService
 * @see android.content.Context#WINDOW_SERVICE
 */
public interface WindowManager extends ViewManager {

}

Activity 中attach方法

final void attach(Context context, ActivityThread aThread,
        Instrumentation instr, IBinder token, int ident,
        Application application, Intent intent, ActivityInfo info,
        CharSequence title, Activity parent, String id,
        NonConfigurationInstances lastNonConfigurationInstances,
        Configuration config, String referrer, IVoiceInteractor voiceInteractor,
        Window window) {
    attachBaseContext(context);

    mFragments.attachHost(null /*parent*/);

    mWindow = new PhoneWindow(this, window);
 
 
 
mWindow.setWindowManager( (WindowManager)context.getSystemService(Context.WINDOW_SERVICE), 
mToken, mComponent.flattenToString(), (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
 if (mParent != null) { 
mWindow.setContainer(mParent.getWindow()); 
}
 mWindowManager = mWindow.getWindowManager(); 
mCurrentConfig = config;
 
}

frameworks\base\core\java\android\app\ActivityThread.java

调用Activity 的attach()方法初始化mWindow。

这里实际是是创建PhoneWindow,

frameworks\base\core\java\android\view\Window.java

frameworks\base\core\java\com\android\internal\policy\PhoneWindow.java 实现了Window

frameworks\base\core\java\android\view\WindowManager.java

frameworks\base\core\java\android\view\WindowManagerImpl.java

public final class WindowManagerImpl implements WindowManager {
    private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();

}

frameworks\base\core\java\android\app\SystemServiceRegistry.java

registerService(Context.WINDOW_SERVICE, WindowManager.class,
        new CachedServiceFetcher<WindowManager>() {
    @Override
    public WindowManager createService(ContextImpl ctx) {
        return new WindowManagerImpl(ctx);
    }});

frameworks\base\services\java\com\android\server\SystemServer.java

WindowManagerService wm = null;
wm = WindowManagerService.main(context, inputManager,
        mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
        !mFirstBoot, mOnlyCore);
ServiceManager.addService(Context.WINDOW_SERVICE, wm);

frameworks\base\services\core\java\com\android\server\wm\WindowManagerService.java

public static WindowManagerService main(final Context context,
        final InputManagerService im,
        final boolean haveInputMethods, final boolean showBootMsgs,
        final boolean onlyCore) {
    final WindowManagerService[] holder = new WindowManagerService[1];
    DisplayThread.getHandler().runWithScissors(new Runnable() {
        @Override
        public void run() {
            holder[0] = new WindowManagerService(context, im,
                    haveInputMethods, showBootMsgs, onlyCore);
        }
    }, 0);
    return holder[0];
}

public WindowManagerService(。。。){

...

LocalServices.addService(WindowManagerInternal.class, new LocalService());
initPolicy();
...

}

private void initPolicy() {
    UiThread.getHandler().runWithScissors(new Runnable() {
        @Override
        public void run() {
            WindowManagerPolicyThread.set(Thread.currentThread(), Looper.myLooper());
            /// M: ANR mechanism for Message History/Queue for system server @{
            if ("eng".equals(Build.TYPE)) {
                Looper.myLooper().setMessageLogging(
                        ANRAppManager.getDefault(
                                new ANRAppFrameworks())
                                .newMessageLogger(false, Thread.currentThread().getName()));
            }
            /// M: ANR mechanism for Message History/Queue for system server @}
            mPolicy.init(mContext, WindowManagerService.this, WindowManagerService.this);
        }
    }, 0);
}

frameworks\base\core\java\android\view\WindowManagerPolicy.java

/**
 * Perform initialization of the policy.
 *
 * @param context The system context we are running in.
 */
public void init(Context context, IWindowManager windowManager,
        WindowManagerFuncs windowManagerFuncs);

frameworks\base\services\core\java\com\android\server\policy\PhoneWindowManager.java

/** {@inheritDoc} */
@Override
public void init(Context context, IWindowManager windowManager,
        WindowManagerFuncs windowManagerFuncs) {
    mContext = context;
    mWindowManager = windowManager;
    mWindowManagerFuncs = windowManagerFuncs;

}

frameworks\base\core\java\android\view\WindowManagerPolicy.java

public interface WindowManagerPolicy {

}

frameworks\base\core\java\android\view\IWindowManager.aidl

frameworks\base\gen\android\view\IWindowManager.java

frameworks\base\services\core\java\com\android\server\wm\WindowManagerService.java

public class WindowManagerService extends IWindowManager.Stub
        implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
 
 
final WindowManagerPolicy mPolicy = new PhoneWindowManager();

}

 
frameworks\base\services\core\java\com\android\server\policy\PhoneWindowManager.java
 
/**  * WindowManagerPolicy implementation for the Android phone UI. This  
* introduces a new method suffix, Lp, for an internal lock of the  
* PhoneWindowManager. This is used to protect some internal state, and  
* can be acquired with either the Lw and Li lock held, so has the restrictions 
 * of both of those when held.  
*/ 
public class PhoneWindowManager implements WindowManagerPolicy {
 
 
}

 



Android 应用程序建立与WMS服务之间的通信过程_hc-斌斌的博客-优快云博客_android wms

/** * Set the window manager for use by this Window to, for example, 
* display panels. This is <em>not</em> used for displaying the 
* Window itself -- that must be done by the client. 
* * @param wm The window manager for adding new windows.
 */ 
public void setWindowManager(WindowManager wm, IBinder appToken, String appName, boolean hardwareAccelerated) {
 mAppToken = appToken; 
mAppName = appName; 
mHardwareAccelerated = hardwareAccelerated || SystemProperties.getBoolean(PROPERTY_HARDWARE_UI, false); 
   if (wm == null) { 
    wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE); 
   }
 mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this); 
}
 

创建WindowManagerImpl对象,

 
WindowManagerImpl 中成员 
private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
 
frameworks\base\core\java\android\view\WindowManagerGlobal.java
 
 
* Provides low-level communication with the system window manager for
* operations that are not associated with any particular context. 
* * This class is only used internally to implement global functions where 
* the caller already knows the display and relevant compatibility information 
* for the operation. For most purposes, you should use {@link WindowManager} instead 
* since it is bound to a context.

public final class WindowManagerGlobal {

private static WindowManagerGlobal sDefaultWindowManager;
private static IWindowManager sWindowManagerService;
private static IWindowSession sWindowSession;
 
 
public static WindowManagerGlobal getInstance() {
 synchronized (WindowManagerGlobal.class) {
   if (sDefaultWindowManager == null) {
   sDefaultWindowManager = new WindowManagerGlobal(); 
   } 
  return sDefaultWindowManager; 
   }
 } 

public static IWindowManager getWindowManagerService() {
 synchronized (WindowManagerGlobal.class) { 
  if (sWindowManagerService == null) { 
  sWindowManagerService = IWindowManager.Stub.asInterface( 
  ServiceManager.getService("window"));
  try { 
    sWindowManagerService = getWindowManagerService(); 
    ValueAnimator.setDurationScale(sWindowManagerService.getCurrentAnimatorScale());
   } catch (RemoteException e) { 
    throw e.rethrowFromSystemServer(); 
   } 
  } 
   return sWindowManagerService; 
    } 
  } 
public static IWindowSession getWindowSession() { 
  synchronized (WindowManagerGlobal.class) { 
  if (sWindowSession == null) { 
  try { InputMethodManager imm = InputMethodManager.getInstance(); 
  IWindowManager windowManager = getWindowManagerService();
  sWindowSession = windowManager.openSession( new IWindowSessionCallback.Stub() { 
  @Override  public void onAnimatorScaleChanged(float scale) { 
  ValueAnimator.setDurationScale(scale); 
    } 
    }, imm.getClient(), imm.getInputContext());
    } catch (RemoteException e) {
    throw e.rethrowFromSystemServer(); 
   } 
  } return sWindowSession; 
 }
}
 
}
 
 
 
 
WindowManagerImpl是通过调用WindowManagerGlobal方法实现的
 
 
 

应用是通过WindowManagerGlobal与WMS通信的,这里通信是通过双向Binder实现的。

frameworks\base\core\java\android\view\IWindowManager.aidl

frameworks\base\gen\android\view\IWindowManager.java

frameworks\base\services\core\java\com\android\server\wm\WindowManagerService.java

public class WindowManagerService extends IWindowManager.Stub
        implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
 
 
final WindowManagerPolicy mPolicy = new PhoneWindowManager();

}

 
frameworks\base\services\core\java\com\android\server\policy\PhoneWindowManager.java
 
 
/**  * WindowManagerPolicy implementation for the Android phone UI. This 
 * introduces a new method suffix, Lp, for an internal lock of the  
* PhoneWindowManager. This is used to protect some internal state, and  
* can be acquired with either the Lw and Li lock held, so has the restrictions 
 * of both of those when held.  
*/ 
public class PhoneWindowManager implements WindowManagerPolicy {
 
}

frameworks\base\core\java\android\view\WindowManagerPolicy.java

public interface WindowManagerPolicy {

}

建立应用与WMS直接的联系

frameworks\base\core\java\android\view\WindowManagerGlobal.java

与顶层View 相关成员变量:

private final ArrayList<View> mViews = new ArrayList<View>();
private final ArrayList<ViewRootImpl> mRoots = new ArrayList<ViewRootImpl>();
private final ArrayList<WindowManager.LayoutParams> mParams =
        new ArrayList<WindowManager.LayoutParams>();

frameworks\base\core\java\android\view\ViewRootImpl.java

public final class ViewRootImpl implements ViewParent,
        View.AttachInfo.Callbacks, ThreadedRenderer.HardwareDrawCallbacks {

final ArrayList<WindowCallbacks> mWindowCallbacks = new ArrayList<>();
final Context mContext;
final IWindowSession mWindowSession;
@NonNull Display mDisplay;
final DisplayManager mDisplayManager;
final String mBasePackageName;

final int[] mTmpLocation = new int[2];

final TypedValue mTmpValue = new TypedValue();

final Thread mThread;

final WindowLeaked mLocation;

final WindowManager.LayoutParams mWindowAttributes = new WindowManager.LayoutParams();

final W mWindow;

}

与WMS相关变量

final IWindowSession mWindowSession;
final W mWindow;
final View.AttachInfo mAttachInfo;

mWindowSession = WindowManagerGlobal.getWindowSession();
mWindow = new W(this);
mAttachInfo = new View.AttachInfo(mWindowSession, mWindow, display, this, mHandler, this);

* API back to a client window that the Window Manager uses to inform it of
* interesting things happening.

frameworks\base\core\java\android\view\IWindow.aidl

frameworks\base\gen\android\view\IWindow.java

//通知客户端,如失去或者获得焦点

static class W extends IWindow.Stub {
    private final WeakReference<ViewRootImpl> mViewAncestor;
    private final IWindowSession mWindowSession;

    W(ViewRootImpl viewAncestor) {
        mViewAncestor = new WeakReference<ViewRootImpl>(viewAncestor);
        mWindowSession = viewAncestor.mWindowSession;
    }

}

ViewRootImpl 内部类W

System private per-application interface to the window manager.

frameworks\base\core\java\android\view\IWindowSession.aidl

/**
 * This class represents an active client session.  There is generally one
 * Session object per process that is interacting with the window manager.
 */
final class Session extends IWindowSession.Stub

{

}

mWindowSession = WindowManagerGlobal.getWindowSession();

public static IWindowSession getWindowSession() {
    synchronized (WindowManagerGlobal.class) {
        if (sWindowSession == null) {
            try {
                InputMethodManager imm = InputMethodManager.getInstance();
                IWindowManager windowManager = getWindowManagerService();
                sWindowSession = windowManager.openSession(
                        new IWindowSessionCallback.Stub() {
                            @Override
                            public void onAnimatorScaleChanged(float scale) {
                                ValueAnimator.setDurationScale(scale);
                            }
                        },
                        imm.getClient(), imm.getInputContext());
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
        return sWindowSession;
    }
}

这里WindowSession 是WMS中Binder对象的引用

一个用户进程中所有的ViewRootImpl对象中的mWindwoSession 应用对象是相同的。它就是建立应用中一条通往WMS的Binder通道。

这里WindowManagerGlobal.getWindowSession()通过windowManager.openSession()建立了应用到WMS的Binder通道,最终通过

sWindowSession 转到到调用WMS
 
 
建立WMS到应用的联系
frameworks\base\services\core\java\com\android\server\wm\WindowState.java
 
 
final class WindowState implements WindowManagerPolicy.WindowState {
 
final WindowManagerService mService; 
final WindowManagerPolicy mPolicy; 
final Context mContext; 
final Session mSession;
 final IWindow mClient;
}
 
 
IWindow mClient 是客户进程中的Binder对象W的对象引用,用于WMS通向应用的Binder。
Session mSession 是WMS中为客户进程创建的Binder服务对象。
 
Session mSession 就是将用户进程的调用转换成调用WMS的接口。
 
 
frameworks\base\core\java\com\android\internal\policy\DecorView.java 
 
public class DecorView extends FrameLayout implements RootViewSurfaceTaker, WindowCallbacks {

}

 
 
 
public class WindowManagerService extends IWindowManager.Stub 
implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {

 

final WindowManagerPolicy mPolicy = new PhoneWindowManager(); 
final IActivityManager mActivityManager; 
final ActivityManagerInternal mAmInternal;
final AppOpsManager mAppOps;
final DisplaySettings mDisplaySettings;
 
 
/**  * All currently active sessions with clients.  */
 final ArraySet<Session> mSessions = new ArraySet<>(); 
/**  * Mapping from an IWindow IBinder to the server's Window object.  
* This is also used as the lock for all of our state.  
* NOTE: Never call into methods that lock ActivityManagerService while holding this object.  */ 
final HashMap<IBinder, WindowState> mWindowMap = new HashMap<>(); 
/**  * Mapping from a token IBinder to a WindowToken object.  
*/ final HashMap<IBinder, WindowToken> mTokenMap = new HashMap<>(); 
/**  * List of window tokens that have finished starting their application, 
 * and now need to have the policy remove their windows.  
*/
 final ArrayList<AppWindowToken> mFinishedStarting = new ArrayList<>(); 
/**  * List of window tokens that have finished drawing their own windows and  
* no longer need to show any saved surfaces. Windows that's still showing  
* saved surfaces will be cleaned up after next animation pass.  
*/ 
final ArrayList<AppWindowToken> mFinishedEarlyAnim = new ArrayList<>();

 

}

 

final ArraySet<Session> mSessions = new ArraySet<>();

应用调用WMS 的Binder 服务

 
final HashMap<IBinder, WindowState> mWindowMap = new HashMap<>();

WMS调用应用的Binder接口与应用调用WMS 的Binder 服务 信息,代表一个窗口

 
 
 
 
/**  * Container of a set of related windows in the window manager. Often this  
* is an AppWindowToken, which is the handle for an Activity that it uses  
* to display windows. For nested windows, there is a WindowToken created for  
* the parent window to manage its children.  
*/
 class WindowToken {
 // The window manager!  
final WindowManagerService service; 
// The actual token.  
final IBinder token; 
// The type of window this token is for, as per WindowManager.LayoutParams.  
final int windowType; 
// Set if this token was explicitly added by a client, so should  
// not be removed when all windows are removed.  
final boolean explicit; 
// For printing.  String stringName; 
// If this is an AppWindowToken, this is non-null.  AppWindowToken appWindowToken; 
// All of the windows associated with this token.  
final WindowList windows = new WindowList(); 

}

WindowToken 表示一组窗口对象,windowType 表示窗口类型。

final boolean explicit;为false 表示这个token 是在WMS中创建的,为true表示其他模块通过调用
addAppToken()或addWindowToken()方式显示创建的
 
final WindowList windows = new WindowList();

表示WindowState对象的列表,所以具有相同WindowToken 的窗口都在这里list中。一般窗口与依附于它的子窗口拥有相同的WindowToken

 
frameworks\base\services\core\java\com\android\server\wm\AppWindowToken.java
 
 
/** * Version of WindowToken that is specifically for a particular application (or
 * really activity) that is displaying windows.
 */ 
class AppWindowToken extends WindowToken { 
private static final String TAG = TAG_WITH_CLASS_NAME ? "AppWindowToken" : TAG_WM; 
// Non-null only for application tokens. final IApplicationToken appToken; 
// All of the windows and child windows that are included in this 
// application token. Note this list is NOT sorted! 
final WindowList allAppWindows = new WindowList();
 @NonNull final AppWindowAnimator mAppAnimator; 
final boolean voiceInteraction; 
Task mTask; 
boolean appFullscreen; 
int requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 
boolean layoutConfigChanges;
boolean showForAllUsers; 
int targetSdk; 

}

 
AppWindwoToken是比较特殊的WindowToken,代表应用窗口,主要是从Activity中创建的顶层窗口。
一个WindowToken对象的成员appWindowToken如果
为Null,那它就不是AppWindowToken对象    
 
  final IApplicationToken appToken;是在AMS中创建的,代表一个应用。
 final WindowList allAppWindows = new WindowList();拥有相同AppToken的应用窗口及其子窗口。
 AddAppToken()用于向WMS注册。


这两个类中的dump()可以dump出窗口信息,如下命令  dumpsys window | egrep "window|app=true"


frameworks\base\core\java\android\view\WindowManager.java
public interface WindowManager extends ViewManager {
{
   public static class LayoutParams extends ViewGroup.LayoutParams implements Parcelable {
    //窗口的类型定义在这里
   //系统窗口、应用窗口、子窗口
   }
}                        
 
 
 
 
 
窗口的排列             
frameworks\base\services\core\java\com\android\server\wm\WindowState.java        
 
 
if ((mAttrs.type >= FIRST_SUB_WINDOW && mAttrs.type <= LAST_SUB_WINDOW)) { 
// The multiplier here is to reserve space for multiple  
// windows in the same type layer.  
mBaseLayer = mPolicy.windowTypeToLayerLw( attachedWindow.mAttrs.type) * WindowManagerService.TYPE_LAYER_MULTIPLIER  + WindowManagerService.TYPE_LAYER_OFFSET; mSubLayer = mPolicy.subWindowTypeToLayerLw(a.type); mAttachedWindow = attachedWindow;
 if (DEBUG_ADD_REMOVE)
 Slog.v(TAG, "Adding " + this + " to " + mAttachedWindow); 
} else { 
// The multiplier here is to reserve space for multiple  
// windows in the same type layer.  
mBaseLayer = mPolicy.windowTypeToLayerLw(a.type) * WindowManagerService.TYPE_LAYER_MULTIPLIER  + WindowManagerService.TYPE_LAYER_OFFSET; mSubLayer = 0; mAttachedWindow = null;
 } 
 
这里根据窗口的类型返回一个技术值,这个值再 * TYPE_LAYER_MULTIPLIER,
这样同一类型窗口保留了10000(TYPE_LAYER_MULTIPLIER)个位置
 
 
mSubLayer 只有子窗口才起作用,是指在同一类型中某个父窗口添加添加子窗口时,
相对父窗口的位置,-2 ~2 之间,小于0则覆盖父窗口,
这里所有的窗口都排序好了。
 
 
final void assignLayersLocked(WindowList windows) { 
if (DEBUG_LAYERS)
 Slog.v(TAG_WM, "Assigning layers based on windows=" + windows, new RuntimeException("here").fillInStackTrace());
 clear();
 int curBaseLayer = 0; 
int curLayer = 0; 
boolean anyLayerChanged = false; 
for (int i = 0, windowCount = windows.size(); i < windowCount; i++) { 
final WindowState w = windows.get(i); 
boolean layerChanged = false;
int oldLayer = w.mLayer; 
if (w.mBaseLayer == curBaseLayer || w.mIsImWindow || (i > 0 && w.mIsWallpaper)) { 
curLayer += WINDOW_LAYER_MULTIPLIER; 
} else { 
curBaseLayer = curLayer = w.mBaseLayer; 
} 
assignAnimLayer(w, curLayer); 

}

 
private void assignAnimLayer(WindowState w, int layer) { 
w.mLayer = layer; 
w.mWinAnimator.mAnimLayer = w.mLayer + w.getAnimLayerAdjustment() + getSpecialWindowAnimLayerAdjustment(w); 
if (w.mAppToken != null && w.mAppToken.mAppAnimator.thumbnailForceAboveLayer > 0  && w.mWinAnimator.mAnimLayer > w.mAppToken.mAppAnimator.thumbnailForceAboveLayer) { w.mAppToken.mAppAnimator.thumbnailForceAboveLayer = w.mWinAnimator.mAnimLayer; 
} 
} 

对已经排序好的窗口,再遍历每一种类型的窗口,对每一种类型的窗口重新排序,
其排序方法是在之前的序号上加5(WINDOW_LAYER_MULTIPLIER)

从而预留5个位置方便插入新的窗口,并将从新排序的索引赋值给到 mLayer.
 
 
WMS中窗口动画
 
 
 

WindowStateAnimator.java

当前正在显示的动画有两种类型,一种的窗口切换动画,一种是Activity切换动画。

这里使用了mLocalAnimating和mHasLocalTransformation分别表示窗口动画的状态。

// Currently running animation.
boolean mAnimating;   //表示是否正在显示动画
boolean mLocalAnimating; //表示窗口动画是否初始化 
Animation mAnimation;    //窗口动画对象
boolean mAnimationIsEntrance;  //
boolean mHasTransformation;    //当前mTransformation是否可用
boolean mHasLocalTransformation;  //
final Transformation mTransformation = new Transformation();
boolean mWasAnimating;      // Were we animating going into the most recent animation step?
 
 
使用mLocalAnimating; 、mHasLocalTransformation; 表示窗口状态
 
 
 
 
// This must be called while inside a transaction. Returns true if 
// there is more animation to run.
 boolean stepAnimationLocked(long currentTime) { 
// Save the animation state as it was before this step so WindowManagerService can tell if 
 // we just started or just stopped animating by comparing mWasAnimating with 
  isAnimationSet().  
  mWasAnimating = mAnimating; 
  final DisplayContent displayContent = mWin.getDisplayContent(); 
  if (displayContent != null && mService.okToDisplay()) { 
  // We will run animations as long as the display isn't frozen.   
    if (mWin.isDrawnLw() && mAnimation != null) { 
    //窗口准备好而且窗口动画非空 mHasTransformation = true; 
    //动画可用 mHasLocalTransformation = true; 
    //窗口动画 
       if (!mLocalAnimating) { 
       //窗口动画没有初始化 
         if (DEBUG_ANIM) Slog.v( TAG, "Starting animation in " + this + " @ " + currentTime + ": ww=" + mWin.mFrame.width() + " wh=" + mWin.mFrame.height() + " dx=" + mAnimDx + " dy=" + mAnimDy + " scale=" + mService.getWindowAnimationScaleLocked()); 
         final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 
         if (mAnimateMove) { 
           mAnimateMove = false; 
           mAnimation.initialize(mWin.mFrame.width(), mWin.mFrame.height(), mAnimDx, 
 mAnimDy); 
         } else { 
           mAnimation.initialize(mWin.mFrame.width(), mWin.mFrame.height(), 
       displayInfo.appWidth, displayInfo.appHeight); 
} 
        mAnimDx = displayInfo.appWidth; 
        mAnimDy = displayInfo.appHeight; 
       mAnimation.setStartTime(mAnimationStartTime != -1  ? mAnimationStartTime  : 
       currentTime); mLocalAnimating = true; 
       //窗口动画播放
      mAnimating = true; 
    //动画播放中 
} 
   if ((mAnimation != null) && mLocalAnimating) { 
   //窗口动画非空且窗口动画播放中 
   mLastAnimationTime = currentTime; 
   if (stepAnimation(currentTime)) { 
    //窗口动画是否结束 return true; //没结束返回true 
   } 
 } 
 if (DEBUG_ANIM) 
   Slog.v( //没返回说明播放结束了 TAG, "Finished animation in " + this + " @ " + 
   currentTime); //WindowManagerService.this.dump();  
} 
mHasLocalTransformation = false; //取消窗口动画标识
    //mAnimationIsEntrance记录动画类型,是退出还是进入动画。applyAnimationLocked()函数中会更新这个变量。
        if ((!mLocalAnimating || mAnimationIsEntrance) && mAppAnimator != null    //窗口动画结束了或者没有设置窗口动画
                && mAppAnimator.animation != null) {                               //activity 设置了动画
            // When our app token is animating, we kind-of pretend like
            // we are as well.  Note the mLocalAnimating mAnimationIsEntrance
            // part of this check means that we will only do this if
            // our window is not currently exiting, or it is not
            // locally animating itself.  The idea being that one that
            // is exiting and doing a local animation should be removed
            // once that animation is done.
            mAnimating = true;                                                     //动画播放
            mHasTransformation = true;                                            //动画可用
            mTransformation.clear();                                             
            return false;
        } else if (mHasTransformation) {                                         
            // Little trick to get through the path below to act like
            // we have finished an animation.
            mAnimating = true;
        } else if (isAnimationSet()) {    //尽量让动画完成显示,即使没有可显示的动画,多刷新几次不会有副作用,但如果少画了一次,屏幕上就可能留下不正确画面了
            mAnimating = true;
        }
    } else if (mAnimation != null) {
        // If the display is frozen, and there is a pending animation,
        // clear it and make sure we run the cleanup code.
        mAnimating = true;
    }

    if (!mAnimating && !mLocalAnimating) {
        return false;
    }

    // Done animating, clean up.
    /// M: Add more log at WMS
    Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER
            | Trace.TRACE_TAG_PERF, "win animation done");
    if (DEBUG_ANIM) Slog.v(
        TAG, "Animation done in " + this + ": exiting=" + mWin.mAnimatingExit
        + ", reportedVisible="
        + (mWin.mAppToken != null ? mWin.mAppToken.reportedVisible : false));
    Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER | Trace.TRACE_TAG_PERF);

    mAnimating = false;
    mKeyguardGoingAwayAnimation = false;
    mKeyguardGoingAwayWithWallpaper = false;
    mLocalAnimating = false;
    if (mAnimation != null) {
        mAnimation.cancel();
        mAnimation = null;
    }
    if (mAnimator.mWindowDetachedWallpaper == mWin) {
        mAnimator.mWindowDetachedWallpaper = null;
    }
    mAnimLayer = mWin.mLayer
            + mService.mLayersController.getSpecialWindowAnimLayerAdjustment(mWin);
    if (DEBUG_LAYERS) Slog.v(TAG, "Stepping win " + this + " anim layer: " + mAnimLayer);
    mHasTransformation = false;
    mHasLocalTransformation = false;
    mStackClip = STACK_CLIP_BEFORE_ANIM;
    mWin.checkPolicyVisibilityChange();
    mTransformation.clear();
    if (mDrawState == HAS_DRAWN
            && mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING
            && mWin.mAppToken != null
            && mWin.mAppToken.firstWindowDrawn
            && mWin.mAppToken.startingData != null) {
        if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Finish starting "
                + mWin.mToken + ": first real window done animating");
        mService.mFinishedStarting.add(mWin.mAppToken);
        mService.mH.sendEmptyMessage(H.FINISHED_STARTING);
        /// M: [App Launch Reponse Time Enhancement][FSW] Cache bitmap. {@
        if (mService.isFastStartingWindowSupport() && mService.isCacheFirstFrame()) {
            doCacheBitmap();
        }
        /// @}
    } else if (mAttrType == LayoutParams.TYPE_STATUS_BAR && mWin.mPolicyVisibility) {
        // Upon completion of a not-visible to visible status bar animation a relayout is
        // required.
        if (displayContent != null) {
            displayContent.layoutNeeded = true;
        }
    }

    finishExit();
    final int displayId = mWin.getDisplayId();
    mAnimator.setPendingLayoutChanges(displayId, WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM);
    if (DEBUG_LAYOUT_REPEATS)
        mService.mWindowPlacerLocked.debugLayoutRepeats(
                "WindowStateAnimator", mAnimator.getPendingLayoutChanges(displayId));

    if (mWin.mAppToken != null) {
        mWin.mAppToken.updateReportedVisibilityLocked();
    }

    return false;
}

 
 
针对不同对象的Animator. WindowAnimator, 负责整个屏幕的动画,比如说转屏,它提供Runnable实现。
WindowStateAnimator, 负责ViewRoot,即某一个窗口的动画。AppWindowAnimator, 负责应用启动和退出时候的动画。
这几个Animator都会提供一个函数,stepAnimationLocked(), 它会完成一个动画动作的一系列工作,
从计算Transformation到更新Surface的Matrix
 
Line 60: Line 13863: 01-01 04:06:38.255992 882 1052 V WindowManager: Starting animation in AppWindowToken{f4e5148 token=Token{802cfeb ActivityRecord{4bb9e65 u0 com.android.settings/.fingerprint.SetupFingerprintEnrollEnrolling t2}}} @ 4599359 scale=1.0 allDrawn=true animating=false
Line 62: Line 14565: 01-01 04:06:38.550747 882 1052 V WindowManager: Finished animation in AppWindowToken{f4e5148 token=Token{802cfeb ActivityRecord{4bb9e65 u0 com.android.settings/.fingerprint.SetupFingerprintEnrollEnrolling t2}}} @ 4599665
Line 63: Line 14566: 01-01 04:06:38.550901 882 1052 V WindowManager: Animation done in AppWindowToken{f4e5148 token=Token{802cfeb ActivityRecord{4bb9e65 u0 com.android.settings/.fingerprint.SetupFingerprintEnrollEnrolling t2}}}: reportedVisible=false
Line 66: Line 14589: 01-01 04:06:38.555218 882 1052 V WindowManager: Animation done in WindowStateAnimator{d71bec1 com.android.settings/com.android.settings.fingerprint.SetupFingerprintEnrollEnrolling}: exiting=false, reportedVisible=true
 
 
 

流程如下。

①WindowManagerService.scheduleAnimationLocked()-->WindowAnimator.mAnimationRunnable.run()-->WindowAnimator.animateLocked()-->WindowAnimator.performAnimationsLocked()-->WindowAnimator.updateWindowsLocked()

-->WindowStateAnimator.stepAnimationLocked()--> WindowStateAnimator.stepAnimation()-->Animation.getTransformation() -->Animation.applyTransformation()。

②WindowManagerService.scheduleAnimationLocked()-->WindowAnimator.mAnimationRunnable.run()-->WindowAnimator.animateLocked()-->WindowAnimator.updateAppWindowsLocked()-->AppWindowAnimator.stepAnimationLocked()

 -->AppWindowAnimator.stepAnimation()-->Animation.getTransformation() -->Animation.applyTransformation()。

③WindowAnimator.animateLocked()-->WindowStateAnimator.prepareSurfaceLocked()-->WindowStateAnimator.computeShownFrameLocked()。

 
 
 
 
 
 
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值