Loading proto/src/persist_atoms.proto +5 −0 Original line number Diff line number Diff line Loading @@ -720,6 +720,9 @@ message SatelliteController { optional int32 count_of_satellite_access_check_fail = 28; optional bool is_provisioned = 29; optional int32 carrier_id = 30; optional int32 count_of_satellite_allowed_state_changed_events = 31; optional int32 count_of_successful_location_queries = 32; optional int32 count_of_failed_location_queries = 33; } message SatelliteSession { Loading Loading @@ -818,6 +821,7 @@ message CarrierRoamingSatelliteControllerStats { optional int32 satellite_session_gap_avg_sec = 6; optional int32 satellite_session_gap_max_sec = 7; optional int32 carrier_id = 8; optional bool is_device_entitled = 9; } message SatelliteEntitlement { Loading Loading @@ -846,4 +850,5 @@ message SatelliteAccessController { repeated string country_codes = 8; optional int32 config_data_source = 9; optional int32 carrier_id = 10; optional int32 triggering_event = 11; } src/java/com/android/internal/telephony/data/DataNetworkController.java +1 −1 Original line number Diff line number Diff line Loading @@ -3195,7 +3195,7 @@ public class DataNetworkController extends Handler { telephonyNetworkRequest, DataEvaluationReason.DATA_RETRY); if (!evaluation.containsDisallowedReasons()) { DataProfile dataProfile = dataSetupRetryEntry.dataProfile; if (dataProfile == null) { if (dataProfile == null || !mDataProfileManager.isDataProfileCompatible(dataProfile)) { dataProfile = evaluation.getCandidateDataProfile(); } if (dataProfile != null) { Loading src/java/com/android/internal/telephony/euicc/EuiccConnector.java +2 −0 Original line number Diff line number Diff line Loading @@ -831,6 +831,7 @@ public class EuiccConnector extends StateMachine implements ServiceConnection { } case CMD_DOWNLOAD_SUBSCRIPTION: { DownloadRequest request = (DownloadRequest) message.obj; EuiccSession.get().startSession(EuiccSession.DOWNLOAD); mEuiccService.downloadSubscription(slotId, request.mPortIndex, request.mSubscription, Loading @@ -845,6 +846,7 @@ public class EuiccConnector extends StateMachine implements ServiceConnection { .onDownloadComplete(result); onCommandEnd(callback); }); EuiccSession.get().endSession(EuiccSession.DOWNLOAD); } }); break; Loading src/java/com/android/internal/telephony/euicc/EuiccSession.java 0 → 100644 +141 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 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.euicc; import android.util.ArraySet; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.telephony.flags.Flags; import com.android.internal.telephony.uicc.euicc.apdu.ApduSender; import com.android.telephony.Rlog; import java.util.Set; /** * A eUICC transaction session aims to optimize multiple back-to-back EuiccPort API calls by only * open and close a logical channel once. * * <p>This class is thread-safe. */ public class EuiccSession { private static final String TAG = "EuiccSession"; // **** Well known session IDs, see #startSession() **** public static final String DOWNLOAD = "DOWNLOAD"; @GuardedBy("EuiccSession.class") private static EuiccSession sInstance; public static synchronized EuiccSession get() { if (sInstance == null) { sInstance = new EuiccSession(); } return sInstance; } @GuardedBy("this") private final Set<String> mSessions = new ArraySet<>(); @GuardedBy("this") private final Set<ApduSender> mApduSenders = new ArraySet<>(); /** * Marks the start of a eUICC transaction session. * * <p>A session means a long-open logical channel (see {@link ApduSender}) used to * send multiple APDUs for one action e.g. {@link EuiccController#downloadSubscription()}. * Those APDUs can be send by one or multiple {@link EuiccCardController} methods. * * <p>Ideally a session should correespond to one phoneId and hence just one logical channel. * But many {@link EuiccCardController} methods uses first available port and is not specific * to a phoneId. So EuiccController cannot choose one phoneId to use. Hence a session has to * be not specific to phoneId, i.e. for DSDS device both phoneId's will be in a session. * * <p>If called multiple times with different {@code sessionId}'s, the session is truly closed * when the all sessions are ended. See {@link #endSession()}. * * @param sessionId The session ID. */ public void startSession(String sessionId) { if (!Flags.optimizationApduSender()) { // Other methods in this class is no-op if no session started. // Do not add flag to other methods, so if the flag gets turned off, // the session can be ended properly. return; } Rlog.i(TAG, "startSession: " + sessionId); synchronized(this) { mSessions.add(sessionId); } } /** Returns {@code true} if there is at least one session ongoing. */ public boolean hasSession() { boolean hasSession; synchronized(this) { hasSession = !mSessions.isEmpty(); } Rlog.i(TAG, "hasSession: " + hasSession); return hasSession; } /** * Notes that a logical channel may be opened by the {@code apduSender}, which will * be used to close the channel when session ends (see {@link #endSession()}). * * <p>No-op if no session ongoing (see {@link #hasSession()}). * * @param apduSender The ApduSender that will open the channel. */ public void noteChannelOpen(ApduSender apduSender) { Rlog.i(TAG, "noteChannelOpen: " + apduSender); synchronized(this) { if (hasSession()) { mApduSenders.add(apduSender); } } } /** * Marks the end of a eUICC transaction session. If this ends the last ongoing session, * try to close the logical channel using the noted {@code apduSender} * (see {@link #noteChannelOpen()}). * * @param sessionId The session ID. */ public void endSession(String sessionId) { Rlog.i(TAG, "endSession: " + sessionId); ApduSender[] apduSenders = new ApduSender[0]; synchronized(this) { boolean sessionRemoved = mSessions.remove(sessionId); // sessionRemoved is false if the `sessionId` was never started or there was // no session at all i.e. `sessions` is empty. Don't bother invoke `apduSender`. if (sessionRemoved && mSessions.isEmpty()) { // copy mApduSenders to a local variable so we don't call closeAnyOpenChannel() // which can take time in synchronized block. apduSenders = mApduSenders.toArray(apduSenders); mApduSenders.clear(); } } for (ApduSender apduSender : apduSenders) { apduSender.closeAnyOpenChannel(); } } @VisibleForTesting public EuiccSession() {} } src/java/com/android/internal/telephony/metrics/MetricsCollector.java +8 −3 Original line number Diff line number Diff line Loading @@ -1477,7 +1477,10 @@ public class MetricsCollector implements StatsManager.StatsPullAtomCallback { satelliteController.countOfDisallowedSatelliteAccess, satelliteController.countOfSatelliteAccessCheckFail, satelliteController.isProvisioned, satelliteController.carrierId); satelliteController.carrierId, satelliteController.countOfSatelliteAllowedStateChangedEvents, satelliteController.countOfSuccessfulLocationQueries, satelliteController.countOfFailedLocationQueries); } private static StatsEvent buildStatsEvent(SatelliteSession satelliteSession) { Loading Loading @@ -1591,7 +1594,8 @@ public class MetricsCollector implements StatsManager.StatsPullAtomCallback { stats.satelliteSessionGapMinSec, stats.satelliteSessionGapAvgSec, stats.satelliteSessionGapMaxSec, stats.carrierId); stats.carrierId, stats.isDeviceEntitled); } private static StatsEvent buildStatsEvent(SatelliteEntitlement stats) { Loading Loading @@ -1624,7 +1628,8 @@ public class MetricsCollector implements StatsManager.StatsPullAtomCallback { stats.resultCode, stats.countryCodes, stats.configDataSource, stats.carrierId); stats.carrierId, stats.triggeringEvent); } /** Returns all phones in {@link PhoneFactory}, or an empty array if phones not made yet. */ Loading Loading
proto/src/persist_atoms.proto +5 −0 Original line number Diff line number Diff line Loading @@ -720,6 +720,9 @@ message SatelliteController { optional int32 count_of_satellite_access_check_fail = 28; optional bool is_provisioned = 29; optional int32 carrier_id = 30; optional int32 count_of_satellite_allowed_state_changed_events = 31; optional int32 count_of_successful_location_queries = 32; optional int32 count_of_failed_location_queries = 33; } message SatelliteSession { Loading Loading @@ -818,6 +821,7 @@ message CarrierRoamingSatelliteControllerStats { optional int32 satellite_session_gap_avg_sec = 6; optional int32 satellite_session_gap_max_sec = 7; optional int32 carrier_id = 8; optional bool is_device_entitled = 9; } message SatelliteEntitlement { Loading Loading @@ -846,4 +850,5 @@ message SatelliteAccessController { repeated string country_codes = 8; optional int32 config_data_source = 9; optional int32 carrier_id = 10; optional int32 triggering_event = 11; }
src/java/com/android/internal/telephony/data/DataNetworkController.java +1 −1 Original line number Diff line number Diff line Loading @@ -3195,7 +3195,7 @@ public class DataNetworkController extends Handler { telephonyNetworkRequest, DataEvaluationReason.DATA_RETRY); if (!evaluation.containsDisallowedReasons()) { DataProfile dataProfile = dataSetupRetryEntry.dataProfile; if (dataProfile == null) { if (dataProfile == null || !mDataProfileManager.isDataProfileCompatible(dataProfile)) { dataProfile = evaluation.getCandidateDataProfile(); } if (dataProfile != null) { Loading
src/java/com/android/internal/telephony/euicc/EuiccConnector.java +2 −0 Original line number Diff line number Diff line Loading @@ -831,6 +831,7 @@ public class EuiccConnector extends StateMachine implements ServiceConnection { } case CMD_DOWNLOAD_SUBSCRIPTION: { DownloadRequest request = (DownloadRequest) message.obj; EuiccSession.get().startSession(EuiccSession.DOWNLOAD); mEuiccService.downloadSubscription(slotId, request.mPortIndex, request.mSubscription, Loading @@ -845,6 +846,7 @@ public class EuiccConnector extends StateMachine implements ServiceConnection { .onDownloadComplete(result); onCommandEnd(callback); }); EuiccSession.get().endSession(EuiccSession.DOWNLOAD); } }); break; Loading
src/java/com/android/internal/telephony/euicc/EuiccSession.java 0 → 100644 +141 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 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.euicc; import android.util.ArraySet; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.telephony.flags.Flags; import com.android.internal.telephony.uicc.euicc.apdu.ApduSender; import com.android.telephony.Rlog; import java.util.Set; /** * A eUICC transaction session aims to optimize multiple back-to-back EuiccPort API calls by only * open and close a logical channel once. * * <p>This class is thread-safe. */ public class EuiccSession { private static final String TAG = "EuiccSession"; // **** Well known session IDs, see #startSession() **** public static final String DOWNLOAD = "DOWNLOAD"; @GuardedBy("EuiccSession.class") private static EuiccSession sInstance; public static synchronized EuiccSession get() { if (sInstance == null) { sInstance = new EuiccSession(); } return sInstance; } @GuardedBy("this") private final Set<String> mSessions = new ArraySet<>(); @GuardedBy("this") private final Set<ApduSender> mApduSenders = new ArraySet<>(); /** * Marks the start of a eUICC transaction session. * * <p>A session means a long-open logical channel (see {@link ApduSender}) used to * send multiple APDUs for one action e.g. {@link EuiccController#downloadSubscription()}. * Those APDUs can be send by one or multiple {@link EuiccCardController} methods. * * <p>Ideally a session should correespond to one phoneId and hence just one logical channel. * But many {@link EuiccCardController} methods uses first available port and is not specific * to a phoneId. So EuiccController cannot choose one phoneId to use. Hence a session has to * be not specific to phoneId, i.e. for DSDS device both phoneId's will be in a session. * * <p>If called multiple times with different {@code sessionId}'s, the session is truly closed * when the all sessions are ended. See {@link #endSession()}. * * @param sessionId The session ID. */ public void startSession(String sessionId) { if (!Flags.optimizationApduSender()) { // Other methods in this class is no-op if no session started. // Do not add flag to other methods, so if the flag gets turned off, // the session can be ended properly. return; } Rlog.i(TAG, "startSession: " + sessionId); synchronized(this) { mSessions.add(sessionId); } } /** Returns {@code true} if there is at least one session ongoing. */ public boolean hasSession() { boolean hasSession; synchronized(this) { hasSession = !mSessions.isEmpty(); } Rlog.i(TAG, "hasSession: " + hasSession); return hasSession; } /** * Notes that a logical channel may be opened by the {@code apduSender}, which will * be used to close the channel when session ends (see {@link #endSession()}). * * <p>No-op if no session ongoing (see {@link #hasSession()}). * * @param apduSender The ApduSender that will open the channel. */ public void noteChannelOpen(ApduSender apduSender) { Rlog.i(TAG, "noteChannelOpen: " + apduSender); synchronized(this) { if (hasSession()) { mApduSenders.add(apduSender); } } } /** * Marks the end of a eUICC transaction session. If this ends the last ongoing session, * try to close the logical channel using the noted {@code apduSender} * (see {@link #noteChannelOpen()}). * * @param sessionId The session ID. */ public void endSession(String sessionId) { Rlog.i(TAG, "endSession: " + sessionId); ApduSender[] apduSenders = new ApduSender[0]; synchronized(this) { boolean sessionRemoved = mSessions.remove(sessionId); // sessionRemoved is false if the `sessionId` was never started or there was // no session at all i.e. `sessions` is empty. Don't bother invoke `apduSender`. if (sessionRemoved && mSessions.isEmpty()) { // copy mApduSenders to a local variable so we don't call closeAnyOpenChannel() // which can take time in synchronized block. apduSenders = mApduSenders.toArray(apduSenders); mApduSenders.clear(); } } for (ApduSender apduSender : apduSenders) { apduSender.closeAnyOpenChannel(); } } @VisibleForTesting public EuiccSession() {} }
src/java/com/android/internal/telephony/metrics/MetricsCollector.java +8 −3 Original line number Diff line number Diff line Loading @@ -1477,7 +1477,10 @@ public class MetricsCollector implements StatsManager.StatsPullAtomCallback { satelliteController.countOfDisallowedSatelliteAccess, satelliteController.countOfSatelliteAccessCheckFail, satelliteController.isProvisioned, satelliteController.carrierId); satelliteController.carrierId, satelliteController.countOfSatelliteAllowedStateChangedEvents, satelliteController.countOfSuccessfulLocationQueries, satelliteController.countOfFailedLocationQueries); } private static StatsEvent buildStatsEvent(SatelliteSession satelliteSession) { Loading Loading @@ -1591,7 +1594,8 @@ public class MetricsCollector implements StatsManager.StatsPullAtomCallback { stats.satelliteSessionGapMinSec, stats.satelliteSessionGapAvgSec, stats.satelliteSessionGapMaxSec, stats.carrierId); stats.carrierId, stats.isDeviceEntitled); } private static StatsEvent buildStatsEvent(SatelliteEntitlement stats) { Loading Loading @@ -1624,7 +1628,8 @@ public class MetricsCollector implements StatsManager.StatsPullAtomCallback { stats.resultCode, stats.countryCodes, stats.configDataSource, stats.carrierId); stats.carrierId, stats.triggeringEvent); } /** Returns all phones in {@link PhoneFactory}, or an empty array if phones not made yet. */ Loading