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

Commit 85baffad authored by Angela Wang's avatar Angela Wang
Browse files

Stop updating BT devices event history if user is categorized

Once the user is categorized as one of the interested group, there's no
need to update and maintain the event history. Clear the history and
stop monitoring the new events if user is already categorized.

Bug: 294627726
Test: atest CachedBluetoothDeviceTest
Test: atest HearingAidStatsLogUtilsTest
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:314e23af09ce3b8bd310bd110ef987fd95404be5)

Change-Id: I4e503533b57619e9c01a549b61af8c7262e4c877
parent eb7e15be
Loading
Loading
Loading
Loading
+32 −24
Original line number Diff line number Diff line
@@ -278,10 +278,13 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
                mLocalNapRoleConnected = false;
            }

            if (!HearingAidStatsLogUtils.isUserCategorized(mContext)) {
                if (HearingAidStatsLogUtils.isJustBonded(getAddress())) {
                // Saves bonded timestamp as the source for judging whether to display the survey
                    // Saves bonded timestamp as the source for judging whether to display
                    // the survey
                    if (getProfiles().stream().anyMatch(
                        p -> (p instanceof HearingAidProfile || p instanceof HapClientProfile))) {
                            p -> (p instanceof HearingAidProfile
                                    || p instanceof HapClientProfile))) {
                        HearingAidStatsLogUtils.addCurrentTimeToHistory(mContext,
                                HearingAidStatsLogUtils.HistoryType.TYPE_HEARING_AIDS_PAIRED);
                    } else if (getProfiles().stream().anyMatch(
@@ -292,9 +295,11 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
                    HearingAidStatsLogUtils.removeFromJustBonded(getAddress());
                }

            // Saves connected timestamp as the source for judging whether to display the survey
                // Saves connected timestamp as the source for judging whether to display
                // the survey
                if (newProfileState == BluetoothProfile.STATE_CONNECTED) {
                if (profile instanceof HearingAidProfile || profile instanceof HapClientProfile) {
                    if (profile instanceof HearingAidProfile
                            || profile instanceof HapClientProfile) {
                        HearingAidStatsLogUtils.addCurrentTimeToHistory(mContext,
                                HearingAidStatsLogUtils.HistoryType.TYPE_HEARING_AIDS_CONNECTED);
                    } else if (profile instanceof A2dpSinkProfile
@@ -304,6 +309,7 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
                    }
                }
            }
        }

        fetchActiveDevices();
    }
