处理华为Framework层中curosr和空指针问题(反编译ROM和Hook动态代理)

最近一直忙着解决公司游戏的Bug,但有些问题是顽固分子,许多个迭代都没解决掉,但不处理总觉有一根刺,在扎着肉。

本篇是记录如何处理手机系统ROM中Framework中报错,可以适用不同的手机厂商。

bugly上的问题:

android.database.CursorWindowAllocationException
Cursor window could not be created from binder.
android.database.CursorWindow.<init>(CursorWindow.java:137)
android.database.CursorWindow.<init>(CursorWindow.java)
android.database.CursorWindow$1.createFromParcel(CursorWindow.java:685)
android.database.CursorWindow$1.createFromParcel(CursorWindow.java:684)
android.database.BulkCursorDescriptor.readFromParcel(BulkCursorDescriptor.java:75)
android.database.BulkCursorDescriptor$1.createFromParcel(BulkCursorDescriptor.java:34)
android.database.BulkCursorDescriptor$1.createFromParcel(BulkCursorDescriptor.java:32)
android.content.ContentProviderProxy.query(ContentProviderNative.java:424)
android.content.ContentResolver.query(ContentResolver.java:541)
android.content.ContentResolver.query(ContentResolver.java:476)
com.huawei.android.hwaps.OperateExperienceLib.isGameInfoExist(OperateExperienceLib.java:497)
com.huawei.android.hwaps.OperateExperienceLib.saveAPSResult(OperateExperienceLib.java:429)
com.huawei.android.hwaps.EventAnalyzed.setAdaptFPS(EventAnalyzed.java:1373)
com.huawei.android.hwaps.EventAnalyzed.processAnalyze(EventAnalyzed.java:1726)
android.view.HwNsdImpl.adaptPowerSave(HwNsdImpl.java:1182)
android.view.ViewRootImpl$EarlyPostImeInputStage.processPointerEvent(ViewRootImpl.java:4648)
android.view.ViewRootImpl$EarlyPostImeInputStage.onProcess(ViewRootImpl.java:4617)
android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4258)
android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:6690)
android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:6664)
android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:6625)
android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:6819)
android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:192)
android.os.MessageQueue.nativePollOnce(Native Method)
android.os.MessageQueue.next(MessageQueue.java:356)
android.os.Looper.loop(Looper.java:138)
android.app.ActivityThread.main(ActivityThread.java:6623)
java.lang.reflect.Method.invoke(Native Method)
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:942)
com.android.internal.os.ZygoteInit.main(ZygoteInit.java:832)

从代码报错点来看是,cursor 过多未关闭,存在泄漏,产生的原因可能是cursor未关闭或者fd 过多或者是内存不足。

因报错点发生在华为ROM的framework层,因此要先考虑获取到对应的framework.dex, 查看代码调用流程,再来确定解决方案。

设备信息:

设备机型系统版本ROM
WAS-AL00Android 8.0.0,level 26HuaWei/EMOTION

1.前期准备:反编译华为Rom系统

可考虑下载华为固件Rom 或者通过adb pull 获取该机型的framework.dex, 详细操作,请阅读Android反编译之各大手机厂商的系统(adb pull和Rom包)

经过一些列操作,获取到framework有关的dex,如下图所示:
在这里插入图片描述

2.源码分析定位

通过gui 工具打开华为rom 的framework 层源码。
在这里插入图片描述

先从ViewRootImpl#EarlyPostImeInputStage的onProcess()开始入手,追查起。

