Aplicación de gestión de ahorro de energía de Android Sprd (5) gestión de red en espera

La red de datos en espera controlará la frecuencia de acceso a los datos en segundo plano de la aplicación, lo que reducirá el consumo de energía en espera. Tiene como objetivo la optimización del acceso frecuente de la red al fondo de la aplicación.

Para optimizar el consumo de energía de la red en espera, primero se debe capturar el estado de la aplicación

Existe un enlazador IUidObserver en el marco

oneway interface IUidObserver {
    /**
     * General report of a state change of an uid.
     *
     * @param uid The uid for which the state change is being reported.
     * @param procState The updated process state for the uid.
     * @param procStateSeq The sequence no. associated with process state change of the uid,
     *                     see UidRecord.procStateSeq for details.
     */
    void onUidStateChanged(int uid, int procState, long procStateSeq);

    /**
     * Report that there are no longer any processes running for a uid.
     */
    void onUidGone(int uid, boolean disabled);

    /**
     * Report that a uid is now active (no longer idle).
     */
    void onUidActive(int uid);

    /**
     * Report that a uid is idle -- it has either been running in the background for
     * a sufficient period of time, or all of its processes have gone away.
     */
    void onUidIdle(int uid, boolean disabled);

    /**
     * Report when the cached state of a uid has changed.
     * If true, a uid has become cached -- that is, it has some active processes that are
     * all in the cached state.  It should be doing as little as possible at this point.
     * If false, that a uid is no longer cached.  This will only be called after
     * onUidCached() has been reported true.  It will happen when either one of its actively
     * running processes is no longer cached, or it no longer has any actively running processes.
     */
    void onUidCachedChanged(int uid, boolean cached);
}

La solución de Spreadtrum es monitorear el método onUidGone. ¿Por qué no usas onUidIdle? Aún no lo entiendo. Comprendamos por el momento que cuando se llama a onUidGone, significa que la aplicación ha entrado en modo adle. A continuación, Procederé al análisis de onUidGone

PowerController.java -> onUidGone ()

        @Override public void onUidGone(int uid, boolean disabled) throws RemoteException {
            synchronized (mUidStateLock) {
                removeUidStateLocked(uid);
            }
            mAppStateInfoCollector.removeUidState(uid);
        }

PowerController.java -> updateUidStateLocked ()

    private void removeUidStateLocked(int uid) {
        final int index = mUidState.indexOfKey(uid);
        if (index >= 0) {
            final int oldUidState = mUidState.valueAt(index);
            mUidState.removeAt(index);
            String appName = null;
            try {
                appName = AppGlobals.getPackageManager().getNameForUid(uid);
            } catch (RemoteException e) {
                // can't happen; package manager is process-local
            }
            if (DEBUG_MORE) Slog.d(TAG, "removeUidStateLocked: packageName:" + appName + ", uid:" + uid + " state : "  + Util.ProcState2Str(oldUidState));

            if ((null != appName) ) {
                msgHandler.sendMessage(msgHandler.obtainMessage(MSG_UID_STATE_CHANGED, uid, ActivityManager.PROCESS_STATE_CACHED_EMPTY, appName));
                // Fot PowerHint
                if (mBackgroundCleanHelper != null) {
                    mBackgroundCleanHelper.noteAppStopped(uid, appName);
                }
            }
        }
    }

Enviar MSG_UID_STATE_CHANGED

            case MSG_UID_STATE_CHANGED:
                handleProcStateChanged((String)msg.obj, msg.arg1, msg.arg2);
                break;

