Merge "Prevent Closure of Underlying Socket FDs"
diff --git a/Android.bp b/Android.bp
index d4b15ca..facc741 100644
--- a/Android.bp
+++ b/Android.bp
@@ -248,6 +248,7 @@
"core/java/android/service/euicc/IGetEuiccInfoCallback.aidl",
"core/java/android/service/euicc/IGetEuiccProfileInfoListCallback.aidl",
"core/java/android/service/euicc/IGetOtaStatusCallback.aidl",
+ "core/java/android/service/euicc/IOtaStatusChangedCallback.aidl",
"core/java/android/service/euicc/IRetainSubscriptionsForFactoryResetCallback.aidl",
"core/java/android/service/euicc/ISwitchToSubscriptionCallback.aidl",
"core/java/android/service/euicc/IUpdateSubscriptionNicknameCallback.aidl",
@@ -509,7 +510,9 @@
"telephony/java/com/android/internal/telephony/ITelephony.aidl",
"telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl",
"telephony/java/com/android/internal/telephony/IWapPushManager.aidl",
+ "telephony/java/com/android/internal/telephony/euicc/IEuiccCardController.aidl",
"telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl",
+ "telephony/java/com/android/internal/telephony/euicc/IGetAllProfilesCallback.aidl",
"wifi/java/android/net/wifi/IWifiManager.aidl",
"wifi/java/android/net/wifi/aware/IWifiAwareEventCallback.aidl",
"wifi/java/android/net/wifi/aware/IWifiAwareManager.aidl",
@@ -595,6 +598,7 @@
"android.hardware.vibrator-V1.0-java-constants",
"android.hardware.vibrator-V1.1-java-constants",
"android.hardware.wifi-V1.0-java-constants",
+ "android.hardware.radio-V1.0-java",
],
// Loaded with System.loadLibrary by android.view.textclassifier
diff --git a/Android.mk b/Android.mk
index 9877557..cf6aa2a 100644
--- a/Android.mk
+++ b/Android.mk
@@ -82,7 +82,7 @@
# to document and check apis
files_to_check_apis := \
$(call find-other-java-files, \
- legacy-test/src \
+ test-base/src \
$(non_base_dirs) \
)
@@ -698,4 +698,4 @@
include $(call first-makefiles-under,$(LOCAL_PATH))
endif
-endif # ANDROID_BUILD_EMBEDDED
+endif # ANDROID_BUILD_EMBEDDED
\ No newline at end of file
diff --git a/api/current.txt b/api/current.txt
index 50e93b8..bfed6d2 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -19873,6 +19873,13 @@
ctor public ICUUncheckedIOException(java.lang.String, java.lang.Throwable);
}
+ public class IllformedLocaleException extends java.lang.RuntimeException {
+ ctor public IllformedLocaleException();
+ ctor public IllformedLocaleException(java.lang.String);
+ ctor public IllformedLocaleException(java.lang.String, int);
+ method public int getErrorIndex();
+ }
+
public class IndianCalendar extends android.icu.util.Calendar {
ctor public IndianCalendar();
ctor public IndianCalendar(android.icu.util.TimeZone);
@@ -19957,6 +19964,32 @@
field public static final int TAISHO;
}
+ public final class LocaleData {
+ method public static android.icu.util.VersionInfo getCLDRVersion();
+ method public java.lang.String getDelimiter(int);
+ method public static final android.icu.util.LocaleData getInstance(android.icu.util.ULocale);
+ method public static final android.icu.util.LocaleData getInstance();
+ method public static final android.icu.util.LocaleData.MeasurementSystem getMeasurementSystem(android.icu.util.ULocale);
+ method public boolean getNoSubstitute();
+ method public static final android.icu.util.LocaleData.PaperSize getPaperSize(android.icu.util.ULocale);
+ method public void setNoSubstitute(boolean);
+ field public static final int ALT_QUOTATION_END = 3; // 0x3
+ field public static final int ALT_QUOTATION_START = 2; // 0x2
+ field public static final int QUOTATION_END = 1; // 0x1
+ field public static final int QUOTATION_START = 0; // 0x0
+ }
+
+ public static final class LocaleData.MeasurementSystem {
+ field public static final android.icu.util.LocaleData.MeasurementSystem SI;
+ field public static final android.icu.util.LocaleData.MeasurementSystem UK;
+ field public static final android.icu.util.LocaleData.MeasurementSystem US;
+ }
+
+ public static final class LocaleData.PaperSize {
+ method public int getHeight();
+ method public int getWidth();
+ }
+
public class Measure {
ctor public Measure(java.lang.Number, android.icu.util.MeasureUnit);
method public java.lang.Number getNumber();
@@ -25906,10 +25939,10 @@
}
public final class MacAddress implements android.os.Parcelable {
- method public int addressType();
method public int describeContents();
method public static android.net.MacAddress fromBytes(byte[]);
method public static android.net.MacAddress fromString(java.lang.String);
+ method public int getAddressType();
method public boolean isLocallyAssigned();
method public byte[] toByteArray();
method public java.lang.String toOuiString();
@@ -25919,7 +25952,6 @@
field public static final int TYPE_BROADCAST = 3; // 0x3
field public static final int TYPE_MULTICAST = 2; // 0x2
field public static final int TYPE_UNICAST = 1; // 0x1
- field public static final int TYPE_UNKNOWN = 0; // 0x0
}
public class MailTo {
@@ -37414,6 +37446,7 @@
public class CarrierIdentifier implements android.os.Parcelable {
ctor public CarrierIdentifier(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String);
+ ctor public CarrierIdentifier(byte[], java.lang.String, java.lang.String);
method public int describeContents();
method public java.lang.String getGid1();
method public java.lang.String getGid2();
@@ -40095,8 +40128,13 @@
field public static final java.lang.String KEY_WORLD_PHONE_BOOL = "world_phone_bool";
}
- public final class CellIdentityCdma implements android.os.Parcelable {
+ public abstract class CellIdentity implements android.os.Parcelable {
method public int describeContents();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.telephony.CellIdentity> CREATOR;
+ }
+
+ public final class CellIdentityCdma extends android.telephony.CellIdentity {
method public int getBasestationId();
method public int getLatitude();
method public int getLongitude();
@@ -40108,8 +40146,7 @@
field public static final android.os.Parcelable.Creator<android.telephony.CellIdentityCdma> CREATOR;
}
- public final class CellIdentityGsm implements android.os.Parcelable {
- method public int describeContents();
+ public final class CellIdentityGsm extends android.telephony.CellIdentity {
method public int getArfcn();
method public int getBsic();
method public int getCid();
@@ -40126,8 +40163,7 @@
field public static final android.os.Parcelable.Creator<android.telephony.CellIdentityGsm> CREATOR;
}
- public final class CellIdentityLte implements android.os.Parcelable {
- method public int describeContents();
+ public final class CellIdentityLte extends android.telephony.CellIdentity {
method public int getCi();
method public int getEarfcn();
method public deprecated int getMcc();
@@ -40143,8 +40179,17 @@
field public static final android.os.Parcelable.Creator<android.telephony.CellIdentityLte> CREATOR;
}
- public final class CellIdentityWcdma implements android.os.Parcelable {
- method public int describeContents();
+ public final class CellIdentityTdscdma extends android.telephony.CellIdentity {
+ method public int getCid();
+ method public int getCpid();
+ method public int getLac();
+ method public java.lang.String getMccStr();
+ method public java.lang.String getMncStr();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.telephony.CellIdentityTdscdma> CREATOR;
+ }
+
+ public final class CellIdentityWcdma extends android.telephony.CellIdentity {
method public int getCid();
method public int getLac();
method public deprecated int getMcc();
@@ -40445,6 +40490,7 @@
method public void onServiceStateChanged(android.telephony.ServiceState);
method public deprecated void onSignalStrengthChanged(int);
method public void onSignalStrengthsChanged(android.telephony.SignalStrength);
+ method public void onUserMobileDataStateChanged(boolean);
field public static final int LISTEN_CALL_FORWARDING_INDICATOR = 8; // 0x8
field public static final int LISTEN_CALL_STATE = 32; // 0x20
field public static final int LISTEN_CELL_INFO = 1024; // 0x400
@@ -40456,6 +40502,7 @@
field public static final int LISTEN_SERVICE_STATE = 1; // 0x1
field public static final deprecated int LISTEN_SIGNAL_STRENGTH = 2; // 0x2
field public static final int LISTEN_SIGNAL_STRENGTHS = 256; // 0x100
+ field public static final int LISTEN_USER_MOBILE_DATA_STATE = 524288; // 0x80000
}
public final class RadioAccessSpecifier implements android.os.Parcelable {
@@ -40921,6 +40968,78 @@
}
+package android.telephony.data {
+
+ public class ApnSetting implements android.os.Parcelable {
+ method public int describeContents();
+ method public java.lang.String getApnName();
+ method public int getAuthType();
+ method public java.lang.String getEntryName();
+ method public int getId();
+ method public int getMmsPort();
+ method public java.net.InetAddress getMmsProxy();
+ method public java.net.URL getMmsc();
+ method public java.lang.String getMvnoType();
+ method public java.lang.String getOperatorNumeric();
+ method public java.lang.String getPassword();
+ method public int getPort();
+ method public java.lang.String getProtocol();
+ method public java.net.InetAddress getProxy();
+ method public java.lang.String getRoamingProtocol();
+ method public java.util.List<java.lang.String> getTypes();
+ method public java.lang.String getUser();
+ method public boolean isEnabled();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final int AUTH_TYPE_CHAP = 2; // 0x2
+ field public static final int AUTH_TYPE_NONE = 0; // 0x0
+ field public static final int AUTH_TYPE_PAP = 1; // 0x1
+ field public static final int AUTH_TYPE_PAP_OR_CHAP = 3; // 0x3
+ field public static final android.os.Parcelable.Creator<android.telephony.data.ApnSetting> CREATOR;
+ field public static final java.lang.String MVNO_TYPE_GID = "gid";
+ field public static final java.lang.String MVNO_TYPE_ICCID = "iccid";
+ field public static final java.lang.String MVNO_TYPE_IMSI = "imsi";
+ field public static final java.lang.String MVNO_TYPE_SPN = "spn";
+ field public static final java.lang.String PROTOCOL_IP = "IP";
+ field public static final java.lang.String PROTOCOL_IPV4V6 = "IPV4V6";
+ field public static final java.lang.String PROTOCOL_IPV6 = "IPV6";
+ field public static final java.lang.String PROTOCOL_PPP = "PPP";
+ field public static final java.lang.String TYPE_ALL = "*";
+ field public static final java.lang.String TYPE_CBS = "cbs";
+ field public static final java.lang.String TYPE_DEFAULT = "default";
+ field public static final java.lang.String TYPE_DUN = "dun";
+ field public static final java.lang.String TYPE_EMERGENCY = "emergency";
+ field public static final java.lang.String TYPE_FOTA = "fota";
+ field public static final java.lang.String TYPE_HIPRI = "hipri";
+ field public static final java.lang.String TYPE_IA = "ia";
+ field public static final java.lang.String TYPE_IMS = "ims";
+ field public static final java.lang.String TYPE_MMS = "mms";
+ field public static final java.lang.String TYPE_SUPL = "supl";
+ }
+
+ public static class ApnSetting.Builder {
+ ctor public ApnSetting.Builder();
+ method public android.telephony.data.ApnSetting build();
+ method public android.telephony.data.ApnSetting.Builder setApnName(java.lang.String);
+ method public android.telephony.data.ApnSetting.Builder setAuthType(int);
+ method public android.telephony.data.ApnSetting.Builder setCarrierEnabled(boolean);
+ method public android.telephony.data.ApnSetting.Builder setEntryName(java.lang.String);
+ method public android.telephony.data.ApnSetting.Builder setId(int);
+ method public android.telephony.data.ApnSetting.Builder setMmsPort(int);
+ method public android.telephony.data.ApnSetting.Builder setMmsProxy(java.net.InetAddress);
+ method public android.telephony.data.ApnSetting.Builder setMmsc(java.net.URL);
+ method public android.telephony.data.ApnSetting.Builder setMvnoType(java.lang.String);
+ method public android.telephony.data.ApnSetting.Builder setOperatorNumeric(java.lang.String);
+ method public android.telephony.data.ApnSetting.Builder setPassword(java.lang.String);
+ method public android.telephony.data.ApnSetting.Builder setPort(int);
+ method public android.telephony.data.ApnSetting.Builder setProtocol(java.lang.String);
+ method public android.telephony.data.ApnSetting.Builder setProxy(java.net.InetAddress);
+ method public android.telephony.data.ApnSetting.Builder setRoamingProtocol(java.lang.String);
+ method public android.telephony.data.ApnSetting.Builder setTypes(java.util.List<java.lang.String>);
+ method public android.telephony.data.ApnSetting.Builder setUser(java.lang.String);
+ }
+
+}
+
package android.telephony.gsm {
public class GsmCellLocation extends android.telephony.CellLocation {
diff --git a/api/system-current.txt b/api/system-current.txt
index 2a757ef..aa84f32 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -628,6 +628,9 @@
method public boolean isEncrypted();
method public boolean removeBond();
method public boolean setPhonebookAccessPermission(int);
+ field public static final int ACCESS_ALLOWED = 1; // 0x1
+ field public static final int ACCESS_REJECTED = 2; // 0x2
+ field public static final int ACCESS_UNKNOWN = 0; // 0x0
}
public final class BluetoothHeadset implements android.bluetooth.BluetoothProfile {
@@ -636,6 +639,11 @@
method public boolean setPriority(android.bluetooth.BluetoothDevice, int);
}
+ public abstract interface BluetoothProfile {
+ field public static final int PRIORITY_OFF = 0; // 0x0
+ field public static final int PRIORITY_ON = 100; // 0x64
+ }
+
}
package android.bluetooth.le {
@@ -4068,11 +4076,11 @@
package android.telephony.data {
public final class DataCallResponse implements android.os.Parcelable {
- ctor public DataCallResponse(int, int, int, int, java.lang.String, java.lang.String, java.util.List<android.telephony.data.InterfaceAddress>, java.util.List<java.net.InetAddress>, java.util.List<java.net.InetAddress>, java.util.List<java.lang.String>, int);
+ ctor public DataCallResponse(int, int, int, int, java.lang.String, java.lang.String, java.util.List<android.net.LinkAddress>, java.util.List<java.net.InetAddress>, java.util.List<java.net.InetAddress>, java.util.List<java.lang.String>, int);
ctor public DataCallResponse(android.os.Parcel);
method public int describeContents();
method public int getActive();
- method public java.util.List<android.telephony.data.InterfaceAddress> getAddresses();
+ method public java.util.List<android.net.LinkAddress> getAddresses();
method public int getCallId();
method public java.util.List<java.net.InetAddress> getDnses();
method public java.util.List<java.net.InetAddress> getGateways();
@@ -4115,17 +4123,6 @@
field public static final int TYPE_COMMON = 0; // 0x0
}
- public final class InterfaceAddress implements android.os.Parcelable {
- ctor public InterfaceAddress(java.net.InetAddress, int);
- ctor public InterfaceAddress(java.lang.String, int) throws java.net.UnknownHostException;
- ctor public InterfaceAddress(android.os.Parcel);
- method public int describeContents();
- method public java.net.InetAddress getAddress();
- method public int getNetworkPrefixLength();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.telephony.data.InterfaceAddress> CREATOR;
- }
-
}
package android.telephony.ims {
diff --git a/cmds/svc/src/com/android/commands/svc/UsbCommand.java b/cmds/svc/src/com/android/commands/svc/UsbCommand.java
index adbe9d0..34f6d7d 100644
--- a/cmds/svc/src/com/android/commands/svc/UsbCommand.java
+++ b/cmds/svc/src/com/android/commands/svc/UsbCommand.java
@@ -18,6 +18,7 @@
import android.content.Context;
import android.hardware.usb.IUsbManager;
+import android.hardware.usb.UsbManager;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemProperties;
@@ -38,6 +39,9 @@
+ "\n"
+ "usage: svc usb setFunction [function] [usbDataUnlocked=false]\n"
+ " Set the current usb function and optionally the data lock state.\n\n"
+ + " svc usb setScreenUnlockedFunctions [function]\n"
+ + " Sets the functions which, if the device was charging,"
+ + " become current on screen unlock.\n"
+ " svc usb getFunction\n"
+ " Gets the list of currently enabled functions\n";
}
@@ -62,6 +66,16 @@
} else if ("getFunction".equals(args[1])) {
System.err.println(SystemProperties.get("sys.usb.config"));
return;
+ } else if ("setScreenUnlockedFunctions".equals(args[1])) {
+ IUsbManager usbMgr = IUsbManager.Stub.asInterface(ServiceManager.getService(
+ Context.USB_SERVICE));
+ try {
+ usbMgr.setScreenUnlockedFunctions((args.length >= 3 ? args[2] :
+ UsbManager.USB_FUNCTION_NONE));
+ } catch (RemoteException e) {
+ System.err.println("Error communicating with UsbManager: " + e);
+ }
+ return;
}
}
System.err.println(longHelp());
diff --git a/core/java/Android.bp b/core/java/Android.bp
index 42b0f6b..fb27f74 100644
--- a/core/java/Android.bp
+++ b/core/java/Android.bp
@@ -2,3 +2,8 @@
name: "IKeyAttestationApplicationIdProvider.aidl",
srcs: ["android/security/keymaster/IKeyAttestationApplicationIdProvider.aidl"],
}
+
+filegroup {
+ name: "IDropBoxManagerService.aidl",
+ srcs: ["com/android/internal/os/IDropBoxManagerService.aidl"],
+}
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index c8d9839..f2160e1 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -268,4 +268,11 @@
* @param token The IApplicationToken for the activity
*/
public abstract void setFocusedActivity(IBinder token);
+
+ public interface ScreenObserver {
+ public void onAwakeStateChanged(boolean isAwake);
+ public void onKeyguardStateChanged(boolean isShowing);
+ }
+
+ public abstract void registerScreenObserver(ScreenObserver observer);
}
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 45f7eba..2ecd312 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -366,7 +366,7 @@
ActivityInfo activityInfo;
CompatibilityInfo compatInfo;
- LoadedApk packageInfo;
+ LoadedApk loadedApk;
List<ResultInfo> pendingResults;
List<ReferrerIntent> pendingIntents;
@@ -542,7 +542,7 @@
}
static final class AppBindData {
- LoadedApk info;
+ LoadedApk loadedApk;
String processName;
ApplicationInfo appInfo;
List<ProviderInfo> providers;
@@ -1584,7 +1584,7 @@
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
- r.packageInfo = getPackageInfoNoCheck(
+ r.loadedApk = getLoadedApkNoCheck(
r.activityInfo.applicationInfo, r.compatInfo);
handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
@@ -1832,9 +1832,11 @@
handleLocalVoiceInteractionStarted((IBinder) ((SomeArgs) msg.obj).arg1,
(IVoiceInteractor) ((SomeArgs) msg.obj).arg2);
break;
- case ATTACH_AGENT:
- handleAttachAgent((String) msg.obj);
+ case ATTACH_AGENT: {
+ Application app = getApplication();
+ handleAttachAgent((String) msg.obj, app != null ? app.mLoadedApk : null);
break;
+ }
case APPLICATION_INFO_CHANGED:
mUpdatingSystemConfig = true;
try {
@@ -1971,13 +1973,13 @@
return mH;
}
- public final LoadedApk getPackageInfo(String packageName, CompatibilityInfo compatInfo,
- int flags) {
- return getPackageInfo(packageName, compatInfo, flags, UserHandle.myUserId());
+ public final LoadedApk getLoadedApkForPackageName(String packageName,
+ CompatibilityInfo compatInfo, int flags) {
+ return getLoadedApkForPackageName(packageName, compatInfo, flags, UserHandle.myUserId());
}
- public final LoadedApk getPackageInfo(String packageName, CompatibilityInfo compatInfo,
- int flags, int userId) {
+ public final LoadedApk getLoadedApkForPackageName(String packageName,
+ CompatibilityInfo compatInfo, int flags, int userId) {
final boolean differentUser = (UserHandle.myUserId() != userId);
synchronized (mResourcesManager) {
WeakReference<LoadedApk> ref;
@@ -1990,13 +1992,13 @@
ref = mResourcePackages.get(packageName);
}
- LoadedApk packageInfo = ref != null ? ref.get() : null;
- //Slog.i(TAG, "getPackageInfo " + packageName + ": " + packageInfo);
- //if (packageInfo != null) Slog.i(TAG, "isUptoDate " + packageInfo.mResDir
- // + ": " + packageInfo.mResources.getAssets().isUpToDate());
- if (packageInfo != null && (packageInfo.mResources == null
- || packageInfo.mResources.getAssets().isUpToDate())) {
- if (packageInfo.isSecurityViolation()
+ LoadedApk loadedApk = ref != null ? ref.get() : null;
+ //Slog.i(TAG, "getLoadedApkForPackageName " + packageName + ": " + loadedApk);
+ //if (loadedApk != null) Slog.i(TAG, "isUptoDate " + loadedApk.mResDir
+ // + ": " + loadedApk.mResources.getAssets().isUpToDate());
+ if (loadedApk != null && (loadedApk.mResources == null
+ || loadedApk.mResources.getAssets().isUpToDate())) {
+ if (loadedApk.isSecurityViolation()
&& (flags&Context.CONTEXT_IGNORE_SECURITY) == 0) {
throw new SecurityException(
"Requesting code from " + packageName
@@ -2004,7 +2006,7 @@
+ mBoundApplication.processName
+ "/" + mBoundApplication.appInfo.uid);
}
- return packageInfo;
+ return loadedApk;
}
}
@@ -2019,13 +2021,13 @@
}
if (ai != null) {
- return getPackageInfo(ai, compatInfo, flags);
+ return getLoadedApk(ai, compatInfo, flags);
}
return null;
}
- public final LoadedApk getPackageInfo(ApplicationInfo ai, CompatibilityInfo compatInfo,
+ public final LoadedApk getLoadedApk(ApplicationInfo ai, CompatibilityInfo compatInfo,
int flags) {
boolean includeCode = (flags&Context.CONTEXT_INCLUDE_CODE) != 0;
boolean securityViolation = includeCode && ai.uid != 0
@@ -2047,16 +2049,16 @@
throw new SecurityException(msg);
}
}
- return getPackageInfo(ai, compatInfo, null, securityViolation, includeCode,
+ return getLoadedApk(ai, compatInfo, null, securityViolation, includeCode,
registerPackage);
}
- public final LoadedApk getPackageInfoNoCheck(ApplicationInfo ai,
+ public final LoadedApk getLoadedApkNoCheck(ApplicationInfo ai,
CompatibilityInfo compatInfo) {
- return getPackageInfo(ai, compatInfo, null, false, true, false);
+ return getLoadedApk(ai, compatInfo, null, false, true, false);
}
- public final LoadedApk peekPackageInfo(String packageName, boolean includeCode) {
+ public final LoadedApk peekLoadedApk(String packageName, boolean includeCode) {
synchronized (mResourcesManager) {
WeakReference<LoadedApk> ref;
if (includeCode) {
@@ -2068,7 +2070,7 @@
}
}
- private LoadedApk getPackageInfo(ApplicationInfo aInfo, CompatibilityInfo compatInfo,
+ private LoadedApk getLoadedApk(ApplicationInfo aInfo, CompatibilityInfo compatInfo,
ClassLoader baseLoader, boolean securityViolation, boolean includeCode,
boolean registerPackage) {
final boolean differentUser = (UserHandle.myUserId() != UserHandle.getUserId(aInfo.uid));
@@ -2083,35 +2085,35 @@
ref = mResourcePackages.get(aInfo.packageName);
}
- LoadedApk packageInfo = ref != null ? ref.get() : null;
- if (packageInfo == null || (packageInfo.mResources != null
- && !packageInfo.mResources.getAssets().isUpToDate())) {
+ LoadedApk loadedApk = ref != null ? ref.get() : null;
+ if (loadedApk == null || (loadedApk.mResources != null
+ && !loadedApk.mResources.getAssets().isUpToDate())) {
if (localLOGV) Slog.v(TAG, (includeCode ? "Loading code package "
: "Loading resource-only package ") + aInfo.packageName
+ " (in " + (mBoundApplication != null
? mBoundApplication.processName : null)
+ ")");
- packageInfo =
+ loadedApk =
new LoadedApk(this, aInfo, compatInfo, baseLoader,
securityViolation, includeCode &&
(aInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0, registerPackage);
if (mSystemThread && "android".equals(aInfo.packageName)) {
- packageInfo.installSystemApplicationInfo(aInfo,
- getSystemContext().mPackageInfo.getClassLoader());
+ loadedApk.installSystemApplicationInfo(aInfo,
+ getSystemContext().mLoadedApk.getClassLoader());
}
if (differentUser) {
// Caching not supported across users
} else if (includeCode) {
mPackages.put(aInfo.packageName,
- new WeakReference<LoadedApk>(packageInfo));
+ new WeakReference<LoadedApk>(loadedApk));
} else {
mResourcePackages.put(aInfo.packageName,
- new WeakReference<LoadedApk>(packageInfo));
+ new WeakReference<LoadedApk>(loadedApk));
}
}
- return packageInfo;
+ return loadedApk;
}
}
@@ -2645,8 +2647,8 @@
// System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")");
ActivityInfo aInfo = r.activityInfo;
- if (r.packageInfo == null) {
- r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
+ if (r.loadedApk == null) {
+ r.loadedApk = getLoadedApk(aInfo.applicationInfo, r.compatInfo,
Context.CONTEXT_INCLUDE_CODE);
}
@@ -2683,15 +2685,15 @@
}
try {
- Application app = r.packageInfo.makeApplication(false, mInstrumentation);
+ Application app = r.loadedApk.makeApplication(false, mInstrumentation);
if (localLOGV) Slog.v(TAG, "Performing launch of " + r);
if (localLOGV) Slog.v(
TAG, r + ": app=" + app
+ ", appName=" + app.getPackageName()
- + ", pkg=" + r.packageInfo.getPackageName()
+ + ", pkg=" + r.loadedApk.getPackageName()
+ ", comp=" + r.intent.getComponent().toShortString()
- + ", dir=" + r.packageInfo.getAppDir());
+ + ", dir=" + r.loadedApk.getAppDir());
if (activity != null) {
CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
@@ -2809,7 +2811,7 @@
}
ContextImpl appContext = ContextImpl.createActivityContext(
- this, r.packageInfo, r.activityInfo, r.token, displayId, r.overrideConfig);
+ this, r.loadedApk, r.activityInfo, r.token, displayId, r.overrideConfig);
final DisplayManagerGlobal dm = DisplayManagerGlobal.getInstance();
// For debugging purposes, if the activity's package name contains the value of
@@ -2817,7 +2819,7 @@
// its content on a secondary display if there is one.
String pkgName = SystemProperties.get("debug.second-display.pkg");
if (pkgName != null && !pkgName.isEmpty()
- && r.packageInfo.mPackageName.contains(pkgName)) {
+ && r.loadedApk.mPackageName.contains(pkgName)) {
for (int id : dm.getDisplayIds()) {
if (id != Display.DEFAULT_DISPLAY) {
Display display =
@@ -3119,11 +3121,23 @@
}
}
- static final void handleAttachAgent(String agent) {
+ private static boolean attemptAttachAgent(String agent, ClassLoader classLoader) {
try {
- VMDebug.attachAgent(agent);
+ VMDebug.attachAgent(agent, classLoader);
+ return true;
} catch (IOException e) {
- Slog.e(TAG, "Attaching agent failed: " + agent);
+ Slog.e(TAG, "Attaching agent with " + classLoader + " failed: " + agent);
+ return false;
+ }
+ }
+
+ static void handleAttachAgent(String agent, LoadedApk loadedApk) {
+ ClassLoader classLoader = loadedApk != null ? loadedApk.getClassLoader() : null;
+ if (attemptAttachAgent(agent, classLoader)) {
+ return;
+ }
+ if (classLoader != null) {
+ attemptAttachAgent(agent, null);
}
}
@@ -3145,7 +3159,7 @@
String component = data.intent.getComponent().getClassName();
- LoadedApk packageInfo = getPackageInfoNoCheck(
+ LoadedApk loadedApk = getLoadedApkNoCheck(
data.info.applicationInfo, data.compatInfo);
IActivityManager mgr = ActivityManager.getService();
@@ -3154,7 +3168,7 @@
BroadcastReceiver receiver;
ContextImpl context;
try {
- app = packageInfo.makeApplication(false, mInstrumentation);
+ app = loadedApk.makeApplication(false, mInstrumentation);
context = (ContextImpl) app.getBaseContext();
if (data.info.splitName != null) {
context = (ContextImpl) context.createContextForSplit(data.info.splitName);
@@ -3178,9 +3192,9 @@
TAG, "Performing receive of " + data.intent
+ ": app=" + app
+ ", appName=" + app.getPackageName()
- + ", pkg=" + packageInfo.getPackageName()
+ + ", pkg=" + loadedApk.getPackageName()
+ ", comp=" + data.intent.getComponent().toShortString()
- + ", dir=" + packageInfo.getAppDir());
+ + ", dir=" + loadedApk.getAppDir());
sCurrentBroadcastIntent.set(data.intent);
receiver.setPendingResult(data);
@@ -3225,8 +3239,8 @@
unscheduleGcIdler();
// instantiate the BackupAgent class named in the manifest
- LoadedApk packageInfo = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
- String packageName = packageInfo.mPackageName;
+ LoadedApk loadedApk = getLoadedApkNoCheck(data.appInfo, data.compatInfo);
+ String packageName = loadedApk.mPackageName;
if (packageName == null) {
Slog.d(TAG, "Asked to create backup agent for nonexistent package");
return;
@@ -3252,11 +3266,11 @@
try {
if (DEBUG_BACKUP) Slog.v(TAG, "Initializing agent class " + classname);
- java.lang.ClassLoader cl = packageInfo.getClassLoader();
+ java.lang.ClassLoader cl = loadedApk.getClassLoader();
agent = (BackupAgent) cl.loadClass(classname).newInstance();
// set up the agent's context
- ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
+ ContextImpl context = ContextImpl.createAppContext(this, loadedApk);
context.setOuterContext(agent);
agent.attach(context);
@@ -3292,8 +3306,8 @@
private void handleDestroyBackupAgent(CreateBackupAgentData data) {
if (DEBUG_BACKUP) Slog.v(TAG, "handleDestroyBackupAgent: " + data);
- LoadedApk packageInfo = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
- String packageName = packageInfo.mPackageName;
+ LoadedApk loadedApk = getLoadedApkNoCheck(data.appInfo, data.compatInfo);
+ String packageName = loadedApk.mPackageName;
BackupAgent agent = mBackupAgents.get(packageName);
if (agent != null) {
try {
@@ -3313,11 +3327,11 @@
// we are back active so skip it.
unscheduleGcIdler();
- LoadedApk packageInfo = getPackageInfoNoCheck(
+ LoadedApk loadedApk = getLoadedApkNoCheck(
data.info.applicationInfo, data.compatInfo);
Service service = null;
try {
- java.lang.ClassLoader cl = packageInfo.getClassLoader();
+ java.lang.ClassLoader cl = loadedApk.getClassLoader();
service = (Service) cl.loadClass(data.info.name).newInstance();
} catch (Exception e) {
if (!mInstrumentation.onException(service, e)) {
@@ -3330,10 +3344,10 @@
try {
if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);
- ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
+ ContextImpl context = ContextImpl.createAppContext(this, loadedApk);
context.setOuterContext(service);
- Application app = packageInfo.makeApplication(false, mInstrumentation);
+ Application app = loadedApk.makeApplication(false, mInstrumentation);
service.attach(context, this, data.info.name, data.token, app,
ActivityManager.getService());
service.onCreate();
@@ -3943,7 +3957,7 @@
Bundle.dumpStats(pw, persistentState);
if (ex instanceof TransactionTooLargeException
- && activity.packageInfo.getTargetSdkVersion() < Build.VERSION_CODES.N) {
+ && activity.loadedApk.getTargetSdkVersion() < Build.VERSION_CODES.N) {
Log.e(TAG, "App sent too much data in instance state, so it was ignored", ex);
return;
}
@@ -4238,11 +4252,11 @@
}
private void handleUpdatePackageCompatibilityInfo(UpdateCompatibilityData data) {
- LoadedApk apk = peekPackageInfo(data.pkg, false);
+ LoadedApk apk = peekLoadedApk(data.pkg, false);
if (apk != null) {
apk.setCompatibilityInfo(data.info);
}
- apk = peekPackageInfo(data.pkg, true);
+ apk = peekLoadedApk(data.pkg, true);
if (apk != null) {
apk.setCompatibilityInfo(data.info);
}
@@ -4739,7 +4753,7 @@
if (a != null) {
Configuration thisConfig = applyConfigCompatMainThread(
mCurDefaultDisplayDpi, newConfig,
- ar.packageInfo.getCompatibilityInfo());
+ ar.loadedApk.getCompatibilityInfo());
if (!ar.activity.mFinished && (allActivities || !ar.paused)) {
// If the activity is currently resumed, its configuration
// needs to change right now.
@@ -5209,7 +5223,7 @@
}
final void handleDispatchPackageBroadcast(int cmd, String[] packages) {
- boolean hasPkgInfo = false;
+ boolean hasLoadedApk = false;
switch (cmd) {
case ApplicationThreadConstants.PACKAGE_REMOVED:
case ApplicationThreadConstants.PACKAGE_REMOVED_DONT_KILL:
@@ -5220,14 +5234,14 @@
}
synchronized (mResourcesManager) {
for (int i = packages.length - 1; i >= 0; i--) {
- if (!hasPkgInfo) {
+ if (!hasLoadedApk) {
WeakReference<LoadedApk> ref = mPackages.get(packages[i]);
if (ref != null && ref.get() != null) {
- hasPkgInfo = true;
+ hasLoadedApk = true;
} else {
ref = mResourcePackages.get(packages[i]);
if (ref != null && ref.get() != null) {
- hasPkgInfo = true;
+ hasLoadedApk = true;
}
}
}
@@ -5247,21 +5261,21 @@
synchronized (mResourcesManager) {
for (int i = packages.length - 1; i >= 0; i--) {
WeakReference<LoadedApk> ref = mPackages.get(packages[i]);
- LoadedApk pkgInfo = ref != null ? ref.get() : null;
- if (pkgInfo != null) {
- hasPkgInfo = true;
+ LoadedApk loadedApk = ref != null ? ref.get() : null;
+ if (loadedApk != null) {
+ hasLoadedApk = true;
} else {
ref = mResourcePackages.get(packages[i]);
- pkgInfo = ref != null ? ref.get() : null;
- if (pkgInfo != null) {
- hasPkgInfo = true;
+ loadedApk = ref != null ? ref.get() : null;
+ if (loadedApk != null) {
+ hasLoadedApk = true;
}
}
// If the package is being replaced, yet it still has a valid
// LoadedApk object, the package was updated with _DONT_KILL.
// Adjust it's internal references to the application info and
// resources.
- if (pkgInfo != null) {
+ if (loadedApk != null) {
try {
final String packageName = packages[i];
final ApplicationInfo aInfo =
@@ -5275,13 +5289,13 @@
if (ar.activityInfo.applicationInfo.packageName
.equals(packageName)) {
ar.activityInfo.applicationInfo = aInfo;
- ar.packageInfo = pkgInfo;
+ ar.loadedApk = loadedApk;
}
}
}
final List<String> oldPaths =
sPackageManager.getPreviousCodePaths(packageName);
- pkgInfo.updateApplicationInfo(aInfo, oldPaths);
+ loadedApk.updateApplicationInfo(aInfo, oldPaths);
} catch (RemoteException e) {
}
}
@@ -5290,7 +5304,7 @@
break;
}
}
- ApplicationPackageManager.handlePackageBroadcast(cmd, packages, hasPkgInfo);
+ ApplicationPackageManager.handlePackageBroadcast(cmd, packages, hasLoadedApk);
}
final void handleLowMemory() {
@@ -5441,12 +5455,16 @@
mCompatConfiguration = new Configuration(data.config);
mProfiler = new Profiler();
+ String agent = null;
if (data.initProfilerInfo != null) {
mProfiler.profileFile = data.initProfilerInfo.profileFile;
mProfiler.profileFd = data.initProfilerInfo.profileFd;
mProfiler.samplingInterval = data.initProfilerInfo.samplingInterval;
mProfiler.autoStopProfiler = data.initProfilerInfo.autoStopProfiler;
mProfiler.streamingOutput = data.initProfilerInfo.streamingOutput;
+ if (data.initProfilerInfo.attachAgentDuringBind) {
+ agent = data.initProfilerInfo.agent;
+ }
}
// send up app name; do this *before* waiting for debugger
@@ -5494,7 +5512,11 @@
applyCompatConfiguration(mCurDefaultDisplayDpi);
}
- data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
+ data.loadedApk = getLoadedApkNoCheck(data.appInfo, data.compatInfo);
+
+ if (agent != null) {
+ handleAttachAgent(agent, data.loadedApk);
+ }
/**
* Switch this process to density compatibility mode if needed.
@@ -5562,7 +5584,7 @@
// XXX should have option to change the port.
Debug.changeDebugPort(8100);
if (data.debugMode == ApplicationThreadConstants.DEBUG_WAIT) {
- Slog.w(TAG, "Application " + data.info.getPackageName()
+ Slog.w(TAG, "Application " + data.loadedApk.getPackageName()
+ " is waiting for the debugger on port 8100...");
IActivityManager mgr = ActivityManager.getService();
@@ -5581,7 +5603,7 @@
}
} else {
- Slog.w(TAG, "Application " + data.info.getPackageName()
+ Slog.w(TAG, "Application " + data.loadedApk.getPackageName()
+ " can be debugged on port 8100...");
}
}
@@ -5629,14 +5651,14 @@
mInstrumentationAppDir = ii.sourceDir;
mInstrumentationSplitAppDirs = ii.splitSourceDirs;
mInstrumentationLibDir = getInstrumentationLibrary(data.appInfo, ii);
- mInstrumentedAppDir = data.info.getAppDir();
- mInstrumentedSplitAppDirs = data.info.getSplitAppDirs();
- mInstrumentedLibDir = data.info.getLibDir();
+ mInstrumentedAppDir = data.loadedApk.getAppDir();
+ mInstrumentedSplitAppDirs = data.loadedApk.getSplitAppDirs();
+ mInstrumentedLibDir = data.loadedApk.getLibDir();
} else {
ii = null;
}
- final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
+ final ContextImpl appContext = ContextImpl.createAppContext(this, data.loadedApk);
updateLocaleListFromAppContext(appContext,
mResourcesManager.getConfiguration().getLocales());
@@ -5666,9 +5688,9 @@
final ApplicationInfo instrApp = new ApplicationInfo();
ii.copyTo(instrApp);
instrApp.initForUser(UserHandle.myUserId());
- final LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,
+ final LoadedApk loadedApk = getLoadedApk(instrApp, data.compatInfo,
appContext.getClassLoader(), false, true, false);
- final ContextImpl instrContext = ContextImpl.createAppContext(this, pi);
+ final ContextImpl instrContext = ContextImpl.createAppContext(this, loadedApk);
try {
final ClassLoader cl = instrContext.getClassLoader();
@@ -5712,7 +5734,7 @@
try {
// If the app is being launched for full backup or restore, bring it up in
// a restricted environment with the base application class.
- app = data.info.makeApplication(data.restrictedBackupMode, null);
+ app = data.loadedApk.makeApplication(data.restrictedBackupMode, null);
mInitialApplication = app;
// don't bring up providers in restricted mode; they may depend on the
@@ -5766,7 +5788,7 @@
final int preloadedFontsResource = info.metaData.getInt(
ApplicationInfo.METADATA_PRELOADED_FONTS, 0);
if (preloadedFontsResource != 0) {
- data.info.getResources().preloadFonts(preloadedFontsResource);
+ data.loadedApk.getResources().preloadFonts(preloadedFontsResource);
}
}
} catch (RemoteException e) {
@@ -6361,8 +6383,8 @@
try {
mInstrumentation = new Instrumentation();
ContextImpl context = ContextImpl.createAppContext(
- this, getSystemContext().mPackageInfo);
- mInitialApplication = context.mPackageInfo.makeApplication(true, null);
+ this, getSystemContext().mLoadedApk);
+ mInitialApplication = context.mLoadedApk.makeApplication(true, null);
mInitialApplication.onCreate();
} catch (Exception e) {
throw new RuntimeException(
diff --git a/core/java/android/app/Application.java b/core/java/android/app/Application.java
index 156df36..5822f5c 100644
--- a/core/java/android/app/Application.java
+++ b/core/java/android/app/Application.java
@@ -187,7 +187,7 @@
*/
/* package */ final void attach(Context context) {
attachBaseContext(context);
- mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;
+ mLoadedApk = ContextImpl.getImpl(context).mLoadedApk;
}
/* package */ void dispatchActivityCreated(Activity activity, Bundle savedInstanceState) {
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 0eafdec..4d47d82 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -1379,7 +1379,7 @@
sameUid ? app.sourceDir : app.publicSourceDir,
sameUid ? app.splitSourceDirs : app.splitPublicSourceDirs,
app.resourceDirs, app.sharedLibraryFiles, Display.DEFAULT_DISPLAY,
- mContext.mPackageInfo);
+ mContext.mLoadedApk);
if (r != null) {
return r;
}
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 5f34322..64ddfbc 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -159,7 +159,7 @@
private ArrayMap<String, File> mSharedPrefsPaths;
final @NonNull ActivityThread mMainThread;
- final @NonNull LoadedApk mPackageInfo;
+ final @NonNull LoadedApk mLoadedApk;
private @Nullable ClassLoader mClassLoader;
private final @Nullable IBinder mActivityToken;
@@ -252,8 +252,8 @@
@Override
public Context getApplicationContext() {
- return (mPackageInfo != null) ?
- mPackageInfo.getApplication() : mMainThread.getApplication();
+ return (mLoadedApk != null) ?
+ mLoadedApk.getApplication() : mMainThread.getApplication();
}
@Override
@@ -297,15 +297,15 @@
@Override
public ClassLoader getClassLoader() {
- return mClassLoader != null ? mClassLoader : (mPackageInfo != null ? mPackageInfo.getClassLoader() : ClassLoader.getSystemClassLoader());
+ return mClassLoader != null ? mClassLoader : (mLoadedApk != null ? mLoadedApk.getClassLoader() : ClassLoader.getSystemClassLoader());
}
@Override
public String getPackageName() {
- if (mPackageInfo != null) {
- return mPackageInfo.getPackageName();
+ if (mLoadedApk != null) {
+ return mLoadedApk.getPackageName();
}
- // No mPackageInfo means this is a Context for the system itself,
+ // No mLoadedApk means this is a Context for the system itself,
// and this here is its name.
return "android";
}
@@ -324,24 +324,24 @@
@Override
public ApplicationInfo getApplicationInfo() {
- if (mPackageInfo != null) {
- return mPackageInfo.getApplicationInfo();
+ if (mLoadedApk != null) {
+ return mLoadedApk.getApplicationInfo();
}
throw new RuntimeException("Not supported in system context");
}
@Override
public String getPackageResourcePath() {
- if (mPackageInfo != null) {
- return mPackageInfo.getResDir();
+ if (mLoadedApk != null) {
+ return mLoadedApk.getResDir();
}
throw new RuntimeException("Not supported in system context");
}
@Override
public String getPackageCodePath() {
- if (mPackageInfo != null) {
- return mPackageInfo.getAppDir();
+ if (mLoadedApk != null) {
+ return mLoadedApk.getAppDir();
}
throw new RuntimeException("Not supported in system context");
}
@@ -351,7 +351,7 @@
// At least one application in the world actually passes in a null
// name. This happened to work because when we generated the file name
// we would stringify it to "null.xml". Nice.
- if (mPackageInfo.getApplicationInfo().targetSdkVersion <
+ if (mLoadedApk.getApplicationInfo().targetSdkVersion <
Build.VERSION_CODES.KITKAT) {
if (name == null) {
name = "null";
@@ -1093,11 +1093,11 @@
warnIfCallingFromSystemProcess();
IIntentReceiver rd = null;
if (resultReceiver != null) {
- if (mPackageInfo != null) {
+ if (mLoadedApk != null) {
if (scheduler == null) {
scheduler = mMainThread.getHandler();
}
- rd = mPackageInfo.getReceiverDispatcher(
+ rd = mLoadedApk.getReceiverDispatcher(
resultReceiver, getOuterContext(), scheduler,
mMainThread.getInstrumentation(), false);
} else {
@@ -1197,11 +1197,11 @@
Handler scheduler, int initialCode, String initialData, Bundle initialExtras) {
IIntentReceiver rd = null;
if (resultReceiver != null) {
- if (mPackageInfo != null) {
+ if (mLoadedApk != null) {
if (scheduler == null) {
scheduler = mMainThread.getHandler();
}
- rd = mPackageInfo.getReceiverDispatcher(
+ rd = mLoadedApk.getReceiverDispatcher(
resultReceiver, getOuterContext(), scheduler,
mMainThread.getInstrumentation(), false);
} else {
@@ -1251,11 +1251,11 @@
warnIfCallingFromSystemProcess();
IIntentReceiver rd = null;
if (resultReceiver != null) {
- if (mPackageInfo != null) {
+ if (mLoadedApk != null) {
if (scheduler == null) {
scheduler = mMainThread.getHandler();
}
- rd = mPackageInfo.getReceiverDispatcher(
+ rd = mLoadedApk.getReceiverDispatcher(
resultReceiver, getOuterContext(), scheduler,
mMainThread.getInstrumentation(), false);
} else {
@@ -1333,11 +1333,11 @@
Bundle initialExtras) {
IIntentReceiver rd = null;
if (resultReceiver != null) {
- if (mPackageInfo != null) {
+ if (mLoadedApk != null) {
if (scheduler == null) {
scheduler = mMainThread.getHandler();
}
- rd = mPackageInfo.getReceiverDispatcher(
+ rd = mLoadedApk.getReceiverDispatcher(
resultReceiver, getOuterContext(), scheduler,
mMainThread.getInstrumentation(), false);
} else {
@@ -1414,11 +1414,11 @@
Handler scheduler, Context context, int flags) {
IIntentReceiver rd = null;
if (receiver != null) {
- if (mPackageInfo != null && context != null) {
+ if (mLoadedApk != null && context != null) {
if (scheduler == null) {
scheduler = mMainThread.getHandler();
}
- rd = mPackageInfo.getReceiverDispatcher(
+ rd = mLoadedApk.getReceiverDispatcher(
receiver, context, scheduler,
mMainThread.getInstrumentation(), true);
} else {
@@ -1445,8 +1445,8 @@
@Override
public void unregisterReceiver(BroadcastReceiver receiver) {
- if (mPackageInfo != null) {
- IIntentReceiver rd = mPackageInfo.forgetReceiverDispatcher(
+ if (mLoadedApk != null) {
+ IIntentReceiver rd = mLoadedApk.forgetReceiverDispatcher(
getOuterContext(), receiver);
try {
ActivityManager.getService().unregisterReceiver(rd);
@@ -1579,7 +1579,7 @@
@Override
public IServiceConnection getServiceDispatcher(ServiceConnection conn, Handler handler,
int flags) {
- return mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
+ return mLoadedApk.getServiceDispatcher(conn, getOuterContext(), handler, flags);
}
/** @hide */
@@ -1601,16 +1601,16 @@
if (conn == null) {
throw new IllegalArgumentException("connection is null");
}
- if (mPackageInfo != null) {
- sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
+ if (mLoadedApk != null) {
+ sd = mLoadedApk.getServiceDispatcher(conn, getOuterContext(), handler, flags);
} else {
throw new RuntimeException("Not supported in system context");
}
validateServiceIntent(service);
try {
IBinder token = getActivityToken();
- if (token == null && (flags&BIND_AUTO_CREATE) == 0 && mPackageInfo != null
- && mPackageInfo.getApplicationInfo().targetSdkVersion
+ if (token == null && (flags&BIND_AUTO_CREATE) == 0 && mLoadedApk != null
+ && mLoadedApk.getApplicationInfo().targetSdkVersion
< android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
flags |= BIND_WAIVE_PRIORITY;
}
@@ -1634,8 +1634,8 @@
if (conn == null) {
throw new IllegalArgumentException("connection is null");
}
- if (mPackageInfo != null) {
- IServiceConnection sd = mPackageInfo.forgetServiceDispatcher(
+ if (mLoadedApk != null) {
+ IServiceConnection sd = mLoadedApk.forgetServiceDispatcher(
getOuterContext(), conn);
try {
ActivityManager.getService().unbindService(sd);
@@ -1980,40 +1980,20 @@
}
}
- private static Resources createResources(IBinder activityToken, LoadedApk pi, String splitName,
- int displayId, Configuration overrideConfig, CompatibilityInfo compatInfo) {
- final String[] splitResDirs;
- final ClassLoader classLoader;
- try {
- splitResDirs = pi.getSplitPaths(splitName);
- classLoader = pi.getSplitClassLoader(splitName);
- } catch (NameNotFoundException e) {
- throw new RuntimeException(e);
- }
- return ResourcesManager.getInstance().getResources(activityToken,
- pi.getResDir(),
- splitResDirs,
- pi.getOverlayDirs(),
- pi.getApplicationInfo().sharedLibraryFiles,
- displayId,
- overrideConfig,
- compatInfo,
- classLoader);
- }
-
@Override
public Context createApplicationContext(ApplicationInfo application, int flags)
throws NameNotFoundException {
- LoadedApk pi = mMainThread.getPackageInfo(application, mResources.getCompatibilityInfo(),
+ LoadedApk loadedApk = mMainThread.getLoadedApk(application,
+ mResources.getCompatibilityInfo(),
flags | CONTEXT_REGISTER_PACKAGE);
- if (pi != null) {
- ContextImpl c = new ContextImpl(this, mMainThread, pi, null, mActivityToken,
+ if (loadedApk != null) {
+ ContextImpl c = new ContextImpl(this, mMainThread, loadedApk, null, mActivityToken,
new UserHandle(UserHandle.getUserId(application.uid)), flags, null);
final int displayId = mDisplay != null
? mDisplay.getDisplayId() : Display.DEFAULT_DISPLAY;
- c.setResources(createResources(mActivityToken, pi, null, displayId, null,
+ c.setResources(loadedApk.createResources(mActivityToken, null, displayId, null,
getDisplayAdjustments(displayId).getCompatibilityInfo()));
if (c.mResources != null) {
return c;
@@ -2037,20 +2017,21 @@
if (packageName.equals("system") || packageName.equals("android")) {
// The system resources are loaded in every application, so we can safely copy
// the context without reloading Resources.
- return new ContextImpl(this, mMainThread, mPackageInfo, null, mActivityToken, user,
+ return new ContextImpl(this, mMainThread, mLoadedApk, null, mActivityToken, user,
flags, null);
}
- LoadedApk pi = mMainThread.getPackageInfo(packageName, mResources.getCompatibilityInfo(),
+ LoadedApk loadedApk = mMainThread.getLoadedApkForPackageName(packageName,
+ mResources.getCompatibilityInfo(),
flags | CONTEXT_REGISTER_PACKAGE, user.getIdentifier());
- if (pi != null) {
- ContextImpl c = new ContextImpl(this, mMainThread, pi, null, mActivityToken, user,
+ if (loadedApk != null) {
+ ContextImpl c = new ContextImpl(this, mMainThread, loadedApk, null, mActivityToken, user,
flags, null);
final int displayId = mDisplay != null
? mDisplay.getDisplayId() : Display.DEFAULT_DISPLAY;
- c.setResources(createResources(mActivityToken, pi, null, displayId, null,
+ c.setResources(loadedApk.createResources(mActivityToken, null, displayId, null,
getDisplayAdjustments(displayId).getCompatibilityInfo()));
if (c.mResources != null) {
return c;
@@ -2064,30 +2045,21 @@
@Override
public Context createContextForSplit(String splitName) throws NameNotFoundException {
- if (!mPackageInfo.getApplicationInfo().requestsIsolatedSplitLoading()) {
+ if (!mLoadedApk.getApplicationInfo().requestsIsolatedSplitLoading()) {
// All Splits are always loaded.
return this;
}
- final ClassLoader classLoader = mPackageInfo.getSplitClassLoader(splitName);
- final String[] paths = mPackageInfo.getSplitPaths(splitName);
+ final ClassLoader classLoader = mLoadedApk.getSplitClassLoader(splitName);
- final ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo, splitName,
+ final ContextImpl context = new ContextImpl(this, mMainThread, mLoadedApk, splitName,
mActivityToken, mUser, mFlags, classLoader);
final int displayId = mDisplay != null
? mDisplay.getDisplayId() : Display.DEFAULT_DISPLAY;
- context.setResources(ResourcesManager.getInstance().getResources(
- mActivityToken,
- mPackageInfo.getResDir(),
- paths,
- mPackageInfo.getOverlayDirs(),
- mPackageInfo.getApplicationInfo().sharedLibraryFiles,
- displayId,
- null,
- mPackageInfo.getCompatibilityInfo(),
- classLoader));
+ context.setResources(mLoadedApk.getOrCreateResourcesForSplit(splitName,
+ mActivityToken, displayId));
return context;
}
@@ -2097,11 +2069,11 @@
throw new IllegalArgumentException("overrideConfiguration must not be null");
}
- ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo, mSplitName,
+ ContextImpl context = new ContextImpl(this, mMainThread, mLoadedApk, mSplitName,
mActivityToken, mUser, mFlags, mClassLoader);
final int displayId = mDisplay != null ? mDisplay.getDisplayId() : Display.DEFAULT_DISPLAY;
- context.setResources(createResources(mActivityToken, mPackageInfo, mSplitName, displayId,
+ context.setResources(mLoadedApk.createResources(mActivityToken, mSplitName, displayId,
overrideConfiguration, getDisplayAdjustments(displayId).getCompatibilityInfo()));
return context;
}
@@ -2112,11 +2084,11 @@
throw new IllegalArgumentException("display must not be null");
}
- ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo, mSplitName,
+ ContextImpl context = new ContextImpl(this, mMainThread, mLoadedApk, mSplitName,
mActivityToken, mUser, mFlags, mClassLoader);
final int displayId = display.getDisplayId();
- context.setResources(createResources(mActivityToken, mPackageInfo, mSplitName, displayId,
+ context.setResources(mLoadedApk.createResources(mActivityToken, mSplitName, displayId,
null, getDisplayAdjustments(displayId).getCompatibilityInfo()));
context.mDisplay = display;
return context;
@@ -2126,7 +2098,7 @@
public Context createDeviceProtectedStorageContext() {
final int flags = (mFlags & ~Context.CONTEXT_CREDENTIAL_PROTECTED_STORAGE)
| Context.CONTEXT_DEVICE_PROTECTED_STORAGE;
- return new ContextImpl(this, mMainThread, mPackageInfo, mSplitName, mActivityToken, mUser,
+ return new ContextImpl(this, mMainThread, mLoadedApk, mSplitName, mActivityToken, mUser,
flags, mClassLoader);
}
@@ -2134,7 +2106,7 @@
public Context createCredentialProtectedStorageContext() {
final int flags = (mFlags & ~Context.CONTEXT_DEVICE_PROTECTED_STORAGE)
| Context.CONTEXT_CREDENTIAL_PROTECTED_STORAGE;
- return new ContextImpl(this, mMainThread, mPackageInfo, mSplitName, mActivityToken, mUser,
+ return new ContextImpl(this, mMainThread, mLoadedApk, mSplitName, mActivityToken, mUser,
flags, mClassLoader);
}
@@ -2183,14 +2155,14 @@
@Override
public File getDataDir() {
- if (mPackageInfo != null) {
+ if (mLoadedApk != null) {
File res = null;
if (isCredentialProtectedStorage()) {
- res = mPackageInfo.getCredentialProtectedDataDirFile();
+ res = mLoadedApk.getCredentialProtectedDataDirFile();
} else if (isDeviceProtectedStorage()) {
- res = mPackageInfo.getDeviceProtectedDataDirFile();
+ res = mLoadedApk.getDeviceProtectedDataDirFile();
} else {
- res = mPackageInfo.getDataDirFile();
+ res = mLoadedApk.getDataDirFile();
}
if (res != null) {
@@ -2241,10 +2213,10 @@
}
static ContextImpl createSystemContext(ActivityThread mainThread) {
- LoadedApk packageInfo = new LoadedApk(mainThread);
- ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, null, null, 0,
+ LoadedApk loadedApk = new LoadedApk(mainThread);
+ ContextImpl context = new ContextImpl(null, mainThread, loadedApk, null, null, null, 0,
null);
- context.setResources(packageInfo.getResources());
+ context.setResources(loadedApk.getResources());
context.mResources.updateConfiguration(context.mResourcesManager.getConfiguration(),
context.mResourcesManager.getDisplayMetrics());
return context;
@@ -2255,35 +2227,35 @@
* Make sure that the created system UI context shares the same LoadedApk as the system context.
*/
static ContextImpl createSystemUiContext(ContextImpl systemContext) {
- final LoadedApk packageInfo = systemContext.mPackageInfo;
- ContextImpl context = new ContextImpl(null, systemContext.mMainThread, packageInfo, null,
+ final LoadedApk loadedApk = systemContext.mLoadedApk;
+ ContextImpl context = new ContextImpl(null, systemContext.mMainThread, loadedApk, null,
null, null, 0, null);
- context.setResources(createResources(null, packageInfo, null, Display.DEFAULT_DISPLAY, null,
- packageInfo.getCompatibilityInfo()));
+ context.setResources(loadedApk.createResources(null, null, Display.DEFAULT_DISPLAY, null,
+ loadedApk.getCompatibilityInfo()));
return context;
}
- static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo) {
- if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
- ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, null, null, 0,
+ static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk loadedApk) {
+ if (loadedApk == null) throw new IllegalArgumentException("loadedApk");
+ ContextImpl context = new ContextImpl(null, mainThread, loadedApk, null, null, null, 0,
null);
- context.setResources(packageInfo.getResources());
+ context.setResources(loadedApk.getResources());
return context;
}
static ContextImpl createActivityContext(ActivityThread mainThread,
- LoadedApk packageInfo, ActivityInfo activityInfo, IBinder activityToken, int displayId,
+ LoadedApk loadedApk, ActivityInfo activityInfo, IBinder activityToken, int displayId,
Configuration overrideConfiguration) {
- if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
+ if (loadedApk == null) throw new IllegalArgumentException("loadedApk");
- String[] splitDirs = packageInfo.getSplitResDirs();
- ClassLoader classLoader = packageInfo.getClassLoader();
+ String[] splitDirs = loadedApk.getSplitResDirs();
+ ClassLoader classLoader = loadedApk.getClassLoader();
- if (packageInfo.getApplicationInfo().requestsIsolatedSplitLoading()) {
+ if (loadedApk.getApplicationInfo().requestsIsolatedSplitLoading()) {
Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, "SplitDependencies");
try {
- classLoader = packageInfo.getSplitClassLoader(activityInfo.splitName);
- splitDirs = packageInfo.getSplitPaths(activityInfo.splitName);
+ classLoader = loadedApk.getSplitClassLoader(activityInfo.splitName);
+ splitDirs = loadedApk.getSplitPaths(activityInfo.splitName);
} catch (NameNotFoundException e) {
// Nothing above us can handle a NameNotFoundException, better crash.
throw new RuntimeException(e);
@@ -2292,14 +2264,14 @@
}
}
- ContextImpl context = new ContextImpl(null, mainThread, packageInfo, activityInfo.splitName,
+ ContextImpl context = new ContextImpl(null, mainThread, loadedApk, activityInfo.splitName,
activityToken, null, 0, classLoader);
// Clamp display ID to DEFAULT_DISPLAY if it is INVALID_DISPLAY.
displayId = (displayId != Display.INVALID_DISPLAY) ? displayId : Display.DEFAULT_DISPLAY;
final CompatibilityInfo compatInfo = (displayId == Display.DEFAULT_DISPLAY)
- ? packageInfo.getCompatibilityInfo()
+ ? loadedApk.getCompatibilityInfo()
: CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO;
final ResourcesManager resourcesManager = ResourcesManager.getInstance();
@@ -2307,10 +2279,10 @@
// Create the base resources for which all configuration contexts for this Activity
// will be rebased upon.
context.setResources(resourcesManager.createBaseActivityResources(activityToken,
- packageInfo.getResDir(),
+ loadedApk.getResDir(),
splitDirs,
- packageInfo.getOverlayDirs(),
- packageInfo.getApplicationInfo().sharedLibraryFiles,
+ loadedApk.getOverlayDirs(),
+ loadedApk.getApplicationInfo().sharedLibraryFiles,
displayId,
overrideConfiguration,
compatInfo,
@@ -2321,7 +2293,7 @@
}
private ContextImpl(@Nullable ContextImpl container, @NonNull ActivityThread mainThread,
- @NonNull LoadedApk packageInfo, @Nullable String splitName,
+ @NonNull LoadedApk loadedApk, @Nullable String splitName,
@Nullable IBinder activityToken, @Nullable UserHandle user, int flags,
@Nullable ClassLoader classLoader) {
mOuterContext = this;
@@ -2330,10 +2302,10 @@
// location for application.
if ((flags & (Context.CONTEXT_CREDENTIAL_PROTECTED_STORAGE
| Context.CONTEXT_DEVICE_PROTECTED_STORAGE)) == 0) {
- final File dataDir = packageInfo.getDataDirFile();
- if (Objects.equals(dataDir, packageInfo.getCredentialProtectedDataDirFile())) {
+ final File dataDir = loadedApk.getDataDirFile();
+ if (Objects.equals(dataDir, loadedApk.getCredentialProtectedDataDirFile())) {
flags |= Context.CONTEXT_CREDENTIAL_PROTECTED_STORAGE;
- } else if (Objects.equals(dataDir, packageInfo.getDeviceProtectedDataDirFile())) {
+ } else if (Objects.equals(dataDir, loadedApk.getDeviceProtectedDataDirFile())) {
flags |= Context.CONTEXT_DEVICE_PROTECTED_STORAGE;
}
}
@@ -2347,7 +2319,7 @@
}
mUser = user;
- mPackageInfo = packageInfo;
+ mLoadedApk = loadedApk;
mSplitName = splitName;
mClassLoader = classLoader;
mResourcesManager = ResourcesManager.getInstance();
@@ -2358,8 +2330,8 @@
setResources(container.mResources);
mDisplay = container.mDisplay;
} else {
- mBasePackageName = packageInfo.mPackageName;
- ApplicationInfo ainfo = packageInfo.getApplicationInfo();
+ mBasePackageName = loadedApk.mPackageName;
+ ApplicationInfo ainfo = loadedApk.getApplicationInfo();
if (ainfo.uid == Process.SYSTEM_UID && ainfo.uid != Process.myUid()) {
// Special case: system components allow themselves to be loaded in to other
// processes. For purposes of app ops, we must then consider the context as
@@ -2382,7 +2354,7 @@
}
void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) {
- mPackageInfo.installSystemApplicationInfo(info, classLoader);
+ mLoadedApk.installSystemApplicationInfo(info, classLoader);
}
final void scheduleFinalCleanup(String who, String what) {
@@ -2391,7 +2363,7 @@
final void performFinalCleanup(String who, String what) {
//Log.i(TAG, "Cleanup up context: " + this);
- mPackageInfo.removeContextRegistrations(getOuterContext(), who, what);
+ mLoadedApk.removeContextRegistrations(getOuterContext(), who, what);
}
final Context getReceiverRestrictedContext() {
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index f6d9710..236a42c 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -31,6 +31,7 @@
import android.content.pm.split.SplitDependencyLoader;
import android.content.res.AssetManager;
import android.content.res.CompatibilityInfo;
+import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Build;
import android.os.Bundle;
@@ -48,15 +49,13 @@
import android.util.AndroidRuntimeException;
import android.util.ArrayMap;
import android.util.Log;
+import android.util.LogPrinter;
import android.util.Slog;
import android.util.SparseArray;
import android.view.Display;
import android.view.DisplayAdjustments;
-
import com.android.internal.util.ArrayUtils;
-
import dalvik.system.VMRuntime;
-
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
@@ -948,14 +947,78 @@
throw new AssertionError("null split not found");
}
- mResources = ResourcesManager.getInstance().getResources(null, mResDir,
- splitPaths, mOverlayDirs, mApplicationInfo.sharedLibraryFiles,
- Display.DEFAULT_DISPLAY, null, getCompatibilityInfo(),
+ mResources = ResourcesManager.getInstance().getResources(
+ null,
+ mResDir,
+ splitPaths,
+ mOverlayDirs,
+ mApplicationInfo.sharedLibraryFiles,
+ Display.DEFAULT_DISPLAY,
+ null,
+ getCompatibilityInfo(),
getClassLoader());
}
return mResources;
}
+ public Resources getOrCreateResourcesForSplit(@NonNull String splitName,
+ @Nullable IBinder activityToken, int displayId) throws NameNotFoundException {
+ return ResourcesManager.getInstance().getResources(
+ activityToken,
+ mResDir,
+ getSplitPaths(splitName),
+ mOverlayDirs,
+ mApplicationInfo.sharedLibraryFiles,
+ displayId,
+ null,
+ getCompatibilityInfo(),
+ getSplitClassLoader(splitName));
+ }
+
+ /**
+ * Creates the top level resources for the given package. Will return an existing
+ * Resources if one has already been created.
+ */
+ public Resources getOrCreateTopLevelResources(@NonNull ApplicationInfo appInfo) {
+ // Request for this app, short circuit
+ if (appInfo.uid == Process.myUid()) {
+ return getResources();
+ }
+
+ // Get resources for a different package
+ return ResourcesManager.getInstance().getResources(
+ null,
+ appInfo.publicSourceDir,
+ appInfo.splitPublicSourceDirs,
+ appInfo.resourceDirs,
+ appInfo.sharedLibraryFiles,
+ Display.DEFAULT_DISPLAY,
+ null,
+ getCompatibilityInfo(),
+ getClassLoader());
+ }
+
+ public Resources createResources(IBinder activityToken, String splitName,
+ int displayId, Configuration overrideConfig, CompatibilityInfo compatInfo) {
+ final String[] splitResDirs;
+ final ClassLoader classLoader;
+ try {
+ splitResDirs = getSplitPaths(splitName);
+ classLoader = getSplitClassLoader(splitName);
+ } catch (NameNotFoundException e) {
+ throw new RuntimeException(e);
+ }
+ return ResourcesManager.getInstance().getResources(activityToken,
+ mResDir,
+ splitResDirs,
+ mOverlayDirs,
+ mApplicationInfo.sharedLibraryFiles,
+ displayId,
+ overrideConfig,
+ compatInfo,
+ classLoader);
+ }
+
public Application makeApplication(boolean forceDefaultAppClass,
Instrumentation instrumentation) {
if (mApplication != null) {
diff --git a/core/java/android/app/ProfilerInfo.java b/core/java/android/app/ProfilerInfo.java
index fad4798..044b780 100644
--- a/core/java/android/app/ProfilerInfo.java
+++ b/core/java/android/app/ProfilerInfo.java
@@ -54,14 +54,24 @@
*/
public final String agent;
+ /**
+ * Whether the {@link agent} should be attached early (before bind-application) or during
+ * bind-application. Agents attached prior to binding cannot be loaded from the app's APK
+ * directly and must be given as an absolute path (or available in the default LD_LIBRARY_PATH).
+ * Agents attached during bind-application will miss early setup (e.g., resource initialization
+ * and classloader generation), but are searched in the app's library search path.
+ */
+ public final boolean attachAgentDuringBind;
+
public ProfilerInfo(String filename, ParcelFileDescriptor fd, int interval, boolean autoStop,
- boolean streaming, String agent) {
+ boolean streaming, String agent, boolean attachAgentDuringBind) {
profileFile = filename;
profileFd = fd;
samplingInterval = interval;
autoStopProfiler = autoStop;
streamingOutput = streaming;
this.agent = agent;
+ this.attachAgentDuringBind = attachAgentDuringBind;
}
public ProfilerInfo(ProfilerInfo in) {
@@ -71,6 +81,7 @@
autoStopProfiler = in.autoStopProfiler;
streamingOutput = in.streamingOutput;
agent = in.agent;
+ attachAgentDuringBind = in.attachAgentDuringBind;
}
/**
@@ -109,6 +120,7 @@
out.writeInt(autoStopProfiler ? 1 : 0);
out.writeInt(streamingOutput ? 1 : 0);
out.writeString(agent);
+ out.writeBoolean(attachAgentDuringBind);
}
public static final Parcelable.Creator<ProfilerInfo> CREATOR =
@@ -131,5 +143,6 @@
autoStopProfiler = in.readInt() != 0;
streamingOutput = in.readInt() != 0;
agent = in.readString();
+ attachAgentDuringBind = in.readBoolean();
}
}
diff --git a/core/java/android/app/SharedPreferencesImpl.java b/core/java/android/app/SharedPreferencesImpl.java
index 8c47598..6ac15a5 100644
--- a/core/java/android/app/SharedPreferencesImpl.java
+++ b/core/java/android/app/SharedPreferencesImpl.java
@@ -71,6 +71,8 @@
@GuardedBy("mLock")
private Map<String, Object> mMap;
+ @GuardedBy("mLock")
+ private Throwable mThrowable;
@GuardedBy("mLock")
private int mDiskWritesInFlight = 0;
@@ -107,6 +109,7 @@
mMode = mode;
mLoaded = false;
mMap = null;
+ mThrowable = null;
startLoadFromDisk();
}
@@ -139,13 +142,14 @@
Map<String, Object> map = null;
StructStat stat = null;
+ Throwable thrown = null;
try {
stat = Os.stat(mFile.getPath());
if (mFile.canRead()) {
BufferedInputStream str = null;
try {
str = new BufferedInputStream(
- new FileInputStream(mFile), 16*1024);
+ new FileInputStream(mFile), 16 * 1024);
map = (Map<String, Object>) XmlUtils.readMapXml(str);
} catch (Exception e) {
Log.w(TAG, "Cannot read " + mFile.getAbsolutePath(), e);
@@ -154,19 +158,36 @@
}
}
} catch (ErrnoException e) {
- /* ignore */
+ // An errno exception means the stat failed. Treat as empty/non-existing by
+ // ignoring.
+ } catch (Throwable t) {
+ thrown = t;
}
synchronized (mLock) {
mLoaded = true;
- if (map != null) {
- mMap = map;
- mStatTimestamp = stat.st_mtim;
- mStatSize = stat.st_size;
- } else {
- mMap = new HashMap<>();
+ mThrowable = thrown;
+
+ // It's important that we always signal waiters, even if we'll make
+ // them fail with an exception. The try-finally is pretty wide, but
+ // better safe than sorry.
+ try {
+ if (thrown == null) {
+ if (map != null) {
+ mMap = map;
+ mStatTimestamp = stat.st_mtim;
+ mStatSize = stat.st_size;
+ } else {
+ mMap = new HashMap<>();
+ }
+ }
+ // In case of a thrown exception, we retain the old map. That allows
+ // any open editors to commit and store updates.
+ } catch (Throwable t) {
+ mThrowable = t;
+ } finally {
+ mLock.notifyAll();
}
- mLock.notifyAll();
}
}
@@ -226,6 +247,7 @@
}
}
+ @GuardedBy("mLock")
private void awaitLoadedLocked() {
if (!mLoaded) {
// Raise an explicit StrictMode onReadFromDisk for this
@@ -239,6 +261,9 @@
} catch (InterruptedException unused) {
}
}
+ if (mThrowable != null) {
+ throw new IllegalStateException(mThrowable);
+ }
}
@Override
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index ab70f0e..97c6681 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -81,10 +81,10 @@
import android.net.IpSecManager;
import android.net.NetworkPolicyManager;
import android.net.NetworkScoreManager;
-import android.net.nsd.INsdManager;
-import android.net.nsd.NsdManager;
import android.net.lowpan.ILowpanManager;
import android.net.lowpan.LowpanManager;
+import android.net.nsd.INsdManager;
+import android.net.nsd.NsdManager;
import android.net.wifi.IRttManager;
import android.net.wifi.IWifiManager;
import android.net.wifi.IWifiScanner;
@@ -130,6 +130,7 @@
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
+import android.telephony.euicc.EuiccCardManager;
import android.telephony.euicc.EuiccManager;
import android.util.Log;
import android.view.ContextThemeWrapper;
@@ -504,6 +505,13 @@
return new EuiccManager(ctx.getOuterContext());
}});
+ registerService(Context.EUICC_CARD_SERVICE, EuiccCardManager.class,
+ new CachedServiceFetcher<EuiccCardManager>() {
+ @Override
+ public EuiccCardManager createService(ContextImpl ctx) {
+ return new EuiccCardManager(ctx.getOuterContext());
+ }});
+
registerService(Context.UI_MODE_SERVICE, UiModeManager.class,
new CachedServiceFetcher<UiModeManager>() {
@Override
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index ad7a93c..9b736b7 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -618,6 +618,7 @@
*
* @hide
*/
+ @SystemApi
public static final int ACCESS_UNKNOWN = 0;
/**
@@ -626,6 +627,7 @@
*
* @hide
*/
+ @SystemApi
public static final int ACCESS_ALLOWED = 1;
/**
@@ -634,6 +636,7 @@
*
* @hide
*/
+ @SystemApi
public static final int ACCESS_REJECTED = 2;
/**
diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java
index c94540a..a68f485 100644
--- a/core/java/android/bluetooth/BluetoothHeadset.java
+++ b/core/java/android/bluetooth/BluetoothHeadset.java
@@ -556,8 +556,8 @@
* Set priority of the profile
*
* <p> The device should already be paired.
- * Priority can be one of {@link #PRIORITY_ON} or
- * {@link #PRIORITY_OFF},
+ * Priority can be one of {@link BluetoothProfile#PRIORITY_ON} or
+ * {@link BluetoothProfile#PRIORITY_OFF},
*
* <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
* permission.
diff --git a/core/java/android/bluetooth/BluetoothProfile.java b/core/java/android/bluetooth/BluetoothProfile.java
index 41cf809..0e2263f 100644
--- a/core/java/android/bluetooth/BluetoothProfile.java
+++ b/core/java/android/bluetooth/BluetoothProfile.java
@@ -19,6 +19,7 @@
import android.Manifest;
import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
import java.util.List;
@@ -185,6 +186,7 @@
*
* @hide
**/
+ @SystemApi
public static final int PRIORITY_ON = 100;
/**
@@ -193,6 +195,7 @@
*
* @hide
**/
+ @SystemApi
public static final int PRIORITY_OFF = 0;
/**
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 7e2ac63..70087da 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -3589,8 +3589,18 @@
public static final String EUICC_SERVICE = "euicc_service";
/**
- * Use with {@link #getSystemService} to retrieve a
- * {@link android.text.ClipboardManager} for accessing and modifying
+ * Use with {@link #getSystemService(String)} to retrieve a
+ * {@link android.telephony.euicc.EuiccCardManager} to access the device eUICC (embedded SIM).
+ *
+ * @see #getSystemService(String)
+ * @see android.telephony.euicc.EuiccCardManager
+ * TODO(b/35851809): Make this a SystemApi.
+ * @hide
+ */
+ public static final String EUICC_CARD_SERVICE = "euicc_card_service";
+
+ /**
+ * Use with {@link #getSystemService(String)} to retrieve a
* {@link android.content.ClipboardManager} for accessing and modifying
* the contents of the global clipboard.
*
diff --git a/core/java/android/hardware/usb/IUsbManager.aidl b/core/java/android/hardware/usb/IUsbManager.aidl
index 025d46d..4e8c45d 100644
--- a/core/java/android/hardware/usb/IUsbManager.aidl
+++ b/core/java/android/hardware/usb/IUsbManager.aidl
@@ -96,6 +96,11 @@
*/
void setCurrentFunction(String function, boolean usbDataUnlocked);
+ /* Sets the screen unlocked USB function(s), which will be set automatically
+ * when the screen is unlocked.
+ */
+ void setScreenUnlockedFunctions(String function);
+
/* Allow USB debugging from the attached host. If alwaysAllow is true, add the
* the public key to list of host keys that the user has approved.
*/
diff --git a/core/java/android/hardware/usb/UsbManager.java b/core/java/android/hardware/usb/UsbManager.java
index d73d3d8..48e8d34 100644
--- a/core/java/android/hardware/usb/UsbManager.java
+++ b/core/java/android/hardware/usb/UsbManager.java
@@ -590,6 +590,32 @@
}
/**
+ * Sets the screen unlocked functions, which are persisted and set as the current functions
+ * whenever the screen is unlocked.
+ * <p>
+ * The allowed values are: {@link #USB_FUNCTION_NONE},
+ * {@link #USB_FUNCTION_MIDI}, {@link #USB_FUNCTION_MTP}, {@link #USB_FUNCTION_PTP},
+ * or {@link #USB_FUNCTION_RNDIS}.
+ * {@link #USB_FUNCTION_NONE} has the effect of switching off this feature, so functions
+ * no longer change on screen unlock.
+ * </p><p>
+ * Note: When the screen is on, this method will apply given functions as current functions,
+ * which is asynchronous and may fail silently without applying the requested changes.
+ * </p>
+ *
+ * @param function function to set as default
+ *
+ * {@hide}
+ */
+ public void setScreenUnlockedFunctions(String function) {
+ try {
+ mService.setScreenUnlockedFunctions(function);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Returns a list of physical USB ports on the device.
* <p>
* This list is guaranteed to contain all dual-role USB Type C ports but it might
diff --git a/core/java/android/net/MacAddress.java b/core/java/android/net/MacAddress.java
index d6992aa..287bdc8 100644
--- a/core/java/android/net/MacAddress.java
+++ b/core/java/android/net/MacAddress.java
@@ -17,6 +17,7 @@
package android.net;
import android.annotation.IntDef;
+import android.annotation.NonNull;
import android.os.Parcel;
import android.os.Parcelable;
@@ -60,7 +61,7 @@
})
public @interface MacAddressType { }
- /** Indicates a MAC address of unknown type. */
+ /** @hide Indicates a MAC address of unknown type. */
public static final int TYPE_UNKNOWN = 0;
/** Indicates a MAC address is a unicast address. */
public static final int TYPE_UNICAST = 1;
@@ -92,7 +93,7 @@
*
* @return the int constant representing the MAC address type of this MacAddress.
*/
- public @MacAddressType int addressType() {
+ public @MacAddressType int getAddressType() {
if (equals(BROADCAST_ADDRESS)) {
return TYPE_BROADCAST;
}
@@ -120,12 +121,12 @@
/**
* @return a byte array representation of this MacAddress.
*/
- public byte[] toByteArray() {
+ public @NonNull byte[] toByteArray() {
return byteAddrFromLongAddr(mAddr);
}
@Override
- public String toString() {
+ public @NonNull String toString() {
return stringAddrFromLongAddr(mAddr);
}
@@ -133,7 +134,7 @@
* @return a String representation of the OUI part of this MacAddress made of 3 hexadecimal
* numbers in [0,ff] joined by ':' characters.
*/
- public String toOuiString() {
+ public @NonNull String toOuiString() {
return String.format(
"%02x:%02x:%02x", (mAddr >> 40) & 0xff, (mAddr >> 32) & 0xff, (mAddr >> 24) & 0xff);
}
@@ -197,7 +198,7 @@
if (!isMacAddress(addr)) {
return TYPE_UNKNOWN;
}
- return MacAddress.fromBytes(addr).addressType();
+ return MacAddress.fromBytes(addr).getAddressType();
}
/**
@@ -211,7 +212,7 @@
*
* @hide
*/
- public static byte[] byteAddrFromStringAddr(String addr) {
+ public static @NonNull byte[] byteAddrFromStringAddr(String addr) {
Preconditions.checkNotNull(addr);
String[] parts = addr.split(":");
if (parts.length != ETHER_ADDR_LEN) {
@@ -239,7 +240,7 @@
*
* @hide
*/
- public static String stringAddrFromByteAddr(byte[] addr) {
+ public static @NonNull String stringAddrFromByteAddr(byte[] addr) {
if (!isMacAddress(addr)) {
return null;
}
@@ -291,7 +292,7 @@
// Internal conversion function equivalent to stringAddrFromByteAddr(byteAddrFromLongAddr(addr))
// that avoids the allocation of an intermediary byte[].
- private static String stringAddrFromLongAddr(long addr) {
+ private static @NonNull String stringAddrFromLongAddr(long addr) {
return String.format("%02x:%02x:%02x:%02x:%02x:%02x",
(addr >> 40) & 0xff,
(addr >> 32) & 0xff,
@@ -310,7 +311,7 @@
* @return the MacAddress corresponding to the given String representation.
* @throws IllegalArgumentException if the given String is not a valid representation.
*/
- public static MacAddress fromString(String addr) {
+ public static @NonNull MacAddress fromString(@NonNull String addr) {
return new MacAddress(longAddrFromStringAddr(addr));
}
@@ -322,7 +323,7 @@
* @return the MacAddress corresponding to the given byte array representation.
* @throws IllegalArgumentException if the given byte array is not a valid representation.
*/
- public static MacAddress fromBytes(byte[] addr) {
+ public static @NonNull MacAddress fromBytes(@NonNull byte[] addr) {
return new MacAddress(longAddrFromByteAddr(addr));
}
@@ -336,7 +337,7 @@
*
* @hide
*/
- public static MacAddress createRandomUnicastAddress() {
+ public static @NonNull MacAddress createRandomUnicastAddress() {
return createRandomUnicastAddress(BASE_GOOGLE_MAC, new Random());
}
@@ -352,7 +353,7 @@
*
* @hide
*/
- public static MacAddress createRandomUnicastAddress(MacAddress base, Random r) {
+ public static @NonNull MacAddress createRandomUnicastAddress(MacAddress base, Random r) {
long addr = (base.mAddr & OUI_MASK) | (NIC_MASK & r.nextLong());
addr = addr | LOCALLY_ASSIGNED_MASK;
addr = addr & ~MULTICAST_MASK;
diff --git a/core/java/android/net/Network.java b/core/java/android/net/Network.java
index 903b602..3683d34 100644
--- a/core/java/android/net/Network.java
+++ b/core/java/android/net/Network.java
@@ -356,13 +356,13 @@
// Multiple Provisioning Domains API recommendations, as made by the
// IETF mif working group.
//
- // The HANDLE_MAGIC value MUST be kept in sync with the corresponding
+ // The handleMagic value MUST be kept in sync with the corresponding
// value in the native/android/net.c NDK implementation.
if (netId == 0) {
return 0L; // make this zero condition obvious for debugging
}
- final long HANDLE_MAGIC = 0xfacade;
- return (((long) netId) << 32) | HANDLE_MAGIC;
+ final long handleMagic = 0xcafed00dL;
+ return (((long) netId) << 32) | handleMagic;
}
// implement the Parcelable interface
diff --git a/core/java/android/net/metrics/WakeupStats.java b/core/java/android/net/metrics/WakeupStats.java
index 7277ba3..bb36536 100644
--- a/core/java/android/net/metrics/WakeupStats.java
+++ b/core/java/android/net/metrics/WakeupStats.java
@@ -80,7 +80,7 @@
break;
}
- switch (ev.dstHwAddr.addressType()) {
+ switch (ev.dstHwAddr.getAddressType()) {
case MacAddress.TYPE_UNICAST:
l2UnicastCount++;
break;
diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl
index a474b47..a5e1934 100644
--- a/core/java/android/os/INetworkManagementService.aidl
+++ b/core/java/android/os/INetworkManagementService.aidl
@@ -339,7 +339,8 @@
/**
* Configure name servers, search paths, and resolver parameters for the given network.
*/
- void setDnsConfigurationForNetwork(int netId, in String[] servers, String domains);
+ void setDnsConfigurationForNetwork(int netId, in String[] servers, in String[] domains,
+ in int[] params, boolean useTls, String tlsHostname);
void setFirewallEnabled(boolean enabled);
boolean isFirewallEnabled();
diff --git a/core/java/android/os/Seccomp.java b/core/java/android/os/Seccomp.java
index 335e44b..f14e93f 100644
--- a/core/java/android/os/Seccomp.java
+++ b/core/java/android/os/Seccomp.java
@@ -20,6 +20,5 @@
* @hide
*/
public final class Seccomp {
- public static native void setSystemServerPolicy();
- public static native void setAppPolicy();
+ public static final native void setPolicy();
}
diff --git a/core/java/android/os/VintfObject.java b/core/java/android/os/VintfObject.java
index 340f3fb..12a495b 100644
--- a/core/java/android/os/VintfObject.java
+++ b/core/java/android/os/VintfObject.java
@@ -76,8 +76,8 @@
/**
* @return a list of VNDK snapshots supported by the framework, as
* specified in framework manifest. For example,
- * [("25.0.5", ["libjpeg.so", "libbase.so"]),
- * ("25.1.3", ["libjpeg.so", "libbase.so"])]
+ * [("27", ["libjpeg.so", "libbase.so"]),
+ * ("28", ["libjpeg.so", "libbase.so"])]
*/
public static native Map<String, String[]> getVndkSnapshots();
}
diff --git a/core/java/android/service/carrier/CarrierIdentifier.java b/core/java/android/service/carrier/CarrierIdentifier.java
index b47e872..09bba4b 100644
--- a/core/java/android/service/carrier/CarrierIdentifier.java
+++ b/core/java/android/service/carrier/CarrierIdentifier.java
@@ -16,9 +16,14 @@
package android.service.carrier;
+import android.annotation.Nullable;
import android.os.Parcel;
import android.os.Parcelable;
+import com.android.internal.telephony.uicc.IccUtils;
+
+import java.util.Objects;
+
/**
* Used to pass info to CarrierConfigService implementations so they can decide what values to
* return.
@@ -40,13 +45,13 @@
private String mMcc;
private String mMnc;
- private String mSpn;
- private String mImsi;
- private String mGid1;
- private String mGid2;
+ private @Nullable String mSpn;
+ private @Nullable String mImsi;
+ private @Nullable String mGid1;
+ private @Nullable String mGid2;
- public CarrierIdentifier(String mcc, String mnc, String spn, String imsi, String gid1,
- String gid2) {
+ public CarrierIdentifier(String mcc, String mnc, @Nullable String spn, @Nullable String imsi,
+ @Nullable String gid1, @Nullable String gid2) {
mMcc = mcc;
mMnc = mnc;
mSpn = spn;
@@ -55,6 +60,32 @@
mGid2 = gid2;
}
+ /**
+ * Creates a carrier identifier instance.
+ *
+ * @param mccMnc A 3-byte array as defined by 3GPP TS 24.008.
+ * @param gid1 The group identifier level 1.
+ * @param gid2 The group identifier level 2.
+ * @throws IllegalArgumentException If the length of {@code mccMnc} is not 3.
+ */
+ public CarrierIdentifier(byte[] mccMnc, @Nullable String gid1, @Nullable String gid2) {
+ if (mccMnc.length != 3) {
+ throw new IllegalArgumentException(
+ "MCC & MNC must be set by a 3-byte array: byte[" + mccMnc.length + "]");
+ }
+ String hex = IccUtils.bytesToHexString(mccMnc);
+ mMcc = new String(new char[] {hex.charAt(1), hex.charAt(0), hex.charAt(3)});
+ if (hex.charAt(2) == 'F') {
+ mMnc = new String(new char[] {hex.charAt(5), hex.charAt(4)});
+ } else {
+ mMnc = new String(new char[] {hex.charAt(5), hex.charAt(4), hex.charAt(2)});
+ }
+ mGid1 = gid1;
+ mGid2 = gid2;
+ mSpn = null;
+ mImsi = null;
+ }
+
/** @hide */
public CarrierIdentifier(Parcel parcel) {
readFromParcel(parcel);
@@ -71,26 +102,60 @@
}
/** Get the service provider name. */
+ @Nullable
public String getSpn() {
return mSpn;
}
/** Get the international mobile subscriber identity. */
+ @Nullable
public String getImsi() {
return mImsi;
}
/** Get the group identifier level 1. */
+ @Nullable
public String getGid1() {
return mGid1;
}
/** Get the group identifier level 2. */
+ @Nullable
public String getGid2() {
return mGid2;
}
@Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+
+ CarrierIdentifier that = (CarrierIdentifier) obj;
+ return Objects.equals(mMcc, that.mMcc)
+ && Objects.equals(mMnc, that.mMnc)
+ && Objects.equals(mSpn, that.mSpn)
+ && Objects.equals(mImsi, that.mImsi)
+ && Objects.equals(mGid1, that.mGid1)
+ && Objects.equals(mGid2, that.mGid2);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = 1;
+ result = 31 * result + Objects.hashCode(mMcc);
+ result = 31 * result + Objects.hashCode(mMnc);
+ result = 31 * result + Objects.hashCode(mSpn);
+ result = 31 * result + Objects.hashCode(mImsi);
+ result = 31 * result + Objects.hashCode(mGid1);
+ result = 31 * result + Objects.hashCode(mGid2);
+ return result;
+ }
+
+ @Override
public int describeContents() {
return 0;
}
diff --git a/telephony/java/android/telephony/data/InterfaceAddress.aidl b/core/java/android/service/euicc/EuiccProfileInfo.aidl
similarity index 81%
copy from telephony/java/android/telephony/data/InterfaceAddress.aidl
copy to core/java/android/service/euicc/EuiccProfileInfo.aidl
index d750363..321021b 100644
--- a/telephony/java/android/telephony/data/InterfaceAddress.aidl
+++ b/core/java/android/service/euicc/EuiccProfileInfo.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright 2017 The Android Open Source Project
+ * Copyright (C) 2018 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.
@@ -13,8 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package android.service.euicc;
-/** @hide */
-package android.telephony.data;
-
-parcelable InterfaceAddress;
+parcelable EuiccProfileInfo;
diff --git a/core/java/android/service/euicc/EuiccProfileInfo.java b/core/java/android/service/euicc/EuiccProfileInfo.java
index ba6c9a2..8e752d1 100644
--- a/core/java/android/service/euicc/EuiccProfileInfo.java
+++ b/core/java/android/service/euicc/EuiccProfileInfo.java
@@ -15,12 +15,19 @@
*/
package android.service.euicc;
+import android.annotation.IntDef;
import android.annotation.Nullable;
import android.os.Parcel;
import android.os.Parcelable;
+import android.service.carrier.CarrierIdentifier;
import android.telephony.UiccAccessRule;
import android.text.TextUtils;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Arrays;
+import java.util.Objects;
+
/**
* Information about an embedded profile (subscription) on an eUICC.
*
@@ -30,18 +37,90 @@
*/
public final class EuiccProfileInfo implements Parcelable {
+ /** Profile policy rules (bit mask) */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(flag = true, prefix = { "POLICY_RULE_" }, value = {
+ POLICY_RULE_DO_NOT_DISABLE,
+ POLICY_RULE_DO_NOT_DELETE,
+ POLICY_RULE_DELETE_AFTER_DISABLING
+ })
+ public @interface PolicyRule {}
+ /** Once this profile is enabled, it cannot be disabled. */
+ public static final int POLICY_RULE_DO_NOT_DISABLE = 1;
+ /** This profile cannot be deleted. */
+ public static final int POLICY_RULE_DO_NOT_DELETE = 1 << 1;
+ /** This profile should be deleted after being disabled. */
+ public static final int POLICY_RULE_DELETE_AFTER_DISABLING = 1 << 2;
+
+ /** Class of the profile */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = { "PROFILE_CLASS_" }, value = {
+ PROFILE_CLASS_TESTING,
+ PROFILE_CLASS_PROVISIONING,
+ PROFILE_CLASS_OPERATIONAL,
+ PROFILE_CLASS_UNSET
+ })
+ public @interface ProfileClass {}
+ /** Testing profiles */
+ public static final int PROFILE_CLASS_TESTING = 0;
+ /** Provisioning profiles which are pre-loaded on eUICC */
+ public static final int PROFILE_CLASS_PROVISIONING = 1;
+ /** Operational profiles which can be pre-loaded or downloaded */
+ public static final int PROFILE_CLASS_OPERATIONAL = 2;
+ /**
+ * Profile class not set.
+ * @hide
+ */
+ public static final int PROFILE_CLASS_UNSET = -1;
+
+ /** State of the profile */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = { "PROFILE_STATE_" }, value = {
+ PROFILE_STATE_DISABLED,
+ PROFILE_STATE_ENABLED,
+ PROFILE_STATE_UNSET
+ })
+ public @interface ProfileState {}
+ /** Disabled profiles */
+ public static final int PROFILE_STATE_DISABLED = 0;
+ /** Enabled profile */
+ public static final int PROFILE_STATE_ENABLED = 1;
+ /**
+ * Profile state not set.
+ * @hide
+ */
+ public static final int PROFILE_STATE_UNSET = -1;
+
/** The iccid of the subscription. */
public final String iccid;
+ /** An optional nickname for the subscription. */
+ public final @Nullable String nickname;
+
+ /** The service provider name for the subscription. */
+ public final String serviceProviderName;
+
+ /** The profile name for the subscription. */
+ public final String profileName;
+
+ /** Profile class for the subscription. */
+ @ProfileClass public final int profileClass;
+
+ /** The profile state of the subscription. */
+ @ProfileState public final int state;
+
+ /** The operator Id of the subscription. */
+ public final CarrierIdentifier carrierIdentifier;
+
+ /** The policy rules of the subscription. */
+ @PolicyRule public final int policyRules;
+
/**
* Optional access rules defining which apps can manage this subscription. If unset, only the
* platform can manage it.
*/
public final @Nullable UiccAccessRule[] accessRules;
- /** An optional nickname for the subscription. */
- public final @Nullable String nickname;
-
public static final Creator<EuiccProfileInfo> CREATOR = new Creator<EuiccProfileInfo>() {
@Override
public EuiccProfileInfo createFromParcel(Parcel in) {
@@ -54,6 +133,12 @@
}
};
+ // TODO(b/70292228): Remove this method when LPA can be updated.
+ /**
+ * @hide
+ * @deprecated - Do not use.
+ */
+ @Deprecated
public EuiccProfileInfo(String iccid, @Nullable UiccAccessRule[] accessRules,
@Nullable String nickname) {
if (!TextUtils.isDigitsOnly(iccid)) {
@@ -62,23 +147,290 @@
this.iccid = iccid;
this.accessRules = accessRules;
this.nickname = nickname;
+
+ this.serviceProviderName = null;
+ this.profileName = null;
+ this.profileClass = PROFILE_CLASS_UNSET;
+ this.state = PROFILE_CLASS_UNSET;
+ this.carrierIdentifier = null;
+ this.policyRules = 0;
}
private EuiccProfileInfo(Parcel in) {
iccid = in.readString();
- accessRules = in.createTypedArray(UiccAccessRule.CREATOR);
nickname = in.readString();
+ serviceProviderName = in.readString();
+ profileName = in.readString();
+ profileClass = in.readInt();
+ state = in.readInt();
+ byte exist = in.readByte();
+ if (exist == (byte) 1) {
+ carrierIdentifier = CarrierIdentifier.CREATOR.createFromParcel(in);
+ } else {
+ carrierIdentifier = null;
+ }
+ policyRules = in.readInt();
+ accessRules = in.createTypedArray(UiccAccessRule.CREATOR);
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(iccid);
- dest.writeTypedArray(accessRules, flags);
dest.writeString(nickname);
+ dest.writeString(serviceProviderName);
+ dest.writeString(profileName);
+ dest.writeInt(profileClass);
+ dest.writeInt(state);
+ if (carrierIdentifier != null) {
+ dest.writeByte((byte) 1);
+ carrierIdentifier.writeToParcel(dest, flags);
+ } else {
+ dest.writeByte((byte) 0);
+ }
+ dest.writeInt(policyRules);
+ dest.writeTypedArray(accessRules, flags);
}
@Override
public int describeContents() {
return 0;
}
+
+ /** The builder to build a new {@link EuiccProfileInfo} instance. */
+ public static final class Builder {
+ public String iccid;
+ public UiccAccessRule[] accessRules;
+ public String nickname;
+ public String serviceProviderName;
+ public String profileName;
+ @ProfileClass public int profileClass;
+ @ProfileState public int state;
+ public CarrierIdentifier carrierIdentifier;
+ @PolicyRule public int policyRules;
+
+ public Builder() {}
+
+ public Builder(EuiccProfileInfo baseProfile) {
+ iccid = baseProfile.iccid;
+ nickname = baseProfile.nickname;
+ serviceProviderName = baseProfile.serviceProviderName;
+ profileName = baseProfile.profileName;
+ profileClass = baseProfile.profileClass;
+ state = baseProfile.state;
+ carrierIdentifier = baseProfile.carrierIdentifier;
+ policyRules = baseProfile.policyRules;
+ accessRules = baseProfile.accessRules;
+ }
+
+ /** Builds the profile instance. */
+ public EuiccProfileInfo build() {
+ if (iccid == null) {
+ throw new IllegalStateException("ICCID must be set for a profile.");
+ }
+ return new EuiccProfileInfo(
+ iccid,
+ nickname,
+ serviceProviderName,
+ profileName,
+ profileClass,
+ state,
+ carrierIdentifier,
+ policyRules,
+ accessRules);
+ }
+
+ /** Sets the iccId of the subscription. */
+ public Builder setIccid(String value) {
+ if (!TextUtils.isDigitsOnly(value)) {
+ throw new IllegalArgumentException("iccid contains invalid characters: " + value);
+ }
+ iccid = value;
+ return this;
+ }
+
+ /** Sets the nickname of the subscription. */
+ public Builder setNickname(String value) {
+ nickname = value;
+ return this;
+ }
+
+ /** Sets the service provider name of the subscription. */
+ public Builder setServiceProviderName(String value) {
+ serviceProviderName = value;
+ return this;
+ }
+
+ /** Sets the profile name of the subscription. */
+ public Builder setProfileName(String value) {
+ profileName = value;
+ return this;
+ }
+
+ /** Sets the profile class of the subscription. */
+ public Builder setProfileClass(@ProfileClass int value) {
+ profileClass = value;
+ return this;
+ }
+
+ /** Sets the state of the subscription. */
+ public Builder setState(@ProfileState int value) {
+ state = value;
+ return this;
+ }
+
+ /** Sets the carrier identifier of the subscription. */
+ public Builder setCarrierIdentifier(CarrierIdentifier value) {
+ carrierIdentifier = value;
+ return this;
+ }
+
+ /** Sets the policy rules of the subscription. */
+ public Builder setPolicyRules(@PolicyRule int value) {
+ policyRules = value;
+ return this;
+ }
+
+ /** Sets the access rules of the subscription. */
+ public Builder setUiccAccessRule(@Nullable UiccAccessRule[] value) {
+ accessRules = value;
+ return this;
+ }
+ }
+
+ private EuiccProfileInfo(
+ String iccid,
+ @Nullable String nickname,
+ String serviceProviderName,
+ String profileName,
+ @ProfileClass int profileClass,
+ @ProfileState int state,
+ CarrierIdentifier carrierIdentifier,
+ @PolicyRule int policyRules,
+ @Nullable UiccAccessRule[] accessRules) {
+ this.iccid = iccid;
+ this.nickname = nickname;
+ this.serviceProviderName = serviceProviderName;
+ this.profileName = profileName;
+ this.profileClass = profileClass;
+ this.state = state;
+ this.carrierIdentifier = carrierIdentifier;
+ this.policyRules = policyRules;
+ this.accessRules = accessRules;
+ }
+
+ /** Gets the ICCID string. */
+ public String getIccid() {
+ return iccid;
+ }
+
+ /** Gets the access rules. */
+ @Nullable
+ public UiccAccessRule[] getUiccAccessRules() {
+ return accessRules;
+ }
+
+ /** Gets the nickname. */
+ public String getNickname() {
+ return nickname;
+ }
+
+ /** Gets the service provider name. */
+ public String getServiceProviderName() {
+ return serviceProviderName;
+ }
+
+ /** Gets the profile name. */
+ public String getProfileName() {
+ return profileName;
+ }
+
+ /** Gets the profile class. */
+ @ProfileClass
+ public int getProfileClass() {
+ return profileClass;
+ }
+
+ /** Gets the state of the subscription. */
+ @ProfileState
+ public int getState() {
+ return state;
+ }
+
+ /** Gets the carrier identifier. */
+ public CarrierIdentifier getCarrierIdentifier() {
+ return carrierIdentifier;
+ }
+
+ /** Gets the policy rules. */
+ @PolicyRule
+ public int getPolicyRules() {
+ return policyRules;
+ }
+
+ /** Returns whether any policy rule exists. */
+ public boolean hasPolicyRules() {
+ return policyRules != 0;
+ }
+
+ /** Checks whether a certain policy rule exists. */
+ public boolean hasPolicyRule(@PolicyRule int policy) {
+ return (policyRules & policy) != 0;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+
+ EuiccProfileInfo that = (EuiccProfileInfo) obj;
+ return Objects.equals(iccid, that.iccid)
+ && Objects.equals(nickname, that.nickname)
+ && Objects.equals(serviceProviderName, that.serviceProviderName)
+ && Objects.equals(profileName, that.profileName)
+ && profileClass == that.profileClass
+ && state == that.state
+ && Objects.equals(carrierIdentifier, that.carrierIdentifier)
+ && policyRules == that.policyRules
+ && Arrays.equals(accessRules, that.accessRules);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = 1;
+ result = 31 * result + Objects.hashCode(iccid);
+ result = 31 * result + Objects.hashCode(nickname);
+ result = 31 * result + Objects.hashCode(serviceProviderName);
+ result = 31 * result + Objects.hashCode(profileName);
+ result = 31 * result + profileClass;
+ result = 31 * result + state;
+ result = 31 * result + Objects.hashCode(carrierIdentifier);
+ result = 31 * result + policyRules;
+ result = 31 * result + Arrays.hashCode(accessRules);
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "EuiccProfileInfo (nickname="
+ + nickname
+ + ", serviceProviderName="
+ + serviceProviderName
+ + ", profileName="
+ + profileName
+ + ", profileClass="
+ + profileClass
+ + ", state="
+ + state
+ + ", CarrierIdentifier="
+ + carrierIdentifier.toString()
+ + ", policyRules="
+ + policyRules
+ + ", accessRules="
+ + Arrays.toString(accessRules)
+ + ")";
+ }
}
diff --git a/core/java/android/service/euicc/EuiccService.java b/core/java/android/service/euicc/EuiccService.java
index fb53007..be85800 100644
--- a/core/java/android/service/euicc/EuiccService.java
+++ b/core/java/android/service/euicc/EuiccService.java
@@ -193,6 +193,18 @@
}
/**
+ * Callback class for {@link #onStartOtaIfNecessary(int, OtaStatusChangedCallback)}
+ *
+ * The status of OTA which can be {@code android.telephony.euicc.EuiccManager#EUICC_OTA_}
+ *
+ * @see IEuiccService#startOtaIfNecessary
+ */
+ public interface OtaStatusChangedCallback {
+ /** Called when OTA status is changed. */
+ void onOtaStatusChanged(int status);
+ }
+
+ /**
* Return the EID of the eUICC.
*
* @param slotId ID of the SIM slot being queried. This is currently not populated but is here
@@ -214,6 +226,16 @@
public abstract @OtaStatus int onGetOtaStatus(int slotId);
/**
+ * Perform OTA if current OS is not the latest one.
+ *
+ * @param slotId ID of the SIM slot to use for the operation. This is currently not populated
+ * but is here to future-proof the APIs.
+ * @param statusChangedCallback Function called when OTA status changed.
+ */
+ public abstract void onStartOtaIfNecessary(
+ int slotId, OtaStatusChangedCallback statusChangedCallback);
+
+ /**
* Populate {@link DownloadableSubscription} metadata for the given downloadable subscription.
*
* @param slotId ID of the SIM slot to use for the operation. This is currently not populated
@@ -396,6 +418,26 @@
}
@Override
+ public void startOtaIfNecessary(
+ int slotId, IOtaStatusChangedCallback statusChangedCallback) {
+ mExecutor.execute(new Runnable() {
+ @Override
+ public void run() {
+ EuiccService.this.onStartOtaIfNecessary(slotId, new OtaStatusChangedCallback() {
+ @Override
+ public void onOtaStatusChanged(int status) {
+ try {
+ statusChangedCallback.onOtaStatusChanged(status);
+ } catch (RemoteException e) {
+ // Can't communicate with the phone process; ignore.
+ }
+ }
+ });
+ }
+ });
+ }
+
+ @Override
public void getOtaStatus(int slotId, IGetOtaStatusCallback callback) {
mExecutor.execute(new Runnable() {
@Override
diff --git a/core/java/android/service/euicc/IEuiccService.aidl b/core/java/android/service/euicc/IEuiccService.aidl
index a24e5c3..45be527 100644
--- a/core/java/android/service/euicc/IEuiccService.aidl
+++ b/core/java/android/service/euicc/IEuiccService.aidl
@@ -25,6 +25,7 @@
import android.service.euicc.IGetEuiccInfoCallback;
import android.service.euicc.IGetEuiccProfileInfoListCallback;
import android.service.euicc.IGetOtaStatusCallback;
+import android.service.euicc.IOtaStatusChangedCallback;
import android.service.euicc.IRetainSubscriptionsForFactoryResetCallback;
import android.service.euicc.ISwitchToSubscriptionCallback;
import android.service.euicc.IUpdateSubscriptionNicknameCallback;
@@ -39,6 +40,7 @@
boolean forceDeactivateSim, in IGetDownloadableSubscriptionMetadataCallback callback);
void getEid(int slotId, in IGetEidCallback callback);
void getOtaStatus(int slotId, in IGetOtaStatusCallback callback);
+ void startOtaIfNecessary(int slotId, in IOtaStatusChangedCallback statusChangedCallback);
void getEuiccProfileInfoList(int slotId, in IGetEuiccProfileInfoListCallback callback);
void getDefaultDownloadableSubscriptionList(int slotId, boolean forceDeactivateSim,
in IGetDefaultDownloadableSubscriptionListCallback callback);
diff --git a/telephony/java/android/telephony/data/InterfaceAddress.aidl b/core/java/android/service/euicc/IOtaStatusChangedCallback.aidl
similarity index 76%
copy from telephony/java/android/telephony/data/InterfaceAddress.aidl
copy to core/java/android/service/euicc/IOtaStatusChangedCallback.aidl
index d750363..caec75f 100644
--- a/telephony/java/android/telephony/data/InterfaceAddress.aidl
+++ b/core/java/android/service/euicc/IOtaStatusChangedCallback.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright 2017 The Android Open Source Project
+ * Copyright (C) 2017 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.
@@ -14,7 +14,9 @@
* limitations under the License.
*/
-/** @hide */
-package android.telephony.data;
+package android.service.euicc;
-parcelable InterfaceAddress;
+/** @hide */
+oneway interface IOtaStatusChangedCallback {
+ void onOtaStatusChanged(int status);
+}
\ No newline at end of file
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index ebebad2..3ee8b47 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -17,7 +17,6 @@
package com.android.internal.os;
-import android.os.Seccomp;
import android.os.Trace;
import dalvik.system.ZygoteHooks;
import android.system.ErrnoException;
@@ -156,9 +155,6 @@
*/
public static int forkSystemServer(int uid, int gid, int[] gids, int runtimeFlags,
int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
- // Set system server specific seccomp policy.
- Seccomp.setSystemServerPolicy();
-
VM_HOOKS.preFork();
// Resets nice priority for zygote process.
resetNicePriority();
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index 24c4a8d..6a87b1f 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -30,7 +30,6 @@
import android.net.LocalSocket;
import android.os.FactoryTest;
import android.os.Process;
-import android.os.Seccomp;
import android.os.SystemProperties;
import android.os.Trace;
import android.system.ErrnoException;
@@ -768,9 +767,6 @@
Process.setArgV0(parsedArgs.niceName);
}
- // Set app specific seccomp policy.
- Seccomp.setAppPolicy();
-
// End of the postFork event.
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
if (parsedArgs.invokeWith != null) {
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 4016832..2be6212 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -782,6 +782,9 @@
// Zygote process unmounts root storage spaces.
Zygote.nativeUnmountStorageOnInit();
+ // Set seccomp policy
+ Seccomp.setPolicy();
+
ZygoteHooks.stopZygoteNoThreadCreation();
if (startSystemServer) {
diff --git a/core/jni/android_os_VintfObject.cpp b/core/jni/android_os_VintfObject.cpp
index 1eeea51..1659168 100644
--- a/core/jni/android_os_VintfObject.cpp
+++ b/core/jni/android_os_VintfObject.cpp
@@ -146,8 +146,8 @@
return nullptr;
}
jobject jMap = env->NewObject(gHashMapClazz, gHashMapInit);
- for (const Vndk &vndk : manifest->vndks()) {
- std::string key = to_string(vndk.versionRange());
+ for (const auto &vndk : manifest->vendorNdks()) {
+ std::string key = vndk.version();
env->CallObjectMethod(jMap, gHashMapPut,
env->NewStringUTF(key.c_str()), toJavaStringArray(env, vndk.libraries()));
}
diff --git a/core/jni/android_os_seccomp.cpp b/core/jni/android_os_seccomp.cpp
index b9006e4..06e2a16 100644
--- a/core/jni/android_os_seccomp.cpp
+++ b/core/jni/android_os_seccomp.cpp
@@ -21,33 +21,20 @@
#include "seccomp_policy.h"
-static void Seccomp_setSystemServerPolicy(JNIEnv* /*env*/) {
+static void Seccomp_setPolicy(JNIEnv* /*env*/) {
if (security_getenforce() == 0) {
ALOGI("seccomp disabled by setenforce 0");
return;
}
- if (!set_system_seccomp_filter()) {
- ALOGE("Failed to set seccomp policy - killing");
- exit(1);
- }
-}
-
-static void Seccomp_setAppPolicy(JNIEnv* /*env*/) {
- if (security_getenforce() == 0) {
- ALOGI("seccomp disabled by setenforce 0");
- return;
- }
-
- if (!set_app_seccomp_filter()) {
+ if (!set_seccomp_filter()) {
ALOGE("Failed to set seccomp policy - killing");
exit(1);
}
}
static const JNINativeMethod method_table[] = {
- NATIVE_METHOD(Seccomp, setSystemServerPolicy, "()V"),
- NATIVE_METHOD(Seccomp, setAppPolicy, "()V"),
+ NATIVE_METHOD(Seccomp, setPolicy, "()V"),
};
namespace android {
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 4b2ae06..fdda55b 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -563,6 +563,9 @@
<protected-broadcast android:name="android.media.tv.action.CHANNEL_BROWSABLE_REQUESTED" />
<protected-broadcast android:name="com.android.server.InputMethodManagerService.SHOW_INPUT_METHOD_PICKER" />
+ <!-- Added in P -->
+ <protected-broadcast android:name="android.telephony.euicc.action.OTA_STATUS_CHANGED" />
+
<!-- ====================================================================== -->
<!-- RUNTIME PERMISSIONS -->
<!-- ====================================================================== -->
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 960ad1b..e18265b 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2557,6 +2557,13 @@
<bool name="config_sms_force_7bit_encoding">false</bool>
+ <!-- Number of physical SIM slots on the device. This includes both eSIM and pSIM slots, and
+ is not necessarily the same as the number of phones/logical modems supported by the device.
+ For example, a multi-sim device can have 2 phones/logical modems, but 3 physical slots,
+ or a single SIM device can have 1 phones/logical modems, but 2 physical slots (one eSIM
+ and one pSIM) -->
+ <integer name="config_num_physical_slots">1</integer>
+
<!--Thresholds for LTE dbm in status bar-->
<integer-array translatable="false" name="config_lteDbmThresholds">
<item>-140</item> <!-- SIGNAL_STRENGTH_NONE_OR_UNKNOWN -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 438ed82..f1070de 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -445,6 +445,7 @@
<java-symbol type="integer" name="config_keepPreloadsMinDays" />
<java-symbol type="bool" name="config_hasPermanentDpad" />
<java-symbol type="bool" name="config_useDefaultFocusHighlight" />
+ <java-symbol type="integer" name="config_num_physical_slots" />
<java-symbol type="color" name="tab_indicator_text_v4" />
diff --git a/core/tests/coretests/src/android/service/euicc/EuiccProfileInfoTest.java b/core/tests/coretests/src/android/service/euicc/EuiccProfileInfoTest.java
new file mode 100644
index 0000000..1e3ddf3
--- /dev/null
+++ b/core/tests/coretests/src/android/service/euicc/EuiccProfileInfoTest.java
@@ -0,0 +1,247 @@
+/*
+ * Copyright (C) 2017 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 android.service.euicc;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertTrue;
+
+import android.os.Parcel;
+import android.service.carrier.CarrierIdentifier;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.telephony.UiccAccessRule;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class EuiccProfileInfoTest {
+ @Test
+ public void testWriteToParcel() {
+ EuiccProfileInfo p =
+ new EuiccProfileInfo.Builder()
+ .setIccid("21430000000000006587")
+ .setNickname("profile nickname")
+ .setServiceProviderName("service provider")
+ .setProfileName("profile name")
+ .setProfileClass(EuiccProfileInfo.PROFILE_CLASS_OPERATIONAL)
+ .setState(EuiccProfileInfo.PROFILE_STATE_ENABLED)
+ .setCarrierIdentifier(
+ new CarrierIdentifier(
+ new byte[] {0x23, 0x45, 0x67},
+ "123",
+ "45"))
+ .setPolicyRules(EuiccProfileInfo.POLICY_RULE_DO_NOT_DELETE)
+ .setUiccAccessRule(
+ new UiccAccessRule[] {
+ new UiccAccessRule(new byte[] {}, "package", 12345L)
+ })
+ .build();
+
+ Parcel parcel = Parcel.obtain();
+ assertTrue(parcel != null);
+ p.writeToParcel(parcel, 0);
+
+ parcel.setDataPosition(0);
+ EuiccProfileInfo fromParcel = EuiccProfileInfo.CREATOR.createFromParcel(parcel);
+
+ assertEquals(p, fromParcel);
+ }
+
+ @Test
+ public void testWriteToParcelNullCarrierId() {
+ EuiccProfileInfo p =
+ new EuiccProfileInfo.Builder()
+ .setIccid("21430000000000006587")
+ .setNickname("profile nickname")
+ .setServiceProviderName("service provider")
+ .setProfileName("profile name")
+ .setProfileClass(EuiccProfileInfo.PROFILE_CLASS_OPERATIONAL)
+ .setState(EuiccProfileInfo.PROFILE_STATE_ENABLED)
+ .setPolicyRules(EuiccProfileInfo.POLICY_RULE_DO_NOT_DELETE)
+ .setUiccAccessRule(
+ new UiccAccessRule[] {
+ new UiccAccessRule(new byte[] {}, "package", 12345L)
+ })
+ .build();
+
+ Parcel parcel = Parcel.obtain();
+ assertTrue(parcel != null);
+ p.writeToParcel(parcel, 0);
+
+ parcel.setDataPosition(0);
+ EuiccProfileInfo fromParcel = EuiccProfileInfo.CREATOR.createFromParcel(parcel);
+
+ assertEquals(p, fromParcel);
+ }
+
+ @Test
+ public void testBuilderAndGetters() {
+ EuiccProfileInfo p =
+ new EuiccProfileInfo.Builder()
+ .setIccid("21430000000000006587")
+ .setNickname("profile nickname")
+ .setProfileName("profile name")
+ .setServiceProviderName("service provider")
+ .setCarrierIdentifier(
+ new CarrierIdentifier(
+ new byte[] {0x23, 0x45, 0x67},
+ "123",
+ "45"))
+ .setState(EuiccProfileInfo.PROFILE_STATE_ENABLED)
+ .setProfileClass(EuiccProfileInfo.PROFILE_CLASS_OPERATIONAL)
+ .setPolicyRules(EuiccProfileInfo.POLICY_RULE_DO_NOT_DELETE)
+ .setUiccAccessRule(
+ new UiccAccessRule[] {
+ new UiccAccessRule(new byte[0], null, 0)
+ })
+ .build();
+
+ assertEquals("21430000000000006587", p.getIccid());
+ assertEquals("profile nickname", p.getNickname());
+ assertEquals("profile name", p.getProfileName());
+ assertEquals("service provider", p.getServiceProviderName());
+ assertEquals("325", p.getCarrierIdentifier().getMcc());
+ assertEquals("764", p.getCarrierIdentifier().getMnc());
+ assertEquals("123", p.getCarrierIdentifier().getGid1());
+ assertEquals("45", p.getCarrierIdentifier().getGid2());
+ assertEquals(EuiccProfileInfo.PROFILE_STATE_ENABLED, p.getState());
+ assertEquals(EuiccProfileInfo.PROFILE_CLASS_OPERATIONAL, p.getProfileClass());
+ assertEquals(EuiccProfileInfo.POLICY_RULE_DO_NOT_DELETE, p.getPolicyRules());
+ assertTrue(p.hasPolicyRules());
+ assertTrue(p.hasPolicyRule(EuiccProfileInfo.POLICY_RULE_DO_NOT_DELETE));
+ assertFalse(p.hasPolicyRule(EuiccProfileInfo.POLICY_RULE_DO_NOT_DISABLE));
+ assertArrayEquals(
+ new UiccAccessRule[] {new UiccAccessRule(new byte[0], null, 0)},
+ p.getUiccAccessRules());
+ }
+
+ @Test
+ public void testBuilder_BasedOnAnotherProfile() {
+ EuiccProfileInfo p =
+ new EuiccProfileInfo.Builder()
+ .setIccid("21430000000000006587")
+ .setNickname("profile nickname")
+ .setProfileName("profile name")
+ .setServiceProviderName("service provider")
+ .setCarrierIdentifier(
+ new CarrierIdentifier(
+ new byte[] {0x23, 0x45, 0x67},
+ "123",
+ "45"))
+ .setState(EuiccProfileInfo.PROFILE_STATE_ENABLED)
+ .setProfileClass(EuiccProfileInfo.PROFILE_CLASS_OPERATIONAL)
+ .setPolicyRules(EuiccProfileInfo.POLICY_RULE_DO_NOT_DELETE)
+ .setUiccAccessRule(
+ new UiccAccessRule[] {
+ new UiccAccessRule(new byte[0], null, 0)
+ })
+ .build();
+
+ EuiccProfileInfo copied = new EuiccProfileInfo.Builder(p).build();
+
+ assertEquals(p, copied);
+ assertEquals(p.hashCode(), copied.hashCode());
+ }
+
+ @Test
+ public void testEqualsHashCode() {
+ EuiccProfileInfo p =
+ new EuiccProfileInfo.Builder()
+ .setIccid("21430000000000006587")
+ .setNickname("profile nickname")
+ .setProfileName("profile name")
+ .setServiceProviderName("service provider")
+ .setCarrierIdentifier(
+ new CarrierIdentifier(
+ new byte[] {0x23, 0x45, 0x67},
+ "123",
+ "45"))
+ .setState(EuiccProfileInfo.PROFILE_STATE_ENABLED)
+ .setProfileClass(EuiccProfileInfo.PROFILE_STATE_ENABLED)
+ .setPolicyRules(EuiccProfileInfo.POLICY_RULE_DO_NOT_DELETE)
+ .setUiccAccessRule(
+ new UiccAccessRule[] {
+ new UiccAccessRule(new byte[0], null, 0)
+ })
+ .build();
+
+ assertTrue(p.equals(p));
+ assertFalse(p.equals(new Object()));
+
+ EuiccProfileInfo t = null;
+ assertFalse(p.equals(t));
+
+ t = new EuiccProfileInfo.Builder(p).setIccid("21").build();
+ assertFalse(p.equals(t));
+ assertNotEquals(p.hashCode(), t.hashCode());
+
+ t = new EuiccProfileInfo.Builder(p).setNickname(null).build();
+ assertFalse(p.equals(t));
+ assertNotEquals(p.hashCode(), t.hashCode());
+
+ t = new EuiccProfileInfo.Builder(p).setProfileName(null).build();
+ assertFalse(p.equals(t));
+ assertNotEquals(p.hashCode(), t.hashCode());
+
+ t = new EuiccProfileInfo.Builder(p).setServiceProviderName(null).build();
+ assertFalse(p.equals(t));
+ assertNotEquals(p.hashCode(), t.hashCode());
+
+ t = new EuiccProfileInfo.Builder(p).setCarrierIdentifier(null).build();
+ assertFalse(p.equals(t));
+ assertNotEquals(p.hashCode(), t.hashCode());
+
+ t = new EuiccProfileInfo.Builder(p)
+ .setState(EuiccProfileInfo.PROFILE_STATE_DISABLED).build();
+ assertFalse(p.equals(t));
+ assertNotEquals(p.hashCode(), t.hashCode());
+
+ t = new EuiccProfileInfo.Builder(p)
+ .setProfileClass(EuiccProfileInfo.PROFILE_CLASS_TESTING).build();
+ assertFalse(p.equals(t));
+ assertNotEquals(p.hashCode(), t.hashCode());
+
+ t = new EuiccProfileInfo.Builder(p).setPolicyRules(0).build();
+ assertFalse(p.equals(t));
+ assertNotEquals(p.hashCode(), t.hashCode());
+
+ t = new EuiccProfileInfo.Builder(p).setUiccAccessRule(null).build();
+ assertFalse(p.equals(t));
+ assertNotEquals(p.hashCode(), t.hashCode());
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void testBuilderBuild_NoIccid() {
+ new EuiccProfileInfo.Builder().build();
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testBuilderSetOperatorMccMnc_Illegal() {
+ new EuiccProfileInfo.Builder()
+ .setCarrierIdentifier(new CarrierIdentifier(new byte[] {1, 2, 3, 4}, null, null));
+ }
+
+ @Test
+ public void testCreatorNewArray() {
+ EuiccProfileInfo[] profiles = EuiccProfileInfo.CREATOR.newArray(123);
+ assertEquals(123, profiles.length);
+ }
+}
diff --git a/legacy-test/Android.mk b/legacy-test/Android.mk
deleted file mode 100644
index 793bbe8..0000000
--- a/legacy-test/Android.mk
+++ /dev/null
@@ -1,118 +0,0 @@
-#
-# Copyright (C) 2016 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.
-#
-
-LOCAL_PATH:= $(call my-dir)
-
-# Generate the stub source files for legacy.test.stubs
-# ====================================================
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
- $(call all-java-files-under, src)
-
-LOCAL_JAVA_LIBRARIES := \
- core-oj \
- core-libart \
- framework \
-
-LOCAL_MODULE_CLASS := JAVA_LIBRARIES
-LOCAL_DROIDDOC_SOURCE_PATH := $(LOCAL_PATH)/src
-
-LEGACY_TEST_OUTPUT_API_FILE := $(TARGET_OUT_COMMON_INTERMEDIATES)/JAVA_LIBRARIES/legacy.test.stubs_intermediates/api.txt
-LEGACY_TEST_OUTPUT_REMOVED_API_FILE := $(TARGET_OUT_COMMON_INTERMEDIATES)/JAVA_LIBRARIES/legacy.test.stubs_intermediates/removed.txt
-
-LEGACY_TEST_API_FILE := $(LOCAL_PATH)/api/legacy-test-current.txt
-LEGACY_TEST_REMOVED_API_FILE := $(LOCAL_PATH)/api/legacy-test-removed.txt
-
-LOCAL_DROIDDOC_OPTIONS:= \
- -stubpackages android.test:android.test.suitebuilder.annotation:com.android.internal.util:junit.framework \
- -stubsourceonly \
- -stubs $(TARGET_OUT_COMMON_INTERMEDIATES)/JAVA_LIBRARIES/legacy.test.stubs_intermediates/src \
- -nodocs \
- -api $(LEGACY_TEST_OUTPUT_API_FILE) \
- -removedApi $(LEGACY_TEST_OUTPUT_REMOVED_API_FILE) \
-
-LOCAL_UNINSTALLABLE_MODULE := true
-LOCAL_MODULE := legacy-test-api-stubs-gen
-
-include $(BUILD_DROIDDOC)
-
-# Remember the target that will trigger the code generation.
-legacy_test_api_gen_stamp := $(full_target)
-
-# Add some additional dependencies
-$(LEGACY_TEST_OUTPUT_API_FILE): $(full_target)
-$(LEGACY_TEST_OUTPUT_REMOVED_API_FILE): $(full_target)
-
-# Build the legacy.test.stubs library
-# ===================================
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := legacy.test.stubs
-
-LOCAL_SOURCE_FILES_ALL_GENERATED := true
-
-# Make sure to run droiddoc first to generate the stub source files.
-LOCAL_ADDITIONAL_DEPENDENCIES := $(legacy_test_api_gen_stamp)
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
-# Archive a copy of the classes.jar in SDK build.
-$(call dist-for-goals,sdk win_sdk,$(full_classes_jar):legacy.test.stubs.jar)
-
-# Check that the legacy.test.stubs library has not changed
-# ========================================================
-
-# Check that the API we're building hasn't changed from the not-yet-released
-# SDK version.
-$(eval $(call check-api, \
- check-legacy-test-api-current, \
- $(LEGACY_TEST_API_FILE), \
- $(LEGACY_TEST_OUTPUT_API_FILE), \
- $(LEGACY_TEST_REMOVED_API_FILE), \
- $(LEGACY_TEST_OUTPUT_REMOVED_API_FILE), \
- -error 2 -error 3 -error 4 -error 5 -error 6 \
- -error 7 -error 8 -error 9 -error 10 -error 11 -error 12 -error 13 -error 14 -error 15 \
- -error 16 -error 17 -error 18 -error 19 -error 20 -error 21 -error 23 -error 24 \
- -error 25 -error 26 -error 27, \
- cat $(LOCAL_PATH)/api/apicheck_msg_legacy_test.txt, \
- check-legacy-test-api, \
- $(call doc-timestamp-for,legacy-test-api-stubs-gen) \
- ))
-
-.PHONY: check-legacy-test-api
-checkapi: check-legacy-test-api
-
-.PHONY: update-legacy-test-api
-update-api: update-legacy-test-api
-
-update-legacy-test-api: $(LEGACY_TEST_OUTPUT_API_FILE) | $(ACP)
- @echo Copying current.txt
- $(hide) $(ACP) $(LEGACY_TEST_OUTPUT_API_FILE) $(LEGACY_TEST_API_FILE)
- @echo Copying removed.txt
- $(hide) $(ACP) $(LEGACY_TEST_OUTPUT_REMOVED_API_FILE) $(LEGACY_TEST_REMOVED_API_FILE)
-
-ifeq ($(HOST_OS),linux)
-# Build the legacy-performance-test-hostdex library
-# =================================================
-# This contains the android.test.PerformanceTestCase class only
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := src/android/test/PerformanceTestCase.java
-LOCAL_MODULE := legacy-performance-test-hostdex
-
-include $(BUILD_HOST_DALVIK_STATIC_JAVA_LIBRARY)
-endif # HOST_OS == linux
diff --git a/legacy-test/api/apicheck_msg_legacy_test.txt b/legacy-test/api/apicheck_msg_legacy_test.txt
deleted file mode 100644
index ad5f235..0000000
--- a/legacy-test/api/apicheck_msg_legacy_test.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-
-******************************
-You have tried to change the API from what has been previously approved.
-
-To make these errors go away, you have two choices:
- 1) You can add "@hide" javadoc comments to the methods, etc. listed in the
- errors above.
-
- 2) You can update legacy-test-current.txt by executing the following command:
- make update-legacy-test-api
-
- To submit the revised legacy-test-current.txt to the main Android repository,
- you will need approval.
-******************************
-
-
-
diff --git a/libs/input/PointerController.cpp b/libs/input/PointerController.cpp
index 7c60467..e3af655 100644
--- a/libs/input/PointerController.cpp
+++ b/libs/input/PointerController.cpp
@@ -551,18 +551,20 @@
}
// Animate spots that are fading out and being removed.
- for (size_t i = 0; i < mLocked.spots.size(); i++) {
+ for (size_t i = 0; i < mLocked.spots.size();) {
Spot* spot = mLocked.spots.itemAt(i);
if (spot->id == Spot::INVALID_ID) {
spot->alpha -= float(frameDelay) / SPOT_FADE_DURATION;
if (spot->alpha <= 0) {
- mLocked.spots.removeAt(i--);
+ mLocked.spots.removeAt(i);
releaseSpotLocked(spot);
+ continue;
} else {
spot->sprite->setAlpha(spot->alpha);
keepAnimating = true;
}
}
+ ++i;
}
return keepAnimating;
}
diff --git a/libs/services/Android.bp b/libs/services/Android.bp
new file mode 100644
index 0000000..53e6201
--- /dev/null
+++ b/libs/services/Android.bp
@@ -0,0 +1,46 @@
+// Copyright (C) 2018 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.
+
+// Provides C++ wrappers for system services.
+
+cc_library_shared {
+ name: "libservices",
+ srcs: [
+ ":IDropBoxManagerService.aidl",
+ "src/os/DropBoxManager.cpp",
+ ],
+
+ shared_libs: [
+ "libbinder",
+ "liblog",
+ "libcutils",
+ "libutils",
+ ],
+ header_libs: [
+ "libbase_headers",
+ ],
+ aidl: {
+ include_dirs: ["frameworks/base/core/java/"],
+ },
+
+ export_include_dirs: ["include"],
+ export_header_lib_headers: ["libbase_headers"],
+
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wunused",
+ "-Wunreachable-code",
+ ],
+}
diff --git a/libs/services/Android.mk b/libs/services/Android.mk
deleted file mode 100644
index cbfd4b3..0000000
--- a/libs/services/Android.mk
+++ /dev/null
@@ -1,43 +0,0 @@
-# Copyright (C) 2010 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.
-
-LOCAL_PATH:= $(call my-dir)
-
-# Provides C++ wrappers for system services.
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libservices
-LOCAL_SRC_FILES := \
- ../../core/java/com/android/internal/os/IDropBoxManagerService.aidl \
- src/os/DropBoxManager.cpp
-
-LOCAL_AIDL_INCLUDES := \
- $(LOCAL_PATH)/../../core/java
-LOCAL_C_INCLUDES := \
- system/core/include
-LOCAL_SHARED_LIBRARIES := \
- libbinder \
- liblog \
- libcutils \
- libutils
-
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
-LOCAL_C_INCLUDES += $(LOCAL_PATH)/include
-
-LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code
-
-include $(BUILD_SHARED_LIBRARY)
-
-
diff --git a/native/android/net.c b/native/android/net.c
index de4b90c..60296a7 100644
--- a/native/android/net.c
+++ b/native/android/net.c
@@ -27,7 +27,7 @@
static const uint32_t k32BitMask = 0xffffffff;
// This value MUST be kept in sync with the corresponding value in
// the android.net.Network#getNetworkHandle() implementation.
- static const uint32_t kHandleMagic = 0xfacade;
+ static const uint32_t kHandleMagic = 0xcafed00d;
// Check for minimum acceptable version of the API in the low bits.
if (handle != NETWORK_UNSPECIFIED &&
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 5228498..ed1e011 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -130,6 +130,7 @@
import com.android.internal.util.XmlUtils;
import com.android.server.am.BatteryStatsService;
import com.android.server.connectivity.DataConnectionStats;
+import com.android.server.connectivity.DnsManager;
import com.android.server.connectivity.IpConnectivityMetrics;
import com.android.server.connectivity.KeepaliveTracker;
import com.android.server.connectivity.LingerMonitor;
@@ -224,7 +225,11 @@
@GuardedBy("mVpns")
private final SparseArray<Vpn> mVpns = new SparseArray<Vpn>();
+ // TODO: investigate if mLockdownEnabled can be removed and replaced everywhere by
+ // a direct call to LockdownVpnTracker.isEnabled().
+ @GuardedBy("mVpns")
private boolean mLockdownEnabled;
+ @GuardedBy("mVpns")
private LockdownVpnTracker mLockdownTracker;
final private Context mContext;
@@ -232,8 +237,6 @@
// 0 is full bad, 100 is full good
private int mDefaultInetConditionPublished = 0;
- private int mNumDnsEntries;
-
private boolean mTestMode;
private static ConnectivityService sServiceInstance;
@@ -407,6 +410,7 @@
final private InternalHandler mHandler;
/** Handler used for incoming {@link NetworkStateTracker} events. */
final private NetworkStateTrackerHandler mTrackerHandler;
+ private final DnsManager mDnsManager;
private boolean mSystemReady;
private Intent mInitialBroadcast;
@@ -857,6 +861,8 @@
mMultinetworkPolicyTracker = createMultinetworkPolicyTracker(
mContext, mHandler, () -> rematchForAvoidBadWifiUpdate());
mMultinetworkPolicyTracker.start();
+
+ mDnsManager = new DnsManager(mContext, mNetd, mSystemProperties);
}
private Tethering makeTethering() {
@@ -972,9 +978,9 @@
}
private Network[] getVpnUnderlyingNetworks(int uid) {
- if (!mLockdownEnabled) {
- int user = UserHandle.getUserId(uid);
- synchronized (mVpns) {
+ synchronized (mVpns) {
+ if (!mLockdownEnabled) {
+ int user = UserHandle.getUserId(uid);
Vpn vpn = mVpns.get(user);
if (vpn != null && vpn.appliesToUid(uid)) {
return vpn.getUnderlyingNetworks();
@@ -1062,8 +1068,10 @@
if (isNetworkWithLinkPropertiesBlocked(state.linkProperties, uid, ignoreBlocked)) {
state.networkInfo.setDetailedState(DetailedState.BLOCKED, null, null);
}
- if (mLockdownTracker != null) {
- mLockdownTracker.augmentNetworkInfo(state.networkInfo);
+ synchronized (mVpns) {
+ if (mLockdownTracker != null) {
+ mLockdownTracker.augmentNetworkInfo(state.networkInfo);
+ }
}
}
@@ -1228,8 +1236,8 @@
result.put(nai.network, nc);
}
- if (!mLockdownEnabled) {
- synchronized (mVpns) {
+ synchronized (mVpns) {
+ if (!mLockdownEnabled) {
Vpn vpn = mVpns.get(userId);
if (vpn != null) {
Network[] networks = vpn.getUnderlyingNetworks();
@@ -1555,9 +1563,11 @@
}
private Intent makeGeneralIntent(NetworkInfo info, String bcastType) {
- if (mLockdownTracker != null) {
- info = new NetworkInfo(info);
- mLockdownTracker.augmentNetworkInfo(info);
+ synchronized (mVpns) {
+ if (mLockdownTracker != null) {
+ info = new NetworkInfo(info);
+ mLockdownTracker.augmentNetworkInfo(info);
+ }
}
Intent intent = new Intent(bcastType);
@@ -1803,24 +1813,6 @@
}
}
- private void flushVmDnsCache() {
- /*
- * Tell the VMs to toss their DNS caches
- */
- Intent intent = new Intent(Intent.ACTION_CLEAR_DNS_CACHE);
- intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
- /*
- * Connectivity events can happen before boot has completed ...
- */
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
- final long ident = Binder.clearCallingIdentity();
- try {
- mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- }
-
@Override
public int getRestoreDefaultNetworkDelay(int networkType) {
String restoreDefaultNetworkDelayStr = mSystemProperties.get(
@@ -2488,6 +2480,7 @@
private void handleRemoveNetworkRequest(final NetworkRequestInfo nri) {
nri.unlinkDeathRecipient();
mNetworkRequests.remove(nri.request);
+
synchronized (mUidToNetworkRequestCount) {
int requests = mUidToNetworkRequestCount.get(nri.mUid, 0);
if (requests < 1) {
@@ -2500,6 +2493,7 @@
mUidToNetworkRequestCount.put(nri.mUid, requests - 1);
}
}
+
mNetworkRequestInfoLogs.log("RELEASE " + nri);
if (nri.request.isRequest()) {
boolean wasKept = false;
@@ -3422,9 +3416,9 @@
public boolean prepareVpn(@Nullable String oldPackage, @Nullable String newPackage,
int userId) {
enforceCrossUserPermission(userId);
- throwIfLockdownEnabled();
synchronized (mVpns) {
+ throwIfLockdownEnabled();
Vpn vpn = mVpns.get(userId);
if (vpn != null) {
return vpn.prepare(oldPackage, newPackage);
@@ -3468,9 +3462,9 @@
*/
@Override
public ParcelFileDescriptor establishVpn(VpnConfig config) {
- throwIfLockdownEnabled();
int user = UserHandle.getUserId(Binder.getCallingUid());
synchronized (mVpns) {
+ throwIfLockdownEnabled();
return mVpns.get(user).establish(config);
}
}
@@ -3481,13 +3475,13 @@
*/
@Override
public void startLegacyVpn(VpnProfile profile) {
- throwIfLockdownEnabled();
+ int user = UserHandle.getUserId(Binder.getCallingUid());
final LinkProperties egress = getActiveLinkProperties();
if (egress == null) {
throw new IllegalStateException("Missing active network connection");
}
- int user = UserHandle.getUserId(Binder.getCallingUid());
synchronized (mVpns) {
+ throwIfLockdownEnabled();
mVpns.get(user).startLegacyVpn(profile, mKeyStore, egress);
}
}
@@ -3513,11 +3507,11 @@
@Override
public VpnInfo[] getAllVpnInfo() {
enforceConnectivityInternalPermission();
- if (mLockdownEnabled) {
- return new VpnInfo[0];
- }
-
synchronized (mVpns) {
+ if (mLockdownEnabled) {
+ return new VpnInfo[0];
+ }
+
List<VpnInfo> infoList = new ArrayList<>();
for (int i = 0; i < mVpns.size(); i++) {
VpnInfo info = createVpnInfo(mVpns.valueAt(i));
@@ -3582,33 +3576,33 @@
return false;
}
- // Tear down existing lockdown if profile was removed
- mLockdownEnabled = LockdownVpnTracker.isEnabled();
- if (mLockdownEnabled) {
- byte[] profileTag = mKeyStore.get(Credentials.LOCKDOWN_VPN);
- if (profileTag == null) {
- Slog.e(TAG, "Lockdown VPN configured but cannot be read from keystore");
- return false;
- }
- String profileName = new String(profileTag);
- final VpnProfile profile = VpnProfile.decode(
- profileName, mKeyStore.get(Credentials.VPN + profileName));
- if (profile == null) {
- Slog.e(TAG, "Lockdown VPN configured invalid profile " + profileName);
- setLockdownTracker(null);
- return true;
- }
- int user = UserHandle.getUserId(Binder.getCallingUid());
- synchronized (mVpns) {
+ synchronized (mVpns) {
+ // Tear down existing lockdown if profile was removed
+ mLockdownEnabled = LockdownVpnTracker.isEnabled();
+ if (mLockdownEnabled) {
+ byte[] profileTag = mKeyStore.get(Credentials.LOCKDOWN_VPN);
+ if (profileTag == null) {
+ Slog.e(TAG, "Lockdown VPN configured but cannot be read from keystore");
+ return false;
+ }
+ String profileName = new String(profileTag);
+ final VpnProfile profile = VpnProfile.decode(
+ profileName, mKeyStore.get(Credentials.VPN + profileName));
+ if (profile == null) {
+ Slog.e(TAG, "Lockdown VPN configured invalid profile " + profileName);
+ setLockdownTracker(null);
+ return true;
+ }
+ int user = UserHandle.getUserId(Binder.getCallingUid());
Vpn vpn = mVpns.get(user);
if (vpn == null) {
Slog.w(TAG, "VPN for user " + user + " not ready yet. Skipping lockdown");
return false;
}
setLockdownTracker(new LockdownVpnTracker(mContext, mNetd, this, vpn, profile));
+ } else {
+ setLockdownTracker(null);
}
- } else {
- setLockdownTracker(null);
}
return true;
@@ -3618,6 +3612,7 @@
* Internally set new {@link LockdownVpnTracker}, shutting down any existing
* {@link LockdownVpnTracker}. Can be {@code null} to disable lockdown.
*/
+ @GuardedBy("mVpns")
private void setLockdownTracker(LockdownVpnTracker tracker) {
// Shutdown any existing tracker
final LockdownVpnTracker existing = mLockdownTracker;
@@ -3632,6 +3627,7 @@
}
}
+ @GuardedBy("mVpns")
private void throwIfLockdownEnabled() {
if (mLockdownEnabled) {
throw new IllegalStateException("Unavailable in lockdown mode");
@@ -3679,12 +3675,12 @@
enforceConnectivityInternalPermission();
enforceCrossUserPermission(userId);
- // Can't set always-on VPN if legacy VPN is already in lockdown mode.
- if (LockdownVpnTracker.isEnabled()) {
- return false;
- }
-
synchronized (mVpns) {
+ // Can't set always-on VPN if legacy VPN is already in lockdown mode.
+ if (LockdownVpnTracker.isEnabled()) {
+ return false;
+ }
+
Vpn vpn = mVpns.get(userId);
if (vpn == null) {
Slog.w(TAG, "User " + userId + " has no Vpn configuration");
@@ -3860,9 +3856,9 @@
}
userVpn = new Vpn(mHandler.getLooper(), mContext, mNetd, userId);
mVpns.put(userId, userVpn);
- }
- if (mUserManager.getUserInfo(userId).isPrimary() && LockdownVpnTracker.isEnabled()) {
- updateLockdownVpn();
+ if (mUserManager.getUserInfo(userId).isPrimary() && LockdownVpnTracker.isEnabled()) {
+ updateLockdownVpn();
+ }
}
}
@@ -3899,11 +3895,13 @@
}
private void onUserUnlocked(int userId) {
- // User present may be sent because of an unlock, which might mean an unlocked keystore.
- if (mUserManager.getUserInfo(userId).isPrimary() && LockdownVpnTracker.isEnabled()) {
- updateLockdownVpn();
- } else {
- startAlwaysOnVpn(userId);
+ synchronized (mVpns) {
+ // User present may be sent because of an unlock, which might mean an unlocked keystore.
+ if (mUserManager.getUserInfo(userId).isPrimary() && LockdownVpnTracker.isEnabled()) {
+ updateLockdownVpn();
+ } else {
+ startAlwaysOnVpn(userId);
+ }
}
}
@@ -4558,41 +4556,17 @@
return; // no updating necessary
}
+ final NetworkAgentInfo defaultNai = getDefaultNetwork();
+ final boolean isDefaultNetwork = (defaultNai != null && defaultNai.network.netId == netId);
+
Collection<InetAddress> dnses = newLp.getDnsServers();
if (DBG) log("Setting DNS servers for network " + netId + " to " + dnses);
try {
- mNetd.setDnsConfigurationForNetwork(
- netId, NetworkUtils.makeStrings(dnses), newLp.getDomains());
+ mDnsManager.setDnsConfigurationForNetwork(
+ netId, dnses, newLp.getDomains(), isDefaultNetwork);
} catch (Exception e) {
loge("Exception in setDnsConfigurationForNetwork: " + e);
}
- final NetworkAgentInfo defaultNai = getDefaultNetwork();
- if (defaultNai != null && defaultNai.network.netId == netId) {
- setDefaultDnsSystemProperties(dnses);
- }
- flushVmDnsCache();
- }
-
- private void setDefaultDnsSystemProperties(Collection<InetAddress> dnses) {
- int last = 0;
- for (InetAddress dns : dnses) {
- ++last;
- setNetDnsProperty(last, dns.getHostAddress());
- }
- for (int i = last + 1; i <= mNumDnsEntries; ++i) {
- setNetDnsProperty(i, "");
- }
- mNumDnsEntries = last;
- }
-
- private void setNetDnsProperty(int which, String value) {
- final String key = "net.dns" + which;
- // Log and forget errors setting unsupported properties.
- try {
- mSystemProperties.set(key, value);
- } catch (Exception e) {
- Log.e(TAG, "Error setting unsupported net.dns property: ", e);
- }
}
private String getNetworkPermission(NetworkCapabilities nc) {
@@ -4607,51 +4581,67 @@
}
/**
- * Update the NetworkCapabilities for {@code networkAgent} to {@code networkCapabilities}
- * augmented with any stateful capabilities implied from {@code networkAgent}
- * (e.g., validated status and captive portal status).
- *
- * @param oldScore score of the network before any of the changes that prompted us
- * to call this function.
- * @param nai the network having its capabilities updated.
- * @param networkCapabilities the new network capabilities.
+ * Augments the NetworkCapabilities passed in by a NetworkAgent with capabilities that are
+ * maintained here that the NetworkAgent is not aware of (e.g., validated, captive portal,
+ * and foreground status).
*/
- private void updateCapabilities(
- int oldScore, NetworkAgentInfo nai, NetworkCapabilities networkCapabilities) {
+ private NetworkCapabilities mixInCapabilities(NetworkAgentInfo nai, NetworkCapabilities nc) {
// Once a NetworkAgent is connected, complain if some immutable capabilities are removed.
- if (nai.everConnected && !nai.networkCapabilities.satisfiedByImmutableNetworkCapabilities(
- networkCapabilities)) {
- // TODO: consider not complaining when a network agent degrade its capabilities if this
+ if (nai.everConnected &&
+ !nai.networkCapabilities.satisfiedByImmutableNetworkCapabilities(nc)) {
+ // TODO: consider not complaining when a network agent degrades its capabilities if this
// does not cause any request (that is not a listen) currently matching that agent to
// stop being matched by the updated agent.
- String diff = nai.networkCapabilities.describeImmutableDifferences(networkCapabilities);
+ String diff = nai.networkCapabilities.describeImmutableDifferences(nc);
if (!TextUtils.isEmpty(diff)) {
Slog.wtf(TAG, "BUG: " + nai + " lost immutable capabilities:" + diff);
}
}
// Don't modify caller's NetworkCapabilities.
- networkCapabilities = new NetworkCapabilities(networkCapabilities);
+ NetworkCapabilities newNc = new NetworkCapabilities(nc);
if (nai.lastValidated) {
- networkCapabilities.addCapability(NET_CAPABILITY_VALIDATED);
+ newNc.addCapability(NET_CAPABILITY_VALIDATED);
} else {
- networkCapabilities.removeCapability(NET_CAPABILITY_VALIDATED);
+ newNc.removeCapability(NET_CAPABILITY_VALIDATED);
}
if (nai.lastCaptivePortalDetected) {
- networkCapabilities.addCapability(NET_CAPABILITY_CAPTIVE_PORTAL);
+ newNc.addCapability(NET_CAPABILITY_CAPTIVE_PORTAL);
} else {
- networkCapabilities.removeCapability(NET_CAPABILITY_CAPTIVE_PORTAL);
+ newNc.removeCapability(NET_CAPABILITY_CAPTIVE_PORTAL);
}
if (nai.isBackgroundNetwork()) {
- networkCapabilities.removeCapability(NET_CAPABILITY_FOREGROUND);
+ newNc.removeCapability(NET_CAPABILITY_FOREGROUND);
} else {
- networkCapabilities.addCapability(NET_CAPABILITY_FOREGROUND);
+ newNc.addCapability(NET_CAPABILITY_FOREGROUND);
}
- if (Objects.equals(nai.networkCapabilities, networkCapabilities)) return;
+ return newNc;
+ }
+
+ /**
+ * Update the NetworkCapabilities for {@code nai} to {@code nc}. Specifically:
+ *
+ * 1. Calls mixInCapabilities to merge the passed-in NetworkCapabilities {@code nc} with the
+ * capabilities we manage and store in {@code nai}, such as validated status and captive
+ * portal status)
+ * 2. Takes action on the result: changes network permissions, sends CAP_CHANGED callbacks, and
+ * potentially triggers rematches.
+ * 3. Directly informs other network stack components (NetworkStatsService, VPNs, etc. of the
+ * change.)
+ *
+ * @param oldScore score of the network before any of the changes that prompted us
+ * to call this function.
+ * @param nai the network having its capabilities updated.
+ * @param nc the new network capabilities.
+ */
+ private void updateCapabilities(int oldScore, NetworkAgentInfo nai, NetworkCapabilities nc) {
+ NetworkCapabilities newNc = mixInCapabilities(nai, nc);
+
+ if (Objects.equals(nai.networkCapabilities, newNc)) return;
final String oldPermission = getNetworkPermission(nai.networkCapabilities);
- final String newPermission = getNetworkPermission(networkCapabilities);
+ final String newPermission = getNetworkPermission(newNc);
if (!Objects.equals(oldPermission, newPermission) && nai.created && !nai.isVPN()) {
try {
mNetd.setNetworkPermission(nai.network.netId, newPermission);
@@ -4663,11 +4653,10 @@
final NetworkCapabilities prevNc;
synchronized (nai) {
prevNc = nai.networkCapabilities;
- nai.networkCapabilities = networkCapabilities;
+ nai.networkCapabilities = newNc;
}
- if (nai.getCurrentScore() == oldScore &&
- networkCapabilities.equalRequestableCapabilities(prevNc)) {
+ if (nai.getCurrentScore() == oldScore && newNc.equalRequestableCapabilities(prevNc)) {
// If the requestable capabilities haven't changed, and the score hasn't changed, then
// the change we're processing can't affect any requests, it can only affect the listens
// on this network. We might have been called by rematchNetworkAndRequests when a
@@ -4683,15 +4672,15 @@
// Report changes that are interesting for network statistics tracking.
if (prevNc != null) {
final boolean meteredChanged = prevNc.hasCapability(NET_CAPABILITY_NOT_METERED) !=
- networkCapabilities.hasCapability(NET_CAPABILITY_NOT_METERED);
+ newNc.hasCapability(NET_CAPABILITY_NOT_METERED);
final boolean roamingChanged = prevNc.hasCapability(NET_CAPABILITY_NOT_ROAMING) !=
- networkCapabilities.hasCapability(NET_CAPABILITY_NOT_ROAMING);
+ newNc.hasCapability(NET_CAPABILITY_NOT_ROAMING);
if (meteredChanged || roamingChanged) {
notifyIfacesChangedForNetworkStats();
}
}
- if (!networkCapabilities.hasTransport(TRANSPORT_VPN)) {
+ if (!newNc.hasTransport(TRANSPORT_VPN)) {
// Tell VPNs about updated capabilities, since they may need to
// bubble those changes through.
synchronized (mVpns) {
@@ -4865,7 +4854,7 @@
notifyLockdownVpn(newNetwork);
handleApplyDefaultProxy(newNetwork.linkProperties.getHttpProxy());
updateTcpBufferSizes(newNetwork);
- setDefaultDnsSystemProperties(newNetwork.linkProperties.getDnsServers());
+ mDnsManager.setDefaultDnsSystemProperties(newNetwork.linkProperties.getDnsServers());
}
private void processListenRequests(NetworkAgentInfo nai, boolean capabilitiesChanged) {
@@ -5215,11 +5204,13 @@
}
private void notifyLockdownVpn(NetworkAgentInfo nai) {
- if (mLockdownTracker != null) {
- if (nai != null && nai.isVPN()) {
- mLockdownTracker.onVpnStateChanged(nai.networkInfo);
- } else {
- mLockdownTracker.onNetworkInfoChanged();
+ synchronized (mVpns) {
+ if (mLockdownTracker != null) {
+ if (nai != null && nai.isVPN()) {
+ mLockdownTracker.onVpnStateChanged(nai.networkInfo);
+ } else {
+ mLockdownTracker.onNetworkInfoChanged();
+ }
}
}
}
@@ -5449,28 +5440,28 @@
@Override
public boolean addVpnAddress(String address, int prefixLength) {
- throwIfLockdownEnabled();
int user = UserHandle.getUserId(Binder.getCallingUid());
synchronized (mVpns) {
+ throwIfLockdownEnabled();
return mVpns.get(user).addAddress(address, prefixLength);
}
}
@Override
public boolean removeVpnAddress(String address, int prefixLength) {
- throwIfLockdownEnabled();
int user = UserHandle.getUserId(Binder.getCallingUid());
synchronized (mVpns) {
+ throwIfLockdownEnabled();
return mVpns.get(user).removeAddress(address, prefixLength);
}
}
@Override
public boolean setUnderlyingNetworksForVpn(Network[] networks) {
- throwIfLockdownEnabled();
int user = UserHandle.getUserId(Binder.getCallingUid());
- boolean success;
+ final boolean success;
synchronized (mVpns) {
+ throwIfLockdownEnabled();
success = mVpns.get(user).setUnderlyingNetworks(networks);
}
if (success) {
@@ -5530,31 +5521,31 @@
setAlwaysOnVpnPackage(userId, null, false);
setVpnPackageAuthorization(alwaysOnPackage, userId, false);
}
- }
- // Turn Always-on VPN off
- if (mLockdownEnabled && userId == UserHandle.USER_SYSTEM) {
- final long ident = Binder.clearCallingIdentity();
- try {
- mKeyStore.delete(Credentials.LOCKDOWN_VPN);
- mLockdownEnabled = false;
- setLockdownTracker(null);
- } finally {
- Binder.restoreCallingIdentity(ident);
+ // Turn Always-on VPN off
+ if (mLockdownEnabled && userId == UserHandle.USER_SYSTEM) {
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ mKeyStore.delete(Credentials.LOCKDOWN_VPN);
+ mLockdownEnabled = false;
+ setLockdownTracker(null);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
}
- }
- // Turn VPN off
- VpnConfig vpnConfig = getVpnConfig(userId);
- if (vpnConfig != null) {
- if (vpnConfig.legacy) {
- prepareVpn(VpnConfig.LEGACY_VPN, VpnConfig.LEGACY_VPN, userId);
- } else {
- // Prevent this app (packagename = vpnConfig.user) from initiating VPN connections
- // in the future without user intervention.
- setVpnPackageAuthorization(vpnConfig.user, userId, false);
+ // Turn VPN off
+ VpnConfig vpnConfig = getVpnConfig(userId);
+ if (vpnConfig != null) {
+ if (vpnConfig.legacy) {
+ prepareVpn(VpnConfig.LEGACY_VPN, VpnConfig.LEGACY_VPN, userId);
+ } else {
+ // Prevent this app (packagename = vpnConfig.user) from initiating
+ // VPN connections in the future without user intervention.
+ setVpnPackageAuthorization(vpnConfig.user, userId, false);
- prepareVpn(null, VpnConfig.LEGACY_VPN, userId);
+ prepareVpn(null, VpnConfig.LEGACY_VPN, userId);
+ }
}
}
}
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index 8a15ded..8f646e7 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -18,6 +18,7 @@
import static android.Manifest.permission.CONNECTIVITY_INTERNAL;
import static android.Manifest.permission.DUMP;
+import static android.Manifest.permission.NETWORK_SETTINGS;
import static android.Manifest.permission.NETWORK_STACK;
import static android.Manifest.permission.SHUTDOWN;
import static android.net.ConnectivityManager.PRIVATE_DNS_DEFAULT_MODE;
@@ -209,12 +210,6 @@
public static final int StrictCleartext = 617;
}
- /* Defaults for resolver parameters. */
- public static final int DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS = 1800;
- public static final int DNS_RESOLVER_DEFAULT_SUCCESS_THRESHOLD_PERCENT = 25;
- public static final int DNS_RESOLVER_DEFAULT_MIN_SAMPLES = 8;
- public static final int DNS_RESOLVER_DEFAULT_MAX_SAMPLES = 64;
-
/**
* String indicating a softap command.
*/
@@ -1768,6 +1763,8 @@
@Override
public boolean setDataSaverModeEnabled(boolean enable) {
+ mContext.enforceCallingOrSelfPermission(NETWORK_SETTINGS, TAG);
+
if (DBG) Log.d(TAG, "setDataSaverMode: " + enable);
synchronized (mQuotaLock) {
if (mDataSaverMode == enable) {
@@ -1947,66 +1944,14 @@
}
@Override
- public void setDnsConfigurationForNetwork(int netId, String[] servers, String domains) {
+ public void setDnsConfigurationForNetwork(int netId, String[] servers, String[] domains,
+ int[] params, boolean useTls, String tlsHostname) {
mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
- final ContentResolver cr = mContext.getContentResolver();
-
- int sampleValidity = Settings.Global.getInt(cr,
- Settings.Global.DNS_RESOLVER_SAMPLE_VALIDITY_SECONDS,
- DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS);
- if (sampleValidity < 0 || sampleValidity > 65535) {
- Slog.w(TAG, "Invalid sampleValidity=" + sampleValidity + ", using default=" +
- DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS);
- sampleValidity = DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS;
- }
-
- int successThreshold = Settings.Global.getInt(cr,
- Settings.Global.DNS_RESOLVER_SUCCESS_THRESHOLD_PERCENT,
- DNS_RESOLVER_DEFAULT_SUCCESS_THRESHOLD_PERCENT);
- if (successThreshold < 0 || successThreshold > 100) {
- Slog.w(TAG, "Invalid successThreshold=" + successThreshold + ", using default=" +
- DNS_RESOLVER_DEFAULT_SUCCESS_THRESHOLD_PERCENT);
- successThreshold = DNS_RESOLVER_DEFAULT_SUCCESS_THRESHOLD_PERCENT;
- }
-
- int minSamples = Settings.Global.getInt(cr,
- Settings.Global.DNS_RESOLVER_MIN_SAMPLES, DNS_RESOLVER_DEFAULT_MIN_SAMPLES);
- int maxSamples = Settings.Global.getInt(cr,
- Settings.Global.DNS_RESOLVER_MAX_SAMPLES, DNS_RESOLVER_DEFAULT_MAX_SAMPLES);
- if (minSamples < 0 || minSamples > maxSamples || maxSamples > 64) {
- Slog.w(TAG, "Invalid sample count (min, max)=(" + minSamples + ", " + maxSamples +
- "), using default=(" + DNS_RESOLVER_DEFAULT_MIN_SAMPLES + ", " +
- DNS_RESOLVER_DEFAULT_MAX_SAMPLES + ")");
- minSamples = DNS_RESOLVER_DEFAULT_MIN_SAMPLES;
- maxSamples = DNS_RESOLVER_DEFAULT_MAX_SAMPLES;
- }
-
- final String[] domainStrs = domains == null ? new String[0] : domains.split(" ");
- final int[] params = { sampleValidity, successThreshold, minSamples, maxSamples };
- final boolean useTls = shouldUseTls(cr);
- // TODO: Populate tlsHostname once it's decided how the hostname's IP
- // addresses will be resolved:
- //
- // [1] network-provided DNS servers are included here with the
- // hostname and netd will use the network-provided servers to
- // resolve the hostname and fix up its internal structures, or
- //
- // [2] network-provided DNS servers are included here without the
- // hostname, the ConnectivityService layer resolves the given
- // hostname, and then reconfigures netd with this information.
- //
- // In practice, there will always be a need for ConnectivityService or
- // the captive portal app to use the network-provided services to make
- // some queries. This argues in favor of [1], in concert with another
- // mechanism, perhaps setting a high bit in the netid, to indicate
- // via existing DNS APIs which set of servers (network-provided or
- // non-network-provided private DNS) should be queried.
- final String tlsHostname = "";
final String[] tlsFingerprints = new String[0];
try {
- mNetdService.setResolverConfiguration(netId, servers, domainStrs, params,
- useTls, tlsHostname, tlsFingerprints);
+ mNetdService.setResolverConfiguration(
+ netId, servers, domains, params, useTls, tlsHostname, tlsFingerprints);
} catch (RemoteException e) {
throw new RuntimeException(e);
}
@@ -2563,12 +2508,16 @@
@Override
public void removeNetwork(int netId) {
- mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
+ mContext.enforceCallingOrSelfPermission(NETWORK_STACK, TAG);
try {
- mConnector.execute("network", "destroy", netId);
- } catch (NativeDaemonConnectorException e) {
- throw e.rethrowAsParcelableException();
+ mNetdService.networkDestroy(netId);
+ } catch (ServiceSpecificException e) {
+ Log.w(TAG, "removeNetwork(" + netId + "): ", e);
+ throw e;
+ } catch (RemoteException e) {
+ Log.w(TAG, "removeNetwork(" + netId + "): ", e);
+ throw e.rethrowAsRuntimeException();
}
}
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 831c9cb..6747be3 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -147,6 +147,8 @@
private int[] mDataActivationState;
+ private boolean[] mUserMobileDataState;
+
private SignalStrength[] mSignalStrength;
private boolean[] mMessageWaiting;
@@ -304,6 +306,7 @@
mServiceState = new ServiceState[numPhones];
mVoiceActivationState = new int[numPhones];
mDataActivationState = new int[numPhones];
+ mUserMobileDataState = new boolean[numPhones];
mSignalStrength = new SignalStrength[numPhones];
mMessageWaiting = new boolean[numPhones];
mCallForwarding = new boolean[numPhones];
@@ -320,6 +323,7 @@
mCallIncomingNumber[i] = "";
mServiceState[i] = new ServiceState();
mSignalStrength[i] = new SignalStrength();
+ mUserMobileDataState[i] = false;
mMessageWaiting[i] = false;
mCallForwarding[i] = false;
mCellLocation[i] = new Bundle();
@@ -656,6 +660,13 @@
remove(r.binder);
}
}
+ if ((events & PhoneStateListener.LISTEN_USER_MOBILE_DATA_STATE) != 0) {
+ try {
+ r.callback.onUserMobileDataStateChanged(mUserMobileDataState[phoneId]);
+ } catch (RemoteException ex) {
+ remove(r.binder);
+ }
+ }
}
}
} else {
@@ -1012,6 +1023,33 @@
}
}
+ public void notifyUserMobileDataStateChangedForPhoneId(int phoneId, int subId, boolean state) {
+ if (!checkNotifyPermission("notifyUserMobileDataStateChanged()")) {
+ return;
+ }
+ if (VDBG) {
+ log("notifyUserMobileDataStateChangedForSubscriberPhoneID: subId=" + phoneId
+ + " state=" + state);
+ }
+ synchronized (mRecords) {
+ if (validatePhoneId(phoneId)) {
+ mMessageWaiting[phoneId] = state;
+ for (Record r : mRecords) {
+ if (r.matchPhoneStateListenerEvent(
+ PhoneStateListener.LISTEN_USER_MOBILE_DATA_STATE) &&
+ idMatch(r.subId, subId, phoneId)) {
+ try {
+ r.callback.onUserMobileDataStateChanged(state);
+ } catch (RemoteException ex) {
+ mRemoveList.add(r.binder);
+ }
+ }
+ }
+ }
+ handleRemoveListLocked();
+ }
+ }
+
public void notifyCallForwardingChanged(boolean cfi) {
notifyCallForwardingChangedForSubscriber(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, cfi);
}
@@ -1374,6 +1412,7 @@
pw.println("mServiceState=" + mServiceState[i]);
pw.println("mVoiceActivationState= " + mVoiceActivationState[i]);
pw.println("mDataActivationState= " + mDataActivationState[i]);
+ pw.println("mUserMobileDataState= " + mUserMobileDataState[i]);
pw.println("mSignalStrength=" + mSignalStrength[i]);
pw.println("mMessageWaiting=" + mMessageWaiting[i]);
pw.println("mCallForwarding=" + mCallForwarding[i]);
@@ -1755,6 +1794,18 @@
}
}
+ if ((events & PhoneStateListener.LISTEN_USER_MOBILE_DATA_STATE) != 0) {
+ try {
+ if (VDBG) {
+ log("checkPossibleMissNotify: onUserMobileDataStateChanged phoneId="
+ + phoneId + " umds=" + mUserMobileDataState[phoneId]);
+ }
+ r.callback.onUserMobileDataStateChanged(mUserMobileDataState[phoneId]);
+ } catch (RemoteException ex) {
+ mRemoveList.add(r.binder);
+ }
+ }
+
if ((events & PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR) != 0) {
try {
if (VDBG) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index dce0c38..002381a 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -200,6 +200,7 @@
import android.app.ActivityManager.TaskSnapshot;
import android.app.ActivityManager.TaskThumbnailInfo;
import android.app.ActivityManagerInternal;
+import android.app.ActivityManagerInternal.ScreenObserver;
import android.app.ActivityManagerInternal.SleepToken;
import android.app.ActivityOptions;
import android.app.ActivityThread;
@@ -1548,6 +1549,8 @@
}
}
+ final List<ScreenObserver> mScreenObservers = new ArrayList<>();
+
final RemoteCallbackList<IProcessObserver> mProcessObservers = new RemoteCallbackList<>();
ProcessChangeItem[] mActiveProcessChanges = new ProcessChangeItem[5];
@@ -1689,6 +1692,8 @@
static final int PUSH_TEMP_WHITELIST_UI_MSG = 68;
static final int SERVICE_FOREGROUND_CRASH_MSG = 69;
static final int DISPATCH_OOM_ADJ_OBSERVER_MSG = 70;
+ static final int DISPATCH_SCREEN_AWAKE_MSG = 71;
+ static final int DISPATCH_SCREEN_KEYGUARD_MSG = 72;
static final int START_USER_SWITCH_FG_MSG = 712;
static final int NOTIFY_VR_KEYGUARD_MSG = 74;
@@ -2412,11 +2417,17 @@
}
}
} break;
- case NOTIFY_VR_SLEEPING_MSG: {
- notifyVrManagerOfSleepState(msg.arg1 != 0);
+ case DISPATCH_SCREEN_AWAKE_MSG: {
+ final boolean isAwake = msg.arg1 != 0;
+ for (int i = mScreenObservers.size() - 1; i >= 0; i--) {
+ mScreenObservers.get(i).onAwakeStateChanged(isAwake);
+ }
} break;
- case NOTIFY_VR_KEYGUARD_MSG: {
- notifyVrManagerOfKeyguardState(msg.arg1 != 0);
+ case DISPATCH_SCREEN_KEYGUARD_MSG: {
+ final boolean isShowing = msg.arg1 != 0;
+ for (int i = mScreenObservers.size() - 1; i >= 0; i--) {
+ mScreenObservers.get(i).onKeyguardStateChanged(isShowing);
+ }
} break;
case HANDLE_TRUST_STORAGE_UPDATE_MSG: {
synchronized (ActivityManagerService.this) {
@@ -3260,32 +3271,6 @@
mHandler.obtainMessage(VR_MODE_CHANGE_MSG, 0, 0, r));
}
- private void sendNotifyVrManagerOfSleepState(boolean isSleeping) {
- mHandler.sendMessage(
- mHandler.obtainMessage(NOTIFY_VR_SLEEPING_MSG, isSleeping ? 1 : 0, 0));
- }
-
- private void notifyVrManagerOfSleepState(boolean isSleeping) {
- final VrManagerInternal vrService = LocalServices.getService(VrManagerInternal.class);
- if (vrService == null) {
- return;
- }
- vrService.onSleepStateChanged(isSleeping);
- }
-
- private void sendNotifyVrManagerOfKeyguardState(boolean isShowing) {
- mHandler.sendMessage(
- mHandler.obtainMessage(NOTIFY_VR_KEYGUARD_MSG, isShowing ? 1 : 0, 0));
- }
-
- private void notifyVrManagerOfKeyguardState(boolean isShowing) {
- final VrManagerInternal vrService = LocalServices.getService(VrManagerInternal.class);
- if (vrService == null) {
- return;
- }
- vrService.onKeyguardStateChanged(isShowing);
- }
-
final void showAskCompatModeDialogLocked(ActivityRecord r) {
Message msg = Message.obtain();
msg.what = SHOW_COMPAT_MODE_DIALOG_UI_MSG;
@@ -7027,15 +7012,22 @@
}
ProfilerInfo profilerInfo = null;
- String agent = null;
+ String preBindAgent = null;
if (mProfileApp != null && mProfileApp.equals(processName)) {
mProfileProc = app;
- profilerInfo = (mProfilerInfo != null && mProfilerInfo.profileFile != null) ?
- new ProfilerInfo(mProfilerInfo) : null;
- agent = mProfilerInfo != null ? mProfilerInfo.agent : null;
+ if (mProfilerInfo != null) {
+ // Send a profiler info object to the app if either a file is given, or
+ // an agent should be loaded at bind-time.
+ boolean needsInfo = mProfilerInfo.profileFile != null
+ || mProfilerInfo.attachAgentDuringBind;
+ profilerInfo = needsInfo ? new ProfilerInfo(mProfilerInfo) : null;
+ if (!mProfilerInfo.attachAgentDuringBind) {
+ preBindAgent = mProfilerInfo.agent;
+ }
+ }
} else if (app.instr != null && app.instr.mProfileFile != null) {
profilerInfo = new ProfilerInfo(app.instr.mProfileFile, null, 0, false, false,
- null);
+ null, false);
}
boolean enableTrackAllocation = false;
@@ -7102,8 +7094,8 @@
// If we were asked to attach an agent on startup, do so now, before we're binding
// application code.
- if (agent != null) {
- thread.attachAgent(agent);
+ if (preBindAgent != null) {
+ thread.attachAgent(preBindAgent);
}
checkTime(startTime, "attachApplicationLocked: immediately before bindApplication");
@@ -12497,7 +12489,8 @@
if (wasAwake != isAwake) {
// Also update state in a special way for running foreground services UI.
mServices.updateScreenStateLocked(isAwake);
- sendNotifyVrManagerOfSleepState(!isAwake);
+ mHandler.obtainMessage(DISPATCH_SCREEN_AWAKE_MSG, isAwake ? 1 : 0, 0)
+ .sendToTarget();
}
}
}
@@ -12650,7 +12643,9 @@
Binder.restoreCallingIdentity(ident);
}
}
- sendNotifyVrManagerOfKeyguardState(showing);
+
+ mHandler.obtainMessage(DISPATCH_SCREEN_KEYGUARD_MSG, showing ? 1 : 0, 0)
+ .sendToTarget();
}
@Override
@@ -24258,6 +24253,11 @@
}
}
}
+
+ @Override
+ public void registerScreenObserver(ScreenObserver observer) {
+ mScreenObservers.add(observer);
+ }
}
/**
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index 8488e52..a7ace21 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -114,6 +114,7 @@
private boolean mAutoStop;
private boolean mStreaming; // Streaming the profiling output to a file.
private String mAgent; // Agent to attach on startup.
+ private boolean mAttachAgentDuringBind; // Whether agent should be attached late.
private int mDisplayId;
private int mStackId;
private int mTaskId;
@@ -295,7 +296,21 @@
} else if (opt.equals("--streaming")) {
mStreaming = true;
} else if (opt.equals("--attach-agent")) {
+ if (mAgent != null) {
+ cmd.getErrPrintWriter().println(
+ "Multiple --attach-agent(-bind) not supported");
+ return false;
+ }
mAgent = getNextArgRequired();
+ mAttachAgentDuringBind = false;
+ } else if (opt.equals("--attach-agent-bind")) {
+ if (mAgent != null) {
+ cmd.getErrPrintWriter().println(
+ "Multiple --attach-agent(-bind) not supported");
+ return false;
+ }
+ mAgent = getNextArgRequired();
+ mAttachAgentDuringBind = true;
} else if (opt.equals("-R")) {
mRepeat = Integer.parseInt(getNextArgRequired());
} else if (opt.equals("-S")) {
@@ -381,7 +396,7 @@
}
}
profilerInfo = new ProfilerInfo(mProfileFile, fd, mSamplingInterval, mAutoStop,
- mStreaming, mAgent);
+ mStreaming, mAgent, mAttachAgentDuringBind);
}
pw.println("Starting: " + intent);
@@ -755,7 +770,7 @@
return -1;
}
profilerInfo = new ProfilerInfo(profileFile, fd, mSamplingInterval, false, mStreaming,
- null);
+ null, false);
}
try {
@@ -2679,6 +2694,7 @@
pw.println(" (use with --start-profiler)");
pw.println(" -P <FILE>: like above, but profiling stops when app goes idle");
pw.println(" --attach-agent <agent>: attach the given agent before binding");
+ pw.println(" --attach-agent-bind <agent>: attach the given agent during binding");
pw.println(" -R: repeat the activity launch <COUNT> times. Prior to each repeat,");
pw.println(" the top activity will be finished.");
pw.println(" -S: force stop the target app before starting the activity");
diff --git a/services/core/java/com/android/server/connectivity/DnsManager.java b/services/core/java/com/android/server/connectivity/DnsManager.java
new file mode 100644
index 0000000..a4170ce
--- /dev/null
+++ b/services/core/java/com/android/server/connectivity/DnsManager.java
@@ -0,0 +1,226 @@
+/*
+ * Copyright (C) 2018 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.server.connectivity;
+
+import static android.net.ConnectivityManager.PRIVATE_DNS_DEFAULT_MODE;
+import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OPPORTUNISTIC;
+import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME;
+import static android.provider.Settings.Global.DNS_RESOLVER_MIN_SAMPLES;
+import static android.provider.Settings.Global.DNS_RESOLVER_MAX_SAMPLES;
+import static android.provider.Settings.Global.DNS_RESOLVER_SAMPLE_VALIDITY_SECONDS;
+import static android.provider.Settings.Global.DNS_RESOLVER_SUCCESS_THRESHOLD_PERCENT;
+import static android.provider.Settings.Global.PRIVATE_DNS_MODE;
+import static android.provider.Settings.Global.PRIVATE_DNS_SPECIFIER;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.net.NetworkUtils;
+import android.os.Binder;
+import android.os.INetworkManagementService;
+import android.os.Handler;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.util.Slog;
+
+import com.android.server.connectivity.MockableSystemProperties;
+
+import java.net.InetAddress;
+import java.util.Collection;
+
+
+/**
+ * Encapsulate the management of DNS settings for networks.
+ *
+ * This class it NOT designed for concurrent access. Furthermore, all non-static
+ * methods MUST be called from ConnectivityService's thread.
+ *
+ * @hide
+ */
+public class DnsManager {
+ private static final String TAG = DnsManager.class.getSimpleName();
+
+ /* Defaults for resolver parameters. */
+ private static final int DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS = 1800;
+ private static final int DNS_RESOLVER_DEFAULT_SUCCESS_THRESHOLD_PERCENT = 25;
+ private static final int DNS_RESOLVER_DEFAULT_MIN_SAMPLES = 8;
+ private static final int DNS_RESOLVER_DEFAULT_MAX_SAMPLES = 64;
+
+ private final Context mContext;
+ private final ContentResolver mContentResolver;
+ private final INetworkManagementService mNMS;
+ private final MockableSystemProperties mSystemProperties;
+
+ private int mNumDnsEntries;
+ private int mSampleValidity;
+ private int mSuccessThreshold;
+ private int mMinSamples;
+ private int mMaxSamples;
+ private String mPrivateDnsMode;
+ private String mPrivateDnsSpecifier;
+
+ public DnsManager(Context ctx, INetworkManagementService nms, MockableSystemProperties sp) {
+ mContext = ctx;
+ mContentResolver = mContext.getContentResolver();
+ mNMS = nms;
+ mSystemProperties = sp;
+
+ // TODO: Create and register ContentObservers to track every setting
+ // used herein, posting messages to respond to changes.
+ }
+
+ public boolean isPrivateDnsInStrictMode() {
+ return !TextUtils.isEmpty(mPrivateDnsMode) &&
+ mPrivateDnsMode.startsWith(PRIVATE_DNS_MODE_PROVIDER_HOSTNAME) &&
+ !TextUtils.isEmpty(mPrivateDnsSpecifier);
+ }
+
+ public void setDnsConfigurationForNetwork(
+ int netId, Collection<InetAddress> servers, String domains, boolean isDefaultNetwork) {
+ updateParametersSettings();
+ updatePrivateDnsSettings();
+
+ final String[] serverStrs = NetworkUtils.makeStrings(servers);
+ final String[] domainStrs = (domains == null) ? new String[0] : domains.split(" ");
+ final int[] params = { mSampleValidity, mSuccessThreshold, mMinSamples, mMaxSamples };
+ final boolean useTls = shouldUseTls(mPrivateDnsMode);
+ // TODO: Populate tlsHostname once it's decided how the hostname's IP
+ // addresses will be resolved:
+ //
+ // [1] network-provided DNS servers are included here with the
+ // hostname and netd will use the network-provided servers to
+ // resolve the hostname and fix up its internal structures, or
+ //
+ // [2] network-provided DNS servers are included here without the
+ // hostname, the ConnectivityService layer resolves the given
+ // hostname, and then reconfigures netd with this information.
+ //
+ // In practice, there will always be a need for ConnectivityService or
+ // the captive portal app to use the network-provided services to make
+ // some queries. This argues in favor of [1], in concert with another
+ // mechanism, perhaps setting a high bit in the netid, to indicate
+ // via existing DNS APIs which set of servers (network-provided or
+ // non-network-provided private DNS) should be queried.
+ final String tlsHostname = "";
+ try {
+ mNMS.setDnsConfigurationForNetwork(
+ netId, serverStrs, domainStrs, params, useTls, tlsHostname);
+ } catch (Exception e) {
+ Slog.e(TAG, "Error setting DNS configuration: " + e);
+ return;
+ }
+
+ // TODO: netd should listen on [::1]:53 and proxy queries to the current
+ // default network, and we should just set net.dns1 to ::1, not least
+ // because applications attempting to use net.dns resolvers will bypass
+ // the privacy protections of things like DNS-over-TLS.
+ if (isDefaultNetwork) setDefaultDnsSystemProperties(servers);
+ flushVmDnsCache();
+ }
+
+ public void setDefaultDnsSystemProperties(Collection<InetAddress> dnses) {
+ int last = 0;
+ for (InetAddress dns : dnses) {
+ ++last;
+ setNetDnsProperty(last, dns.getHostAddress());
+ }
+ for (int i = last + 1; i <= mNumDnsEntries; ++i) {
+ setNetDnsProperty(i, "");
+ }
+ mNumDnsEntries = last;
+ }
+
+ private void flushVmDnsCache() {
+ /*
+ * Tell the VMs to toss their DNS caches
+ */
+ final Intent intent = new Intent(Intent.ACTION_CLEAR_DNS_CACHE);
+ intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
+ /*
+ * Connectivity events can happen before boot has completed ...
+ */
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ private void updatePrivateDnsSettings() {
+ mPrivateDnsMode = getStringSetting(PRIVATE_DNS_MODE);
+ mPrivateDnsSpecifier = getStringSetting(PRIVATE_DNS_SPECIFIER);
+ }
+
+ private void updateParametersSettings() {
+ mSampleValidity = getIntSetting(
+ DNS_RESOLVER_SAMPLE_VALIDITY_SECONDS,
+ DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS);
+ if (mSampleValidity < 0 || mSampleValidity > 65535) {
+ Slog.w(TAG, "Invalid sampleValidity=" + mSampleValidity + ", using default=" +
+ DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS);
+ mSampleValidity = DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS;
+ }
+
+ mSuccessThreshold = getIntSetting(
+ DNS_RESOLVER_SUCCESS_THRESHOLD_PERCENT,
+ DNS_RESOLVER_DEFAULT_SUCCESS_THRESHOLD_PERCENT);
+ if (mSuccessThreshold < 0 || mSuccessThreshold > 100) {
+ Slog.w(TAG, "Invalid successThreshold=" + mSuccessThreshold + ", using default=" +
+ DNS_RESOLVER_DEFAULT_SUCCESS_THRESHOLD_PERCENT);
+ mSuccessThreshold = DNS_RESOLVER_DEFAULT_SUCCESS_THRESHOLD_PERCENT;
+ }
+
+ mMinSamples = getIntSetting(DNS_RESOLVER_MIN_SAMPLES, DNS_RESOLVER_DEFAULT_MIN_SAMPLES);
+ mMaxSamples = getIntSetting(DNS_RESOLVER_MAX_SAMPLES, DNS_RESOLVER_DEFAULT_MAX_SAMPLES);
+ if (mMinSamples < 0 || mMinSamples > mMaxSamples || mMaxSamples > 64) {
+ Slog.w(TAG, "Invalid sample count (min, max)=(" + mMinSamples + ", " + mMaxSamples +
+ "), using default=(" + DNS_RESOLVER_DEFAULT_MIN_SAMPLES + ", " +
+ DNS_RESOLVER_DEFAULT_MAX_SAMPLES + ")");
+ mMinSamples = DNS_RESOLVER_DEFAULT_MIN_SAMPLES;
+ mMaxSamples = DNS_RESOLVER_DEFAULT_MAX_SAMPLES;
+ }
+ }
+
+ private String getStringSetting(String which) {
+ return Settings.Global.getString(mContentResolver, which);
+ }
+
+ private int getIntSetting(String which, int dflt) {
+ return Settings.Global.getInt(mContentResolver, which, dflt);
+ }
+
+ private void setNetDnsProperty(int which, String value) {
+ final String key = "net.dns" + which;
+ // Log and forget errors setting unsupported properties.
+ try {
+ mSystemProperties.set(key, value);
+ } catch (Exception e) {
+ Slog.e(TAG, "Error setting unsupported net.dns property: ", e);
+ }
+ }
+
+ private static boolean shouldUseTls(String mode) {
+ if (TextUtils.isEmpty(mode)) {
+ mode = PRIVATE_DNS_DEFAULT_MODE;
+ }
+ return mode.equals(PRIVATE_DNS_MODE_OPPORTUNISTIC) ||
+ mode.startsWith(PRIVATE_DNS_MODE_PROVIDER_HOSTNAME);
+ }
+}
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index d1bab89..7b171b3 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -19,7 +19,6 @@
import static android.hardware.usb.UsbManager.USB_CONFIGURED;
import static android.hardware.usb.UsbManager.USB_CONNECTED;
import static android.hardware.usb.UsbManager.USB_FUNCTION_RNDIS;
-import static android.net.ConnectivityManager.getNetworkTypeName;
import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_INTERFACE_NAME;
import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_MODE;
import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_STATE;
@@ -43,7 +42,6 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.hardware.usb.UsbManager;
import android.net.ConnectivityManager;
@@ -53,9 +51,7 @@
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.Network;
-import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
-import android.net.NetworkRequest;
import android.net.NetworkState;
import android.net.NetworkUtils;
import android.net.RouteInfo;
@@ -76,7 +72,6 @@
import android.os.UserHandle;
import android.provider.Settings;
import android.telephony.CarrierConfigManager;
-import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.Log;
@@ -85,8 +80,6 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.internal.notification.SystemNotificationChannels;
-import com.android.internal.telephony.IccCardConstants;
-import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.MessageUtils;
@@ -110,12 +103,8 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
-import java.util.HashMap;
import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Map;
import java.util.Set;
-import java.util.concurrent.atomic.AtomicInteger;
/**
@@ -193,8 +182,6 @@
private int mLastNotificationId;
private boolean mRndisEnabled; // track the RNDIS function enabled state
- private boolean mUsbTetherRequested; // true if USB tethering should be started
- // when RNDIS is enabled
// True iff. WiFi tethering should be started when soft AP is ready.
private boolean mWifiTetherRequested;
@@ -867,33 +854,18 @@
//
// For more explanation, see b/62552150 .
synchronized (Tethering.this.mPublicSync) {
- // Always record the state of RNDIS.
- // TODO: consider:
- // final boolean disconnected = !usbConnected;
- // if (disconnected) {
- // mRndisEnabled = false;
- // mUsbTetherRequested = false;
- // return;
- // }
- // final boolean configured = usbConnected && usbConfigured;
- // mRndisEnabled = configured ? rndisEnabled : false;
- // if (!configured) return;
- mRndisEnabled = rndisEnabled;
-
- if (usbConnected && !usbConfigured) {
- // Nothing to do here (only CONNECTED, not yet CONFIGURED).
- return;
- }
-
- // start tethering if we have a request pending
- if (usbConfigured && mRndisEnabled && mUsbTetherRequested) {
+ if (!usbConnected && mRndisEnabled) {
+ // Turn off tethering if it was enabled and there is a disconnect.
+ tetherMatchingInterfaces(
+ IControlsTethering.STATE_AVAILABLE,
+ ConnectivityManager.TETHERING_USB);
+ } else if (usbConfigured && rndisEnabled) {
+ // Tether if rndis is enabled and usb is configured.
tetherMatchingInterfaces(
IControlsTethering.STATE_TETHERED,
ConnectivityManager.TETHERING_USB);
}
-
- // TODO: Figure out how to remove the need for this variable.
- mUsbTetherRequested = false;
+ mRndisEnabled = usbConfigured && rndisEnabled;
}
}
@@ -1065,34 +1037,8 @@
public int setUsbTethering(boolean enable) {
if (VDBG) Log.d(TAG, "setUsbTethering(" + enable + ")");
UsbManager usbManager = (UsbManager) mContext.getSystemService(Context.USB_SERVICE);
-
synchronized (mPublicSync) {
- if (enable) {
- if (mRndisEnabled) {
- final long ident = Binder.clearCallingIdentity();
- try {
- tetherMatchingInterfaces(IControlsTethering.STATE_TETHERED,
- ConnectivityManager.TETHERING_USB);
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- } else {
- mUsbTetherRequested = true;
- usbManager.setCurrentFunction(UsbManager.USB_FUNCTION_RNDIS, false);
- }
- } else {
- final long ident = Binder.clearCallingIdentity();
- try {
- tetherMatchingInterfaces(IControlsTethering.STATE_AVAILABLE,
- ConnectivityManager.TETHERING_USB);
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- if (mRndisEnabled) {
- usbManager.setCurrentFunction(null, false);
- }
- mUsbTetherRequested = false;
- }
+ usbManager.setCurrentFunction(enable ? UsbManager.USB_FUNCTION_RNDIS : null, false);
}
return ConnectivityManager.TETHER_ERROR_NO_ERROR;
}
@@ -1149,7 +1095,7 @@
if (!mForwardedDownstreams.isEmpty()) return true;
synchronized (mPublicSync) {
- return mUsbTetherRequested || mWifiTetherRequested;
+ return mWifiTetherRequested;
}
}
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index c7a4315..3c2d724 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -128,7 +128,7 @@
// Length of time (in milliseconds) that an app hosting an always-on VPN is placed on
// the device idle whitelist during service launch and VPN bootstrap.
- private static final long VPN_LAUNCH_IDLE_WHITELIST_DURATION = 60 * 1000;
+ private static final long VPN_LAUNCH_IDLE_WHITELIST_DURATION_MS = 60 * 1000;
// TODO: create separate trackers for each unique VPN to support
// automated reconnection
@@ -183,10 +183,10 @@
@GuardedBy("this")
private Set<UidRange> mBlockedUsers = new ArraySet<>();
- // Handle of user initiating VPN.
+ // Handle of the user initiating VPN.
private final int mUserHandle;
- // Listen to package remove and change event in this user
+ // Listen to package removal and change events (update/uninstall) for this user
private final BroadcastReceiver mPackageIntentReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@@ -197,14 +197,14 @@
}
synchronized (Vpn.this) {
- // Avoid race that always-on package has been unset
+ // Avoid race where always-on package has been unset
if (!packageName.equals(getAlwaysOnPackage())) {
return;
}
final String action = intent.getAction();
- Log.i(TAG, "Received broadcast " + action + " for always-on package " + packageName
- + " in user " + mUserHandle);
+ Log.i(TAG, "Received broadcast " + action + " for always-on VPN package "
+ + packageName + " in user " + mUserHandle);
switch(action) {
case Intent.ACTION_PACKAGE_REPLACED:
@@ -248,7 +248,8 @@
Log.wtf(TAG, "Problem registering observer", e);
}
- mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_VPN, 0, NETWORKTYPE, "");
+ mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_VPN, 0 /* subtype */, NETWORKTYPE,
+ "" /* subtypeName */);
mNetworkCapabilities = new NetworkCapabilities();
mNetworkCapabilities.addTransportType(NetworkCapabilities.TRANSPORT_VPN);
mNetworkCapabilities.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN);
@@ -258,7 +259,7 @@
}
/**
- * Set if this object is responsible for watching for {@link NetworkInfo}
+ * Set whether this object is responsible for watching for {@link NetworkInfo}
* teardown. When {@code false}, teardown is handled externally by someone
* else.
*/
@@ -481,7 +482,6 @@
}
private void unregisterPackageChangeReceiverLocked() {
- // register previous intent filter
if (mIsPackageIntentReceiverRegistered) {
mContext.unregisterReceiver(mPackageIntentReceiver);
mIsPackageIntentReceiverRegistered = false;
@@ -582,7 +582,7 @@
DeviceIdleController.LocalService idleController =
LocalServices.getService(DeviceIdleController.LocalService.class);
idleController.addPowerSaveTempWhitelistApp(Process.myUid(), alwaysOnPackage,
- VPN_LAUNCH_IDLE_WHITELIST_DURATION, mUserHandle, false, "vpn");
+ VPN_LAUNCH_IDLE_WHITELIST_DURATION_MS, mUserHandle, false, "vpn");
// Start the VPN service declared in the app's manifest.
Intent serviceIntent = new Intent(VpnConfig.SERVICE_INTERFACE);
@@ -612,9 +612,10 @@
* It uses {@link VpnConfig#LEGACY_VPN} as its package name, and
* it can be revoked by itself.
*
- * Note: when we added VPN pre-consent in http://ag/522961 the names oldPackage
- * and newPackage become misleading, because when an app is pre-consented, we
- * actually prepare oldPackage, not newPackage.
+ * Note: when we added VPN pre-consent in
+ * https://android.googlesource.com/platform/frameworks/base/+/0554260
+ * the names oldPackage and newPackage became misleading, because when
+ * an app is pre-consented, we actually prepare oldPackage, not newPackage.
*
* Their meanings actually are:
*
@@ -630,7 +631,7 @@
* @param oldPackage The package name of the old VPN application
* @param newPackage The package name of the new VPN application
*
- * @return true if the operation is succeeded.
+ * @return true if the operation succeeded.
*/
public synchronized boolean prepare(String oldPackage, String newPackage) {
if (oldPackage != null) {
@@ -639,7 +640,7 @@
return false;
}
- // Package is not same or old package was reinstalled.
+ // Package is not the same or old package was reinstalled.
if (!isCurrentPreparedPackage(oldPackage)) {
// The package doesn't match. We return false (to obtain user consent) unless the
// user has already consented to that VPN package.
@@ -861,8 +862,8 @@
long token = Binder.clearCallingIdentity();
try {
- mNetworkAgent = new NetworkAgent(mLooper, mContext, NETWORKTYPE,
- mNetworkInfo, mNetworkCapabilities, lp, 0, networkMisc) {
+ mNetworkAgent = new NetworkAgent(mLooper, mContext, NETWORKTYPE /* logtag */,
+ mNetworkInfo, mNetworkCapabilities, lp, 0 /* score */, networkMisc) {
@Override
public void unwanted() {
// We are user controlled, not driven by NetworkRequest.
@@ -936,7 +937,7 @@
}
ResolveInfo info = AppGlobals.getPackageManager().resolveService(intent,
- null, 0, mUserHandle);
+ null, 0, mUserHandle);
if (info == null) {
throw new SecurityException("Cannot find " + config.user);
}
@@ -944,7 +945,7 @@
throw new SecurityException(config.user + " does not require " + BIND_VPN_SERVICE);
}
} catch (RemoteException e) {
- throw new SecurityException("Cannot find " + config.user);
+ throw new SecurityException("Cannot find " + config.user);
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -1337,7 +1338,7 @@
}
private void enforceControlPermissionOrInternalCaller() {
- // Require caller to be either an application with CONTROL_VPN permission or a process
+ // Require the caller to be either an application with CONTROL_VPN permission or a process
// in the system server.
mContext.enforceCallingOrSelfPermission(Manifest.permission.CONTROL_VPN,
"Unauthorized Caller");
@@ -1417,7 +1418,7 @@
}
/**
- * This method should only be called by ConnectivityService. Because it doesn't
+ * This method should only be called by ConnectivityService because it doesn't
* have enough data to fill VpnInfo.primaryUnderlyingIface field.
*/
public synchronized VpnInfo getVpnInfo() {
@@ -1768,7 +1769,7 @@
* Bringing up a VPN connection takes time, and that is all this thread
* does. Here we have plenty of time. The only thing we need to take
* care of is responding to interruptions as soon as possible. Otherwise
- * requests will be piled up. This can be done in a Handler as a state
+ * requests will pile up. This could be done in a Handler as a state
* machine, but it is much easier to read in the current form.
*/
private class LegacyVpnRunner extends Thread {
@@ -1781,7 +1782,7 @@
private final AtomicInteger mOuterConnection =
new AtomicInteger(ConnectivityManager.TYPE_NONE);
- private long mTimer = -1;
+ private long mBringupStartTime = -1;
/**
* Watch for the outer connection (passing in the constructor) going away.
@@ -1861,8 +1862,8 @@
synchronized (TAG) {
Log.v(TAG, "Executing");
try {
- execute();
- monitorDaemons();
+ bringup();
+ waitForDaemonsToStop();
interrupted(); // Clear interrupt flag if execute called exit.
} catch (InterruptedException e) {
} finally {
@@ -1883,30 +1884,27 @@
}
}
- private void checkpoint(boolean yield) throws InterruptedException {
+ private void checkInterruptAndDelay(boolean sleepLonger) throws InterruptedException {
long now = SystemClock.elapsedRealtime();
- if (mTimer == -1) {
- mTimer = now;
- Thread.sleep(1);
- } else if (now - mTimer <= 60000) {
- Thread.sleep(yield ? 200 : 1);
+ if (now - mBringupStartTime <= 60000) {
+ Thread.sleep(sleepLonger ? 200 : 1);
} else {
updateState(DetailedState.FAILED, "checkpoint");
- throw new IllegalStateException("Time is up");
+ throw new IllegalStateException("VPN bringup took too long");
}
}
- private void execute() {
- // Catch all exceptions so we can clean up few things.
+ private void bringup() {
+ // Catch all exceptions so we can clean up a few things.
boolean initFinished = false;
try {
// Initialize the timer.
- checkpoint(false);
+ mBringupStartTime = SystemClock.elapsedRealtime();
// Wait for the daemons to stop.
for (String daemon : mDaemons) {
while (!SystemService.isStopped(daemon)) {
- checkpoint(true);
+ checkInterruptAndDelay(true);
}
}
@@ -1943,7 +1941,7 @@
// Wait for the daemon to start.
while (!SystemService.isRunning(daemon)) {
- checkpoint(true);
+ checkInterruptAndDelay(true);
}
// Create the control socket.
@@ -1959,7 +1957,7 @@
} catch (Exception e) {
// ignore
}
- checkpoint(true);
+ checkInterruptAndDelay(true);
}
mSockets[i].setSoTimeout(500);
@@ -1973,7 +1971,7 @@
out.write(bytes.length >> 8);
out.write(bytes.length);
out.write(bytes);
- checkpoint(false);
+ checkInterruptAndDelay(false);
}
out.write(0xFF);
out.write(0xFF);
@@ -1989,7 +1987,7 @@
} catch (Exception e) {
// ignore
}
- checkpoint(true);
+ checkInterruptAndDelay(true);
}
}
@@ -2002,7 +2000,7 @@
throw new IllegalStateException(daemon + " is dead");
}
}
- checkpoint(true);
+ checkInterruptAndDelay(true);
}
// Now we are connected. Read and parse the new state.
@@ -2058,8 +2056,8 @@
// Set the start time
mConfig.startTime = SystemClock.elapsedRealtime();
- // Check if the thread is interrupted while we are waiting.
- checkpoint(false);
+ // Check if the thread was interrupted while we were waiting on the lock.
+ checkInterruptAndDelay(false);
// Check if the interface is gone while we are waiting.
if (jniCheck(mConfig.interfaze) == 0) {
@@ -2082,10 +2080,11 @@
}
/**
- * Monitor the daemons we started, moving to disconnected state if the
- * underlying services fail.
+ * Check all daemons every two seconds. Return when one of them is stopped.
+ * The caller will move to the disconnected state when this function returns,
+ * which can happen if a daemon failed or if the VPN was torn down.
*/
- private void monitorDaemons() throws InterruptedException{
+ private void waitForDaemonsToStop() throws InterruptedException {
if (!mNetworkInfo.isConnected()) {
return;
}
diff --git a/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java b/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java
index 17adb1a..2224913 100644
--- a/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java
+++ b/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java
@@ -30,6 +30,7 @@
import android.net.ip.InterfaceController;
import android.net.ip.RouterAdvertisementDaemon;
import android.net.ip.RouterAdvertisementDaemon.RaParams;
+import android.net.util.InterfaceParams;
import android.net.util.NetdService;
import android.net.util.SharedLog;
import android.os.INetworkManagementService;
@@ -48,7 +49,6 @@
import java.net.Inet6Address;
import java.net.InetAddress;
-import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.ArrayList;
@@ -120,8 +120,7 @@
private int mLastError;
private int mServingMode;
private String mMyUpstreamIfaceName; // may change over time
- private NetworkInterface mNetworkInterface;
- private byte[] mHwAddr;
+ private InterfaceParams mInterfaceParams;
// TODO: De-duplicate this with mLinkProperties above. Currently, these link
// properties are those selected by the IPv6TetheringCoordinator and relayed
// to us. By comparison, mLinkProperties contains the addresses and directly
@@ -247,31 +246,16 @@
}
private boolean startIPv6() {
- // TODO: Refactor for testability (perhaps passing an android.system.Os
- // instance and calling getifaddrs() directly).
- try {
- mNetworkInterface = NetworkInterface.getByName(mIfaceName);
- } catch (SocketException e) {
- mLog.e("Error looking up NetworkInterfaces: " + e);
- stopIPv6();
- return false;
- }
- if (mNetworkInterface == null) {
- mLog.e("Failed to find NetworkInterface");
+ // TODO: Refactor for better testability. This is one of the things
+ // that prohibits unittesting IPv6 tethering setup.
+ mInterfaceParams = InterfaceParams.getByName(mIfaceName);
+ if (mInterfaceParams == null) {
+ mLog.e("Failed to find InterfaceParams");
stopIPv6();
return false;
}
- try {
- mHwAddr = mNetworkInterface.getHardwareAddress();
- } catch (SocketException e) {
- mLog.e("Failed to find hardware address: " + e);
- stopIPv6();
- return false;
- }
-
- final int ifindex = mNetworkInterface.getIndex();
- mRaDaemon = new RouterAdvertisementDaemon(mIfaceName, ifindex, mHwAddr);
+ mRaDaemon = new RouterAdvertisementDaemon(mInterfaceParams);
if (!mRaDaemon.start()) {
stopIPv6();
return false;
@@ -281,8 +265,7 @@
}
private void stopIPv6() {
- mNetworkInterface = null;
- mHwAddr = null;
+ mInterfaceParams = null;
setRaParams(null);
if (mRaDaemon != null) {
diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java
index b7b91a7..625764c 100644
--- a/services/core/java/com/android/server/notification/ManagedServices.java
+++ b/services/core/java/com/android/server/notification/ManagedServices.java
@@ -39,8 +39,10 @@
import android.content.pm.UserInfo;
import android.os.Binder;
import android.os.Build;
+import android.os.Handler;
import android.os.IBinder;
import android.os.IInterface;
+import android.os.Looper;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
@@ -82,6 +84,7 @@
protected final String TAG = getClass().getSimpleName();
protected final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+ private static final int ON_BINDING_DIED_REBIND_DELAY_MS = 10000;
protected static final String ENABLED_SERVICES_SEPARATOR = ":";
/**
@@ -101,12 +104,15 @@
private final IPackageManager mPm;
private final UserManager mUm;
private final Config mConfig;
+ private final Handler mHandler = new Handler(Looper.getMainLooper());
// contains connections to all connected services, including app services
// and system services
private final ArrayList<ManagedServiceInfo> mServices = new ArrayList<>();
// things that will be put into mServices as soon as they're ready
private final ArrayList<String> mServicesBinding = new ArrayList<>();
+ private final ArraySet<String> mServicesRebinding = new ArraySet<>();
+
// lists the component names of all enabled (and therefore potentially connected)
// app services for current profiles.
private ArraySet<ComponentName> mEnabledServicesForCurrentProfiles
@@ -823,6 +829,7 @@
final String servicesBindingTag = name.toString() + "/" + userid;
if (mServicesBinding.contains(servicesBindingTag)) {
+ Slog.v(TAG, "Not registering " + name + " as bind is already in progress");
// stop registering this thing already! we're working on it
return;
}
@@ -871,6 +878,7 @@
boolean added = false;
ManagedServiceInfo info = null;
synchronized (mMutex) {
+ mServicesRebinding.remove(servicesBindingTag);
mServicesBinding.remove(servicesBindingTag);
try {
mService = asInterface(binder);
@@ -892,6 +900,27 @@
mServicesBinding.remove(servicesBindingTag);
Slog.v(TAG, getCaption() + " connection lost: " + name);
}
+
+ @Override
+ public void onBindingDied(ComponentName name) {
+ Slog.w(TAG, getCaption() + " binding died: " + name);
+ synchronized (mMutex) {
+ mServicesBinding.remove(servicesBindingTag);
+ mContext.unbindService(this);
+ if (!mServicesRebinding.contains(servicesBindingTag)) {
+ mServicesRebinding.add(servicesBindingTag);
+ mHandler.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ registerService(name, userid);
+ }
+ }, ON_BINDING_DIED_REBIND_DELAY_MS);
+ } else {
+ Slog.v(TAG, getCaption() + " not rebinding as "
+ + "a previous rebind attempt was made: " + name);
+ }
+ }
+ }
};
if (!mContext.bindServiceAsUser(intent,
serviceConnection,
diff --git a/services/core/java/com/android/server/power/ShutdownThread.java b/services/core/java/com/android/server/power/ShutdownThread.java
index 72b2211..3aca330 100644
--- a/services/core/java/com/android/server/power/ShutdownThread.java
+++ b/services/core/java/com/android/server/power/ShutdownThread.java
@@ -24,8 +24,6 @@
import android.app.ProgressDialog;
import android.app.WallpaperColors;
import android.app.WallpaperManager;
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.IBluetoothManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
@@ -120,7 +118,6 @@
private static String METRIC_AM = "shutdown_activity_manager";
private static String METRIC_PM = "shutdown_package_manager";
private static String METRIC_RADIOS = "shutdown_radios";
- private static String METRIC_BT = "shutdown_bt";
private static String METRIC_RADIO = "shutdown_radio";
private static String METRIC_SM = "shutdown_storage_manager";
@@ -415,7 +412,7 @@
/**
* Makes sure we handle the shutdown gracefully.
- * Shuts off power regardless of radio and bluetooth state if the alloted time has passed.
+ * Shuts off power regardless of radio state if the allotted time has passed.
*/
public void run() {
TimingsTraceLog shutdownTimingLog = newTimingsLog();
@@ -627,27 +624,10 @@
Thread t = new Thread() {
public void run() {
TimingsTraceLog shutdownTimingsTraceLog = newTimingsLog();
- boolean bluetoothReadyForShutdown;
boolean radioOff;
final ITelephony phone =
ITelephony.Stub.asInterface(ServiceManager.checkService("phone"));
- final IBluetoothManager bluetooth =
- IBluetoothManager.Stub.asInterface(ServiceManager.checkService(
- BluetoothAdapter.BLUETOOTH_MANAGER_SERVICE));
-
- try {
- bluetoothReadyForShutdown = bluetooth == null ||
- bluetooth.getState() == BluetoothAdapter.STATE_OFF;
- if (!bluetoothReadyForShutdown) {
- Log.w(TAG, "Disabling Bluetooth...");
- metricStarted(METRIC_BT);
- bluetooth.disable(mContext.getPackageName(), false); // disable but don't persist new state
- }
- } catch (RemoteException ex) {
- Log.e(TAG, "RemoteException during bluetooth shutdown", ex);
- bluetoothReadyForShutdown = true;
- }
try {
radioOff = phone == null || !phone.needMobileRadioShutdown();
@@ -661,7 +641,7 @@
radioOff = true;
}
- Log.i(TAG, "Waiting for Bluetooth and Radio...");
+ Log.i(TAG, "Waiting for Radio...");
long delay = endTime - SystemClock.elapsedRealtime();
while (delay > 0) {
@@ -672,25 +652,6 @@
sInstance.setRebootProgress(status, null);
}
- if (!bluetoothReadyForShutdown) {
- try {
- // BLE only mode can happen when BT is turned off
- // We will continue shutting down in such case
- bluetoothReadyForShutdown =
- bluetooth.getState() == BluetoothAdapter.STATE_OFF ||
- bluetooth.getState() == BluetoothAdapter.STATE_BLE_TURNING_OFF ||
- bluetooth.getState() == BluetoothAdapter.STATE_BLE_ON;
- } catch (RemoteException ex) {
- Log.e(TAG, "RemoteException during bluetooth shutdown", ex);
- bluetoothReadyForShutdown = true;
- }
- if (bluetoothReadyForShutdown) {
- Log.i(TAG, "Bluetooth turned off.");
- metricEnded(METRIC_BT);
- shutdownTimingsTraceLog
- .logDuration("ShutdownBt", TRON_METRICS.get(METRIC_BT));
- }
- }
if (!radioOff) {
try {
radioOff = !phone.needMobileRadioShutdown();
@@ -706,8 +667,8 @@
}
}
- if (radioOff && bluetoothReadyForShutdown) {
- Log.i(TAG, "Radio and Bluetooth shutdown complete.");
+ if (radioOff) {
+ Log.i(TAG, "Radio shutdown complete.");
done[0] = true;
break;
}
@@ -724,7 +685,7 @@
} catch (InterruptedException ex) {
}
if (!done[0]) {
- Log.w(TAG, "Timed out waiting for Radio and Bluetooth shutdown.");
+ Log.w(TAG, "Timed out waiting for Radio shutdown.");
}
}
diff --git a/services/core/java/com/android/server/vr/VrManagerInternal.java b/services/core/java/com/android/server/vr/VrManagerInternal.java
index 7b1e12e..35b6ad3 100644
--- a/services/core/java/com/android/server/vr/VrManagerInternal.java
+++ b/services/core/java/com/android/server/vr/VrManagerInternal.java
@@ -59,13 +59,6 @@
int userId, int processId, @NonNull ComponentName calling);
/**
- * Set whether the system has acquired a sleep token.
- *
- * @param isAsleep is {@code true} if the device is asleep, or {@code false} otherwise.
- */
- public abstract void onSleepStateChanged(boolean isAsleep);
-
- /**
* Set whether the display used for VR output is on.
*
* @param isScreenOn is {@code true} if the display is on and can receive commands,
@@ -74,13 +67,6 @@
public abstract void onScreenStateChanged(boolean isScreenOn);
/**
- * Set whether the keyguard is currently active/showing.
- *
- * @param isShowing is {@code true} if the keyguard is active/showing.
- */
- public abstract void onKeyguardStateChanged(boolean isShowing);
-
- /**
* Return NO_ERROR if the given package is installed on the device and enabled as a
* VrListenerService for the given current user, or a negative error code indicating a failure.
*
diff --git a/services/core/java/com/android/server/vr/VrManagerService.java b/services/core/java/com/android/server/vr/VrManagerService.java
index b0fd248..56cacf4 100644
--- a/services/core/java/com/android/server/vr/VrManagerService.java
+++ b/services/core/java/com/android/server/vr/VrManagerService.java
@@ -19,6 +19,7 @@
import android.Manifest;
import android.app.ActivityManagerInternal;
+import android.app.ActivityManagerInternal.ScreenObserver;
import android.app.ActivityManager;
import android.app.AppOpsManager;
import android.app.INotificationManager;
@@ -104,7 +105,8 @@
*
* @hide
*/
-public class VrManagerService extends SystemService implements EnabledComponentChangeListener{
+public class VrManagerService extends SystemService
+ implements EnabledComponentChangeListener, ScreenObserver {
public static final String TAG = "VrManagerService";
static final boolean DBG = false;
@@ -231,15 +233,17 @@
}
}
- private void setSleepState(boolean isAsleep) {
- setSystemState(FLAG_AWAKE, !isAsleep);
- }
-
private void setScreenOn(boolean isScreenOn) {
setSystemState(FLAG_SCREEN_ON, isScreenOn);
}
- private void setKeyguardShowing(boolean isShowing) {
+ @Override
+ public void onAwakeStateChanged(boolean isAwake) {
+ setSystemState(FLAG_AWAKE, isAwake);
+ }
+
+ @Override
+ public void onKeyguardStateChanged(boolean isShowing) {
setSystemState(FLAG_KEYGUARD_UNLOCKED, !isShowing);
}
@@ -675,21 +679,11 @@
}
@Override
- public void onSleepStateChanged(boolean isAsleep) {
- VrManagerService.this.setSleepState(isAsleep);
- }
-
- @Override
public void onScreenStateChanged(boolean isScreenOn) {
VrManagerService.this.setScreenOn(isScreenOn);
}
@Override
- public void onKeyguardStateChanged(boolean isShowing) {
- VrManagerService.this.setKeyguardShowing(isShowing);
- }
-
- @Override
public boolean isCurrentVrListener(String packageName, int userId) {
return VrManagerService.this.isCurrentVrListener(packageName, userId);
}
@@ -740,6 +734,9 @@
@Override
public void onBootPhase(int phase) {
if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
+ LocalServices.getService(ActivityManagerInternal.class)
+ .registerScreenObserver(this);
+
mNotificationManager = INotificationManager.Stub.asInterface(
ServiceManager.getService(Context.NOTIFICATION_SERVICE));
synchronized (mLock) {
diff --git a/services/net/java/android/net/apf/ApfFilter.java b/services/net/java/android/net/apf/ApfFilter.java
index 31a1abb..7d9736e 100644
--- a/services/net/java/android/net/apf/ApfFilter.java
+++ b/services/net/java/android/net/apf/ApfFilter.java
@@ -38,6 +38,7 @@
import android.net.metrics.ApfStats;
import android.net.metrics.IpConnectivityLog;
import android.net.metrics.RaEvent;
+import android.net.util.InterfaceParams;
import android.system.ErrnoException;
import android.system.Os;
import android.system.PacketSocketAddress;
@@ -56,7 +57,6 @@
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
-import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
@@ -247,7 +247,7 @@
private final ApfCapabilities mApfCapabilities;
private final IpClient.Callback mIpClientCallback;
- private final NetworkInterface mNetworkInterface;
+ private final InterfaceParams mInterfaceParams;
private final IpConnectivityLog mMetricsLog;
@VisibleForTesting
@@ -269,11 +269,11 @@
private int mIPv4PrefixLength;
@VisibleForTesting
- ApfFilter(ApfConfiguration config, NetworkInterface networkInterface,
+ ApfFilter(ApfConfiguration config, InterfaceParams ifParams,
IpClient.Callback ipClientCallback, IpConnectivityLog log) {
mApfCapabilities = config.apfCapabilities;
mIpClientCallback = ipClientCallback;
- mNetworkInterface = networkInterface;
+ mInterfaceParams = ifParams;
mMulticastFilter = config.multicastFilter;
mDrop802_3Frames = config.ieee802_3Filter;
@@ -287,7 +287,7 @@
}
private void log(String s) {
- Log.d(TAG, "(" + mNetworkInterface.getName() + "): " + s);
+ Log.d(TAG, "(" + mInterfaceParams.name + "): " + s);
}
@GuardedBy("this")
@@ -332,14 +332,14 @@
void maybeStartFilter() {
FileDescriptor socket;
try {
- mHardwareAddress = mNetworkInterface.getHardwareAddress();
+ mHardwareAddress = mInterfaceParams.macAddr.toByteArray();
synchronized(this) {
// Install basic filters
installNewProgramLocked();
}
socket = Os.socket(AF_PACKET, SOCK_RAW, ETH_P_IPV6);
- PacketSocketAddress addr = new PacketSocketAddress((short) ETH_P_IPV6,
- mNetworkInterface.getIndex());
+ PacketSocketAddress addr = new PacketSocketAddress(
+ (short) ETH_P_IPV6, mInterfaceParams.index);
Os.bind(socket, addr);
NetworkUtils.attachRaFilter(socket, mApfCapabilities.apfPacketFormat);
} catch(SocketException|ErrnoException e) {
@@ -1168,10 +1168,10 @@
* filtering using APF programs.
*/
public static ApfFilter maybeCreate(ApfConfiguration config,
- NetworkInterface networkInterface, IpClient.Callback ipClientCallback) {
- if (config == null) return null;
+ InterfaceParams ifParams, IpClient.Callback ipClientCallback) {
+ if (config == null || ifParams == null) return null;
ApfCapabilities apfCapabilities = config.apfCapabilities;
- if (apfCapabilities == null || networkInterface == null) return null;
+ if (apfCapabilities == null) return null;
if (apfCapabilities.apfVersionSupported == 0) return null;
if (apfCapabilities.maximumApfProgramSize < 512) {
Log.e(TAG, "Unacceptably small APF limit: " + apfCapabilities.maximumApfProgramSize);
@@ -1186,7 +1186,7 @@
Log.e(TAG, "Unsupported APF version: " + apfCapabilities.apfVersionSupported);
return null;
}
- return new ApfFilter(config, networkInterface, ipClientCallback, new IpConnectivityLog());
+ return new ApfFilter(config, ifParams, ipClientCallback, new IpConnectivityLog());
}
public synchronized void shutdown() {
diff --git a/services/net/java/android/net/dhcp/DhcpClient.java b/services/net/java/android/net/dhcp/DhcpClient.java
index ed78175..a956cef 100644
--- a/services/net/java/android/net/dhcp/DhcpClient.java
+++ b/services/net/java/android/net/dhcp/DhcpClient.java
@@ -34,6 +34,7 @@
import android.net.metrics.IpConnectivityLog;
import android.net.metrics.DhcpClientEvent;
import android.net.metrics.DhcpErrorEvent;
+import android.net.util.InterfaceParams;
import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -50,7 +51,6 @@
import java.io.IOException;
import java.lang.Thread;
import java.net.Inet4Address;
-import java.net.NetworkInterface;
import java.net.SocketException;
import java.nio.ByteBuffer;
import java.util.Arrays;
@@ -187,7 +187,8 @@
private final String mIfaceName;
private boolean mRegisteredForPreDhcpNotification;
- private NetworkInterface mIface;
+ private InterfaceParams mIface;
+ // TODO: MacAddress-ify more of this class hierarchy.
private byte[] mHwAddr;
private PacketSocketAddress mInterfaceBroadcastAddr;
private int mTransactionId;
@@ -221,8 +222,9 @@
return new WakeupMessage(mContext, getHandler(), cmdName, cmd);
}
+ // TODO: Take an InterfaceParams instance instead of an interface name String.
private DhcpClient(Context context, StateMachine controller, String iface) {
- super(TAG);
+ super(TAG, controller.getHandler());
mContext = context;
mController = controller;
@@ -262,23 +264,23 @@
}
public static DhcpClient makeDhcpClient(
- Context context, StateMachine controller, String intf) {
- DhcpClient client = new DhcpClient(context, controller, intf);
+ Context context, StateMachine controller, InterfaceParams ifParams) {
+ DhcpClient client = new DhcpClient(context, controller, ifParams.name);
+ client.mIface = ifParams;
client.start();
return client;
}
private boolean initInterface() {
- try {
- mIface = NetworkInterface.getByName(mIfaceName);
- mHwAddr = mIface.getHardwareAddress();
- mInterfaceBroadcastAddr = new PacketSocketAddress(mIface.getIndex(),
- DhcpPacket.ETHER_BROADCAST);
- return true;
- } catch(SocketException | NullPointerException e) {
- Log.e(TAG, "Can't determine ifindex or MAC address for " + mIfaceName, e);
+ if (mIface == null) mIface = InterfaceParams.getByName(mIfaceName);
+ if (mIface == null) {
+ Log.e(TAG, "Can't determine InterfaceParams for " + mIfaceName);
return false;
}
+
+ mHwAddr = mIface.macAddr.toByteArray();
+ mInterfaceBroadcastAddr = new PacketSocketAddress(mIface.index, DhcpPacket.ETHER_BROADCAST);
+ return true;
}
private void startNewTransaction() {
@@ -293,7 +295,7 @@
private boolean initPacketSocket() {
try {
mPacketSock = Os.socket(AF_PACKET, SOCK_RAW, ETH_P_IP);
- PacketSocketAddress addr = new PacketSocketAddress((short) ETH_P_IP, mIface.getIndex());
+ PacketSocketAddress addr = new PacketSocketAddress((short) ETH_P_IP, mIface.index);
Os.bind(mPacketSock, addr);
NetworkUtils.attachDhcpFilter(mPacketSock);
} catch(SocketException|ErrnoException e) {
diff --git a/services/net/java/android/net/ip/ConnectivityPacketTracker.java b/services/net/java/android/net/ip/ConnectivityPacketTracker.java
index 6cf4fa9a..e6ddbbc 100644
--- a/services/net/java/android/net/ip/ConnectivityPacketTracker.java
+++ b/services/net/java/android/net/ip/ConnectivityPacketTracker.java
@@ -21,6 +21,7 @@
import android.net.NetworkUtils;
import android.net.util.PacketReader;
import android.net.util.ConnectivityPacketSummary;
+import android.net.util.InterfaceParams;
import android.os.Handler;
import android.system.ErrnoException;
import android.system.Os;
@@ -35,7 +36,6 @@
import java.io.FileDescriptor;
import java.io.InterruptedIOException;
import java.io.IOException;
-import java.net.NetworkInterface;
import java.net.SocketException;
@@ -69,24 +69,12 @@
private boolean mRunning;
private String mDisplayName;
- public ConnectivityPacketTracker(Handler h, NetworkInterface netif, LocalLog log) {
- final String ifname;
- final int ifindex;
- final byte[] hwaddr;
- final int mtu;
+ public ConnectivityPacketTracker(Handler h, InterfaceParams ifParams, LocalLog log) {
+ if (ifParams == null) throw new IllegalArgumentException("null InterfaceParams");
- try {
- ifname = netif.getName();
- ifindex = netif.getIndex();
- hwaddr = netif.getHardwareAddress();
- mtu = netif.getMTU();
- } catch (NullPointerException|SocketException e) {
- throw new IllegalArgumentException("bad network interface", e);
- }
-
- mTag = TAG + "." + ifname;
+ mTag = TAG + "." + ifParams.name;
mLog = log;
- mPacketListener = new PacketListener(h, ifindex, hwaddr, mtu);
+ mPacketListener = new PacketListener(h, ifParams);
}
public void start(String displayName) {
@@ -102,13 +90,11 @@
}
private final class PacketListener extends PacketReader {
- private final int mIfIndex;
- private final byte mHwAddr[];
+ private final InterfaceParams mInterface;
- PacketListener(Handler h, int ifindex, byte[] hwaddr, int mtu) {
- super(h, mtu);
- mIfIndex = ifindex;
- mHwAddr = hwaddr;
+ PacketListener(Handler h, InterfaceParams ifParams) {
+ super(h, ifParams.defaultMtu);
+ mInterface = ifParams;
}
@Override
@@ -117,7 +103,7 @@
try {
s = Os.socket(AF_PACKET, SOCK_RAW, 0);
NetworkUtils.attachControlPacketFilter(s, ARPHRD_ETHER);
- Os.bind(s, new PacketSocketAddress((short) ETH_P_ALL, mIfIndex));
+ Os.bind(s, new PacketSocketAddress((short) ETH_P_ALL, mInterface.index));
} catch (ErrnoException | IOException e) {
logError("Failed to create packet tracking socket: ", e);
closeFd(s);
@@ -129,7 +115,7 @@
@Override
protected void handlePacket(byte[] recvbuf, int length) {
final String summary = ConnectivityPacketSummary.summarize(
- mHwAddr, recvbuf, length);
+ mInterface.macAddr, recvbuf, length);
if (summary == null) return;
if (DBG) Log.d(mTag, summary);
diff --git a/services/net/java/android/net/ip/IpClient.java b/services/net/java/android/net/ip/IpClient.java
index fdb366c..d3a97b3 100644
--- a/services/net/java/android/net/ip/IpClient.java
+++ b/services/net/java/android/net/ip/IpClient.java
@@ -35,6 +35,7 @@
import android.net.dhcp.DhcpClient;
import android.net.metrics.IpConnectivityLog;
import android.net.metrics.IpManagerEvent;
+import android.net.util.InterfaceParams;
import android.net.util.MultinetworkPolicyTracker;
import android.net.util.NetdService;
import android.net.util.NetworkConstants;
@@ -63,7 +64,6 @@
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
-import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.Collection;
@@ -556,7 +556,7 @@
private final IpConnectivityLog mMetricsLog = new IpConnectivityLog();
private final InterfaceController mInterfaceCtrl;
- private NetworkInterface mNetworkInterface;
+ private InterfaceParams mInterfaceParams;
/**
* Non-final member variables accessed only from within our StateMachine.
@@ -722,7 +722,12 @@
return;
}
- getNetworkInterface();
+ mInterfaceParams = InterfaceParams.getByName(mInterfaceName);
+ if (mInterfaceParams == null) {
+ logError("Failed to find InterfaceParams for " + mInterfaceName);
+ // TODO: call doImmediateProvisioningFailure() with an error code
+ // indicating something like "interface not ready".
+ }
mCallback.setNeighborDiscoveryOffload(true);
sendMessage(CMD_START, new ProvisioningConfiguration(req));
@@ -858,7 +863,7 @@
protected String getLogRecString(Message msg) {
final String logLine = String.format(
"%s/%d %d %d %s [%s]",
- mInterfaceName, mNetworkInterface == null ? -1 : mNetworkInterface.getIndex(),
+ mInterfaceName, (mInterfaceParams == null) ? -1 : mInterfaceParams.index,
msg.arg1, msg.arg2, Objects.toString(msg.obj), mMsgStateLogger);
final String richerLogLine = getWhatToString(msg.what) + " " + logLine;
@@ -889,15 +894,6 @@
mLog.log(msg);
}
- private void getNetworkInterface() {
- try {
- mNetworkInterface = NetworkInterface.getByName(mInterfaceName);
- } catch (SocketException | NullPointerException e) {
- // TODO: throw new IllegalStateException.
- logError("Failed to get interface object: %s", e);
- }
- }
-
// This needs to be called with care to ensure that our LinkProperties
// are in sync with the actual LinkProperties of the interface. For example,
// we should only call this if we know for sure that there are no IP addresses
@@ -1218,7 +1214,7 @@
}
} else {
// Start DHCPv4.
- mDhcpClient = DhcpClient.makeDhcpClient(mContext, IpClient.this, mInterfaceName);
+ mDhcpClient = DhcpClient.makeDhcpClient(mContext, IpClient.this, mInterfaceParams);
mDhcpClient.registerForPreDhcpNotification();
mDhcpClient.sendMessage(DhcpClient.CMD_START_DHCP);
}
@@ -1245,7 +1241,7 @@
try {
mIpReachabilityMonitor = new IpReachabilityMonitor(
mContext,
- mInterfaceName,
+ mInterfaceParams,
getHandler(),
mLog,
new IpReachabilityMonitor.Callback() {
@@ -1447,7 +1443,7 @@
mContext.getResources().getBoolean(R.bool.config_apfDrop802_3Frames);
apfConfig.ethTypeBlackList =
mContext.getResources().getIntArray(R.array.config_apfEthTypeBlackList);
- mApfFilter = ApfFilter.maybeCreate(apfConfig, mNetworkInterface, mCallback);
+ mApfFilter = ApfFilter.maybeCreate(apfConfig, mInterfaceParams, mCallback);
// TODO: investigate the effects of any multicast filtering racing/interfering with the
// rest of this IP configuration startup.
if (mApfFilter == null) {
@@ -1515,7 +1511,7 @@
private ConnectivityPacketTracker createPacketTracker() {
try {
return new ConnectivityPacketTracker(
- getHandler(), mNetworkInterface, mConnectivityPacketLog);
+ getHandler(), mInterfaceParams, mConnectivityPacketLog);
} catch (IllegalArgumentException e) {
return null;
}
diff --git a/services/net/java/android/net/ip/IpNeighborMonitor.java b/services/net/java/android/net/ip/IpNeighborMonitor.java
index 6807334..fc07aa1 100644
--- a/services/net/java/android/net/ip/IpNeighborMonitor.java
+++ b/services/net/java/android/net/ip/IpNeighborMonitor.java
@@ -16,7 +16,11 @@
package android.net.ip;
-import android.net.netlink.NetlinkConstants;
+import static android.net.netlink.NetlinkConstants.hexify;
+import static android.net.netlink.NetlinkConstants.RTM_DELNEIGH;
+import static android.net.netlink.NetlinkConstants.stringForNlMsgType;
+
+import android.net.MacAddress;
import android.net.netlink.NetlinkErrorMessage;
import android.net.netlink.NetlinkMessage;
import android.net.netlink.NetlinkSocket;
@@ -92,37 +96,35 @@
final int ifindex;
final InetAddress ip;
final short nudState;
- final byte[] linkLayerAddr;
+ final MacAddress macAddr;
public NeighborEvent(long elapsedMs, short msgType, int ifindex, InetAddress ip,
- short nudState, byte[] linkLayerAddr) {
+ short nudState, MacAddress macAddr) {
this.elapsedMs = elapsedMs;
this.msgType = msgType;
this.ifindex = ifindex;
this.ip = ip;
this.nudState = nudState;
- this.linkLayerAddr = linkLayerAddr;
+ this.macAddr = macAddr;
}
boolean isConnected() {
- return (msgType != NetlinkConstants.RTM_DELNEIGH) &&
- StructNdMsg.isNudStateConnected(nudState);
+ return (msgType != RTM_DELNEIGH) && StructNdMsg.isNudStateConnected(nudState);
}
boolean isValid() {
- return (msgType != NetlinkConstants.RTM_DELNEIGH) &&
- StructNdMsg.isNudStateValid(nudState);
+ return (msgType != RTM_DELNEIGH) && StructNdMsg.isNudStateValid(nudState);
}
@Override
public String toString() {
final StringJoiner j = new StringJoiner(",", "NeighborEvent{", "}");
return j.add("@" + elapsedMs)
- .add(NetlinkConstants.stringForNlMsgType(msgType))
+ .add(stringForNlMsgType(msgType))
.add("if=" + ifindex)
.add(ip.getHostAddress())
.add(StructNdMsg.stringForNudState(nudState))
- .add("[" + NetlinkConstants.hexify(linkLayerAddr) + "]")
+ .add("[" + macAddr + "]")
.toString();
}
}
@@ -183,7 +185,7 @@
final NetlinkMessage nlMsg = NetlinkMessage.parse(byteBuffer);
if (nlMsg == null || nlMsg.getHeader() == null) {
byteBuffer.position(position);
- mLog.e("unparsable netlink msg: " + NetlinkConstants.hexify(byteBuffer));
+ mLog.e("unparsable netlink msg: " + hexify(byteBuffer));
break;
}
@@ -217,12 +219,13 @@
final int ifindex = ndMsg.ndm_ifindex;
final InetAddress destination = neighMsg.getDestination();
final short nudState =
- (msgType == NetlinkConstants.RTM_DELNEIGH)
+ (msgType == RTM_DELNEIGH)
? StructNdMsg.NUD_NONE
: ndMsg.ndm_state;
final NeighborEvent event = new NeighborEvent(
- whenMs, msgType, ifindex, destination, nudState, neighMsg.getLinkLayerAddress());
+ whenMs, msgType, ifindex, destination, nudState,
+ getMacAddress(neighMsg.getLinkLayerAddress()));
if (VDBG) {
Log.d(TAG, neighMsg.toString());
@@ -233,4 +236,16 @@
mConsumer.accept(event);
}
+
+ private static MacAddress getMacAddress(byte[] linkLayerAddress) {
+ if (linkLayerAddress != null) {
+ try {
+ return MacAddress.fromBytes(linkLayerAddress);
+ } catch (IllegalArgumentException e) {
+ Log.e(TAG, "Failed to parse link-layer address: " + hexify(linkLayerAddress));
+ }
+ }
+
+ return null;
+ }
}
diff --git a/services/net/java/android/net/ip/IpReachabilityMonitor.java b/services/net/java/android/net/ip/IpReachabilityMonitor.java
index b31ffbb..7e02a28 100644
--- a/services/net/java/android/net/ip/IpReachabilityMonitor.java
+++ b/services/net/java/android/net/ip/IpReachabilityMonitor.java
@@ -26,6 +26,7 @@
import android.net.metrics.IpConnectivityLog;
import android.net.metrics.IpReachabilityEvent;
import android.net.netlink.StructNdMsg;
+import android.net.util.InterfaceParams;
import android.net.util.MultinetworkPolicyTracker;
import android.net.util.SharedLog;
import android.os.Handler;
@@ -46,9 +47,7 @@
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;
-import java.net.NetworkInterface;
import java.net.SocketAddress;
-import java.net.SocketException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
@@ -168,8 +167,7 @@
}
}
- private final String mInterfaceName;
- private final int mInterfaceIndex;
+ private final InterfaceParams mInterfaceParams;
private final IpNeighborMonitor mIpNeighborMonitor;
private final SharedLog mLog;
private final Callback mCallback;
@@ -182,30 +180,25 @@
private volatile long mLastProbeTimeMs;
public IpReachabilityMonitor(
- Context context, String ifName, Handler h, SharedLog log, Callback callback) {
- this(context, ifName, h, log, callback, null);
- }
-
- public IpReachabilityMonitor(
- Context context, String ifName, Handler h, SharedLog log, Callback callback,
+ Context context, InterfaceParams ifParams, Handler h, SharedLog log, Callback callback,
MultinetworkPolicyTracker tracker) {
- this(ifName, getInterfaceIndex(ifName), h, log, callback, tracker,
- Dependencies.makeDefault(context, ifName));
+ this(ifParams, h, log, callback, tracker, Dependencies.makeDefault(context, ifParams.name));
}
@VisibleForTesting
- IpReachabilityMonitor(String ifName, int ifIndex, Handler h, SharedLog log, Callback callback,
+ IpReachabilityMonitor(InterfaceParams ifParams, Handler h, SharedLog log, Callback callback,
MultinetworkPolicyTracker tracker, Dependencies dependencies) {
- mInterfaceName = ifName;
+ if (ifParams == null) throw new IllegalArgumentException("null InterfaceParams");
+
+ mInterfaceParams = ifParams;
mLog = log.forSubComponent(TAG);
mCallback = callback;
mMultinetworkPolicyTracker = tracker;
- mInterfaceIndex = ifIndex;
mDependencies = dependencies;
mIpNeighborMonitor = new IpNeighborMonitor(h, mLog,
(NeighborEvent event) -> {
- if (mInterfaceIndex != event.ifindex) return;
+ if (mInterfaceParams.index != event.ifindex) return;
if (!mNeighborWatchList.containsKey(event.ip)) return;
final NeighborEvent prev = mNeighborWatchList.put(event.ip, event);
@@ -241,7 +234,7 @@
private String describeWatchList(String sep) {
final StringBuilder sb = new StringBuilder();
- sb.append("iface{" + mInterfaceName + "/" + mInterfaceIndex + "}," + sep);
+ sb.append("iface{" + mInterfaceParams + "}," + sep);
sb.append("ntable=[" + sep);
String delimiter = "";
for (Map.Entry<InetAddress, NeighborEvent> entry : mNeighborWatchList.entrySet()) {
@@ -262,10 +255,10 @@
}
public void updateLinkProperties(LinkProperties lp) {
- if (!mInterfaceName.equals(lp.getInterfaceName())) {
+ if (!mInterfaceParams.name.equals(lp.getInterfaceName())) {
// TODO: figure out whether / how to cope with interface changes.
Log.wtf(TAG, "requested LinkProperties interface '" + lp.getInterfaceName() +
- "' does not match: " + mInterfaceName);
+ "' does not match: " + mInterfaceParams.name);
return;
}
@@ -353,10 +346,10 @@
mDependencies.acquireWakeLock(getProbeWakeLockDuration());
}
- for (InetAddress target : ipProbeList) {
- final int rval = IpNeighborMonitor.startKernelNeighborProbe(mInterfaceIndex, target);
+ for (InetAddress ip : ipProbeList) {
+ final int rval = IpNeighborMonitor.startKernelNeighborProbe(mInterfaceParams.index, ip);
mLog.log(String.format("put neighbor %s into NUD_PROBE state (rval=%d)",
- target.getHostAddress(), rval));
+ ip.getHostAddress(), rval));
logEvent(IpReachabilityEvent.PROBE, rval);
}
mLastProbeTimeMs = SystemClock.elapsedRealtime();
@@ -378,22 +371,9 @@
return (numUnicastProbes * retransTimeMs) + gracePeriodMs;
}
- private static int getInterfaceIndex(String ifname) {
- final NetworkInterface iface;
- try {
- iface = NetworkInterface.getByName(ifname);
- } catch (SocketException e) {
- throw new IllegalArgumentException("invalid interface '" + ifname + "': ", e);
- }
- if (iface == null) {
- throw new IllegalArgumentException("NetworkInterface was null for " + ifname);
- }
- return iface.getIndex();
- }
-
private void logEvent(int probeType, int errorCode) {
int eventType = probeType | (errorCode & 0xff);
- mMetricsLog.log(mInterfaceName, new IpReachabilityEvent(eventType));
+ mMetricsLog.log(mInterfaceParams.name, new IpReachabilityEvent(eventType));
}
private void logNudFailed(ProvisioningChange delta) {
@@ -401,6 +381,6 @@
boolean isFromProbe = (duration < getProbeWakeLockDuration());
boolean isProvisioningLost = (delta == ProvisioningChange.LOST_PROVISIONING);
int eventType = IpReachabilityEvent.nudFailureEventType(isFromProbe, isProvisioningLost);
- mMetricsLog.log(mInterfaceName, new IpReachabilityEvent(eventType));
+ mMetricsLog.log(mInterfaceParams.name, new IpReachabilityEvent(eventType));
}
}
diff --git a/services/net/java/android/net/ip/RouterAdvertisementDaemon.java b/services/net/java/android/net/ip/RouterAdvertisementDaemon.java
index cb3123c..49a1e79 100644
--- a/services/net/java/android/net/ip/RouterAdvertisementDaemon.java
+++ b/services/net/java/android/net/ip/RouterAdvertisementDaemon.java
@@ -25,6 +25,7 @@
import android.net.LinkProperties;
import android.net.NetworkUtils;
import android.net.TrafficStats;
+import android.net.util.InterfaceParams;
import android.system.ErrnoException;
import android.system.Os;
import android.system.StructGroupReq;
@@ -96,9 +97,7 @@
(byte) 0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
};
- private final String mIfName;
- private final int mIfIndex;
- private final byte[] mHwAddr;
+ private final InterfaceParams mInterface;
private final InetSocketAddress mAllNodes;
// This lock is to protect the RA from being updated while being
@@ -223,11 +222,9 @@
}
- public RouterAdvertisementDaemon(String ifname, int ifindex, byte[] hwaddr) {
- mIfName = ifname;
- mIfIndex = ifindex;
- mHwAddr = hwaddr;
- mAllNodes = new InetSocketAddress(getAllNodesForScopeId(mIfIndex), 0);
+ public RouterAdvertisementDaemon(InterfaceParams ifParams) {
+ mInterface = ifParams;
+ mAllNodes = new InetSocketAddress(getAllNodesForScopeId(mInterface.index), 0);
mDeprecatedInfoTracker = new DeprecatedInfoTracker();
}
@@ -279,7 +276,7 @@
try {
putHeader(ra, mRaParams != null && mRaParams.hasDefaultRoute);
- putSlla(ra, mHwAddr);
+ putSlla(ra, mInterface.macAddr.toByteArray());
mRaLength = ra.position();
// https://tools.ietf.org/html/rfc5175#section-4 says:
@@ -579,9 +576,9 @@
// Setting SNDTIMEO is purely for defensive purposes.
Os.setsockoptTimeval(
mSocket, SOL_SOCKET, SO_SNDTIMEO, StructTimeval.fromMillis(SEND_TIMEOUT_MS));
- Os.setsockoptIfreq(mSocket, SOL_SOCKET, SO_BINDTODEVICE, mIfName);
+ Os.setsockoptIfreq(mSocket, SOL_SOCKET, SO_BINDTODEVICE, mInterface.name);
NetworkUtils.protectFromVpn(mSocket);
- NetworkUtils.setupRaSocket(mSocket, mIfIndex);
+ NetworkUtils.setupRaSocket(mSocket, mInterface.index);
} catch (ErrnoException | IOException e) {
Log.e(TAG, "Failed to create RA daemon socket: " + e);
return false;
@@ -614,7 +611,7 @@
final InetAddress destip = dest.getAddress();
return (destip instanceof Inet6Address) &&
destip.isLinkLocalAddress() &&
- (((Inet6Address) destip).getScopeId() == mIfIndex);
+ (((Inet6Address) destip).getScopeId() == mInterface.index);
}
private void maybeSendRA(InetSocketAddress dest) {
diff --git a/services/net/java/android/net/util/ConnectivityPacketSummary.java b/services/net/java/android/net/util/ConnectivityPacketSummary.java
index dae93af..4951400 100644
--- a/services/net/java/android/net/util/ConnectivityPacketSummary.java
+++ b/services/net/java/android/net/util/ConnectivityPacketSummary.java
@@ -17,6 +17,7 @@
package android.net.util;
import android.net.dhcp.DhcpPacket;
+import android.net.MacAddress;
import java.net.InetAddress;
import java.net.UnknownHostException;
@@ -45,21 +46,20 @@
private final ByteBuffer mPacket;
private final String mSummary;
- public static String summarize(byte[] hwaddr, byte[] buffer) {
+ public static String summarize(MacAddress hwaddr, byte[] buffer) {
return summarize(hwaddr, buffer, buffer.length);
}
// Methods called herein perform some but by no means all error checking.
// They may throw runtime exceptions on malformed packets.
- public static String summarize(byte[] hwaddr, byte[] buffer, int length) {
- if ((hwaddr == null) || (hwaddr.length != ETHER_ADDR_LEN)) return null;
- if (buffer == null) return null;
+ public static String summarize(MacAddress macAddr, byte[] buffer, int length) {
+ if ((macAddr == null) || (buffer == null)) return null;
length = Math.min(length, buffer.length);
- return (new ConnectivityPacketSummary(hwaddr, buffer, length)).toString();
+ return (new ConnectivityPacketSummary(macAddr, buffer, length)).toString();
}
- private ConnectivityPacketSummary(byte[] hwaddr, byte[] buffer, int length) {
- mHwAddr = hwaddr;
+ private ConnectivityPacketSummary(MacAddress macAddr, byte[] buffer, int length) {
+ mHwAddr = macAddr.toByteArray();
mBytes = buffer;
mLength = Math.min(length, mBytes.length);
mPacket = ByteBuffer.wrap(mBytes, 0, mLength);
diff --git a/services/net/java/android/net/util/InterfaceParams.java b/services/net/java/android/net/util/InterfaceParams.java
new file mode 100644
index 0000000..a4b2fbb
--- /dev/null
+++ b/services/net/java/android/net/util/InterfaceParams.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2017 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 android.net.util;
+
+import static android.net.MacAddress.ALL_ZEROS_ADDRESS;
+import static android.net.util.NetworkConstants.ETHER_MTU;
+import static android.net.util.NetworkConstants.IPV6_MIN_MTU;
+import static com.android.internal.util.Preconditions.checkArgument;
+
+import android.net.MacAddress;
+import android.text.TextUtils;
+
+import java.net.NetworkInterface;
+import java.net.SocketException;
+
+
+/**
+ * Encapsulate the interface parameters common to IpClient/IpServer components.
+ *
+ * Basically all java.net.NetworkInterface methods throw Exceptions. IpClient
+ * and IpServer (sub)components need most or all of this information at some
+ * point during their lifecycles, so pass only this simplified object around
+ * which can be created once when IpClient/IpServer are told to start.
+ *
+ * @hide
+ */
+public class InterfaceParams {
+ public final String name;
+ public final int index;
+ public final MacAddress macAddr;
+ public final int defaultMtu;
+
+ public static InterfaceParams getByName(String name) {
+ final NetworkInterface netif = getNetworkInterfaceByName(name);
+ if (netif == null) return null;
+
+ // Not all interfaces have MAC addresses, e.g. rmnet_data0.
+ final MacAddress macAddr = getMacAddress(netif);
+
+ try {
+ return new InterfaceParams(name, netif.getIndex(), macAddr, netif.getMTU());
+ } catch (IllegalArgumentException|SocketException e) {
+ return null;
+ }
+ }
+
+ public InterfaceParams(String name, int index, MacAddress macAddr) {
+ this(name, index, macAddr, ETHER_MTU);
+ }
+
+ public InterfaceParams(String name, int index, MacAddress macAddr, int defaultMtu) {
+ checkArgument((!TextUtils.isEmpty(name)), "impossible interface name");
+ checkArgument((index > 0), "invalid interface index");
+ this.name = name;
+ this.index = index;
+ this.macAddr = (macAddr != null) ? macAddr : ALL_ZEROS_ADDRESS;
+ this.defaultMtu = (defaultMtu > IPV6_MIN_MTU) ? defaultMtu : IPV6_MIN_MTU;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("%s/%d/%s/%d", name, index, macAddr, defaultMtu);
+ }
+
+ private static NetworkInterface getNetworkInterfaceByName(String name) {
+ try {
+ return NetworkInterface.getByName(name);
+ } catch (NullPointerException|SocketException e) {
+ return null;
+ }
+ }
+
+ private static MacAddress getMacAddress(NetworkInterface netif) {
+ try {
+ return MacAddress.fromBytes(netif.getHardwareAddress());
+ } catch (IllegalArgumentException|NullPointerException|SocketException e) {
+ return null;
+ }
+ }
+}
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index c668100..4a7072d 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -16,6 +16,9 @@
package com.android.server.usb;
+import android.app.ActivityManager;
+import android.app.ActivityManagerInternal;
+import android.app.KeyguardManager;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
@@ -26,6 +29,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.database.ContentObserver;
@@ -38,6 +42,7 @@
import android.hardware.usb.UsbPort;
import android.hardware.usb.UsbPortStatus;
import android.os.BatteryManager;
+import android.os.Environment;
import android.os.FileUtils;
import android.os.Handler;
import android.os.Looper;
@@ -60,6 +65,7 @@
import com.android.internal.os.SomeArgs;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.FgThread;
+import com.android.server.LocalServices;
import java.io.File;
import java.io.FileNotFoundException;
@@ -75,7 +81,7 @@
/**
* UsbDeviceManager manages USB state in device mode.
*/
-public class UsbDeviceManager {
+public class UsbDeviceManager implements ActivityManagerInternal.ScreenObserver {
private static final String TAG = "UsbDeviceManager";
private static final boolean DEBUG = false;
@@ -97,6 +103,12 @@
private static final String USB_STATE_PROPERTY = "sys.usb.state";
/**
+ * The SharedPreference setting per user that stores the screen unlocked functions between
+ * sessions.
+ */
+ private static final String UNLOCKED_CONFIG_PREF = "usb-screen-unlocked-config-%d";
+
+ /**
* ro.bootmode value when phone boots into usual Android.
*/
private static final String NORMAL_BOOT = "normal";
@@ -128,6 +140,8 @@
private static final int MSG_UPDATE_CHARGING_STATE = 9;
private static final int MSG_UPDATE_HOST_STATE = 10;
private static final int MSG_LOCALE_CHANGED = 11;
+ private static final int MSG_SET_SCREEN_UNLOCKED_FUNCTIONS = 12;
+ private static final int MSG_UPDATE_SCREEN_LOCK = 13;
private static final int AUDIO_MODE_SOURCE = 1;
@@ -169,6 +183,7 @@
private Intent mBroadcastedIntent;
private boolean mPendingBootBroadcast;
private static Set<Integer> sBlackListedInterfaces;
+ private SharedPreferences mSettings;
static {
sBlackListedInterfaces = new HashSet<>();
@@ -217,6 +232,31 @@
}
};
+ @Override
+ public void onKeyguardStateChanged(boolean isShowing) {
+ int userHandle = ActivityManager.getCurrentUser();
+ boolean secure = mContext.getSystemService(KeyguardManager.class)
+ .isDeviceSecure(userHandle);
+ boolean unlocking = mContext.getSystemService(UserManager.class)
+ .isUserUnlockingOrUnlocked(userHandle);
+ if (DEBUG) {
+ Slog.v(TAG, "onKeyguardStateChanged: isShowing:" + isShowing + " secure:" + secure
+ + " unlocking:" + unlocking + " user:" + userHandle);
+ }
+ // We are unlocked when the keyguard is down or non-secure, and user storage is unlocked.
+ mHandler.sendMessage(MSG_UPDATE_SCREEN_LOCK, (isShowing && secure) || !unlocking);
+ }
+
+ @Override
+ public void onAwakeStateChanged(boolean isAwake) {
+ // ignore
+ }
+
+ /** Called when a user is unlocked. */
+ public void onUnlockUser(int userHandle) {
+ onKeyguardStateChanged(false);
+ }
+
public UsbDeviceManager(Context context, UsbAlsaManager alsaManager,
UsbSettingsManager settingsManager) {
mContext = context;
@@ -303,6 +343,8 @@
public void systemReady() {
if (DEBUG) Slog.d(TAG, "systemReady");
+ LocalServices.getService(ActivityManagerInternal.class).registerScreenObserver(this);
+
mNotificationManager = (NotificationManager)
mContext.getSystemService(Context.NOTIFICATION_SERVICE);
@@ -407,6 +449,14 @@
return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK);
}
+ private SharedPreferences getPinnedSharedPrefs(Context context) {
+ final File prefsFile = new File(new File(
+ Environment.getDataUserCePackageDirectory(StorageManager.UUID_PRIVATE_INTERNAL,
+ context.getUserId(), context.getPackageName()), "shared_prefs"),
+ UsbDeviceManager.class.getSimpleName() + ".xml");
+ return context.getSharedPreferences(prefsFile, Context.MODE_PRIVATE);
+ }
+
private final class UsbHandler extends Handler {
// current USB state
@@ -423,17 +473,21 @@
private UsbAccessory mCurrentAccessory;
private int mUsbNotificationId;
private boolean mAdbNotificationShown;
- private int mCurrentUser = UserHandle.USER_NULL;
+ private int mCurrentUser;
private boolean mUsbCharging;
private String mCurrentOemFunctions;
private boolean mHideUsbNotification;
private boolean mSupportsAllCombinations;
+ private String mScreenUnlockedFunctions = UsbManager.USB_FUNCTION_NONE;
+ private boolean mScreenLocked;
public UsbHandler(Looper looper) {
super(looper);
try {
// Restore default functions.
+ mCurrentOemFunctions = SystemProperties.get(UsbDeviceManager.getPersistProp(false),
+ UsbManager.USB_FUNCTION_NONE);
if (isNormalBoot()) {
mCurrentFunctions = SystemProperties.get(USB_CONFIG_PROPERTY,
UsbManager.USB_FUNCTION_NONE);
@@ -447,6 +501,9 @@
SystemProperties.get(USB_STATE_PROPERTY));
}
+ mCurrentUser = ActivityManager.getCurrentUser();
+ mScreenLocked = true;
+
/*
* Use the normal bootmode persistent prop to maintain state of adb across
* all boot modes.
@@ -651,7 +708,7 @@
private boolean trySetEnabledFunctions(String functions, boolean forceRestart) {
if (functions == null || applyAdbFunction(functions)
.equals(UsbManager.USB_FUNCTION_NONE)) {
- functions = getDefaultFunctions();
+ functions = getChargingFunctions();
}
functions = applyAdbFunction(functions);
@@ -662,8 +719,7 @@
}
if ((!functions.equals(oemFunctions) &&
- (mCurrentOemFunctions == null ||
- !mCurrentOemFunctions.equals(oemFunctions)))
+ !mCurrentOemFunctions.equals(oemFunctions))
|| !mCurrentFunctions.equals(functions)
|| !mCurrentFunctionsApplied
|| forceRestart) {
@@ -875,6 +931,14 @@
mMidiEnabled && mConfigured, mMidiCard, mMidiDevice);
}
+ private void setScreenUnlockedFunctions() {
+ setEnabledFunctions(mScreenUnlockedFunctions, false,
+ UsbManager.containsFunction(mScreenUnlockedFunctions,
+ UsbManager.USB_FUNCTION_MTP)
+ || UsbManager.containsFunction(mScreenUnlockedFunctions,
+ UsbManager.USB_FUNCTION_PTP));
+ }
+
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
@@ -894,7 +958,13 @@
if (mBootCompleted) {
if (!mConnected && !hasMessages(MSG_ACCESSORY_MODE_ENTER_TIMEOUT)) {
// restore defaults when USB is disconnected
- setEnabledFunctions(null, !mAdbEnabled, false);
+ if (!mScreenLocked
+ && !UsbManager.USB_FUNCTION_NONE.equals(
+ mScreenUnlockedFunctions)) {
+ setScreenUnlockedFunctions();
+ } else {
+ setEnabledFunctions(null, !mAdbEnabled, false);
+ }
}
updateUsbFunctions();
} else {
@@ -977,6 +1047,47 @@
String functions = (String) msg.obj;
setEnabledFunctions(functions, false, msg.arg1 == 1);
break;
+ case MSG_SET_SCREEN_UNLOCKED_FUNCTIONS:
+ mScreenUnlockedFunctions = (String) msg.obj;
+ SharedPreferences.Editor editor = mSettings.edit();
+ editor.putString(String.format(Locale.ENGLISH, UNLOCKED_CONFIG_PREF,
+ mCurrentUser), mScreenUnlockedFunctions);
+ editor.commit();
+ if (!mScreenLocked && !UsbManager.USB_FUNCTION_NONE.equals(
+ mScreenUnlockedFunctions)) {
+ // If the screen is unlocked, also set current functions.
+ setScreenUnlockedFunctions();
+ }
+ break;
+ case MSG_UPDATE_SCREEN_LOCK:
+ if (msg.arg1 == 1 == mScreenLocked) {
+ break;
+ }
+ mScreenLocked = msg.arg1 == 1;
+ if (mSettings == null && !mScreenLocked) {
+ // Shared preferences aren't accessible until the user has been unlocked.
+ mSettings = getPinnedSharedPrefs(mContext);
+ mScreenUnlockedFunctions = mSettings.getString(
+ String.format(Locale.ENGLISH, UNLOCKED_CONFIG_PREF, mCurrentUser),
+ UsbManager.USB_FUNCTION_NONE);
+ }
+ if (!mBootCompleted) {
+ break;
+ }
+ if (mScreenLocked) {
+ if (!mConnected) {
+ setEnabledFunctions(null, false, false);
+ }
+ } else {
+ if (!UsbManager.USB_FUNCTION_NONE.equals(mScreenUnlockedFunctions)
+ && (UsbManager.USB_FUNCTION_ADB.equals(mCurrentFunctions)
+ || (UsbManager.USB_FUNCTION_MTP.equals(mCurrentFunctions)
+ && !mUsbDataUnlocked))) {
+ // Set the screen unlocked functions if current function is charging.
+ setScreenUnlockedFunctions();
+ }
+ }
+ break;
case MSG_UPDATE_USER_RESTRICTIONS:
// Restart the USB stack if USB transfer is enabled but no longer allowed.
final boolean forceRestart = mUsbDataUnlocked
@@ -1000,7 +1111,13 @@
updateUsbStateBroadcastIfNeeded(false);
mPendingBootBroadcast = false;
}
- setEnabledFunctions(null, false, false);
+
+ if (!mScreenLocked
+ && !UsbManager.USB_FUNCTION_NONE.equals(mScreenUnlockedFunctions)) {
+ setScreenUnlockedFunctions();
+ } else {
+ setEnabledFunctions(null, false, false);
+ }
if (mCurrentAccessory != null) {
getCurrentSettings().accessoryAttached(mCurrentAccessory);
}
@@ -1010,16 +1127,15 @@
break;
case MSG_USER_SWITCHED: {
if (mCurrentUser != msg.arg1) {
- // Restart the USB stack and re-apply user restrictions for MTP or PTP.
- if (mUsbDataUnlocked
- && isUsbDataTransferActive()
- && mCurrentUser != UserHandle.USER_NULL) {
- Slog.v(TAG, "Current user switched to " + msg.arg1
- + "; resetting USB host stack for MTP or PTP");
- // avoid leaking sensitive data from previous user
- setEnabledFunctions(null, true, false);
+ if (DEBUG) {
+ Slog.v(TAG, "Current user switched to " + msg.arg1);
}
mCurrentUser = msg.arg1;
+ mScreenLocked = true;
+ mScreenUnlockedFunctions = mSettings.getString(
+ String.format(Locale.ENGLISH, UNLOCKED_CONFIG_PREF, mCurrentUser),
+ UsbManager.USB_FUNCTION_NONE);
+ setEnabledFunctions(null, false, false);
}
break;
}
@@ -1071,20 +1187,12 @@
titleRes = com.android.internal.R.string.usb_unsupported_audio_accessory_title;
id = SystemMessage.NOTE_USB_AUDIO_ACCESSORY_NOT_SUPPORTED;
} else if (mConnected) {
- if (!mUsbDataUnlocked) {
- if (mSourcePower) {
- titleRes = com.android.internal.R.string.usb_supplying_notification_title;
- id = SystemMessage.NOTE_USB_SUPPLYING;
- } else {
- titleRes = com.android.internal.R.string.usb_charging_notification_title;
- id = SystemMessage.NOTE_USB_CHARGING;
- }
- } else if (UsbManager.containsFunction(mCurrentFunctions,
- UsbManager.USB_FUNCTION_MTP)) {
+ if (UsbManager.containsFunction(mCurrentFunctions,
+ UsbManager.USB_FUNCTION_MTP) && mUsbDataUnlocked) {
titleRes = com.android.internal.R.string.usb_mtp_notification_title;
id = SystemMessage.NOTE_USB_MTP;
} else if (UsbManager.containsFunction(mCurrentFunctions,
- UsbManager.USB_FUNCTION_PTP)) {
+ UsbManager.USB_FUNCTION_PTP) && mUsbDataUnlocked) {
titleRes = com.android.internal.R.string.usb_ptp_notification_title;
id = SystemMessage.NOTE_USB_PTP;
} else if (UsbManager.containsFunction(mCurrentFunctions,
@@ -1235,7 +1343,7 @@
}
}
- private String getDefaultFunctions() {
+ private String getChargingFunctions() {
String func = SystemProperties.get(getPersistProp(true),
UsbManager.USB_FUNCTION_NONE);
// if ADB is enabled, reset functions to ADB
@@ -1252,6 +1360,8 @@
pw.println(" mCurrentFunctions: " + mCurrentFunctions);
pw.println(" mCurrentOemFunctions: " + mCurrentOemFunctions);
pw.println(" mCurrentFunctionsApplied: " + mCurrentFunctionsApplied);
+ pw.println(" mScreenUnlockedFunctions: " + mScreenUnlockedFunctions);
+ pw.println(" mScreenLocked: " + mScreenLocked);
pw.println(" mConnected: " + mConnected);
pw.println(" mConfigured: " + mConfigured);
pw.println(" mUsbDataUnlocked: " + mUsbDataUnlocked);
@@ -1308,6 +1418,17 @@
mHandler.sendMessage(MSG_SET_CURRENT_FUNCTIONS, functions, usbDataUnlocked);
}
+ /**
+ * Sets the functions which are set when the screen is unlocked.
+ * @param functions Functions to set.
+ */
+ public void setScreenUnlockedFunctions(String functions) {
+ if (DEBUG) {
+ Slog.d(TAG, "setScreenUnlockedFunctions(" + functions + ")");
+ }
+ mHandler.sendMessage(MSG_SET_SCREEN_UNLOCKED_FUNCTIONS, functions);
+ }
+
private void readOemUsbOverrideConfig() {
String[] configList = mContext.getResources().getStringArray(
com.android.internal.R.array.config_oemUsbModeOverride);
diff --git a/services/usb/java/com/android/server/usb/UsbService.java b/services/usb/java/com/android/server/usb/UsbService.java
index e4fcea7..039597c 100644
--- a/services/usb/java/com/android/server/usb/UsbService.java
+++ b/services/usb/java/com/android/server/usb/UsbService.java
@@ -87,6 +87,11 @@
public void onStopUser(int userHandle) {
mUsbService.onStopUser(UserHandle.of(userHandle));
}
+
+ @Override
+ public void onUnlockUser(int userHandle) {
+ mUsbService.onUnlockUser(userHandle);
+ }
}
private static final String TAG = "UsbService";
@@ -205,6 +210,13 @@
}
}
+ /** Called when a user is unlocked. */
+ public void onUnlockUser(int user) {
+ if (mDeviceManager != null) {
+ mDeviceManager.onUnlockUser(user);
+ }
+ }
+
/* Returns a list of all currently attached USB devices (host mdoe) */
@Override
public void getDeviceList(Bundle devices) {
@@ -389,6 +401,23 @@
}
}
+ @Override
+ public void setScreenUnlockedFunctions(String function) {
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
+
+ if (!isSupportedCurrentFunction(function)) {
+ Slog.w(TAG, "Caller of setScreenUnlockedFunctions() requested unsupported USB function:"
+ + function);
+ function = UsbManager.USB_FUNCTION_NONE;
+ }
+
+ if (mDeviceManager != null) {
+ mDeviceManager.setScreenUnlockedFunctions(function);
+ } else {
+ throw new IllegalStateException("USB device mode not supported");
+ }
+ }
+
private static boolean isSupportedCurrentFunction(String function) {
if (function == null) return true;
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index 2091101..8c7d6b3 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -1408,7 +1408,7 @@
* @param extras Bundle containing extra information associated with the event.
*/
public void sendCallEvent(String event, Bundle extras) {
- mInCallAdapter.sendCallEvent(mTelecomCallId, event, extras);
+ mInCallAdapter.sendCallEvent(mTelecomCallId, event, mTargetSdkVersion, extras);
}
/**
diff --git a/telecomm/java/android/telecom/InCallAdapter.java b/telecomm/java/android/telecom/InCallAdapter.java
index 4bc2a9b..658685f 100644
--- a/telecomm/java/android/telecom/InCallAdapter.java
+++ b/telecomm/java/android/telecom/InCallAdapter.java
@@ -286,11 +286,12 @@
*
* @param callId The callId to send the event for.
* @param event The event.
+ * @param targetSdkVer Target sdk version of the app calling this api
* @param extras Extras associated with the event.
*/
- public void sendCallEvent(String callId, String event, Bundle extras) {
+ public void sendCallEvent(String callId, String event, int targetSdkVer, Bundle extras) {
try {
- mAdapter.sendCallEvent(callId, event, extras);
+ mAdapter.sendCallEvent(callId, event, targetSdkVer, extras);
} catch (RemoteException ignored) {
}
}
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index a9bbd24..96c6e0a 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -24,6 +24,7 @@
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
+import android.os.Build;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -236,6 +237,15 @@
"android.telecom.extra.INCOMING_CALL_EXTRAS";
/**
+ * Optional extra for {@link #ACTION_INCOMING_CALL} containing a boolean to indicate that the
+ * call has an externally generated ringer. Used by the HfpClientConnectionService when In Band
+ * Ringtone is enabled to prevent two ringers from being generated.
+ * @hide
+ */
+ public static final String EXTRA_CALL_EXTERNAL_RINGER =
+ "android.telecom.extra.CALL_EXTERNAL_RINGER";
+
+ /**
* Optional extra for {@link android.content.Intent#ACTION_CALL} and
* {@link android.content.Intent#ACTION_DIAL} {@code Intent} containing a {@link Bundle}
* which contains metadata about the call. This {@link Bundle} will be saved into
@@ -1423,6 +1433,13 @@
public void addNewIncomingCall(PhoneAccountHandle phoneAccount, Bundle extras) {
try {
if (isServiceConnected()) {
+ if (extras != null && extras.getBoolean(EXTRA_IS_HANDOVER) &&
+ mContext.getApplicationContext().getApplicationInfo().targetSdkVersion >
+ Build.VERSION_CODES.O_MR1) {
+ Log.e("TAG", "addNewIncomingCall failed. Use public api " +
+ "acceptHandover for API > O-MR1");
+ // TODO add "return" after DUO team adds support for new handover API
+ }
getTelecomService().addNewIncomingCall(
phoneAccount, extras == null ? new Bundle() : extras);
}
diff --git a/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl b/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl
index 23ac940..87ccd3e 100644
--- a/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl
+++ b/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl
@@ -64,7 +64,7 @@
void pullExternalCall(String callId);
- void sendCallEvent(String callId, String event, in Bundle extras);
+ void sendCallEvent(String callId, String event, int targetSdkVer, in Bundle extras);
void putExtras(String callId, in Bundle extras);
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 0a8d9cb..0c05a02 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -950,8 +950,9 @@
public static final String KEY_CARRIER_NAME_OVERRIDE_BOOL = "carrier_name_override_bool";
/**
- * String to identify carrier name in CarrierConfig app. This string is used only if
- * #KEY_CARRIER_NAME_OVERRIDE_BOOL is true
+ * String to identify carrier name in CarrierConfig app. This string overrides SPN if
+ * #KEY_CARRIER_NAME_OVERRIDE_BOOL is true; otherwise, it will be used if its value is provided
+ * and SPN is unavailable
* @hide
*/
public static final String KEY_CARRIER_NAME_STRING = "carrier_name_string";
@@ -1006,6 +1007,13 @@
public static final String KEY_ALWAYS_SHOW_DATA_RAT_ICON_BOOL =
"always_show_data_rat_icon_bool";
+ /**
+ * Boolean to decide whether to show precise call failed cause to user
+ * @hide
+ */
+ public static final String KEY_SHOW_PRECISE_FAILED_CAUSE_BOOL =
+ "show_precise_failed_cause_bool";
+
// These variables are used by the MMS service and exposed through another API, {@link
// SmsManager}. The variable names and string values are copied from there.
public static final String KEY_MMS_ALIAS_ENABLED_BOOL = "aliasEnabled";
@@ -2012,6 +2020,7 @@
sDefaults.putBoolean(KEY_DISABLE_CHARGE_INDICATION_BOOL, false);
sDefaults.putStringArray(KEY_FEATURE_ACCESS_CODES_STRING_ARRAY, null);
sDefaults.putBoolean(KEY_IDENTIFY_HIGH_DEFINITION_CALLS_IN_CALL_LOG_BOOL, false);
+ sDefaults.putBoolean(KEY_SHOW_PRECISE_FAILED_CAUSE_BOOL, false);
sDefaults.putBoolean(KEY_SPN_DISPLAY_RULE_USE_ROAMING_FROM_SERVICE_STATE_BOOL, false);
sDefaults.putBoolean(KEY_ALWAYS_SHOW_DATA_RAT_ICON_BOOL, false);
sDefaults.putBoolean(KEY_CARRIER_CONFIG_APPLIED_BOOL, false);
diff --git a/telephony/java/android/telephony/data/InterfaceAddress.aidl b/telephony/java/android/telephony/CellIdentity.aidl
similarity index 90%
copy from telephony/java/android/telephony/data/InterfaceAddress.aidl
copy to telephony/java/android/telephony/CellIdentity.aidl
index d750363..aeee769 100644
--- a/telephony/java/android/telephony/data/InterfaceAddress.aidl
+++ b/telephony/java/android/telephony/CellIdentity.aidl
@@ -15,6 +15,6 @@
*/
/** @hide */
-package android.telephony.data;
+package android.telephony;
-parcelable InterfaceAddress;
+parcelable CellIdentity;
diff --git a/telephony/java/android/telephony/CellIdentity.java b/telephony/java/android/telephony/CellIdentity.java
new file mode 100644
index 0000000..e092d52
--- /dev/null
+++ b/telephony/java/android/telephony/CellIdentity.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright 2017 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 android.telephony;
+
+import android.annotation.CallSuper;
+import android.annotation.IntDef;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * CellIdentity represents the identity of a unique cell. This is the base class for
+ * CellIdentityXxx which represents cell identity for specific network access technology.
+ */
+public abstract class CellIdentity implements Parcelable {
+ /**
+ * Cell identity type
+ * @hide
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = "TYPE_", value = {TYPE_GSM, TYPE_CDMA, TYPE_LTE, TYPE_WCDMA, TYPE_TDSCDMA})
+ public @interface Type {}
+
+ /**
+ * Unknown cell identity type
+ * @hide
+ */
+ public static final int TYPE_UNKNOWN = 0;
+ /**
+ * GSM cell identity type
+ * @hide
+ */
+ public static final int TYPE_GSM = 1;
+ /**
+ * CDMA cell identity type
+ * @hide
+ */
+ public static final int TYPE_CDMA = 2;
+ /**
+ * LTE cell identity type
+ * @hide
+ */
+ public static final int TYPE_LTE = 3;
+ /**
+ * WCDMA cell identity type
+ * @hide
+ */
+ public static final int TYPE_WCDMA = 4;
+ /**
+ * TDS-CDMA cell identity type
+ * @hide
+ */
+ public static final int TYPE_TDSCDMA = 5;
+
+ // Log tag
+ /** @hide */
+ protected final String mTag;
+ // Cell identity type
+ /** @hide */
+ protected final int mType;
+ // 3-digit Mobile Country Code in string format. Null for CDMA cell identity.
+ /** @hide */
+ protected final String mMccStr;
+ // 2 or 3-digit Mobile Network Code in string format. Null for CDMA cell identity.
+ /** @hide */
+ protected final String mMncStr;
+
+ /** @hide */
+ protected CellIdentity(String tag, int type, String mcc, String mnc) {
+ mTag = tag;
+ mType = type;
+
+ // Only allow INT_MAX if unknown string mcc/mnc
+ if (mcc == null || mcc.matches("^[0-9]{3}$")) {
+ mMccStr = mcc;
+ } else if (mcc.isEmpty() || mcc.equals(String.valueOf(Integer.MAX_VALUE))) {
+ // If the mccStr is empty or unknown, set it as null.
+ mMccStr = null;
+ } else {
+ // TODO: b/69384059 Should throw IllegalArgumentException for the invalid MCC format
+ // after the bug got fixed.
+ mMccStr = null;
+ log("invalid MCC format: " + mcc);
+ }
+
+ if (mnc == null || mnc.matches("^[0-9]{2,3}$")) {
+ mMncStr = mnc;
+ } else if (mnc.isEmpty() || mnc.equals(String.valueOf(Integer.MAX_VALUE))) {
+ // If the mncStr is empty or unknown, set it as null.
+ mMncStr = null;
+ } else {
+ // TODO: b/69384059 Should throw IllegalArgumentException for the invalid MNC format
+ // after the bug got fixed.
+ mMncStr = null;
+ log("invalid MNC format: " + mnc);
+ }
+ }
+
+ /** Implement the Parcelable interface */
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ /**
+ * @hide
+ * @return The type of the cell identity
+ */
+ public @Type int getType() { return mType; }
+
+ /**
+ * Used by child classes for parceling.
+ *
+ * @hide
+ */
+ @CallSuper
+ public void writeToParcel(Parcel dest, int type) {
+ dest.writeInt(type);
+ dest.writeString(mMccStr);
+ dest.writeString(mMncStr);
+ }
+
+ /**
+ * Construct from Parcel
+ * @hide
+ */
+ protected CellIdentity(String tag, int type, Parcel source) {
+ this(tag, type, source.readString(), source.readString());
+ }
+
+ /** Implement the Parcelable interface */
+ public static final Creator<CellIdentity> CREATOR =
+ new Creator<CellIdentity>() {
+ @Override
+ public CellIdentity createFromParcel(Parcel in) {
+ int type = in.readInt();
+ switch (type) {
+ case TYPE_GSM: return CellIdentityGsm.createFromParcelBody(in);
+ case TYPE_WCDMA: return CellIdentityWcdma.createFromParcelBody(in);
+ case TYPE_CDMA: return CellIdentityCdma.createFromParcelBody(in);
+ case TYPE_LTE: return CellIdentityLte.createFromParcelBody(in);
+ case TYPE_TDSCDMA: return CellIdentityTdscdma.createFromParcelBody(in);
+ default: throw new IllegalArgumentException("Bad Cell identity Parcel");
+ }
+ }
+
+ @Override
+ public CellIdentity[] newArray(int size) {
+ return new CellIdentity[size];
+ }
+ };
+
+ /** @hide */
+ protected void log(String s) {
+ Rlog.w(mTag, s);
+ }
+}
\ No newline at end of file
diff --git a/telephony/java/android/telephony/CellIdentityCdma.java b/telephony/java/android/telephony/CellIdentityCdma.java
index ddc938e..2e1d1dc 100644
--- a/telephony/java/android/telephony/CellIdentityCdma.java
+++ b/telephony/java/android/telephony/CellIdentityCdma.java
@@ -17,8 +17,6 @@
package android.telephony;
import android.os.Parcel;
-import android.os.Parcelable;
-import android.telephony.Rlog;
import android.text.TextUtils;
import java.util.Objects;
@@ -26,9 +24,8 @@
/**
* CellIdentity is to represent a unique CDMA cell
*/
-public final class CellIdentityCdma implements Parcelable {
-
- private static final String LOG_TAG = "CellSignalStrengthCdma";
+public final class CellIdentityCdma extends CellIdentity {
+ private static final String TAG = CellIdentityCdma.class.getSimpleName();
private static final boolean DBG = false;
// Network Id 0..65535
@@ -60,6 +57,7 @@
* @hide
*/
public CellIdentityCdma() {
+ super(TAG, TYPE_CDMA, null, null);
mNetworkId = Integer.MAX_VALUE;
mSystemId = Integer.MAX_VALUE;
mBasestationId = Integer.MAX_VALUE;
@@ -81,7 +79,7 @@
*
* @hide
*/
- public CellIdentityCdma (int nid, int sid, int bid, int lon, int lat) {
+ public CellIdentityCdma(int nid, int sid, int bid, int lon, int lat) {
this(nid, sid, bid, lon, lat, null, null);
}
@@ -99,8 +97,9 @@
*
* @hide
*/
- public CellIdentityCdma (int nid, int sid, int bid, int lon, int lat, String alphal,
+ public CellIdentityCdma(int nid, int sid, int bid, int lon, int lat, String alphal,
String alphas) {
+ super(TAG, TYPE_CDMA, null, null);
mNetworkId = nid;
mSystemId = sid;
mBasestationId = bid;
@@ -196,40 +195,33 @@
CellIdentityCdma o = (CellIdentityCdma) other;
- return mNetworkId == o.mNetworkId &&
- mSystemId == o.mSystemId &&
- mBasestationId == o.mBasestationId &&
- mLatitude == o.mLatitude &&
- mLongitude == o.mLongitude &&
- TextUtils.equals(mAlphaLong, o.mAlphaLong) &&
- TextUtils.equals(mAlphaShort, o.mAlphaShort);
+ return mNetworkId == o.mNetworkId
+ && mSystemId == o.mSystemId
+ && mBasestationId == o.mBasestationId
+ && mLatitude == o.mLatitude
+ && mLongitude == o.mLongitude
+ && TextUtils.equals(mAlphaLong, o.mAlphaLong)
+ && TextUtils.equals(mAlphaShort, o.mAlphaShort);
}
@Override
public String toString() {
- StringBuilder sb = new StringBuilder("CellIdentityCdma:{");
- sb.append(" mNetworkId="); sb.append(mNetworkId);
- sb.append(" mSystemId="); sb.append(mSystemId);
- sb.append(" mBasestationId="); sb.append(mBasestationId);
- sb.append(" mLongitude="); sb.append(mLongitude);
- sb.append(" mLatitude="); sb.append(mLatitude);
- sb.append(" mAlphaLong="); sb.append(mAlphaLong);
- sb.append(" mAlphaShort="); sb.append(mAlphaShort);
- sb.append("}");
-
- return sb.toString();
- }
-
- /** Implement the Parcelable interface */
- @Override
- public int describeContents() {
- return 0;
+ return new StringBuilder(TAG)
+ .append(":{ mNetworkId=").append(mNetworkId)
+ .append(" mSystemId=").append(mSystemId)
+ .append(" mBasestationId=").append(mBasestationId)
+ .append(" mLongitude=").append(mLongitude)
+ .append(" mLatitude=").append(mLatitude)
+ .append(" mAlphaLong=").append(mAlphaLong)
+ .append(" mAlphaShort=").append(mAlphaShort)
+ .append("}").toString();
}
/** Implement the Parcelable interface */
@Override
public void writeToParcel(Parcel dest, int flags) {
if (DBG) log("writeToParcel(Parcel, int): " + toString());
+ super.writeToParcel(dest, TYPE_CDMA);
dest.writeInt(mNetworkId);
dest.writeInt(mSystemId);
dest.writeInt(mBasestationId);
@@ -241,10 +233,16 @@
/** Construct from Parcel, type has already been processed */
private CellIdentityCdma(Parcel in) {
- this(in.readInt(), in.readInt(), in.readInt(), in.readInt(), in.readInt(),
- in.readString(), in.readString());
+ super(TAG, TYPE_CDMA, in);
+ mNetworkId = in.readInt();
+ mSystemId = in.readInt();
+ mBasestationId = in.readInt();
+ mLongitude = in.readInt();
+ mLatitude = in.readInt();
+ mAlphaLong = in.readString();
+ mAlphaShort = in.readString();
- if (DBG) log("CellIdentityCdma(Parcel): " + toString());
+ if (DBG) log(toString());
}
/** Implement the Parcelable interface */
@@ -253,7 +251,8 @@
new Creator<CellIdentityCdma>() {
@Override
public CellIdentityCdma createFromParcel(Parcel in) {
- return new CellIdentityCdma(in);
+ in.readInt(); // skip
+ return createFromParcelBody(in);
}
@Override
@@ -262,10 +261,8 @@
}
};
- /**
- * log
- */
- private static void log(String s) {
- Rlog.w(LOG_TAG, s);
+ /** @hide */
+ protected static CellIdentityCdma createFromParcelBody(Parcel in) {
+ return new CellIdentityCdma(in);
}
}
diff --git a/telephony/java/android/telephony/CellIdentityGsm.java b/telephony/java/android/telephony/CellIdentityGsm.java
index 376e6aa..f948f81 100644
--- a/telephony/java/android/telephony/CellIdentityGsm.java
+++ b/telephony/java/android/telephony/CellIdentityGsm.java
@@ -17,8 +17,6 @@
package android.telephony;
import android.os.Parcel;
-import android.os.Parcelable;
-import android.telephony.Rlog;
import android.text.TextUtils;
import java.util.Objects;
@@ -26,9 +24,8 @@
/**
* CellIdentity to represent a unique GSM cell
*/
-public final class CellIdentityGsm implements Parcelable {
-
- private static final String LOG_TAG = "CellIdentityGsm";
+public final class CellIdentityGsm extends CellIdentity {
+ private static final String TAG = CellIdentityGsm.class.getSimpleName();
private static final boolean DBG = false;
// 16-bit Location Area Code, 0..65535
@@ -39,10 +36,6 @@
private final int mArfcn;
// 6-bit Base Station Identity Code
private final int mBsic;
- // 3-digit Mobile Country Code in string format
- private final String mMccStr;
- // 2 or 3-digit Mobile Network Code in string format
- private final String mMncStr;
// long alpha Operator Name String or Enhanced Operator Name String
private final String mAlphaLong;
// short alpha Operator Name String or Enhanced Operator Name String
@@ -52,12 +45,11 @@
* @hide
*/
public CellIdentityGsm() {
+ super(TAG, TYPE_GSM, null, null);
mLac = Integer.MAX_VALUE;
mCid = Integer.MAX_VALUE;
mArfcn = Integer.MAX_VALUE;
mBsic = Integer.MAX_VALUE;
- mMccStr = null;
- mMncStr = null;
mAlphaLong = null;
mAlphaShort = null;
}
@@ -70,7 +62,7 @@
*
* @hide
*/
- public CellIdentityGsm (int mcc, int mnc, int lac, int cid) {
+ public CellIdentityGsm(int mcc, int mnc, int lac, int cid) {
this(lac, cid, Integer.MAX_VALUE, Integer.MAX_VALUE,
String.valueOf(mcc), String.valueOf(mnc), null, null);
}
@@ -86,7 +78,7 @@
*
* @hide
*/
- public CellIdentityGsm (int mcc, int mnc, int lac, int cid, int arfcn, int bsic) {
+ public CellIdentityGsm(int mcc, int mnc, int lac, int cid, int arfcn, int bsic) {
this(lac, cid, arfcn, bsic, String.valueOf(mcc), String.valueOf(mnc), null, null);
}
@@ -103,8 +95,9 @@
*
* @hide
*/
- public CellIdentityGsm (int lac, int cid, int arfcn, int bsic, String mccStr,
+ public CellIdentityGsm(int lac, int cid, int arfcn, int bsic, String mccStr,
String mncStr, String alphal, String alphas) {
+ super(TAG, TYPE_GSM, mccStr, mncStr);
mLac = lac;
mCid = cid;
mArfcn = arfcn;
@@ -112,31 +105,6 @@
// for inbound parcels
mBsic = (bsic == 0xFF) ? Integer.MAX_VALUE : bsic;
- // Only allow INT_MAX if unknown string mcc/mnc
- if (mccStr == null || mccStr.matches("^[0-9]{3}$")) {
- mMccStr = mccStr;
- } else if (mccStr.isEmpty() || mccStr.equals(String.valueOf(Integer.MAX_VALUE))) {
- // If the mccStr is empty or unknown, set it as null.
- mMccStr = null;
- } else {
- // TODO: b/69384059 Should throw IllegalArgumentException for the invalid MCC format
- // after the bug got fixed.
- mMccStr = null;
- log("invalid MCC format: " + mccStr);
- }
-
- if (mncStr == null || mncStr.matches("^[0-9]{2,3}$")) {
- mMncStr = mncStr;
- } else if (mncStr.isEmpty() || mncStr.equals(String.valueOf(Integer.MAX_VALUE))) {
- // If the mncStr is empty or unknown, set it as null.
- mMncStr = null;
- } else {
- // TODO: b/69384059 Should throw IllegalArgumentException for the invalid MNC format
- // after the bug got fixed.
- mMncStr = null;
- log("invalid MNC format: " + mncStr);
- }
-
mAlphaLong = alphal;
mAlphaShort = alphas;
}
@@ -237,6 +205,7 @@
/**
+ * @deprecated Primary Scrambling Code is not applicable to GSM.
* @return Integer.MAX_VALUE, undefined for GSM
*/
@Deprecated
@@ -260,58 +229,54 @@
}
CellIdentityGsm o = (CellIdentityGsm) other;
- return mLac == o.mLac &&
- mCid == o.mCid &&
- mArfcn == o.mArfcn &&
- mBsic == o.mBsic &&
- TextUtils.equals(mMccStr, o.mMccStr) &&
- TextUtils.equals(mMncStr, o.mMncStr) &&
- TextUtils.equals(mAlphaLong, o.mAlphaLong) &&
- TextUtils.equals(mAlphaShort, o.mAlphaShort);
+ return mLac == o.mLac
+ && mCid == o.mCid
+ && mArfcn == o.mArfcn
+ && mBsic == o.mBsic
+ && TextUtils.equals(mMccStr, o.mMccStr)
+ && TextUtils.equals(mMncStr, o.mMncStr)
+ && TextUtils.equals(mAlphaLong, o.mAlphaLong)
+ && TextUtils.equals(mAlphaShort, o.mAlphaShort);
}
@Override
public String toString() {
- StringBuilder sb = new StringBuilder("CellIdentityGsm:{");
- sb.append(" mLac=").append(mLac);
- sb.append(" mCid=").append(mCid);
- sb.append(" mArfcn=").append(mArfcn);
- sb.append(" mBsic=").append("0x").append(Integer.toHexString(mBsic));
- sb.append(" mMcc=").append(mMccStr);
- sb.append(" mMnc=").append(mMncStr);
- sb.append(" mAlphaLong=").append(mAlphaLong);
- sb.append(" mAlphaShort=").append(mAlphaShort);
- sb.append("}");
-
- return sb.toString();
- }
-
- /** Implement the Parcelable interface */
- @Override
- public int describeContents() {
- return 0;
+ return new StringBuilder(TAG)
+ .append(":{ mLac=").append(mLac)
+ .append(" mCid=").append(mCid)
+ .append(" mArfcn=").append(mArfcn)
+ .append(" mBsic=").append("0x").append(Integer.toHexString(mBsic))
+ .append(" mMcc=").append(mMccStr)
+ .append(" mMnc=").append(mMncStr)
+ .append(" mAlphaLong=").append(mAlphaLong)
+ .append(" mAlphaShort=").append(mAlphaShort)
+ .append("}").toString();
}
/** Implement the Parcelable interface */
@Override
public void writeToParcel(Parcel dest, int flags) {
if (DBG) log("writeToParcel(Parcel, int): " + toString());
+ super.writeToParcel(dest, TYPE_GSM);
dest.writeInt(mLac);
dest.writeInt(mCid);
dest.writeInt(mArfcn);
dest.writeInt(mBsic);
- dest.writeString(mMccStr);
- dest.writeString(mMncStr);
dest.writeString(mAlphaLong);
dest.writeString(mAlphaShort);
}
/** Construct from Parcel, type has already been processed */
private CellIdentityGsm(Parcel in) {
- this(in.readInt(), in.readInt(), in.readInt(), in.readInt(), in.readString(),
- in.readString(), in.readString(), in.readString());
+ super(TAG, TYPE_GSM, in);
+ mLac = in.readInt();
+ mCid = in.readInt();
+ mArfcn = in.readInt();
+ mBsic = in.readInt();
+ mAlphaLong = in.readString();
+ mAlphaShort = in.readString();
- if (DBG) log("CellIdentityGsm(Parcel): " + toString());
+ if (DBG) log(toString());
}
/** Implement the Parcelable interface */
@@ -320,7 +285,8 @@
new Creator<CellIdentityGsm>() {
@Override
public CellIdentityGsm createFromParcel(Parcel in) {
- return new CellIdentityGsm(in);
+ in.readInt(); // skip
+ return createFromParcelBody(in);
}
@Override
@@ -329,10 +295,8 @@
}
};
- /**
- * log
- */
- private static void log(String s) {
- Rlog.w(LOG_TAG, s);
+ /** @hide */
+ protected static CellIdentityGsm createFromParcelBody(Parcel in) {
+ return new CellIdentityGsm(in);
}
-}
\ No newline at end of file
+}
diff --git a/telephony/java/android/telephony/CellIdentityLte.java b/telephony/java/android/telephony/CellIdentityLte.java
index 6ca5daf6..7f20c8a 100644
--- a/telephony/java/android/telephony/CellIdentityLte.java
+++ b/telephony/java/android/telephony/CellIdentityLte.java
@@ -17,8 +17,6 @@
package android.telephony;
import android.os.Parcel;
-import android.os.Parcelable;
-import android.telephony.Rlog;
import android.text.TextUtils;
import java.util.Objects;
@@ -26,9 +24,8 @@
/**
* CellIdentity is to represent a unique LTE cell
*/
-public final class CellIdentityLte implements Parcelable {
-
- private static final String LOG_TAG = "CellIdentityLte";
+public final class CellIdentityLte extends CellIdentity {
+ private static final String TAG = CellIdentityLte.class.getSimpleName();
private static final boolean DBG = false;
// 28-bit cell identity
@@ -39,10 +36,6 @@
private final int mTac;
// 18-bit Absolute RF Channel Number
private final int mEarfcn;
- // 3-digit Mobile Country Code in string format
- private final String mMccStr;
- // 2 or 3-digit Mobile Network Code in string format
- private final String mMncStr;
// long alpha Operator Name String or Enhanced Operator Name String
private final String mAlphaLong;
// short alpha Operator Name String or Enhanced Operator Name String
@@ -52,12 +45,11 @@
* @hide
*/
public CellIdentityLte() {
+ super(TAG, TYPE_LTE, null, null);
mCi = Integer.MAX_VALUE;
mPci = Integer.MAX_VALUE;
mTac = Integer.MAX_VALUE;
mEarfcn = Integer.MAX_VALUE;
- mMccStr = null;
- mMncStr = null;
mAlphaLong = null;
mAlphaShort = null;
}
@@ -72,7 +64,7 @@
*
* @hide
*/
- public CellIdentityLte (int mcc, int mnc, int ci, int pci, int tac) {
+ public CellIdentityLte(int mcc, int mnc, int ci, int pci, int tac) {
this(ci, pci, tac, Integer.MAX_VALUE, String.valueOf(mcc), String.valueOf(mnc), null, null);
}
@@ -87,7 +79,7 @@
*
* @hide
*/
- public CellIdentityLte (int mcc, int mnc, int ci, int pci, int tac, int earfcn) {
+ public CellIdentityLte(int mcc, int mnc, int ci, int pci, int tac, int earfcn) {
this(ci, pci, tac, earfcn, String.valueOf(mcc), String.valueOf(mnc), null, null);
}
@@ -104,38 +96,13 @@
*
* @hide
*/
- public CellIdentityLte (int ci, int pci, int tac, int earfcn, String mccStr,
+ public CellIdentityLte(int ci, int pci, int tac, int earfcn, String mccStr,
String mncStr, String alphal, String alphas) {
+ super(TAG, TYPE_LTE, mccStr, mncStr);
mCi = ci;
mPci = pci;
mTac = tac;
mEarfcn = earfcn;
-
- // Only allow INT_MAX if unknown string mcc/mnc
- if (mccStr == null || mccStr.matches("^[0-9]{3}$")) {
- mMccStr = mccStr;
- } else if (mccStr.isEmpty() || mccStr.equals(String.valueOf(Integer.MAX_VALUE))) {
- // If the mccStr is empty or unknown, set it as null.
- mMccStr = null;
- } else {
- // TODO: b/69384059 Should throw IllegalArgumentException for the invalid MCC format
- // after the bug got fixed.
- mMccStr = null;
- log("invalid MCC format: " + mccStr);
- }
-
- if (mncStr == null || mncStr.matches("^[0-9]{2,3}$")) {
- mMncStr = mncStr;
- } else if (mncStr.isEmpty() || mncStr.equals(String.valueOf(Integer.MAX_VALUE))) {
- // If the mncStr is empty or unknown, set it as null.
- mMncStr = null;
- } else {
- // TODO: b/69384059 Should throw IllegalArgumentException for the invalid MNC format
- // after the bug got fixed.
- mMncStr = null;
- log("invalid MNC format: " + mncStr);
- }
-
mAlphaLong = alphal;
mAlphaShort = alphas;
}
@@ -248,58 +215,54 @@
}
CellIdentityLte o = (CellIdentityLte) other;
- return mCi == o.mCi &&
- mPci == o.mPci &&
- mTac == o.mTac &&
- mEarfcn == o.mEarfcn &&
- TextUtils.equals(mMccStr, o.mMccStr) &&
- TextUtils.equals(mMncStr, o.mMncStr) &&
- TextUtils.equals(mAlphaLong, o.mAlphaLong) &&
- TextUtils.equals(mAlphaShort, o.mAlphaShort);
+ return mCi == o.mCi
+ && mPci == o.mPci
+ && mTac == o.mTac
+ && mEarfcn == o.mEarfcn
+ && TextUtils.equals(mMccStr, o.mMccStr)
+ && TextUtils.equals(mMncStr, o.mMncStr)
+ && TextUtils.equals(mAlphaLong, o.mAlphaLong)
+ && TextUtils.equals(mAlphaShort, o.mAlphaShort);
}
@Override
public String toString() {
- StringBuilder sb = new StringBuilder("CellIdentityLte:{");
- sb.append(" mCi="); sb.append(mCi);
- sb.append(" mPci="); sb.append(mPci);
- sb.append(" mTac="); sb.append(mTac);
- sb.append(" mEarfcn="); sb.append(mEarfcn);
- sb.append(" mMcc="); sb.append(mMccStr);
- sb.append(" mMnc="); sb.append(mMncStr);
- sb.append(" mAlphaLong="); sb.append(mAlphaLong);
- sb.append(" mAlphaShort="); sb.append(mAlphaShort);
- sb.append("}");
-
- return sb.toString();
- }
-
- /** Implement the Parcelable interface */
- @Override
- public int describeContents() {
- return 0;
+ return new StringBuilder(TAG)
+ .append(":{ mCi=").append(mCi)
+ .append(" mPci=").append(mPci)
+ .append(" mTac=").append(mTac)
+ .append(" mEarfcn=").append(mEarfcn)
+ .append(" mMcc=").append(mMccStr)
+ .append(" mMnc=").append(mMncStr)
+ .append(" mAlphaLong=").append(mAlphaLong)
+ .append(" mAlphaShort=").append(mAlphaShort)
+ .append("}").toString();
}
/** Implement the Parcelable interface */
@Override
public void writeToParcel(Parcel dest, int flags) {
if (DBG) log("writeToParcel(Parcel, int): " + toString());
+ super.writeToParcel(dest, TYPE_LTE);
dest.writeInt(mCi);
dest.writeInt(mPci);
dest.writeInt(mTac);
dest.writeInt(mEarfcn);
- dest.writeString(mMccStr);
- dest.writeString(mMncStr);
dest.writeString(mAlphaLong);
dest.writeString(mAlphaShort);
}
/** Construct from Parcel, type has already been processed */
private CellIdentityLte(Parcel in) {
- this(in.readInt(), in.readInt(), in.readInt(), in.readInt(), in.readString(),
- in.readString(), in.readString(), in.readString());
+ super(TAG, TYPE_LTE, in);
+ mCi = in.readInt();
+ mPci = in.readInt();
+ mTac = in.readInt();
+ mEarfcn = in.readInt();
+ mAlphaLong = in.readString();
+ mAlphaShort = in.readString();
- if (DBG) log("CellIdentityLte(Parcel): " + toString());
+ if (DBG) log(toString());
}
/** Implement the Parcelable interface */
@@ -308,7 +271,8 @@
new Creator<CellIdentityLte>() {
@Override
public CellIdentityLte createFromParcel(Parcel in) {
- return new CellIdentityLte(in);
+ in.readInt(); // skip;
+ return createFromParcelBody(in);
}
@Override
@@ -317,10 +281,8 @@
}
};
- /**
- * log
- */
- private static void log(String s) {
- Rlog.w(LOG_TAG, s);
+ /** @hide */
+ protected static CellIdentityLte createFromParcelBody(Parcel in) {
+ return new CellIdentityLte(in);
}
-}
\ No newline at end of file
+}
diff --git a/telephony/java/android/telephony/data/InterfaceAddress.aidl b/telephony/java/android/telephony/CellIdentityTdscdma.aidl
similarity index 90%
rename from telephony/java/android/telephony/data/InterfaceAddress.aidl
rename to telephony/java/android/telephony/CellIdentityTdscdma.aidl
index d750363..2a182cd 100644
--- a/telephony/java/android/telephony/data/InterfaceAddress.aidl
+++ b/telephony/java/android/telephony/CellIdentityTdscdma.aidl
@@ -15,6 +15,6 @@
*/
/** @hide */
-package android.telephony.data;
+package android.telephony;
-parcelable InterfaceAddress;
+parcelable CellIdentityTdscdma;
diff --git a/telephony/java/android/telephony/CellIdentityTdscdma.java b/telephony/java/android/telephony/CellIdentityTdscdma.java
new file mode 100644
index 0000000..001d19f
--- /dev/null
+++ b/telephony/java/android/telephony/CellIdentityTdscdma.java
@@ -0,0 +1,196 @@
+/*
+ * Copyright 2017 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 android.telephony;
+
+import android.os.Parcel;
+import android.text.TextUtils;
+
+import java.util.Objects;
+
+/**
+ * CellIdentity is to represent a unique TD-SCDMA cell
+ */
+public final class CellIdentityTdscdma extends CellIdentity {
+ private static final String TAG = CellIdentityTdscdma.class.getSimpleName();
+ private static final boolean DBG = false;
+
+ // 16-bit Location Area Code, 0..65535, INT_MAX if unknown.
+ private final int mLac;
+ // 28-bit UMTS Cell Identity described in TS 25.331, 0..268435455, INT_MAX if unknown.
+ private final int mCid;
+ // 8-bit Cell Parameters ID described in TS 25.331, 0..127, INT_MAX if unknown.
+ private final int mCpid;
+
+ /**
+ * @hide
+ */
+ public CellIdentityTdscdma() {
+ super(TAG, TYPE_TDSCDMA, null, null);
+ mLac = Integer.MAX_VALUE;
+ mCid = Integer.MAX_VALUE;
+ mCpid = Integer.MAX_VALUE;
+ }
+
+ /**
+ * @param mcc 3-digit Mobile Country Code, 0..999
+ * @param mnc 2 or 3-digit Mobile Network Code, 0..999
+ * @param lac 16-bit Location Area Code, 0..65535, INT_MAX if unknown
+ * @param cid 28-bit UMTS Cell Identity described in TS 25.331, 0..268435455, INT_MAX if unknown
+ * @param cpid 8-bit Cell Parameters ID described in TS 25.331, 0..127, INT_MAX if unknown
+ *
+ * @hide
+ */
+ public CellIdentityTdscdma(int mcc, int mnc, int lac, int cid, int cpid) {
+ this(String.valueOf(mcc), String.valueOf(mnc), lac, cid, cpid);
+ }
+
+ /**
+ * @param mcc 3-digit Mobile Country Code in string format
+ * @param mnc 2 or 3-digit Mobile Network Code in string format
+ * @param lac 16-bit Location Area Code, 0..65535, INT_MAX if unknown
+ * @param cid 28-bit UMTS Cell Identity described in TS 25.331, 0..268435455, INT_MAX if unknown
+ * @param cpid 8-bit Cell Parameters ID described in TS 25.331, 0..127, INT_MAX if unknown
+ *
+ * @hide
+ */
+ public CellIdentityTdscdma(String mcc, String mnc, int lac, int cid, int cpid) {
+ super(TAG, TYPE_TDSCDMA, mcc, mnc);
+ mLac = lac;
+ mCid = cid;
+ mCpid = cpid;
+ }
+
+ private CellIdentityTdscdma(CellIdentityTdscdma cid) {
+ this(cid.mMccStr, cid.mMncStr, cid.mLac, cid.mCid, cid.mCpid);
+ }
+
+ CellIdentityTdscdma copy() {
+ return new CellIdentityTdscdma(this);
+ }
+
+ /**
+ * Get Mobile Country Code in string format
+ * @return Mobile Country Code in string format, null if unknown
+ */
+ public String getMccStr() {
+ return mMccStr;
+ }
+
+ /**
+ * Get Mobile Network Code in string format
+ * @return Mobile Network Code in string format, null if unknown
+ */
+ public String getMncStr() {
+ return mMncStr;
+ }
+
+ /**
+ * @return 16-bit Location Area Code, 0..65535, INT_MAX if unknown
+ */
+ public int getLac() {
+ return mLac;
+ }
+
+ /**
+ * @return 28-bit UMTS Cell Identity described in TS 25.331, 0..268435455, INT_MAX if unknown
+ */
+ public int getCid() {
+ return mCid;
+ }
+
+ /**
+ * @return 8-bit Cell Parameters ID described in TS 25.331, 0..127, INT_MAX if unknown
+ */
+ public int getCpid() {
+ return mCpid;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mMccStr, mMncStr, mLac, mCid, mCpid);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (this == other) {
+ return true;
+ }
+
+ if (!(other instanceof CellIdentityTdscdma)) {
+ return false;
+ }
+
+ CellIdentityTdscdma o = (CellIdentityTdscdma) other;
+ return TextUtils.equals(mMccStr, o.mMccStr)
+ && TextUtils.equals(mMncStr, o.mMncStr)
+ && mLac == o.mLac
+ && mCid == o.mCid
+ && mCpid == o.mCpid;
+ }
+
+ @Override
+ public String toString() {
+ return new StringBuilder(TAG)
+ .append(":{ mMcc=").append(mMccStr)
+ .append(" mMnc=").append(mMncStr)
+ .append(" mLac=").append(mLac)
+ .append(" mCid=").append(mCid)
+ .append(" mCpid=").append(mCpid)
+ .append("}").toString();
+ }
+
+ /** Implement the Parcelable interface */
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ if (DBG) log("writeToParcel(Parcel, int): " + toString());
+ super.writeToParcel(dest, TYPE_TDSCDMA);
+ dest.writeInt(mLac);
+ dest.writeInt(mCid);
+ dest.writeInt(mCpid);
+ }
+
+ /** Construct from Parcel, type has already been processed */
+ private CellIdentityTdscdma(Parcel in) {
+ super(TAG, TYPE_TDSCDMA, in);
+ mLac = in.readInt();
+ mCid = in.readInt();
+ mCpid = in.readInt();
+
+ if (DBG) log(toString());
+ }
+
+ /** Implement the Parcelable interface */
+ @SuppressWarnings("hiding")
+ public static final Creator<CellIdentityTdscdma> CREATOR =
+ new Creator<CellIdentityTdscdma>() {
+ @Override
+ public CellIdentityTdscdma createFromParcel(Parcel in) {
+ in.readInt(); // skip
+ return createFromParcelBody(in);
+ }
+
+ @Override
+ public CellIdentityTdscdma[] newArray(int size) {
+ return new CellIdentityTdscdma[size];
+ }
+ };
+
+ /** @hide */
+ protected static CellIdentityTdscdma createFromParcelBody(Parcel in) {
+ return new CellIdentityTdscdma(in);
+ }
+}
diff --git a/telephony/java/android/telephony/CellIdentityWcdma.java b/telephony/java/android/telephony/CellIdentityWcdma.java
index e4bb4f2..1aa1715 100644
--- a/telephony/java/android/telephony/CellIdentityWcdma.java
+++ b/telephony/java/android/telephony/CellIdentityWcdma.java
@@ -17,8 +17,6 @@
package android.telephony;
import android.os.Parcel;
-import android.os.Parcelable;
-import android.telephony.Rlog;
import android.text.TextUtils;
import java.util.Objects;
@@ -26,9 +24,8 @@
/**
* CellIdentity to represent a unique UMTS cell
*/
-public final class CellIdentityWcdma implements Parcelable {
-
- private static final String LOG_TAG = "CellIdentityWcdma";
+public final class CellIdentityWcdma extends CellIdentity {
+ private static final String TAG = CellIdentityWcdma.class.getSimpleName();
private static final boolean DBG = false;
// 16-bit Location Area Code, 0..65535
@@ -39,10 +36,6 @@
private final int mPsc;
// 16-bit UMTS Absolute RF Channel Number
private final int mUarfcn;
- // 3-digit Mobile Country Code in string format
- private final String mMccStr;
- // 2 or 3-digit Mobile Network Code in string format
- private final String mMncStr;
// long alpha Operator Name String or Enhanced Operator Name String
private final String mAlphaLong;
// short alpha Operator Name String or Enhanced Operator Name String
@@ -52,12 +45,11 @@
* @hide
*/
public CellIdentityWcdma() {
+ super(TAG, TYPE_TDSCDMA, null, null);
mLac = Integer.MAX_VALUE;
mCid = Integer.MAX_VALUE;
mPsc = Integer.MAX_VALUE;
mUarfcn = Integer.MAX_VALUE;
- mMccStr = null;
- mMncStr = null;
mAlphaLong = null;
mAlphaShort = null;
}
@@ -106,36 +98,11 @@
*/
public CellIdentityWcdma (int lac, int cid, int psc, int uarfcn,
String mccStr, String mncStr, String alphal, String alphas) {
+ super(TAG, TYPE_WCDMA, mccStr, mncStr);
mLac = lac;
mCid = cid;
mPsc = psc;
mUarfcn = uarfcn;
-
- // Only allow INT_MAX if unknown string mcc/mnc
- if (mccStr == null || mccStr.matches("^[0-9]{3}$")) {
- mMccStr = mccStr;
- } else if (mccStr.isEmpty() || mccStr.equals(String.valueOf(Integer.MAX_VALUE))) {
- // If the mccStr is empty or unknown, set it as null.
- mMccStr = null;
- } else {
- // TODO: b/69384059 Should throw IllegalArgumentException for the invalid MCC format
- // after the bug got fixed.
- mMccStr = null;
- log("invalid MCC format: " + mccStr);
- }
-
- if (mncStr == null || mncStr.matches("^[0-9]{2,3}$")) {
- mMncStr = mncStr;
- } else if (mncStr.isEmpty() || mncStr.equals(String.valueOf(Integer.MAX_VALUE))) {
- // If the mncStr is empty or unknown, set it as null.
- mMncStr = null;
- } else {
- // TODO: b/69384059 Should throw IllegalArgumentException for the invalid MNC format
- // after the bug got fixed.
- mMncStr = null;
- log("invalid MNC format: " + mncStr);
- }
-
mAlphaLong = alphal;
mAlphaShort = alphas;
}
@@ -250,58 +217,53 @@
}
CellIdentityWcdma o = (CellIdentityWcdma) other;
- return mLac == o.mLac &&
- mCid == o.mCid &&
- mPsc == o.mPsc &&
- mUarfcn == o.mUarfcn &&
- TextUtils.equals(mMccStr, o.mMccStr) &&
- TextUtils.equals(mMncStr, o.mMncStr) &&
- TextUtils.equals(mAlphaLong, o.mAlphaLong) &&
- TextUtils.equals(mAlphaShort, o.mAlphaShort);
+ return mLac == o.mLac
+ && mCid == o.mCid
+ && mPsc == o.mPsc
+ && mUarfcn == o.mUarfcn
+ && TextUtils.equals(mMccStr, o.mMccStr)
+ && TextUtils.equals(mMncStr, o.mMncStr)
+ && TextUtils.equals(mAlphaLong, o.mAlphaLong)
+ && TextUtils.equals(mAlphaShort, o.mAlphaShort);
}
@Override
public String toString() {
- StringBuilder sb = new StringBuilder("CellIdentityWcdma:{");
- sb.append(" mLac=").append(mLac);
- sb.append(" mCid=").append(mCid);
- sb.append(" mPsc=").append(mPsc);
- sb.append(" mUarfcn=").append(mUarfcn);
- sb.append(" mMcc=").append(mMccStr);
- sb.append(" mMnc=").append(mMncStr);
- sb.append(" mAlphaLong=").append(mAlphaLong);
- sb.append(" mAlphaShort=").append(mAlphaShort);
- sb.append("}");
-
- return sb.toString();
- }
-
- /** Implement the Parcelable interface */
- @Override
- public int describeContents() {
- return 0;
+ return new StringBuilder(TAG)
+ .append(":{ mLac=").append(mLac)
+ .append(" mCid=").append(mCid)
+ .append(" mPsc=").append(mPsc)
+ .append(" mUarfcn=").append(mUarfcn)
+ .append(" mMcc=").append(mMccStr)
+ .append(" mMnc=").append(mMncStr)
+ .append(" mAlphaLong=").append(mAlphaLong)
+ .append(" mAlphaShort=").append(mAlphaShort)
+ .append("}").toString();
}
/** Implement the Parcelable interface */
@Override
public void writeToParcel(Parcel dest, int flags) {
if (DBG) log("writeToParcel(Parcel, int): " + toString());
+ super.writeToParcel(dest, TYPE_WCDMA);
dest.writeInt(mLac);
dest.writeInt(mCid);
dest.writeInt(mPsc);
dest.writeInt(mUarfcn);
- dest.writeString(mMccStr);
- dest.writeString(mMncStr);
dest.writeString(mAlphaLong);
dest.writeString(mAlphaShort);
}
/** Construct from Parcel, type has already been processed */
private CellIdentityWcdma(Parcel in) {
- this(in.readInt(), in.readInt(), in.readInt(), in.readInt(), in.readString(),
- in.readString(), in.readString(), in.readString());
-
- if (DBG) log("CellIdentityWcdma(Parcel): " + toString());
+ super(TAG, TYPE_WCDMA, in);
+ mLac = in.readInt();
+ mCid = in.readInt();
+ mPsc = in.readInt();
+ mUarfcn = in.readInt();
+ mAlphaLong = in.readString();
+ mAlphaShort = in.readString();
+ if (DBG) log(toString());
}
/** Implement the Parcelable interface */
@@ -310,7 +272,8 @@
new Creator<CellIdentityWcdma>() {
@Override
public CellIdentityWcdma createFromParcel(Parcel in) {
- return new CellIdentityWcdma(in);
+ in.readInt(); // skip
+ return createFromParcelBody(in);
}
@Override
@@ -319,10 +282,8 @@
}
};
- /**
- * log
- */
- private static void log(String s) {
- Rlog.w(LOG_TAG, s);
+ /** @hide */
+ protected static CellIdentityWcdma createFromParcelBody(Parcel in) {
+ return new CellIdentityWcdma(in);
}
}
\ No newline at end of file
diff --git a/telephony/java/android/telephony/PhoneStateListener.java b/telephony/java/android/telephony/PhoneStateListener.java
index c7e5131..98ea451 100644
--- a/telephony/java/android/telephony/PhoneStateListener.java
+++ b/telephony/java/android/telephony/PhoneStateListener.java
@@ -244,6 +244,13 @@
*/
public static final int LISTEN_DATA_ACTIVATION_STATE = 0x00040000;
+ /**
+ * Listen for changes to the user mobile data state
+ *
+ * @see #onUserMobileDataStateChanged
+ */
+ public static final int LISTEN_USER_MOBILE_DATA_STATE = 0x00080000;
+
/*
* Subscription used to listen to the phone state changes
* @hide
@@ -349,6 +356,9 @@
case LISTEN_DATA_ACTIVATION_STATE:
PhoneStateListener.this.onDataActivationStateChanged((int)msg.obj);
break;
+ case LISTEN_USER_MOBILE_DATA_STATE:
+ PhoneStateListener.this.onUserMobileDataStateChanged((boolean)msg.obj);
+ break;
case LISTEN_CARRIER_NETWORK_CHANGE:
PhoneStateListener.this.onCarrierNetworkChange((boolean)msg.obj);
break;
@@ -543,6 +553,14 @@
}
/**
+ * Callback invoked when the user mobile data state has changed
+ * @param enabled indicates whether the current user mobile data state is enabled or disabled.
+ */
+ public void onUserMobileDataStateChanged(boolean enabled) {
+ // default implementation empty
+ }
+
+ /**
* Callback invoked when telephony has received notice from a carrier
* app that a network action that could result in connectivity loss
* has been requested by an app using
@@ -654,6 +672,10 @@
send(LISTEN_DATA_ACTIVATION_STATE, 0, 0, activationState);
}
+ public void onUserMobileDataStateChanged(boolean enabled) {
+ send(LISTEN_USER_MOBILE_DATA_STATE, 0, 0, enabled);
+ }
+
public void onCarrierNetworkChange(boolean active) {
send(LISTEN_CARRIER_NETWORK_CHANGE, 0, 0, active);
}
diff --git a/telephony/java/android/telephony/UiccAccessRule.java b/telephony/java/android/telephony/UiccAccessRule.java
index e42a758..3937201 100644
--- a/telephony/java/android/telephony/UiccAccessRule.java
+++ b/telephony/java/android/telephony/UiccAccessRule.java
@@ -32,6 +32,7 @@
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
+import java.util.Objects;
/**
* Describes a single UICC access rule according to the GlobalPlatform Secure Element Access Control
@@ -205,6 +206,21 @@
}
@Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+
+ UiccAccessRule that = (UiccAccessRule) obj;
+ return Arrays.equals(mCertificateHash, that.mCertificateHash)
+ && Objects.equals(mPackageName, that.mPackageName)
+ && mAccessType == that.mAccessType;
+ }
+
+ @Override
public String toString() {
return "cert: " + IccUtils.bytesToHexString(mCertificateHash) + " pkg: " +
mPackageName + " access: " + mAccessType;
diff --git a/telephony/java/android/telephony/data/InterfaceAddress.aidl b/telephony/java/android/telephony/data/ApnSetting.aidl
similarity index 86%
copy from telephony/java/android/telephony/data/InterfaceAddress.aidl
copy to telephony/java/android/telephony/data/ApnSetting.aidl
index d750363..381e5e8 100644
--- a/telephony/java/android/telephony/data/InterfaceAddress.aidl
+++ b/telephony/java/android/telephony/data/ApnSetting.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright 2017 The Android Open Source Project
+ * Copyright (C) 2018 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.
@@ -13,8 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
-/** @hide */
package android.telephony.data;
-parcelable InterfaceAddress;
+parcelable ApnSetting;
diff --git a/telephony/java/android/telephony/data/ApnSetting.java b/telephony/java/android/telephony/data/ApnSetting.java
new file mode 100644
index 0000000..2ab8d4f
--- /dev/null
+++ b/telephony/java/android/telephony/data/ApnSetting.java
@@ -0,0 +1,1370 @@
+/*
+ * Copyright (C) 2018 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 android.telephony.data;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.StringDef;
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.hardware.radio.V1_0.ApnTypes;
+import android.net.NetworkUtils;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.provider.Telephony;
+import android.telephony.Rlog;
+import android.text.TextUtils;
+import android.util.Log;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.net.MalformedURLException;
+import java.net.UnknownHostException;
+import java.net.URL;
+import java.net.InetAddress;
+import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * A class representing an APN configuration.
+ */
+public class ApnSetting implements Parcelable {
+
+ static final String LOG_TAG = "ApnSetting";
+ private static final boolean VDBG = false;
+
+ private final String mEntryName;
+ private final String mApnName;
+ private final InetAddress mProxy;
+ private final int mPort;
+ private final URL mMmsc;
+ private final InetAddress mMmsProxy;
+ private final int mMmsPort;
+ private final String mUser;
+ private final String mPassword;
+ private final int mAuthType;
+ private final List<String> mTypes;
+ private final int mTypesBitmap;
+ private final int mId;
+ private final String mOperatorNumeric;
+ private final String mProtocol;
+ private final String mRoamingProtocol;
+ private final int mMtu;
+
+ private final boolean mCarrierEnabled;
+ private final int mBearer;
+ private final int mBearerBitmask;
+
+ private final int mProfileId;
+
+ private final boolean mModemCognitive;
+ private final int mMaxConns;
+ private final int mWaitTime;
+ private final int mMaxConnsTime;
+
+ private final String mMvnoType;
+ private final String mMvnoMatchData;
+
+ private boolean mPermanentFailed = false;
+
+ /**
+ * Returns the types bitmap of the APN.
+ *
+ * @return types bitmap of the APN
+ * @hide
+ */
+ public int getTypesBitmap() {
+ return mTypesBitmap;
+ }
+
+ /**
+ * Returns the MTU size of the mobile interface to which the APN connected.
+ *
+ * @return the MTU size of the APN
+ * @hide
+ */
+ public int getMtu() {
+ return mMtu;
+ }
+
+ /**
+ * Radio Access Technology info.
+ * To check what values can hold, refer to ServiceState.java.
+ * This should be spread to other technologies,
+ * but currently only used for LTE(14) and EHRPD(13).
+ *
+ * @return the bearer info of the APN
+ * @hide
+ */
+ public int getBearer() {
+ return mBearer;
+ }
+
+ /**
+ * Returns the radio access technology bitmask for this APN.
+ *
+ * To check what values can hold, refer to ServiceState.java. This is a bitmask of radio
+ * technologies in ServiceState.
+ * This should be spread to other technologies,
+ * but currently only used for LTE(14) and EHRPD(13).
+ *
+ * @return the radio access technology bitmask
+ * @hide
+ */
+ public int getBearerBitmask() {
+ return mBearerBitmask;
+ }
+
+ /**
+ * Returns the profile id to which the APN saved in modem.
+ *
+ * @return the profile id of the APN
+ * @hide
+ */
+ public int getProfileId() {
+ return mProfileId;
+ }
+
+ /**
+ * Returns if the APN setting is to be set in modem.
+ *
+ * @return is the APN setting to be set in modem
+ * @hide
+ */
+ public boolean getModemCognitive() {
+ return mModemCognitive;
+ }
+
+ /**
+ * Returns the max connections of this APN.
+ *
+ * @return the max connections of this APN
+ * @hide
+ */
+ public int getMaxConns() {
+ return mMaxConns;
+ }
+
+ /**
+ * Returns the wait time for retry of the APN.
+ *
+ * @return the wait time for retry of the APN
+ * @hide
+ */
+ public int getWaitTime() {
+ return mWaitTime;
+ }
+
+ /**
+ * Returns the time to limit max connection for the APN.
+ *
+ * @return the time to limit max connection for the APN
+ * @hide
+ */
+ public int getMaxConnsTime() {
+ return mMaxConnsTime;
+ }
+
+ /**
+ * Returns the MVNO data. Examples:
+ * "spn": A MOBILE, BEN NL
+ * "imsi": 302720x94, 2060188
+ * "gid": 4E, 33
+ * "iccid": 898603 etc..
+ *
+ * @return the mvno match data
+ * @hide
+ */
+ public String getMvnoMatchData() {
+ return mMvnoMatchData;
+ }
+
+ /**
+ * Indicates this APN setting is permanently failed and cannot be
+ * retried by the retry manager anymore.
+ *
+ * @return if this APN setting is permanently failed
+ * @hide
+ */
+ public boolean getPermanentFailed() {
+ return mPermanentFailed;
+ }
+
+ /**
+ * Sets if this APN setting is permanently failed.
+ *
+ * @param permanentFailed if this APN setting is permanently failed
+ * @hide
+ */
+ public void setPermanentFailed(boolean permanentFailed) {
+ mPermanentFailed = permanentFailed;
+ }
+
+ /**
+ * Returns the entry name of the APN.
+ *
+ * @return the entry name for the APN
+ */
+ public String getEntryName() {
+ return mEntryName;
+ }
+
+ /**
+ * Returns the name of the APN.
+ *
+ * @return APN name
+ */
+ public String getApnName() {
+ return mApnName;
+ }
+
+ /**
+ * Returns the proxy address of the APN.
+ *
+ * @return proxy address.
+ */
+ public InetAddress getProxy() {
+ return mProxy;
+ }
+
+ /**
+ * Returns the proxy port of the APN.
+ *
+ * @return proxy port
+ */
+ public int getPort() {
+ return mPort;
+ }
+ /**
+ * Returns the MMSC URL of the APN.
+ *
+ * @return MMSC URL.
+ */
+ public URL getMmsc() {
+ return mMmsc;
+ }
+
+ /**
+ * Returns the MMS proxy address of the APN.
+ *
+ * @return MMS proxy address.
+ */
+ public InetAddress getMmsProxy() {
+ return mMmsProxy;
+ }
+
+ /**
+ * Returns the MMS proxy port of the APN.
+ *
+ * @return MMS proxy port
+ */
+ public int getMmsPort() {
+ return mMmsPort;
+ }
+
+ /**
+ * Returns the APN username of the APN.
+ *
+ * @return APN username
+ */
+ public String getUser() {
+ return mUser;
+ }
+
+ /**
+ * Returns the APN password of the APN.
+ *
+ * @return APN password
+ */
+ public String getPassword() {
+ return mPassword;
+ }
+
+ /** @hide */
+ @IntDef({
+ AUTH_TYPE_NONE,
+ AUTH_TYPE_PAP,
+ AUTH_TYPE_CHAP,
+ AUTH_TYPE_PAP_OR_CHAP,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface AuthType {}
+
+ /**
+ * Returns the authentication type of the APN.
+ *
+ * Example of possible values: {@link #AUTH_TYPE_NONE}, {@link #AUTH_TYPE_PAP}.
+ *
+ * @return authentication type
+ */
+ @AuthType
+ public int getAuthType() {
+ return mAuthType;
+ }
+
+ /** @hide */
+ @StringDef({
+ TYPE_DEFAULT,
+ TYPE_MMS,
+ TYPE_SUPL,
+ TYPE_DUN,
+ TYPE_HIPRI,
+ TYPE_FOTA,
+ TYPE_IMS,
+ TYPE_CBS,
+ TYPE_IA,
+ TYPE_EMERGENCY
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ApnType {}
+
+ /**
+ * Returns the list of APN types of the APN.
+ *
+ * Example of possible values: {@link #TYPE_DEFAULT}, {@link #TYPE_MMS}.
+ *
+ * @return the list of APN types
+ */
+ @ApnType
+ public List<String> getTypes() {
+ return mTypes;
+ }
+
+ /**
+ * Returns the unique database id for this entry.
+ *
+ * @return the unique database id
+ */
+ public int getId() {
+ return mId;
+ }
+
+ /**
+ * Returns the numeric operator ID for the APN. Usually
+ * {@link android.provider.Telephony.Carriers#MCC} +
+ * {@link android.provider.Telephony.Carriers#MNC}.
+ *
+ * @return the numeric operator ID
+ */
+ public String getOperatorNumeric() {
+ return mOperatorNumeric;
+ }
+
+ /** @hide */
+ @StringDef({
+ PROTOCOL_IP,
+ PROTOCOL_IPV6,
+ PROTOCOL_IPV4V6,
+ PROTOCOL_PPP,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ProtocolType {}
+
+ /**
+ * Returns the protocol to use to connect to this APN.
+ *
+ * One of the {@code PDP_type} values in TS 27.007 section 10.1.1.
+ * Example of possible values: {@link #PROTOCOL_IP}, {@link #PROTOCOL_IPV6}.
+ *
+ * @return the protocol
+ */
+ @ProtocolType
+ public String getProtocol() {
+ return mProtocol;
+ }
+
+ /**
+ * Returns the protocol to use to connect to this APN when roaming.
+ *
+ * The syntax is the same as {@link android.provider.Telephony.Carriers#PROTOCOL}.
+ *
+ * @return the roaming protocol
+ */
+ public String getRoamingProtocol() {
+ return mRoamingProtocol;
+ }
+
+ /**
+ * Returns the current status of APN.
+ *
+ * {@code true} : enabled APN.
+ * {@code false} : disabled APN.
+ *
+ * @return the current status
+ */
+ public boolean isEnabled() {
+ return mCarrierEnabled;
+ }
+
+ /** @hide */
+ @StringDef({
+ MVNO_TYPE_SPN,
+ MVNO_TYPE_IMSI,
+ MVNO_TYPE_GID,
+ MVNO_TYPE_ICCID,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface MvnoType {}
+
+ /**
+ * Returns the MVNO match type for this APN.
+ *
+ * Example of possible values: {@link #MVNO_TYPE_SPN}, {@link #MVNO_TYPE_IMSI}.
+ *
+ * @return the MVNO match type
+ */
+ @MvnoType
+ public String getMvnoType() {
+ return mMvnoType;
+ }
+
+ private ApnSetting(Builder builder) {
+ this.mEntryName = builder.mEntryName;
+ this.mApnName = builder.mApnName;
+ this.mProxy = builder.mProxy;
+ this.mPort = builder.mPort;
+ this.mMmsc = builder.mMmsc;
+ this.mMmsProxy = builder.mMmsProxy;
+ this.mMmsPort = builder.mMmsPort;
+ this.mUser = builder.mUser;
+ this.mPassword = builder.mPassword;
+ this.mAuthType = builder.mAuthType;
+ this.mTypes = (builder.mTypes == null ? new ArrayList<String>() : builder.mTypes);
+ this.mTypesBitmap = builder.mTypesBitmap;
+ this.mId = builder.mId;
+ this.mOperatorNumeric = builder.mOperatorNumeric;
+ this.mProtocol = builder.mProtocol;
+ this.mRoamingProtocol = builder.mRoamingProtocol;
+ this.mMtu = builder.mMtu;
+ this.mCarrierEnabled = builder.mCarrierEnabled;
+ this.mBearer = builder.mBearer;
+ this.mBearerBitmask = builder.mBearerBitmask;
+ this.mProfileId = builder.mProfileId;
+ this.mModemCognitive = builder.mModemCognitive;
+ this.mMaxConns = builder.mMaxConns;
+ this.mWaitTime = builder.mWaitTime;
+ this.mMaxConnsTime = builder.mMaxConnsTime;
+ this.mMvnoType = builder.mMvnoType;
+ this.mMvnoMatchData = builder.mMvnoMatchData;
+ }
+
+ /** @hide */
+ public static ApnSetting makeApnSetting(int id, String operatorNumeric, String entryName,
+ String apnName, InetAddress proxy, int port, URL mmsc, InetAddress mmsProxy,
+ int mmsPort, String user, String password, int authType, List<String> types,
+ String protocol, String roamingProtocol, boolean carrierEnabled, int bearer,
+ int bearerBitmask, int profileId, boolean modemCognitive, int maxConns,
+ int waitTime, int maxConnsTime, int mtu, String mvnoType, String mvnoMatchData) {
+ return new Builder()
+ .setId(id)
+ .setOperatorNumeric(operatorNumeric)
+ .setEntryName(entryName)
+ .setApnName(apnName)
+ .setProxy(proxy)
+ .setPort(port)
+ .setMmsc(mmsc)
+ .setMmsProxy(mmsProxy)
+ .setMmsPort(mmsPort)
+ .setUser(user)
+ .setPassword(password)
+ .setAuthType(authType)
+ .setTypes(types)
+ .setProtocol(protocol)
+ .setRoamingProtocol(roamingProtocol)
+ .setCarrierEnabled(carrierEnabled)
+ .setBearer(bearer)
+ .setBearerBitmask(bearerBitmask)
+ .setProfileId(profileId)
+ .setModemCognitive(modemCognitive)
+ .setMaxConns(maxConns)
+ .setWaitTime(waitTime)
+ .setMaxConnsTime(maxConnsTime)
+ .setMtu(mtu)
+ .setMvnoType(mvnoType)
+ .setMvnoMatchData(mvnoMatchData)
+ .build();
+ }
+
+ /** @hide */
+ public static ApnSetting makeApnSetting(Cursor cursor) {
+ String[] types = parseTypes(
+ cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.TYPE)));
+
+ return makeApnSetting(
+ cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers._ID)),
+ cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.NUMERIC)),
+ cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.NAME)),
+ cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.APN)),
+ inetAddressFromString(cursor.getString(
+ cursor.getColumnIndexOrThrow(Telephony.Carriers.PROXY))),
+ portFromString(cursor.getString(
+ cursor.getColumnIndexOrThrow(Telephony.Carriers.PORT))),
+ URLFromString(cursor.getString(
+ cursor.getColumnIndexOrThrow(Telephony.Carriers.MMSC))),
+ inetAddressFromString(cursor.getString(
+ cursor.getColumnIndexOrThrow(Telephony.Carriers.MMSPROXY))),
+ portFromString(cursor.getString(
+ cursor.getColumnIndexOrThrow(Telephony.Carriers.MMSPORT))),
+ cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.USER)),
+ cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.PASSWORD)),
+ cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.AUTH_TYPE)),
+ Arrays.asList(types),
+ cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.PROTOCOL)),
+ cursor.getString(cursor.getColumnIndexOrThrow(
+ Telephony.Carriers.ROAMING_PROTOCOL)),
+ cursor.getInt(cursor.getColumnIndexOrThrow(
+ Telephony.Carriers.CARRIER_ENABLED)) == 1,
+ cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.BEARER)),
+ cursor.getInt(cursor.getColumnIndexOrThrow(
+ Telephony.Carriers.BEARER_BITMASK)),
+ cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.PROFILE_ID)),
+ cursor.getInt(cursor.getColumnIndexOrThrow(
+ Telephony.Carriers.MODEM_COGNITIVE)) == 1,
+ cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.MAX_CONNS)),
+ cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.WAIT_TIME)),
+ cursor.getInt(cursor.getColumnIndexOrThrow(
+ Telephony.Carriers.MAX_CONNS_TIME)),
+ cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.MTU)),
+ cursor.getString(cursor.getColumnIndexOrThrow(
+ Telephony.Carriers.MVNO_TYPE)),
+ cursor.getString(cursor.getColumnIndexOrThrow(
+ Telephony.Carriers.MVNO_MATCH_DATA)));
+ }
+
+ /** @hide */
+ public static ApnSetting makeApnSetting(ApnSetting apn) {
+ return makeApnSetting(apn.mId, apn.mOperatorNumeric, apn.mEntryName, apn.mApnName,
+ apn.mProxy, apn.mPort, apn.mMmsc, apn.mMmsProxy, apn.mMmsPort, apn.mUser,
+ apn.mPassword, apn.mAuthType, apn.mTypes, apn.mProtocol, apn.mRoamingProtocol,
+ apn.mCarrierEnabled, apn.mBearer, apn.mBearerBitmask, apn.mProfileId,
+ apn.mModemCognitive, apn.mMaxConns, apn.mWaitTime, apn.mMaxConnsTime, apn.mMtu,
+ apn.mMvnoType, apn.mMvnoMatchData);
+ }
+
+ /** @hide */
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("[ApnSettingV3] ")
+ .append(mEntryName)
+ .append(", ").append(mId)
+ .append(", ").append(mOperatorNumeric)
+ .append(", ").append(mApnName)
+ .append(", ").append(inetAddressToString(mProxy))
+ .append(", ").append(URLToString(mMmsc))
+ .append(", ").append(inetAddressToString(mMmsProxy))
+ .append(", ").append(portToString(mMmsPort))
+ .append(", ").append(portToString(mPort))
+ .append(", ").append(mAuthType).append(", ");
+ for (int i = 0; i < mTypes.size(); i++) {
+ sb.append(mTypes.get(i));
+ if (i < mTypes.size() - 1) {
+ sb.append(" | ");
+ }
+ }
+ sb.append(", ").append(mProtocol);
+ sb.append(", ").append(mRoamingProtocol);
+ sb.append(", ").append(mCarrierEnabled);
+ sb.append(", ").append(mBearer);
+ sb.append(", ").append(mBearerBitmask);
+ sb.append(", ").append(mProfileId);
+ sb.append(", ").append(mModemCognitive);
+ sb.append(", ").append(mMaxConns);
+ sb.append(", ").append(mWaitTime);
+ sb.append(", ").append(mMaxConnsTime);
+ sb.append(", ").append(mMtu);
+ sb.append(", ").append(mMvnoType);
+ sb.append(", ").append(mMvnoMatchData);
+ sb.append(", ").append(mPermanentFailed);
+ return sb.toString();
+ }
+
+ /**
+ * Returns true if there are MVNO params specified.
+ * @hide
+ */
+ public boolean hasMvnoParams() {
+ return !TextUtils.isEmpty(mMvnoType) && !TextUtils.isEmpty(mMvnoMatchData);
+ }
+
+ /** @hide */
+ public boolean canHandleType(String type) {
+ if (!mCarrierEnabled) return false;
+ boolean wildcardable = true;
+ if (TYPE_IA.equalsIgnoreCase(type)) wildcardable = false;
+ for (String t : mTypes) {
+ // DEFAULT handles all, and HIPRI is handled by DEFAULT
+ if (t.equalsIgnoreCase(type)
+ || (wildcardable && t.equalsIgnoreCase(TYPE_ALL))
+ || (t.equalsIgnoreCase(TYPE_DEFAULT)
+ && type.equalsIgnoreCase(TYPE_HIPRI))) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // check whether the types of two APN same (even only one type of each APN is same)
+ private boolean typeSameAny(ApnSetting first, ApnSetting second) {
+ if (VDBG) {
+ StringBuilder apnType1 = new StringBuilder(first.mApnName + ": ");
+ for (int index1 = 0; index1 < first.mTypes.size(); index1++) {
+ apnType1.append(first.mTypes.get(index1));
+ apnType1.append(",");
+ }
+
+ StringBuilder apnType2 = new StringBuilder(second.mApnName + ": ");
+ for (int index1 = 0; index1 < second.mTypes.size(); index1++) {
+ apnType2.append(second.mTypes.get(index1));
+ apnType2.append(",");
+ }
+ Rlog.d(LOG_TAG, "APN1: is " + apnType1);
+ Rlog.d(LOG_TAG, "APN2: is " + apnType2);
+ }
+
+ for (int index1 = 0; index1 < first.mTypes.size(); index1++) {
+ for (int index2 = 0; index2 < second.mTypes.size(); index2++) {
+ if (first.mTypes.get(index1).equals(ApnSetting.TYPE_ALL)
+ || second.mTypes.get(index2).equals(ApnSetting.TYPE_ALL)
+ || first.mTypes.get(index1).equals(second.mTypes.get(index2))) {
+ if (VDBG) Rlog.d(LOG_TAG, "typeSameAny: return true");
+ return true;
+ }
+ }
+ }
+
+ if (VDBG) Rlog.d(LOG_TAG, "typeSameAny: return false");
+ return false;
+ }
+
+ // TODO - if we have this function we should also have hashCode.
+ // Also should handle changes in type order and perhaps case-insensitivity
+ /** @hide */
+ public boolean equals(Object o) {
+ if (o instanceof ApnSetting == false) {
+ return false;
+ }
+
+ ApnSetting other = (ApnSetting) o;
+
+ return mEntryName.equals(other.mEntryName)
+ && Objects.equals(mId, other.mId)
+ && Objects.equals(mOperatorNumeric, other.mOperatorNumeric)
+ && Objects.equals(mApnName, other.mApnName)
+ && Objects.equals(mProxy, other.mProxy)
+ && Objects.equals(mMmsc, other.mMmsc)
+ && Objects.equals(mMmsProxy, other.mMmsProxy)
+ && Objects.equals(mMmsPort, other.mMmsPort)
+ && Objects.equals(mPort,other.mPort)
+ && Objects.equals(mUser, other.mUser)
+ && Objects.equals(mPassword, other.mPassword)
+ && Objects.equals(mAuthType, other.mAuthType)
+ && Objects.equals(mTypes, other.mTypes)
+ && Objects.equals(mTypesBitmap, other.mTypesBitmap)
+ && Objects.equals(mProtocol, other.mProtocol)
+ && Objects.equals(mRoamingProtocol, other.mRoamingProtocol)
+ && Objects.equals(mCarrierEnabled, other.mCarrierEnabled)
+ && Objects.equals(mBearer, other.mBearer)
+ && Objects.equals(mBearerBitmask, other.mBearerBitmask)
+ && Objects.equals(mProfileId, other.mProfileId)
+ && Objects.equals(mModemCognitive, other.mModemCognitive)
+ && Objects.equals(mMaxConns, other.mMaxConns)
+ && Objects.equals(mWaitTime, other.mWaitTime)
+ && Objects.equals(mMaxConnsTime, other.mMaxConnsTime)
+ && Objects.equals(mMtu, other.mMtu)
+ && Objects.equals(mMvnoType, other.mMvnoType)
+ && Objects.equals(mMvnoMatchData, other.mMvnoMatchData);
+ }
+
+ /**
+ * Compare two APN settings
+ *
+ * Note: This method does not compare 'id', 'bearer', 'bearerBitmask'. We only use this for
+ * determining if tearing a data call is needed when conditions change. See
+ * cleanUpConnectionsOnUpdatedApns in DcTracker.
+ *
+ * @param o the other object to compare
+ * @param isDataRoaming True if the device is on data roaming
+ * @return True if the two APN settings are same
+ * @hide
+ */
+ public boolean equals(Object o, boolean isDataRoaming) {
+ if (!(o instanceof ApnSetting)) {
+ return false;
+ }
+
+ ApnSetting other = (ApnSetting) o;
+
+ return mEntryName.equals(other.mEntryName)
+ && Objects.equals(mOperatorNumeric, other.mOperatorNumeric)
+ && Objects.equals(mApnName, other.mApnName)
+ && Objects.equals(mProxy, other.mProxy)
+ && Objects.equals(mMmsc, other.mMmsc)
+ && Objects.equals(mMmsProxy, other.mMmsProxy)
+ && Objects.equals(mMmsPort, other.mMmsPort)
+ && Objects.equals(mPort, other.mPort)
+ && Objects.equals(mUser, other.mUser)
+ && Objects.equals(mPassword, other.mPassword)
+ && Objects.equals(mAuthType, other.mAuthType)
+ && Objects.equals(mTypes, other.mTypes)
+ && Objects.equals(mTypesBitmap, other.mTypesBitmap)
+ && (isDataRoaming || Objects.equals(mProtocol,other.mProtocol))
+ && (!isDataRoaming || Objects.equals(mRoamingProtocol, other.mRoamingProtocol))
+ && Objects.equals(mCarrierEnabled, other.mCarrierEnabled)
+ && Objects.equals(mProfileId, other.mProfileId)
+ && Objects.equals(mModemCognitive, other.mModemCognitive)
+ && Objects.equals(mMaxConns, other.mMaxConns)
+ && Objects.equals(mWaitTime, other.mWaitTime)
+ && Objects.equals(mMaxConnsTime, other.mMaxConnsTime)
+ && Objects.equals(mMtu, other.mMtu)
+ && Objects.equals(mMvnoType, other.mMvnoType)
+ && Objects.equals(mMvnoMatchData, other.mMvnoMatchData);
+ }
+
+ /**
+ * Check if neither mention DUN and are substantially similar
+ *
+ * @param other The other APN settings to compare
+ * @return True if two APN settings are similar
+ * @hide
+ */
+ public boolean similar(ApnSetting other) {
+ return (!this.canHandleType(TYPE_DUN)
+ && !other.canHandleType(TYPE_DUN)
+ && Objects.equals(this.mApnName, other.mApnName)
+ && !typeSameAny(this, other)
+ && xorEqualsInetAddress(this.mProxy, other.mProxy)
+ && xorEqualsPort(this.mPort, other.mPort)
+ && xorEquals(this.mProtocol, other.mProtocol)
+ && xorEquals(this.mRoamingProtocol, other.mRoamingProtocol)
+ && Objects.equals(this.mCarrierEnabled, other.mCarrierEnabled)
+ && Objects.equals(this.mBearerBitmask, other.mBearerBitmask)
+ && Objects.equals(this.mProfileId, other.mProfileId)
+ && Objects.equals(this.mMvnoType, other.mMvnoType)
+ && Objects.equals(this.mMvnoMatchData, other.mMvnoMatchData)
+ && xorEqualsURL(this.mMmsc, other.mMmsc)
+ && xorEqualsInetAddress(this.mMmsProxy, other.mMmsProxy)
+ && xorEqualsPort(this.mMmsPort, other.mMmsPort));
+ }
+
+ // Equal or one is not specified.
+ private boolean xorEquals(String first, String second) {
+ return (Objects.equals(first, second)
+ || TextUtils.isEmpty(first)
+ || TextUtils.isEmpty(second));
+ }
+
+ // Equal or one is not specified.
+ private boolean xorEqualsInetAddress(InetAddress first, InetAddress second) {
+ return first == null || second == null || first.equals(second);
+ }
+
+ // Equal or one is not specified.
+ private boolean xorEqualsURL(URL first, URL second) {
+ return first == null || second == null || first.equals(second);
+ }
+
+ // Equal or one is not specified.
+ private boolean xorEqualsPort(int first, int second) {
+ return first == -1 || second == -1 || Objects.equals(first, second);
+ }
+
+ // Helper function to convert APN string into a 32-bit bitmask.
+ private static int getApnBitmask(String apn) {
+ switch (apn) {
+ case TYPE_DEFAULT: return ApnTypes.DEFAULT;
+ case TYPE_MMS: return ApnTypes.MMS;
+ case TYPE_SUPL: return ApnTypes.SUPL;
+ case TYPE_DUN: return ApnTypes.DUN;
+ case TYPE_HIPRI: return ApnTypes.HIPRI;
+ case TYPE_FOTA: return ApnTypes.FOTA;
+ case TYPE_IMS: return ApnTypes.IMS;
+ case TYPE_CBS: return ApnTypes.CBS;
+ case TYPE_IA: return ApnTypes.IA;
+ case TYPE_EMERGENCY: return ApnTypes.EMERGENCY;
+ case TYPE_ALL: return ApnTypes.ALL;
+ default: return ApnTypes.NONE;
+ }
+ }
+
+ private String deParseTypes(List<String> types) {
+ if (types == null) {
+ return null;
+ }
+ return TextUtils.join(",", types);
+ }
+
+ /** @hide */
+ // Called by DPM.
+ public ContentValues toContentValues() {
+ ContentValues apnValue = new ContentValues();
+ if (mOperatorNumeric != null) {
+ apnValue.put(Telephony.Carriers.NUMERIC, mOperatorNumeric);
+ }
+ if (mEntryName != null) {
+ apnValue.put(Telephony.Carriers.NAME, mEntryName);
+ }
+ if (mApnName != null) {
+ apnValue.put(Telephony.Carriers.APN, mApnName);
+ }
+ if (mProxy != null) {
+ apnValue.put(Telephony.Carriers.PROXY, inetAddressToString(mProxy));
+ }
+ apnValue.put(Telephony.Carriers.PORT, portToString(mPort));
+ if (mMmsc != null) {
+ apnValue.put(Telephony.Carriers.MMSC, URLToString(mMmsc));
+ }
+ apnValue.put(Telephony.Carriers.MMSPORT, portToString(mMmsPort));
+ if (mMmsProxy != null) {
+ apnValue.put(Telephony.Carriers.MMSPROXY, inetAddressToString(mMmsProxy));
+ }
+ if (mUser != null) {
+ apnValue.put(Telephony.Carriers.USER, mUser);
+ }
+ if (mPassword != null) {
+ apnValue.put(Telephony.Carriers.PASSWORD, mPassword);
+ }
+ apnValue.put(Telephony.Carriers.AUTH_TYPE, mAuthType);
+ String apnType = deParseTypes(mTypes);
+ if (apnType != null) {
+ apnValue.put(Telephony.Carriers.TYPE, apnType);
+ }
+ if (mProtocol != null) {
+ apnValue.put(Telephony.Carriers.PROTOCOL, mProtocol);
+ }
+ if (mRoamingProtocol != null) {
+ apnValue.put(Telephony.Carriers.ROAMING_PROTOCOL, mRoamingProtocol);
+ }
+ apnValue.put(Telephony.Carriers.CARRIER_ENABLED, mCarrierEnabled);
+ // networkTypeBit.
+ apnValue.put(Telephony.Carriers.BEARER_BITMASK, mBearerBitmask);
+ if (mMvnoType != null) {
+ apnValue.put(Telephony.Carriers.MVNO_TYPE, mMvnoType);
+ }
+
+ return apnValue;
+ }
+
+ /**
+ * @param types comma delimited list of APN types
+ * @return array of APN types
+ * @hide
+ */
+ public static String[] parseTypes(String types) {
+ String[] result;
+ // If unset, set to DEFAULT.
+ if (TextUtils.isEmpty(types)) {
+ result = new String[1];
+ result[0] = TYPE_ALL;
+ } else {
+ result = types.split(",");
+ }
+ return result;
+ }
+
+ private static URL URLFromString(String url) {
+ try {
+ return TextUtils.isEmpty(url) ? null : new URL(url);
+ } catch (MalformedURLException e) {
+ Log.e(LOG_TAG, "Can't parse URL from string.");
+ return null;
+ }
+ }
+
+ private static String URLToString(URL url) {
+ return url == null ? "" : url.toString();
+ }
+
+ private static InetAddress inetAddressFromString(String inetAddress) {
+ if (TextUtils.isEmpty(inetAddress)) {
+ return null;
+ }
+ try {
+ return InetAddress.getByName(inetAddress);
+ } catch (UnknownHostException e) {
+ Log.e(LOG_TAG, "Can't parse InetAddress from string: unknown host.");
+ return null;
+ }
+ }
+
+ private static String inetAddressToString(InetAddress inetAddress) {
+ if (inetAddress == null) {
+ return null;
+ }
+ return TextUtils.isEmpty(inetAddress.getHostName())
+ ? inetAddress.getHostAddress() : inetAddress.getHostName();
+ }
+
+ private static int portFromString(String strPort) {
+ int port = -1;
+ if (!TextUtils.isEmpty(strPort)) {
+ try {
+ port = Integer.parseInt(strPort);
+ } catch (NumberFormatException e) {
+ Log.e(LOG_TAG, "Can't parse port from String");
+ }
+ }
+ return port;
+ }
+
+ private static String portToString(int port) {
+ return port == -1 ? "" : Integer.toString(port);
+ }
+
+ // Implement Parcelable.
+ @Override
+ /** @hide */
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ /** @hide */
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeInt(mId);
+ dest.writeString(mOperatorNumeric);
+ dest.writeString(mEntryName);
+ dest.writeString(mApnName);
+ dest.writeValue(mProxy);
+ dest.writeInt(mPort);
+ dest.writeValue(mMmsc);
+ dest.writeValue(mMmsProxy);
+ dest.writeInt(mMmsPort);
+ dest.writeString(mUser);
+ dest.writeString(mPassword);
+ dest.writeInt(mAuthType);
+ dest.writeStringArray(mTypes.toArray(new String[0]));
+ dest.writeString(mProtocol);
+ dest.writeString(mRoamingProtocol);
+ dest.writeInt(mCarrierEnabled ? 1: 0);
+ dest.writeString(mMvnoType);
+ }
+
+ private static ApnSetting readFromParcel(Parcel in) {
+ return makeApnSetting(in.readInt(), in.readString(), in.readString(), in.readString(),
+ (InetAddress)in.readValue(InetAddress.class.getClassLoader()),
+ in.readInt(), (URL)in.readValue(URL.class.getClassLoader()),
+ (InetAddress)in.readValue(InetAddress.class.getClassLoader()),
+ in.readInt(), in.readString(), in.readString(), in.readInt(),
+ Arrays.asList(in.readStringArray()), in.readString(), in.readString(),
+ in.readInt() > 0, 0, 0, 0, false, 0, 0, 0, 0, in.readString(), null);
+ }
+
+ public static final Parcelable.Creator<ApnSetting> CREATOR =
+ new Parcelable.Creator<ApnSetting>() {
+ @Override
+ public ApnSetting createFromParcel(Parcel in) {
+ return readFromParcel(in);
+ }
+
+ @Override
+ public ApnSetting[] newArray(int size) {
+ return new ApnSetting[size];
+ }
+ };
+
+ /**
+ * APN types for data connections. These are usage categories for an APN
+ * entry. One APN entry may support multiple APN types, eg, a single APN
+ * may service regular internet traffic ("default") as well as MMS-specific
+ * connections.<br/>
+ * ALL is a special type to indicate that this APN entry can
+ * service all data connections.
+ */
+ public static final String TYPE_ALL = "*";
+ /** APN type for default data traffic */
+ public static final String TYPE_DEFAULT = "default";
+ /** APN type for MMS traffic */
+ public static final String TYPE_MMS = "mms";
+ /** APN type for SUPL assisted GPS */
+ public static final String TYPE_SUPL = "supl";
+ /** APN type for DUN traffic */
+ public static final String TYPE_DUN = "dun";
+ /** APN type for HiPri traffic */
+ public static final String TYPE_HIPRI = "hipri";
+ /** APN type for FOTA */
+ public static final String TYPE_FOTA = "fota";
+ /** APN type for IMS */
+ public static final String TYPE_IMS = "ims";
+ /** APN type for CBS */
+ public static final String TYPE_CBS = "cbs";
+ /** APN type for IA Initial Attach APN */
+ public static final String TYPE_IA = "ia";
+ /** APN type for Emergency PDN. This is not an IA apn, but is used
+ * for access to carrier services in an emergency call situation. */
+ public static final String TYPE_EMERGENCY = "emergency";
+ /**
+ * Array of all APN types
+ *
+ * @hide
+ */
+ public static final String[] ALL_TYPES = {
+ TYPE_DEFAULT,
+ TYPE_MMS,
+ TYPE_SUPL,
+ TYPE_DUN,
+ TYPE_HIPRI,
+ TYPE_FOTA,
+ TYPE_IMS,
+ TYPE_CBS,
+ TYPE_IA,
+ TYPE_EMERGENCY
+ };
+
+ // Possible values for authentication types.
+ public static final int AUTH_TYPE_NONE = 0;
+ public static final int AUTH_TYPE_PAP = 1;
+ public static final int AUTH_TYPE_CHAP = 2;
+ public static final int AUTH_TYPE_PAP_OR_CHAP = 3;
+
+ // Possible values for protocol.
+ public static final String PROTOCOL_IP = "IP";
+ public static final String PROTOCOL_IPV6 = "IPV6";
+ public static final String PROTOCOL_IPV4V6 = "IPV4V6";
+ public static final String PROTOCOL_PPP = "PPP";
+
+ // Possible values for MVNO type.
+ public static final String MVNO_TYPE_SPN = "spn";
+ public static final String MVNO_TYPE_IMSI = "imsi";
+ public static final String MVNO_TYPE_GID = "gid";
+ public static final String MVNO_TYPE_ICCID = "iccid";
+
+ public static class Builder{
+ private String mEntryName;
+ private String mApnName;
+ private InetAddress mProxy;
+ private int mPort = -1;
+ private URL mMmsc;
+ private InetAddress mMmsProxy;
+ private int mMmsPort = -1;
+ private String mUser;
+ private String mPassword;
+ private int mAuthType;
+ private List<String> mTypes;
+ private int mTypesBitmap;
+ private int mId;
+ private String mOperatorNumeric;
+ private String mProtocol;
+ private String mRoamingProtocol;
+ private int mMtu;
+ private boolean mCarrierEnabled;
+ private int mBearer;
+ private int mBearerBitmask;
+ private int mProfileId;
+ private boolean mModemCognitive;
+ private int mMaxConns;
+ private int mWaitTime;
+ private int mMaxConnsTime;
+ private String mMvnoType;
+ private String mMvnoMatchData;
+
+ /**
+ * Default constructor for Builder.
+ */
+ public Builder() {}
+
+ /**
+ * Set the MTU size of the mobile interface to which the APN connected.
+ *
+ * @param mtu the MTU size to set for the APN
+ * @hide
+ */
+ public Builder setMtu(int mtu) {
+ this.mMtu = mtu;
+ return this;
+ }
+
+ /**
+ * Sets bearer info.
+ *
+ * @param bearer the bearer info to set for the APN
+ * @hide
+ */
+ public Builder setBearer(int bearer) {
+ this.mBearer = bearer;
+ return this;
+ }
+
+ /**
+ * Sets the radio access technology bitmask for this APN.
+ *
+ * @param bearerBitmask the radio access technology bitmask to set for this APN
+ * @hide
+ */
+ public Builder setBearerBitmask(int bearerBitmask) {
+ this.mBearerBitmask = bearerBitmask;
+ return this;
+ }
+
+ /**
+ * Sets the profile id to which the APN saved in modem.
+ *
+ * @param profileId the profile id to set for the APN
+ * @hide
+ */
+ public Builder setProfileId(int profileId) {
+ this.mProfileId = profileId;
+ return this;
+ }
+
+ /**
+ * Sets if the APN setting is to be set in modem.
+ *
+ * @param modemCognitive if the APN setting is to be set in modem
+ * @hide
+ */
+ public Builder setModemCognitive(boolean modemCognitive) {
+ this.mModemCognitive = modemCognitive;
+ return this;
+ }
+
+ /**
+ * Sets the max connections of this APN.
+ *
+ * @param maxConns the max connections of this APN
+ * @hide
+ */
+ public Builder setMaxConns(int maxConns) {
+ this.mMaxConns = maxConns;
+ return this;
+ }
+
+ /**
+ * Sets the wait time for retry of the APN.
+ *
+ * @param waitTime the wait time for retry of the APN
+ * @hide
+ */
+ public Builder setWaitTime(int waitTime) {
+ this.mWaitTime = waitTime;
+ return this;
+ }
+
+ /**
+ * Sets the time to limit max connection for the APN.
+ *
+ * @param maxConnsTime the time to limit max connection for the APN
+ * @hide
+ */
+ public Builder setMaxConnsTime(int maxConnsTime) {
+ this.mMaxConnsTime = maxConnsTime;
+ return this;
+ }
+
+ /**
+ * Sets the MVNO match data for the APN.
+ *
+ * @param mvnoMatchData the MVNO match data for the APN
+ * @hide
+ */
+ public Builder setMvnoMatchData(String mvnoMatchData) {
+ this.mMvnoMatchData = mvnoMatchData;
+ return this;
+ }
+
+ /**
+ * Sets the entry name of the APN.
+ *
+ * @param entryName the entry name to set for the APN
+ */
+ public Builder setEntryName(String entryName) {
+ this.mEntryName = entryName;
+ return this;
+ }
+
+ /**
+ * Sets the name of the APN.
+ *
+ * @param apnName the name to set for the APN
+ */
+ public Builder setApnName(String apnName) {
+ this.mApnName = apnName;
+ return this;
+ }
+
+ /**
+ * Sets the proxy address of the APN.
+ *
+ * @param proxy the proxy address to set for the APN
+ */
+ public Builder setProxy(InetAddress proxy) {
+ this.mProxy = proxy;
+ return this;
+ }
+
+ /**
+ * Sets the proxy port of the APN.
+ *
+ * @param port the proxy port to set for the APN
+ */
+ public Builder setPort(int port) {
+ this.mPort = port;
+ return this;
+ }
+
+ /**
+ * Sets the MMSC URL of the APN.
+ *
+ * @param mmsc the MMSC URL to set for the APN
+ */
+ public Builder setMmsc(URL mmsc) {
+ this.mMmsc = mmsc;
+ return this;
+ }
+
+ /**
+ * Sets the MMS proxy address of the APN.
+ *
+ * @param mmsProxy the MMS proxy address to set for the APN
+ */
+ public Builder setMmsProxy(InetAddress mmsProxy) {
+ this.mMmsProxy = mmsProxy;
+ return this;
+ }
+
+ /**
+ * Sets the MMS proxy port of the APN.
+ *
+ * @param mmsPort the MMS proxy port to set for the APN
+ */
+ public Builder setMmsPort(int mmsPort) {
+ this.mMmsPort = mmsPort;
+ return this;
+ }
+
+ /**
+ * Sets the APN username of the APN.
+ *
+ * @param user the APN username to set for the APN
+ */
+ public Builder setUser(String user) {
+ this.mUser = user;
+ return this;
+ }
+
+ /**
+ * Sets the APN password of the APN.
+ *
+ * @see android.provider.Telephony.Carriers#PASSWORD
+ * @param password the APN password to set for the APN
+ */
+ public Builder setPassword(String password) {
+ this.mPassword = password;
+ return this;
+ }
+
+ /**
+ * Sets the authentication type of the APN.
+ *
+ * Example of possible values: {@link #AUTH_TYPE_NONE}, {@link #AUTH_TYPE_PAP}.
+ *
+ * @param authType the authentication type to set for the APN
+ */
+ public Builder setAuthType(@AuthType int authType) {
+ this.mAuthType = authType;
+ return this;
+ }
+
+ /**
+ * Sets the list of APN types of the APN.
+ *
+ * Example of possible values: {@link #TYPE_DEFAULT}, {@link #TYPE_MMS}.
+ *
+ * @param types the list of APN types to set for the APN
+ */
+ public Builder setTypes(@ApnType List<String> types) {
+ this.mTypes = types;
+ int apnBitmap = 0;
+ for (int i = 0; i < mTypes.size(); i++) {
+ mTypes.set(i, mTypes.get(i).toLowerCase());
+ apnBitmap |= getApnBitmask(mTypes.get(i));
+ }
+ this.mTypesBitmap = apnBitmap;
+ return this;
+ }
+
+ /**
+ * Sets the unique database id for this entry.
+ *
+ * @param id the unique database id to set for this entry
+ */
+ public Builder setId(int id) {
+ this.mId = id;
+ return this;
+ }
+
+ /**
+ * Set the numeric operator ID for the APN.
+ *
+ * @param operatorNumeric the numeric operator ID to set for this entry
+ */
+ public Builder setOperatorNumeric(String operatorNumeric) {
+ this.mOperatorNumeric = operatorNumeric;
+ return this;
+ }
+
+ /**
+ * Sets the protocol to use to connect to this APN.
+ *
+ * One of the {@code PDP_type} values in TS 27.007 section 10.1.1.
+ * Example of possible values: {@link #PROTOCOL_IP}, {@link #PROTOCOL_IPV6}.
+ *
+ * @param protocol the protocol to set to use to connect to this APN
+ */
+ public Builder setProtocol(@ProtocolType String protocol) {
+ this.mProtocol = protocol;
+ return this;
+ }
+
+ /**
+ * Sets the protocol to use to connect to this APN when roaming.
+ *
+ * @param roamingProtocol the protocol to set to use to connect to this APN when roaming
+ */
+ public Builder setRoamingProtocol(String roamingProtocol) {
+ this.mRoamingProtocol = roamingProtocol;
+ return this;
+ }
+
+ /**
+ * Sets the current status of APN.
+ *
+ * @param carrierEnabled the current status to set for this APN
+ */
+ public Builder setCarrierEnabled(boolean carrierEnabled) {
+ this.mCarrierEnabled = carrierEnabled;
+ return this;
+ }
+
+ /**
+ * Sets the MVNO match type for this APN.
+ *
+ * Example of possible values: {@link #MVNO_TYPE_SPN}, {@link #MVNO_TYPE_IMSI}.
+ *
+ * @param mvnoType the MVNO match type to set for this APN
+ */
+ public Builder setMvnoType(@MvnoType String mvnoType) {
+ this.mMvnoType = mvnoType;
+ return this;
+ }
+
+ public ApnSetting build() {
+ return new ApnSetting(this);
+ }
+ }
+}
+
diff --git a/telephony/java/android/telephony/data/DataCallResponse.java b/telephony/java/android/telephony/data/DataCallResponse.java
index da51c86..ef3a183 100644
--- a/telephony/java/android/telephony/data/DataCallResponse.java
+++ b/telephony/java/android/telephony/data/DataCallResponse.java
@@ -20,6 +20,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
+import android.net.LinkAddress;
import android.os.Parcel;
import android.os.Parcelable;
@@ -40,7 +41,7 @@
private final int mActive;
private final String mType;
private final String mIfname;
- private final List<InterfaceAddress> mAddresses;
+ private final List<LinkAddress> mAddresses;
private final List<InetAddress> mDnses;
private final List<InetAddress> mGateways;
private final List<String> mPcscfs;
@@ -71,7 +72,7 @@
*/
public DataCallResponse(int status, int suggestedRetryTime, int cid, int active,
@Nullable String type, @Nullable String ifname,
- @Nullable List<InterfaceAddress> addresses,
+ @Nullable List<LinkAddress> addresses,
@Nullable List<InetAddress> dnses,
@Nullable List<InetAddress> gateways,
@Nullable List<String> pcscfs, int mtu) {
@@ -96,7 +97,7 @@
mType = source.readString();
mIfname = source.readString();
mAddresses = new ArrayList<>();
- source.readList(mAddresses, InterfaceAddress.class.getClassLoader());
+ source.readList(mAddresses, LinkAddress.class.getClassLoader());
mDnses = new ArrayList<>();
source.readList(mDnses, InetAddress.class.getClassLoader());
mGateways = new ArrayList<>();
@@ -140,10 +141,10 @@
public String getIfname() { return mIfname; }
/**
- * @return A list of {@link InterfaceAddress}
+ * @return A list of {@link LinkAddress}
*/
@NonNull
- public List<InterfaceAddress> getAddresses() { return mAddresses; }
+ public List<LinkAddress> getAddresses() { return mAddresses; }
/**
* @return A list of DNS server addresses, e.g., "192.0.1.3" or
diff --git a/telephony/java/android/telephony/data/InterfaceAddress.java b/telephony/java/android/telephony/data/InterfaceAddress.java
deleted file mode 100644
index 00d212a..0000000
--- a/telephony/java/android/telephony/data/InterfaceAddress.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright 2017 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 android.telephony.data;
-
-import android.annotation.SystemApi;
-import android.net.NetworkUtils;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-
-/**
- * This class represents a Network Interface address. In short it's an IP address, a subnet mask
- * when the address is an IPv4 one. An IP address and a network prefix length in the case of IPv6
- * address.
- *
- * @hide
- */
-@SystemApi
-public final class InterfaceAddress implements Parcelable {
-
- private final InetAddress mInetAddress;
-
- private final int mPrefixLength;
-
- /**
- * @param inetAddress A {@link InetAddress} of the address
- * @param prefixLength The network prefix length for this address.
- */
- public InterfaceAddress(InetAddress inetAddress, int prefixLength) {
- mInetAddress = inetAddress;
- mPrefixLength = prefixLength;
- }
-
- /**
- * @param address The address in string format
- * @param prefixLength The network prefix length for this address.
- * @throws UnknownHostException
- */
- public InterfaceAddress(String address, int prefixLength) throws UnknownHostException {
- InetAddress ia;
- try {
- ia = NetworkUtils.numericToInetAddress(address);
- } catch (IllegalArgumentException e) {
- throw new UnknownHostException("Non-numeric ip addr=" + address);
- }
- mInetAddress = ia;
- mPrefixLength = prefixLength;
- }
-
- public InterfaceAddress(Parcel source) {
- mInetAddress = (InetAddress) source.readSerializable();
- mPrefixLength = source.readInt();
- }
-
- /**
- * @return an InetAddress for this address.
- */
- public InetAddress getAddress() { return mInetAddress; }
-
- /**
- * @return The network prefix length for this address.
- */
- public int getNetworkPrefixLength() { return mPrefixLength; }
-
- @Override
- public boolean equals (Object o) {
- if (this == o) return true;
-
- if (o == null || !(o instanceof InterfaceAddress)) {
- return false;
- }
-
- InterfaceAddress other = (InterfaceAddress) o;
- return this.mInetAddress.equals(other.mInetAddress)
- && this.mPrefixLength == other.mPrefixLength;
- }
-
- @Override
- public int hashCode() {
- return mInetAddress.hashCode() * 31 + mPrefixLength * 37;
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public String toString() {
- return mInetAddress + "/" + mPrefixLength;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeSerializable(mInetAddress);
- dest.writeInt(mPrefixLength);
- }
-
- public static final Parcelable.Creator<InterfaceAddress> CREATOR =
- new Parcelable.Creator<InterfaceAddress>() {
- @Override
- public InterfaceAddress createFromParcel(Parcel source) {
- return new InterfaceAddress(source);
- }
-
- @Override
- public InterfaceAddress[] newArray(int size) {
- return new InterfaceAddress[size];
- }
- };
-}
diff --git a/telephony/java/android/telephony/euicc/EuiccCardManager.java b/telephony/java/android/telephony/euicc/EuiccCardManager.java
new file mode 100644
index 0000000..29849c1
--- /dev/null
+++ b/telephony/java/android/telephony/euicc/EuiccCardManager.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2018 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 android.telephony.euicc;
+
+import android.content.Context;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.service.euicc.EuiccProfileInfo;
+import android.util.Log;
+
+import com.android.internal.telephony.euicc.IEuiccCardController;
+import com.android.internal.telephony.euicc.IGetAllProfilesCallback;
+
+/**
+ * EuiccCardManager is the application interface to an eSIM card.
+ *
+ * @hide
+ *
+ * TODO(b/35851809): Make this a SystemApi.
+ */
+public class EuiccCardManager {
+ private static final String TAG = "EuiccCardManager";
+
+ /** Result code of execution with no error. */
+ public static final int RESULT_OK = 0;
+
+ /**
+ * Callback to receive the result of an eUICC card API.
+ *
+ * @param <T> Type of the result.
+ */
+ public interface ResultCallback<T> {
+ /**
+ * This method will be called when an eUICC card API call is completed.
+ *
+ * @param resultCode This can be {@link #RESULT_OK} or other positive values returned by the
+ * eUICC.
+ * @param result The result object. It can be null if the {@code resultCode} is not
+ * {@link #RESULT_OK}.
+ */
+ void onComplete(int resultCode, T result);
+ }
+
+ private final Context mContext;
+
+ /** @hide */
+ public EuiccCardManager(Context context) {
+ mContext = context;
+ }
+
+ private IEuiccCardController getIEuiccCardController() {
+ return IEuiccCardController.Stub.asInterface(
+ ServiceManager.getService("euicc_card_controller"));
+ }
+
+ /**
+ * Gets all the profiles on eUicc.
+ *
+ * @param callback the callback to get the result code and all the profiles.
+ */
+ public void getAllProfiles(ResultCallback<EuiccProfileInfo[]> callback) {
+ try {
+ getIEuiccCardController().getAllProfiles(mContext.getOpPackageName(),
+ new IGetAllProfilesCallback.Stub() {
+ @Override
+ public void onComplete(int resultCode, EuiccProfileInfo[] profiles) {
+ callback.onComplete(resultCode, profiles);
+ }
+ });
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error calling getAllProfiles", e);
+ throw e.rethrowFromSystemServer();
+ }
+ }
+}
diff --git a/telephony/java/android/telephony/euicc/EuiccManager.java b/telephony/java/android/telephony/euicc/EuiccManager.java
index f777649..3dfadf5 100644
--- a/telephony/java/android/telephony/euicc/EuiccManager.java
+++ b/telephony/java/android/telephony/euicc/EuiccManager.java
@@ -60,6 +60,20 @@
public static final String ACTION_MANAGE_EMBEDDED_SUBSCRIPTIONS =
"android.telephony.euicc.action.MANAGE_EMBEDDED_SUBSCRIPTIONS";
+
+ /**
+ * Broadcast Action: The eUICC OTA status is changed.
+ * <p class="note">
+ * Requires the {@link android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission.
+ *
+ * <p class="note">This is a protected intent that can only be sent
+ * by the system.
+ * TODO(b/35851809): Make this a SystemApi.
+ */
+ @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_OTA_STATUS_CHANGED
+ = "android.telephony.euicc.action.OTA_STATUS_CHANGED";
+
/**
* Intent action to provision an embedded subscription.
*
diff --git a/telephony/java/android/telephony/euicc/EuiccNotification.java b/telephony/java/android/telephony/euicc/EuiccNotification.java
new file mode 100644
index 0000000..ef3c1ce
--- /dev/null
+++ b/telephony/java/android/telephony/euicc/EuiccNotification.java
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2018 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 android.telephony.euicc;
+
+import android.annotation.IntDef;
+import android.annotation.Nullable;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Arrays;
+import java.util.Objects;
+
+/**
+ * This represents a signed notification which is defined in SGP.22. It can be either a profile
+ * installation result or a notification generated for profile operations (e.g., enabling,
+ * disabling, or deleting).
+ *
+ * @hide
+ *
+ * TODO(b/35851809): Make this a @SystemApi.
+ */
+public class EuiccNotification implements Parcelable {
+ /** Event */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(flag = true, prefix = { "EVENT_" }, value = {
+ EVENT_INSTALL,
+ EVENT_ENABLE,
+ EVENT_DISABLE,
+ EVENT_DELETE
+ })
+ public @interface Event {}
+
+ /** A profile is downloaded and installed. */
+ public static final int EVENT_INSTALL = 1;
+
+ /** A profile is enabled. */
+ public static final int EVENT_ENABLE = 1 << 1;
+
+ /** A profile is disabled. */
+ public static final int EVENT_DISABLE = 1 << 2;
+
+ /** A profile is deleted. */
+ public static final int EVENT_DELETE = 1 << 3;
+
+ /** Value of the bits of all above events */
+ @Event
+ public static final int ALL_EVENTS =
+ EVENT_INSTALL | EVENT_ENABLE | EVENT_DISABLE | EVENT_DELETE;
+
+ private final int mSeq;
+ private final String mTargetAddr;
+ @Event private final int mEvent;
+ @Nullable private final byte[] mData;
+
+ /**
+ * Creates an instance.
+ *
+ * @param seq The sequence number of this notification.
+ * @param targetAddr The target server where to send this notification.
+ * @param event The event which causes this notification.
+ * @param data The data which needs to be sent to the target server. This can be null for
+ * building a list of notification metadata without data.
+ */
+ public EuiccNotification(int seq, String targetAddr, @Event int event, @Nullable byte[] data) {
+ mSeq = seq;
+ mTargetAddr = targetAddr;
+ mEvent = event;
+ mData = data;
+ }
+
+ /** @return The sequence number of this notification. */
+ public int getSeq() {
+ return mSeq;
+ }
+
+ /** @return The target server address where this notification should be sent to. */
+ public String getTargetAddr() {
+ return mTargetAddr;
+ }
+
+ /** @return The event of this notification. */
+ @Event
+ public int getEvent() {
+ return mEvent;
+ }
+
+ /** @return The notification data which needs to be sent to the target server. */
+ @Nullable
+ public byte[] getData() {
+ return mData;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+
+ EuiccNotification that = (EuiccNotification) obj;
+ return mSeq == that.mSeq
+ && Objects.equals(mTargetAddr, that.mTargetAddr)
+ && mEvent == that.mEvent
+ && Arrays.equals(mData, that.mData);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = 1;
+ result = 31 * result + mSeq;
+ result = 31 * result + Objects.hashCode(mTargetAddr);
+ result = 31 * result + mEvent;
+ result = 31 * result + Arrays.hashCode(mData);
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "EuiccNotification (seq="
+ + mSeq
+ + ", targetAddr="
+ + mTargetAddr
+ + ", event="
+ + mEvent
+ + ", data="
+ + (mData == null ? "null" : "byte[" + mData.length + "]")
+ + ")";
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(mSeq);
+ dest.writeString(mTargetAddr);
+ dest.writeInt(mEvent);
+ dest.writeByteArray(mData);
+ }
+
+ private EuiccNotification(Parcel source) {
+ mSeq = source.readInt();
+ mTargetAddr = source.readString();
+ mEvent = source.readInt();
+ mData = source.createByteArray();
+ }
+
+ public static final Creator<EuiccNotification> CREATOR =
+ new Creator<EuiccNotification>() {
+ @Override
+ public EuiccNotification createFromParcel(Parcel source) {
+ return new EuiccNotification(source);
+ }
+
+ @Override
+ public EuiccNotification[] newArray(int size) {
+ return new EuiccNotification[size];
+ }
+ };
+}
diff --git a/telephony/java/android/telephony/euicc/EuiccRat.java b/telephony/java/android/telephony/euicc/EuiccRat.java
new file mode 100644
index 0000000..6a56503a
--- /dev/null
+++ b/telephony/java/android/telephony/euicc/EuiccRat.java
@@ -0,0 +1,259 @@
+/*
+ * Copyright (C) 2018 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 android.telephony.euicc;
+
+import android.annotation.IntDef;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.service.carrier.CarrierIdentifier;
+import android.service.euicc.EuiccProfileInfo;
+import android.text.TextUtils;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Arrays;
+
+/**
+ * This represents the RAT (Rules Authorisation Table) stored on eUICC.
+ *
+ * @hide
+ *
+ * TODO(b/35851809): Make this a @SystemApi.
+ */
+public final class EuiccRat implements Parcelable {
+ /** Profile policy rule flags */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(flag = true, prefix = { "POLICY_RULE_FLAG_" }, value = {
+ POLICY_RULE_FLAG_CONSENT_REQUIRED
+ })
+ public @interface PolicyRuleFlag {}
+
+ /** User consent is required to install the profile. */
+ public static final int POLICY_RULE_FLAG_CONSENT_REQUIRED = 1;
+
+ private final int[] mPolicyRules;
+ private final CarrierIdentifier[][] mCarrierIds;
+ private final int[] mPolicyRuleFlags;
+
+ /** This is used to build new {@link EuiccRat} instance. */
+ public static final class Builder {
+ private int[] mPolicyRules;
+ private CarrierIdentifier[][] mCarrierIds;
+ private int[] mPolicyRuleFlags;
+ private int mPosition;
+
+ /**
+ * Creates a new builder.
+ *
+ * @param ruleNum The number of authorisation rules in the table.
+ */
+ public Builder(int ruleNum) {
+ mPolicyRules = new int[ruleNum];
+ mCarrierIds = new CarrierIdentifier[ruleNum][];
+ mPolicyRuleFlags = new int[ruleNum];
+ }
+
+ /**
+ * Builds the RAT instance. This builder should not be used anymore after this method is
+ * called, otherwise {@link NullPointerException} will be thrown.
+ */
+ public EuiccRat build() {
+ if (mPosition != mPolicyRules.length) {
+ throw new IllegalStateException(
+ "Not enough rules are added, expected: "
+ + mPolicyRules.length
+ + ", added: "
+ + mPosition);
+ }
+ return new EuiccRat(mPolicyRules, mCarrierIds, mPolicyRuleFlags);
+ }
+
+ /**
+ * Adds an authorisation rule.
+ *
+ * @throws ArrayIndexOutOfBoundsException If the {@code mPosition} is larger than the size
+ * this table.
+ */
+ public Builder add(int policyRules, CarrierIdentifier[] carrierId, int policyRuleFlags) {
+ if (mPosition >= mPolicyRules.length) {
+ throw new ArrayIndexOutOfBoundsException(mPosition);
+ }
+ mPolicyRules[mPosition] = policyRules;
+ mCarrierIds[mPosition] = carrierId;
+ mPolicyRuleFlags[mPosition] = policyRuleFlags;
+ mPosition++;
+ return this;
+ }
+ }
+
+ /**
+ * @param mccRule A 2-character or 3-character string which can be either MCC or MNC. The
+ * character 'E' is used as a wild char to match any digit.
+ * @param mcc A 2-character or 3-character string which can be either MCC or MNC.
+ * @return Whether the {@code mccRule} matches {@code mcc}.
+ *
+ * @hide
+ */
+ @VisibleForTesting
+ public static boolean match(String mccRule, String mcc) {
+ if (mccRule.length() < mcc.length()) {
+ return false;
+ }
+ for (int i = 0; i < mccRule.length(); i++) {
+ // 'E' is the wild char to match any digit.
+ if (mccRule.charAt(i) == 'E'
+ || (i < mcc.length() && mccRule.charAt(i) == mcc.charAt(i))) {
+ continue;
+ }
+ return false;
+ }
+ return true;
+ }
+
+ private EuiccRat(int[] policyRules, CarrierIdentifier[][] carrierIds, int[] policyRuleFlags) {
+ mPolicyRules = policyRules;
+ mCarrierIds = carrierIds;
+ mPolicyRuleFlags = policyRuleFlags;
+ }
+
+ /**
+ * Finds the index of the first authorisation rule matching the given policy and carrier id. If
+ * the returned index is not negative, the carrier is allowed to apply this policy to its
+ * profile.
+ *
+ * @param policy The policy rule.
+ * @param carrierId The carrier id.
+ * @return The index of authorization rule. If no rule is found, -1 will be returned.
+ */
+ public int findIndex(@EuiccProfileInfo.PolicyRule int policy, CarrierIdentifier carrierId) {
+ for (int i = 0; i < mPolicyRules.length; i++) {
+ if ((mPolicyRules[i] & policy) == 0) {
+ continue;
+ }
+ CarrierIdentifier[] carrierIds = mCarrierIds[i];
+ if (carrierIds == null || carrierIds.length == 0) {
+ continue;
+ }
+ for (int j = 0; j < carrierIds.length; j++) {
+ CarrierIdentifier ruleCarrierId = carrierIds[j];
+ if (!match(ruleCarrierId.getMcc(), carrierId.getMcc())
+ || !match(ruleCarrierId.getMnc(), carrierId.getMnc())) {
+ continue;
+ }
+ String gid = ruleCarrierId.getGid1();
+ if (!TextUtils.isEmpty(gid) && !gid.equals(carrierId.getGid1())) {
+ continue;
+ }
+ gid = ruleCarrierId.getGid2();
+ if (!TextUtils.isEmpty(gid) && !gid.equals(carrierId.getGid2())) {
+ continue;
+ }
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Tests if the entry in the table has the given policy rule flag.
+ *
+ * @param index The index of the entry.
+ * @param flag The policy rule flag to be tested.
+ * @throws ArrayIndexOutOfBoundsException If the {@code index} is negative or larger than the
+ * size of this table.
+ */
+ public boolean hasPolicyRuleFlag(int index, @PolicyRuleFlag int flag) {
+ if (index < 0 || index >= mPolicyRules.length) {
+ throw new ArrayIndexOutOfBoundsException(index);
+ }
+ return (mPolicyRuleFlags[index] & flag) != 0;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeIntArray(mPolicyRules);
+ for (CarrierIdentifier[] ids : mCarrierIds) {
+ dest.writeTypedArray(ids, flags);
+ }
+ dest.writeIntArray(mPolicyRuleFlags);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+
+ EuiccRat that = (EuiccRat) obj;
+ if (mCarrierIds.length != that.mCarrierIds.length) {
+ return false;
+ }
+ for (int i = 0; i < mCarrierIds.length; i++) {
+ CarrierIdentifier[] carrierIds = mCarrierIds[i];
+ CarrierIdentifier[] thatCarrierIds = that.mCarrierIds[i];
+ if (carrierIds != null && thatCarrierIds != null) {
+ if (carrierIds.length != thatCarrierIds.length) {
+ return false;
+ }
+ for (int j = 0; j < carrierIds.length; j++) {
+ if (!carrierIds[j].equals(thatCarrierIds[j])) {
+ return false;
+ }
+ }
+ continue;
+ } else if (carrierIds == null && thatCarrierIds == null) {
+ continue;
+ }
+ return false;
+ }
+
+ return Arrays.equals(mPolicyRules, that.mPolicyRules)
+ && Arrays.equals(mPolicyRuleFlags, that.mPolicyRuleFlags);
+ }
+
+ private EuiccRat(Parcel source) {
+ mPolicyRules = source.createIntArray();
+ int len = mPolicyRules.length;
+ mCarrierIds = new CarrierIdentifier[len][];
+ for (int i = 0; i < len; i++) {
+ mCarrierIds[i] = source.createTypedArray(CarrierIdentifier.CREATOR);
+ }
+ mPolicyRuleFlags = source.createIntArray();
+ }
+
+ public static final Creator<EuiccRat> CREATOR =
+ new Creator<EuiccRat>() {
+ @Override
+ public EuiccRat createFromParcel(Parcel source) {
+ return new EuiccRat(source);
+ }
+
+ @Override
+ public EuiccRat[] newArray(int size) {
+ return new EuiccRat[size];
+ }
+ };
+}
diff --git a/telephony/java/com/android/ims/ImsCallProfile.java b/telephony/java/com/android/ims/ImsCallProfile.java
index 489c208..693aaff 100644
--- a/telephony/java/com/android/ims/ImsCallProfile.java
+++ b/telephony/java/com/android/ims/ImsCallProfile.java
@@ -351,7 +351,7 @@
mServiceType = in.readInt();
mCallType = in.readInt();
mCallExtras = in.readBundle();
- mMediaProfile = in.readParcelable(null);
+ mMediaProfile = in.readParcelable(ImsStreamMediaProfile.class.getClassLoader());
}
public static final Creator<ImsCallProfile> CREATOR = new Creator<ImsCallProfile>() {
diff --git a/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl b/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl
index ac16139..8e3f4c0 100644
--- a/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl
+++ b/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl
@@ -46,5 +46,6 @@
void onVoiceActivationStateChanged(int activationState);
void onDataActivationStateChanged(int activationState);
void onCarrierNetworkChange(in boolean active);
+ void onUserMobileDataStateChanged(in boolean enabled);
}
diff --git a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
index 75d8f3f..188167c 100644
--- a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
@@ -69,4 +69,5 @@
int activationState, int activationType);
void notifySubscriptionInfoChanged();
void notifyCarrierNetworkChange(in boolean active);
+ void notifyUserMobileDataStateChangedForPhoneId(in int phoneId, in int subId, in boolean state);
}
diff --git a/telephony/java/android/telephony/data/InterfaceAddress.aidl b/telephony/java/com/android/internal/telephony/euicc/IEuiccCardController.aidl
similarity index 65%
copy from telephony/java/android/telephony/data/InterfaceAddress.aidl
copy to telephony/java/com/android/internal/telephony/euicc/IEuiccCardController.aidl
index d750363..2846a1a 100644
--- a/telephony/java/android/telephony/data/InterfaceAddress.aidl
+++ b/telephony/java/com/android/internal/telephony/euicc/IEuiccCardController.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright 2017 The Android Open Source Project
+ * Copyright (C) 2018 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.
@@ -14,7 +14,11 @@
* limitations under the License.
*/
-/** @hide */
-package android.telephony.data;
+package com.android.internal.telephony.euicc;
-parcelable InterfaceAddress;
+import com.android.internal.telephony.euicc.IGetAllProfilesCallback;
+
+/** @hide */
+interface IEuiccCardController {
+ oneway void getAllProfiles(String callingPackage, in IGetAllProfilesCallback callback);
+}
diff --git a/telephony/java/android/telephony/data/InterfaceAddress.aidl b/telephony/java/com/android/internal/telephony/euicc/IGetAllProfilesCallback.aidl
similarity index 68%
copy from telephony/java/android/telephony/data/InterfaceAddress.aidl
copy to telephony/java/com/android/internal/telephony/euicc/IGetAllProfilesCallback.aidl
index d750363..97b0768 100644
--- a/telephony/java/android/telephony/data/InterfaceAddress.aidl
+++ b/telephony/java/com/android/internal/telephony/euicc/IGetAllProfilesCallback.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright 2017 The Android Open Source Project
+ * Copyright (C) 2018 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.
@@ -13,8 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package com.android.internal.telephony.euicc;
+
+import android.service.euicc.EuiccProfileInfo;
/** @hide */
-package android.telephony.data;
-
-parcelable InterfaceAddress;
+oneway interface IGetAllProfilesCallback {
+ void onComplete(int resultCode, in EuiccProfileInfo[] profiles);
+}
diff --git a/legacy-test/Android.bp b/test-base/Android.bp
similarity index 66%
rename from legacy-test/Android.bp
rename to test-base/Android.bp
index 1173bc6..a42dc5a 100644
--- a/legacy-test/Android.bp
+++ b/test-base/Android.bp
@@ -14,6 +14,24 @@
// limitations under the License.
//
+// Build the android.test.base library
+// ===================================
+// This contains the junit.framework and android.test classes that were in
+// Android API level 25 excluding those from android.test.runner.
+// Also contains the com.android.internal.util.Predicate[s] classes.
+java_library {
+ name: "android.test.base",
+
+ srcs: ["src/**/*.java"],
+
+ no_framework_libs: true,
+ hostdex: true,
+ libs: [
+ "framework",
+ ],
+
+}
+
// Build the legacy-test library
// =============================
// This contains the junit.framework and android.test classes that were in
@@ -21,23 +39,27 @@
// Also contains the com.android.internal.util.Predicate[s] classes.
java_library {
name: "legacy-test",
-
- srcs: ["src/**/*.java"],
+ static_libs: ["android.test.base"],
no_framework_libs: true,
libs: [
"framework",
],
-
}
-// Build the repackaged-legacy-test library
-// ========================================
-// This contains repackaged versions of the classes from legacy-test.
+// Build the repackaged.android.test.base library
+// ==============================================
+// This contains repackaged versions of the classes from
+// android.test.base.
java_library_static {
- name: "repackaged-legacy-test",
+ name: "repackaged.android.test.base",
- static_libs: ["legacy-test"],
+ static_libs: ["android.test.base"],
+
+ no_framework_libs: true,
+ libs: [
+ "framework",
+ ],
jarjar_rules: "jarjar-rules.txt",
}
@@ -56,7 +78,7 @@
],
static_libs: [
- "android.test.runner",
+ "android.test.runner-minus-junit",
"android.test.mock",
],
diff --git a/test-base/Android.mk b/test-base/Android.mk
new file mode 100644
index 0000000..25c3d76
--- /dev/null
+++ b/test-base/Android.mk
@@ -0,0 +1,120 @@
+#
+# Copyright (C) 2016 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.
+#
+
+LOCAL_PATH:= $(call my-dir)
+
+# Generate the stub source files for legacy.test.stubs
+# ====================================================
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ $(call all-java-files-under, src)
+
+LOCAL_JAVA_LIBRARIES := \
+ core-oj \
+ core-libart \
+ framework \
+
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+LOCAL_DROIDDOC_SOURCE_PATH := $(LOCAL_PATH)/src
+
+ANDROID_TEST_BASE_OUTPUT_API_FILE := $(TARGET_OUT_COMMON_INTERMEDIATES)/JAVA_LIBRARIES/android.test.base.stubs_intermediates/api.txt
+ANDROID_TEST_BASE_OUTPUT_REMOVED_API_FILE := $(TARGET_OUT_COMMON_INTERMEDIATES)/JAVA_LIBRARIES/android.test.base.stubs_intermediates/removed.txt
+
+ANDROID_TEST_BASE_API_FILE := $(LOCAL_PATH)/api/android-test-base-current.txt
+ANDROID_TEST_BASE_REMOVED_API_FILE := $(LOCAL_PATH)/api/android-test-base-removed.txt
+
+LOCAL_DROIDDOC_OPTIONS:= \
+ -stubpackages android.test:android.test.suitebuilder.annotation:com.android.internal.util:junit.framework \
+ -stubsourceonly \
+ -stubs $(TARGET_OUT_COMMON_INTERMEDIATES)/JAVA_LIBRARIES/android.test.base.stubs_intermediates/src \
+ -nodocs \
+ -api $(ANDROID_TEST_BASE_OUTPUT_API_FILE) \
+ -removedApi $(ANDROID_TEST_BASE_OUTPUT_REMOVED_API_FILE) \
+
+LOCAL_UNINSTALLABLE_MODULE := true
+LOCAL_MODULE := android-test-base-api-stubs-gen
+
+include $(BUILD_DROIDDOC)
+
+# Remember the target that will trigger the code generation.
+android_test_base_gen_stamp := $(full_target)
+
+# Add some additional dependencies
+$(ANDROID_TEST_BASE_OUTPUT_API_FILE): $(full_target)
+$(ANDROID_TEST_BASE_OUTPUT_REMOVED_API_FILE): $(full_target)
+
+# Build the android.test.base.stubs library
+# =========================================
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := android.test.base.stubs
+
+LOCAL_SOURCE_FILES_ALL_GENERATED := true
+LOCAL_SDK_VERSION := current
+
+# Make sure to run droiddoc first to generate the stub source files.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(android_test_base_gen_stamp)
+android_test_base_gen_stamp :=
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+# Archive a copy of the classes.jar in SDK build.
+$(call dist-for-goals,sdk win_sdk,$(full_classes_jar):android.test.base.stubs.jar)
+
+# Check that the android.test.base.stubs library has not changed
+# ==============================================================
+
+# Check that the API we're building hasn't changed from the not-yet-released
+# SDK version.
+$(eval $(call check-api, \
+ check-android-test-base-api-current, \
+ $(ANDROID_TEST_BASE_API_FILE), \
+ $(ANDROID_TEST_BASE_OUTPUT_API_FILE), \
+ $(ANDROID_TEST_BASE_REMOVED_API_FILE), \
+ $(ANDROID_TEST_BASE_OUTPUT_REMOVED_API_FILE), \
+ -error 2 -error 3 -error 4 -error 5 -error 6 \
+ -error 7 -error 8 -error 9 -error 10 -error 11 -error 12 -error 13 -error 14 -error 15 \
+ -error 16 -error 17 -error 18 -error 19 -error 20 -error 21 -error 23 -error 24 \
+ -error 25 -error 26 -error 27, \
+ cat $(LOCAL_PATH)/api/apicheck_msg_android_test_base.txt, \
+ check-android-test-base-api, \
+ $(call doc-timestamp-for,android-test-base-api-stubs-gen) \
+ ))
+
+.PHONY: check-android-test-base-api
+checkapi: check-android-test-base-api
+
+.PHONY: update-android-test-base-api
+update-api: update-android-test-base-api
+
+update-android-test-base-api: $(ANDROID_TEST_BASE_OUTPUT_API_FILE) | $(ACP)
+ @echo Copying current.txt
+ $(hide) $(ACP) $(ANDROID_TEST_BASE_OUTPUT_API_FILE) $(ANDROID_TEST_BASE_API_FILE)
+ @echo Copying removed.txt
+ $(hide) $(ACP) $(ANDROID_TEST_BASE_OUTPUT_REMOVED_API_FILE) $(ANDROID_TEST_BASE_REMOVED_API_FILE)
+
+ifeq ($(HOST_OS),linux)
+# Build the legacy-performance-test-hostdex library
+# =================================================
+# This contains the android.test.PerformanceTestCase class only
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := src/android/test/PerformanceTestCase.java
+LOCAL_MODULE := legacy-performance-test-hostdex
+
+include $(BUILD_HOST_DALVIK_STATIC_JAVA_LIBRARY)
+endif # HOST_OS == linux
diff --git a/legacy-test/api/legacy-test-current.txt b/test-base/api/android-test-base-current.txt
similarity index 100%
rename from legacy-test/api/legacy-test-current.txt
rename to test-base/api/android-test-base-current.txt
diff --git a/legacy-test/api/legacy-test-removed.txt b/test-base/api/android-test-base-removed.txt
similarity index 100%
rename from legacy-test/api/legacy-test-removed.txt
rename to test-base/api/android-test-base-removed.txt
diff --git a/test-base/api/apicheck_msg_android_test_base.txt b/test-base/api/apicheck_msg_android_test_base.txt
new file mode 100644
index 0000000..144aecc
--- /dev/null
+++ b/test-base/api/apicheck_msg_android_test_base.txt
@@ -0,0 +1,17 @@
+
+******************************
+You have tried to change the API from what has been previously approved.
+
+To make these errors go away, you have two choices:
+ 1) You can add "@hide" javadoc comments to the methods, etc. listed in the
+ errors above.
+
+ 2) You can update android-test-base-current.txt by executing the following command:
+ make update-android-test-base-api
+
+ To submit the revised android-test-base-current.txt to the main Android repository,
+ you will need approval.
+******************************
+
+
+
diff --git a/legacy-test/jarjar-rules.txt b/test-base/jarjar-rules.txt
similarity index 100%
rename from legacy-test/jarjar-rules.txt
rename to test-base/jarjar-rules.txt
diff --git a/legacy-test/src/android/test/AndroidTestCase.java b/test-base/src/android/test/AndroidTestCase.java
similarity index 100%
rename from legacy-test/src/android/test/AndroidTestCase.java
rename to test-base/src/android/test/AndroidTestCase.java
diff --git a/legacy-test/src/android/test/FlakyTest.java b/test-base/src/android/test/FlakyTest.java
similarity index 100%
rename from legacy-test/src/android/test/FlakyTest.java
rename to test-base/src/android/test/FlakyTest.java
diff --git a/legacy-test/src/android/test/InstrumentationTestCase.java b/test-base/src/android/test/InstrumentationTestCase.java
similarity index 100%
rename from legacy-test/src/android/test/InstrumentationTestCase.java
rename to test-base/src/android/test/InstrumentationTestCase.java
diff --git a/legacy-test/src/android/test/InstrumentationTestSuite.java b/test-base/src/android/test/InstrumentationTestSuite.java
similarity index 100%
rename from legacy-test/src/android/test/InstrumentationTestSuite.java
rename to test-base/src/android/test/InstrumentationTestSuite.java
diff --git a/legacy-test/src/android/test/PerformanceTestCase.java b/test-base/src/android/test/PerformanceTestCase.java
similarity index 100%
rename from legacy-test/src/android/test/PerformanceTestCase.java
rename to test-base/src/android/test/PerformanceTestCase.java
diff --git a/legacy-test/src/android/test/RepetitiveTest.java b/test-base/src/android/test/RepetitiveTest.java
similarity index 100%
rename from legacy-test/src/android/test/RepetitiveTest.java
rename to test-base/src/android/test/RepetitiveTest.java
diff --git a/legacy-test/src/android/test/UiThreadTest.java b/test-base/src/android/test/UiThreadTest.java
similarity index 100%
rename from legacy-test/src/android/test/UiThreadTest.java
rename to test-base/src/android/test/UiThreadTest.java
diff --git a/legacy-test/src/android/test/package.html b/test-base/src/android/test/package.html
similarity index 100%
rename from legacy-test/src/android/test/package.html
rename to test-base/src/android/test/package.html
diff --git a/legacy-test/src/android/test/suitebuilder/annotation/LargeTest.java b/test-base/src/android/test/suitebuilder/annotation/LargeTest.java
similarity index 100%
rename from legacy-test/src/android/test/suitebuilder/annotation/LargeTest.java
rename to test-base/src/android/test/suitebuilder/annotation/LargeTest.java
diff --git a/legacy-test/src/android/test/suitebuilder/annotation/MediumTest.java b/test-base/src/android/test/suitebuilder/annotation/MediumTest.java
similarity index 100%
rename from legacy-test/src/android/test/suitebuilder/annotation/MediumTest.java
rename to test-base/src/android/test/suitebuilder/annotation/MediumTest.java
diff --git a/legacy-test/src/android/test/suitebuilder/annotation/SmallTest.java b/test-base/src/android/test/suitebuilder/annotation/SmallTest.java
similarity index 100%
rename from legacy-test/src/android/test/suitebuilder/annotation/SmallTest.java
rename to test-base/src/android/test/suitebuilder/annotation/SmallTest.java
diff --git a/legacy-test/src/android/test/suitebuilder/annotation/Smoke.java b/test-base/src/android/test/suitebuilder/annotation/Smoke.java
similarity index 100%
rename from legacy-test/src/android/test/suitebuilder/annotation/Smoke.java
rename to test-base/src/android/test/suitebuilder/annotation/Smoke.java
diff --git a/legacy-test/src/android/test/suitebuilder/annotation/Suppress.java b/test-base/src/android/test/suitebuilder/annotation/Suppress.java
similarity index 100%
rename from legacy-test/src/android/test/suitebuilder/annotation/Suppress.java
rename to test-base/src/android/test/suitebuilder/annotation/Suppress.java
diff --git a/legacy-test/src/android/test/suitebuilder/annotation/package.html b/test-base/src/android/test/suitebuilder/annotation/package.html
similarity index 100%
rename from legacy-test/src/android/test/suitebuilder/annotation/package.html
rename to test-base/src/android/test/suitebuilder/annotation/package.html
diff --git a/legacy-test/src/com/android/internal/util/Predicate.java b/test-base/src/com/android/internal/util/Predicate.java
similarity index 100%
rename from legacy-test/src/com/android/internal/util/Predicate.java
rename to test-base/src/com/android/internal/util/Predicate.java
diff --git a/legacy-test/src/junit/MODULE_LICENSE_CPL b/test-base/src/junit/MODULE_LICENSE_CPL
similarity index 100%
rename from legacy-test/src/junit/MODULE_LICENSE_CPL
rename to test-base/src/junit/MODULE_LICENSE_CPL
diff --git a/legacy-test/src/junit/README.android b/test-base/src/junit/README.android
similarity index 100%
rename from legacy-test/src/junit/README.android
rename to test-base/src/junit/README.android
diff --git a/legacy-test/src/junit/cpl-v10.html b/test-base/src/junit/cpl-v10.html
similarity index 100%
rename from legacy-test/src/junit/cpl-v10.html
rename to test-base/src/junit/cpl-v10.html
diff --git a/legacy-test/src/junit/framework/Assert.java b/test-base/src/junit/framework/Assert.java
similarity index 100%
rename from legacy-test/src/junit/framework/Assert.java
rename to test-base/src/junit/framework/Assert.java
diff --git a/legacy-test/src/junit/framework/AssertionFailedError.java b/test-base/src/junit/framework/AssertionFailedError.java
similarity index 100%
rename from legacy-test/src/junit/framework/AssertionFailedError.java
rename to test-base/src/junit/framework/AssertionFailedError.java
diff --git a/legacy-test/src/junit/framework/ComparisonCompactor.java b/test-base/src/junit/framework/ComparisonCompactor.java
similarity index 100%
rename from legacy-test/src/junit/framework/ComparisonCompactor.java
rename to test-base/src/junit/framework/ComparisonCompactor.java
diff --git a/legacy-test/src/junit/framework/ComparisonFailure.java b/test-base/src/junit/framework/ComparisonFailure.java
similarity index 100%
rename from legacy-test/src/junit/framework/ComparisonFailure.java
rename to test-base/src/junit/framework/ComparisonFailure.java
diff --git a/legacy-test/src/junit/framework/Protectable.java b/test-base/src/junit/framework/Protectable.java
similarity index 100%
rename from legacy-test/src/junit/framework/Protectable.java
rename to test-base/src/junit/framework/Protectable.java
diff --git a/legacy-test/src/junit/framework/Test.java b/test-base/src/junit/framework/Test.java
similarity index 100%
rename from legacy-test/src/junit/framework/Test.java
rename to test-base/src/junit/framework/Test.java
diff --git a/legacy-test/src/junit/framework/TestCase.java b/test-base/src/junit/framework/TestCase.java
similarity index 100%
rename from legacy-test/src/junit/framework/TestCase.java
rename to test-base/src/junit/framework/TestCase.java
diff --git a/legacy-test/src/junit/framework/TestFailure.java b/test-base/src/junit/framework/TestFailure.java
similarity index 100%
rename from legacy-test/src/junit/framework/TestFailure.java
rename to test-base/src/junit/framework/TestFailure.java
diff --git a/legacy-test/src/junit/framework/TestListener.java b/test-base/src/junit/framework/TestListener.java
similarity index 100%
rename from legacy-test/src/junit/framework/TestListener.java
rename to test-base/src/junit/framework/TestListener.java
diff --git a/legacy-test/src/junit/framework/TestResult.java b/test-base/src/junit/framework/TestResult.java
similarity index 100%
rename from legacy-test/src/junit/framework/TestResult.java
rename to test-base/src/junit/framework/TestResult.java
diff --git a/legacy-test/src/junit/framework/TestSuite.java b/test-base/src/junit/framework/TestSuite.java
similarity index 100%
rename from legacy-test/src/junit/framework/TestSuite.java
rename to test-base/src/junit/framework/TestSuite.java
diff --git a/test-mock/Android.bp b/test-mock/Android.bp
index 8eddec4..b1ae40e 100644
--- a/test-mock/Android.bp
+++ b/test-mock/Android.bp
@@ -24,7 +24,6 @@
no_framework_libs: true,
libs: [
"framework",
- "legacy-test",
],
}
diff --git a/test-mock/jarjar-rules.txt b/test-mock/jarjar-rules.txt
index b0e4bea..f6f7913 120000
--- a/test-mock/jarjar-rules.txt
+++ b/test-mock/jarjar-rules.txt
@@ -1 +1 @@
-../legacy-test/jarjar-rules.txt
\ No newline at end of file
+../test-base/jarjar-rules.txt
\ No newline at end of file
diff --git a/test-runner/Android.bp b/test-runner/Android.bp
index 104ae82..dfaeed5 100644
--- a/test-runner/Android.bp
+++ b/test-runner/Android.bp
@@ -24,11 +24,28 @@
no_framework_libs: true,
libs: [
"framework",
- "legacy-test",
+ "android.test.base",
"android.test.mock",
],
}
+// Build the android.test.runner-minus-junit library
+// =================================================
+// This is provided solely for use by the legacy-android-test module.
+java_library {
+ name: "android.test.runner-minus-junit",
+
+ srcs: ["src/android/**/*.java"],
+
+ no_framework_libs: true,
+ libs: [
+ "framework",
+ "android.test.base",
+ "android.test.mock",
+ "junit",
+ ],
+}
+
// Build the repackaged.android.test.runner library
// ================================================
java_library_static {
diff --git a/test-runner/Android.mk b/test-runner/Android.mk
index 6cf2d56..cdc7756 100644
--- a/test-runner/Android.mk
+++ b/test-runner/Android.mk
@@ -26,7 +26,7 @@
core-oj \
core-libart \
framework \
- legacy-test \
+ android.test.base \
android.test.mock \
LOCAL_MODULE_CLASS := JAVA_LIBRARIES
@@ -65,7 +65,7 @@
LOCAL_MODULE := android.test.runner.stubs
LOCAL_JAVA_LIBRARIES := \
- legacy.test.stubs \
+ android.test.base.stubs \
android.test.mock.stubs \
LOCAL_SOURCE_FILES_ALL_GENERATED := true
diff --git a/test-runner/jarjar-rules.txt b/test-runner/jarjar-rules.txt
index b0e4bea..f6f7913 120000
--- a/test-runner/jarjar-rules.txt
+++ b/test-runner/jarjar-rules.txt
@@ -1 +1 @@
-../legacy-test/jarjar-rules.txt
\ No newline at end of file
+../test-base/jarjar-rules.txt
\ No newline at end of file
diff --git a/tests/net/java/android/net/MacAddressTest.java b/tests/net/java/android/net/MacAddressTest.java
index 473dc538..9aad413 100644
--- a/tests/net/java/android/net/MacAddressTest.java
+++ b/tests/net/java/android/net/MacAddressTest.java
@@ -67,7 +67,7 @@
assertEquals(msg, t.expectedType, got);
if (got != MacAddress.TYPE_UNKNOWN) {
- assertEquals(got, MacAddress.fromBytes(t.addr).addressType());
+ assertEquals(got, MacAddress.fromBytes(t.addr).getAddressType());
}
}
}
@@ -191,7 +191,7 @@
assertTrue(stringRepr + " expected to be a locally assigned address",
mac.isLocallyAssigned());
- assertEquals(MacAddress.TYPE_UNICAST, mac.addressType());
+ assertEquals(MacAddress.TYPE_UNICAST, mac.getAddressType());
assertTrue(stringRepr + " expected to begin with " + expectedLocalOui,
stringRepr.startsWith(expectedLocalOui));
}
diff --git a/tests/net/java/android/net/NetworkTest.java b/tests/net/java/android/net/NetworkTest.java
index bacf986..94d01e9 100644
--- a/tests/net/java/android/net/NetworkTest.java
+++ b/tests/net/java/android/net/NetworkTest.java
@@ -147,9 +147,9 @@
// Adjust as necessary to test an implementation's specific constants.
// When running with runtest, "adb logcat -s TestRunner" can be useful.
- assertEquals(4311403230L, one.getNetworkHandle());
- assertEquals(8606370526L, two.getNetworkHandle());
- assertEquals(12901337822L, three.getNetworkHandle());
+ assertEquals(7700664333L, one.getNetworkHandle());
+ assertEquals(11995631629L, two.getNetworkHandle());
+ assertEquals(16290598925L, three.getNetworkHandle());
}
private static <T> void assertNotEqual(T t1, T t2) {
diff --git a/core/tests/coretests/src/android/net/NetworkUtilsTest.java b/tests/net/java/android/net/NetworkUtilsTest.java
similarity index 100%
rename from core/tests/coretests/src/android/net/NetworkUtilsTest.java
rename to tests/net/java/android/net/NetworkUtilsTest.java
diff --git a/core/tests/coretests/src/android/net/RouteInfoTest.java b/tests/net/java/android/net/RouteInfoTest.java
similarity index 100%
rename from core/tests/coretests/src/android/net/RouteInfoTest.java
rename to tests/net/java/android/net/RouteInfoTest.java
diff --git a/tests/net/java/android/net/apf/ApfTest.java b/tests/net/java/android/net/apf/ApfTest.java
index 725ddb9..9b75a50 100644
--- a/tests/net/java/android/net/apf/ApfTest.java
+++ b/tests/net/java/android/net/apf/ApfTest.java
@@ -35,6 +35,7 @@
import android.net.ip.IpManager;
import android.net.metrics.IpConnectivityLog;
import android.net.metrics.RaEvent;
+import android.net.util.InterfaceParams;
import android.os.ConditionVariable;
import android.os.Parcelable;
import android.os.SystemClock;
@@ -62,7 +63,6 @@
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
-import java.net.NetworkInterface;
import java.nio.ByteBuffer;
import java.util.List;
import java.util.Random;
@@ -635,7 +635,7 @@
public TestApfFilter(ApfConfiguration config, IpManager.Callback ipManagerCallback,
IpConnectivityLog log) throws Exception {
- super(config, NetworkInterface.getByName("lo"), ipManagerCallback, log);
+ super(config, InterfaceParams.getByName("lo"), ipManagerCallback, log);
}
// Pretend an RA packet has been received and show it to ApfFilter.
diff --git a/tests/net/java/android/net/ip/IpReachabilityMonitorTest.java b/tests/net/java/android/net/ip/IpReachabilityMonitorTest.java
index 54776db..e65585f 100644
--- a/tests/net/java/android/net/ip/IpReachabilityMonitorTest.java
+++ b/tests/net/java/android/net/ip/IpReachabilityMonitorTest.java
@@ -21,6 +21,7 @@
import static org.mockito.Mockito.anyString;
import static org.mockito.Mockito.when;
+import android.net.util.InterfaceParams;
import android.net.util.SharedLog;
import android.os.Handler;
import android.os.Looper;
@@ -54,8 +55,8 @@
}
IpReachabilityMonitor makeMonitor() {
- return new IpReachabilityMonitor(
- "fake0", 1, mHandler, mLog, mCallback, null, mDependencies);
+ final InterfaceParams ifParams = new InterfaceParams("fake0", 1, null);
+ return new IpReachabilityMonitor(ifParams, mHandler, mLog, mCallback, null, mDependencies);
}
@Test
diff --git a/tests/net/java/android/net/util/ConnectivityPacketSummaryTest.java b/tests/net/java/android/net/util/ConnectivityPacketSummaryTest.java
index 38d3d74..f9b7ec8 100644
--- a/tests/net/java/android/net/util/ConnectivityPacketSummaryTest.java
+++ b/tests/net/java/android/net/util/ConnectivityPacketSummaryTest.java
@@ -20,6 +20,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
+import android.net.MacAddress;
import android.support.test.runner.AndroidJUnit4;
import android.support.test.filters.SmallTest;
@@ -36,9 +37,7 @@
@RunWith(AndroidJUnit4.class)
@SmallTest
public class ConnectivityPacketSummaryTest {
- private static final byte[] MYHWADDR = {
- asByte(0x80), asByte(0x7a), asByte(0xbf), asByte(0x6f), asByte(0x48), asByte(0xf3)
- };
+ private static final MacAddress MYHWADDR = MacAddress.fromString("80:7a:bf:6f:48:f3");
private String getSummary(String hexBytes) {
hexBytes = hexBytes.replaceAll("\\s+", "");
diff --git a/tests/net/java/android/net/util/InterfaceParamsTest.java b/tests/net/java/android/net/util/InterfaceParamsTest.java
new file mode 100644
index 0000000..21728af
--- /dev/null
+++ b/tests/net/java/android/net/util/InterfaceParamsTest.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2017 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 android.net.util;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class InterfaceParamsTest {
+ @Test
+ public void testNullInterfaceReturnsNull() {
+ assertNull(InterfaceParams.getByName(null));
+ }
+
+ @Test
+ public void testNonExistentInterfaceReturnsNull() {
+ assertNull(InterfaceParams.getByName("doesnotexist0"));
+ }
+
+ @Test
+ public void testLoopback() {
+ final InterfaceParams ifParams = InterfaceParams.getByName("lo");
+ assertNotNull(ifParams);
+ assertEquals("lo", ifParams.name);
+ assertTrue(ifParams.index > 0);
+ assertNotNull(ifParams.macAddr);
+ assertTrue(ifParams.defaultMtu >= NetworkConstants.ETHER_MTU);
+ }
+}
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 113cd37..b8e37f3 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -55,14 +55,20 @@
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import static org.mockito.Matchers.anyBoolean;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.any;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
@@ -116,6 +122,7 @@
import android.util.ArraySet;
import android.util.Log;
+import com.android.internal.util.ArrayUtils;
import com.android.internal.util.WakeupMessage;
import com.android.internal.util.test.BroadcastInterceptingContext;
import com.android.internal.util.test.FakeSettingsProvider;
@@ -132,6 +139,7 @@
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;
@@ -174,8 +182,11 @@
@Mock IpConnectivityMetrics.Logger mMetricsService;
@Mock DefaultNetworkMetrics mDefaultNetworkMetrics;
+ @Mock INetworkManagementService mNetworkManagementService;
@Mock INetworkStatsService mStatsService;
+ private ArgumentCaptor<String[]> mStringArrayCaptor = ArgumentCaptor.forClass(String[].class);
+
// This class exists to test bindProcessToNetwork and getBoundNetworkForProcess. These methods
// do not go through ConnectivityService but talk to netd directly, so they don't automatically
// reflect the state of our test ConnectivityService.
@@ -872,7 +883,7 @@
LocalServices.addService(
NetworkPolicyManagerInternal.class, mock(NetworkPolicyManagerInternal.class));
mService = new WrappedConnectivityService(mServiceContext,
- mock(INetworkManagementService.class),
+ mNetworkManagementService,
mStatsService,
mock(INetworkPolicyManager.class),
mock(IpConnectivityLog.class));
@@ -1381,39 +1392,75 @@
return null;
}
- void expectAvailableCallbacks(
- MockNetworkAgent agent, boolean expectSuspended, int timeoutMs) {
+ // Expects onAvailable and the callbacks that follow it. These are:
+ // - onSuspended, iff the network was suspended when the callbacks fire.
+ // - onCapabilitiesChanged.
+ // - onLinkPropertiesChanged.
+ //
+ // @param agent the network to expect the callbacks on.
+ // @param expectSuspended whether to expect a SUSPENDED callback.
+ // @param expectValidated the expected value of the VALIDATED capability in the
+ // onCapabilitiesChanged callback.
+ // @param timeoutMs how long to wait for the callbacks.
+ void expectAvailableCallbacks(MockNetworkAgent agent, boolean expectSuspended,
+ boolean expectValidated, int timeoutMs) {
expectCallback(CallbackState.AVAILABLE, agent, timeoutMs);
if (expectSuspended) {
expectCallback(CallbackState.SUSPENDED, agent, timeoutMs);
}
- expectCallback(CallbackState.NETWORK_CAPABILITIES, agent, timeoutMs);
+ if (expectValidated) {
+ expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent);
+ } else {
+ expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, agent);
+ }
expectCallback(CallbackState.LINK_PROPERTIES, agent, timeoutMs);
}
- void expectAvailableCallbacks(MockNetworkAgent agent) {
- expectAvailableCallbacks(agent, false, TIMEOUT_MS);
+ // Expects the available callbacks (validated), plus onSuspended.
+ void expectAvailableAndSuspendedCallbacks(MockNetworkAgent agent, boolean expectValidated) {
+ expectAvailableCallbacks(agent, true, expectValidated, TIMEOUT_MS);
}
- void expectAvailableAndSuspendedCallbacks(MockNetworkAgent agent) {
- expectAvailableCallbacks(agent, true, TIMEOUT_MS);
+ void expectAvailableCallbacksValidated(MockNetworkAgent agent) {
+ expectAvailableCallbacks(agent, false, true, TIMEOUT_MS);
}
- void expectAvailableAndValidatedCallbacks(MockNetworkAgent agent) {
- expectAvailableCallbacks(agent, false, TIMEOUT_MS);
+ void expectAvailableCallbacksUnvalidated(MockNetworkAgent agent) {
+ expectAvailableCallbacks(agent, false, false, TIMEOUT_MS);
+ }
+
+ // Expects the available callbacks (where the onCapabilitiesChanged must contain the
+ // VALIDATED capability), plus another onCapabilitiesChanged which is identical to the
+ // one we just sent.
+ // TODO: this is likely a bug. Fix it and remove this method.
+ void expectAvailableDoubleValidatedCallbacks(MockNetworkAgent agent) {
+ expectCallback(CallbackState.AVAILABLE, agent, TIMEOUT_MS);
+ NetworkCapabilities nc1 = expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent);
+ expectCallback(CallbackState.LINK_PROPERTIES, agent, TIMEOUT_MS);
+ NetworkCapabilities nc2 = expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent);
+ assertEquals(nc1, nc2);
+ }
+
+ // Expects the available callbacks where the onCapabilitiesChanged must not have validated,
+ // then expects another onCapabilitiesChanged that has the validated bit set. This is used
+ // when a network connects and satisfies a callback, and then immediately validates.
+ void expectAvailableThenValidatedCallbacks(MockNetworkAgent agent) {
+ expectAvailableCallbacksUnvalidated(agent);
expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent);
}
- void expectCapabilitiesWith(int capability, MockNetworkAgent agent) {
+ NetworkCapabilities expectCapabilitiesWith(int capability, MockNetworkAgent agent) {
CallbackInfo cbi = expectCallback(CallbackState.NETWORK_CAPABILITIES, agent);
NetworkCapabilities nc = (NetworkCapabilities) cbi.arg;
assertTrue(nc.hasCapability(capability));
+ return nc;
}
- void expectCapabilitiesWithout(int capability, MockNetworkAgent agent) {
+ NetworkCapabilities expectCapabilitiesWithout(int capability, MockNetworkAgent agent) {
CallbackInfo cbi = expectCallback(CallbackState.NETWORK_CAPABILITIES, agent);
NetworkCapabilities nc = (NetworkCapabilities) cbi.arg;
assertFalse(nc.hasCapability(capability));
+ return nc;
}
void assertNoCallback() {
@@ -1450,8 +1497,8 @@
ConditionVariable cv = waitForConnectivityBroadcasts(1);
mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
mCellNetworkAgent.connect(false);
- genericNetworkCallback.expectAvailableCallbacks(mCellNetworkAgent);
- cellNetworkCallback.expectAvailableCallbacks(mCellNetworkAgent);
+ genericNetworkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
+ cellNetworkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
waitFor(cv);
assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
@@ -1465,8 +1512,8 @@
cv = waitForConnectivityBroadcasts(2);
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
mWiFiNetworkAgent.connect(false);
- genericNetworkCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
- wifiNetworkCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
+ genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+ wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
waitFor(cv);
assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
@@ -1489,8 +1536,8 @@
// Test validated networks
mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
mCellNetworkAgent.connect(true);
- genericNetworkCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
- cellNetworkCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
+ genericNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
+ cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
@@ -1502,10 +1549,10 @@
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
mWiFiNetworkAgent.connect(true);
- genericNetworkCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
+ genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
genericNetworkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
genericNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
- wifiNetworkCallback.expectAvailableAndValidatedCallbacks(mWiFiNetworkAgent);
+ wifiNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
cellNetworkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
@@ -1541,32 +1588,32 @@
mEthernetNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
mCellNetworkAgent.connect(true);
- callback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
- defaultCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
+ callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
+ defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
mWiFiNetworkAgent.connect(true);
// We get AVAILABLE on wifi when wifi connects and satisfies our unmetered request.
// We then get LOSING when wifi validates and cell is outscored.
- callback.expectAvailableCallbacks(mWiFiNetworkAgent);
+ callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
// TODO: Investigate sending validated before losing.
callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
- defaultCallback.expectAvailableAndValidatedCallbacks(mWiFiNetworkAgent);
+ defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
mEthernetNetworkAgent.connect(true);
- callback.expectAvailableCallbacks(mEthernetNetworkAgent);
+ callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent);
// TODO: Investigate sending validated before losing.
callback.expectCallback(CallbackState.LOSING, mWiFiNetworkAgent);
callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent);
- defaultCallback.expectAvailableAndValidatedCallbacks(mEthernetNetworkAgent);
+ defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
mEthernetNetworkAgent.disconnect();
callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
defaultCallback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
- defaultCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
+ defaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
for (int i = 0; i < 4; i++) {
MockNetworkAgent oldNetwork, newNetwork;
@@ -1583,7 +1630,7 @@
callback.expectCallback(CallbackState.LOSING, oldNetwork);
// TODO: should we send an AVAILABLE callback to newNetwork, to indicate that it is no
// longer lingering?
- defaultCallback.expectAvailableCallbacks(newNetwork);
+ defaultCallback.expectAvailableCallbacksValidated(newNetwork);
assertEquals(newNetwork.getNetwork(), mCm.getActiveNetwork());
}
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
@@ -1603,7 +1650,7 @@
// Disconnect our test networks.
mWiFiNetworkAgent.disconnect();
defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
- defaultCallback.expectAvailableCallbacks(mCellNetworkAgent);
+ defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
mCellNetworkAgent.disconnect();
defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
@@ -1619,22 +1666,22 @@
mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
mCellNetworkAgent.connect(false); // Score: 10
- callback.expectAvailableCallbacks(mCellNetworkAgent);
- defaultCallback.expectAvailableCallbacks(mCellNetworkAgent);
+ callback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
+ defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
// Bring up wifi with a score of 20.
// Cell stays up because it would satisfy the default request if it validated.
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
mWiFiNetworkAgent.connect(false); // Score: 20
- callback.expectAvailableCallbacks(mWiFiNetworkAgent);
- defaultCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
+ callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+ defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
mWiFiNetworkAgent.disconnect();
callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
- defaultCallback.expectAvailableCallbacks(mCellNetworkAgent);
+ defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
// Bring up wifi with a score of 70.
@@ -1642,33 +1689,33 @@
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
mWiFiNetworkAgent.adjustScore(50);
mWiFiNetworkAgent.connect(false); // Score: 70
- callback.expectAvailableCallbacks(mWiFiNetworkAgent);
+ callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
- defaultCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
+ defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
// Tear down wifi.
mWiFiNetworkAgent.disconnect();
callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
- defaultCallback.expectAvailableCallbacks(mCellNetworkAgent);
+ defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
// Bring up wifi, then validate it. Previous versions would immediately tear down cell, but
// it's arguably correct to linger it, since it was the default network before it validated.
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
mWiFiNetworkAgent.connect(true);
- callback.expectAvailableCallbacks(mWiFiNetworkAgent);
+ callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
// TODO: Investigate sending validated before losing.
callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
- defaultCallback.expectAvailableAndValidatedCallbacks(mWiFiNetworkAgent);
+ defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
mWiFiNetworkAgent.disconnect();
callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
- defaultCallback.expectAvailableCallbacks(mCellNetworkAgent);
+ defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
mCellNetworkAgent.disconnect();
callback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
@@ -1676,12 +1723,12 @@
// If a network is lingering, and we add and remove a request from it, resume lingering.
mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
mCellNetworkAgent.connect(true);
- callback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
- defaultCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
+ callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
+ defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
mWiFiNetworkAgent.connect(true);
- defaultCallback.expectAvailableAndValidatedCallbacks(mWiFiNetworkAgent);
- callback.expectAvailableCallbacks(mWiFiNetworkAgent);
+ defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
+ callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
// TODO: Investigate sending validated before losing.
callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
@@ -1700,7 +1747,7 @@
mWiFiNetworkAgent.disconnect();
callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
- defaultCallback.expectAvailableCallbacks(mCellNetworkAgent);
+ defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
// Cell is now the default network. Pin it with a cell-specific request.
noopCallback = new NetworkCallback(); // Can't reuse NetworkCallbacks. http://b/20701525
@@ -1709,8 +1756,8 @@
// Now connect wifi, and expect it to become the default network.
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
mWiFiNetworkAgent.connect(true);
- callback.expectAvailableAndValidatedCallbacks(mWiFiNetworkAgent);
- defaultCallback.expectAvailableAndValidatedCallbacks(mWiFiNetworkAgent);
+ callback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
+ defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
// The default request is lingering on cell, but nothing happens to cell, and we send no
// callbacks for it, because it's kept up by cellRequest.
callback.assertNoCallback();
@@ -1726,14 +1773,14 @@
// Register a TRACK_DEFAULT request and check that it does not affect lingering.
TestNetworkCallback trackDefaultCallback = new TestNetworkCallback();
mCm.registerDefaultNetworkCallback(trackDefaultCallback);
- trackDefaultCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
+ trackDefaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET);
mEthernetNetworkAgent.connect(true);
- callback.expectAvailableCallbacks(mEthernetNetworkAgent);
+ callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent);
callback.expectCallback(CallbackState.LOSING, mWiFiNetworkAgent);
callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent);
- trackDefaultCallback.expectAvailableAndValidatedCallbacks(mEthernetNetworkAgent);
- defaultCallback.expectAvailableAndValidatedCallbacks(mEthernetNetworkAgent);
+ trackDefaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
+ defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
// Let linger run its course.
callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent, lingerTimeoutMs);
@@ -1760,13 +1807,13 @@
// Bring up validated cell.
mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
mCellNetworkAgent.connect(true);
- callback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
+ callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
// Bring up unvalidated wifi with explicitlySelected=true.
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
mWiFiNetworkAgent.explicitlySelected(false);
mWiFiNetworkAgent.connect(false);
- callback.expectAvailableCallbacks(mWiFiNetworkAgent);
+ callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
// Cell Remains the default.
assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
@@ -1789,7 +1836,7 @@
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
mWiFiNetworkAgent.explicitlySelected(false);
mWiFiNetworkAgent.connect(false);
- callback.expectAvailableCallbacks(mWiFiNetworkAgent);
+ callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
// If the user chooses no on the "No Internet access, stay connected?" dialog, we ask the
// network to disconnect.
@@ -1800,7 +1847,7 @@
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
mWiFiNetworkAgent.explicitlySelected(false);
mWiFiNetworkAgent.connect(true);
- callback.expectAvailableCallbacks(mWiFiNetworkAgent);
+ callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
@@ -1809,7 +1856,7 @@
// TODO: fix this.
mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET);
mEthernetNetworkAgent.connect(true);
- callback.expectAvailableAndValidatedCallbacks(mEthernetNetworkAgent);
+ callback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent);
assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
callback.assertNoCallback();
@@ -1982,7 +2029,7 @@
mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
mCellNetworkAgent.connectWithoutInternet();
- networkCallback.expectAvailableCallbacks(mCellNetworkAgent);
+ networkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
verifyActiveNetwork(TRANSPORT_WIFI);
// Test releasing NetworkRequest disconnects cellular with MMS
@@ -2011,7 +2058,7 @@
MockNetworkAgent mmsNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
mmsNetworkAgent.addCapability(NET_CAPABILITY_MMS);
mmsNetworkAgent.connectWithoutInternet();
- networkCallback.expectAvailableCallbacks(mmsNetworkAgent);
+ networkCallback.expectAvailableCallbacksUnvalidated(mmsNetworkAgent);
verifyActiveNetwork(TRANSPORT_CELLULAR);
// Test releasing MMS NetworkRequest does not disconnect main cellular NetworkAgent
@@ -2038,7 +2085,7 @@
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
String firstRedirectUrl = "http://example.com/firstPath";
mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl);
- captivePortalCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
+ captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), firstRedirectUrl);
// Take down network.
@@ -2051,7 +2098,7 @@
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
String secondRedirectUrl = "http://example.com/secondPath";
mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl);
- captivePortalCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
+ captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), secondRedirectUrl);
// Make captive portal disappear then revalidate.
@@ -2061,9 +2108,7 @@
captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
// Expect NET_CAPABILITY_VALIDATED onAvailable callback.
- validatedCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
- // TODO: Investigate only sending available callbacks.
- validatedCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
+ validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
// Break network connectivity.
// Expect NET_CAPABILITY_VALIDATED onLost callback.
@@ -2087,7 +2132,7 @@
// Bring up wifi.
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
mWiFiNetworkAgent.connect(true);
- validatedCallback.expectAvailableAndValidatedCallbacks(mWiFiNetworkAgent);
+ validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
// Check that calling startCaptivePortalApp does nothing.
@@ -2098,7 +2143,7 @@
// Turn into a captive portal.
mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 302;
mCm.reportNetworkConnectivity(wifiNetwork, false);
- captivePortalCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
+ captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
validatedCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
// Check that startCaptivePortalApp sends the expected intent.
@@ -2111,7 +2156,7 @@
mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 204;
CaptivePortal c = (CaptivePortal) intent.getExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL);
c.reportCaptivePortalDismissed();
- validatedCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
+ validatedCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
mCm.unregisterNetworkCallback(validatedCallback);
@@ -2154,7 +2199,7 @@
mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl);
// Expect NET_CAPABILITY_VALIDATED onAvailable callback.
- validatedCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
+ validatedCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
// But there should be no CaptivePortal callback.
captivePortalCallback.assertNoCallback();
}
@@ -2192,14 +2237,14 @@
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
mWiFiNetworkAgent.connect(false);
- cEmpty1.expectAvailableCallbacks(mWiFiNetworkAgent);
- cEmpty2.expectAvailableCallbacks(mWiFiNetworkAgent);
- cEmpty3.expectAvailableCallbacks(mWiFiNetworkAgent);
- cEmpty4.expectAvailableCallbacks(mWiFiNetworkAgent);
+ cEmpty1.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+ cEmpty2.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+ cEmpty3.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+ cEmpty4.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
assertNoCallbacks(cFoo, cBar);
mWiFiNetworkAgent.setNetworkSpecifier(new StringNetworkSpecifier("foo"));
- cFoo.expectAvailableCallbacks(mWiFiNetworkAgent);
+ cFoo.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
for (TestNetworkCallback c: emptyCallbacks) {
c.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent);
}
@@ -2208,7 +2253,7 @@
mWiFiNetworkAgent.setNetworkSpecifier(new StringNetworkSpecifier("bar"));
cFoo.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
- cBar.expectAvailableCallbacks(mWiFiNetworkAgent);
+ cBar.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
for (TestNetworkCallback c: emptyCallbacks) {
c.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent);
}
@@ -2337,14 +2382,14 @@
// Bring up cell and expect CALLBACK_AVAILABLE.
mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
mCellNetworkAgent.connect(true);
- cellNetworkCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
- defaultNetworkCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
+ cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
+ defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
// Bring up wifi and expect CALLBACK_AVAILABLE.
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
mWiFiNetworkAgent.connect(true);
cellNetworkCallback.assertNoCallback();
- defaultNetworkCallback.expectAvailableAndValidatedCallbacks(mWiFiNetworkAgent);
+ defaultNetworkCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
// Bring down cell. Expect no default network callback, since it wasn't the default.
mCellNetworkAgent.disconnect();
@@ -2354,7 +2399,7 @@
// Bring up cell. Expect no default network callback, since it won't be the default.
mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
mCellNetworkAgent.connect(true);
- cellNetworkCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
+ cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
defaultNetworkCallback.assertNoCallback();
// Bring down wifi. Expect the default network callback to notified of LOST wifi
@@ -2362,7 +2407,7 @@
mWiFiNetworkAgent.disconnect();
cellNetworkCallback.assertNoCallback();
defaultNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
- defaultNetworkCallback.expectAvailableCallbacks(mCellNetworkAgent);
+ defaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
mCellNetworkAgent.disconnect();
cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
defaultNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
@@ -2383,7 +2428,7 @@
// We should get onAvailable(), onCapabilitiesChanged(), and
// onLinkPropertiesChanged() in rapid succession. Additionally, we
// should get onCapabilitiesChanged() when the mobile network validates.
- cellNetworkCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
+ cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
cellNetworkCallback.assertNoCallback();
// Update LinkProperties.
@@ -2404,7 +2449,7 @@
mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
// We should get onAvailable(), onCapabilitiesChanged(), onLinkPropertiesChanged(),
// as well as onNetworkSuspended() in rapid succession.
- dfltNetworkCallback.expectAvailableAndSuspendedCallbacks(mCellNetworkAgent);
+ dfltNetworkCallback.expectAvailableAndSuspendedCallbacks(mCellNetworkAgent, true);
dfltNetworkCallback.assertNoCallback();
mCm.unregisterNetworkCallback(dfltNetworkCallback);
@@ -2444,18 +2489,18 @@
mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
mCellNetworkAgent.connect(true);
- callback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
- fgCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
+ callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
+ fgCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
assertTrue(isForegroundNetwork(mCellNetworkAgent));
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
mWiFiNetworkAgent.connect(true);
// When wifi connects, cell lingers.
- callback.expectAvailableCallbacks(mWiFiNetworkAgent);
+ callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
- fgCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
+ fgCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
fgCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
fgCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
assertTrue(isForegroundNetwork(mCellNetworkAgent));
@@ -2479,8 +2524,8 @@
// is currently delivered before the onAvailable() callbacks.
// TODO: Fix this.
cellCallback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
- cellCallback.expectAvailableCallbacks(mCellNetworkAgent);
- fgCallback.expectAvailableCallbacks(mCellNetworkAgent);
+ cellCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
+ fgCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
// Expect a network capabilities update with FOREGROUND, because the most recent
// request causes its state to change.
callback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
@@ -2500,7 +2545,7 @@
mWiFiNetworkAgent.disconnect();
callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
fgCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
- fgCallback.expectAvailableCallbacks(mCellNetworkAgent);
+ fgCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
assertTrue(isForegroundNetwork(mCellNetworkAgent));
mCm.unregisterNetworkCallback(callback);
@@ -2640,7 +2685,7 @@
mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
testFactory.expectAddRequests(2); // Because the cell request changes score twice.
mCellNetworkAgent.connect(true);
- cellNetworkCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
+ cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
testFactory.waitForNetworkRequests(2);
assertFalse(testFactory.getMyStartRequested()); // Because the cell network outscores us.
@@ -2731,16 +2776,15 @@
// Bring up validated cell.
mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
mCellNetworkAgent.connect(true);
- cellNetworkCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
- defaultCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
+ cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
+ defaultCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
Network cellNetwork = mCellNetworkAgent.getNetwork();
// Bring up validated wifi.
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
mWiFiNetworkAgent.connect(true);
- defaultCallback.expectAvailableAndValidatedCallbacks(mWiFiNetworkAgent);
- validatedWifiCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
- validatedWifiCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
+ defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
+ validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
// Fail validation on wifi.
@@ -2761,18 +2805,18 @@
// that we switch back to cell.
tracker.configRestrictsAvoidBadWifi = false;
tracker.reevaluate();
- defaultCallback.expectAvailableCallbacks(mCellNetworkAgent);
+ defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
assertEquals(mCm.getActiveNetwork(), cellNetwork);
// Switch back to a restrictive carrier.
tracker.configRestrictsAvoidBadWifi = true;
tracker.reevaluate();
- defaultCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
+ defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
assertEquals(mCm.getActiveNetwork(), wifiNetwork);
// Simulate the user selecting "switch" on the dialog, and check that we switch to cell.
mCm.setAvoidUnvalidated(wifiNetwork);
- defaultCallback.expectAvailableCallbacks(mCellNetworkAgent);
+ defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
NET_CAPABILITY_VALIDATED));
assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
@@ -2783,9 +2827,8 @@
mWiFiNetworkAgent.disconnect();
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
mWiFiNetworkAgent.connect(true);
- defaultCallback.expectAvailableAndValidatedCallbacks(mWiFiNetworkAgent);
- validatedWifiCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
- validatedWifiCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
+ defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
+ validatedWifiCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
wifiNetwork = mWiFiNetworkAgent.getNetwork();
// Fail validation on wifi and expect the dialog to appear.
@@ -2799,7 +2842,7 @@
tracker.reevaluate();
// We now switch to cell.
- defaultCallback.expectAvailableCallbacks(mCellNetworkAgent);
+ defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
NET_CAPABILITY_VALIDATED));
assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
@@ -2810,17 +2853,17 @@
// We switch to wifi and then to cell.
Settings.Global.putString(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, null);
tracker.reevaluate();
- defaultCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
+ defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
assertEquals(mCm.getActiveNetwork(), wifiNetwork);
Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
tracker.reevaluate();
- defaultCallback.expectAvailableCallbacks(mCellNetworkAgent);
+ defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
assertEquals(mCm.getActiveNetwork(), cellNetwork);
// If cell goes down, we switch to wifi.
mCellNetworkAgent.disconnect();
defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
- defaultCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
+ defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
validatedWifiCallback.assertNoCallback();
mCm.unregisterNetworkCallback(cellNetworkCallback);
@@ -2862,7 +2905,7 @@
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
mWiFiNetworkAgent.connect(false);
- networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, timeoutMs);
+ networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false, timeoutMs);
// pass timeout and validate that UNAVAILABLE is not called
networkCallback.assertNoCallback();
@@ -2883,7 +2926,7 @@
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
mWiFiNetworkAgent.connect(false);
final int assertTimeoutMs = 100;
- networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, assertTimeoutMs);
+ networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false, assertTimeoutMs);
mWiFiNetworkAgent.disconnect();
networkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
@@ -3370,7 +3413,7 @@
// Bring up wifi aware network.
wifiAware.connect(false, false);
- callback.expectAvailableCallbacks(wifiAware);
+ callback.expectAvailableCallbacksUnvalidated(wifiAware);
assertNull(mCm.getActiveNetworkInfo());
assertNull(mCm.getActiveNetwork());
@@ -3489,6 +3532,44 @@
reset(mStatsService);
}
+ @Test
+ public void testBasicDnsConfigurationPushed() throws Exception {
+ mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
+ waitForIdle();
+ verify(mNetworkManagementService, never()).setDnsConfigurationForNetwork(
+ anyInt(), any(), any(), any(), anyBoolean(), anyString());
+
+ final LinkProperties cellLp = new LinkProperties();
+ cellLp.setInterfaceName("test_rmnet_data0");
+ mCellNetworkAgent.sendLinkProperties(cellLp);
+ mCellNetworkAgent.connect(false);
+ waitForIdle();
+ verify(mNetworkManagementService, times(1)).setDnsConfigurationForNetwork(
+ anyInt(), mStringArrayCaptor.capture(), any(), any(), anyBoolean(), anyString());
+ // CS tells netd about the empty DNS config for this network.
+ assertEmpty(mStringArrayCaptor.getValue());
+ reset(mNetworkManagementService);
+
+ cellLp.addDnsServer(InetAddress.getByName("2001:db8::1"));
+ mCellNetworkAgent.sendLinkProperties(cellLp);
+ waitForIdle();
+ verify(mNetworkManagementService, times(1)).setDnsConfigurationForNetwork(
+ anyInt(), mStringArrayCaptor.capture(), any(), any(), anyBoolean(), anyString());
+ assertEquals(1, mStringArrayCaptor.getValue().length);
+ assertTrue(ArrayUtils.contains(mStringArrayCaptor.getValue(), "2001:db8::1"));
+ reset(mNetworkManagementService);
+
+ cellLp.addDnsServer(InetAddress.getByName("192.0.2.1"));
+ mCellNetworkAgent.sendLinkProperties(cellLp);
+ waitForIdle();
+ verify(mNetworkManagementService, times(1)).setDnsConfigurationForNetwork(
+ anyInt(), mStringArrayCaptor.capture(), any(), any(), anyBoolean(), anyString());
+ assertEquals(2, mStringArrayCaptor.getValue().length);
+ assertTrue(ArrayUtils.containsAll(mStringArrayCaptor.getValue(),
+ new String[]{"2001:db8::1", "192.0.2.1"}));
+ reset(mNetworkManagementService);
+ }
+
private void checkDirectlyConnectedRoutes(Object callbackObj,
Collection<LinkAddress> linkAddresses, Collection<RouteInfo> otherRoutes) {
assertTrue(callbackObj instanceof LinkProperties);