android/view/ViewRootImpl:

    final class EarlyPostImeInputStage extends InputStage {

        protected int onProcess(QueuedInputEvent q) {
            if (q.mEvent instanceof KeyEvent) {
                return processKeyEvent(q);
            }
            if ((q.mEvent.getSource() & 2) != 0) {
                return processPointerEvent(q);
            }
            return 0;
        }

        private int processPointerEvent(QueuedInputEvent q) {
            MotionEvent event = q.mEvent;
            if (ViewRootImpl.this.mTranslator != null) {
                ViewRootImpl.this.mTranslator.translateEventInScreenToAppWindow(event);
            }
			    //若是rom 支持aps功能和包名和进程名匹配的情况下
            if (HwFrameworkFactory.getHwNsdImpl().isSupportAps() && HwFrameworkFactory.getHwNsdImpl().isGameProcess(ViewRootImpl.this.mContext.getPackageName())) {
                HwFrameworkFactory.getHwNsdImpl().initAPS(ViewRootImpl.this.mView.getContext(), ViewRootImpl.this.mView.getResources().getDisplayMetrics().widthPixels, Process.myPid());
                HwFrameworkFactory.getHwNsdImpl().adaptPowerSave(event);
            }
            int action = event.getAction();
            if (HwFrameworkFactory.getHwViewRootImpl().filterDecorPointerEvent(ViewRootImpl.this.mContext, event, action, ViewRootImpl.this.mWindowAttributes, ViewRootImpl.this.mDisplay)) {
                return 1;
            }
			//... 
            return 0;
        }
    }


先来看下getHwNsdImpl()获取的对象,才能更好的了解源码调用过程。

android/common/HwFrameworkFactory中:

  public static IHwNsdImpl getHwNsdImpl() {
        Factory obj = getImplObject();
        if (obj != null) {
            return obj.getHwNsdImpl();
        }
        return null;
  }
  private static Factory getImplObject() {
        if (obj != null) {
            return obj;
        }
        synchronized (mLock) {
            try {// 反射获取真正的HwFrameworkFactory实现类
                obj = (Factory) Class.forName("huawei.android.common.HwFrameworkFactoryImpl").newInstance();
            } catch (Exception e) {
                Log.e(TAG, ": reflection exception is " + e);
            }
        }
        //...
        return null;
    }

HwFrameworkFactory 是一个封装的api 类,用于静态方法/工厂类方式,间接调用各种api。

接下来,继续看下huawei/android/common/HwFrameworkFactoryImpl类中的getHwNsdImpl()

    public HwNsdImpl getHwNsdImpl() {
        return HwNsdImpl.getDefault();
    }

接下来看下android/view/HwNsdImpl

   public static HwNsdImpl getDefault() {
        if (mInstance == null) {
            mInstance = new HwNsdImpl();
        }
        return mInstance;
    }

经过一些列的追踪,可以了解到ViewRootImpl对象中调用的是HwNsdImpl中的方法。

接下来看下,isGameProcess()isSupportAps()adaptPowerSave()等几个方法。

2.1 华为framework 统计游戏fps 的条件
    public boolean isSupportAps() { 
        return SystemProperties.getInt("sys.aps.support", 0) > 0;
    }

从上面代码可知,isSupportAps()是检测系统rom 是否支持aps功能。

接下来看下isGameProcess()

 private static IEventAnalyzed mEventAnalyzed = null;

    public boolean isGameProcess(String pkgName) {
        createEventAnalyzed();
        if (mEventAnalyzed != null) {
            return mEventAnalyzed.isGameProcess(pkgName);
        }
        return false;
    }
    public synchronized void createEventAnalyzed() {
        if (mEventAnalyzed == null) {
            mEventAnalyzed = HwapsWrapper.getEventAnalyzed();
        }
    }

接下来看下, com/huawei/android/hwaps/HwapsWrapper类中getEventAnalyzed():

    public static IEventAnalyzed getEventAnalyzed() {
        IHwapsFactory factory = getHwapsFactoryImpl();
        return factory != null ? factory.getEventAnalyzed() : null;
    }

    private static synchronized IHwapsFactory getHwapsFactoryImpl() {
        IHwapsFactory iHwapsFactory;
        synchronized (HwapsWrapper.class) {
            if (mFactory != null) {
                iHwapsFactory = mFactory;
            } else {
                try {
                    mFactory = (IHwapsFactory) Class.forName("com.huawei.android.hwaps.HwapsFactoryImpl").newInstance();
                } catch (ClassNotFoundException e) {
                    Log.e(TAG, "reflection exception is " + e);
                } catch (InstantiationException e2) {
                    Log.e(TAG, "reflection exception is " + e2);
                } catch (IllegalAccessException e3) {
                    Log.e(TAG, "reflection exception is " + e3);
                }
                if (mFactory == null) {
                    Log.e(TAG, "failes to get HwapsFactoryImpl");
                }
                iHwapsFactory = mFactory;
            }
        }
        return iHwapsFactory;
    }