PowerController.java -> handleProcStateChanged ()

    private void handleProcStateChanged(String appName, int uid, int procState) {
        if (DEBUG) Slog.d(TAG, "- handleProcstateChanged() E - packageName:" + appName
            + " uid:" + uid + " procState:" + Util.ProcState2Str(procState));

        if (mAppStateInfoCollector.reportAppProcStateInfo(appName, uid, procState)) {
            // Note: Bug 698133 appIdle cts fail -->BEG
            // Ugly: we have to check if doing cts/gts test
            // is cts/gts test, then
            checkCtsGtsTesting(appName);
            // Note: Bug 698133 appIdle cts fail <--END
        }

        int userId = UserHandle.getUserId(uid);
        AppState appState = mAppStateInfoCollector.getAppState(appName, userId);

        if (appState == null) {
            Slog.w(TAG, "null appState for packageName:" + appName
                + " uid:" + uid + " procState:" + Util.ProcState2Str(procState));
            return;
        }

        // if app is stopped, notify WakelockConstraintHelper
        if (appState.mProcState == ActivityManager.PROCESS_STATE_CACHED_EMPTY) {
            appState.updateAppState(Event.NONE);
            mWakelockConstraintHelper.noteAppStopped(appState);
        }

        mRecogAlgorithm.reportEvent(appName, uid, RecogAlgorithm.EVENT_TYPE_PROC_STATE, procState);

        if (mCharging || mScreenOn)
            return;


        // recode the rxBytes if needed
        // should be called before doing Evaluated time stamp update
        appState.updateAppTrafficStats(false);

        // notify helpers to update time stamp
        updateAppEvaluatedTimeStamp(appState);

        // Note: Bug#695969 Audio Recoder fail --> BEG
        // if new procState is <= PROCESS_STATE_FOREGROUND_SERVICE
        // then update its Notification state
        if (procState <= ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE) {
            appState.updateActiveNotificationState(mContext);
        }
        // Note: Bug#695969 Audio Recoder fail <-- END

        msgHandler.removeMessages(MSG_CHECK);
        msgHandler.sendMessage(msgHandler.obtainMessage(MSG_CHECK));
        cancelAlarmLocked();
    }

Enviar MSG_CHECK

            case MSG_CHECK:
                checkAllAppStateInfo();
                break;

PowerController.java -> checkAllAppStateInfo ()

    private void checkAllAppStateInfo() {
        if (DEBUG) Slog.d(TAG, "- checkAllAppStateInfo() E -");
        if (DEBUG) Slog.d(TAG, "mCharging:" + mCharging + " mScreenOn:" + mScreenOn + " mMobileConnected:" + mMobileConnected);

        //set next check
        //msgHandler.removeMessages(MSG_CHECK);
        //msgHandler.sendMessageDelayed(msgHandler.obtainMessage(MSG_CHECK), CHECK_INTERVAL);
        scheduleAlarmLocked(CHECK_INTERVAL);

        if (mCharging || mScreenOn)
            return;

        checkSystemUpTime();

        boolean bChanged = false;
        // Note:use the same now elapsed time for all the AppStateInfo
        // otherwise, when checking app Parole, some app may have not
        // opportunity to exit app standby.
        long now = SystemClock.elapsedRealtime();

        updatePowerSaveMode();

        try {
            final List<UserInfo> users = mUserManager.getUsers();
            for (int ui = users.size() - 1; ui >= 0; ui--) {
                UserInfo user = users.get(ui);
                if (DEBUG) Slog.d(TAG, "- checkAllAppStateInfo() for user: " + user.id);

                final ArrayMap<String, AppState> appStateInfoList = mAppStateInfoCollector.getAppStateInfoList(user.id);
                for (int i=0;i<appStateInfoList.size();i++) {
                    AppState appState = appStateInfoList.valueAt(i);

                    //let app to be parole
                    mAppIdleHelper.checkAppParole(appState, now);

                    // check app state info
                    if (checkAppStateInfo(appState, now)) {
                        bChanged = true;
                    }
                }
            }
        } catch (Exception e) {
        }

        // note AppidleHelper all check done
        mAppIdleHelper.noteCheckAllAppStateInfoDone();
        // note mWakelockConstraintHelper all check done
        mWakelockConstraintHelper.noteCheckAllAppStateInfoDone();

        //send notification to powerguru & appstandby
        // changed for bug#891620
        //if (bChanged) msgHandler.sendMessage(msgHandler.obtainMessage(MSG_NOTIFY_CHANGED));
        if (bChanged) notifyChanged();

        if (needCheckNetworkConnection(now)) {
            if (DEBUG) Slog.d(TAG, "- checkNetworkConnection() in checkAllAppStateInfo -");
            checkNetworkConnection(true);
        }

        // check doze state
        checkDozeState();
    }

PowerController.java -> notificarChanged ()

    private void notifyChanged() {
        if (DEBUG) Slog.d(TAG, "- notifyChanged() E -");

        for (int i = 0; i < mHelpers.size(); i++) {
            PowerSaveHelper helper = mHelpers.get(i);
            helper.applyConstrain();
        }
    }

