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;
}
……