设置这个属性不会立即生效。只有调用setWindowManager才能生效,而setWindowManager只有Activity建立的时候调用。
1../packages/apps/Settings/src/com/android/settings/DevelopmentSettings.java
在setting设置属性。给所有服务通过binder发送命令SYSPROPS_TRANSACTION。
./apps/Settings/res/values/strings.xml:4033: <string name="force_hw_ui">Force GPU rendering</string>
private static final String HARDWARE_UI_PROPERTY = "persist.sys.ui.hw";
private void writeHardwareUiOptions() {
SystemProperties.set(HARDWARE_UI_PROPERTY, mForceHardwareUi.isChecked() ? "true" : "false");
pokeSystemProperties();
}
void pokeSystemProperties() {
if (!mDontPokeProperties) {
//noinspection unchecked
(new SystemPropPoker()).execute();
}
}
static class SystemPropPoker extends AsyncTask<Void, Void, Void> {
@Override
protected Void doInBackground(Void... params) {
String[] services;
try {
services = ServiceManager.listServices();
} catch (RemoteException e) {
return null;
}
for (String service : services) {
IBinder obj = ServiceManager.checkService(service);
if (obj != null) {
Parcel data = Parcel.obtain();
try {
obj.transact(IBinder.SYSPROPS_TRANSACTION, data, null, 0);
} catch (RemoteException e) {
} catch (Exception e) {
Log.i("DevSettings", "Somone wrote a bad service '" + service
+ "' that doesn't like to be poked: " + e);
}
data.recycle();
}
}
return null;
}
}
1.1 frameworks/native/libs/binder/Binder.cpp
server接受SYSPROPS_TRANSACTION命令
case SYSPROPS_TRANSACTION: {
report_sysprop_change();
return NO_ERROR;
}
1.2 frameworks/native/libs/utils/misc.cpp
回调
void report_sysprop_change() {
#if defined(HAVE_PTHREADS)
pthread_mutex_lock(&gSyspropMutex);
Vector<sysprop_change_callback_info> listeners;
if (gSyspropList != NULL) {
listeners = *gSyspropList;
}
pthread_mutex_unlock(&gSyspropMutex);
//ALOGI("Reporting sysprop change to %d listeners", listeners.size());
for (size_t i=0; i<listeners.size(); i++) {
listeners[i].callback();
}
#endif
}
注册回调函数
void add_sysprop_change_callback(sysprop_change_callback cb, int priority) {
#if defined(HAVE_PTHREADS)
pthread_mutex_lock(&gSyspropMutex);
if (gSyspropList == NULL) {
gSyspropList = new Vector<sysprop_change_callback_info>();
}
sysprop_change_callback_info info;
info.callback = cb;
info.priority = priority;
bool added = false;
for (size_t i=0; i<gSyspropList->size(); i++) {
if (priority >= gSyspropList->itemAt(i).priority) {
gSyspropList->insertAt(info, i);
added = true;
break;
}
}
if (!added) {
gSyspropList->add(info);
}
pthread_mutex_unlock(&gSyspropMutex);
#endif
}
static void SystemProperties_add_change_callback(JNIEnv *env, jobject clazz)
{
// This is called with the Java lock held.
if (sVM == NULL) {
env->GetJavaVM(&sVM);
}
if (sClazz == NULL) {
sClazz = (jclass) env->NewGlobalRef(clazz);
sCallChangeCallbacks = env->GetStaticMethodID(sClazz, "callChangeCallbacks", "()V");
add_sysprop_change_callback(do_report_sysprop_change, -10000);
}
}
1.3 frameworks/base/core/jni/android_os_SystemProperties.cpp
{ "native_add_change_callback", "()V",
(void*) SystemProperties_add_change_callback },
1.4 frameworks/base/core/java/android/os/SystemProperties.java
public static void addChangeCallback(Runnable callback) {
synchronized (sChangeCallbacks) {
if (sChangeCallbacks.size() == 0) {
native_add_change_callback();
}
sChangeCallbacks.add(callback);
}
}
1.5 frameworks/base/core/java/android/view/WindowManagerGlobal.java
public void addView(View view, ViewGroup.LayoutParams params,
Display display, Window parentWindow)
if (mSystemPropertyUpdater == null) {
mSystemPropertyUpdater = new Runnable() {
@Override public void run() {
synchronized (mLock) {
for (ViewRootImpl viewRoot : mRoots) {
viewRoot.loadSystemProperties();
}
}
}
};
SystemProperties.addChangeCallback(mSystemPropertyUpdater);
}
1.6 frameworks/base/core/java/android/view/ViewRootImpl.java
public void loadSystemProperties() {
boolean layout = SystemProperties.getBoolean(
View.DEBUG_LAYOUT_PROPERTY, false);
if (layout != mAttachInfo.mDebugLayout) {
mAttachInfo.mDebugLayout = layout;
if (!mHandler.hasMessages(MSG_INVALIDATE_WORLD)) {
mHandler.sendEmptyMessageDelayed(MSG_INVALIDATE_WORLD, 200);
}
}
}
case MSG_INVALIDATE_WORLD: {
if (mView != null) {
invalidateWorld(mView);
}
void invalidateWorld(View view) {
view.invalidate();
if (view instanceof ViewGroup) {
ViewGroup parent = (ViewGroup) view;
for (int i = 0; i < parent.getChildCount(); i++) {
invalidateWorld(parent.getChildAt(i));
}
}
}
void invalidate() {
mDirty.set(0, 0, mWidth, mHeight);
scheduleTraversals();
}
void scheduleTraversals() {
if (!mTraversalScheduled) {
mTraversalScheduled = true;
mTraversalBarrier = mHandler.getLooper().postSyncBarrier();
mChoreographer.postCallback(
Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
scheduleConsumeBatchedInput();
}
}
final class TraversalRunnable implements Runnable {
@Override
public void run() {
doTraversal();
}
}
void doTraversal() {
if (mTraversalScheduled) {
mTraversalScheduled = false;
mHandler.getLooper().removeSyncBarrier(mTraversalBarrier);
if (mProfile) {
Debug.startMethodTracing("ViewAncestor");
}
Trace.traceBegin(Trace.TRACE_TAG_VIEW, "performTraversals");
try {
performTraversals();
} finally {
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
}
if (mProfile) {
Debug.stopMethodTracing();
mProfile = false;
}
}
}
在doTraversal过程中,不会调用setWindowManager, 也就是强制GPU不会立即生效。
2.frameworks/base/core/java/android/view/Window.java
persist.sys.ui.hw属性只有在setWindowManager函数会得到这个属性。然后会判断这个属性调用gpu画ui。
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);
}
if (mHardwareAccelerated) {
wp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
}
3../base/core/java/android/view/ViewRootImpl.java
private void enableHardwareAcceleration(Context context, WindowManager.LayoutParams attrs) {
mAttachInfo.mHardwareAccelerated = false;
mAttachInfo.mHardwareAccelerationRequested = false;
// Don't enable hardware acceleration when the application is in compatibility mode
if (mTranslator != null) return;
// Try to enable hardware acceleration if requested
final boolean hardwareAccelerated =
(attrs.flags & WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED) != 0;
if (hardwareAccelerated) {
if (!HardwareRenderer.isAvailable()) {
return;
}
mAttachInfo.mHardwareRenderer = HardwareRenderer.createGlRenderer(2, translucent);
4.java/android/view/HardwareRenderer.java
public static boolean isAvailable() {
return GLES20Canvas.isAvailable();
}
static HardwareRenderer createGlRenderer(int glVersion, boolean translucent) {
switch (glVersion) {
case 2:
return Gl20Renderer.create(translucent);
}
throw new IllegalArgumentException("Unknown GL version: " + glVersion);
}
static HardwareRenderer create(boolean translucent) {
if (GLES20Canvas.isAvailable()) {
return new Gl20Renderer(translucent);
}
return null;
}
5./core/java/android/view/GLES20Canvas.java
private static native boolean nIsAvailable();
private static boolean sIsAvailable = nIsAvailable();
static boolean isAvailable() {
return sIsAvailable;
}
6../base/core/java/android/view/ViewRootImpl.java
private void draw(boolean fullRedrawNeeded){
if (!dirty.isEmpty() || mIsAnimating) {
if (attachInfo.mHardwareRenderer != null && attachInfo.mHardwareRenderer.isEnabled()) {
// Draw with hardware renderer.
mIsAnimating = false;
mHardwareYOffset = yoff;
mResizeAlpha = resizeAlpha;
mCurrentDirty.set(dirty);
mCurrentDirty.union(mPreviousDirty);
mPreviousDirty.set(dirty);
dirty.setEmpty();
if (attachInfo.mHardwareRenderer.draw(mView, attachInfo, this,
animating ? null : mCurrentDirty)) {
mPreviousDirty.set(0, 0, mWidth, mHeight);
}
} else if (!drawSoftware(surface, attachInfo, yoff, scalingRequired, dirty)) {
return;
}
}
1138 boolean draw(View view, View.AttachInfo attachInfo, HardwareDrawCallbacks callbacks,
1139 Rect dirty) {
1214 callbacks.onHardwarePreDraw(canvas);
public void onHardwarePostDraw(HardwareCanvas canvas) {
if (mResizeBuffer != null) {
mResizePaint.setAlpha(mResizeAlpha);
canvas.drawHardwareLayer(mResizeBuffer, 0.0f, mHardwareYOffset, mResizePaint);
}
drawAccessibilityFocusedDrawableIfNeeded(canvas);
}
7. frameworks/base/core/java/android/view/GLES20Canvas.java
void drawHardwareLayer(HardwareLayer layer, float x, float y, Paint paint) {
final GLES20Layer glLayer = (GLES20Layer) layer;
final int nativePaint = paint == null ? 0 : paint.mNativePaint;
nDrawLayer(mRenderer, glLayer.getLayer(), x, y, nativePaint);
}
private static native void nDrawLayer(int renderer, int layer, float x, float y, int paint);
8.frameworks/base/core/jni/android_view_GLES20Canvas.cpp
static void android_view_GLES20Canvas_drawLayer(JNIEnv* env, jobject clazz,
OpenGLRenderer* renderer, Layer* layer, jfloat x, jfloat y, SkPaint* paint) {
renderer->drawLayer(layer, x, y, paint);
}
9.frameworks/base/libs/hwui/OpenGLRenderer.cpp
status_t OpenGLRenderer::drawLayer(Layer* layer, float x, float y, SkPaint* paint)