AppIdleHelper hereda PowerSaveHelper

AppIdleHelper.java -> applyConstrain ()

    @Override
    void applyConstrain() {

        for (int index=mNewStandbyListForUsers.size()-1; index>=0; index--) {
            ArrayMap<String, Integer> mNewStandbyList = mNewStandbyListForUsers.valueAt(index);

            for (int i=0;i<mNewStandbyList.size();i++) {
                try {
                    if (DEBUG) Slog.d(TAG, "packageName:" + mNewStandbyList.keyAt(i)
                        + " userId:" + mNewStandbyList.valueAt(i) + " enter standby");
                    int userId = mNewStandbyList.valueAt(i);
                    setAppInactive(mNewStandbyList.keyAt(i), true, userId);
                    updateAppStandbyState(mNewStandbyList.keyAt(i), true, userId);
                } catch (Exception e) {
                    // fall through
                }
            }
            mNewStandbyList.clear();

        }
    }

AppIdleHelper.java -> setAppInactive ()

    private void setAppInactive(String packageName, boolean idle, int userId) {
        if (!mPowerControllerAppIdleEnabled || mUsageStatsInternal == null) return;

        mUsageStatsInternal.setAppInactive(packageName, idle, userId);
    }

UsageStatsManagerInternal es una clase abstracta. La clase interna LocalService de UsageStatsService hereda UsageStatsManagerInternal. UsageStatsService es un servicio privado de Android que se utiliza para contar el uso de aplicaciones. La función principal es recopilar la frecuencia y el tiempo de uso de cada aplicación utilizada por los usuarios.

UsageStatsService.java -> LocalService -> setAppInactive ()

        @Override
        public void setAppInactive(String packageName, boolean idle, int userId) {
            if (mPowerControllerHelper != null)
                mPowerControllerHelper.setAppInactive(packageName, idle, userId);
        }

UsageStatsService.java -> setAppInactive ()

        public void setAppInactive(String packageName, boolean idle, int userId) {
            try {
                PackageInfo pi = AppGlobals.getPackageManager()
                        .getPackageInfo(packageName, 0, userId);
                if (pi == null) return;
                UsageStatsService.this.setAppIdleAsync(packageName, idle, userId);
                setAppForceIdleFlag(packageName, idle, userId);
            } catch (RemoteException re) {
            } finally {
            }
        }


UsageStatsService.java -> setAppIdleAsync ()

    void setAppIdleAsync(String packageName, boolean idle, int userId) {
        if (packageName == null) return;

        mHandler.obtainMessage(MSG_FORCE_IDLE_STATE, userId, idle ? 1 : 0, packageName)
                .sendToTarget();
    }

Enviar MSG_FORCE_IDLE_STATE


                case MSG_FORCE_IDLE_STATE:
                    forceIdleState((String) msg.obj, msg.arg1, msg.arg2 == 1);
                    break;

UsageStatsService.java -> forceIdleState ()

    void forceIdleState(String packageName, int userId, boolean idle) {
        final int appId = getAppId(packageName);
        if (appId < 0) return;
        final long elapsedRealtime = SystemClock.elapsedRealtime();

        final boolean previouslyIdle = isAppIdleFiltered(packageName, appId,
                userId, elapsedRealtime);
        synchronized (mAppIdleLock) {
            mAppIdleHistory.setIdle(packageName, userId, idle, elapsedRealtime);
        }
        final boolean stillIdle = isAppIdleFiltered(packageName, appId,
                userId, elapsedRealtime);
        // Inform listeners if necessary
        if (previouslyIdle != stillIdle) {
            mHandler.sendMessage(mHandler.obtainMessage(MSG_INFORM_LISTENERS, userId,
                    /* idle = */ stillIdle ? 1 : 0, packageName));
            if (!stillIdle) {
                notifyBatteryStats(packageName, userId, idle);
            }
        }
    }

Enviar MSG_INFORM_LISTENERS

                case MSG_INFORM_LISTENERS:
                    informListeners((String) msg.obj, msg.arg1, msg.arg2 == 1);
                    break;

UsageStatsService.java -> informListeners ()

    void informListeners(String packageName, int userId, boolean isIdle) {
        for (AppIdleStateChangeListener listener : mPackageAccessListeners) {
            listener.onAppIdleStateChanged(packageName, userId, isIdle);
        }
    }

