diff options
33 files changed, 603 insertions, 289 deletions
diff --git a/api/current.txt b/api/current.txt index 6f97fdd5ffd9..c657756ba3e9 100644 --- a/api/current.txt +++ b/api/current.txt @@ -9772,7 +9772,7 @@ package android.content { method @RequiresPermission("android.permission.INTERACT_ACROSS_USERS") public abstract void sendBroadcastAsUser(@RequiresPermission android.content.Intent, android.os.UserHandle, @Nullable String); method public abstract void sendOrderedBroadcast(@RequiresPermission android.content.Intent, @Nullable String); method public abstract void sendOrderedBroadcast(@NonNull @RequiresPermission android.content.Intent, @Nullable String, @Nullable android.content.BroadcastReceiver, @Nullable android.os.Handler, int, @Nullable String, @Nullable android.os.Bundle); - method public void sendOrderedBroadcast(@NonNull @RequiresPermission android.content.Intent, @Nullable String, @Nullable String, @Nullable android.content.BroadcastReceiver, @Nullable android.os.Handler, int, @Nullable String, @Nullable android.os.Bundle); + method public void sendOrderedBroadcast(@NonNull android.content.Intent, @Nullable String, @Nullable String, @Nullable android.content.BroadcastReceiver, @Nullable android.os.Handler, int, @Nullable String, @Nullable android.os.Bundle); method @RequiresPermission("android.permission.INTERACT_ACROSS_USERS") public abstract void sendOrderedBroadcastAsUser(@RequiresPermission android.content.Intent, android.os.UserHandle, @Nullable String, android.content.BroadcastReceiver, @Nullable android.os.Handler, int, @Nullable String, @Nullable android.os.Bundle); method @Deprecated @RequiresPermission(android.Manifest.permission.BROADCAST_STICKY) public abstract void sendStickyBroadcast(@RequiresPermission android.content.Intent); method @Deprecated @RequiresPermission(allOf={"android.permission.INTERACT_ACROSS_USERS", android.Manifest.permission.BROADCAST_STICKY}) public abstract void sendStickyBroadcastAsUser(@RequiresPermission android.content.Intent, android.os.UserHandle); @@ -29892,6 +29892,7 @@ package android.net.wifi { field public static final int STATUS_NETWORK_SUGGESTIONS_SUCCESS = 0; // 0x0 field @Deprecated public static final String SUPPLICANT_CONNECTION_CHANGE_ACTION = "android.net.wifi.supplicant.CONNECTION_CHANGE"; field @Deprecated public static final String SUPPLICANT_STATE_CHANGED_ACTION = "android.net.wifi.supplicant.STATE_CHANGE"; + field public static final String UNKNOWN_SSID = "<unknown ssid>"; field @Deprecated public static final int WIFI_MODE_FULL = 1; // 0x1 field public static final int WIFI_MODE_FULL_HIGH_PERF = 3; // 0x3 field public static final int WIFI_MODE_FULL_LOW_LATENCY = 4; // 0x4 diff --git a/api/system-current.txt b/api/system-current.txt index b92462d1ca60..685238a7ba02 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -1366,8 +1366,9 @@ package android.content { public abstract class Context { method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public boolean bindServiceAsUser(@RequiresPermission android.content.Intent, android.content.ServiceConnection, int, android.os.UserHandle); + method @NonNull public android.content.Context createContextAsUser(@NonNull android.os.UserHandle, int); method public abstract android.content.Context createCredentialProtectedStorageContext(); - method public android.content.Context createPackageContextAsUser(String, int, android.os.UserHandle) throws android.content.pm.PackageManager.NameNotFoundException; + method @NonNull public android.content.Context createPackageContextAsUser(@NonNull String, int, @NonNull android.os.UserHandle) throws android.content.pm.PackageManager.NameNotFoundException; method @Nullable public abstract java.io.File getPreloadsFileCache(); method public abstract boolean isCredentialProtectedStorage(); method public abstract void sendBroadcast(android.content.Intent, @Nullable String, @Nullable android.os.Bundle); @@ -8141,6 +8142,7 @@ package android.telephony { } public final class SmsCbLocation implements android.os.Parcelable { + ctor public SmsCbLocation(@NonNull String, int, int); method public int describeContents(); method public int getCid(); method public int getLac(); @@ -8152,7 +8154,7 @@ package android.telephony { } public final class SmsCbMessage implements android.os.Parcelable { - ctor public SmsCbMessage(int, int, int, @NonNull android.telephony.SmsCbLocation, int, @Nullable String, @Nullable String, int, @Nullable android.telephony.SmsCbEtwsInfo, @Nullable android.telephony.SmsCbCmasInfo, int); + ctor public SmsCbMessage(int, int, int, @NonNull android.telephony.SmsCbLocation, int, @Nullable String, @Nullable String, int, @Nullable android.telephony.SmsCbEtwsInfo, @Nullable android.telephony.SmsCbCmasInfo, int, @Nullable java.util.List<android.telephony.CbGeoUtils.Geometry>, long, int); method @NonNull public static android.telephony.SmsCbMessage createFromCursor(@NonNull android.database.Cursor); method public int describeContents(); method @Nullable public android.telephony.SmsCbCmasInfo getCmasWarningInfo(); @@ -8179,6 +8181,7 @@ package android.telephony { field public static final int GEOGRAPHICAL_SCOPE_CELL_WIDE_IMMEDIATE = 0; // 0x0 field public static final int GEOGRAPHICAL_SCOPE_LOCATION_AREA_WIDE = 2; // 0x2 field public static final int GEOGRAPHICAL_SCOPE_PLMN_WIDE = 1; // 0x1 + field public static final int MAXIMUM_WAIT_TIME_NOT_SET = 255; // 0xff field public static final int MESSAGE_FORMAT_3GPP = 1; // 0x1 field public static final int MESSAGE_FORMAT_3GPP2 = 2; // 0x2 field public static final int MESSAGE_PRIORITY_EMERGENCY = 3; // 0x3 diff --git a/api/test-current.txt b/api/test-current.txt index eaf1fd793750..92d89d40dff9 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -640,7 +640,8 @@ package android.content { } public abstract class Context { - method public android.content.Context createPackageContextAsUser(String, int, android.os.UserHandle) throws android.content.pm.PackageManager.NameNotFoundException; + method @NonNull public android.content.Context createContextAsUser(@NonNull android.os.UserHandle, int); + method @NonNull public android.content.Context createPackageContextAsUser(@NonNull String, int, @NonNull android.os.UserHandle) throws android.content.pm.PackageManager.NameNotFoundException; method public abstract android.view.Display getDisplay(); method public abstract int getDisplayId(); method public android.os.UserHandle getUser(); diff --git a/config/OWNERS b/config/OWNERS new file mode 100644 index 000000000000..53f80e698d83 --- /dev/null +++ b/config/OWNERS @@ -0,0 +1,5 @@ +# compat-team@ for changes to hiddenapi files +per-file hiddenapi-* = andreionea@google.com, atrost@google.com, mathewi@google.com, satayev@google.com + +# Escalations: +per-file hiddenapi-* = bdc@google.com, narayan@google.com
\ No newline at end of file diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index 9902f6aa0fe3..794ffcb83078 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -2224,6 +2224,15 @@ class ContextImpl extends Context { } @Override + public Context createContextAsUser(UserHandle user, @CreatePackageOptions int flags) { + try { + return createPackageContextAsUser(getPackageName(), flags, user); + } catch (NameNotFoundException e) { + throw new IllegalStateException("Own package not found: package=" + getPackageName()); + } + } + + @Override public Context createContextForSplit(String splitName) throws NameNotFoundException { if (!mPackageInfo.getApplicationInfo().requestsIsolatedSplitLoading()) { // All Splits are always loaded. diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index a12e4da6e23e..4b22166a9688 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -2424,10 +2424,10 @@ public abstract class Context { * * @see #sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle) */ - public void sendOrderedBroadcast(@RequiresPermission @NonNull Intent intent, - @Nullable String receiverPermission, @Nullable String receiverAppOp, - @Nullable BroadcastReceiver resultReceiver, @Nullable Handler scheduler, - int initialCode, @Nullable String initialData, @Nullable Bundle initialExtras) { + public void sendOrderedBroadcast(@NonNull Intent intent, @Nullable String receiverPermission, + @Nullable String receiverAppOp, @Nullable BroadcastReceiver resultReceiver, + @Nullable Handler scheduler, int initialCode, @Nullable String initialData, + @Nullable Bundle initialExtras) { throw new RuntimeException("Not implemented. Must override in a subclass."); } @@ -5256,8 +5256,9 @@ public abstract class Context { */ @SystemApi @TestApi + @NonNull public Context createPackageContextAsUser( - String packageName, @CreatePackageOptions int flags, UserHandle user) + @NonNull String packageName, @CreatePackageOptions int flags, @NonNull UserHandle user) throws PackageManager.NameNotFoundException { if (Build.IS_ENG) { throw new IllegalStateException("createPackageContextAsUser not overridden!"); @@ -5266,6 +5267,23 @@ public abstract class Context { } /** + * Similar to {@link #createPackageContext(String, int)}, but for the own package with a + * different {@link UserHandle}. For example, {@link #getContentResolver()} + * will open any {@link Uri} as the given user. + * + * @hide + */ + @SystemApi + @TestApi + @NonNull + public Context createContextAsUser(@NonNull UserHandle user, @CreatePackageOptions int flags) { + if (Build.IS_ENG) { + throw new IllegalStateException("createContextAsUser not overridden!"); + } + return this; + } + + /** * Creates a context given an {@link android.content.pm.ApplicationInfo}. * * @hide diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java index 2b1b8eb183ab..428aadb5c3f6 100644 --- a/core/java/android/content/ContextWrapper.java +++ b/core/java/android/content/ContextWrapper.java @@ -898,6 +898,12 @@ public class ContextWrapper extends Context { /** @hide */ @Override + public Context createContextAsUser(UserHandle user, @CreatePackageOptions int flags) { + return mBase.createContextAsUser(user, flags); + } + + /** @hide */ + @Override @UnsupportedAppUsage public Context createApplicationContext(ApplicationInfo application, int flags) throws PackageManager.NameNotFoundException { diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index 75af41cb2b54..56bacf29ac73 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -52,13 +52,12 @@ import android.os.ServiceManager; import android.os.ServiceSpecificException; import android.provider.Settings; import android.telephony.SubscriptionManager; +import android.telephony.TelephonyManager; import android.util.ArrayMap; import android.util.Log; import android.util.SparseIntArray; import com.android.internal.annotations.GuardedBy; -import com.android.internal.telephony.ITelephony; -import com.android.internal.telephony.PhoneConstants; import com.android.internal.util.Preconditions; import com.android.internal.util.Protocol; @@ -711,6 +710,12 @@ public class ConnectivityManager { @Deprecated public static final int TYPE_TEST = 18; // TODO: Remove this once NetworkTypes are unused. + // Deprecated constants for return values of startUsingNetworkFeature. They used to live + // in com.android.internal.telephony.PhoneConstants until they were made inaccessible. + private static final int DEPRECATED_PHONE_CONSTANT_APN_ALREADY_ACTIVE = 0; + private static final int DEPRECATED_PHONE_CONSTANT_APN_REQUEST_STARTED = 1; + private static final int DEPRECATED_PHONE_CONSTANT_APN_REQUEST_FAILED = 3; + /** {@hide} */ public static final int MAX_RADIO_TYPE = TYPE_TEST; @@ -1407,7 +1412,7 @@ public class ConnectivityManager { if (netCap == null) { Log.d(TAG, "Can't satisfy startUsingNetworkFeature for " + networkType + ", " + feature); - return PhoneConstants.APN_REQUEST_FAILED; + return DEPRECATED_PHONE_CONSTANT_APN_REQUEST_FAILED; } NetworkRequest request = null; @@ -1417,9 +1422,9 @@ public class ConnectivityManager { Log.d(TAG, "renewing startUsingNetworkFeature request " + l.networkRequest); renewRequestLocked(l); if (l.currentNetwork != null) { - return PhoneConstants.APN_ALREADY_ACTIVE; + return DEPRECATED_PHONE_CONSTANT_APN_ALREADY_ACTIVE; } else { - return PhoneConstants.APN_REQUEST_STARTED; + return DEPRECATED_PHONE_CONSTANT_APN_REQUEST_STARTED; } } @@ -1427,10 +1432,10 @@ public class ConnectivityManager { } if (request != null) { Log.d(TAG, "starting startUsingNetworkFeature for request " + request); - return PhoneConstants.APN_REQUEST_STARTED; + return DEPRECATED_PHONE_CONSTANT_APN_REQUEST_STARTED; } else { Log.d(TAG, " request Failed"); - return PhoneConstants.APN_REQUEST_FAILED; + return DEPRECATED_PHONE_CONSTANT_APN_REQUEST_FAILED; } } @@ -2149,19 +2154,14 @@ public class ConnectivityManager { @Deprecated @UnsupportedAppUsage public boolean getMobileDataEnabled() { - IBinder b = ServiceManager.getService(Context.TELEPHONY_SERVICE); - if (b != null) { - try { - ITelephony it = ITelephony.Stub.asInterface(b); - int subId = SubscriptionManager.getDefaultDataSubscriptionId(); - Log.d("ConnectivityManager", "getMobileDataEnabled()+ subId=" + subId); - boolean retVal = it.isUserDataEnabled(subId); - Log.d("ConnectivityManager", "getMobileDataEnabled()- subId=" + subId - + " retVal=" + retVal); - return retVal; - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } + TelephonyManager tm = mContext.getSystemService(TelephonyManager.class); + if (tm != null) { + int subId = SubscriptionManager.getDefaultDataSubscriptionId(); + Log.d("ConnectivityManager", "getMobileDataEnabled()+ subId=" + subId); + boolean retVal = tm.createForSubscriptionId(subId).isDataEnabled(); + Log.d("ConnectivityManager", "getMobileDataEnabled()- subId=" + subId + + " retVal=" + retVal); + return retVal; } Log.d("ConnectivityManager", "getMobileDataEnabled()- remote exception retVal=false"); return false; diff --git a/core/java/android/net/NetworkKey.java b/core/java/android/net/NetworkKey.java index a101da7b4b9c..04cb877305b9 100644 --- a/core/java/android/net/NetworkKey.java +++ b/core/java/android/net/NetworkKey.java @@ -21,7 +21,7 @@ import android.annotation.Nullable; import android.annotation.SystemApi; import android.net.wifi.ScanResult; import android.net.wifi.WifiInfo; -import android.net.wifi.WifiSsid; +import android.net.wifi.WifiManager; import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; @@ -69,22 +69,25 @@ public class NetworkKey implements Parcelable { */ @Nullable public static NetworkKey createFromScanResult(@Nullable ScanResult result) { - if (result != null && result.wifiSsid != null) { - final String ssid = result.wifiSsid.toString(); - final String bssid = result.BSSID; - if (!TextUtils.isEmpty(ssid) && !ssid.equals(WifiSsid.NONE) - && !TextUtils.isEmpty(bssid)) { - WifiKey wifiKey; - try { - wifiKey = new WifiKey(String.format("\"%s\"", ssid), bssid); - } catch (IllegalArgumentException e) { - Log.e(TAG, "Unable to create WifiKey.", e); - return null; - } - return new NetworkKey(wifiKey); - } + if (result == null) { + return null; + } + final String ssid = result.SSID; + if (TextUtils.isEmpty(ssid) || ssid.equals(WifiManager.UNKNOWN_SSID)) { + return null; + } + final String bssid = result.BSSID; + if (TextUtils.isEmpty(bssid)) { + return null; + } + + try { + final WifiKey wifiKey = new WifiKey(String.format("\"%s\"", ssid), bssid); + return new NetworkKey(wifiKey); + } catch (IllegalArgumentException e) { + Log.e(TAG, "Unable to create WifiKey.", e); + return null; } - return null; } /** @@ -100,7 +103,7 @@ public class NetworkKey implements Parcelable { if (wifiInfo != null) { final String ssid = wifiInfo.getSSID(); final String bssid = wifiInfo.getBSSID(); - if (!TextUtils.isEmpty(ssid) && !ssid.equals(WifiSsid.NONE) + if (!TextUtils.isEmpty(ssid) && !ssid.equals(WifiManager.UNKNOWN_SSID) && !TextUtils.isEmpty(bssid)) { WifiKey wifiKey; try { diff --git a/core/java/android/os/SystemProperties.java b/core/java/android/os/SystemProperties.java index 8b0ffe155fc3..f08e1ff16999 100644 --- a/core/java/android/os/SystemProperties.java +++ b/core/java/android/os/SystemProperties.java @@ -26,6 +26,9 @@ import android.util.MutableInt; import com.android.internal.annotations.GuardedBy; +import dalvik.annotation.optimization.CriticalNative; +import dalvik.annotation.optimization.FastNative; + import libcore.util.HexEncoding; import java.nio.charset.StandardCharsets; @@ -93,18 +96,43 @@ public class SystemProperties { } } + // The one-argument version of native_get used to be a regular native function. Nowadays, + // we use the two-argument form of native_get all the time, but we can't just delete the + // one-argument overload: apps use it via reflection, as the UnsupportedAppUsage annotation + // indicates. Let's just live with having a Java function with a very unusual name. @UnsupportedAppUsage - private static native String native_get(String key); + private static String native_get(String key) { + return native_get(key, ""); + } + + @FastNative @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) private static native String native_get(String key, String def); + @FastNative @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) private static native int native_get_int(String key, int def); + @FastNative @UnsupportedAppUsage private static native long native_get_long(String key, long def); + @FastNative @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) private static native boolean native_get_boolean(String key, boolean def); + + @FastNative + private static native long native_find(String name); + @FastNative + private static native String native_get(long handle); + @CriticalNative + private static native int native_get_int(long handle, int def); + @CriticalNative + private static native long native_get_long(long handle, long def); + @CriticalNative + private static native boolean native_get_boolean(long handle, boolean def); + + // _NOT_ FastNative: native_set performs IPC and can block @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) private static native void native_set(String key, String def); + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) private static native void native_add_change_callback(); private static native void native_report_sysprop_change(); @@ -229,25 +257,27 @@ public class SystemProperties { @SuppressWarnings("unused") // Called from native code. private static void callChangeCallbacks() { + ArrayList<Runnable> callbacks = null; synchronized (sChangeCallbacks) { //Log.i("foo", "Calling " + sChangeCallbacks.size() + " change callbacks!"); if (sChangeCallbacks.size() == 0) { return; } - ArrayList<Runnable> callbacks = new ArrayList<Runnable>(sChangeCallbacks); - final long token = Binder.clearCallingIdentity(); - try { - for (int i = 0; i < callbacks.size(); i++) { - try { - callbacks.get(i).run(); - } catch (Throwable t) { - Log.wtf(TAG, "Exception in SystemProperties change callback", t); - // Ignore and try to go on. - } + callbacks = new ArrayList<Runnable>(sChangeCallbacks); + } + final long token = Binder.clearCallingIdentity(); + try { + for (int i = 0; i < callbacks.size(); i++) { + try { + callbacks.get(i).run(); + } catch (Throwable t) { + // Ignore and try to go on. Don't use wtf here: that + // will cause the process to exit on some builds and break tests. + Log.e(TAG, "Exception in SystemProperties change callback", t); } - } finally { - Binder.restoreCallingIdentity(token); } + } finally { + Binder.restoreCallingIdentity(token); } } @@ -284,4 +314,60 @@ public class SystemProperties { @UnsupportedAppUsage private SystemProperties() { } + + /** + * Look up a property location by name. + * @name name of the property + * @return property handle or {@code null} if property isn't set + * @hide + */ + @Nullable public static Handle find(@NonNull String name) { + long nativeHandle = native_find(name); + if (nativeHandle == 0) { + return null; + } + return new Handle(nativeHandle); + } + + /** + * Handle to a pre-located property. Looking up a property handle in advance allows + * for optimal repeated lookup of a single property. + * @hide + */ + public static final class Handle { + + private final long mNativeHandle; + + /** + * @return Value of the property + */ + @NonNull public String get() { + return native_get(mNativeHandle); + } + /** + * @param def default value + * @return value or {@code def} on parse error + */ + public int getInt(int def) { + return native_get_int(mNativeHandle, def); + } + /** + * @param def default value + * @return value or {@code def} on parse error + */ + public long getLong(long def) { + return native_get_long(mNativeHandle, def); + } + /** + * @param def default value + * @return value or {@code def} on parse error + */ + public boolean getBoolean(boolean def) { + return native_get_boolean(mNativeHandle, def); + } + + private Handle(long nativeHandle) { + mNativeHandle = nativeHandle; + } + } } diff --git a/core/java/android/telephony/PhoneStateListener.java b/core/java/android/telephony/PhoneStateListener.java index 2af827e36696..a65c8fdf50c9 100644 --- a/core/java/android/telephony/PhoneStateListener.java +++ b/core/java/android/telephony/PhoneStateListener.java @@ -184,7 +184,8 @@ public class PhoneStateListener { public static final int LISTEN_CELL_INFO = 0x00000400; /** - * Listen for {@link PreciseCallState.State} of ringing, background and foreground calls. + * Listen for {@link android.telephony.Annotation.PreciseCallStates} of ringing, + * background and foreground calls. * * @hide */ diff --git a/core/java/android/telephony/TelephonyRegistryManager.java b/core/java/android/telephony/TelephonyRegistryManager.java index 456789fb77bc..5c427309e823 100644 --- a/core/java/android/telephony/TelephonyRegistryManager.java +++ b/core/java/android/telephony/TelephonyRegistryManager.java @@ -29,13 +29,13 @@ import android.os.Handler; import android.os.HandlerExecutor; import android.os.RemoteException; import android.os.ServiceManager; -import android.telephony.Annotation; import android.telephony.Annotation.ApnType; import android.telephony.Annotation.CallState; import android.telephony.Annotation.DataActivityType; import android.telephony.Annotation.DataFailureCause; import android.telephony.Annotation.DataState; import android.telephony.Annotation.NetworkType; +import android.telephony.Annotation.PreciseCallStates; import android.telephony.Annotation.RadioPowerState; import android.telephony.Annotation.SimActivationState; import android.telephony.Annotation.SrvccState; @@ -43,7 +43,6 @@ import android.telephony.CallQuality; import android.telephony.CellInfo; import android.telephony.DisconnectCause; import android.telephony.PhoneCapability; -import android.telephony.PreciseCallState.State; import android.telephony.ServiceState; import android.telephony.SignalStrength; import android.telephony.TelephonyManager; @@ -624,8 +623,10 @@ public class TelephonyRegistryManager { * * @hide */ - public void notifyPreciseCallState(int subId, int slotIndex, @State int ringCallPreciseState, - @State int foregroundCallPreciseState, @State int backgroundCallPreciseState) { + public void notifyPreciseCallState(int subId, int slotIndex, + @PreciseCallStates int ringCallPreciseState, + @PreciseCallStates int foregroundCallPreciseState, + @PreciseCallStates int backgroundCallPreciseState) { try { sRegistry.notifyPreciseCallState(slotIndex, subId, ringCallPreciseState, foregroundCallPreciseState, backgroundCallPreciseState); diff --git a/core/java/com/android/internal/app/LocaleHelper.java b/core/java/com/android/internal/app/LocaleHelper.java index aef4dbf41d35..e3d07aaa8fe8 100644 --- a/core/java/com/android/internal/app/LocaleHelper.java +++ b/core/java/com/android/internal/app/LocaleHelper.java @@ -208,7 +208,7 @@ public class LocaleHelper { * @return the maximized Locale instance. */ public static Locale addLikelySubtags(Locale locale) { - return libcore.icu.ICU.addLikelySubtags(locale); + return ULocale.addLikelySubtags(ULocale.forLocale(locale)).toLocale(); } /** diff --git a/core/jni/android_os_SystemProperties.cpp b/core/jni/android_os_SystemProperties.cpp index 87f498a710c1..7f8bec6ce507 100644 --- a/core/jni/android_os_SystemProperties.cpp +++ b/core/jni/android_os_SystemProperties.cpp @@ -17,9 +17,13 @@ #define LOG_TAG "SysPropJNI" +#include <utility> +#include <optional> + #include "android-base/logging.h" +#include "android-base/parsebool.h" +#include "android-base/parseint.h" #include "android-base/properties.h" -#include "cutils/properties.h" #include "utils/misc.h" #include <utils/Log.h> #include "jni.h" @@ -28,86 +32,171 @@ #include <nativehelper/ScopedPrimitiveArray.h> #include <nativehelper/ScopedUtfChars.h> -namespace android -{ +#if defined(__BIONIC__) +# include <sys/system_properties.h> +#else +struct prop_info; +#endif +namespace android { namespace { -template <typename T, typename Handler> -T ConvertKeyAndForward(JNIEnv *env, jstring keyJ, T defJ, Handler handler) { - std::string key; - { - // Scope the String access. If the handler can throw an exception, - // releasing the string characters late would trigger an abort. - ScopedUtfChars key_utf(env, keyJ); - if (key_utf.c_str() == nullptr) { - return defJ; - } - key = key_utf.c_str(); // This will make a copy, but we can't avoid - // with the existing interface in - // android::base. - } - return handler(key, defJ); -} +using android::base::ParseBoolResult; -jstring SystemProperties_getSS(JNIEnv *env, jclass clazz, jstring keyJ, - jstring defJ) +template<typename Functor> +void ReadProperty(const prop_info* prop, Functor&& functor) { - // Using ConvertKeyAndForward is sub-optimal for copying the key string, - // but improves reuse and reasoning over code. - auto handler = [&](const std::string& key, jstring defJ) { - std::string prop_val = android::base::GetProperty(key, ""); - if (!prop_val.empty()) { - return env->NewStringUTF(prop_val.c_str()); - }; - if (defJ != nullptr) { - return defJ; - } - // This function is specified to never return null (or have an - // exception pending). - return env->NewStringUTF(""); +#if defined(__BIONIC__) + auto thunk = [](void* cookie, + const char* /*name*/, + const char* value, + uint32_t /*serial*/) { + std::forward<Functor>(*static_cast<Functor*>(cookie))(value); }; - return ConvertKeyAndForward(env, keyJ, defJ, handler); + __system_property_read_callback(prop, thunk, &functor); +#else + LOG(FATAL) << "fast property access supported only on device"; +#endif } -jstring SystemProperties_getS(JNIEnv *env, jclass clazz, jstring keyJ) +template<typename Functor> +void ReadProperty(JNIEnv* env, jstring keyJ, Functor&& functor) { - return SystemProperties_getSS(env, clazz, keyJ, nullptr); + ScopedUtfChars key(env, keyJ); + if (!key.c_str()) { + return; + } +#if defined(__BIONIC__) + const prop_info* prop = __system_property_find(key.c_str()); + if (!prop) { + return; + } + ReadProperty(prop, std::forward<Functor>(functor)); +#else + std::forward<Functor>(functor)( + android::base::GetProperty(key.c_str(), "").c_str()); +#endif +} + +jstring SystemProperties_getSS(JNIEnv* env, jclass clazz, jstring keyJ, + jstring defJ) +{ + jstring ret = defJ; + ReadProperty(env, keyJ, [&](const char* value) { + if (value[0]) { + ret = env->NewStringUTF(value); + } + }); + if (ret == nullptr && !env->ExceptionCheck()) { + ret = env->NewStringUTF(""); // Legacy behavior + } + return ret; } template <typename T> T SystemProperties_get_integral(JNIEnv *env, jclass, jstring keyJ, T defJ) { - auto handler = [](const std::string& key, T defV) { - return android::base::GetIntProperty<T>(key, defV); - }; - return ConvertKeyAndForward(env, keyJ, defJ, handler); + T ret = defJ; + ReadProperty(env, keyJ, [&](const char* value) { + android::base::ParseInt<T>(value, &ret); + }); + return ret; +} + +static jboolean jbooleanFromParseBoolResult(ParseBoolResult parseResult, jboolean defJ) { + jboolean ret; + switch (parseResult) { + case ParseBoolResult::kError: + ret = defJ; + break; + case ParseBoolResult::kFalse: + ret = JNI_FALSE; + break; + case ParseBoolResult::kTrue: + ret = JNI_TRUE; + break; + } + return ret; } jboolean SystemProperties_get_boolean(JNIEnv *env, jclass, jstring keyJ, jboolean defJ) { - auto handler = [](const std::string& key, jboolean defV) -> jboolean { - bool result = android::base::GetBoolProperty(key, defV); - return result ? JNI_TRUE : JNI_FALSE; - }; - return ConvertKeyAndForward(env, keyJ, defJ, handler); + ParseBoolResult parseResult; + ReadProperty(env, keyJ, [&](const char* value) { + parseResult = android::base::ParseBool(value); + }); + return jbooleanFromParseBoolResult(parseResult, defJ); +} + +jlong SystemProperties_find(JNIEnv* env, jclass, jstring keyJ) +{ +#if defined(__BIONIC__) + ScopedUtfChars key(env, keyJ); + if (!key.c_str()) { + return 0; + } + const prop_info* prop = __system_property_find(key.c_str()); + return reinterpret_cast<jlong>(prop); +#else + LOG(FATAL) << "fast property access supported only on device"; + __builtin_unreachable(); // Silence warning +#endif +} + +jstring SystemProperties_getH(JNIEnv* env, jclass clazz, jlong propJ) +{ + jstring ret; + auto prop = reinterpret_cast<const prop_info*>(propJ); + ReadProperty(prop, [&](const char* value) { + ret = env->NewStringUTF(value); + }); + return ret; +} + +template <typename T> +T SystemProperties_get_integralH(CRITICAL_JNI_PARAMS_COMMA jlong propJ, T defJ) +{ + T ret = defJ; + auto prop = reinterpret_cast<const prop_info*>(propJ); + ReadProperty(prop, [&](const char* value) { + android::base::ParseInt<T>(value, &ret); + }); + return ret; +} + +jboolean SystemProperties_get_booleanH(CRITICAL_JNI_PARAMS_COMMA jlong propJ, jboolean defJ) +{ + ParseBoolResult parseResult; + auto prop = reinterpret_cast<const prop_info*>(propJ); + ReadProperty(prop, [&](const char* value) { + parseResult = android::base::ParseBool(value); + }); + return jbooleanFromParseBoolResult(parseResult, defJ); } void SystemProperties_set(JNIEnv *env, jobject clazz, jstring keyJ, jstring valJ) { - auto handler = [&](const std::string& key, bool) { - std::string val; - if (valJ != nullptr) { - ScopedUtfChars key_utf(env, valJ); - val = key_utf.c_str(); + ScopedUtfChars key(env, keyJ); + if (!key.c_str()) { + return; + } + std::optional<ScopedUtfChars> value; + if (valJ != nullptr) { + value.emplace(env, valJ); + if (!value->c_str()) { + return; } - return android::base::SetProperty(key, val); - }; - if (!ConvertKeyAndForward(env, keyJ, true, handler)) { - // Must have been a failure in SetProperty. + } + bool success; +#if defined(__BIONIC__) + success = !__system_property_set(key.c_str(), value ? value->c_str() : ""); +#else + success = android::base::SetProperty(key.c_str(), value ? value->c_str() : ""); +#endif + if (!success) { jniThrowException(env, "java/lang/RuntimeException", "failed to set system property (check logcat for reason)"); } @@ -157,8 +246,6 @@ void SystemProperties_report_sysprop_change(JNIEnv /**env*/, jobject /*clazz*/) int register_android_os_SystemProperties(JNIEnv *env) { const JNINativeMethod method_table[] = { - { "native_get", "(Ljava/lang/String;)Ljava/lang/String;", - (void*) SystemProperties_getS }, { "native_get", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", (void*) SystemProperties_getSS }, @@ -168,6 +255,18 @@ int register_android_os_SystemProperties(JNIEnv *env) (void*) SystemProperties_get_integral<jlong> }, { "native_get_boolean", "(Ljava/lang/String;Z)Z", (void*) SystemProperties_get_boolean }, + { "native_find", + "(Ljava/lang/String;)J", + (void*) SystemProperties_find }, + { "native_get", + "(J)Ljava/lang/String;", + (void*) SystemProperties_getH }, + { "native_get_int", "(JI)I", + (void*) SystemProperties_get_integralH<jint> }, + { "native_get_long", "(JJ)J", + (void*) SystemProperties_get_integralH<jlong> }, + { "native_get_boolean", "(JZ)Z", + (void*) SystemProperties_get_booleanH }, { "native_set", "(Ljava/lang/String;Ljava/lang/String;)V", (void*) SystemProperties_set }, { "native_add_change_callback", "()V", @@ -179,4 +278,4 @@ int register_android_os_SystemProperties(JNIEnv *env) method_table, NELEM(method_table)); } -}; +} // namespace android diff --git a/core/tests/coretests/src/android/net/NetworkKeyTest.java b/core/tests/coretests/src/android/net/NetworkKeyTest.java index 0f1c71d7c601..c6c0b46d0505 100644 --- a/core/tests/coretests/src/android/net/NetworkKeyTest.java +++ b/core/tests/coretests/src/android/net/NetworkKeyTest.java @@ -22,7 +22,7 @@ import static org.mockito.Mockito.when; import android.net.wifi.ScanResult; import android.net.wifi.WifiInfo; -import android.net.wifi.WifiSsid; +import android.net.wifi.WifiManager; import androidx.test.runner.AndroidJUnit4; @@ -65,7 +65,7 @@ public class NetworkKeyTest { @Test public void createFromWifi_noneSsid() throws Exception { - when(mWifiInfo.getSSID()).thenReturn(WifiSsid.NONE); + when(mWifiInfo.getSSID()).thenReturn(WifiManager.UNKNOWN_SSID); when(mWifiInfo.getBSSID()).thenReturn(VALID_BSSID); assertNull(NetworkKey.createFromWifiInfo(mWifiInfo)); } @@ -106,7 +106,7 @@ public class NetworkKeyTest { } @Test - public void createFromScanResult_nullWifiSsid() { + public void createFromScanResult_nullSsid() { ScanResult scanResult = new ScanResult(); scanResult.BSSID = VALID_BSSID; @@ -114,18 +114,18 @@ public class NetworkKeyTest { } @Test - public void createFromScanResult_emptyWifiSsid() { + public void createFromScanResult_emptySsid() { ScanResult scanResult = new ScanResult(); - scanResult.wifiSsid = WifiSsid.createFromAsciiEncoded(""); + scanResult.SSID = ""; scanResult.BSSID = VALID_BSSID; assertNull(NetworkKey.createFromScanResult(scanResult)); } @Test - public void createFromScanResult_noneWifiSsid() { + public void createFromScanResult_noneSsid() { ScanResult scanResult = new ScanResult(); - scanResult.wifiSsid = WifiSsid.createFromAsciiEncoded(WifiSsid.NONE); + scanResult.SSID = WifiManager.UNKNOWN_SSID; scanResult.BSSID = VALID_BSSID; assertNull(NetworkKey.createFromScanResult(scanResult)); @@ -134,7 +134,7 @@ public class NetworkKeyTest { @Test public void createFromScanResult_nullBssid() { ScanResult scanResult = new ScanResult(); - scanResult.wifiSsid = WifiSsid.createFromAsciiEncoded(VALID_UNQUOTED_SSID); + scanResult.SSID = VALID_UNQUOTED_SSID; assertNull(NetworkKey.createFromScanResult(scanResult)); } @@ -142,7 +142,7 @@ public class NetworkKeyTest { @Test public void createFromScanResult_emptyBssid() { ScanResult scanResult = new ScanResult(); - scanResult.wifiSsid = WifiSsid.createFromAsciiEncoded(VALID_UNQUOTED_SSID); + scanResult.SSID = VALID_UNQUOTED_SSID; scanResult.BSSID = ""; assertNull(NetworkKey.createFromScanResult(scanResult)); @@ -151,16 +151,16 @@ public class NetworkKeyTest { @Test public void createFromScanResult_invalidBssid() { ScanResult scanResult = new ScanResult(); - scanResult.wifiSsid = WifiSsid.createFromAsciiEncoded(VALID_UNQUOTED_SSID); + scanResult.SSID = VALID_UNQUOTED_SSID; scanResult.BSSID = INVALID_BSSID; assertNull(NetworkKey.createFromScanResult(scanResult)); } @Test - public void createFromScanResult_validWifiSsid() { + public void createFromScanResult_validSsid() { ScanResult scanResult = new ScanResult(); - scanResult.wifiSsid = WifiSsid.createFromAsciiEncoded(VALID_UNQUOTED_SSID); + scanResult.SSID = VALID_UNQUOTED_SSID; scanResult.BSSID = VALID_BSSID; NetworkKey expected = new NetworkKey(new WifiKey(VALID_SSID, VALID_BSSID)); diff --git a/core/tests/systemproperties/src/android/os/SystemPropertiesTest.java b/core/tests/systemproperties/src/android/os/SystemPropertiesTest.java index 928351e7de8c..b48ac3347093 100644 --- a/core/tests/systemproperties/src/android/os/SystemPropertiesTest.java +++ b/core/tests/systemproperties/src/android/os/SystemPropertiesTest.java @@ -93,6 +93,27 @@ public class SystemPropertiesTest extends TestCase { } @SmallTest + private static void testHandle() throws Exception { + String value; + SystemProperties.Handle handle = SystemProperties.find("doesnotexist_2341431"); + assertNull(handle); + SystemProperties.set(KEY, "abc"); + handle = SystemProperties.find(KEY); + assertNotNull(handle); + value = handle.get(); + assertEquals("abc", value); + SystemProperties.set(KEY, "blarg"); + value = handle.get(); + assertEquals("blarg", value); + SystemProperties.set(KEY, "1"); + assertEquals(1, handle.getInt(-1)); + assertEquals(1, handle.getLong(-1)); + assertEquals(true, handle.getBoolean(false)); + SystemProperties.set(KEY, ""); + assertEquals(12345, handle.getInt(12345)); + } + + @SmallTest public void testIntegralProperties() throws Exception { testInt("", 123, 123); testInt("", 0, 0); diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 81eb4b355a21..a75d5d696bd0 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -146,6 +146,7 @@ import android.security.Credentials; import android.security.KeyStore; import android.telephony.TelephonyManager; import android.text.TextUtils; +import android.util.ArrayMap; import android.util.ArraySet; import android.util.LocalLog; import android.util.Log; @@ -3050,7 +3051,8 @@ public class ConnectivityService extends IConnectivityManager.Stub } private void handleAsyncChannelHalfConnect(Message msg) { - AsyncChannel ac = (AsyncChannel) msg.obj; + ensureRunningOnConnectivityServiceThread(); + final AsyncChannel ac = (AsyncChannel) msg.obj; if (mNetworkFactoryInfos.containsKey(msg.replyTo)) { if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) { if (VDBG) log("NetworkFactory connected"); @@ -3060,7 +3062,8 @@ public class ConnectivityService extends IConnectivityManager.Stub // A network factory has connected. Send it all current NetworkRequests. for (NetworkRequestInfo nri : mNetworkRequests.values()) { if (nri.request.isListen()) continue; - NetworkAgentInfo nai = getNetworkForRequest(nri.request.requestId); + ensureRunningOnConnectivityServiceThread(); + NetworkAgentInfo nai = nri.mSatisfier; final int score; final int serial; if (nai != null) { @@ -3116,6 +3119,7 @@ public class ConnectivityService extends IConnectivityManager.Stub // ConnectivityService, free its interfaces and clean up. // Must be called on the Handler thread. private void disconnectAndDestroyNetwork(NetworkAgentInfo nai) { + ensureRunningOnConnectivityServiceThread(); if (DBG) { log(nai.name() + " got DISCONNECTED, was satisfying " + nai.numNetworkRequests()); } @@ -3162,14 +3166,17 @@ public class ConnectivityService extends IConnectivityManager.Stub // Remove all previously satisfied requests. for (int i = 0; i < nai.numNetworkRequests(); i++) { NetworkRequest request = nai.requestAt(i); - NetworkAgentInfo currentNetwork = getNetworkForRequest(request.requestId); + final NetworkRequestInfo nri = mNetworkRequests.get(request); + ensureRunningOnConnectivityServiceThread(); + final NetworkAgentInfo currentNetwork = nri.mSatisfier; if (currentNetwork != null && currentNetwork.network.netId == nai.network.netId) { - clearNetworkForRequest(request.requestId); + nri.mSatisfier = null; sendUpdatedScoreToFactories(request, null); } } nai.clearLingerState(); if (nai.isSatisfyingRequest(mDefaultRequest.requestId)) { + mDefaultNetworkNai = null; updateDataActivityTracking(null /* newNetwork */, nai); notifyLockdownVpn(nai); ensureNetworkTransitionWakelock(nai.name()); @@ -3253,6 +3260,7 @@ public class ConnectivityService extends IConnectivityManager.Stub } private void handleRegisterNetworkRequest(NetworkRequestInfo nri) { + ensureRunningOnConnectivityServiceThread(); mNetworkRequests.put(nri.request, nri); mNetworkRequestInfoLogs.log("REGISTER " + nri); if (nri.request.isListen()) { @@ -3264,7 +3272,8 @@ public class ConnectivityService extends IConnectivityManager.Stub } } rematchAllNetworksAndRequests(null, 0); - if (nri.request.isRequest() && getNetworkForRequest(nri.request.requestId) == null) { + ensureRunningOnConnectivityServiceThread(); + if (nri.request.isRequest() && nri.mSatisfier == null) { sendUpdatedScoreToFactories(nri.request, null); } } @@ -3286,6 +3295,7 @@ public class ConnectivityService extends IConnectivityManager.Stub // - UnneededFor.LINGER: foreground NetworkRequests. If a network is unneeded for this reason, // then it should be lingered. private boolean unneeded(NetworkAgentInfo nai, UnneededFor reason) { + ensureRunningOnConnectivityServiceThread(); final int numRequests; switch (reason) { case TEARDOWN: @@ -3310,6 +3320,7 @@ public class ConnectivityService extends IConnectivityManager.Stub // If this Network is already the highest scoring Network for a request, or if // there is hope for it to become one if it validated, then it is needed. + ensureRunningOnConnectivityServiceThread(); if (nri.request.isRequest() && nai.satisfies(nri.request) && (nai.isSatisfyingRequest(nri.request.requestId) || // Note that this catches two important cases: @@ -3319,8 +3330,8 @@ public class ConnectivityService extends IConnectivityManager.Stub // 2. Unvalidated WiFi will not be reaped when validated cellular // is currently satisfying the request. This is desirable when // WiFi ends up validating and out scoring cellular. - getNetworkForRequest(nri.request.requestId).getCurrentScore() < - nai.getCurrentScoreAsValidated())) { + nri.mSatisfier.getCurrentScore() + < nai.getCurrentScoreAsValidated())) { return false; } } @@ -3344,10 +3355,12 @@ public class ConnectivityService extends IConnectivityManager.Stub } private void handleTimedOutNetworkRequest(final NetworkRequestInfo nri) { + ensureRunningOnConnectivityServiceThread(); if (mNetworkRequests.get(nri.request) == null) { return; } - if (getNetworkForRequest(nri.request.requestId) != null) { + ensureRunningOnConnectivityServiceThread(); + if (nri.mSatisfier != null) { return; } if (VDBG || (DBG && nri.request.isRequest())) { @@ -3374,6 +3387,8 @@ public class ConnectivityService extends IConnectivityManager.Stub } private void handleRemoveNetworkRequest(final NetworkRequestInfo nri) { + ensureRunningOnConnectivityServiceThread(); + nri.unlinkDeathRecipient(); mNetworkRequests.remove(nri.request); @@ -3393,7 +3408,8 @@ public class ConnectivityService extends IConnectivityManager.Stub mNetworkRequestInfoLogs.log("RELEASE " + nri); if (nri.request.isRequest()) { boolean wasKept = false; - NetworkAgentInfo nai = getNetworkForRequest(nri.request.requestId); + ensureRunningOnConnectivityServiceThread(); + final NetworkAgentInfo nai = nri.mSatisfier; if (nai != null) { boolean wasBackgroundNetwork = nai.isBackgroundNetwork(); nai.removeRequest(nri.request.requestId); @@ -3410,7 +3426,7 @@ public class ConnectivityService extends IConnectivityManager.Stub } else { wasKept = true; } - clearNetworkForRequest(nri.request.requestId); + nri.mSatisfier = null; if (!wasBackgroundNetwork && nai.isBackgroundNetwork()) { // Went from foreground to background. updateCapabilities(nai.getCurrentScore(), nai, nai.networkCapabilities); @@ -5093,6 +5109,11 @@ public class ConnectivityService extends IConnectivityManager.Stub */ private class NetworkRequestInfo implements IBinder.DeathRecipient { final NetworkRequest request; + // The network currently satisfying this request, or null if none. Must only be touched + // on the handler thread. This only makes sense for network requests and not for listens, + // as defined by NetworkRequest#isRequest(). For listens, this is always null. + @Nullable + NetworkAgentInfo mSatisfier; final PendingIntent mPendingIntent; boolean mPendingIntentSent; private final IBinder mBinder; @@ -5479,16 +5500,6 @@ public class ConnectivityService extends IConnectivityManager.Stub if (DBG) log("unregisterNetworkFactory for " + nfi.name); } - /** - * NetworkAgentInfo supporting a request by requestId. - * These have already been vetted (their Capabilities satisfy the request) - * and the are the highest scored network available. - * the are keyed off the Requests requestId. - */ - // NOTE: Accessed on multiple threads, must be synchronized on itself. - @GuardedBy("mNetworkForRequestId") - private final SparseArray<NetworkAgentInfo> mNetworkForRequestId = new SparseArray<>(); - // NOTE: Accessed on multiple threads, must be synchronized on itself. @GuardedBy("mNetworkForNetId") private final SparseArray<NetworkAgentInfo> mNetworkForNetId = new SparseArray<>(); @@ -5506,7 +5517,11 @@ public class ConnectivityService extends IConnectivityManager.Stub private final HashSet<Integer> mBlockedAppUids = new HashSet<>(); // Note: if mDefaultRequest is changed, NetworkMonitor needs to be updated. + @NonNull private final NetworkRequest mDefaultRequest; + // The NetworkAgentInfo currently satisfying the default request, if any. + @Nullable + private volatile NetworkAgentInfo mDefaultNetworkNai = null; // Request used to optionally keep mobile data active even when higher // priority networks like Wi-Fi are active. @@ -5516,26 +5531,8 @@ public class ConnectivityService extends IConnectivityManager.Stub // priority networks like ethernet are active. private final NetworkRequest mDefaultWifiRequest; - private NetworkAgentInfo getNetworkForRequest(int requestId) { - synchronized (mNetworkForRequestId) { - return mNetworkForRequestId.get(requestId); - } - } - - private void clearNetworkForRequest(int requestId) { - synchronized (mNetworkForRequestId) { - mNetworkForRequestId.remove(requestId); - } - } - - private void setNetworkForRequest(int requestId, NetworkAgentInfo nai) { - synchronized (mNetworkForRequestId) { - mNetworkForRequestId.put(requestId, nai); - } - } - private NetworkAgentInfo getDefaultNetwork() { - return getNetworkForRequest(mDefaultRequest.requestId); + return mDefaultNetworkNai; } @Nullable @@ -6253,7 +6250,7 @@ public class ConnectivityService extends IConnectivityManager.Stub } } - private void makeDefault(NetworkAgentInfo newNetwork) { + private void makeDefault(@NonNull final NetworkAgentInfo newNetwork) { if (DBG) log("Switching to new default network: " + newNetwork); try { @@ -6262,6 +6259,7 @@ public class ConnectivityService extends IConnectivityManager.Stub loge("Exception setting default network :" + e); } + mDefaultNetworkNai = newNetwork; notifyLockdownVpn(newNetwork); handleApplyDefaultProxy(newNetwork.linkProperties.getHttpProxy()); updateTcpBufferSizes(newNetwork.linkProperties.getTcpBufferSizes()); @@ -6325,6 +6323,7 @@ public class ConnectivityService extends IConnectivityManager.Stub // validated) of becoming the highest scoring network. private void rematchNetworkAndRequests(NetworkAgentInfo newNetwork, ReapUnvalidatedNetworks reapUnvalidatedNetworks, long now) { + ensureRunningOnConnectivityServiceThread(); if (!newNetwork.everConnected) return; boolean keep = newNetwork.isVPN(); boolean isNewDefault = false; @@ -6335,10 +6334,8 @@ public class ConnectivityService extends IConnectivityManager.Stub if (VDBG || DDBG) log("rematching " + newNetwork.name()); - // Find and migrate to this Network any NetworkRequests for - // which this network is now the best. - ArrayList<NetworkAgentInfo> affectedNetworks = new ArrayList<>(); - ArrayList<NetworkRequestInfo> addedRequests = new ArrayList<>(); + final ArrayMap<NetworkRequestInfo, NetworkAgentInfo> reassignedRequests = new ArrayMap<>(); + NetworkCapabilities nc = newNetwork.networkCapabilities; if (VDBG) log(" network has: " + nc); for (NetworkRequestInfo nri : mNetworkRequests.values()) { @@ -6348,16 +6345,10 @@ public class ConnectivityService extends IConnectivityManager.Stub // requests or not, and doesn't affect the network's score. if (nri.request.isListen()) continue; - final NetworkAgentInfo currentNetwork = getNetworkForRequest(nri.request.requestId); + ensureRunningOnConnectivityServiceThread(); + final NetworkAgentInfo currentNetwork = nri.mSatisfier; final boolean satisfies = newNetwork.satisfies(nri.request); - if (newNetwork == currentNetwork && satisfies) { - if (VDBG) { - log("Network " + newNetwork.name() + " was already satisfying" + - " request " + nri.request.requestId + ". No change."); - } - keep = true; - continue; - } + if (newNetwork == currentNetwork && satisfies) continue; // check if it satisfies the NetworkCapabilities if (VDBG) log(" checking if request is satisfied: " + nri.request); @@ -6370,39 +6361,55 @@ public class ConnectivityService extends IConnectivityManager.Stub ", newScore = " + score); } if (currentNetwork == null || currentNetwork.getCurrentScore() < score) { - if (VDBG) log("rematch for " + newNetwork.name()); - if (currentNetwork != null) { - if (VDBG || DDBG){ - log(" accepting network in place of " + currentNetwork.name()); - } - currentNetwork.removeRequest(nri.request.requestId); - currentNetwork.lingerRequest(nri.request, now, mLingerDelayMs); - affectedNetworks.add(currentNetwork); - } else { - if (VDBG || DDBG) log(" accepting network in place of null"); - } - newNetwork.unlingerRequest(nri.request); - setNetworkForRequest(nri.request.requestId, newNetwork); - if (!newNetwork.addRequest(nri.request)) { - Slog.wtf(TAG, "BUG: " + newNetwork.name() + " already has " + nri.request); + reassignedRequests.put(nri, newNetwork); + } + } else if (newNetwork.isSatisfyingRequest(nri.request.requestId)) { + reassignedRequests.put(nri, null); + } + } + + // Find and migrate to this Network any NetworkRequests for + // which this network is now the best. + final ArrayList<NetworkAgentInfo> removedRequests = new ArrayList<>(); + final ArrayList<NetworkRequestInfo> addedRequests = new ArrayList<>(); + for (final Map.Entry<NetworkRequestInfo, NetworkAgentInfo> entry : + reassignedRequests.entrySet()) { + final NetworkRequestInfo nri = entry.getKey(); + final NetworkAgentInfo previousSatisfier = nri.mSatisfier; + final NetworkAgentInfo newSatisfier = entry.getValue(); + if (newSatisfier != null) { + if (VDBG) log("rematch for " + newSatisfier.name()); + if (previousSatisfier != null) { + if (VDBG || DDBG) { + log(" accepting network in place of " + previousSatisfier.name()); } - addedRequests.add(nri); - keep = true; - // Tell NetworkFactories about the new score, so they can stop - // trying to connect if they know they cannot match it. - // TODO - this could get expensive if we have a lot of requests for this - // network. Think about if there is a way to reduce this. Push - // netid->request mapping to each factory? - sendUpdatedScoreToFactories(nri.request, newNetwork); - if (isDefaultRequest(nri)) { - isNewDefault = true; - oldDefaultNetwork = currentNetwork; - if (currentNetwork != null) { - mLingerMonitor.noteLingerDefaultNetwork(currentNetwork, newNetwork); - } + previousSatisfier.removeRequest(nri.request.requestId); + previousSatisfier.lingerRequest(nri.request, now, mLingerDelayMs); + removedRequests.add(previousSatisfier); + } else { + if (VDBG || DDBG) log(" accepting network in place of null"); + } + newSatisfier.unlingerRequest(nri.request); + nri.mSatisfier = newSatisfier; + if (!newSatisfier.addRequest(nri.request)) { + Slog.wtf(TAG, "BUG: " + newSatisfier.name() + " already has " + nri.request); + } + addedRequests.add(nri); + keep = true; + // Tell NetworkFactories about the new score, so they can stop + // trying to connect if they know they cannot match it. + // TODO - this could get expensive if we have a lot of requests for this + // network. Think about if there is a way to reduce this. Push + // netid->request mapping to each factory? + sendUpdatedScoreToFactories(nri.request, newSatisfier); + if (isDefaultRequest(nri)) { + isNewDefault = true; + oldDefaultNetwork = previousSatisfier; + if (previousSatisfier != null) { + mLingerMonitor.noteLingerDefaultNetwork(previousSatisfier, newSatisfier); } } - } else if (newNetwork.isSatisfyingRequest(nri.request.requestId)) { + } else { // If "newNetwork" is listed as satisfying "nri" but no longer satisfies "nri", // mark it as no longer satisfying "nri". Because networks are processed by // rematchAllNetworksAndRequests() in descending score order, "currentNetwork" will @@ -6415,13 +6422,14 @@ public class ConnectivityService extends IConnectivityManager.Stub " request " + nri.request.requestId); } newNetwork.removeRequest(nri.request.requestId); - if (currentNetwork == newNetwork) { - clearNetworkForRequest(nri.request.requestId); + if (previousSatisfier == newNetwork) { + nri.mSatisfier = null; + if (isDefaultRequest(nri)) mDefaultNetworkNai = null; sendUpdatedScoreToFactories(nri.request, null); } else { Slog.wtf(TAG, "BUG: Removing request " + nri.request.requestId + " from " + newNetwork.name() + - " without updating mNetworkForRequestId or factories!"); + " without updating mSatisfier or factories!"); } // TODO: Technically, sending CALLBACK_LOST here is // incorrect if there is a replacement network currently @@ -6433,6 +6441,7 @@ public class ConnectivityService extends IConnectivityManager.Stub callCallbackForRequest(nri, newNetwork, ConnectivityManager.CALLBACK_LOST, 0); } } + if (isNewDefault) { updateDataActivityTracking(newNetwork, oldDefaultNetwork); // Notify system services that this network is up. @@ -6472,7 +6481,7 @@ public class ConnectivityService extends IConnectivityManager.Stub // Linger any networks that are no longer needed. This should be done after sending the // available callback for newNetwork. - for (NetworkAgentInfo nai : affectedNetworks) { + for (NetworkAgentInfo nai : removedRequests) { updateLingerState(nai, now); } // Possibly unlinger newNetwork. Unlingering a network does not send any callbacks so it diff --git a/services/core/java/com/android/server/pm/OWNERS b/services/core/java/com/android/server/pm/OWNERS index 62ea95b21865..f8c173f6a9c1 100644 --- a/services/core/java/com/android/server/pm/OWNERS +++ b/services/core/java/com/android/server/pm/OWNERS @@ -32,6 +32,9 @@ per-file CrossProfileIntentFilter.java = omakoto@google.com, yamasani@google.com per-file CrossProfileIntentResolver.java = omakoto@google.com, yamasani@google.com per-file UserManagerService.java = omakoto@google.com, yamasani@google.com per-file UserRestrictionsUtils.java = omakoto@google.com, rubinxu@google.com, sandness@google.com, yamasani@google.com +per-file UserSystemPackageInstaller.java = bookatz@google.com, omakoto@google.com, yamasani@google.com +per-file UserTypeDetails.java = bookatz@google.com, omakoto@google.com, yamasani@google.com +per-file UserTypeFactory.java = bookatz@google.com, omakoto@google.com, yamasani@google.com # security per-file KeySetHandle.java = cbrubaker@google.com, nnk@google.com diff --git a/services/core/java/com/android/server/RecoverySystemService.java b/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java index 997178e1582b..d78aaa5f9c9d 100644 --- a/services/core/java/com/android/server/RecoverySystemService.java +++ b/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.server; +package com.android.server.recoverysystem; import android.content.Context; import android.net.LocalSocket; @@ -27,6 +27,8 @@ import android.os.RemoteException; import android.os.SystemProperties; import android.util.Slog; +import com.android.server.SystemService; + import libcore.io.IoUtils; import java.io.DataInputStream; diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 16c60ca3997a..c1b7a50a8623 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -135,6 +135,7 @@ import com.android.server.policy.role.LegacyRoleResolutionPolicy; import com.android.server.power.PowerManagerService; import com.android.server.power.ShutdownThread; import com.android.server.power.ThermalManagerService; +import com.android.server.recoverysystem.RecoverySystemService; import com.android.server.restrictions.RestrictionsManagerService; import com.android.server.role.RoleManagerService; import com.android.server.rollback.RollbackManagerService; diff --git a/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java index e9e96c9c7efb..8fd8d0461e75 100644 --- a/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java @@ -56,6 +56,7 @@ import android.net.WifiKey; import android.net.wifi.ScanResult; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiInfo; +import android.net.wifi.WifiManager; import android.net.wifi.WifiSsid; import android.os.Binder; import android.os.Handler; @@ -719,7 +720,7 @@ public class NetworkScoreServiceTest { @Test public void testCurrentNetworkScoreCacheFilter_invalidWifiInfo_noneSsid() throws Exception { - when(mWifiInfo.getSSID()).thenReturn(WifiSsid.NONE); + when(mWifiInfo.getSSID()).thenReturn(WifiManager.UNKNOWN_SSID); NetworkScoreService.CurrentNetworkScoreCacheFilter cacheFilter = new NetworkScoreService.CurrentNetworkScoreCacheFilter(() -> mWifiInfo); @@ -793,7 +794,7 @@ public class NetworkScoreServiceTest { List<ScanResult> invalidScanResults = Lists.newArrayList( new ScanResult(), createScanResult("", SCORED_NETWORK.networkKey.wifiKey.bssid), - createScanResult(WifiSsid.NONE, SCORED_NETWORK.networkKey.wifiKey.bssid), + createScanResult(WifiManager.UNKNOWN_SSID, SCORED_NETWORK.networkKey.wifiKey.bssid), createScanResult(SSID, null), createScanResult(SSID, INVALID_BSSID) ); diff --git a/telecomm/java/android/telecom/Conference.java b/telecomm/java/android/telecom/Conference.java index d669e905e4df..58abf0051539 100644 --- a/telecomm/java/android/telecom/Conference.java +++ b/telecomm/java/android/telecom/Conference.java @@ -24,6 +24,7 @@ import android.net.Uri; import android.os.Bundle; import android.os.SystemClock; import android.telecom.Connection.VideoProvider; +import android.telephony.Annotation.RilRadioTechnology; import android.telephony.ServiceState; import android.telephony.TelephonyManager; import android.util.ArraySet; diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java index e2f5d0bba0b0..4c22ba9715b0 100644 --- a/telecomm/java/android/telecom/Connection.java +++ b/telecomm/java/android/telecom/Connection.java @@ -35,6 +35,7 @@ import android.os.Message; import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.os.SystemClock; +import android.telephony.Annotation.RilRadioTechnology; import android.telephony.ServiceState; import android.telephony.TelephonyManager; import android.util.ArraySet; diff --git a/telephony/java/android/telephony/Annotation.java b/telephony/java/android/telephony/Annotation.java index a884a7039d5b..72f758eba39a 100644 --- a/telephony/java/android/telephony/Annotation.java +++ b/telephony/java/android/telephony/Annotation.java @@ -469,4 +469,44 @@ public class Annotation { @Retention(RetentionPolicy.SOURCE) public @interface DataFailureCause { } + + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = {"PRECISE_CALL_STATE_"}, + value = { + PreciseCallState.PRECISE_CALL_STATE_NOT_VALID, + PreciseCallState.PRECISE_CALL_STATE_IDLE, + PreciseCallState.PRECISE_CALL_STATE_ACTIVE, + PreciseCallState.PRECISE_CALL_STATE_HOLDING, + PreciseCallState.PRECISE_CALL_STATE_DIALING, + PreciseCallState.PRECISE_CALL_STATE_ALERTING, + PreciseCallState. PRECISE_CALL_STATE_INCOMING, + PreciseCallState.PRECISE_CALL_STATE_WAITING, + PreciseCallState.PRECISE_CALL_STATE_DISCONNECTED, + PreciseCallState.PRECISE_CALL_STATE_DISCONNECTING}) + public @interface PreciseCallStates {} + + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = {"RIL_RADIO_TECHNOLOGY_" }, value = { + ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN, + ServiceState.RIL_RADIO_TECHNOLOGY_GPRS, + ServiceState.RIL_RADIO_TECHNOLOGY_EDGE, + ServiceState.RIL_RADIO_TECHNOLOGY_UMTS, + ServiceState.RIL_RADIO_TECHNOLOGY_IS95A, + ServiceState.RIL_RADIO_TECHNOLOGY_IS95B, + ServiceState.RIL_RADIO_TECHNOLOGY_1xRTT, + ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_0, + ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_A, + ServiceState.RIL_RADIO_TECHNOLOGY_HSDPA, + ServiceState.RIL_RADIO_TECHNOLOGY_HSUPA, + ServiceState.RIL_RADIO_TECHNOLOGY_HSPA, + ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_B, + ServiceState.RIL_RADIO_TECHNOLOGY_EHRPD, + ServiceState.RIL_RADIO_TECHNOLOGY_LTE, + ServiceState.RIL_RADIO_TECHNOLOGY_HSPAP, + ServiceState.RIL_RADIO_TECHNOLOGY_GSM, + ServiceState.RIL_RADIO_TECHNOLOGY_TD_SCDMA, + ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN, + ServiceState.RIL_RADIO_TECHNOLOGY_LTE_CA, + ServiceState.RIL_RADIO_TECHNOLOGY_NR}) + public @interface RilRadioTechnology {} } diff --git a/telephony/java/android/telephony/PreciseCallState.java b/telephony/java/android/telephony/PreciseCallState.java index f929649453b9..9f75332c4a03 100644 --- a/telephony/java/android/telephony/PreciseCallState.java +++ b/telephony/java/android/telephony/PreciseCallState.java @@ -23,6 +23,7 @@ import android.annotation.SystemApi; import android.annotation.UnsupportedAppUsage; import android.os.Parcel; import android.os.Parcelable; +import android.telephony.Annotation.PreciseCallStates; import android.telephony.DisconnectCause; import android.telephony.PreciseDisconnectCause; @@ -48,22 +49,6 @@ import java.util.Objects; @SystemApi public final class PreciseCallState implements Parcelable { - /** @hide */ - @Retention(RetentionPolicy.SOURCE) - @IntDef(prefix = {"PRECISE_CALL_STATE_"}, - value = { - PRECISE_CALL_STATE_NOT_VALID, - PRECISE_CALL_STATE_IDLE, - PRECISE_CALL_STATE_ACTIVE, - PRECISE_CALL_STATE_HOLDING, - PRECISE_CALL_STATE_DIALING, - PRECISE_CALL_STATE_ALERTING, - PRECISE_CALL_STATE_INCOMING, - PRECISE_CALL_STATE_WAITING, - PRECISE_CALL_STATE_DISCONNECTED, - PRECISE_CALL_STATE_DISCONNECTING}) - public @interface State {} - /** Call state is not valid (Not received a call state). */ public static final int PRECISE_CALL_STATE_NOT_VALID = -1; /** Call state: No activity. */ @@ -85,9 +70,9 @@ public final class PreciseCallState implements Parcelable { /** Call state: Disconnecting. */ public static final int PRECISE_CALL_STATE_DISCONNECTING = 8; - private @State int mRingingCallState = PRECISE_CALL_STATE_NOT_VALID; - private @State int mForegroundCallState = PRECISE_CALL_STATE_NOT_VALID; - private @State int mBackgroundCallState = PRECISE_CALL_STATE_NOT_VALID; + private @PreciseCallStates int mRingingCallState = PRECISE_CALL_STATE_NOT_VALID; + private @PreciseCallStates int mForegroundCallState = PRECISE_CALL_STATE_NOT_VALID; + private @PreciseCallStates int mBackgroundCallState = PRECISE_CALL_STATE_NOT_VALID; private int mDisconnectCause = DisconnectCause.NOT_VALID; private int mPreciseDisconnectCause = PreciseDisconnectCause.NOT_VALID; @@ -97,8 +82,9 @@ public final class PreciseCallState implements Parcelable { * @hide */ @UnsupportedAppUsage - public PreciseCallState(@State int ringingCall, @State int foregroundCall, - @State int backgroundCall, int disconnectCause, + public PreciseCallState(@PreciseCallStates int ringingCall, + @PreciseCallStates int foregroundCall, + @PreciseCallStates int backgroundCall, int disconnectCause, int preciseDisconnectCause) { mRingingCallState = ringingCall; mForegroundCallState = foregroundCall; @@ -131,21 +117,21 @@ public final class PreciseCallState implements Parcelable { /** * Returns the precise ringing call state. */ - public @State int getRingingCallState() { + public @PreciseCallStates int getRingingCallState() { return mRingingCallState; } /** * Returns the precise foreground call state. */ - public @State int getForegroundCallState() { + public @PreciseCallStates int getForegroundCallState() { return mForegroundCallState; } /** * Returns the precise background call state. */ - public @State int getBackgroundCallState() { + public @PreciseCallStates int getBackgroundCallState() { return mBackgroundCallState; } diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java index 3fd8990ffc9a..1e601cf3de5f 100644 --- a/telephony/java/android/telephony/ServiceState.java +++ b/telephony/java/android/telephony/ServiceState.java @@ -30,6 +30,7 @@ import android.os.Parcelable; import android.telephony.AccessNetworkConstants.AccessNetworkType; import android.telephony.AccessNetworkConstants.TransportType; import android.telephony.Annotation.NetworkType; +import android.telephony.Annotation.RilRadioTechnology; import android.telephony.NetworkRegistrationInfo.Domain; import android.telephony.NetworkRegistrationInfo.NRState; import android.text.TextUtils; @@ -155,32 +156,6 @@ public class ServiceState implements Parcelable { */ public static final int DUPLEX_MODE_TDD = 2; - /** @hide */ - @Retention(RetentionPolicy.SOURCE) - @IntDef(prefix = { "RIL_RADIO_TECHNOLOGY_" }, - value = { - RIL_RADIO_TECHNOLOGY_UNKNOWN, - RIL_RADIO_TECHNOLOGY_GPRS, - RIL_RADIO_TECHNOLOGY_EDGE, - RIL_RADIO_TECHNOLOGY_UMTS, - RIL_RADIO_TECHNOLOGY_IS95A, - RIL_RADIO_TECHNOLOGY_IS95B, - RIL_RADIO_TECHNOLOGY_1xRTT, - RIL_RADIO_TECHNOLOGY_EVDO_0, - RIL_RADIO_TECHNOLOGY_EVDO_A, - RIL_RADIO_TECHNOLOGY_HSDPA, - RIL_RADIO_TECHNOLOGY_HSUPA, - RIL_RADIO_TECHNOLOGY_HSPA, - RIL_RADIO_TECHNOLOGY_EVDO_B, - RIL_RADIO_TECHNOLOGY_EHRPD, - RIL_RADIO_TECHNOLOGY_LTE, - RIL_RADIO_TECHNOLOGY_HSPAP, - RIL_RADIO_TECHNOLOGY_GSM, - RIL_RADIO_TECHNOLOGY_TD_SCDMA, - RIL_RADIO_TECHNOLOGY_IWLAN, - RIL_RADIO_TECHNOLOGY_LTE_CA, - RIL_RADIO_TECHNOLOGY_NR}) - public @interface RilRadioTechnology {} /** * Available radio technologies for GSM, UMTS and CDMA. * Duplicates the constants from hardware/radio/include/ril.h diff --git a/telephony/java/android/telephony/SmsCbLocation.java b/telephony/java/android/telephony/SmsCbLocation.java index adf7154b4e07..663e8e25a115 100644 --- a/telephony/java/android/telephony/SmsCbLocation.java +++ b/telephony/java/android/telephony/SmsCbLocation.java @@ -65,9 +65,12 @@ public final class SmsCbLocation implements Parcelable { /** * Construct a location object for the PLMN, LAC, and Cell ID. This class is immutable, so * the same object can be reused for multiple broadcasts. - * @hide + * + * @param plmn the MCC/MNC of the network + * @param lac the GSM location area code, or UMTS service area code + * @param cid the GSM or UMTS cell ID */ - public SmsCbLocation(String plmn, int lac, int cid) { + public SmsCbLocation(@NonNull String plmn, int lac, int cid) { mPlmn = plmn; mLac = lac; mCid = cid; diff --git a/telephony/java/android/telephony/SmsCbMessage.java b/telephony/java/android/telephony/SmsCbMessage.java index 3e044e52d28b..737ead1f8131 100644 --- a/telephony/java/android/telephony/SmsCbMessage.java +++ b/telephony/java/android/telephony/SmsCbMessage.java @@ -138,8 +138,8 @@ public final class SmsCbMessage implements Parcelable { public @interface MessagePriority {} /** - * ATIS-0700041 Section 5.2.8 WAC Geo-Fencing Maximum Wait Time Table 12. - * @hide + * Integer indicating that the maximum wait time is not set. + * Based on ATIS-0700041 Section 5.2.8 WAC Geo-Fencing Maximum Wait Time Table 12. */ public static final int MAXIMUM_WAIT_TIME_NOT_SET = 255; @@ -209,6 +209,7 @@ public final class SmsCbMessage implements Parcelable { /** * Create a new SmsCbMessage with the specified data. + * @hide */ public SmsCbMessage(int messageFormat, int geographicalScope, int serialNumber, @NonNull SmsCbLocation location, int serviceCategory, @Nullable String language, @@ -221,14 +222,14 @@ public final class SmsCbMessage implements Parcelable { } /** - * Create a new {@link SmsCbMessage} with the warning area coordinates information. - * @hide + * Create a new {@link SmsCbMessage} with the specified data, including warning area + * coordinates information. */ public SmsCbMessage(int messageFormat, int geographicalScope, int serialNumber, - SmsCbLocation location, int serviceCategory, String language, String body, - int priority, SmsCbEtwsInfo etwsWarningInfo, SmsCbCmasInfo cmasWarningInfo, - int maximumWaitTimeSec, List<Geometry> geometries, long receivedTimeMillis, - int slotIndex) { + @NonNull SmsCbLocation location, int serviceCategory, @Nullable String language, + @Nullable String body, int priority, @Nullable SmsCbEtwsInfo etwsWarningInfo, + @Nullable SmsCbCmasInfo cmasWarningInfo, int maximumWaitTimeSec, + @Nullable List<Geometry> geometries, long receivedTimeMillis, int slotIndex) { mMessageFormat = messageFormat; mGeographicalScope = geographicalScope; mSerialNumber = serialNumber; diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java index 9d1b7a918327..3c890a18e344 100644 --- a/telephony/java/android/telephony/SubscriptionManager.java +++ b/telephony/java/android/telephony/SubscriptionManager.java @@ -61,6 +61,7 @@ import android.telephony.euicc.EuiccManager; import android.telephony.ims.ImsMmTelManager; import android.util.DisplayMetrics; import android.util.Log; +import android.util.Pair; import com.android.internal.telephony.ISetOpportunisticDataCallback; import com.android.internal.telephony.ISub; @@ -76,6 +77,7 @@ import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Executor; import java.util.concurrent.TimeUnit; import java.util.function.Consumer; @@ -910,6 +912,11 @@ public class SubscriptionManager { private final Context mContext; private volatile INetworkPolicyManager mNetworkPolicy; + // Cache of Resource that has been created in getResourcesForSubId. Key is a Pair containing + // the Context and subId. + private static final Map<Pair<Context, Integer>, Resources> sResourcesCache = + new ConcurrentHashMap<>(); + /** * A listener class for monitoring changes to {@link SubscriptionInfo} records. * <p> @@ -2304,8 +2311,20 @@ public class SubscriptionManager { * @return Resources associated with Subscription. * @hide */ + @NonNull public static Resources getResourcesForSubId(Context context, int subId, boolean useRootLocale) { + // Check if resources for this context and subId already exist in the resource cache. + // Resources that use the root locale are not cached. + Pair<Context, Integer> cacheKey = null; + if (isValidSubscriptionId(subId) && !useRootLocale) { + cacheKey = Pair.create(context, subId); + if (sResourcesCache.containsKey(cacheKey)) { + // Cache hit. Use cached Resources. + return sResourcesCache.get(cacheKey); + } + } + final SubscriptionInfo subInfo = SubscriptionManager.from(context).getActiveSubscriptionInfo(subId); @@ -2325,7 +2344,13 @@ public class SubscriptionManager { DisplayMetrics metrics = context.getResources().getDisplayMetrics(); DisplayMetrics newMetrics = new DisplayMetrics(); newMetrics.setTo(metrics); - return new Resources(context.getResources().getAssets(), newMetrics, newConfig); + Resources res = new Resources(context.getResources().getAssets(), newMetrics, newConfig); + + if (cacheKey != null) { + // Save the newly created Resources in the resource cache. + sResourcesCache.put(cacheKey, res); + } + return res; } /** diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index 8163a6642089..e99465d58764 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -8832,7 +8832,10 @@ public class TelephonyManager { @Deprecated public boolean isTtyModeSupported() { try { - TelecomManager telecomManager = TelecomManager.from(mContext); + TelecomManager telecomManager = null; + if (mContext != null) { + telecomManager = mContext.getSystemService(TelecomManager.class); + } if (telecomManager != null) { return telecomManager.isTtySupported(); } diff --git a/test-mock/src/android/test/mock/MockContext.java b/test-mock/src/android/test/mock/MockContext.java index 727684eca7ea..1de6260f3719 100644 --- a/test-mock/src/android/test/mock/MockContext.java +++ b/test-mock/src/android/test/mock/MockContext.java @@ -765,6 +765,12 @@ public class MockContext extends Context { /** {@hide} */ @Override + public Context createContextAsUser(UserHandle user, @CreatePackageOptions int flags) { + throw new UnsupportedOperationException(); + } + + /** {@hide} */ + @Override public int getUserId() { throw new UnsupportedOperationException(); } diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java index 2f963efd09d5..b53b2aaaf547 100644 --- a/wifi/java/android/net/wifi/WifiManager.java +++ b/wifi/java/android/net/wifi/WifiManager.java @@ -1128,6 +1128,9 @@ public class WifiManager { */ private static final int MAX_ACTIVE_LOCKS = 50; + /** Indicates an invalid SSID. */ + public static final String UNKNOWN_SSID = "<unknown ssid>"; + /* Number of currently active WifiLocks and MulticastLocks */ @UnsupportedAppUsage private int mActiveLockCount; @@ -2326,7 +2329,7 @@ public class WifiManager { * <p> * In the connected state, access to the SSID and BSSID requires * the same permissions as {@link #getScanResults}. If such access is not allowed, - * {@link WifiInfo#getSSID} will return {@code "<unknown ssid>"} and + * {@link WifiInfo#getSSID} will return {@link #UNKNOWN_SSID} and * {@link WifiInfo#getBSSID} will return {@code "02:00:00:00:00:00"}. * * @return the Wi-Fi information, contained in {@link WifiInfo}. diff --git a/wifi/java/android/net/wifi/WifiSsid.java b/wifi/java/android/net/wifi/WifiSsid.java index 70ca0882d7da..f187e1042c58 100644 --- a/wifi/java/android/net/wifi/WifiSsid.java +++ b/wifi/java/android/net/wifi/WifiSsid.java @@ -48,7 +48,7 @@ public class WifiSsid implements Parcelable { private static final int HEX_RADIX = 16; @UnsupportedAppUsage - public static final String NONE = "<unknown ssid>"; + public static final String NONE = WifiManager.UNKNOWN_SSID; private WifiSsid() { } |