package com.android.systemui.statusbar.phone;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Path;
import android.graphics.Path.Direction;
import android.graphics.Region.Op;
import android.renderscript.Allocation;
import android.renderscript.Element;
import android.renderscript.RenderScript;
import android.renderscript.ScriptIntrinsicBlur;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Surface;
import android.view.View;
import android.view.WindowManager;
import com.android.systemui.R;
import com.android.systemui.screenshot.GlobalScreenshot;
public class BlurView extends View{
public static final String TAG = "BlurView";
private static final float BITMAP_SCALE = 0.125f;
private static final boolean DEBUG = false;
private GlobalScreenshot mScreenshot;
private Context mContext;
private WindowManager mWindowManager;
private int mBackgroud;
private int mBottomLeftRadius;
private int mBottomRightRadius;
private boolean mFullScreen;
private Bitmap mMasterBitmap = null;
public BlurView(Context context) {
this(context, null);
}
public BlurView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public BlurView(Context context, AttributeSet attrs, int defStyleAttr) {
this(context, attrs, defStyleAttr, 0);
}
public BlurView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
mContext = context;
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.blur);
mBackgroud = a.getColor(R.styleable.blur_backgroud,
mContext.getResources().getColor(R.color.status_bar_expanded_blur_masked));
mBottomLeftRadius = a.getDimensionPixelSize(R.styleable.blur_bottomLeftRadius, 0);
mBottomRightRadius = a.getDimensionPixelSize(R.styleable.blur_bottomRightRadius, 0);
mFullScreen = a.getBoolean(R.styleable.blur_fullScreen, false);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (DEBUG)
Log.d(TAG, "onDraw -->"+System.currentTimeMillis());
Bitmap initBitmap = null;
if (mMasterBitmap == null || mMasterBitmap.isRecycled()) {
if(mScreenshot == null){
mScreenshot = new GlobalScreenshot(getContext());
}
initBitmap = mScreenshot.takeScreenshot();//获取到当前屏幕的图片
} else {
initBitmap = mMasterBitmap;
}
if(initBitmap == null) {
//modify for GMOS-6570
Bitmap blackBitmap = Bitmap.createBitmap(1080, 1920, Bitmap.Config.ARGB_8888);
initBitmap = blackBitmap;
// return;
}
if (DEBUG)
Log.d(TAG, "onDraw ---->"+System.currentTimeMillis());
if (!mFullScreen && (getHeight() != initBitmap.getHeight()
|| getWidth() != initBitmap.getWidth())) {
initBitmap = cropBitmap(initBitmap);//如果使用blurview的不是占满整个屏幕的,则截取图片
}
if (mWindowManager == null) {
mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
}
int orientation = mWindowManager.getDefaultDisplay().getRotation();
Bitmap rotateBitmap = null;
Bitmap blurBitmap = null;
int screenWidth;
int screenHeight;
if (Surface.ROTATION_90 == orientation) {
rotateBitmap = rotateBitmap(initBitmap, -90);//如果屏幕是旋转的
} else if (Surface.ROTATION_270 == orientation) {
rotateBitmap = rotateBitmap(initBitmap, -270);
}
if (rotateBitmap == null) {
screenWidth = initBitmap.getWidth();
screenHeight = initBitmap.getHeight();
if (DEBUG)
Log.d(TAG, "onDraw ------>"+System.currentTimeMillis());
blurBitmap = blurBitmap(getContext(), initBitmap, 18f);//模糊效果实现
if (DEBUG)
Log.d(TAG, "onDraw -------->"+System.currentTimeMillis());
initBitmap.recycle();
} else {
screenWidth = rotateBitmap.getWidth();
screenHeight = rotateBitmap.getHeight();
if (DEBUG)
Log.d(TAG, "onDraw ------>"+System.currentTimeMillis());
blurBitmap = blurBitmap(getContext(), rotateBitmap, 18f);
if (DEBUG)
Log.d(TAG, "onDraw -------->"+System.currentTimeMillis());
rotateBitmap.recycle();
}
if (mBottomLeftRadius != 0 || mBottomRightRadius !=0) {
Path path = new Path();
path.addRoundRect(0, 0, getWidth(), getHeight(),
new float[]{0, 0, 0, 0, mBottomLeftRadius, mBottomLeftRadius, mBottomRightRadius, mBottomRightRadius},
Direction.CCW);
canvas.clipPath(path, Op.INTERSECT);
}
if (DEBUG)
Log.d(TAG, "onDraw ---------->"+System.currentTimeMillis());
Bitmap expandBitmap = Bitmap.createScaledBitmap(blurBitmap, screenWidth, screenHeight, true);
if (DEBUG)
Log.d(TAG, "onDraw ------------>"+System.currentTimeMillis());
if (! expandBitmap.equals(blurBitmap)) {
blurBitmap.recycle();
}
canvas.drawBitmap(expandBitmap, 0, 0, null);
Bitmap blackBitmap = Bitmap.createBitmap(screenWidth, screenHeight, Bitmap.Config.ARGB_8888);
blackBitmap.eraseColor(mBackgroud);
canvas.drawBitmap(blackBitmap,0,0,null);
if (DEBUG)
Log.d(TAG, "onDraw ------------>"+System.currentTimeMillis());
}
private Bitmap cropBitmap(Bitmap bitmap) {
if (null == bitmap) {
return null;
}
final int[] location = new int[2];
getLocationOnScreen(location);
Bitmap cache = null;
if (location[0] >= 0 && location[1] >= 0 && bitmap.getWidth() >= location[0]+getWidth()
&& bitmap.getHeight() >= location[1]+getHeight()) {
cache = Bitmap.createBitmap(bitmap, location[0], location[1], getWidth(), getHeight());
} else {
Log.e(TAG, "cropBitmap error location[0]:"+location[0]+",location[1]:"+location[1]
+ ",width:"+getWidth()+",height:"+getHeight());
return bitmap;
}
bitmap.recycle();
return cache;
}
private Bitmap rotateBitmap(Bitmap origin, float degrees) {
if (origin == null) {
return null;
}
int width = origin.getWidth();
int height = origin.getHeight();
Matrix matrix = new Matrix();
matrix.setRotate(degrees);
Bitmap newBM = Bitmap.createBitmap(origin, 0, 0, width, height, matrix, false);
if (newBM.equals(origin)) {
return newBM;
}
origin.recycle();
return newBM;
}
public static Bitmap blurBitmap(Context context, Bitmap image, float blurRadius) {
if (null == image) {
return null;
}
boolean isRgb8888=false;
if (image.getConfig() != Bitmap.Config.ARGB_8888) {
image = RGB565toARGB888(image);
isRgb8888 = true;
}
int width = Math.round(image.getWidth() * BITMAP_SCALE);
int height = Math.round(image.getHeight() * BITMAP_SCALE);
Bitmap inputBitmap = Bitmap.createScaledBitmap(image, width, height, false);
Bitmap outputBitmap = Bitmap.createBitmap(inputBitmap);
if(isRgb8888){
image.recycle();
isRgb8888 = false;
}
RenderScript rs = null;
try {
rs = RenderScript.create(context);
} catch (Exception e) {
e.printStackTrace();
inputBitmap.recycle();
outputBitmap.recycle();
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
bitmap.eraseColor(Color.parseColor("#D9454545"));
return bitmap;
}
ScriptIntrinsicBlur blurScript = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));
Allocation tmpIn = Allocation.createFromBitmap(rs, inputBitmap);
Allocation tmpOut = Allocation.createFromBitmap(rs, outputBitmap);
blurScript.setRadius(blurRadius);
blurScript.setInput(tmpIn);
blurScript.forEach(tmpOut);
tmpOut.copyTo(outputBitmap);
blurScript.destroy();
tmpIn.destroy();
tmpOut.destroy();
rs.destroy();
inputBitmap.recycle();
return outputBitmap;
}
//mengran.wang add for bug PRODUCTION-7098
private static Bitmap RGB565toARGB888(Bitmap img) {
int numPixels = img.getWidth()* img.getHeight();
int[] pixels = new int[numPixels];
img.getPixels(pixels, 0, img.getWidth(), 0, 0, img.getWidth(), img.getHeight());
Bitmap result = Bitmap.createBitmap(img.getWidth(), img.getHeight(), Bitmap.Config.ARGB_8888);
result.setPixels(pixels, 0, result.getWidth(), 0, 0, result.getWidth(), result.getHeight());
//img.recycle();
return result;
}
public void setMasterBitmap(Bitmap bitmap) {
mMasterBitmap = bitmap;
}
}