从上面代码可知, HwapsWrapper是一个封装api的类, 其真正调用是HwapsFactoryImpl类。

com/huawei/android/hwaps/HwapsFactoryImpl

public class HwapsFactoryImpl implements IHwapsFactory {

    //...
    public IEventAnalyzed getEventAnalyzed() {
        return new EventAnalyzed();
    }
}

经过一些列的波折,最终调用链是ViewRootImpl->IHwNsdImpl->EventAnalyzed类的方法:

com/huawei/android/hwaps/EventAnalyzed

    //检查下是否是原始进程对应的包名
    private boolean isIdentifyProcess(String strPkgName) {
        if (!this.mHasIdentifyProcess) {
            if (SystemProperties.get("debug.aps.process.name", "").equals(strPkgName)) {
                this.mIsGameProcess = true;
            } else {
                this.mIsGameProcess = false;
            }
            this.mHasIdentifyProcess = true;
        }
        return this.mIsGameProcess;
    }

    public boolean isGameProcess(String pkgName) {
        if (this.mHasIdentifyProcess && !this.mIsGameProcess) {
            return this.mIsGameProcess;
        }
        if (isAPSReady()) {
            return isIdentifyProcess(pkgName); // 通常下,app主进程 是返回true
        }
        return false;
    }

从上面可见,若pkgName是app 主进程名,是返回true的。

这里注意点, EventAnalyzed 是com/huawei/android/hwaps/IEventAnalyzed接口的实现类,后面会用到。

public interface IEventAnalyzed {

    //......
    boolean isGameProcess(String str);
    void processAnalyze(int i, long j, int i2, int i3, int i4, long j2);
    void setHasOnPaused(boolean z);
}
2.2 华为 framework层是如何存储游戏的fps功能

HwNsdImpl#adaptPowerSave()是调用EventAnalyzed#processAnalyze(),因此,接下来看下processAnalyze()

    public void processAnalyze(int aciton, long eventTime, int x, int y, int pointCount, long downTime) {
       //...
	   else if (CUST_APP_TYPE != mGameType) {
            //...
            setAdaptFPS(gametype, openGLType, this.mLevel);
        }
    }
	
	public void setAdaptFPS(int gameType, int openGLType, int level) {
            //...
            else if (!this.mHasSetFPS) {
                mGameType = gameType;
                int recommendFPS = computeRecommendFPS(gameType, openGLType, level);
                if (gameType == 8 || gameType == 9) {
                    this.mOperateExLib.saveAPSResult(gameType, recommendFPS, recommendFPS);
                } else {
                    this.mOperateExLib.saveAPSResult(gameType, recommendFPS, mMinFps);
                }
				//.....
            }
    }

接下来看下com/huawei/android/hwaps/OperateExperienceLibsaveAPSResult():

    public void saveAPSResult(int gameType, int maxFPS, int minFPS) {
        this.mGameType = gameType;
        this.mMaxFPS = maxFPS;
        this.mMinFPS = minFPS;
        if (this.mIsExistInDataBase) {
            updateAppInfo();
        } else {
            insertAppInfo();
        }
    }

这里发生了一点小变故,可能是同样的手机,同个大编号的系统rom 存在多个小版本,并没有找到isGameInfoExist()方法。

但并不影响,咱们继续分析。看到最后,发现最终是华为系统收集app game 的周期性的fps 信息, 通过广播形式跨进程通信到其他系统app中。

在通信前,会通过cursor查询下该游戏app是否存在,也就是bulgy上的报错点。解决方案,也是基于减少cursor的查询

3.解决方案 Hook 代理

3.1 思路分析

1.通过hook 方式,代理调用EventAnalyzed类调用processAnalyze();
2.经过上面的源码分析,可知HwNsdImpl类中mEventAnalyzed属性时hook 点;
3.因IEventAnalyzed是一个抽象接口,考虑动态代理拦截其中的方法调用。

