Setting this attribute does not take effect immediately. Only the setwindowmanager call can take effect, while the setwindowmanager is called only when the activity is created.
1./packages/apps/settings/src/COM/Android/settings/developmentsettings. Java
Set Properties in setting. Send the command sysprops_transaction to all services through the binder.
./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(cmd.exe cute ();
}
}
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. cpp
Server accepts the sysprops_transaction command
Case sysprops_transaction :{
Report_sysprop_change ();
Return no_error;
}
1.2 frameworks/native/libs/utils/Misc. cpp
Callback
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
}
Register callback Functions
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, 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. 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, "Hangzhou mtraversals ");
Try {
Extends mtraversals ();
} Finally {
Trace. traceend (trace. trace_tag_view );
}
If (mprofile ){
Debug. stopmethodtracing ();
Mprofile = false;
}
}
}
In the dotraversal process, setwindowmanager is not called, that is, the Force GPU does not take effect immediately.
2. Frameworks/base/CORE/Java/Android/View/window. Java
The persist. SYS. UI. HW attribute is only available in the setwindowmanager function. Then, the GPU image UI is called to determine the property.
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, 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. 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 ){
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)