@@ -926,11 +932,13 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
                connect();
            }

            // Saves this device as just bonded and checks if it's an hearing device after profiles
            // are connected. This is for judging whether to display the survey.
            if (!HearingAidStatsLogUtils.isUserCategorized(mContext)) {
                // Saves this device as just bonded and checks if it's an hearing device after
                // profiles are connected. This is for judging whether to display the survey.
                HearingAidStatsLogUtils.addToJustBonded(getAddress());
            }
        }
    }

    public Timestamp getBondTimestamp() {
        return mBondTimestamp;
+88 −5
Original line number Diff line number Diff line
@@ -51,7 +51,18 @@ public final class HearingAidStatsLogUtils {
            "bt_hearing_devices_paired_history";
    private static final String BT_HEARING_DEVICES_CONNECTED_HISTORY =
            "bt_hearing_devices_connected_history";
    private static final String BT_HEARING_USER_CATEGORY = "bt_hearing_user_category";

    private static final String HISTORY_RECORD_DELIMITER = ",";
    private static final String CATEGORY_HEARING_AIDS = "A11yHearingAidsUser";
    private static final String CATEGORY_NEW_HEARING_AIDS = "A11yNewHearingAidsUser";
    private static final String CATEGORY_HEARING_DEVICES = "A11yHearingDevicesUser";
    private static final String CATEGORY_NEW_HEARING_DEVICES = "A11yNewHearingDevicesUser";

    private static final long PAIRED_HISTORY_EXPIRED_TIME = TimeUnit.DAYS.toMillis(30);
    private static final long CONNECTED_HISTORY_EXPIRED_TIME = TimeUnit.DAYS.toMillis(7);
    private static final int VALID_PAIRED_EVENT_COUNT = 1;
    private static final int VALID_CONNECTED_EVENT_COUNT = 7;

    /**
     * Type of different Bluetooth device events history related to hearing.
@@ -114,6 +125,78 @@ public final class HearingAidStatsLogUtils {
        return sDeviceAddressToBondEntryMap;
    }

    /**
     * Indicates if user is categorized as one of {@link #CATEGORY_HEARING_AIDS},
     * {@link #CATEGORY_NEW_HEARING_AIDS}, {@link #CATEGORY_HEARING_DEVICES}, and
     * {@link #CATEGORY_NEW_HEARING_DEVICES}.
     *
     * @param context the request context
     * @return true if user is already categorized as one of interested group
     */
    public static boolean isUserCategorized(Context context) {
        String userCategory = getSharedPreferences(context).getString(BT_HEARING_USER_CATEGORY, "");
        return !userCategory.isEmpty();
    }

    /**
     * Returns the user category if the user is already categorized. Otherwise, checks the
     * history and sees if the user is categorized as one of {@link #CATEGORY_HEARING_AIDS},
     * {@link #CATEGORY_NEW_HEARING_AIDS}, {@link #CATEGORY_HEARING_DEVICES}, and
     * {@link #CATEGORY_NEW_HEARING_DEVICES}.
     *
     * @param context the request context
     * @return the category which user belongs to
     */
    public static synchronized String getUserCategory(Context context) {
        String userCategory = getSharedPreferences(context).getString(BT_HEARING_USER_CATEGORY, "");
        if (!userCategory.isEmpty()) {
            return userCategory;
        }

        LinkedList<Long> hearingAidsConnectedHistory = getHistory(context,
                HistoryType.TYPE_HEARING_AIDS_CONNECTED);
        if (hearingAidsConnectedHistory != null
                && hearingAidsConnectedHistory.size() >= VALID_CONNECTED_EVENT_COUNT) {
            LinkedList<Long> hearingAidsPairedHistory = getHistory(context,
                    HistoryType.TYPE_HEARING_AIDS_PAIRED);
            // Since paired history will be cleared after 30 days. If there's any record within 30
            // days, the user will be categorized as CATEGORY_NEW_HEARING_AIDS. Otherwise, the user
            // will be categorized as CATEGORY_HEARING_AIDS.
            if (hearingAidsPairedHistory != null
                    && hearingAidsPairedHistory.size() >= VALID_PAIRED_EVENT_COUNT) {
                userCategory = CATEGORY_NEW_HEARING_AIDS;
            } else {
                userCategory = CATEGORY_HEARING_AIDS;
            }
        }

        LinkedList<Long> hearingDevicesConnectedHistory = getHistory(context,
                HistoryType.TYPE_HEARING_DEVICES_CONNECTED);
        if (hearingDevicesConnectedHistory != null
                && hearingDevicesConnectedHistory.size() >= VALID_CONNECTED_EVENT_COUNT) {
            LinkedList<Long> hearingDevicesPairedHistory = getHistory(context,
                    HistoryType.TYPE_HEARING_DEVICES_PAIRED);
            // Since paired history will be cleared after 30 days. If there's any record within 30
            // days, the user will be categorized as CATEGORY_NEW_HEARING_DEVICES. Otherwise, the
            // user will be categorized as CATEGORY_HEARING_DEVICES.
            if (hearingDevicesPairedHistory != null
                    && hearingDevicesPairedHistory.size() >= VALID_PAIRED_EVENT_COUNT) {
                userCategory = CATEGORY_NEW_HEARING_DEVICES;
            } else {
                userCategory = CATEGORY_HEARING_DEVICES;
            }
        }

        if (!userCategory.isEmpty()) {
            // History become useless once user is categorized. Clear all history.
            SharedPreferences.Editor editor = getSharedPreferences(context).edit();
            editor.putString(BT_HEARING_USER_CATEGORY, userCategory).apply();
            clearHistory(context);
            sJustBondedDeviceAddressSet.clear();
        }
        return userCategory;
    }

    /**
     * Maintains a temporarily list of just bonded device address. After the device profiles are
     * connected, {@link HearingAidStatsLogUtils#removeFromJustBonded} will be called to remove the
@@ -145,7 +228,7 @@ public final class HearingAidStatsLogUtils {
     * Clears all BT hearing devices related history stored in shared preference.
     * @param context the request context
     */
    public static synchronized void clearHistory(Context context) {
    private static synchronized void clearHistory(Context context) {
        SharedPreferences.Editor editor = getSharedPreferences(context).edit();
        editor.remove(BT_HEARING_AIDS_PAIRED_HISTORY)
                .remove(BT_HEARING_AIDS_CONNECTED_HISTORY)
@@ -192,25 +275,25 @@ public final class HearingAidStatsLogUtils {
                || BT_HEARING_DEVICES_PAIRED_HISTORY.equals(spName)) {
            LinkedList<Long> history = convertToHistoryList(
                    getSharedPreferences(context).getString(spName, ""));
            removeRecordsBeforeDays(history, 30);
            removeRecordsBeforeTime(history, PAIRED_HISTORY_EXPIRED_TIME);
            return history;
        } else if (BT_HEARING_AIDS_CONNECTED_HISTORY.equals(spName)
                || BT_HEARING_DEVICES_CONNECTED_HISTORY.equals(spName)) {
            LinkedList<Long> history = convertToHistoryList(
                    getSharedPreferences(context).getString(spName, ""));
            removeRecordsBeforeDays(history, 7);
            removeRecordsBeforeTime(history, CONNECTED_HISTORY_EXPIRED_TIME);
            return history;
        }
        return null;
    }

    private static void removeRecordsBeforeDays(LinkedList<Long> history, int days) {
    private static void removeRecordsBeforeTime(LinkedList<Long> history, long time) {
        if (history == null) {
            return;
        }
        Long currentTime = System.currentTimeMillis();
        while (history.peekFirst() != null
                && currentTime - history.peekFirst() > TimeUnit.DAYS.toMillis(days)) {
                && currentTime - history.peekFirst() > time) {
            history.poll();
        }
    }