AlertDialog如何创建layerDim的过程

1.首先在alertdialog的构造函数中可以看到它采用了R.style.Theme_Dialog_Alert样式;

 \framework\base\core\java\app\AlertDialog.java
    protected AlertDialog(Context context, boolean cancelable, OnCancelListener cancelListener) {
        super(context, com.android.internal.R.style.Theme_Dialog_Alert);//使用Theme_Dialog_Alert样式
        setCancelable(cancelable);
        setOnCancelListener(cancelListener);
        mAlert = new AlertController(context, this, getWindow());
    }

2.那么我们看看Theme_Dialog_Alert样式到底是什么样的;

\framework\base\core\res\res\values\Theme.xml
……
    <!-- Default theme for alert dialog windows, which is used by the
         {@link android.app.AlertDialog} class.  This is basically a dialog
         but sets the background to empty so it can do two-tone backgrounds. -->
    <style name="Theme.Dialog.Alert">
        <item name="windowBackground">@android:color/transparent</item>
        <item name="windowTitleStyle">@android:style/DialogWindowTitle</item>
        <!-- 窗口默认为浮动的 -->
        <item name="windowIsFloating">true</item>
        <item name="windowContentOverlay">@null</item>
    </style>
……

3.我们再看看系统在显示该窗口之前根据上面的样式做了哪些工作,换句话说系统根据这些样式对窗口属性设置了哪些标记.

\frameworks\base\policy\src\com\android\internal\policy\impl\PhoneWindow.java
  protected ViewGroup generateLayout(DecorView decor) {
……
        mIsFloating = a.getBoolean(com.android.internal.R.styleable.Window_windowIsFloating, false);//从样式中确定是否为浮动窗口,若没有该样式则默认值为false (从我们第二点的分析来看,对于alertdialog该值为true)
        int flagsToUpdate = (FLAG_LAYOUT_IN_SCREEN|FLAG_LAYOUT_INSET_DECOR)
                & (~getForcedWindowFlags());
        if (mIsFloating) {
            setLayout(WRAP_CONTENT, WRAP_CONTENT);
            setFlags(0, flagsToUpdate);
        } else {
            setFlags(FLAG_LAYOUT_IN_SCREEN|FLAG_LAYOUT_INSET_DECOR, flagsToUpdate);
        }
……
        if (a.getBoolean(com.android.internal.R.styleable.Window_backgroundDimEnabled, 
                mIsFloating)) { //从样式中读取backgroundDimEnabled值,如果没有设置则默认值为mIsFloating(依据前面和第二点的分析,对于alertdialog该值为true)
            /* All dialogs should have the window dimmed */
            if ((getForcedWindowFlags()&WindowManager.LayoutParams.FLAG_DIM_BEHIND) == 0) {
                params.flags |= WindowManager.LayoutParams.FLAG_DIM_BEHIND;//最为关键的一步,更改WM的参数为FLAG_DIM_BEHIND,即采用dim surface作为背景.
            }
            params.dimAmount = a.getFloat(
                    android.R.styleable.Window_backgroundDimAmount, 0.5f);
        }
……

}

4.在设置完属性后,则由WindowManager创建surface了.

\frameworks\base\services\java\com\android\server\WindowManagerService.java
   private final void performLayoutAndPlaceSurfacesLockedInner(
            boolean recoveringMemory) {
……
else if (canBeSeen && !obscured &&
                 (attrFlags&FLAG_BLUR_BEHIND|FLAG_DIM_BEHIND) != 0) {
                 if (localLOGV) Slog.v(TAG, "Win " + w
                                + ": blurring=" + blurring
                                + " obscured=" + obscured
                                + " displayed=" + displayed);
                   if ((attrFlags&FLAG_DIM_BEHIND) != 0) {
                            if (!dimming) {
                                //Slog.i(TAG, "DIM BEHIND: " + w);
                                dimming = true;
                                if (mDimAnimator == null) {
                                    mDimAnimator = new DimAnimator(mFxSession);//实际上显示alertdialog的过程是一个动画,通过改变alpha实现由透明边半透明的效果
                                }
                                mDimAnimator.show(dw, dh);
                                mDimAnimator.updateParameters(w, currentTime);
                            }
                    }
          ……
    }
……

    }

5.那么DimAnimator创建了怎样一个surface呢,我们可以从其构造函数看出一些端倪.

 \frameworks\base\services\java\com\android\server\WindowManagerService.java
      DimAnimator (SurfaceSession session) {
            if (mDimSurface == null) {
                if (SHOW_TRANSACTIONS) Slog.i(TAG, "  DIM "
                        + mDimSurface + ": CREATE");
                try {
                    mDimSurface = new Surface(session, 0,
                            "DimSurface",
                            -1, 16, 16, PixelFormat.OPAQUE,
                            Surface.FX_SURFACE_DIM); //实际上向surfaceflinger申请了一个FX_SURFACE_DIM类型的surface
                    mDimSurface.setAlpha(0.0f);
                } catch (Exception e) {
                    Slog.e(TAG, "Exception creating Dim surface", e);
                }
            }
        }

6.现在到surfaceflinger去看看他到底创建了怎样一个layer.

 \frameworks\base\services\surfaceflinger\surfaceflinger.cpp
    sp<ISurface> SurfaceFlinger::createSurface(const sp<Client>& client, int pid,
        const String8& name, ISurfaceComposerClient::surface_data_t* params,
        DisplayID d, uint32_t w, uint32_t h, PixelFormat format,
        uint32_t flags)
{
……
switch (flags & eFXSurfaceMask) {
        case eFXSurfaceNormal:
            if (UNLIKELY(flags & ePushBuffers)) {
                layer = createPushBuffersSurface(client, d, w, h, flags);
            } else {
                normalLayer = createNormalSurface(client, d, w, h, flags, format);
                layer = normalLayer;
            }
            break;
        case eFXSurfaceBlur:
            layer = createBlurSurface(client, d, w, h, flags);
            break;
        case eFXSurfaceDim:
            layer = createDimSurface(client, d, w, h, flags); //调用并创建Dim surface
            break;
    }
……

}
……

sp<LayerDim> SurfaceFlinger::createDimSurface(
        const sp<Client>& client, DisplayID display,
        uint32_t w, uint32_t h, uint32_t flags)
{
    sp<LayerDim> layer = new LayerDim(this, display, client); //很显然创建了一个Dim layer
    layer->initStates(w, h, flags);
    return layer;
}
……





 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值