Loading proto/src/persist_atoms.proto +12 −0 Original line number Diff line number Diff line Loading @@ -87,6 +87,12 @@ message PersistAtoms { /* Last Android build fingerprint. This usually changes after system OTA. */ optional string build_fingerprint = 21; /* Summary of received network requests. */ repeated NetworkRequests network_requests = 22; /* Timestamp of last network_requests pull. */ optional int64 network_requests_pull_timestamp_millis = 23; } // The canonical versions of the following enums live in: Loading Loading @@ -261,3 +267,9 @@ message ImsRegistrationStats { // Internal use only optional int64 last_used_millis = 10001; } message NetworkRequests { optional int32 carrier_id = 1; optional int32 enterprise_request_count = 2; optional int32 enterprise_release_count = 3; } src/java/com/android/internal/telephony/metrics/AirplaneModeStats.java +2 −1 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.internal.telephony.metrics; import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID; import static android.telephony.TelephonyManager.UNKNOWN_CARRIER_ID; import static com.android.internal.telephony.TelephonyStatsLog.AIRPLANE_MODE; Loading Loading @@ -113,6 +114,6 @@ public class AirplaneModeStats extends ContentObserver { int phoneId = dataSubId != INVALID_SUBSCRIPTION_ID ? SubscriptionManager.getPhoneId(dataSubId) : 0; Phone phone = PhoneFactory.getPhone(phoneId); return phone != null ? phone.getCarrierId() : INVALID_SUBSCRIPTION_ID; return phone != null ? phone.getCarrierId() : UNKNOWN_CARRIER_ID; } } src/java/com/android/internal/telephony/metrics/MetricsCollector.java +25 −0 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ import static com.android.internal.telephony.TelephonyStatsLog.INCOMING_SMS; import static com.android.internal.telephony.TelephonyStatsLog.OUTGOING_SMS; import static com.android.internal.telephony.TelephonyStatsLog.SIM_SLOT_STATE; import static com.android.internal.telephony.TelephonyStatsLog.SUPPORTED_RADIO_ACCESS_FAMILY; import static com.android.internal.telephony.TelephonyStatsLog.TELEPHONY_NETWORK_REQUESTS; import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_RAT_USAGE; import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION; Loading @@ -49,6 +50,7 @@ import com.android.internal.telephony.nano.PersistAtomsProto.DataCallSession; import com.android.internal.telephony.nano.PersistAtomsProto.ImsRegistrationStats; import com.android.internal.telephony.nano.PersistAtomsProto.ImsRegistrationTermination; import com.android.internal.telephony.nano.PersistAtomsProto.IncomingSms; import com.android.internal.telephony.nano.PersistAtomsProto.NetworkRequests; import com.android.internal.telephony.nano.PersistAtomsProto.OutgoingSms; import com.android.internal.telephony.nano.PersistAtomsProto.VoiceCallRatUsage; import com.android.internal.telephony.nano.PersistAtomsProto.VoiceCallSession; Loading Loading @@ -118,6 +120,7 @@ public class MetricsCollector implements StatsManager.StatsPullAtomCallback { registerAtom(DATA_CALL_SESSION, POLICY_PULL_DAILY); registerAtom(IMS_REGISTRATION_STATS, POLICY_PULL_DAILY); registerAtom(IMS_REGISTRATION_TERMINATION, POLICY_PULL_DAILY); registerAtom(TELEPHONY_NETWORK_REQUESTS, POLICY_PULL_DAILY); Rlog.d(TAG, "registered"); } else { Loading Loading @@ -167,6 +170,8 @@ public class MetricsCollector implements StatsManager.StatsPullAtomCallback { return pullImsRegistrationStats(data); case IMS_REGISTRATION_TERMINATION: return pullImsRegistrationTermination(data); case TELEPHONY_NETWORK_REQUESTS: return pullTelephonyNetworkRequests(data); default: Rlog.e(TAG, String.format("unexpected atom ID %d", atomTag)); return StatsManager.PULL_SKIP; Loading Loading @@ -363,6 +368,18 @@ public class MetricsCollector implements StatsManager.StatsPullAtomCallback { } } private int pullTelephonyNetworkRequests(List<StatsEvent> data) { NetworkRequests[] persistAtoms = mStorage.getNetworkRequests(MIN_COOLDOWN_MILLIS); if (persistAtoms != null) { Arrays.stream(persistAtoms) .forEach(persistAtom -> data.add(buildStatsEvent(persistAtom))); return StatsManager.PULL_SUCCESS; } else { Rlog.w(TAG, "TELEPHONY_NETWORK_REQUESTS pull too frequent, skipping"); return StatsManager.PULL_SKIP; } } /** Registers a pulled atom ID {@code atomId} with optional {@code policy} for pulling. */ private void registerAtom(int atomId, @Nullable StatsManager.PullAtomMetadata policy) { mStatsManager.setPullAtomCallback(atomId, policy, ConcurrentUtils.DIRECT_EXECUTOR, this); Loading Loading @@ -536,6 +553,14 @@ public class MetricsCollector implements StatsManager.StatsPullAtomCallback { termination.count); } private static StatsEvent buildStatsEvent(NetworkRequests networkRequests) { return TelephonyStatsLog.buildStatsEvent( TELEPHONY_NETWORK_REQUESTS, networkRequests.carrierId, networkRequests.enterpriseRequestCount, networkRequests.enterpriseReleaseCount); } /** Returns all phones in {@link PhoneFactory}, or an empty array if phones not made yet. */ private static Phone[] getPhonesIfAny() { try { Loading src/java/com/android/internal/telephony/metrics/NetworkRequestsStats.java 0 → 100644 +57 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 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 android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import com.android.internal.telephony.Phone; import com.android.internal.telephony.PhoneFactory; import com.android.internal.telephony.nano.PersistAtomsProto.NetworkRequests; /** Metrics for the network requests. */ public class NetworkRequestsStats { private NetworkRequestsStats() { } /** Generate metrics when enterprise network request occurs. */ public static void addEnterpriseRequest(int subId) { NetworkRequests networkRequests = new NetworkRequests(); networkRequests.carrierId = getCarrierId(subId); networkRequests.enterpriseRequestCount = 1; PersistAtomsStorage storage = PhoneFactory.getMetricsCollector().getAtomsStorage(); storage.addNetworkRequests(networkRequests); } /** Generate metrics when enterprise network release occurs. */ public static void addEnterpriseRelease(int subId) { NetworkRequests networkRequests = new NetworkRequests(); networkRequests.carrierId = getCarrierId(subId); networkRequests.enterpriseReleaseCount = 1; PersistAtomsStorage storage = PhoneFactory.getMetricsCollector().getAtomsStorage(); storage.addNetworkRequests(networkRequests); } /** Returns the carrier ID of the given subscription id. */ private static int getCarrierId(int subId) { int phoneId = SubscriptionManager.getPhoneId(subId); Phone phone = PhoneFactory.getPhone(phoneId); return phone != null ? phone.getCarrierId() : TelephonyManager.UNKNOWN_CARRIER_ID; } } src/java/com/android/internal/telephony/metrics/PersistAtomsStorage.java +49 −0 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ import com.android.internal.telephony.nano.PersistAtomsProto.DataCallSession; import com.android.internal.telephony.nano.PersistAtomsProto.ImsRegistrationStats; import com.android.internal.telephony.nano.PersistAtomsProto.ImsRegistrationTermination; import com.android.internal.telephony.nano.PersistAtomsProto.IncomingSms; import com.android.internal.telephony.nano.PersistAtomsProto.NetworkRequests; import com.android.internal.telephony.nano.PersistAtomsProto.OutgoingSms; import com.android.internal.telephony.nano.PersistAtomsProto.PersistAtoms; import com.android.internal.telephony.nano.PersistAtomsProto.VoiceCallRatUsage; Loading Loading @@ -299,6 +300,20 @@ public class PersistAtomsStorage { } } /** Adds a new {@link NetworkRequests} to the storage. */ public synchronized void addNetworkRequests(NetworkRequests networkRequests) { NetworkRequests existingMetrics = find(networkRequests); if (existingMetrics != null) { existingMetrics.enterpriseRequestCount += networkRequests.enterpriseRequestCount; existingMetrics.enterpriseReleaseCount += networkRequests.enterpriseReleaseCount; } else { int newLength = mAtoms.networkRequests.length + 1; mAtoms.networkRequests = Arrays.copyOf(mAtoms.networkRequests, newLength); mAtoms.networkRequests[newLength - 1] = networkRequests; } saveAtomsToFile(SAVE_TO_FILE_DELAY_FOR_UPDATE_MILLIS); } /** * Returns and clears the voice call sessions if last pulled longer than {@code * minIntervalMillis} ago, otherwise returns {@code null}. Loading Loading @@ -465,6 +480,23 @@ public class PersistAtomsStorage { } } /** * Returns and clears the network requests if last pulled longer than {@code * minIntervalMillis} ago, otherwise returns {@code null}. */ @Nullable public synchronized NetworkRequests[] getNetworkRequests(long minIntervalMillis) { if (getWallTimeMillis() - mAtoms.networkRequestsPullTimestampMillis > minIntervalMillis) { mAtoms.networkRequestsPullTimestampMillis = getWallTimeMillis(); NetworkRequests[] previousNetworkRequests = mAtoms.networkRequests; mAtoms.networkRequests = new NetworkRequests[0]; saveAtomsToFile(SAVE_TO_FILE_DELAY_FOR_GET_MILLIS); return previousNetworkRequests; } else { return null; } } /** Loads {@link PersistAtoms} from a file in private storage. */ private PersistAtoms loadAtomsFromFile() { try { Loading Loading @@ -515,6 +547,7 @@ public class PersistAtomsStorage { atoms.imsRegistrationTermination, ImsRegistrationTermination.class, MAX_NUM_IMS_REGISTRATION_TERMINATIONS); atoms.networkRequests = sanitizeAtoms(atoms.networkRequests, NetworkRequests.class); // out of caution, sanitize also the timestamps atoms.voiceCallRatUsagePullTimestampMillis = sanitizeTimestamp(atoms.voiceCallRatUsagePullTimestampMillis); Loading @@ -534,6 +567,8 @@ public class PersistAtomsStorage { sanitizeTimestamp(atoms.imsRegistrationStatsPullTimestampMillis); atoms.imsRegistrationTerminationPullTimestampMillis = sanitizeTimestamp(atoms.imsRegistrationTerminationPullTimestampMillis); atoms.networkRequestsPullTimestampMillis = sanitizeTimestamp(atoms.networkRequestsPullTimestampMillis); return atoms; } catch (NoSuchFileException e) { Rlog.d(TAG, "PersistAtoms file not found"); Loading Loading @@ -656,6 +691,19 @@ public class PersistAtomsStorage { return null; } /** * Returns the network requests event that has the same carrier id as the given one, * or {@code null} if it does not exist. */ private @Nullable NetworkRequests find(NetworkRequests key) { for (NetworkRequests item : mAtoms.networkRequests) { if (item.carrierId == key.carrierId) { return item; } } return null; } /** * Inserts a new element in a random position in an array with a maximum size, replacing the * least recent item if possible. Loading Loading @@ -745,6 +793,7 @@ public class PersistAtomsStorage { atoms.cellularDataServiceSwitchPullTimestampMillis = currentTime; atoms.imsRegistrationStatsPullTimestampMillis = currentTime; atoms.imsRegistrationTerminationPullTimestampMillis = currentTime; atoms.networkRequestsPullTimestampMillis = currentTime; Rlog.d(TAG, "created new PersistAtoms"); return atoms; } Loading Loading
proto/src/persist_atoms.proto +12 −0 Original line number Diff line number Diff line Loading @@ -87,6 +87,12 @@ message PersistAtoms { /* Last Android build fingerprint. This usually changes after system OTA. */ optional string build_fingerprint = 21; /* Summary of received network requests. */ repeated NetworkRequests network_requests = 22; /* Timestamp of last network_requests pull. */ optional int64 network_requests_pull_timestamp_millis = 23; } // The canonical versions of the following enums live in: Loading Loading @@ -261,3 +267,9 @@ message ImsRegistrationStats { // Internal use only optional int64 last_used_millis = 10001; } message NetworkRequests { optional int32 carrier_id = 1; optional int32 enterprise_request_count = 2; optional int32 enterprise_release_count = 3; }
src/java/com/android/internal/telephony/metrics/AirplaneModeStats.java +2 −1 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.internal.telephony.metrics; import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID; import static android.telephony.TelephonyManager.UNKNOWN_CARRIER_ID; import static com.android.internal.telephony.TelephonyStatsLog.AIRPLANE_MODE; Loading Loading @@ -113,6 +114,6 @@ public class AirplaneModeStats extends ContentObserver { int phoneId = dataSubId != INVALID_SUBSCRIPTION_ID ? SubscriptionManager.getPhoneId(dataSubId) : 0; Phone phone = PhoneFactory.getPhone(phoneId); return phone != null ? phone.getCarrierId() : INVALID_SUBSCRIPTION_ID; return phone != null ? phone.getCarrierId() : UNKNOWN_CARRIER_ID; } }
src/java/com/android/internal/telephony/metrics/MetricsCollector.java +25 −0 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ import static com.android.internal.telephony.TelephonyStatsLog.INCOMING_SMS; import static com.android.internal.telephony.TelephonyStatsLog.OUTGOING_SMS; import static com.android.internal.telephony.TelephonyStatsLog.SIM_SLOT_STATE; import static com.android.internal.telephony.TelephonyStatsLog.SUPPORTED_RADIO_ACCESS_FAMILY; import static com.android.internal.telephony.TelephonyStatsLog.TELEPHONY_NETWORK_REQUESTS; import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_RAT_USAGE; import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION; Loading @@ -49,6 +50,7 @@ import com.android.internal.telephony.nano.PersistAtomsProto.DataCallSession; import com.android.internal.telephony.nano.PersistAtomsProto.ImsRegistrationStats; import com.android.internal.telephony.nano.PersistAtomsProto.ImsRegistrationTermination; import com.android.internal.telephony.nano.PersistAtomsProto.IncomingSms; import com.android.internal.telephony.nano.PersistAtomsProto.NetworkRequests; import com.android.internal.telephony.nano.PersistAtomsProto.OutgoingSms; import com.android.internal.telephony.nano.PersistAtomsProto.VoiceCallRatUsage; import com.android.internal.telephony.nano.PersistAtomsProto.VoiceCallSession; Loading Loading @@ -118,6 +120,7 @@ public class MetricsCollector implements StatsManager.StatsPullAtomCallback { registerAtom(DATA_CALL_SESSION, POLICY_PULL_DAILY); registerAtom(IMS_REGISTRATION_STATS, POLICY_PULL_DAILY); registerAtom(IMS_REGISTRATION_TERMINATION, POLICY_PULL_DAILY); registerAtom(TELEPHONY_NETWORK_REQUESTS, POLICY_PULL_DAILY); Rlog.d(TAG, "registered"); } else { Loading Loading @@ -167,6 +170,8 @@ public class MetricsCollector implements StatsManager.StatsPullAtomCallback { return pullImsRegistrationStats(data); case IMS_REGISTRATION_TERMINATION: return pullImsRegistrationTermination(data); case TELEPHONY_NETWORK_REQUESTS: return pullTelephonyNetworkRequests(data); default: Rlog.e(TAG, String.format("unexpected atom ID %d", atomTag)); return StatsManager.PULL_SKIP; Loading Loading @@ -363,6 +368,18 @@ public class MetricsCollector implements StatsManager.StatsPullAtomCallback { } } private int pullTelephonyNetworkRequests(List<StatsEvent> data) { NetworkRequests[] persistAtoms = mStorage.getNetworkRequests(MIN_COOLDOWN_MILLIS); if (persistAtoms != null) { Arrays.stream(persistAtoms) .forEach(persistAtom -> data.add(buildStatsEvent(persistAtom))); return StatsManager.PULL_SUCCESS; } else { Rlog.w(TAG, "TELEPHONY_NETWORK_REQUESTS pull too frequent, skipping"); return StatsManager.PULL_SKIP; } } /** Registers a pulled atom ID {@code atomId} with optional {@code policy} for pulling. */ private void registerAtom(int atomId, @Nullable StatsManager.PullAtomMetadata policy) { mStatsManager.setPullAtomCallback(atomId, policy, ConcurrentUtils.DIRECT_EXECUTOR, this); Loading Loading @@ -536,6 +553,14 @@ public class MetricsCollector implements StatsManager.StatsPullAtomCallback { termination.count); } private static StatsEvent buildStatsEvent(NetworkRequests networkRequests) { return TelephonyStatsLog.buildStatsEvent( TELEPHONY_NETWORK_REQUESTS, networkRequests.carrierId, networkRequests.enterpriseRequestCount, networkRequests.enterpriseReleaseCount); } /** Returns all phones in {@link PhoneFactory}, or an empty array if phones not made yet. */ private static Phone[] getPhonesIfAny() { try { Loading
src/java/com/android/internal/telephony/metrics/NetworkRequestsStats.java 0 → 100644 +57 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 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 android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import com.android.internal.telephony.Phone; import com.android.internal.telephony.PhoneFactory; import com.android.internal.telephony.nano.PersistAtomsProto.NetworkRequests; /** Metrics for the network requests. */ public class NetworkRequestsStats { private NetworkRequestsStats() { } /** Generate metrics when enterprise network request occurs. */ public static void addEnterpriseRequest(int subId) { NetworkRequests networkRequests = new NetworkRequests(); networkRequests.carrierId = getCarrierId(subId); networkRequests.enterpriseRequestCount = 1; PersistAtomsStorage storage = PhoneFactory.getMetricsCollector().getAtomsStorage(); storage.addNetworkRequests(networkRequests); } /** Generate metrics when enterprise network release occurs. */ public static void addEnterpriseRelease(int subId) { NetworkRequests networkRequests = new NetworkRequests(); networkRequests.carrierId = getCarrierId(subId); networkRequests.enterpriseReleaseCount = 1; PersistAtomsStorage storage = PhoneFactory.getMetricsCollector().getAtomsStorage(); storage.addNetworkRequests(networkRequests); } /** Returns the carrier ID of the given subscription id. */ private static int getCarrierId(int subId) { int phoneId = SubscriptionManager.getPhoneId(subId); Phone phone = PhoneFactory.getPhone(phoneId); return phone != null ? phone.getCarrierId() : TelephonyManager.UNKNOWN_CARRIER_ID; } }
src/java/com/android/internal/telephony/metrics/PersistAtomsStorage.java +49 −0 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ import com.android.internal.telephony.nano.PersistAtomsProto.DataCallSession; import com.android.internal.telephony.nano.PersistAtomsProto.ImsRegistrationStats; import com.android.internal.telephony.nano.PersistAtomsProto.ImsRegistrationTermination; import com.android.internal.telephony.nano.PersistAtomsProto.IncomingSms; import com.android.internal.telephony.nano.PersistAtomsProto.NetworkRequests; import com.android.internal.telephony.nano.PersistAtomsProto.OutgoingSms; import com.android.internal.telephony.nano.PersistAtomsProto.PersistAtoms; import com.android.internal.telephony.nano.PersistAtomsProto.VoiceCallRatUsage; Loading Loading @@ -299,6 +300,20 @@ public class PersistAtomsStorage { } } /** Adds a new {@link NetworkRequests} to the storage. */ public synchronized void addNetworkRequests(NetworkRequests networkRequests) { NetworkRequests existingMetrics = find(networkRequests); if (existingMetrics != null) { existingMetrics.enterpriseRequestCount += networkRequests.enterpriseRequestCount; existingMetrics.enterpriseReleaseCount += networkRequests.enterpriseReleaseCount; } else { int newLength = mAtoms.networkRequests.length + 1; mAtoms.networkRequests = Arrays.copyOf(mAtoms.networkRequests, newLength); mAtoms.networkRequests[newLength - 1] = networkRequests; } saveAtomsToFile(SAVE_TO_FILE_DELAY_FOR_UPDATE_MILLIS); } /** * Returns and clears the voice call sessions if last pulled longer than {@code * minIntervalMillis} ago, otherwise returns {@code null}. Loading Loading @@ -465,6 +480,23 @@ public class PersistAtomsStorage { } } /** * Returns and clears the network requests if last pulled longer than {@code * minIntervalMillis} ago, otherwise returns {@code null}. */ @Nullable public synchronized NetworkRequests[] getNetworkRequests(long minIntervalMillis) { if (getWallTimeMillis() - mAtoms.networkRequestsPullTimestampMillis > minIntervalMillis) { mAtoms.networkRequestsPullTimestampMillis = getWallTimeMillis(); NetworkRequests[] previousNetworkRequests = mAtoms.networkRequests; mAtoms.networkRequests = new NetworkRequests[0]; saveAtomsToFile(SAVE_TO_FILE_DELAY_FOR_GET_MILLIS); return previousNetworkRequests; } else { return null; } } /** Loads {@link PersistAtoms} from a file in private storage. */ private PersistAtoms loadAtomsFromFile() { try { Loading Loading @@ -515,6 +547,7 @@ public class PersistAtomsStorage { atoms.imsRegistrationTermination, ImsRegistrationTermination.class, MAX_NUM_IMS_REGISTRATION_TERMINATIONS); atoms.networkRequests = sanitizeAtoms(atoms.networkRequests, NetworkRequests.class); // out of caution, sanitize also the timestamps atoms.voiceCallRatUsagePullTimestampMillis = sanitizeTimestamp(atoms.voiceCallRatUsagePullTimestampMillis); Loading @@ -534,6 +567,8 @@ public class PersistAtomsStorage { sanitizeTimestamp(atoms.imsRegistrationStatsPullTimestampMillis); atoms.imsRegistrationTerminationPullTimestampMillis = sanitizeTimestamp(atoms.imsRegistrationTerminationPullTimestampMillis); atoms.networkRequestsPullTimestampMillis = sanitizeTimestamp(atoms.networkRequestsPullTimestampMillis); return atoms; } catch (NoSuchFileException e) { Rlog.d(TAG, "PersistAtoms file not found"); Loading Loading @@ -656,6 +691,19 @@ public class PersistAtomsStorage { return null; } /** * Returns the network requests event that has the same carrier id as the given one, * or {@code null} if it does not exist. */ private @Nullable NetworkRequests find(NetworkRequests key) { for (NetworkRequests item : mAtoms.networkRequests) { if (item.carrierId == key.carrierId) { return item; } } return null; } /** * Inserts a new element in a random position in an array with a maximum size, replacing the * least recent item if possible. Loading Loading @@ -745,6 +793,7 @@ public class PersistAtomsStorage { atoms.cellularDataServiceSwitchPullTimestampMillis = currentTime; atoms.imsRegistrationStatsPullTimestampMillis = currentTime; atoms.imsRegistrationTerminationPullTimestampMillis = currentTime; atoms.networkRequestsPullTimestampMillis = currentTime; Rlog.d(TAG, "created new PersistAtoms"); return atoms; } Loading