La clase interna AppIdleStateChangeListener de NetworkPolicyManagerService hereda UsageStatsManagerInternal.AppIdleStateChangeListener

    private class AppIdleStateChangeListener
            extends UsageStatsManagerInternal.AppIdleStateChangeListener {

        @Override
        public void onAppIdleStateChanged(String packageName, int userId, boolean idle) {
            try {
                final int uid = mContext.getPackageManager().getPackageUidAsUser(packageName,
                        PackageManager.MATCH_UNINSTALLED_PACKAGES, userId);
                if (LOGV) Log.v(TAG, "onAppIdleStateChanged(): uid=" + uid + ", idle=" + idle);
                synchronized (mUidRulesFirstLock) {
                    updateRuleForAppIdleUL(uid);
                    updateRulesForPowerRestrictionsUL(uid);
                }
            } catch (NameNotFoundException nnfe) {
            }
        }
        ......
    }

NetworkPolicyManagerService.java -> updateRuleForAppIdleUL ()

    void updateRuleForAppIdleUL(int uid) {
        if (!isUidValidForBlacklistRules(uid)) return;

        // NOTE: Bug #693427 low power Feature BEG -->
        boolean ignoreProcState = PowerControllerHelper.getInstance(mContext).ignoreProcStateForAppIdle();
        // <-- NOTE: Bug #693427 low power Feature END

        if (Trace.isTagEnabled(Trace.TRACE_TAG_NETWORK)) {
            Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "updateRuleForAppIdleUL: " + uid );
        }
        try {
            int appId = UserHandle.getAppId(uid);
            if (!mPowerSaveTempWhitelistAppIds.get(appId) && isUidIdle(uid)
                    && (ignoreProcState || !isUidForegroundOnRestrictPowerUL(uid))) {
                setUidFirewallRule(FIREWALL_CHAIN_STANDBY, uid, FIREWALL_RULE_DENY);
            } else {
                setUidFirewallRule(FIREWALL_CHAIN_STANDBY, uid, FIREWALL_RULE_DEFAULT);
            }
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
        }
    }

NetworkPolicyManagerService.java -> setUidFirewallRule ()

    /**
     * Add or remove a uid to the firewall blacklist for all network ifaces.
     */
    private void setUidFirewallRule(int chain, int uid, int rule) {
        if (Trace.isTagEnabled(Trace.TRACE_TAG_NETWORK)) {
            Trace.traceBegin(Trace.TRACE_TAG_NETWORK,
                    "setUidFirewallRule: " + chain + "/" + uid + "/" + rule);
        }
        try {
            if (chain == FIREWALL_CHAIN_DOZABLE) {
                mUidFirewallDozableRules.put(uid, rule);
            } else if (chain == FIREWALL_CHAIN_STANDBY) {
                mUidFirewallStandbyRules.put(uid, rule);
            } else if (chain == FIREWALL_CHAIN_POWERSAVE) {
                mUidFirewallPowerSaveRules.put(uid, rule);
            }

            try {
                mNetworkManager.setFirewallUidRule(chain, uid, rule);
            } catch (IllegalStateException e) {
                Log.wtf(TAG, "problem setting firewall uid rules", e);
            } catch (RemoteException e) {
                // ignored; service lives in system_server
            }
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
        }
    }

NetworkManagementService.java -> setFirewallUidRule ()


    @Override
    public void setFirewallUidRule(int chain, int uid, int rule) {
        enforceSystemUid();
        synchronized (mQuotaLock) {
            setFirewallUidRuleLocked(chain, uid, rule);
        }
    }

NetworkManagementService.java -> setFirewallUidRuleLocked ()

    private void setFirewallUidRuleLocked(int chain, int uid, int rule) {
        if (updateFirewallUidRuleLocked(chain, uid, rule)) {
            try {
                mConnector.execute("firewall", "set_uid_rule", getFirewallChainName(chain), uid,
                        getFirewallRuleName(chain, rule));
            } catch (NativeDaemonConnectorException e) {
                throw e.rethrowAsParcelableException();
            }
        }
    }

 

Supongo que te gusta

Origin blog.csdn.net/liu362732346/article/details/86494730
Recomendado
Clasificación