From 41f94629c9f84f9fc1f81bcdc2a2653e732e25b2 Mon Sep 17 00:00:00 2001 From: Collin Fijalkovich Date: Fri, 10 Apr 2020 14:01:42 -0700 Subject: [PATCH] Cache getPhoneId and getSlotIndex binder calls. Use PropertyInvalidatedCache to avoid redundant calls to SubscriptionController getSlotIndex and getPhoneId. Bug: 151953109 Test: Verified cache operated correctly when phone process is killed. Test: atest SubscriptionControllerTest Test: atest android.telephony.cts.SubscriptionManagerTest Change-Id: I70552537af44f3e05b156cd190ebb28f0d940bf6 --- .../internal/util/FunctionalUtils.java | 27 ++++ .../telephony/SubscriptionManager.java | 146 ++++++++++-------- 2 files changed, 109 insertions(+), 64 deletions(-) diff --git a/core/java/com/android/internal/util/FunctionalUtils.java b/core/java/com/android/internal/util/FunctionalUtils.java index 9168438dc2bf6..05ecdf9056236 100644 --- a/core/java/com/android/internal/util/FunctionalUtils.java +++ b/core/java/com/android/internal/util/FunctionalUtils.java @@ -21,6 +21,7 @@ import android.os.RemoteException; import android.util.ExceptionUtils; import java.util.function.BiConsumer; +import java.util.function.BiFunction; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Supplier; @@ -195,6 +196,32 @@ public class FunctionalUtils { } } + /** + * A {@link BiFunction} that allows throwing checked exceptions from its single abstract method. + * + * Can be used together with {@link #uncheckExceptions} to effectively turn a lambda expression + * that throws a checked exception into a regular {@link BiFunction} + * + * @param see {@link BiFunction} + * @param see {@link BiFunction} + * @param see {@link BiFunction} + */ + @FunctionalInterface + @SuppressWarnings("FunctionalInterfaceMethodChanged") + public interface ThrowingBiFunction extends BiFunction { + /** @see ThrowingFunction */ + R applyOrThrow(T t, U u) throws Exception; + + @Override + default R apply(T t, U u) { + try { + return applyOrThrow(t, u); + } catch (Exception ex) { + throw ExceptionUtils.propagate(ex); + } + } + } + /** * A {@link BiConsumer} that allows throwing checked exceptions from its single abstract method. * diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java index ce5412f0fbcc2..e9ee06c246baa 100644 --- a/telephony/java/android/telephony/SubscriptionManager.java +++ b/telephony/java/android/telephony/SubscriptionManager.java @@ -148,20 +148,24 @@ public class SubscriptionManager { public static final String CACHE_KEY_ACTIVE_DATA_SUB_ID_PROPERTY = "cache_key.telephony.get_active_data_sub_id"; + /** @hide */ + public static final String CACHE_KEY_SLOT_INDEX_PROPERTY = + "cache_key.telephony.get_slot_index"; + private static final int MAX_CACHE_SIZE = 4; - private static class SubscriptionPropertyInvalidatedCache + private static class VoidPropertyInvalidatedCache extends PropertyInvalidatedCache { - private final FunctionalUtils.ThrowingFunction mSubscriptionInterfaceMethod; + private final FunctionalUtils.ThrowingFunction mInterfaceMethod; private final String mCacheKeyProperty; private final T mDefaultValue; - SubscriptionPropertyInvalidatedCache( + VoidPropertyInvalidatedCache( FunctionalUtils.ThrowingFunction subscriptionInterfaceMethod, String cacheKeyProperty, T defaultValue) { super(MAX_CACHE_SIZE, cacheKeyProperty); - mSubscriptionInterfaceMethod = subscriptionInterfaceMethod; + mInterfaceMethod = subscriptionInterfaceMethod; mCacheKeyProperty = cacheKeyProperty; mDefaultValue = defaultValue; } @@ -173,7 +177,7 @@ public class SubscriptionManager { try { ISub iSub = TelephonyManager.getSubscriptionService(); if (iSub != null) { - result = mSubscriptionInterfaceMethod.applyOrThrow(iSub); + result = mInterfaceMethod.applyOrThrow(iSub); } } catch (Exception ex) { Rlog.w(LOG_TAG, "Failed to recompute cache key for " + mCacheKeyProperty); @@ -184,26 +188,71 @@ public class SubscriptionManager { } } - private static SubscriptionPropertyInvalidatedCache sDefaultSubIdCache = - new SubscriptionPropertyInvalidatedCache<>(ISub::getDefaultSubId, + private static class IntegerPropertyInvalidatedCache + extends PropertyInvalidatedCache { + private final FunctionalUtils.ThrowingBiFunction mInterfaceMethod; + private final String mCacheKeyProperty; + private final T mDefaultValue; + + IntegerPropertyInvalidatedCache( + FunctionalUtils.ThrowingBiFunction subscriptionInterfaceMethod, + String cacheKeyProperty, + T defaultValue) { + super(MAX_CACHE_SIZE, cacheKeyProperty); + mInterfaceMethod = subscriptionInterfaceMethod; + mCacheKeyProperty = cacheKeyProperty; + mDefaultValue = defaultValue; + } + + @Override + protected T recompute(Integer query) { + T result = mDefaultValue; + + try { + ISub iSub = TelephonyManager.getSubscriptionService(); + if (iSub != null) { + result = mInterfaceMethod.applyOrThrow(iSub, query); + } + } catch (Exception ex) { + Rlog.w(LOG_TAG, "Failed to recompute cache key for " + mCacheKeyProperty); + } + + if (VDBG) logd("recomputing " + mCacheKeyProperty + ", result = " + result); + return result; + } + } + + private static VoidPropertyInvalidatedCache sDefaultSubIdCache = + new VoidPropertyInvalidatedCache<>(ISub::getDefaultSubId, CACHE_KEY_DEFAULT_SUB_ID_PROPERTY, INVALID_SUBSCRIPTION_ID); - private static SubscriptionPropertyInvalidatedCache sDefaultDataSubIdCache = - new SubscriptionPropertyInvalidatedCache<>(ISub::getDefaultDataSubId, + private static VoidPropertyInvalidatedCache sDefaultDataSubIdCache = + new VoidPropertyInvalidatedCache<>(ISub::getDefaultDataSubId, CACHE_KEY_DEFAULT_DATA_SUB_ID_PROPERTY, INVALID_SUBSCRIPTION_ID); - private static PropertyInvalidatedCache sDefaultSmsSubIdCache = - new SubscriptionPropertyInvalidatedCache<>(ISub::getDefaultSmsSubId, + private static VoidPropertyInvalidatedCache sDefaultSmsSubIdCache = + new VoidPropertyInvalidatedCache<>(ISub::getDefaultSmsSubId, CACHE_KEY_DEFAULT_SMS_SUB_ID_PROPERTY, INVALID_SUBSCRIPTION_ID); - private static PropertyInvalidatedCache sActiveDataSubIdCache = - new SubscriptionPropertyInvalidatedCache<>(ISub::getActiveDataSubscriptionId, + private static VoidPropertyInvalidatedCache sActiveDataSubIdCache = + new VoidPropertyInvalidatedCache<>(ISub::getActiveDataSubscriptionId, CACHE_KEY_ACTIVE_DATA_SUB_ID_PROPERTY, INVALID_SUBSCRIPTION_ID); + private static IntegerPropertyInvalidatedCache sSlotIndexCache = + new IntegerPropertyInvalidatedCache<>(ISub::getSlotIndex, + CACHE_KEY_SLOT_INDEX_PROPERTY, + INVALID_SIM_SLOT_INDEX); + + /** Cache depends on getDefaultSubId, so we use the defaultSubId cache key */ + private static IntegerPropertyInvalidatedCache sPhoneIdCache = + new IntegerPropertyInvalidatedCache<>(ISub::getPhoneId, + CACHE_KEY_DEFAULT_SUB_ID_PROPERTY, + INVALID_PHONE_INDEX); + /** * Generates a content {@link Uri} used to receive updates on simInfo change * on the given subscriptionId @@ -1246,7 +1295,6 @@ public class SubscriptionManager { } return subInfo; - } /** @@ -1816,25 +1864,7 @@ public class SubscriptionManager { * subscriptionId doesn't have an associated slot index. */ public static int getSlotIndex(int subscriptionId) { - if (!isValidSubscriptionId(subscriptionId)) { - if (DBG) { - logd("[getSlotIndex]- supplied subscriptionId is invalid."); - } - } - - int result = INVALID_SIM_SLOT_INDEX; - - try { - ISub iSub = TelephonyManager.getSubscriptionService(); - if (iSub != null) { - result = iSub.getSlotIndex(subscriptionId); - } - } catch (RemoteException ex) { - // ignore it - } - - return result; - + return sSlotIndexCache.query(subscriptionId); } /** @@ -1873,27 +1903,7 @@ public class SubscriptionManager { /** @hide */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) public static int getPhoneId(int subId) { - if (!isValidSubscriptionId(subId)) { - if (DBG) { - logd("[getPhoneId]- fail"); - } - return INVALID_PHONE_INDEX; - } - - int result = INVALID_PHONE_INDEX; - - try { - ISub iSub = TelephonyManager.getSubscriptionService(); - if (iSub != null) { - result = iSub.getPhoneId(subId); - } - } catch (RemoteException ex) { - // ignore it - } - - if (VDBG) logd("[getPhoneId]- phoneId=" + result); - return result; - + return sPhoneIdCache.query(subId); } private static void logd(String msg) { @@ -3326,16 +3336,9 @@ public class SubscriptionManager { PropertyInvalidatedCache.invalidateCache(CACHE_KEY_ACTIVE_DATA_SUB_ID_PROPERTY); } - /** - * Clears all process-local binder caches. - * - * @hide - */ - public static void clearCaches() { - sDefaultSubIdCache.clear(); - sDefaultDataSubIdCache.clear(); - sActiveDataSubIdCache.clear(); - sDefaultSmsSubIdCache.clear(); + /** @hide */ + public static void invalidateSlotIndexCaches() { + PropertyInvalidatedCache.invalidateCache(CACHE_KEY_SLOT_INDEX_PROPERTY); } /** @@ -3348,5 +3351,20 @@ public class SubscriptionManager { sDefaultDataSubIdCache.disableLocal(); sActiveDataSubIdCache.disableLocal(); sDefaultSmsSubIdCache.disableLocal(); + sSlotIndexCache.disableLocal(); + sPhoneIdCache.disableLocal(); + } + + /** + * Clears all process-local binder caches. + * + * @hide */ + public static void clearCaches() { + sDefaultSubIdCache.clear(); + sDefaultDataSubIdCache.clear(); + sActiveDataSubIdCache.clear(); + sDefaultSmsSubIdCache.clear(); + sSlotIndexCache.clear(); + sPhoneIdCache.clear(); } }