Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7fcf5f95 authored by Rafael Higuera Silva's avatar Rafael Higuera Silva
Browse files

Add fold state to service state

Bug: 276772849
Test: make, atest com.android.internal.telephony.metrics and manual test
Change-Id: I62ff6fb1be3aef6ac9044990b78094025da1da73
Merged-In: I62ff6fb1be3aef6ac9044990b78094025da1da73
parent d92836c6
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -274,6 +274,7 @@ message VoiceCallSession {
    optional bool is_multiparty = 31;
    optional int32 call_duration = 32;
    optional int32 last_known_rat = 33;

    // Internal use only
    optional int64 setup_begin_millis = 10001;
}
@@ -375,6 +376,7 @@ message CellularServiceState {
    optional int64 total_time_millis = 9; // Duration needs to be rounded when pulled
    optional bool is_emergency_only = 10;
    optional bool is_internet_pdn_up = 11;
    optional int32 fold_state = 12;

    // Internal use only
    optional int64 last_used_millis = 10001;
+77 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.internal.telephony.metrics;

import static com.android.internal.telephony.TelephonyStatsLog.CELLULAR_SERVICE_STATE__FOLD_STATE__STATE_CLOSED;
import static com.android.internal.telephony.TelephonyStatsLog.CELLULAR_SERVICE_STATE__FOLD_STATE__STATE_FLIPPED;
import static com.android.internal.telephony.TelephonyStatsLog.CELLULAR_SERVICE_STATE__FOLD_STATE__STATE_HALF_OPENED;
import static com.android.internal.telephony.TelephonyStatsLog.CELLULAR_SERVICE_STATE__FOLD_STATE__STATE_OPENED;
import static com.android.internal.telephony.TelephonyStatsLog.CELLULAR_SERVICE_STATE__FOLD_STATE__STATE_UNKNOWN;

import android.content.Context;
import android.hardware.devicestate.DeviceStateManager;
import android.os.Handler;
import android.os.HandlerExecutor;
import android.os.HandlerThread;

import com.android.internal.telephony.Phone;

/** Device state information like the fold state. */
public class DeviceStateHelper {
    private int mFoldState = CELLULAR_SERVICE_STATE__FOLD_STATE__STATE_UNKNOWN;

    public DeviceStateHelper(Context context) {
        HandlerThread mHandlerThread = new HandlerThread("DeviceStateHelperThread");
        mHandlerThread.start();
        context.getSystemService(DeviceStateManager.class)
                .registerCallback(
                        new HandlerExecutor(new Handler(mHandlerThread.getLooper())),
                        state -> {
                            updateFoldState(state);
                        });
    }

    private void updateFoldState(int posture) {
        switch (posture) {
            case 0:
                mFoldState = CELLULAR_SERVICE_STATE__FOLD_STATE__STATE_CLOSED;
                break;
            case 1:
                mFoldState = CELLULAR_SERVICE_STATE__FOLD_STATE__STATE_HALF_OPENED;
                break;
            case 2:
                mFoldState = CELLULAR_SERVICE_STATE__FOLD_STATE__STATE_OPENED;
                break;
            case 4:
                mFoldState = CELLULAR_SERVICE_STATE__FOLD_STATE__STATE_FLIPPED;
                break;
            default:
                mFoldState = CELLULAR_SERVICE_STATE__FOLD_STATE__STATE_UNKNOWN;
        }
        updateServiceStateStats();
    }

    private void updateServiceStateStats() {
        for (Phone phone : MetricsCollector.getPhonesIfAny()) {
            phone.getServiceStateTracker().getServiceStateStats().onFoldStateChanged(mFoldState);
        }
    }

    public int getFoldState() {
        return mFoldState;
    }
}
+13 −5
Original line number Diff line number Diff line
@@ -145,20 +145,22 @@ public class MetricsCollector implements StatsManager.StatsPullAtomCallback {
            DBG ? 2L * MILLIS_PER_SECOND : 5L * MILLIS_PER_MINUTE;

    private final PersistAtomsStorage mStorage;
    private final DeviceStateHelper mDeviceStateHelper;
    private final StatsManager mStatsManager;
    private final AirplaneModeStats mAirplaneModeStats;
    private final Set<DataCallSessionStats> mOngoingDataCallStats = ConcurrentHashMap.newKeySet();
    private static final Random sRandom = new Random();

    public MetricsCollector(Context context) {
        this(context, new PersistAtomsStorage(context));
        this(context, new PersistAtomsStorage(context), new DeviceStateHelper(context));
    }

    /** Allows dependency injection. Used during unit tests. */
    @VisibleForTesting
    public MetricsCollector(Context context,
            PersistAtomsStorage storage) {
    public MetricsCollector(
            Context context, PersistAtomsStorage storage, DeviceStateHelper deviceStateHelper) {
        mStorage = storage;
        mDeviceStateHelper = deviceStateHelper;
        mStatsManager = (StatsManager) context.getSystemService(Context.STATS_MANAGER);
        if (mStatsManager != null) {
            // Most (but not all) of these are subject to cooldown specified by MIN_COOLDOWN_MILLIS.
@@ -299,6 +301,11 @@ public class MetricsCollector implements StatsManager.StatsPullAtomCallback {
        return mStorage;
    }

    /** Returns the {@link DeviceStateHelper}. */
    public DeviceStateHelper getDeviceStateHelper() {
        return mDeviceStateHelper;
    }

    /** Updates duration segments and calls {@link PersistAtomsStorage#flushAtoms()}. */
    public void flushAtomsStorage() {
        concludeAll();
@@ -915,7 +922,8 @@ public class MetricsCollector implements StatsManager.StatsPullAtomCallback {
                state.carrierId,
                roundAndConvertMillisToSeconds(state.totalTimeMillis),
                state.isEmergencyOnly,
                state.isInternetPdnUp);
                state.isInternetPdnUp,
                state.foldState);
    }

    private static StatsEvent buildStatsEvent(VoiceCallRatUsage usage) {
@@ -1316,7 +1324,7 @@ public class MetricsCollector implements StatsManager.StatsPullAtomCallback {
    }

    /** Returns all phones in {@link PhoneFactory}, or an empty array if phones not made yet. */
    private static Phone[] getPhonesIfAny() {
    static Phone[] getPhonesIfAny() {
        try {
            return PhoneFactory.getPhones();
        } catch (IllegalStateException e) {
+3 −2
Original line number Diff line number Diff line
@@ -1708,7 +1708,8 @@ public class PersistAtomsStorage {
                    && state.isMultiSim == key.isMultiSim
                    && state.carrierId == key.carrierId
                    && state.isEmergencyOnly == key.isEmergencyOnly
                    && state.isInternetPdnUp == key.isInternetPdnUp) {
                    && state.isInternetPdnUp == key.isInternetPdnUp
                    && state.foldState == key.foldState) {
                return state;
            }
        }
+24 −0
Original line number Diff line number Diff line
@@ -54,11 +54,13 @@ public class ServiceStateStats extends DataNetworkControllerCallback {
            new AtomicReference<>(new TimestampedServiceState(null, 0L));
    private final Phone mPhone;
    private final PersistAtomsStorage mStorage;
    private final DeviceStateHelper mDeviceStateHelper;

    public ServiceStateStats(Phone phone) {
        super(Runnable::run);
        mPhone = phone;
        mStorage = PhoneFactory.getMetricsCollector().getAtomsStorage();
        mDeviceStateHelper = PhoneFactory.getMetricsCollector().getDeviceStateHelper();
    }

    /** Finalizes the durations of the current service state segment. */
@@ -120,6 +122,7 @@ public class ServiceStateStats extends DataNetworkControllerCallback {
            newState.carrierId = mPhone.getCarrierId();
            newState.isEmergencyOnly = isEmergencyOnly(serviceState);
            newState.isInternetPdnUp = isInternetPdnUp(mPhone);
            newState.foldState = mDeviceStateHelper.getFoldState();
            TimestampedServiceState prevState =
                    mLastState.getAndSet(new TimestampedServiceState(newState, now));
            addServiceStateAndSwitch(
@@ -127,6 +130,26 @@ public class ServiceStateStats extends DataNetworkControllerCallback {
        }
    }

    /** Updates the fold state of the device for the current service state. */
    public void onFoldStateChanged(int foldState) {
        final long now = getTimeMillis();
        CellularServiceState lastServiceState = mLastState.get().mServiceState;
        if (lastServiceState == null || lastServiceState.foldState == foldState) {
            // Not need to update the fold state if modem is off or if is the
            // same fold state
            return;
        } else {
            TimestampedServiceState lastState =
                    mLastState.getAndUpdate(
                            state -> {
                                CellularServiceState newServiceState = copyOf(state.mServiceState);
                                newServiceState.foldState = foldState;
                                return new TimestampedServiceState(newServiceState, now);
                            });
            addServiceState(lastState, now);
        }
    }

    private void addServiceState(TimestampedServiceState prevState, long now) {
        addServiceStateAndSwitch(prevState, now, null);
    }
@@ -247,6 +270,7 @@ public class ServiceStateStats extends DataNetworkControllerCallback {
        copy.totalTimeMillis = state.totalTimeMillis;
        copy.isEmergencyOnly = state.isEmergencyOnly;
        copy.isInternetPdnUp = state.isInternetPdnUp;
        copy.foldState = state.foldState;
        return copy;
    }

Loading