3.2 编写相应的代码
  public static void hookHwFrameworkFactory() {
        if (isSafeHookHuawei()) {
            try {
                Class<?> hwNsdImplClass = Class.forName("android.view.HwNsdImpl");
                Method getDefaultMethod = hwNsdImplClass.getDeclaredMethod("getDefault");
                getDefaultMethod.setAccessible(true);
                // 获取HwNsdImpl 类对象
                Object hwNsdImplObject = getDefaultMethod.invoke(null);
                // 调用createEventAnalyzed(),先构建出真正的EventAnalyzed对象
                Method createEventAnalyzedMethod = hwNsdImplClass.getDeclaredMethod("createEventAnalyzed");
                createEventAnalyzedMethod.setAccessible(true);
                createEventAnalyzedMethod.invoke(hwNsdImplObject);
                // 获取真正的EventAnalyzed对象
                Field mEventAnalyzedFiled = hwNsdImplClass.getDeclaredField("mEventAnalyzed");
                mEventAnalyzedFiled.setAccessible(true);
                Object oldFactory = mEventAnalyzedFiled.get(null);
                // 构建IEventAnalyzed的代理对类
                Class<?> iEventAnalyzedClass = Class.forName("com.huawei.android.hwaps.IEventAnalyzed");
                Object proxyFactory = CommonProxy.startHook(oldFactory, iEventAnalyzedClass, new ProxyCallBack() {
                    @Override
                    public Object interrupt(CommonProxy proxy, Method method, Object[] args) throws Throwable {
                        Object result = null;
                        if (method.getName().equals("processAnalyze")) {
                            //处理bugly上的问题:https://bugly.qq.com/v2/crash-reporting/crashes/1105308248/33050435/report?pid=1&crashDataType=undefined
                            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && Build.VERSION.SDK_INT <= Build.VERSION_CODES.O_MR1) {
                                //6.0到8.1的版本上屏蔽该方法的调用
                            } else {
                                result = proxy.doRealInvoke(method, args);
                            }
                        } else {
                            result = proxy.doRealInvoke(method, args);
                        }
                        return result;
                    }
                });
                mEventAnalyzedFiled.set(null, proxyFactory);

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
3.3 云真机验证

在云真机进行验证发现,mEventAnalyzed是非静态,通过静态方式获取直接报错,可能每个Rom中代码又有新的变化:

08-29 19:39:29.633 W/System.err( 5126): java.lang.NullPointerException: null receiver
08-29 19:39:29.635 W/System.err( 5126): 	at java.lang.reflect.Field.get(Native Method)
08-29 19:39:29.635 W/System.err( 5126): 	at com.minitech.miniworld.HuaWeiHook.hookHwFrameworkFactory(HuaWeiHook.java:91)
08-29 19:39:29.635 W/System.err( 5126): 	at org.appplay.lib.GameBaseActivity$7.run(GameBaseActivity.java:625)
08-29 19:39:29.635 W/System.err( 5126): 	at android.os.Handler.handleCallback(Handler.java:761)
08-29 19:39:29.635 W/System.err( 5126): 	at android.os.Handler.dispatchMessage(Handler.java:98)
08-29 19:39:29.635 W/System.err( 5126): 	at android.os.Looper.loop(Looper.java:156)
08-29 19:39:29.635 W/System.err( 5126): 	at android.app.ActivityThread.main(ActivityThread.java:6623)
08-29 19:39:29.635 W/System.err( 5126): 	at java.lang.reflect.Method.invoke(Native Method)
08-29 19:39:29.635 W/System.err( 5126): 	at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:942)
08-29 19:39:29.635 W/System.err( 5126): 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:832)

结合报错的机型,如下:

在这里插入图片描述

3.4 完善代码

因此调整代码如下:

public class HuaWeiHook {
    private static final String TAG = "HuaWeiHook";

    /**
     * 是否是华为rom
     *
     * @return
     */
    public static boolean isHuWeiRoom() {
        final String huawei_room_name = "huawei";
        boolean result=false;
        try {
            String brand = Build.BRAND;
            Log.i(TAG," room brand "+brand);
            if (!TextUtils.isEmpty(brand)) {
                brand = brand.toLowerCase();
            }
            result=brand.contains(huawei_room_name);
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (!result){
            try {
                String manufacturer = Build.MANUFACTURER;
                Log.i(TAG," room  manufacturer "+ manufacturer);
                if (!TextUtils.isEmpty(manufacturer)) {
                    manufacturer = manufacturer.toLowerCase();
                }
               result= manufacturer.contains(huawei_room_name);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return result;
    }

    /**
     * 是否支持反射framework 层的api,9.0以下
     *
     * @return
     */
    public static boolean isSupportHook() {
        return Build.VERSION.SDK_INT < Build.VERSION_CODES.P;
    }

    /**
     * 检查是否满足华为机型反射调用
     *
     * @return
     */
    public static boolean isSafeHookHuawei() {
        return isHuWeiRoom() && isSupportHook();
    }

    private static AtomicBoolean init = new AtomicBoolean(false);

    public static void hookHwFrameworkFactory() {
        if (init.compareAndSet(false, true)) {
            boolean isSafe = isSafeHookHuawei();
            Log.i(TAG, " room huawei " + isSafe);
            if (isSafe) {// 非华为手机系统,不做处理
                try {
                    Class<?> hwNsdImplClass = Class.forName("android.view.HwNsdImpl");
                    Method getDefaultMethod = hwNsdImplClass.getDeclaredMethod("getDefault");
                    getDefaultMethod.setAccessible(true);
                    // 获取HwNsdImpl 类对象
                    Object hwNsdImplObject = getDefaultMethod.invoke(null);
                    // 调用createEventAnalyzed(),先构建出真正的EventAnalyzed对象
                    Method createEventAnalyzedMethod = hwNsdImplClass.getDeclaredMethod("createEventAnalyzed");
                    createEventAnalyzedMethod.setAccessible(true);
                    createEventAnalyzedMethod.invoke(hwNsdImplObject);
                    // 获取真正的EventAnalyzed对象
                    Field mEventAnalyzedFiled = hwNsdImplClass.getDeclaredField("mEventAnalyzed");
                    mEventAnalyzedFiled.setAccessible(true);
                    //检查是否为静态属性
                    boolean static_access=false;
                    Object oldFactory =null;
                    try {
                        oldFactory=mEventAnalyzedFiled.get(null);
                        static_access=true;
                    }catch (Exception e){
                    }
                    if (oldFactory==null){
                        static_access=false;
                        oldFactory= mEventAnalyzedFiled.get(hwNsdImplObject);
                    }
                    // 构建IEventAnalyzed的代理对类
                    Class<?> iEventAnalyzedClass = Class.forName("com.huawei.android.hwaps.IEventAnalyzed");
                    Object proxyFactory = CommonProxy.startHook(oldFactory, iEventAnalyzedClass, new ProxyCallBack() {
                        @Override
                        public Object interrupt(CommonProxy proxy, Method method, Object[] args) throws Throwable {
                            Object result = null;
                            if (method.getName().equals("processAnalyze")) {
                                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && Build.VERSION.SDK_INT <= Build.VERSION_CODES.O_MR1) {
                                    //6.0到8.1的版本上屏蔽该方法的调用
                                    Log.i(TAG, " interrupt huawei processAnalyze method ");
                                } else {
                                    result = proxy.doRealInvoke(method, args);
                                }
                            } 
                            //...
							else {
                                result = proxy.doRealInvoke(method, args);
                            }
                            return result;
                        }
                    });
                    if (!static_access){
                        mEventAnalyzedFiled.set(hwNsdImplObject, proxyFactory);
                    }else {
                        mEventAnalyzedFiled.set(null,proxyFactory);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 构建一个通用的代理类
     */
    public static class CommonProxy implements InvocationHandler {
        protected Object oldObject;
        protected ProxyCallBack callBack;

        private CommonProxy(Object oldFactory, ProxyCallBack callBack) {
            this.oldObject = oldFactory;
            this.callBack = callBack;
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            return callBack != null ? callBack.interrupt(this, method, args) : doRealInvoke(method, args);
        }

        /**
         * 调用原本的逻辑,继续走下去
         *
         * @param method
         * @param args
         * @return
         * @throws Throwable
         */
        public Object doRealInvoke(Method method, Object[] args) throws Throwable {
            return method.invoke(oldObject, args);
        }

        public static Object startHook(Object oldFactory, Class<?> interfaceClass, ProxyCallBack callBack) throws Exception {
            return Proxy.newProxyInstance(HuaWeiHook.class.getClassLoader(), new Class[]{interfaceClass}, new CommonProxy(oldFactory, callBack));
        }
    }

    public static interface ProxyCallBack {
        Object interrupt(CommonProxy proxy, Method method, Object[] args) throws Throwable;
    }
}

4.处理华为Framework中的其他问题(空指针)

另外一个问题:

java.lang.NullPointerException
Attempt to invoke interface method 'java.util.Iterator java.util.List.iterator()' on a null object reference
com.huawei.android.hwaps.EventAnalyzed.isBackground(EventAnalyzed.java:1932)
com.huawei.android.hwaps.EventAnalyzed$1.run(EventAnalyzed.java:1956)
android.os.Handler.handleCallback(Handler.java:743)
android.os.Handler.dispatchMessage(Handler.java:95)
android.os.Looper.loop(Looper.java:150)
android.app.ActivityThread.main(ActivityThread.java:5621)
java.lang.reflect.Method.invoke(Native Method)
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:794)
com.android.internal.os.ZygoteInit.main(ZygoteInit.java:684)

通过一些列的反向逆推,找到调用链接。调用链接:EventAnalyzed#setHasOnPaused()->EventAnalyzed#checkBackground()->EventAnalyzed#isBackground()

先来看下, com/huawei/android/hwaps/EventAnalyzed#setHasOnPaused()

 public void setHasOnPaused(boolean hasOnPaused) {
        boolean haspause = mHasOnPaused;
        mHasOnPaused = hasOnPaused;
        checkBackground();
        if (mApsThermal != null) {
            mApsThermal.stop();
        } else {
            ApsCommon.logI(TAG, "setHasOnPaused-ApsThermal is null");
        }
        if (mApsUserFeedback != null) {
            mApsUserFeedback.stop();
        } else {
            ApsCommon.logI(TAG, "setHasOnPaused-ApsUserFeedback is null");
        }
        //...  
}

接下来看下checkBackground()

    private void checkBackground() {
        new Handler().postDelayed(new Runnable() {// 通过handler 延迟执行
            public void run() {
                if (EventAnalyzed.this.isBackground() && EventAnalyzed.mSdrController != null) {
                    ApsCommon.logI(EventAnalyzed.TAG, "SDR: stop SDR because the package is in background");
                    EventAnalyzed.mSdrController.stopSdrImmediately();
                    EventAnalyzed.this.mHasSetSdr = false;
                }
            }
        }, 0);
    }

接下来看下,isBackground():

    public boolean isBackground() {
        if (mActivityManager == null) {
            return false;
        }
        for (RunningAppProcessInfo appProcess : mActivityManager.getRunningAppProcesses()) {// 报错点,在这里,返回list 为空
            if (appProcess.processName.equals(mPkgName) && appProcess.importance != 100) {
                ApsCommon.logD(TAG, "SDR: The pkg is in Background and pkg: " + mPkgName);
                return true;
            }
        }
        ApsCommon.logD(TAG, "SDR: The pkg is not in Background and pkg: " + mPkgName);
        return false;
    }

解决方法
也是采用hook 方式,拦截IEventAnalyzed 是一个接口,可以考虑动态代理掉setHasOnPaused().

再结合报错的机型,如下:

在这里插入图片描述

关键代码

        else if (method.getName().equals("setHasOnPaused")) {
                      
                            //EventAnalyzed#setHasOnPaused->EventAnalyzed#checkBackground()->EventAnalyzed#isBackground()
                            if (Build.VERSION_CODES.M == Build.VERSION.SDK_INT) {
                                // 在 华为机型的android 6.0 屏蔽该方法的调用
                            } else {
                                result = proxy.doRealInvoke(method, args);
                            }
        }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值