Merge "Add Support for Async requestCellInfoUpdate()"
diff --git a/Android.bp b/Android.bp
index 8c40c19..8b60745 100644
--- a/Android.bp
+++ b/Android.bp
@@ -577,6 +577,7 @@
"telephony/java/com/android/internal/telephony/euicc/ISetDefaultSmdpAddressCallback.aidl",
"telephony/java/com/android/internal/telephony/euicc/ISetNicknameCallback.aidl",
"telephony/java/com/android/internal/telephony/euicc/ISwitchToProfileCallback.aidl",
+ "telephony/java/com/android/internal/telephony/rcs/IRcs.aidl",
"wifi/java/android/net/wifi/ISoftApCallback.aidl",
"wifi/java/android/net/wifi/IWifiManager.aidl",
"wifi/java/android/net/wifi/aware/IWifiAwareDiscoverySessionCallback.aidl",
diff --git a/api/current.txt b/api/current.txt
index 4165432..3c014cb 100755
--- a/api/current.txt
+++ b/api/current.txt
@@ -42581,6 +42581,7 @@
public class PhoneStateListener {
ctor public PhoneStateListener();
+ ctor public PhoneStateListener(java.util.concurrent.Executor);
method public void onCallForwardingIndicatorChanged(boolean);
method public void onCallStateChanged(int, java.lang.String);
method public void onCellInfoChanged(java.util.List<android.telephony.CellInfo>);
diff --git a/api/system-current.txt b/api/system-current.txt
index 0f8bc42..aac8ebd 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -5094,6 +5094,7 @@
method public static android.os.PersistableBundle getDefaultConfig();
method public void overrideConfig(int, android.os.PersistableBundle);
method public void updateConfigForPhoneId(int, java.lang.String);
+ field public static final java.lang.String KEY_CARRIER_SETUP_APP_STRING = "carrier_setup_app_string";
field public static final java.lang.String KEY_CONFIG_PLANS_PACKAGE_OVERRIDE_STRING = "config_plans_package_override_string";
}
@@ -5168,8 +5169,10 @@
public class PhoneStateListener {
method public void onRadioPowerStateChanged(int);
method public void onSrvccStateChanged(int);
+ method public void onVoiceActivationStateChanged(int);
field public static final int LISTEN_RADIO_POWER_STATE_CHANGED = 8388608; // 0x800000
field public static final int LISTEN_SRVCC_STATE_CHANGED = 16384; // 0x4000
+ field public static final int LISTEN_VOICE_ACTIVATION_STATE = 131072; // 0x20000
}
public class ServiceState implements android.os.Parcelable {
@@ -5591,6 +5594,7 @@
field public static final int RESET_OPTION_DELETE_FIELD_LOADED_TEST_PROFILES = 2; // 0x2
field public static final int RESET_OPTION_DELETE_OPERATIONAL_PROFILES = 1; // 0x1
field public static final int RESET_OPTION_RESET_DEFAULT_SMDP_ADDRESS = 4; // 0x4
+ field public static final int RESULT_CALLER_NOT_ALLOWED = -3; // 0xfffffffd
field public static final int RESULT_EUICC_NOT_FOUND = -2; // 0xfffffffe
field public static final int RESULT_OK = 0; // 0x0
field public static final int RESULT_UNKNOWN_ERROR = -1; // 0xffffffff
@@ -6233,6 +6237,22 @@
method public void receiveSessionModifyResponse(int, android.telecom.VideoProfile, android.telecom.VideoProfile);
}
+ public class ProvisioningManager {
+ method public static android.telephony.ims.ProvisioningManager createForSubscriptionId(android.content.Context, int);
+ method public int getProvisioningIntValue(int);
+ method public java.lang.String getProvisioningStringValue(int);
+ method public void registerProvisioningChangedCallback(java.util.concurrent.Executor, android.telephony.ims.ProvisioningManager.Callback);
+ method public int setProvisioningIntValue(int, int);
+ method public int setProvisioningStringValue(int, java.lang.String);
+ method public void unregisterProvisioningChangedCallback(android.telephony.ims.ProvisioningManager.Callback);
+ }
+
+ public static class ProvisioningManager.Callback {
+ ctor public ProvisioningManager.Callback();
+ method public void onProvisioningIntChanged(int, int);
+ method public void onProvisioningStringChanged(int, java.lang.String);
+ }
+
}
package android.telephony.ims.feature {
diff --git a/config/hiddenapi-light-greylist.txt b/config/hiddenapi-light-greylist.txt
index ce0f945..374a336 100644
--- a/config/hiddenapi-light-greylist.txt
+++ b/config/hiddenapi-light-greylist.txt
@@ -1392,18 +1392,6 @@
Landroid/security/Credentials;->convertToPem([Ljava/security/cert/Certificate;)[B
Landroid/security/IKeyChainService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/security/IKeyChainService;
Landroid/security/IKeyChainService;->requestPrivateKey(Ljava/lang/String;)Ljava/lang/String;
-Landroid/security/IKeystoreService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/security/IKeystoreService;
-Landroid/security/IKeystoreService;->clear_uid(J)I
-Landroid/security/IKeystoreService;->del(Ljava/lang/String;I)I
-Landroid/security/IKeystoreService;->exist(Ljava/lang/String;I)I
-Landroid/security/IKeystoreService;->generateKey(Ljava/lang/String;Landroid/security/keymaster/KeymasterArguments;[BIILandroid/security/keymaster/KeyCharacteristics;)I
-Landroid/security/IKeystoreService;->get(Ljava/lang/String;I)[B
-Landroid/security/IKeystoreService;->getState(I)I
-Landroid/security/IKeystoreService;->insert(Ljava/lang/String;[BII)I
-Landroid/security/IKeystoreService;->is_hardware_backed(Ljava/lang/String;)I
-Landroid/security/IKeystoreService;->list(Ljava/lang/String;I)[Ljava/lang/String;
-Landroid/security/IKeystoreService;->reset()I
-Landroid/security/IKeystoreService;->ungrant(Ljava/lang/String;I)I
Landroid/security/keymaster/KeymasterBlobArgument;-><init>(ILandroid/os/Parcel;)V
Landroid/security/keymaster/KeymasterBlobArgument;-><init>(I[B)V
Landroid/security/keymaster/KeymasterBlobArgument;->blob:[B
@@ -1415,6 +1403,17 @@
Landroid/security/keymaster/KeymasterLongArgument;-><init>(IJ)V
Landroid/security/keymaster/KeymasterLongArgument;-><init>(ILandroid/os/Parcel;)V
Landroid/security/keymaster/KeymasterLongArgument;->value:J
+Landroid/security/keystore/IKeystoreService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/security/keystore/IKeystoreService;
+Landroid/security/keystore/IKeystoreService;->clear_uid(J)I
+Landroid/security/keystore/IKeystoreService;->del(Ljava/lang/String;I)I
+Landroid/security/keystore/IKeystoreService;->exist(Ljava/lang/String;I)I
+Landroid/security/keystore/IKeystoreService;->get(Ljava/lang/String;I)[B
+Landroid/security/keystore/IKeystoreService;->getState(I)I
+Landroid/security/keystore/IKeystoreService;->insert(Ljava/lang/String;[BII)I
+Landroid/security/keystore/IKeystoreService;->is_hardware_backed(Ljava/lang/String;)I
+Landroid/security/keystore/IKeystoreService;->list(Ljava/lang/String;I)[Ljava/lang/String;
+Landroid/security/keystore/IKeystoreService;->reset()I
+Landroid/security/keystore/IKeystoreService;->ungrant(Ljava/lang/String;I)I
Landroid/service/carrier/ICarrierMessagingCallback$Stub;-><init>()V
Landroid/service/carrier/ICarrierMessagingService;->filterSms(Landroid/service/carrier/MessagePdu;Ljava/lang/String;IILandroid/service/carrier/ICarrierMessagingCallback;)V
Landroid/service/dreams/IDreamManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/service/dreams/IDreamManager;
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index fdda85d..83c43e7 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -143,6 +143,7 @@
import android.telephony.TelephonyManager;
import android.telephony.euicc.EuiccCardManager;
import android.telephony.euicc.EuiccManager;
+import android.telephony.rcs.RcsManager;
import android.util.Log;
import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
@@ -514,6 +515,14 @@
return new SubscriptionManager(ctx.getOuterContext());
}});
+ registerService(Context.TELEPHONY_RCS_SERVICE, RcsManager.class,
+ new CachedServiceFetcher<RcsManager>() {
+ @Override
+ public RcsManager createService(ContextImpl ctx) {
+ return new RcsManager();
+ }
+ });
+
registerService(Context.CARRIER_CONFIG_SERVICE, CarrierConfigManager.class,
new CachedServiceFetcher<CarrierConfigManager>() {
@Override
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 4630ad2..5cbb1f8 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -4250,6 +4250,13 @@
public static final String TIME_ZONE_DETECTOR_SERVICE = "time_zone_detector";
/**
+ * Use with {@link #getSystemService(String)} to retrieve an
+ * {@link android.telephony.rcs.RcsManager}.
+ * @hide
+ */
+ public static final String TELEPHONY_RCS_SERVICE = "ircs";
+
+ /**
* Determine whether the given permission is allowed for a particular
* process and user ID running in the system.
*
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index d818228..0ec509e 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -27,7 +27,6 @@
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
-import android.os.Build;
import android.os.Environment;
import android.os.Parcel;
import android.os.Parcelable;
@@ -1155,11 +1154,11 @@
* system apps.
* @hide
*/
- public static final int HIDDEN_API_ENFORCEMENT_NONE = 0;
+ public static final int HIDDEN_API_ENFORCEMENT_DISABLED = 0;
/**
* No API enforcement, but enable the detection logic and warnings. Observed behaviour is the
- * same as {@link #HIDDEN_API_ENFORCEMENT_NONE} but you may see warnings in the log when APIs
- * are accessed.
+ * same as {@link #HIDDEN_API_ENFORCEMENT_DISABLED} but you may see warnings in the log when
+ * APIs are accessed.
* @hide
* */
public static final int HIDDEN_API_ENFORCEMENT_JUST_WARN = 1;
@@ -1167,14 +1166,10 @@
* Dark grey list enforcement. Enforces the dark grey and black lists
* @hide
*/
- public static final int HIDDEN_API_ENFORCEMENT_DARK_GREY_AND_BLACK = 2;
- /**
- * Blacklist enforcement only.
- * @hide
- */
- public static final int HIDDEN_API_ENFORCEMENT_BLACK = 3;
+ public static final int HIDDEN_API_ENFORCEMENT_ENABLED = 2;
- private static final int HIDDEN_API_ENFORCEMENT_MAX = HIDDEN_API_ENFORCEMENT_BLACK;
+ private static final int HIDDEN_API_ENFORCEMENT_MIN = HIDDEN_API_ENFORCEMENT_DEFAULT;
+ private static final int HIDDEN_API_ENFORCEMENT_MAX = HIDDEN_API_ENFORCEMENT_ENABLED;
/**
* Values in this IntDef MUST be kept in sync with enum hiddenapi::EnforcementPolicy in
@@ -1183,17 +1178,16 @@
*/
@IntDef(prefix = { "HIDDEN_API_ENFORCEMENT_" }, value = {
HIDDEN_API_ENFORCEMENT_DEFAULT,
- HIDDEN_API_ENFORCEMENT_NONE,
+ HIDDEN_API_ENFORCEMENT_DISABLED,
HIDDEN_API_ENFORCEMENT_JUST_WARN,
- HIDDEN_API_ENFORCEMENT_DARK_GREY_AND_BLACK,
- HIDDEN_API_ENFORCEMENT_BLACK,
+ HIDDEN_API_ENFORCEMENT_ENABLED,
})
@Retention(RetentionPolicy.SOURCE)
public @interface HiddenApiEnforcementPolicy {}
/** @hide */
public static boolean isValidHiddenApiEnforcementPolicy(int policy) {
- return policy >= HIDDEN_API_ENFORCEMENT_DEFAULT && policy <= HIDDEN_API_ENFORCEMENT_MAX;
+ return policy >= HIDDEN_API_ENFORCEMENT_MIN && policy <= HIDDEN_API_ENFORCEMENT_MAX;
}
private int mHiddenApiPolicy = HIDDEN_API_ENFORCEMENT_DEFAULT;
@@ -1733,16 +1727,12 @@
*/
public @HiddenApiEnforcementPolicy int getHiddenApiEnforcementPolicy() {
if (isAllowedToUseHiddenApis()) {
- return HIDDEN_API_ENFORCEMENT_NONE;
+ return HIDDEN_API_ENFORCEMENT_DISABLED;
}
if (mHiddenApiPolicy != HIDDEN_API_ENFORCEMENT_DEFAULT) {
return mHiddenApiPolicy;
}
- if (targetSdkVersion < Build.VERSION_CODES.P) {
- return HIDDEN_API_ENFORCEMENT_BLACK;
- } else {
- return HIDDEN_API_ENFORCEMENT_DARK_GREY_AND_BLACK;
- }
+ return HIDDEN_API_ENFORCEMENT_ENABLED;
}
/**
@@ -1761,23 +1751,15 @@
* This will have no effect if this app is not subject to hidden API enforcement, i.e. if it
* is on the package whitelist.
*
- * @param policyPreP configured policy for pre-P apps, or {@link
- * #HIDDEN_API_ENFORCEMENT_DEFAULT} if nothing configured.
- * @param policyP configured policy for apps targeting P or later, or {@link
- * #HIDDEN_API_ENFORCEMENT_DEFAULT} if nothing configured.
+ * @param policy configured policy for this app, or {@link #HIDDEN_API_ENFORCEMENT_DEFAULT}
+ * if nothing configured.
* @hide
*/
- public void maybeUpdateHiddenApiEnforcementPolicy(
- @HiddenApiEnforcementPolicy int policyPreP, @HiddenApiEnforcementPolicy int policyP) {
+ public void maybeUpdateHiddenApiEnforcementPolicy(@HiddenApiEnforcementPolicy int policy) {
if (isPackageWhitelistedForHiddenApis()) {
return;
}
- if (targetSdkVersion < Build.VERSION_CODES.P) {
- setHiddenApiEnforcementPolicy(policyPreP);
- } else if (targetSdkVersion >= Build.VERSION_CODES.P) {
- setHiddenApiEnforcementPolicy(policyP);
- }
-
+ setHiddenApiEnforcementPolicy(policy);
}
/**
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 7b076f6..7aea261 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -6317,6 +6317,7 @@
public ArrayList<String> usesOptionalLibraries = null;
@UnsupportedAppUsage
public String[] usesLibraryFiles = null;
+ public ArrayList<SharedLibraryInfo> usesLibraryInfos = null;
public ArrayList<ActivityIntentInfo> preferredActivityFilters = null;
@@ -6846,6 +6847,8 @@
internStringArrayList(usesOptionalLibraries);
usesLibraryFiles = dest.readStringArray();
+ usesLibraryInfos = dest.createTypedArrayList(SharedLibraryInfo.CREATOR);
+
final int libCount = dest.readInt();
if (libCount > 0) {
usesStaticLibraries = new ArrayList<>(libCount);
@@ -6996,6 +6999,7 @@
dest.writeStringList(usesLibraries);
dest.writeStringList(usesOptionalLibraries);
dest.writeStringArray(usesLibraryFiles);
+ dest.writeTypedList(usesLibraryInfos);
if (ArrayUtils.isEmpty(usesStaticLibraries)) {
dest.writeInt(-1);
@@ -7456,6 +7460,10 @@
&& p.usesLibraryFiles != null) {
return true;
}
+ if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0
+ && p.usesLibraryInfos != null) {
+ return true;
+ }
if (p.staticSharedLibName != null) {
return true;
}
diff --git a/core/java/android/content/pm/SharedLibraryInfo.java b/core/java/android/content/pm/SharedLibraryInfo.java
index 33bc951..096301c 100644
--- a/core/java/android/content/pm/SharedLibraryInfo.java
+++ b/core/java/android/content/pm/SharedLibraryInfo.java
@@ -19,11 +19,13 @@
import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.NonNull;
+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.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -69,12 +71,15 @@
*/
public static final int VERSION_UNDEFINED = -1;
+ private final String mPath;
+ private final String mPackageName;
private final String mName;
private final long mVersion;
private final @Type int mType;
private final VersionedPackage mDeclaringPackage;
private final List<VersionedPackage> mDependentPackages;
+ private List<SharedLibraryInfo> mDependencies;
/**
* Creates a new instance.
@@ -87,18 +92,23 @@
*
* @hide
*/
- public SharedLibraryInfo(String name, long version, int type,
- VersionedPackage declaringPackage, List<VersionedPackage> dependentPackages) {
+ public SharedLibraryInfo(String path, String packageName, String name, long version, int type,
+ VersionedPackage declaringPackage, List<VersionedPackage> dependentPackages,
+ List<SharedLibraryInfo> dependencies) {
+ mPath = path;
+ mPackageName = packageName;
mName = name;
mVersion = version;
mType = type;
mDeclaringPackage = declaringPackage;
mDependentPackages = dependentPackages;
+ mDependencies = dependencies;
}
private SharedLibraryInfo(Parcel parcel) {
- this(parcel.readString(), parcel.readLong(), parcel.readInt(),
- parcel.readParcelable(null), parcel.readArrayList(null));
+ this(parcel.readString(), parcel.readString(), parcel.readString(), parcel.readLong(),
+ parcel.readInt(), parcel.readParcelable(null), parcel.readArrayList(null),
+ parcel.createTypedArrayList(SharedLibraryInfo.CREATOR));
}
/**
@@ -121,6 +131,71 @@
}
/**
+ * If the shared library is a jar file, returns the path of that jar. Null otherwise.
+ * Only libraries with TYPE_BUILTIN are in jar files.
+ *
+ * @return The path.
+ *
+ * @hide
+ */
+ public @Nullable String getPath() {
+ return mPath;
+ }
+
+ /**
+ * If the shared library is an apk, returns the package name. Null otherwise.
+ * Only libraries with TYPE_DYNAMIC or TYPE_STATIC are in apks.
+ *
+ * @return The package name.
+ *
+ * @hide
+ */
+ public @Nullable String getPackageName() {
+ return mPackageName;
+ }
+
+ /**
+ * Add a library dependency to that library. Note that this
+ * should be called under the package manager lock.
+ *
+ * @hide
+ */
+ public void addDependency(@Nullable SharedLibraryInfo info) {
+ if (info == null) {
+ // For convenience of the caller, allow null to be passed.
+ // This can happen when we create the dependencies of builtin
+ // libraries.
+ return;
+ }
+ if (mDependencies == null) {
+ mDependencies = new ArrayList<>();
+ }
+ mDependencies.add(info);
+ }
+
+ /**
+ * Clear all dependencies.
+ *
+ * @hide
+ */
+ public void clearDependencies() {
+ mDependencies = null;
+ }
+
+ /**
+ * Gets the libraries this library directly depends on. Note that
+ * the package manager prevents recursive dependencies when installing
+ * a package.
+ *
+ * @return The dependencies.
+ *
+ * @hide
+ */
+ public @Nullable List<SharedLibraryInfo> getDependencies() {
+ return mDependencies;
+ }
+
+ /**
* @deprecated Use {@link #getLongVersion()} instead.
*/
@Deprecated
@@ -196,11 +271,14 @@
@Override
public void writeToParcel(Parcel parcel, int flags) {
+ parcel.writeString(mPath);
+ parcel.writeString(mPackageName);
parcel.writeString(mName);
parcel.writeLong(mVersion);
parcel.writeInt(mType);
parcel.writeParcelable(mDeclaringPackage, flags);
parcel.writeList(mDependentPackages);
+ parcel.writeTypedList(mDependencies);
}
private static String typeToString(int type) {
diff --git a/core/java/android/content/pm/SharedLibraryNames.java b/core/java/android/content/pm/SharedLibraryNames.java
index 387d29e8..5afc8a9 100644
--- a/core/java/android/content/pm/SharedLibraryNames.java
+++ b/core/java/android/content/pm/SharedLibraryNames.java
@@ -22,15 +22,15 @@
*/
public class SharedLibraryNames {
- static final String ANDROID_HIDL_BASE = "android.hidl.base-V1.0-java";
+ public static final String ANDROID_HIDL_BASE = "android.hidl.base-V1.0-java";
- static final String ANDROID_HIDL_MANAGER = "android.hidl.manager-V1.0-java";
+ public static final String ANDROID_HIDL_MANAGER = "android.hidl.manager-V1.0-java";
- static final String ANDROID_TEST_BASE = "android.test.base";
+ public static final String ANDROID_TEST_BASE = "android.test.base";
- static final String ANDROID_TEST_MOCK = "android.test.mock";
+ public static final String ANDROID_TEST_MOCK = "android.test.mock";
- static final String ANDROID_TEST_RUNNER = "android.test.runner";
+ public static final String ANDROID_TEST_RUNNER = "android.test.runner";
- static final String ORG_APACHE_HTTP_LEGACY = "org.apache.http.legacy";
+ public static final String ORG_APACHE_HTTP_LEGACY = "org.apache.http.legacy";
}
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 221abed..517eaf8 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -2419,7 +2419,7 @@
public static final IntToString[] HISTORY_EVENT_INT_FORMATTERS = new IntToString[] {
sUidToString, sUidToString, sUidToString, sUidToString, sUidToString, sUidToString,
- sUidToString, sUidToString, sUidToString, sUidToString, sUidToString, sUidToString,
+ sUidToString, sUidToString, sUidToString, sUidToString, sUidToString, sIntToString,
sUidToString, sUidToString, sUidToString, sUidToString, sUidToString, sUidToString,
sUidToString, sUidToString, sUidToString, sIntToString
};
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java
index 88d6e84..ddeb838 100644
--- a/core/java/android/os/FileUtils.java
+++ b/core/java/android/os/FileUtils.java
@@ -16,6 +16,18 @@
package android.os;
+import static android.os.ParcelFileDescriptor.MODE_APPEND;
+import static android.os.ParcelFileDescriptor.MODE_CREATE;
+import static android.os.ParcelFileDescriptor.MODE_READ_ONLY;
+import static android.os.ParcelFileDescriptor.MODE_READ_WRITE;
+import static android.os.ParcelFileDescriptor.MODE_TRUNCATE;
+import static android.os.ParcelFileDescriptor.MODE_WRITE_ONLY;
+import static android.system.OsConstants.O_APPEND;
+import static android.system.OsConstants.O_CREAT;
+import static android.system.OsConstants.O_RDONLY;
+import static android.system.OsConstants.O_RDWR;
+import static android.system.OsConstants.O_TRUNC;
+import static android.system.OsConstants.O_WRONLY;
import static android.system.OsConstants.SPLICE_F_MORE;
import static android.system.OsConstants.SPLICE_F_MOVE;
import static android.system.OsConstants.S_ISFIFO;
@@ -1050,6 +1062,30 @@
return val * pow;
}
+ /** {@hide} */
+ public static int translateModePfdToPosix(int mode) {
+ int res = 0;
+ if ((mode & MODE_READ_WRITE) == MODE_READ_WRITE) {
+ res |= O_RDWR;
+ } else if ((mode & MODE_WRITE_ONLY) == MODE_WRITE_ONLY) {
+ res |= O_WRONLY;
+ } else if ((mode & MODE_READ_ONLY) == MODE_READ_ONLY) {
+ res |= O_RDONLY;
+ } else {
+ throw new IllegalArgumentException("Bad mode: " + mode);
+ }
+ if ((mode & MODE_CREATE) == MODE_CREATE) {
+ res |= O_CREAT;
+ }
+ if ((mode & MODE_TRUNCATE) == MODE_TRUNCATE) {
+ res |= O_TRUNC;
+ }
+ if ((mode & MODE_APPEND) == MODE_APPEND) {
+ res |= O_APPEND;
+ }
+ return res;
+ }
+
@VisibleForTesting
public static class MemoryPipe extends Thread implements AutoCloseable {
private final FileDescriptor[] pipe;
@@ -1115,3 +1151,4 @@
}
}
}
+
diff --git a/core/java/android/os/ParcelFileDescriptor.java b/core/java/android/os/ParcelFileDescriptor.java
index 7409ca7..81fc5c0 100644
--- a/core/java/android/os/ParcelFileDescriptor.java
+++ b/core/java/android/os/ParcelFileDescriptor.java
@@ -1092,6 +1092,9 @@
/**
* Internal class representing a remote status read by
* {@link ParcelFileDescriptor#readCommStatus(FileDescriptor, byte[])}.
+ *
+ * Warning: this must be kept in sync with ParcelFileDescriptorStatus at
+ * frameworks/native/libs/binder/Parcel.cpp
*/
private static class Status {
/** Special value indicating remote side died. */
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 916676a..258426e 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -12166,27 +12166,14 @@
"hidden_api_access_log_sampling_rate";
/**
- * Hidden API enforcement policy for apps targeting SDK versions prior to the latest
- * version.
+ * Hidden API enforcement policy for apps.
*
* Values correspond to @{@link
* android.content.pm.ApplicationInfo.HiddenApiEnforcementPolicy}
*
* @hide
*/
- public static final String HIDDEN_API_POLICY_PRE_P_APPS =
- "hidden_api_policy_pre_p_apps";
-
- /**
- * Hidden API enforcement policy for apps targeting the current SDK version.
- *
- * Values correspond to @{@link
- * android.content.pm.ApplicationInfo.HiddenApiEnforcementPolicy}
- *
- * @hide
- */
- public static final String HIDDEN_API_POLICY_P_APPS =
- "hidden_api_policy_p_apps";
+ public static final String HIDDEN_API_POLICY = "hidden_api_policy";
/**
* Timeout for a single {@link android.media.soundtrigger.SoundTriggerDetectionService}
diff --git a/core/java/android/security/keymaster/ExportResult.java b/core/java/android/security/keymaster/ExportResult.java
index c104671..1ab79fb 100644
--- a/core/java/android/security/keymaster/ExportResult.java
+++ b/core/java/android/security/keymaster/ExportResult.java
@@ -28,6 +28,11 @@
public final int resultCode;
public final byte[] exportData;
+ public ExportResult(int resultCode) {
+ this.resultCode = resultCode;
+ this.exportData = new byte[0];
+ }
+
@UnsupportedAppUsage
public static final Parcelable.Creator<ExportResult> CREATOR = new
Parcelable.Creator<ExportResult>() {
diff --git a/core/java/android/security/keymaster/KeyCharacteristics.java b/core/java/android/security/keymaster/KeyCharacteristics.java
index 555863e..a4fe75d 100644
--- a/core/java/android/security/keymaster/KeyCharacteristics.java
+++ b/core/java/android/security/keymaster/KeyCharacteristics.java
@@ -52,6 +52,14 @@
readFromParcel(in);
}
+ /**
+ * Makes a shallow copy of other by copying the other's references to the KeymasterArguments
+ */
+ public void shallowCopyFrom(KeyCharacteristics other) {
+ this.swEnforced = other.swEnforced;
+ this.hwEnforced = other.hwEnforced;
+ }
+
@Override
public int describeContents() {
return 0;
diff --git a/core/java/android/security/keymaster/KeymasterCertificateChain.java b/core/java/android/security/keymaster/KeymasterCertificateChain.java
index 243b9fe..00a1a1c 100644
--- a/core/java/android/security/keymaster/KeymasterCertificateChain.java
+++ b/core/java/android/security/keymaster/KeymasterCertificateChain.java
@@ -54,6 +54,14 @@
readFromParcel(in);
}
+ /**
+ * Makes a shallow copy of other by copying the reference to the certificate chain list.
+ * @param other
+ */
+ public void shallowCopyFrom(KeymasterCertificateChain other) {
+ this.mCertificates = other.mCertificates;
+ }
+
public List<byte[]> getCertificates() {
return mCertificates;
}
diff --git a/core/java/android/security/keymaster/OperationResult.java b/core/java/android/security/keymaster/OperationResult.java
index 2943211..bc4f360 100644
--- a/core/java/android/security/keymaster/OperationResult.java
+++ b/core/java/android/security/keymaster/OperationResult.java
@@ -59,6 +59,10 @@
this.outParams = outParams;
}
+ public OperationResult(int resultCode) {
+ this(resultCode, null, 0, 0, null, null);
+ }
+
protected OperationResult(Parcel in) {
resultCode = in.readInt();
token = in.readStrongBinder();
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 8f87f91..8bdb000 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -173,12 +173,13 @@
}
native private static void nativePreloadAppProcessHALs();
+ native private static void nativePreloadOpenGL();
private static void preloadOpenGL() {
String driverPackageName = SystemProperties.get(PROPERTY_GFX_DRIVER);
if (!SystemProperties.getBoolean(PROPERTY_DISABLE_OPENGL_PRELOADING, false) &&
(driverPackageName == null || driverPackageName.isEmpty())) {
- EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY);
+ nativePreloadOpenGL();
}
}
diff --git a/core/jni/com_android_internal_os_ZygoteInit.cpp b/core/jni/com_android_internal_os_ZygoteInit.cpp
index 258a55c..ac0e600 100644
--- a/core/jni/com_android_internal_os_ZygoteInit.cpp
+++ b/core/jni/com_android_internal_os_ZygoteInit.cpp
@@ -16,21 +16,58 @@
#define LOG_TAG "Zygote"
+#include <EGL/egl.h>
#include <ui/GraphicBufferMapper.h>
#include "core_jni_helpers.h"
namespace {
+// Shadow call stack (SCS) is a security mitigation that uses a separate stack
+// (the SCS) for return addresses. In versions of Android newer than P, the
+// compiler cooperates with the system to ensure that the SCS address is always
+// stored in register x18, as long as the app was compiled with a new enough
+// compiler and does not use features that rely on SP-HALs (this restriction is
+// because the SP-HALs might not preserve x18 due to potentially having been
+// compiled with an old compiler as a consequence of Treble; it generally means
+// that the app must be a system app without a UI). This struct is used to
+// temporarily store the address on the stack while preloading the SP-HALs, so
+// that such apps can use the same zygote as everything else.
+struct ScopedSCSExit {
+#ifdef __aarch64__
+ void* scs;
+
+ ScopedSCSExit() {
+ __asm__ __volatile__("str x18, [%0]" ::"r"(&scs));
+ }
+
+ ~ScopedSCSExit() {
+ __asm__ __volatile__("ldr x18, [%0]; str xzr, [%0]" ::"r"(&scs));
+ }
+#else
+ // Silence unused variable warnings in non-SCS builds.
+ ScopedSCSExit() {}
+ ~ScopedSCSExit() {}
+#endif
+};
+
void android_internal_os_ZygoteInit_nativePreloadAppProcessHALs(JNIEnv* env, jclass) {
+ ScopedSCSExit x;
android::GraphicBufferMapper::preloadHal();
// Add preloading here for other HALs that are (a) always passthrough, and
// (b) loaded by most app processes.
}
+void android_internal_os_ZygoteInit_nativePreloadOpenGL(JNIEnv* env, jclass) {
+ ScopedSCSExit x;
+ eglGetDisplay(EGL_DEFAULT_DISPLAY);
+}
+
const JNINativeMethod gMethods[] = {
{ "nativePreloadAppProcessHALs", "()V",
(void*)android_internal_os_ZygoteInit_nativePreloadAppProcessHALs },
+ { "nativePreloadOpenGL", "()V",
+ (void*)android_internal_os_ZygoteInit_nativePreloadOpenGL },
};
} // anonymous namespace
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index f599b1f..9ce6044 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -399,6 +399,7 @@
<protected-broadcast android:name="android.telecom.action.DEFAULT_DIALER_CHANGED" />
<protected-broadcast android:name="android.provider.action.DEFAULT_SMS_PACKAGE_CHANGED" />
<protected-broadcast android:name="android.provider.action.SMS_MMS_DB_CREATED" />
+ <protected-broadcast android:name="android.provider.action.SMS_MMS_DB_LOST" />
<protected-broadcast android:name="android.intent.action.CONTENT_CHANGED" />
<protected-broadcast android:name="android.provider.Telephony.MMS_DOWNLOADED" />
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index d498268..9d3085a 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -256,8 +256,7 @@
Settings.Global.HDMI_SYSTEM_AUDIO_CONTROL_ENABLED,
Settings.Global.HEADS_UP_NOTIFICATIONS_ENABLED,
Settings.Global.HIDDEN_API_ACCESS_LOG_SAMPLING_RATE,
- Settings.Global.HIDDEN_API_POLICY_P_APPS,
- Settings.Global.HIDDEN_API_POLICY_PRE_P_APPS,
+ Settings.Global.HIDDEN_API_POLICY,
Settings.Global.HIDE_ERROR_DIALOGS,
Settings.Global.HTTP_PROXY,
HYBRID_SYSUI_BATTERY_WARNING_FLAGS,
diff --git a/data/etc/Android.mk b/data/etc/Android.mk
index 936ad22..d24c140 100644
--- a/data/etc/Android.mk
+++ b/data/etc/Android.mk
@@ -47,3 +47,11 @@
LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/sysconfig
LOCAL_SRC_FILES := $(LOCAL_MODULE)
include $(BUILD_PREBUILT)
+
+########################
+include $(CLEAR_VARS)
+LOCAL_MODULE := com.android.timezone.updater.xml
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_RELATIVE_PATH := permissions
+LOCAL_SRC_FILES := $(LOCAL_MODULE)
+include $(BUILD_PREBUILT)
diff --git a/data/etc/com.android.timezone.updater.xml b/data/etc/com.android.timezone.updater.xml
new file mode 100644
index 0000000..60a66e2
--- /dev/null
+++ b/data/etc/com.android.timezone.updater.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ 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
+ -->
+<permissions>
+ <privapp-permissions package="com.android.timezone.updater">
+ <permission name="android.permission.QUERY_TIME_ZONE_RULES" />
+ <permission name="android.permission.UPDATE_TIME_ZONE_RULES" />
+ </privapp-permissions>
+</permissions>
diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java
index 4e01883..40570c1 100644
--- a/keystore/java/android/security/KeyStore.java
+++ b/keystore/java/android/security/KeyStore.java
@@ -38,11 +38,13 @@
import android.security.keymaster.KeymasterCertificateChain;
import android.security.keymaster.KeymasterDefs;
import android.security.keymaster.OperationResult;
+import android.security.keystore.IKeystoreService;
import android.security.keystore.KeyExpiredException;
import android.security.keystore.KeyNotYetValidException;
import android.security.keystore.KeyPermanentlyInvalidatedException;
import android.security.keystore.KeyProperties;
import android.security.keystore.KeyProtection;
+import android.security.keystore.KeystoreResponse;
import android.security.keystore.StrongBoxUnavailableException;
import android.security.keystore.UserNotAuthenticatedException;
import android.util.Log;
@@ -52,8 +54,11 @@
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.security.InvalidKeyException;
+import java.util.Arrays;
import java.util.List;
import java.util.Locale;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
import sun.security.util.ObjectIdentifier;
import sun.security.x509.AlgorithmId;
@@ -292,6 +297,31 @@
}
}
+ /**
+ * List uids of all keys that are auth bound to the current user.
+ * Only system is allowed to call this method.
+ */
+ @UnsupportedAppUsage
+ public int[] listUidsOfAuthBoundKeys() {
+ final int MAX_RESULT_SIZE = 100;
+ int[] uidsOut = new int[MAX_RESULT_SIZE];
+ try {
+ int rc = mBinder.listUidsOfAuthBoundKeys(uidsOut);
+ if (rc != NO_ERROR) {
+ Log.w(TAG, String.format("listUidsOfAuthBoundKeys failed with error code %d", rc));
+ return null;
+ }
+ } catch (RemoteException e) {
+ Log.w(TAG, "Cannot connect to keystore", e);
+ return null;
+ } catch (android.os.ServiceSpecificException e) {
+ Log.w(TAG, "KeyStore exception", e);
+ return null;
+ }
+ // Remove any 0 entries
+ return Arrays.stream(uidsOut).filter(x -> x > 0).toArray();
+ }
+
public String[] list(String prefix) {
return list(prefix, UID_SELF);
}
@@ -440,27 +470,107 @@
public boolean addRngEntropy(byte[] data, int flags) {
try {
- return mBinder.addRngEntropy(data, flags) == NO_ERROR;
+ KeystoreResultPromise promise = new KeystoreResultPromise();
+ int errorCode = mBinder.addRngEntropy(promise, data, flags);
+ if (errorCode == NO_ERROR) {
+ return promise.getFuture().get().getErrorCode() == NO_ERROR;
+ } else {
+ return false;
+ }
} catch (RemoteException e) {
Log.w(TAG, "Cannot connect to keystore", e);
return false;
+ } catch (ExecutionException | InterruptedException e) {
+ Log.e(TAG, "AddRngEntropy completed with exception", e);
+ return false;
}
}
+ private class KeyCharacteristicsCallbackResult {
+ private KeystoreResponse keystoreResponse;
+ private KeyCharacteristics keyCharacteristics;
+
+ public KeyCharacteristicsCallbackResult(KeystoreResponse keystoreResponse,
+ KeyCharacteristics keyCharacteristics) {
+ this.keystoreResponse = keystoreResponse;
+ this.keyCharacteristics = keyCharacteristics;
+ }
+
+ public KeystoreResponse getKeystoreResponse() {
+ return keystoreResponse;
+ }
+
+ public void setKeystoreResponse(KeystoreResponse keystoreResponse) {
+ this.keystoreResponse = keystoreResponse;
+ }
+
+ public KeyCharacteristics getKeyCharacteristics() {
+ return keyCharacteristics;
+ }
+
+ public void setKeyCharacteristics(KeyCharacteristics keyCharacteristics) {
+ this.keyCharacteristics = keyCharacteristics;
+ }
+ }
+
+ private class KeyCharacteristicsPromise
+ extends android.security.keystore.IKeystoreKeyCharacteristicsCallback.Stub {
+ final private CompletableFuture<KeyCharacteristicsCallbackResult> future =
+ new CompletableFuture<KeyCharacteristicsCallbackResult>();
+ @Override
+ public void onFinished(KeystoreResponse keystoreResponse,
+ KeyCharacteristics keyCharacteristics)
+ throws android.os.RemoteException {
+ future.complete(
+ new KeyCharacteristicsCallbackResult(keystoreResponse, keyCharacteristics));
+ }
+ public final CompletableFuture<KeyCharacteristicsCallbackResult> getFuture() {
+ return future;
+ }
+ };
+
+ private int generateKeyInternal(String alias, KeymasterArguments args, byte[] entropy, int uid,
+ int flags, KeyCharacteristics outCharacteristics)
+ throws RemoteException, ExecutionException, InterruptedException {
+ KeyCharacteristicsPromise promise = new KeyCharacteristicsPromise();
+ int error = mBinder.generateKey(promise, alias, args, entropy, uid, flags);
+ if (error != NO_ERROR) {
+ Log.e(TAG, "generateKeyInternal failed on request " + error);
+ return error;
+ }
+
+ KeyCharacteristicsCallbackResult result = promise.getFuture().get();
+ error = result.getKeystoreResponse().getErrorCode();
+ if (error != NO_ERROR) {
+ Log.e(TAG, "generateKeyInternal failed on response " + error);
+ return error;
+ }
+ KeyCharacteristics characteristics = result.getKeyCharacteristics();
+ if (characteristics == null) {
+ Log.e(TAG, "generateKeyInternal got empty key cheractariestics " + error);
+ return SYSTEM_ERROR;
+ }
+ outCharacteristics.shallowCopyFrom(characteristics);
+ return NO_ERROR;
+ }
+
public int generateKey(String alias, KeymasterArguments args, byte[] entropy, int uid,
int flags, KeyCharacteristics outCharacteristics) {
try {
entropy = entropy != null ? entropy : new byte[0];
args = args != null ? args : new KeymasterArguments();
- int error = mBinder.generateKey(alias, args, entropy, uid, flags, outCharacteristics);
+ int error = generateKeyInternal(alias, args, entropy, uid, flags, outCharacteristics);
if (error == KEY_ALREADY_EXISTS) {
mBinder.del(alias, uid);
- error = mBinder.generateKey(alias, args, entropy, uid, flags, outCharacteristics);
+ error = generateKeyInternal(alias, args, entropy, uid, flags, outCharacteristics);
}
return error;
} catch (RemoteException e) {
Log.w(TAG, "Cannot connect to keystore", e);
return SYSTEM_ERROR;
+ } catch (ExecutionException | InterruptedException e) {
+ Log.e(TAG, "generateKey completed with exception", e);
+ return SYSTEM_ERROR;
}
}
@@ -474,10 +584,24 @@
try {
clientId = clientId != null ? clientId : new KeymasterBlob(new byte[0]);
appId = appId != null ? appId : new KeymasterBlob(new byte[0]);
- return mBinder.getKeyCharacteristics(alias, clientId, appId, uid, outCharacteristics);
+ KeyCharacteristicsPromise promise = new KeyCharacteristicsPromise();
+ int error = mBinder.getKeyCharacteristics(promise, alias, clientId, appId, uid);
+ if (error != NO_ERROR) return error;
+
+ KeyCharacteristicsCallbackResult result = promise.getFuture().get();
+ error = result.getKeystoreResponse().getErrorCode();
+ if (error != NO_ERROR) return error;
+
+ KeyCharacteristics characteristics = result.getKeyCharacteristics();
+ if (characteristics == null) return SYSTEM_ERROR;
+ outCharacteristics.shallowCopyFrom(characteristics);
+ return NO_ERROR;
} catch (RemoteException e) {
Log.w(TAG, "Cannot connect to keystore", e);
return SYSTEM_ERROR;
+ } catch (ExecutionException | InterruptedException e) {
+ Log.e(TAG, "GetKeyCharacteristics completed with exception", e);
+ return SYSTEM_ERROR;
}
}
@@ -486,20 +610,40 @@
return getKeyCharacteristics(alias, clientId, appId, UID_SELF, outCharacteristics);
}
+ private int importKeyInternal(String alias, KeymasterArguments args, int format, byte[] keyData,
+ int uid, int flags, KeyCharacteristics outCharacteristics)
+ throws RemoteException, ExecutionException, InterruptedException {
+ KeyCharacteristicsPromise promise = new KeyCharacteristicsPromise();
+ int error = mBinder.importKey(promise, alias, args, format, keyData, uid, flags);
+ if (error != NO_ERROR) return error;
+
+ KeyCharacteristicsCallbackResult result = promise.getFuture().get();
+ error = result.getKeystoreResponse().getErrorCode();
+ if (error != NO_ERROR) return error;
+
+ KeyCharacteristics characteristics = result.getKeyCharacteristics();
+ if (characteristics == null) return SYSTEM_ERROR;
+ outCharacteristics.shallowCopyFrom(characteristics);
+ return NO_ERROR;
+ }
+
public int importKey(String alias, KeymasterArguments args, int format, byte[] keyData,
int uid, int flags, KeyCharacteristics outCharacteristics) {
try {
- int error = mBinder.importKey(alias, args, format, keyData, uid, flags,
+ int error = importKeyInternal(alias, args, format, keyData, uid, flags,
outCharacteristics);
if (error == KEY_ALREADY_EXISTS) {
mBinder.del(alias, uid);
- error = mBinder.importKey(alias, args, format, keyData, uid, flags,
+ error = importKeyInternal(alias, args, format, keyData, uid, flags,
outCharacteristics);
}
return error;
} catch (RemoteException e) {
Log.w(TAG, "Cannot connect to keystore", e);
return SYSTEM_ERROR;
+ } catch (ExecutionException | InterruptedException e) {
+ Log.e(TAG, "ImportKey completed with exception", e);
+ return SYSTEM_ERROR;
}
}
@@ -567,34 +711,79 @@
return true;
}
+ private int importWrappedKeyInternal(String wrappedKeyAlias, byte[] wrappedKey,
+ String wrappingKeyAlias,
+ byte[] maskingKey, KeymasterArguments args, long rootSid, long fingerprintSid,
+ KeyCharacteristics outCharacteristics)
+ throws RemoteException, ExecutionException, InterruptedException {
+ KeyCharacteristicsPromise promise = new KeyCharacteristicsPromise();
+ int error = mBinder.importWrappedKey(promise, wrappedKeyAlias, wrappedKey, wrappingKeyAlias,
+ maskingKey, args, rootSid, fingerprintSid);
+ if (error != NO_ERROR) return error;
+
+ KeyCharacteristicsCallbackResult result = promise.getFuture().get();
+ error = result.getKeystoreResponse().getErrorCode();
+ if (error != NO_ERROR) return error;
+
+ KeyCharacteristics characteristics = result.getKeyCharacteristics();
+ if (characteristics == null) return SYSTEM_ERROR;
+ outCharacteristics.shallowCopyFrom(characteristics);
+ return NO_ERROR;
+ }
+
public int importWrappedKey(String wrappedKeyAlias, byte[] wrappedKey,
String wrappingKeyAlias,
byte[] maskingKey, KeymasterArguments args, long rootSid, long fingerprintSid, int uid,
KeyCharacteristics outCharacteristics) {
+ // TODO b/119217337 uid parameter gets silently ignored.
try {
- int error = mBinder.importWrappedKey(wrappedKeyAlias, wrappedKey, wrappingKeyAlias,
+ int error = importWrappedKeyInternal(wrappedKeyAlias, wrappedKey, wrappingKeyAlias,
maskingKey, args, rootSid, fingerprintSid, outCharacteristics);
if (error == KEY_ALREADY_EXISTS) {
- mBinder.del(wrappedKeyAlias, -1);
- error = mBinder.importWrappedKey(wrappedKeyAlias, wrappedKey, wrappingKeyAlias,
+ mBinder.del(wrappedKeyAlias, UID_SELF);
+ error = importWrappedKeyInternal(wrappedKeyAlias, wrappedKey, wrappingKeyAlias,
maskingKey, args, rootSid, fingerprintSid, outCharacteristics);
}
return error;
} catch (RemoteException e) {
Log.w(TAG, "Cannot connect to keystore", e);
return SYSTEM_ERROR;
+ } catch (ExecutionException | InterruptedException e) {
+ Log.e(TAG, "ImportWrappedKey completed with exception", e);
+ return SYSTEM_ERROR;
}
}
+ private class ExportKeyPromise
+ extends android.security.keystore.IKeystoreExportKeyCallback.Stub {
+ final private CompletableFuture<ExportResult> future = new CompletableFuture<ExportResult>();
+ @Override
+ public void onFinished(ExportResult exportKeyResult) throws android.os.RemoteException {
+ future.complete(exportKeyResult);
+ }
+ public final CompletableFuture<ExportResult> getFuture() {
+ return future;
+ }
+ };
+
public ExportResult exportKey(String alias, int format, KeymasterBlob clientId,
KeymasterBlob appId, int uid) {
try {
clientId = clientId != null ? clientId : new KeymasterBlob(new byte[0]);
appId = appId != null ? appId : new KeymasterBlob(new byte[0]);
- return mBinder.exportKey(alias, format, clientId, appId, uid);
+ ExportKeyPromise promise = new ExportKeyPromise();
+ int error = mBinder.exportKey(promise, alias, format, clientId, appId, uid);
+ if (error == NO_ERROR) {
+ return promise.getFuture().get();
+ } else {
+ return new ExportResult(error);
+ }
} catch (RemoteException e) {
Log.w(TAG, "Cannot connect to keystore", e);
return null;
+ } catch (ExecutionException | InterruptedException e) {
+ Log.e(TAG, "ExportKey completed with exception", e);
+ return null;
}
}
public ExportResult exportKey(String alias, int format, KeymasterBlob clientId,
@@ -602,15 +791,37 @@
return exportKey(alias, format, clientId, appId, UID_SELF);
}
+ private class OperationPromise
+ extends android.security.keystore.IKeystoreOperationResultCallback.Stub {
+ final private CompletableFuture<OperationResult> future = new CompletableFuture<OperationResult>();
+ @Override
+ public void onFinished(OperationResult operationResult) throws android.os.RemoteException {
+ future.complete(operationResult);
+ }
+ public final CompletableFuture<OperationResult> getFuture() {
+ return future;
+ }
+ };
+
public OperationResult begin(String alias, int purpose, boolean pruneable,
KeymasterArguments args, byte[] entropy, int uid) {
try {
args = args != null ? args : new KeymasterArguments();
entropy = entropy != null ? entropy : new byte[0];
- return mBinder.begin(getToken(), alias, purpose, pruneable, args, entropy, uid);
+ OperationPromise promise = new OperationPromise();
+ int errorCode = mBinder.begin(promise, getToken(), alias, purpose, pruneable, args,
+ entropy, uid);
+ if (errorCode == NO_ERROR) {
+ return promise.getFuture().get();
+ } else {
+ return new OperationResult(errorCode);
+ }
} catch (RemoteException e) {
Log.w(TAG, "Cannot connect to keystore", e);
return null;
+ } catch (ExecutionException | InterruptedException e) {
+ Log.e(TAG, "Begin completed with exception", e);
+ return null;
}
}
@@ -625,10 +836,19 @@
try {
arguments = arguments != null ? arguments : new KeymasterArguments();
input = input != null ? input : new byte[0];
- return mBinder.update(token, arguments, input);
+ OperationPromise promise = new OperationPromise();
+ int errorCode = mBinder.update(promise, token, arguments, input);
+ if (errorCode == NO_ERROR) {
+ return promise.getFuture().get();
+ } else {
+ return new OperationResult(errorCode);
+ }
} catch (RemoteException e) {
Log.w(TAG, "Cannot connect to keystore", e);
return null;
+ } catch (ExecutionException | InterruptedException e) {
+ Log.e(TAG, "Update completed with exception", e);
+ return null;
}
}
@@ -638,10 +858,19 @@
arguments = arguments != null ? arguments : new KeymasterArguments();
entropy = entropy != null ? entropy : new byte[0];
signature = signature != null ? signature : new byte[0];
- return mBinder.finish(token, arguments, signature, entropy);
+ OperationPromise promise = new OperationPromise();
+ int errorCode = mBinder.finish(promise, token, arguments, signature, entropy);
+ if (errorCode == NO_ERROR) {
+ return promise.getFuture().get();
+ } else {
+ return new OperationResult(errorCode);
+ }
} catch (RemoteException e) {
Log.w(TAG, "Cannot connect to keystore", e);
return null;
+ } catch (ExecutionException | InterruptedException e) {
+ Log.e(TAG, "Finish completed with exception", e);
+ return null;
}
}
@@ -649,12 +878,33 @@
return finish(token, arguments, signature, null);
}
+ private class KeystoreResultPromise
+ extends android.security.keystore.IKeystoreResponseCallback.Stub {
+ final private CompletableFuture<KeystoreResponse> future = new CompletableFuture<KeystoreResponse>();
+ @Override
+ public void onFinished(KeystoreResponse keystoreResponse) throws android.os.RemoteException {
+ future.complete(keystoreResponse);
+ }
+ public final CompletableFuture<KeystoreResponse> getFuture() {
+ return future;
+ }
+ };
+
public int abort(IBinder token) {
try {
- return mBinder.abort(token);
+ KeystoreResultPromise promise = new KeystoreResultPromise();
+ int errorCode = mBinder.abort(promise, token);
+ if (errorCode == NO_ERROR) {
+ return promise.getFuture().get().getErrorCode();
+ } else {
+ return errorCode;
+ }
} catch (RemoteException e) {
Log.w(TAG, "Cannot connect to keystore", e);
return SYSTEM_ERROR;
+ } catch (ExecutionException | InterruptedException e) {
+ Log.e(TAG, "Abort completed with exception", e);
+ return SYSTEM_ERROR;
}
}
@@ -736,6 +986,47 @@
return onUserPasswordChanged(UserHandle.getUserId(Process.myUid()), newPassword);
}
+ private class KeyAttestationCallbackResult {
+ private KeystoreResponse keystoreResponse;
+ private KeymasterCertificateChain certificateChain;
+
+ public KeyAttestationCallbackResult(KeystoreResponse keystoreResponse,
+ KeymasterCertificateChain certificateChain) {
+ this.keystoreResponse = keystoreResponse;
+ this.certificateChain = certificateChain;
+ }
+
+ public KeystoreResponse getKeystoreResponse() {
+ return keystoreResponse;
+ }
+
+ public void setKeystoreResponse(KeystoreResponse keystoreResponse) {
+ this.keystoreResponse = keystoreResponse;
+ }
+
+ public KeymasterCertificateChain getCertificateChain() {
+ return certificateChain;
+ }
+
+ public void setCertificateChain(KeymasterCertificateChain certificateChain) {
+ this.certificateChain = certificateChain;
+ }
+ }
+
+ private class CertificateChainPromise
+ extends android.security.keystore.IKeystoreCertificateChainCallback.Stub {
+ final private CompletableFuture<KeyAttestationCallbackResult> future = new CompletableFuture<KeyAttestationCallbackResult>();
+ @Override
+ public void onFinished(KeystoreResponse keystoreResponse,
+ KeymasterCertificateChain certificateChain) throws android.os.RemoteException {
+ future.complete(new KeyAttestationCallbackResult(keystoreResponse, certificateChain));
+ }
+ public final CompletableFuture<KeyAttestationCallbackResult> getFuture() {
+ return future;
+ }
+ };
+
+
public int attestKey(
String alias, KeymasterArguments params, KeymasterCertificateChain outChain) {
try {
@@ -745,10 +1036,21 @@
if (outChain == null) {
outChain = new KeymasterCertificateChain();
}
- return mBinder.attestKey(alias, params, outChain);
+ CertificateChainPromise promise = new CertificateChainPromise();
+ int error = mBinder.attestKey(promise, alias, params);
+ if (error != NO_ERROR) return error;
+ KeyAttestationCallbackResult result = promise.getFuture().get();
+ error = result.getKeystoreResponse().getErrorCode();
+ if (error == NO_ERROR) {
+ outChain.shallowCopyFrom(result.getCertificateChain());
+ }
+ return error;
} catch (RemoteException e) {
Log.w(TAG, "Cannot connect to keystore", e);
return SYSTEM_ERROR;
+ } catch (ExecutionException | InterruptedException e) {
+ Log.e(TAG, "AttestKey completed with exception", e);
+ return SYSTEM_ERROR;
}
}
@@ -760,10 +1062,21 @@
if (outChain == null) {
outChain = new KeymasterCertificateChain();
}
- return mBinder.attestDeviceIds(params, outChain);
+ CertificateChainPromise promise = new CertificateChainPromise();
+ int error = mBinder.attestDeviceIds(promise, params);
+ if (error != NO_ERROR) return error;
+ KeyAttestationCallbackResult result = promise.getFuture().get();
+ error = result.getKeystoreResponse().getErrorCode();
+ if (error == NO_ERROR) {
+ outChain.shallowCopyFrom(result.getCertificateChain());
+ }
+ return error;
} catch (RemoteException e) {
Log.w(TAG, "Cannot connect to keystore", e);
return SYSTEM_ERROR;
+ } catch (ExecutionException | InterruptedException e) {
+ Log.e(TAG, "AttestDevicdeIds completed with exception", e);
+ return SYSTEM_ERROR;
}
}
diff --git a/keystore/java/android/security/keystore/KeystoreResponse.java b/keystore/java/android/security/keystore/KeystoreResponse.java
new file mode 100644
index 0000000..3a229cb
--- /dev/null
+++ b/keystore/java/android/security/keystore/KeystoreResponse.java
@@ -0,0 +1,78 @@
+/*
+ * 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.security.keystore;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.ParcelFormatException;
+
+/**
+ * The Java side of the KeystoreResponse.
+ * <p>
+ * Serialization code for this and subclasses must be kept in sync with system/security/keystore.
+ * @hide
+ */
+public class KeystoreResponse implements Parcelable {
+ public final int error_code_;
+ public final String error_msg_;
+
+ public static final Parcelable.Creator<KeystoreResponse> CREATOR = new
+ Parcelable.Creator<KeystoreResponse>() {
+ @Override
+ public KeystoreResponse createFromParcel(Parcel in) {
+ final int error_code = in.readInt();
+ final String error_msg = in.readString();
+ return new KeystoreResponse(error_code, error_msg);
+ }
+
+ @Override
+ public KeystoreResponse[] newArray(int size) {
+ return new KeystoreResponse[size];
+ }
+ };
+
+ protected KeystoreResponse(int error_code, String error_msg) {
+ this.error_code_ = error_code;
+ this.error_msg_ = error_msg;
+ }
+
+ /**
+ * @return the error_code_
+ */
+ public final int getErrorCode() {
+ return error_code_;
+ }
+
+ /**
+ * @return the error_msg_
+ */
+ public final String getErrorMessage() {
+ return error_msg_;
+ }
+
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeInt(error_code_);
+ out.writeString(error_msg_);
+ }
+}
diff --git a/native/graphics/jni/Android.bp b/native/graphics/jni/Android.bp
index 9426148..942eafd 100644
--- a/native/graphics/jni/Android.bp
+++ b/native/graphics/jni/Android.bp
@@ -37,6 +37,7 @@
ldflags: ["-Wl,--hash-style=both"],
},
},
+ version_script: "libjnigraphics.map.txt",
}
// The headers module is in frameworks/native/Android.bp.
diff --git a/packages/CaptivePortalLogin/AndroidManifest.xml b/packages/CaptivePortalLogin/AndroidManifest.xml
index 72e37ed..c84f3ec 100644
--- a/packages/CaptivePortalLogin/AndroidManifest.xml
+++ b/packages/CaptivePortalLogin/AndroidManifest.xml
@@ -26,7 +26,8 @@
<uses-permission android:name="android.permission.NETWORK_BYPASS_PRIVATE_DNS" />
<application android:label="@string/app_name"
- android:usesCleartextTraffic="true">
+ android:usesCleartextTraffic="true"
+ android:supportsRtl="true" >
<activity
android:name="com.android.captiveportallogin.CaptivePortalLoginActivity"
android:label="@string/action_bar_label"
diff --git a/packages/CaptivePortalLogin/res/layout/ssl_error_msg.xml b/packages/CaptivePortalLogin/res/layout/ssl_error_msg.xml
new file mode 100644
index 0000000..d460041
--- /dev/null
+++ b/packages/CaptivePortalLogin/res/layout/ssl_error_msg.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<TextView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/ssl_error_msg"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:layout_marginStart="20dip"
+ android:layout_marginEnd="20dip"
+ android:gravity="center_vertical"
+ android:layout_marginBottom="4dip"
+ android:layout_marginTop="4dip" />
+
diff --git a/packages/CaptivePortalLogin/res/layout/ssl_warning.xml b/packages/CaptivePortalLogin/res/layout/ssl_warning.xml
new file mode 100644
index 0000000..ffd57a4
--- /dev/null
+++ b/packages/CaptivePortalLogin/res/layout/ssl_warning.xml
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical" >
+
+ <!-- ssl error type -->
+ <TextView
+ android:id="@+id/ssl_error_type"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="start"
+ android:text="SSL_UNKNOWN"
+ android:layout_marginStart="24dip"
+ android:layout_marginEnd="24dip"
+ android:layout_marginBottom="0dip"
+ android:layout_marginTop="24dip" />
+
+ <!-- Page info: -->
+ <TextView
+ android:id="@+id/page_info"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/page_info"
+ android:textStyle="bold"
+ android:layout_marginStart="24dip"
+ android:layout_marginEnd="24dip" />
+
+ <!-- Title: -->
+ <TextView
+ android:id="@+id/title"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:textStyle="bold"
+ android:layout_marginStart="24dip"
+ android:layout_marginEnd="24dip" />
+
+ <!-- Address: -->
+ <TextView
+ android:id="@+id/address_header"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/page_info_address"
+ android:layout_marginStart="24dip"
+ android:layout_marginEnd="24dip" />
+
+ <TextView
+ android:id="@+id/address"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="24dip"
+ android:layout_marginEnd="24dip" />
+
+ <ScrollView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingStart="4dip"
+ android:paddingEnd="4dip" >
+
+ <!-- certificate view: -->
+ <LinearLayout
+ android:id="@+id/certificate_layout"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="16dip" >
+ </LinearLayout>
+
+ </ScrollView>
+
+</LinearLayout>
diff --git a/packages/CaptivePortalLogin/res/values-af/strings.xml b/packages/CaptivePortalLogin/res/values-af/strings.xml
index fa6f3fa..cf4dc82 100644
--- a/packages/CaptivePortalLogin/res/values-af/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-af/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"Die netwerk waarby jy probeer aansluit, het sekuriteitkwessies."</string>
<string name="ssl_error_example" msgid="647898534624078900">"Byvoorbeeld, die aanmeldbladsy behoort dalk nie aan die organisasie wat gewys word nie."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Gaan in elk geval deur blaaier voort"</string>
+ <string name="ok" msgid="1509280796718850364">"OK"</string>
+ <string name="page_info" msgid="4048529256302257195">"Bladsy-inligting"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Adres:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Sekuriteitswaarskuwing"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Bekyk sertifikaat"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"Hierdie sertifikaat is nie van \'n betroubare owerheid nie."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"Die naam van die werf kom nie ooreen met die naam op die sertifikaat nie."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"Hierdie sertifikaat het verval."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Hierdie sertifikaat is nog nie geldig nie."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Hierdie sertifikaat het \'n ongeldige datum."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"Hierdie sertifikaat is ongeldig."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Onbekende sertifikaatfout."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-am/strings.xml b/packages/CaptivePortalLogin/res/values-am/strings.xml
index 36d5e19..cdcb5a5 100644
--- a/packages/CaptivePortalLogin/res/values-am/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-am/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"ለመቀላቀል እየሞከሩ ያሉት አውታረ መረብ የደህንነት ችግሮች አሉበት።"</string>
<string name="ssl_error_example" msgid="647898534624078900">"ለምሳሌ፣ የመግቢያ ገጹ የሚታየው ድርጅት ላይሆን ይችላል።"</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"ለማንኛውም በአሳሽ በኩል ይቀጥሉ"</string>
+ <string name="ok" msgid="1509280796718850364">"እሺ"</string>
+ <string name="page_info" msgid="4048529256302257195">"የገፅ መረጃ"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"አድራሻ:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"የደህንነት ቅንብሮች"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"ምስክሮች ይመልከቱ"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"ይህ ምስክር ከታማኝ ቦታ አይደለም።"</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"የጣቢያው ስም ከምስክር ወረቀቱ ስም ጋር አይዛመድም።"</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"ይህ ምስክር ጊዜው አልፏል"</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"ይህ ምስክር ገና ትክክል አይደለም።"</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"ይህ ምስክር ትክክለኛ ቀን አለው።"</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"ይህ ምስክር ትክክል ያልሆነ ነው።"</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"ያልታወቀ የምስክር ስህተት።"</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-ar/strings.xml b/packages/CaptivePortalLogin/res/values-ar/strings.xml
index 8eb259b..7773eeb 100644
--- a/packages/CaptivePortalLogin/res/values-ar/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-ar/strings.xml
@@ -11,4 +11,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"الشبكة التي تحاول الانضمام إليها بها مشاكل أمنية."</string>
<string name="ssl_error_example" msgid="647898534624078900">"على سبيل المثال، قد لا تنتمي صفحة تسجيل الدخول إلى المنظمة المعروضة."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"المتابعة على أي حال عبر المتصفح"</string>
+ <string name="ok" msgid="1509280796718850364">"موافق"</string>
+ <string name="page_info" msgid="4048529256302257195">"معلومات الصفحة"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"العنوان:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"تحذير أمان"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"عرض الشهادة"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"هذه الشهادة ليست من جهة موثوق بها."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"لا يتطابق اسم الموقع مع الاسم على الشهادة."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"انتهت صلاحية هذه الشهادة."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"هذه الشهادة ليست صالحة بعد."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"تشتمل هذه الشهادة على تاريخ غير صالح."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"هذه الشهادة غير صالحة."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"حدث خطأ غير معروف بالشهادة."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-as/strings.xml b/packages/CaptivePortalLogin/res/values-as/strings.xml
index 2281ce7..94c3147 100644
--- a/packages/CaptivePortalLogin/res/values-as/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-as/strings.xml
@@ -4,14 +4,9 @@
<string name="app_name" msgid="5934709770924185752">"CaptivePortalLogin"</string>
<string name="action_use_network" msgid="6076184727448466030">"এই নেটৱৰ্কটো এইদৰে ব্যৱহাৰ কৰক"</string>
<string name="action_do_not_use_network" msgid="4577366536956516683">"এই নেটৱৰ্কটো ব্যৱহাৰ নকৰিব"</string>
- <!-- no translation found for action_bar_label (917235635415966620) -->
- <skip />
- <!-- no translation found for action_bar_title (5645564790486983117) -->
- <skip />
- <!-- no translation found for ssl_error_warning (6653188881418638872) -->
- <skip />
- <!-- no translation found for ssl_error_example (647898534624078900) -->
- <skip />
- <!-- no translation found for ssl_error_continue (6492718244923937110) -->
- <skip />
+ <string name="action_bar_label" msgid="917235635415966620">"নেটৱৰ্কত ছাইন ইন কৰক"</string>
+ <string name="action_bar_title" msgid="5645564790486983117">"%1$st ছাইন ইন কৰক"</string>
+ <string name="ssl_error_warning" msgid="6653188881418638872">"আপুনি সংযোগ কৰিবলৈ চেষ্টা কৰি থকা নেটৱৰ্কটোত সুৰক্ষাজনিত সমস্যা আছে।"</string>
+ <string name="ssl_error_example" msgid="647898534624078900">"উদাহৰণস্বৰূপে, আপোনাক দেখুওৱা লগ ইনৰ পৃষ্ঠাটো প্ৰতিষ্ঠানটোৰ নিজা নহ\'বও পাৰে।"</string>
+ <string name="ssl_error_continue" msgid="6492718244923937110">"তথাপি ব্ৰাউজাৰৰ জৰিয়তে অব্যাহত ৰাখক"</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-bg/strings.xml b/packages/CaptivePortalLogin/res/values-bg/strings.xml
index 8ce9deb..4dd8aa0 100644
--- a/packages/CaptivePortalLogin/res/values-bg/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-bg/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"Мрежата, към която опитвате да се присъедините, има проблеми със сигурността."</string>
<string name="ssl_error_example" msgid="647898534624078900">"Например страницата за вход може да не принадлежи на показаната организация."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Продължаване през браузър въпреки това"</string>
+ <string name="ok" msgid="1509280796718850364">"OK"</string>
+ <string name="page_info" msgid="4048529256302257195">"Данни за страницата"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Адрес:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Предупреждение относно защитата"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Преглед на сертификата"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"Сертификатът не е от надежден орган."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"Името на сайта не съответства на името в сертификата."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"Сертификатът е изтекъл."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Сертификатът още не е валиден."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Този сертификат е с невалидна дата."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"Този сертификат е невалиден."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Неизвестна грешка в сертификата."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-bn/strings.xml b/packages/CaptivePortalLogin/res/values-bn/strings.xml
index b75d76e..fb703cf 100644
--- a/packages/CaptivePortalLogin/res/values-bn/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-bn/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"আপনি যে নেটওয়ার্কে যোগ দেওয়ার চেষ্টা করছেন তাতে নিরাপত্তার সমস্যা আছে।"</string>
<string name="ssl_error_example" msgid="647898534624078900">"উদাহরণস্বরূপ, লগ-ইন পৃষ্ঠাটি প্রদর্শিত প্রতিষ্ঠানের অন্তর্গত নাও হতে পারে৷"</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"যাই হোক না কেন ব্রাউজারের মাধ্যমে অবিরত রাখুন"</string>
+ <string name="ok" msgid="1509280796718850364">"OK"</string>
+ <string name="page_info" msgid="4048529256302257195">"Sideinfo"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Adresse:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Sikkerhetsadvarsel"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Vis sertifikat"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"Sertifikatet er ikke fra en pålitelig myndighet."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"Navnet på nettstedet samsvarer ikke med navnet på sertifikatet."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"Sertifikatet er utløpt."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Sertifikatet er ikke gyldig ennå."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Dette sertifikatet har en ugyldig dato."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"Dette sertifikatet er ugyldig."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Ukjent sertifikatfeil."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-ca/strings.xml b/packages/CaptivePortalLogin/res/values-ca/strings.xml
index fe189ed..a2c9ed8 100644
--- a/packages/CaptivePortalLogin/res/values-ca/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-ca/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"La xarxa a què et vols connectar té problemes de seguretat."</string>
<string name="ssl_error_example" msgid="647898534624078900">"Per exemple, la pàgina d\'inici de sessió podria no pertànyer a l\'organització que es mostra."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Continua igualment mitjançant el navegador"</string>
+ <string name="ok" msgid="1509280796718850364">"D\'acord"</string>
+ <string name="page_info" msgid="4048529256302257195">"Informació de la pàgina"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Adreça:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Advertiment de seguretat"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Visualitza el certificat"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"Aquest certificat no és d\'una autoritat de confiança."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"El nom del lloc no coincideix amb el del certificat."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"Aquest certificat ha caducat."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Aquest certificat encara no és vàlid."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Aquest certificat té una data no vàlida."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"Aquest certificat no és vàlid."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Error de certificat desconegut."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-cs/strings.xml b/packages/CaptivePortalLogin/res/values-cs/strings.xml
index 09dcc5f..be649a5 100644
--- a/packages/CaptivePortalLogin/res/values-cs/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-cs/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"Síť, ke které se pokoušíte připojit, má bezpečnostní problémy."</string>
<string name="ssl_error_example" msgid="647898534624078900">"Například přihlašovací stránka nemusí patřit do zobrazované organizace."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Přesto pokračovat prostřednictvím prohlížeče"</string>
+ <string name="ok" msgid="1509280796718850364">"OK"</string>
+ <string name="page_info" msgid="4048529256302257195">"Informace o stránce"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Adresa:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Upozornění zabezpečení"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Zobrazit certifikát"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"Tento certifikát nepochází od důvěryhodné autority."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"Název webu se neshoduje s názvem uvedeným v certifikátu."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"Platnost certifikátu vypršela."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Tento certifikát ještě není platný."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Datum tohoto certifikátu není platné."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"Tento certifikát je neplatný."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Neznámá chyba certifikátu."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-da/strings.xml b/packages/CaptivePortalLogin/res/values-da/strings.xml
index dc0dd17..8183105 100644
--- a/packages/CaptivePortalLogin/res/values-da/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-da/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"Der er sikkerhedsproblemer på det netværk, du forsøger at logge ind på."</string>
<string name="ssl_error_example" msgid="647898534624078900">"Det er f.eks. ikke sikkert, at loginsiden tilhører den anførte organisation."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Fortsæt alligevel via browseren"</string>
+ <string name="ok" msgid="1509280796718850364">"OK"</string>
+ <string name="page_info" msgid="4048529256302257195">"Sideoplysninger"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Adresse:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Sikkerhedsadvarsel"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Vis certifikat"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"Dette certifikat stammer ikke fra en troværdig autoritet."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"Navnet på websitet stemmer ikke overens med navnet på certifikatet."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"Dette certifikat er udløbet."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Dette certifikat er endnu ikke gyldigt."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Dette certifikat har en ugyldig dato."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"Dette certifikat er ugyldigt."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Ukendt fejl i certifikatet."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-de/strings.xml b/packages/CaptivePortalLogin/res/values-de/strings.xml
index d8f7be9..a9b7415 100644
--- a/packages/CaptivePortalLogin/res/values-de/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-de/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"Im Netzwerk, zu dem du eine Verbindung herstellen möchtest, liegen Sicherheitsprobleme vor."</string>
<string name="ssl_error_example" msgid="647898534624078900">"Beispiel: Die Log-in-Seite gehört eventuell nicht zur angezeigten Organisation."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Trotzdem in einem Browser fortfahren"</string>
+ <string name="ok" msgid="1509280796718850364">"OK"</string>
+ <string name="page_info" msgid="4048529256302257195">"Seiteninfo"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Adresse:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Sicherheitswarnung"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Zertifikat ansehen"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"Dieses Zertifikat wurde nicht von einer vertrauenswürdigen Stelle ausgegeben."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"Name der Website stimmt nicht mit dem Namen auf dem Zertifikat überein."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"Dieses Zertifikat ist abgelaufen."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Dieses Zertifikat ist noch nicht gültig."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Dieses Zertifikat weist ein ungültiges Datum auf."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"Dieses Zertifikat ist ungültig."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Unbekannter Zertifikatfehler"</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-el/strings.xml b/packages/CaptivePortalLogin/res/values-el/strings.xml
index cb61710..16bf6e2 100644
--- a/packages/CaptivePortalLogin/res/values-el/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-el/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"Παρουσιάζονται προβλήματα ασφάλειας στο δίκτυο στο οποίο προσπαθείτε να συνδεθείτε."</string>
<string name="ssl_error_example" msgid="647898534624078900">"Για παράδειγμα, η σελίδα σύνδεσης ενδέχεται να μην ανήκει στον οργανισμό που εμφανίζεται."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Συνέχεια ούτως ή άλλως μέσω του προγράμματος περιήγησης"</string>
+ <string name="ok" msgid="1509280796718850364">"OK"</string>
+ <string name="page_info" msgid="4048529256302257195">"Πληροφορίες σελίδας"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Διεύθυνση:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Προειδοποίηση ασφαλείας"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Προβολή πιστοποιητικού"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"Αυτό το πιστοποιητικό δεν προέρχεται από αξιόπιστη αρχή."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"Το όνομα του ιστότοπου δεν αντιστοιχεί με το όνομα στο πιστοποιητικό."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"Αυτό το πιστοποιητικό έχει λήξει."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Αυτό το πιστοποιητικό δεν είναι έγκυρο ακόμα."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Αυτό το πιστοποιητικό δεν έχει έγκυρη ημερομηνία."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"Αυτό το πιστοποιητικό δεν είναι έγκυρο."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Άγνωστο σφάλμα πιστοποιητικού."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-en-rGB/strings.xml b/packages/CaptivePortalLogin/res/values-en-rGB/strings.xml
index 2e8d1f0..f940299 100644
--- a/packages/CaptivePortalLogin/res/values-en-rGB/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-en-rGB/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"The network that you’re trying to join has security issues."</string>
<string name="ssl_error_example" msgid="647898534624078900">"For example, the login page might not belong to the organisation shown."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Continue anyway via browser"</string>
+ <string name="ok" msgid="1509280796718850364">"OK"</string>
+ <string name="page_info" msgid="4048529256302257195">"Page info"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Address:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Security warning"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"View certificate"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"This certificate isn\'t from a trusted authority."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"The name of the site doesn\'t match the name on the certificate."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"This certificate has expired."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"This certificate isn\'t valid yet."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"This certificate has an invalid date."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"This certificate is invalid."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Unknown certificate error."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-en-rIN/strings.xml b/packages/CaptivePortalLogin/res/values-en-rIN/strings.xml
index 2e8d1f0..f940299 100644
--- a/packages/CaptivePortalLogin/res/values-en-rIN/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-en-rIN/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"The network that you’re trying to join has security issues."</string>
<string name="ssl_error_example" msgid="647898534624078900">"For example, the login page might not belong to the organisation shown."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Continue anyway via browser"</string>
+ <string name="ok" msgid="1509280796718850364">"OK"</string>
+ <string name="page_info" msgid="4048529256302257195">"Page info"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Address:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Security warning"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"View certificate"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"This certificate isn\'t from a trusted authority."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"The name of the site doesn\'t match the name on the certificate."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"This certificate has expired."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"This certificate isn\'t valid yet."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"This certificate has an invalid date."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"This certificate is invalid."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Unknown certificate error."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-es-rUS/strings.xml b/packages/CaptivePortalLogin/res/values-es-rUS/strings.xml
index 5d7ba91..c011664 100644
--- a/packages/CaptivePortalLogin/res/values-es-rUS/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-es-rUS/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"La red a la que intentas conectarte tiene problemas de seguridad."</string>
<string name="ssl_error_example" msgid="647898534624078900">"Por ejemplo, es posible que la página de acceso no pertenezca a la organización que aparece."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Continuar de todos modos desde el navegador"</string>
+ <string name="ok" msgid="1509280796718850364">"Aceptar"</string>
+ <string name="page_info" msgid="4048529256302257195">"Información de la página"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Dirección:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Advertencia de seguridad"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Ver certificado"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"Este certificado no proviene de una autoridad confiable."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"El nombre del sitio no coincide con el nombre del certificado."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"Este certificado ha expirado."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Este certificado aún no es válido."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"La fecha de este certificado no es válida."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"Este certificado no es válido."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Error de certificado desconocido"</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-es/strings.xml b/packages/CaptivePortalLogin/res/values-es/strings.xml
index da2eae9..65244e7 100644
--- a/packages/CaptivePortalLogin/res/values-es/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-es/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"La red a la que intentas unirte tiene problemas de seguridad."</string>
<string name="ssl_error_example" msgid="647898534624078900">"Por ejemplo, es posible que la página de inicio de sesión no pertenezca a la organización mostrada."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Continuar de todos modos a través del navegador"</string>
+ <string name="ok" msgid="1509280796718850364">"Aceptar"</string>
+ <string name="page_info" msgid="4048529256302257195">"Información de la página"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Dirección:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Advertencia de seguridad"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Ver certificado"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"Este certificado no procede de una entidad de certificación de confianza."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"El nombre del sitio no coincide con el del certificado."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"Este certificado ha caducado."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Este certificado aún no es válido."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"La fecha de este certificado no es válida."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"Este certificado no es válido."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Error de certificado desconocido"</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-et/strings.xml b/packages/CaptivePortalLogin/res/values-et/strings.xml
index 41fcb9a..e4c4c98 100644
--- a/packages/CaptivePortalLogin/res/values-et/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-et/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"Võrgul, millega üritate ühenduse luua, on turvaprobleeme."</string>
<string name="ssl_error_example" msgid="647898534624078900">"Näiteks ei pruugi sisselogimisleht kuuluda kuvatavale organisatsioonile."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Jätka siiski brauseris"</string>
+ <string name="ok" msgid="1509280796718850364">"OK"</string>
+ <string name="page_info" msgid="4048529256302257195">"Lehe teave"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Aadress:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Turvahoiatus"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Kuva sertifikaat"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"See sertifikaat ei pärine usaldusväärselt asutuselt."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"Saidi nimi ei vasta sertifikaadil olevale nimele."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"See sertifikaat on aegunud."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"See sertifikaat pole veel kehtiv."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Sellel sertifikaadil on kehtetu kuupäev."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"See sertifikaat on kehtetu."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Tundmatu sertifikaadiviga."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-fa/strings.xml b/packages/CaptivePortalLogin/res/values-fa/strings.xml
index 2e4cc51..27b9b7f 100644
--- a/packages/CaptivePortalLogin/res/values-fa/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-fa/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"شبکهای که میخواهید به آن بپیوندید مشکلات امنیتی دارد."</string>
<string name="ssl_error_example" msgid="647898534624078900">"به عنوان مثال، صفحه ورود به سیستم ممکن است متعلق به سازمان نشان داده شده نباشد."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"در هر صورت از طریق مرورگر ادامه یابد"</string>
+ <string name="ok" msgid="1509280796718850364">"تأیید"</string>
+ <string name="page_info" msgid="4048529256302257195">"اطلاعات صفحه"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"آدرس:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"اخطار امنیتی"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"مشاهده گواهی"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"این گواهی از یک منبع مورد اطمینان صادر نشده است."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"نام سایت با نام موجود در گواهی مطابقت ندارد."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"این گواهی منقضی شده است."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"این گواهی هنوز معتبر نیست."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"تاریخ این گواهی نامعتبر است."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"این گواهی نامعتبر است."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"خطای ناشناخته در گواهی."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-fi/strings.xml b/packages/CaptivePortalLogin/res/values-fi/strings.xml
index 1976f7d..8086fbf 100644
--- a/packages/CaptivePortalLogin/res/values-fi/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-fi/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"Verkossa, johon yrität muodostaa yhteyttä, on turvallisuusongelmia."</string>
<string name="ssl_error_example" msgid="647898534624078900">"Kirjautumissivu ei välttämättä kuulu näytetylle organisaatiolle."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Jatka silti selaimen kautta."</string>
+ <string name="ok" msgid="1509280796718850364">"OK"</string>
+ <string name="page_info" msgid="4048529256302257195">"Sivun tiedot"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Osoite:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Suojausvaroitus"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Näytä varmenne"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"Varmenteen myöntäjä ei ole luotettava taho."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"Sivuston nimi ei vastaa varmenteessa olevaa nimeä."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"Varmenne ei ole enää voimassa."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Varmenne ei ole vielä voimassa."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Varmenteen päiväys ei kelpaa."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"Varmenne on virheellinen."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Tuntematon varmennevirhe."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-fr/strings.xml b/packages/CaptivePortalLogin/res/values-fr/strings.xml
index 8f98bb5..39fc569 100644
--- a/packages/CaptivePortalLogin/res/values-fr/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-fr/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"Le réseau que vous essayez de rejoindre présente des problèmes de sécurité."</string>
<string name="ssl_error_example" msgid="647898534624078900">"Par exemple, la page de connexion peut ne pas appartenir à l\'organisation représentée."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Continuer quand même dans le navigateur"</string>
+ <string name="ok" msgid="1509280796718850364">"OK"</string>
+ <string name="page_info" msgid="4048529256302257195">"Infos sur la page"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Adresse :"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Avertissement de sécurité"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Afficher le certificat"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"Ce certificat provient d\'une autorité non approuvée."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"Le nom du site ne correspond pas au nom indiqué dans le certificat."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"Le certificat a expiré."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Ce certificat n\'est pas encore valide."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"La date de ce certificat n\'est pas valide."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"Ce certificat n\'est pas valide."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Erreur : Certificat inconnu."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-hi/strings.xml b/packages/CaptivePortalLogin/res/values-hi/strings.xml
index 1bacc46..d924fff 100644
--- a/packages/CaptivePortalLogin/res/values-hi/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-hi/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"आप जिस नेटवर्क में शामिल होने का प्रयास कर रहे हैं उसमें सुरक्षा समस्याएं हैं."</string>
<string name="ssl_error_example" msgid="647898534624078900">"उदाहरण के लिए, हो सकता है कि लॉगिन पृष्ठ दिखाए गए संगठन से संबद्ध ना हो."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"ब्राउज़र के द्वारा फिर जारी रखें"</string>
+ <string name="ok" msgid="1509280796718850364">"ठीक"</string>
+ <string name="page_info" msgid="4048529256302257195">"पृष्ठ जानकारी"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"पता:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"सुरक्षा चेतावनी"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"प्रमाणपत्र देखें"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"यह प्रमाणपत्र किसी विश्वस्त प्राधिकारी का नहीं है."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"साइट का नाम, प्रमाणपत्र के नाम से मिलान नहीं करता."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"इस प्रमाणपत्र की समय सीमा समाप्त हो गई है."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"यह प्रमाणपत्र अभी तक मान्य नहीं है."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"इस प्रमाणपत्र में एक अमान्य दिनांक है."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"यह प्रमाणपत्र अमान्य है."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"अज्ञात प्रमाणपत्र त्रुटि."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-hr/strings.xml b/packages/CaptivePortalLogin/res/values-hr/strings.xml
index e44cd3b..11b1dd3 100644
--- a/packages/CaptivePortalLogin/res/values-hr/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-hr/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"Mreža kojoj se pokušavate pridružiti ima sigurnosne poteškoće."</string>
<string name="ssl_error_example" msgid="647898534624078900">"Na primjer, stranica za prijavu možda ne pripada prikazanoj organizaciji."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Ipak nastavi putem preglednika"</string>
+ <string name="ok" msgid="1509280796718850364">"U redu"</string>
+ <string name="page_info" msgid="4048529256302257195">"Informacije o stranici"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Adresa:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Upozorenje o sigurnosti"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Prikaži certifikat"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"Ovaj certifikat ne potječe iz pouzdanog izvora."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"Naziv web-lokacije ne podudara se s nazivom na certifikatu."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"Ovaj je certifikat istekao."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Ovaj certifikat još nije važeći."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Ovaj certifikat ima nevažeći datum."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"Ovaj certifikat nije valjan."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Nepoznata pogreška certifikata."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-hu/strings.xml b/packages/CaptivePortalLogin/res/values-hu/strings.xml
index f15fb49..145e2ab 100644
--- a/packages/CaptivePortalLogin/res/values-hu/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-hu/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"Biztonsági problémák vannak azzal a hálózattal, amelyhez csatlakozni szeretne."</string>
<string name="ssl_error_example" msgid="647898534624078900">"Például lehet, hogy a bejelentkezési oldal nem a megjelenített szervezethez tartozik."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Folytatás ennek ellenére böngészőn keresztül"</string>
+ <string name="ok" msgid="1509280796718850364">"OK"</string>
+ <string name="page_info" msgid="4048529256302257195">"Oldaladatok"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Cím:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Biztonsági figyelmeztetés"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Tanúsítvány megtekintése"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"Ez a tanúsítvány nem hiteles tanúsítványkibocsátótól származik."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"A webhely neve nem egyezik a tanúsítványon lévő névvel."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"A tanúsítvány lejárt."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"A tanúsítvány még nem érvényes."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"A tanúsítvány dátuma érvénytelen."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"Ez a tanúsítvány érvénytelen."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Ismeretlen tanúsítványhiba."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-in/strings.xml b/packages/CaptivePortalLogin/res/values-in/strings.xml
index 10e3de6..4a335dd 100644
--- a/packages/CaptivePortalLogin/res/values-in/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-in/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"Jaringan yang ingin Anda masuki mengalami masalah keamanan."</string>
<string name="ssl_error_example" msgid="647898534624078900">"Misalnya, halaman masuk mungkin bukan milik organisasi yang ditampilkan."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Tetap lanjutkan melalui browser"</string>
+ <string name="ok" msgid="1509280796718850364">"Oke"</string>
+ <string name="page_info" msgid="4048529256302257195">"Info laman"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Alamat:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Peringatan sertifikat"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Lihat sertifikat"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"Sertifikat ini tidak berasal dari otoritas tepercaya."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"Nama situs tidak cocok dengan nama pada sertifikat."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"Sertifikat ini telah kedaluwarsa."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Sertifikat ini belum valid."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Tanggal sertifikat ini tidak valid."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"Sertifikat ini tidak valid."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Kesalahan sertifikat tak dikenal."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-it/strings.xml b/packages/CaptivePortalLogin/res/values-it/strings.xml
index a01a553..2cc4038 100644
--- a/packages/CaptivePortalLogin/res/values-it/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-it/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"La rete a cui stai tentando di accedere presenta problemi di sicurezza."</string>
<string name="ssl_error_example" msgid="647898534624078900">"Ad esempio, la pagina di accesso potrebbe non appartenere all\'organizzazione indicata."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Continua comunque dal browser"</string>
+ <string name="ok" msgid="1509280796718850364">"OK"</string>
+ <string name="page_info" msgid="4048529256302257195">"Info pagina"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Indirizzo:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Avviso di sicurezza"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Visualizza certificato"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"Questo certificato non proviene da un\'autorità attendibile."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"Il nome del sito non corrisponde al nome nel certificato."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"Il certificato è scaduto."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Questo certificato non è ancora valido."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Questo certificato presenta una data non valida."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"Questo certificato non è valido."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Errore certificato sconosciuto."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-iw/strings.xml b/packages/CaptivePortalLogin/res/values-iw/strings.xml
index 8e7915d..527e692 100644
--- a/packages/CaptivePortalLogin/res/values-iw/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-iw/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"יש בעיות אבטחה ברשת שאליה אתה מנסה להתחבר."</string>
<string name="ssl_error_example" msgid="647898534624078900">"לדוגמה, ייתכן שדף ההתחברות אינו שייך לארגון המוצג."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"המשך בכל זאת באמצעות דפדפן"</string>
+ <string name="ok" msgid="1509280796718850364">"אישור"</string>
+ <string name="page_info" msgid="4048529256302257195">"פרטי דף"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"כתובת:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"אזהרת אבטחה"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"הצג אישור"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"אישור זה אינו מגיע מרשות אמינה."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"שם האתר לא תואם לשם באישור."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"פג תוקפו של אישור זה."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"אישור זה אינו חוקי עדיין."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"לאישור זה יש תאריך בלתי חוקי."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"אישור זה אינו חוקי."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"שגיאת אישור לא ידועה."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-ja/strings.xml b/packages/CaptivePortalLogin/res/values-ja/strings.xml
index e275b95..bcc8686 100644
--- a/packages/CaptivePortalLogin/res/values-ja/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-ja/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"接続しようとしているネットワークにセキュリティの問題があります。"</string>
<string name="ssl_error_example" msgid="647898534624078900">"たとえば、ログインページが表示されている組織に属していない可能性があります。"</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"ブラウザから続行"</string>
+ <string name="ok" msgid="1509280796718850364">"OK"</string>
+ <string name="page_info" msgid="4048529256302257195">"ページ情報"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"アドレス:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"セキュリティ警告"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"証明書を表示"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"この証明書は信頼できる認証機関のものではありません。"</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"サイト名と証明書上の名前が一致しません。"</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"この証明書は有効期限切れです。"</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"この証明書はまだ有効ではありません。"</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"この証明書の日付は無効です。"</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"この証明書は無効です。"</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"不明な証明書エラーです。"</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-ko/strings.xml b/packages/CaptivePortalLogin/res/values-ko/strings.xml
index 75f2b48..7a7f7e0 100644
--- a/packages/CaptivePortalLogin/res/values-ko/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-ko/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"가입하려는 네트워크에 보안 문제가 있습니다."</string>
<string name="ssl_error_example" msgid="647898534624078900">"예를 들어 로그인 페이지가 표시된 조직에 속하지 않을 수 있습니다."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"브라우저를 통해 계속하기"</string>
+ <string name="ok" msgid="1509280796718850364">"확인"</string>
+ <string name="page_info" msgid="4048529256302257195">"페이지 정보"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"주소:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"보안 경고"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"인증서 보기"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"신뢰할 수 있는 인증 기관에서 발급한 인증서가 아닙니다."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"사이트 이름이 인증서에 있는 것과 일치하지 않습니다."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"인증서가 만료되었습니다."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"인증서가 아직 유효하지 않습니다."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"인증서 날짜가 유효하지 않습니다."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"인증서가 잘못되었습니다."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"알 수 없는 인증서 오류입니다."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-lt/strings.xml b/packages/CaptivePortalLogin/res/values-lt/strings.xml
index 17da83f..158f7ce 100644
--- a/packages/CaptivePortalLogin/res/values-lt/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-lt/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"Kilo tinklo, prie kurio bandote prisijungti, problemų."</string>
<string name="ssl_error_example" msgid="647898534624078900">"Pavyzdžiui, prisijungimo puslapis gali nepriklausyti rodomai organizacijai."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Vis tiek tęsti naudojant naršyklę"</string>
+ <string name="ok" msgid="1509280796718850364">"Gerai"</string>
+ <string name="page_info" msgid="4048529256302257195">"Puslapio informacija"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Adresas:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Saugos įspėjimas"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Žiūrėti sertifikatą"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"Šį sertifikatą išdavė nepatikima įstaiga."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"Svetainės pavadinimas neatitinka sertifikate nurodyto pavadinimo."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"Šio sertifikato galiojimo laikas baigėsi."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Šis sertifikatas dar negalioja."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Šio sertifikato data netinkama."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"Šis sertifikatas netinkamas."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Nežinoma sertifikato klaida."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-lv/strings.xml b/packages/CaptivePortalLogin/res/values-lv/strings.xml
index 95b8558..a42cb22 100644
--- a/packages/CaptivePortalLogin/res/values-lv/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-lv/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"Tīklam, kuram mēģināt pievienoties, ir drošības problēmas."</string>
<string name="ssl_error_example" msgid="647898534624078900">"Piemēram, pieteikšanās lapa, iespējams, nepieder norādītajai organizācijai."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Tik un tā turpināt, izmantojot pārlūkprogrammu"</string>
+ <string name="ok" msgid="1509280796718850364">"Labi"</string>
+ <string name="page_info" msgid="4048529256302257195">"Lapas informācija"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Adrese:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Drošības brīdinājums"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Skatīt sertifikātu"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"Šo sertifikātu nav izsniegusi uzticama iestāde."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"Vietnes nosaukums neatbilst nosaukumam sertifikātā."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"Šī sertifikāta derīguma termiņš ir beidzies."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Šis sertifikāts vēl nav derīgs."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Šī sertifikāta datums nav derīgs."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"Šis sertifikāts nav derīgs."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Nezināma sertifikāta kļūda."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-ms/strings.xml b/packages/CaptivePortalLogin/res/values-ms/strings.xml
index 933721a..aaa51c8 100644
--- a/packages/CaptivePortalLogin/res/values-ms/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-ms/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"Rangkaian yang anda cuba sertai mempunyai isu keselamatan."</string>
<string name="ssl_error_example" msgid="647898534624078900">"Contohnya, halaman log masuk mungkin bukan milik organisasi yang ditunjukkan."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Teruskan juga melalui penyemak imbas"</string>
+ <string name="ok" msgid="1509280796718850364">"OK"</string>
+ <string name="page_info" msgid="4048529256302257195">"Maklumat halaman"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Alamat:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Amaran keselamatan"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Lihat sijil"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"Sijil ini bukan daripada pihak berkuasa yang dipercayai."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"Nama tapak tidak sepadan dengan nama pada sijil."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"Sijil ini telah tamat tempoh."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Sijil ini belum lagi sah."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Sijil ini mempunyai tarikh yang tidak sah."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"Sijil ini tidak sah."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Ralat sijil tidak diketahui."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-nb/strings.xml b/packages/CaptivePortalLogin/res/values-nb/strings.xml
index 0dd5b6c..29c23ed 100644
--- a/packages/CaptivePortalLogin/res/values-nb/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-nb/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"Nettverket du prøver å logge på, har sikkerhetsproblemer."</string>
<string name="ssl_error_example" msgid="647898534624078900">"Det er for eksempel mulig at påloggingssiden kanskje ikke tilhører organisasjonen som vises."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Fortsett likevel via nettleseren"</string>
+ <string name="ok" msgid="1509280796718850364">"OK"</string>
+ <string name="page_info" msgid="4048529256302257195">"Sideinfo"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Adresse:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Sikkerhetsadvarsel"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Vis sertifikat"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"Sertifikatet er ikke fra en pålitelig myndighet."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"Navnet på nettstedet samsvarer ikke med navnet på sertifikatet."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"Sertifikatet er utløpt."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Sertifikatet er ikke gyldig ennå."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Dette sertifikatet har en ugyldig dato."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"Dette sertifikatet er ugyldig."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Ukjent sertifikatfeil."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-nl/strings.xml b/packages/CaptivePortalLogin/res/values-nl/strings.xml
index 1c59601..2cbca06 100644
--- a/packages/CaptivePortalLogin/res/values-nl/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-nl/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"Het netwerk waarmee u verbinding probeert te maken, heeft beveiligingsproblemen."</string>
<string name="ssl_error_example" msgid="647898534624078900">"Zo hoort de weergegeven inlogpagina misschien niet bij de weergegeven organisatie."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Toch doorgaan via browser"</string>
+ <string name="ok" msgid="1509280796718850364">"OK"</string>
+ <string name="page_info" msgid="4048529256302257195">"Pagina-informatie"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Adres:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Beveiligingsmelding"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Certificaat weergeven"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"Dit is geen certificaat van een vertrouwde autoriteit."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"De naam van deze site komt niet overeen met de naam op het certificaat."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"Dit certificaat is verlopen."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Dit certificaat is nog niet geldig."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Dit certificaat heeft een ongeldige datum."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"Dit certificaat is ongeldig."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Onbekende certificaatfout."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-or/strings.xml b/packages/CaptivePortalLogin/res/values-or/strings.xml
index b7c8321..80074c3 100644
--- a/packages/CaptivePortalLogin/res/values-or/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-or/strings.xml
@@ -5,8 +5,7 @@
<string name="action_use_network" msgid="6076184727448466030">"ଏହି ନେଟ୍ୱର୍କ ଯେପରି ଅଛି, ସେହିପରି ବ୍ୟବହାର କରନ୍ତୁ"</string>
<string name="action_do_not_use_network" msgid="4577366536956516683">"ଏହି ନେଟ୍ୱର୍କକୁ ବ୍ୟବହାର କରନ୍ତୁ ନାହିଁ"</string>
<string name="action_bar_label" msgid="917235635415966620">"ନେଟ୍ୱର୍କରେ ସାଇନ୍ ଇନ୍ କରନ୍ତୁ"</string>
- <!-- no translation found for action_bar_title (5645564790486983117) -->
- <skip />
+ <string name="action_bar_title" msgid="5645564790486983117">"%1$sରେ ସାଇନ୍-ଇନ୍ କରନ୍ତୁ"</string>
<string name="ssl_error_warning" msgid="6653188881418638872">"ଆପଣ ଯୋଗ ଦେବାକୁ ଚେଷ୍ଟା କରୁଥିବା ନେଟ୍ୱର୍କର ସୁରକ୍ଷା ସମସ୍ୟା ଅଛି।"</string>
<string name="ssl_error_example" msgid="647898534624078900">"ଉଦାହରଣସ୍ୱରୂପ, ଲଗଇନ୍ ପୃଷ୍ଠା ଦେଖାଯାଇଥିବା ସଂସ୍ଥାର ନହୋଇଥାଇପାରେ।"</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"ବ୍ରାଉଜର୍ ଜରିଆରେ ଯେମିତିବି ହେଉ ଜାରି ରଖନ୍ତୁ"</string>
diff --git a/packages/CaptivePortalLogin/res/values-pl/strings.xml b/packages/CaptivePortalLogin/res/values-pl/strings.xml
index 17f20df..9ba066e 100644
--- a/packages/CaptivePortalLogin/res/values-pl/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-pl/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"W sieci, z którą próbujesz się połączyć, występują problemy z zabezpieczeniami."</string>
<string name="ssl_error_example" msgid="647898534624078900">"Na przykład strona logowania może nie należeć do wyświetlanej organizacji."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Kontynuuj mimo to w przeglądarce"</string>
+ <string name="ok" msgid="1509280796718850364">"OK"</string>
+ <string name="page_info" msgid="4048529256302257195">"Informacje o stronie"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Adres:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Ostrzeżenie zabezpieczeń"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Wyświetl certyfikat"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"Certyfikat nie pochodzi od zaufanego urzędu."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"Nazwa witryny nie pasuje do nazwy na certyfikacie."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"Ten certyfikat wygasł."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Certyfikat nie jest jeszcze ważny."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Certyfikat ma nieprawidłową datę."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"Certyfikat jest nieprawidłowy."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Nieznany błąd certyfikatu"</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-pt-rPT/strings.xml b/packages/CaptivePortalLogin/res/values-pt-rPT/strings.xml
index 94b9d60..5bef235 100644
--- a/packages/CaptivePortalLogin/res/values-pt-rPT/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-pt-rPT/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"A rede à qual está a tentar aceder tem problemas de segurança."</string>
<string name="ssl_error_example" msgid="647898534624078900">"Por exemplo, a página de início de sessão pode não pertencer à entidade apresentada."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Continuar mesmo assim através do navegador"</string>
+ <string name="ok" msgid="1509280796718850364">"OK"</string>
+ <string name="page_info" msgid="4048529256302257195">"Informações da página"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Endereço:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Aviso de segurança"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Ver certificado"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"Este certificado não pertence a uma autoridade fidedigna."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"O nome do Web site não corresponde ao nome constante no certificado."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"Este certificado expirou."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Este certificado ainda não é válido."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Este certificado tem uma data inválida."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"Este certificado é inválido."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Erro: certificado desconhecido."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-pt/strings.xml b/packages/CaptivePortalLogin/res/values-pt/strings.xml
index 3d1064c..ebe4148 100644
--- a/packages/CaptivePortalLogin/res/values-pt/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-pt/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"A rede à qual você está tentando se conectar tem problemas de segurança."</string>
<string name="ssl_error_example" msgid="647898534624078900">"Por exemplo, a página de login pode não pertencer à organização mostrada."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Continuar mesmo assim pelo navegador"</string>
+ <string name="ok" msgid="1509280796718850364">"OK"</string>
+ <string name="page_info" msgid="4048529256302257195">"Informações da página"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Endereço:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Aviso de segurança"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Visualizar certificado"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"Este certificado não é de uma autoridade confiável."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"O nome do site não corresponde ao nome no certificado."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"Este certificado expirou."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Este certificado ainda não é válido."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Este certificado tem uma data inválida."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"Este certificado é inválido."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Erro de certificado desconhecido."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-ro/strings.xml b/packages/CaptivePortalLogin/res/values-ro/strings.xml
index cf1b6b5..e2e4eac 100644
--- a/packages/CaptivePortalLogin/res/values-ro/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-ro/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"Rețeaua la care încercați să vă conectați are probleme de securitate."</string>
<string name="ssl_error_example" msgid="647898534624078900">"De exemplu, este posibil ca pagina de conectare să nu aparțină organizației afișate."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Continuați oricum prin browser"</string>
+ <string name="ok" msgid="1509280796718850364">"OK"</string>
+ <string name="page_info" msgid="4048529256302257195">"Informaţii pagină"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Adresă:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Avertisment de securitate"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Vizualizaţi certificatul"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"Acest certificat nu provine de la o autoritate de încredere."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"Numele acestui site nu se potriveşte cu numele de pe certificat."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"Acest certificat a expirat."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Acest certificat nu este încă valid."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Acest certificat are o dată nevalidă."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"Acest certificat este nevalid."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Eroare de certificat necunoscută."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-ru/strings.xml b/packages/CaptivePortalLogin/res/values-ru/strings.xml
index 6966bcd..c0153e6 100644
--- a/packages/CaptivePortalLogin/res/values-ru/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-ru/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"Сеть, к которой вы хотите подключиться, небезопасна."</string>
<string name="ssl_error_example" msgid="647898534624078900">"Например, страница входа в аккаунт может быть фиктивной."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Игнорировать и открыть браузер"</string>
+ <string name="ok" msgid="1509280796718850364">"ОК"</string>
+ <string name="page_info" msgid="4048529256302257195">"Информация о странице"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Адрес:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Угроза безопасности"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Просмотреть сертификат"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"Этот сертификат получен из ненадежных источников."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"Название сайта не соответствует названию в сертификате."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"Срок действия сертификата истек."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Сертификат еще не действителен."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Дата этого сертификата недействительна."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"Этот сертификат недействителен."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Неизвестная ошибка сертификата."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-sk/strings.xml b/packages/CaptivePortalLogin/res/values-sk/strings.xml
index 54763be..8ba24b1 100644
--- a/packages/CaptivePortalLogin/res/values-sk/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-sk/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"Sieť, ku ktorej sa pokúšate pripojiť, má problémy so zabezpečením"</string>
<string name="ssl_error_example" msgid="647898534624078900">"Napríklad prihlasovacia stránka nemusí patriť uvedenej organizácii."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Pokračovať pomocou prehliadača"</string>
+ <string name="ok" msgid="1509280796718850364">"OK"</string>
+ <string name="page_info" msgid="4048529256302257195">"Informácie o stránke"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Adresa:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Upozornenie zabezpečenia"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Zobraziť certifikát"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"Tento certifikát nepochádza od dôveryhodnej autority."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"Názov stránky sa nezhoduje s názvom uvedeným v certifikáte."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"Platnosť certifikátu skončila."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Tento certifikát zatiaľ nie je platný."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Tento certifikát má neplatný dátum."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"Tento certifikát je neplatný."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Neznáma chyba certifikátu."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-sl/strings.xml b/packages/CaptivePortalLogin/res/values-sl/strings.xml
index 7dd0b37..b7d9a8a 100644
--- a/packages/CaptivePortalLogin/res/values-sl/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-sl/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"Omrežje, ki se mu poskušate pridružiti, ima varnostne težave."</string>
<string name="ssl_error_example" msgid="647898534624078900">"Stran za prijavo na primer morda ne pripada prikazani organizaciji."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Vseeno nadaljuj v brskalniku"</string>
+ <string name="ok" msgid="1509280796718850364">"V redu"</string>
+ <string name="page_info" msgid="4048529256302257195">"Podatki o strani"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Naslov:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Varnostno opozorilo"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Prikaži potrdilo"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"Potrdila ni izdal zaupanja vreden overitelj."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"Ime spletnega mesta se ne ujema z imenom na potrdilu."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"Potrdilo je poteklo."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"To potrdilo še ni veljavno."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Potrdilo ima neveljaven datum."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"To potrdilo ni veljavno."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Neznana napaka potrdila."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-sr/strings.xml b/packages/CaptivePortalLogin/res/values-sr/strings.xml
index f604289..967c8ba 100644
--- a/packages/CaptivePortalLogin/res/values-sr/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-sr/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"Мрежа којој покушавате да се придружите има безбедносних проблема."</string>
<string name="ssl_error_example" msgid="647898534624078900">"На пример, страница за пријављивање можда не припада приказаној организацији."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Ипак настави преко прегледача"</string>
+ <string name="ok" msgid="1509280796718850364">"Потврди"</string>
+ <string name="page_info" msgid="4048529256302257195">"Информације о страници"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Адреса:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Безбедносно упозорење"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Прикажи сертификат"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"Овај сертификат не потиче од поузданог ауторитета."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"Назив сајта се не подудара са називом на сертификату."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"Овај сертификат је истекао."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Овај сертификат још увек није важећи."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Датум овог сертификата је неважећи."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"Овај сертификат је неважећи."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Непозната грешка сертификата."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-sv/strings.xml b/packages/CaptivePortalLogin/res/values-sv/strings.xml
index 8cf7041..75356f0 100644
--- a/packages/CaptivePortalLogin/res/values-sv/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-sv/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"Nätverket du försöker ansluta till har säkerhetsproblem."</string>
<string name="ssl_error_example" msgid="647898534624078900">"Det kan t.ex. hända att inloggningssidan inte tillhör den organisation som visas."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Fortsätt ändå via webbläsaren"</string>
+ <string name="ok" msgid="1509280796718850364">"OK"</string>
+ <string name="page_info" msgid="4048529256302257195">"Sidinformation"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Adress:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Säkerhetsvarning"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Visa certifikat"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"Certifikatet kommer inte från en betrodd utfärdare."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"Webbplatsens namn stämmer inte med namnet på certifikatet."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"Certifikatet har upphört att gälla."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Certifikatet är inte giltigt än."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Det här certifikatet har ett ogiltigt datum."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"Certifikatet är ogiltigt."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Okänt certifikatfel."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-sw/strings.xml b/packages/CaptivePortalLogin/res/values-sw/strings.xml
index 1c8b6e1..feb2dde 100644
--- a/packages/CaptivePortalLogin/res/values-sw/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-sw/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"Mtandao unaojaribu kujiunga nao una matatizo ya usalama."</string>
<string name="ssl_error_example" msgid="647898534624078900">"Kwa mfano, ukurasa wa kuingia katika akaunti unaweza usiwe unamilikiwa na shirika lililoonyeshwa."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Endelea hata hivyo kupitia kivinjari"</string>
+ <string name="ok" msgid="1509280796718850364">"Sawa"</string>
+ <string name="page_info" msgid="4048529256302257195">"Maelezo ya ukurasa"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Anwani:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Ilani ya usalama"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Tazama cheti"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"Cheti hiki hakijatoka kwa mamlaka inayoaminika."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"Jina la tovuti halilingani na jina lililo katika cheti."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"Cheti hiki kimepitwa na muda"</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Cheti bado si halali."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Cheti hiki kina tarehe batili."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"Hati hii ni batili."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Hitilafu isiyojulikana ya cheti."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-th/strings.xml b/packages/CaptivePortalLogin/res/values-th/strings.xml
index 9a3a626..11a2131 100644
--- a/packages/CaptivePortalLogin/res/values-th/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-th/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"เครือข่ายที่คุณพยายามเข้าร่วมมีปัญหาด้านความปลอดภัย"</string>
<string name="ssl_error_example" msgid="647898534624078900">"ตัวอย่างเช่น หน้าเข้าสู่ระบบอาจไม่ใช่ขององค์กรที่แสดงไว้"</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"ดำเนินการต่อผ่านเบราว์เซอร์"</string>
+ <string name="ok" msgid="1509280796718850364">"ตกลง"</string>
+ <string name="page_info" msgid="4048529256302257195">"ข้อมูลหน้าเว็บ"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"ที่อยู่:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"คำเตือนเกี่ยวกับความปลอดภัย"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"ดูใบรับรอง"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"ใบรับรองนี้ไม่ได้มาจากผู้ออกที่เชื่อถือได้"</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"ชื่อไซต์ไม่ตรงกับในใบรับรอง"</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"ใบรับรองนี้หมดอายุแล้ว"</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"ใบรับรองนี้ยังใช้งานไม่ได้"</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"ใบรับรองนี้มีวันที่ไม่ถูกต้อง"</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"ใบรับรองนี้ไม่ถูกต้อง"</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"ข้อผิดพลาดใบรับรองที่ไม่รู้จัก"</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-tl/strings.xml b/packages/CaptivePortalLogin/res/values-tl/strings.xml
index 565ef8f..07a2479 100644
--- a/packages/CaptivePortalLogin/res/values-tl/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-tl/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"May mga isyu sa seguridad ang network kung saan mo sinusubukang sumali."</string>
<string name="ssl_error_example" msgid="647898534624078900">"Halimbawa, maaaring hindi sa organisasyong ipinapakita ang page sa pag-log in."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Magpatuloy pa rin sa pamamagitan ng browser"</string>
+ <string name="ok" msgid="1509280796718850364">"OK"</string>
+ <string name="page_info" msgid="4048529256302257195">"Impormasyon ng pahina"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Address:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Babala sa seguridad"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Tingnan ang certificate"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"Ang certificate ay hindi mula sa isang pinagkakatiwalaang kinauukulan."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"Ang pangalan ng site ay hindi tumutugma sa pangalan sa certificate."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"Nag-expire na ang certificate na ito."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Wala pang bisa ang certificate na ito."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Ang certificate ay mayroong di-wastong petsa."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"Di-wasto ang certificate na ito."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Hindi kilalang error ng certificate."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-tr/strings.xml b/packages/CaptivePortalLogin/res/values-tr/strings.xml
index 73d2455..cdedd33 100644
--- a/packages/CaptivePortalLogin/res/values-tr/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-tr/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"Katılmaya çalıştığınız ağda güvenlik sorunları var."</string>
<string name="ssl_error_example" msgid="647898534624078900">"Örneğin, giriş sayfası, gösterilen kuruluşa ait olmayabilir."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Yine de tarayıcıyla devam et"</string>
+ <string name="ok" msgid="1509280796718850364">"Tamam"</string>
+ <string name="page_info" msgid="4048529256302257195">"Sayfa bilgileri"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Adres:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Güvenlik uyarısı"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Sertifikayı görüntüle"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"Bu sertifika güvenilir bir yetkiliden değil."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"Sitenin adı sertifika üzerindeki adla eşleşmiyor."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"Bu sertifikanın süresi dolmuş."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Bu sertifika henüz geçerli değil."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Bu sertifikanın tarihi geçersiz."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"Bu sertifika geçersiz."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Bilinmeyen sertifika hatası."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-uk/strings.xml b/packages/CaptivePortalLogin/res/values-uk/strings.xml
index 0e818d3..0f4cd16 100644
--- a/packages/CaptivePortalLogin/res/values-uk/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-uk/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"У мережі, до якої ви намагаєтеся під’єднатись, є проблеми з безпекою."</string>
<string name="ssl_error_example" msgid="647898534624078900">"Наприклад, сторінка входу може не належати вказаній організації."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Усе одно продовжити у веб-переглядачі"</string>
+ <string name="ok" msgid="1509280796718850364">"OK"</string>
+ <string name="page_info" msgid="4048529256302257195">"Інфо про стор."</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Адреса:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Застереж. про небезп."</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Переглянути сертиф."</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"Сертифікат видано ненадійним центром сертифікації."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"Назва сайту не збігається з назвою в сертифікаті."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"Термін дії сертиф. завершився."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Цей сертифікат ще не дійсний."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Цей сертифікат має недійсну дату."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"Цей сертифікат недійсний."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Помилка невідомого сертифіката."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-vi/strings.xml b/packages/CaptivePortalLogin/res/values-vi/strings.xml
index e51d2aa..9c702b9 100644
--- a/packages/CaptivePortalLogin/res/values-vi/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-vi/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"Mạng mà bạn đang cố gắng tham gia có vấn đề về bảo mật."</string>
<string name="ssl_error_example" msgid="647898534624078900">"Ví dụ, trang đăng nhập có thể không thuộc về tổ chức được hiển thị."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Vẫn tiếp tục qua trình duyệt"</string>
+ <string name="ok" msgid="1509280796718850364">"OK"</string>
+ <string name="page_info" msgid="4048529256302257195">"Thông tin trang"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Địa chỉ:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Cảnh báo bảo mật"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Xem chứng chỉ"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"Chứng chỉ này không xuất phát từ tổ chức phát hành đáng tin cậy."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"Tên của trang web không khớp với tên trên chứng chỉ."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"Chứng chỉ này đã hết hạn."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Chứng chỉ này chưa hợp lệ."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Chứng chỉ này có ngày không hợp lệ."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"Chứng chỉ này không hợp lệ."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Lỗi chứng chỉ không xác định."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-zh-rCN/strings.xml b/packages/CaptivePortalLogin/res/values-zh-rCN/strings.xml
index ce822e7..70c2a08 100644
--- a/packages/CaptivePortalLogin/res/values-zh-rCN/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-zh-rCN/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"您尝试加入的网络存在安全问题。"</string>
<string name="ssl_error_example" msgid="647898534624078900">"例如,登录页面可能并不属于页面上显示的单位。"</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"仍然通过浏览器继续操作"</string>
+ <string name="ok" msgid="1509280796718850364">"确定"</string>
+ <string name="page_info" msgid="4048529256302257195">"网页信息"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"网址:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"安全警告"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"查看证书"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"该证书并非来自可信的授权中心。"</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"网站的名称与证书上的名称不一致。"</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"该证书已过期。"</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"该证书尚未生效。"</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"该证书的日期无效。"</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"该证书无效。"</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"未知证书错误。"</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-zh-rHK/strings.xml b/packages/CaptivePortalLogin/res/values-zh-rHK/strings.xml
index 9010e1e..df1c700 100644
--- a/packages/CaptivePortalLogin/res/values-zh-rHK/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-zh-rHK/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"您正在嘗試加入的網絡有安全性問題。"</string>
<string name="ssl_error_example" msgid="647898534624078900">"例如,登入頁面並不屬於所顯示的機構。"</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"透過瀏覽器繼續"</string>
+ <string name="ok" msgid="1509280796718850364">"確定"</string>
+ <string name="page_info" msgid="4048529256302257195">"網頁資訊"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"地址:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"安全性警告"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"查看憑證"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"這個憑證並非由受信任的權威機構發出。"</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"網站名稱與憑證上的名稱不相符。"</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"這個憑證已過期。"</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"這個憑證尚未生效。"</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"此憑證的日期無效。"</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"此憑證是無效的。"</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"不明的憑證錯誤。"</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-zh-rTW/strings.xml b/packages/CaptivePortalLogin/res/values-zh-rTW/strings.xml
index 5b535e2..2a2e397 100644
--- a/packages/CaptivePortalLogin/res/values-zh-rTW/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-zh-rTW/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"你嘗試加入的網路有安全問題。"</string>
<string name="ssl_error_example" msgid="647898534624078900">"例如,登入網頁中顯示的機構可能並非該網頁實際隸屬的機構。"</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"透過瀏覽器繼續"</string>
+ <string name="ok" msgid="1509280796718850364">"確定"</string>
+ <string name="page_info" msgid="4048529256302257195">"頁面資訊"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"位址:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"安全性警告"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"檢視憑證"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"這個憑證並非來自信任的授權單位。"</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"網站名稱與憑證上的名稱不相符。"</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"此憑證已過期"</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"這個憑證尚未生效。"</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"這個憑證的日期無效。"</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"這個憑證無效。"</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"不明的憑證錯誤。"</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-zu/strings.xml b/packages/CaptivePortalLogin/res/values-zu/strings.xml
index 866ba18..7943645 100644
--- a/packages/CaptivePortalLogin/res/values-zu/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-zu/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"Inethiwekhi ozama ukuyijoyina inezinkinga zokuvikela."</string>
<string name="ssl_error_example" msgid="647898534624078900">"Isibonelo, ikhasi lokungena ngemvume kungenzeka lingelenhlangano ebonisiwe."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Qhubeka noma kunjalo ngesiphequluli"</string>
+ <string name="ok" msgid="1509280796718850364">"KULUNGILE"</string>
+ <string name="page_info" msgid="4048529256302257195">"Ulwazi lekhasi"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Ikheli:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Isexwayiso sokuvikeleka"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Buka isitifiketi"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"Lesi sitifiketi asiphumi embusweni othembekile."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"Igama lale ngosi alifani negama elikusitifiketi."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"Lesi sitifiketi siphelelwe yisikhathi"</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Lesi sitifiketi asilungile okwamanje"</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Lesi sitifiketi sinosuku olungalungile."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"Lesi sitifiketi asilungile."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Iphutha lesitifiketi elingaziwa."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values/strings.xml b/packages/CaptivePortalLogin/res/values/strings.xml
index f486fe4..e9698db 100644
--- a/packages/CaptivePortalLogin/res/values/strings.xml
+++ b/packages/CaptivePortalLogin/res/values/strings.xml
@@ -9,5 +9,17 @@
<string name="ssl_error_warning">The network you’re trying to join has security issues.</string>
<string name="ssl_error_example">For example, the login page may not belong to the organization shown.</string>
<string name="ssl_error_continue">Continue anyway via browser</string>
+ <string name="ssl_error_untrusted">This certificate isn\'t from a trusted authority.</string>
+ <string name="ssl_error_mismatch">The name of the site doesn\'t match the name on the certificate.</string>
+ <string name="ssl_error_expired">This certificate has expired.</string>
+ <string name="ssl_error_not_yet_valid">This certificate isn\'t valid yet.</string>
+ <string name="ssl_error_date_invalid">This certificate has an invalid date.</string>
+ <string name="ssl_error_invalid">This certificate is invalid.</string>
+ <string name="ssl_error_unknown">Unknown certificate error.</string>
+ <string name="ssl_security_warning_title">Security warning</string>
+ <string name="ssl_error_view_certificate">View certificate</string>
+ <string name="ok">OK</string>
+ <string name="page_info_address">Address:</string>
+ <string name="page_info">Page info</string>
</resources>
diff --git a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
index 774a035..7e20f2d 100644
--- a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
+++ b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
@@ -20,8 +20,10 @@
import static android.net.captiveportal.CaptivePortalProbeSpec.HTTP_LOCATION_HEADER_NAME;
import android.app.Activity;
+import android.app.AlertDialog;
import android.app.LoadedApk;
import android.content.Context;
+import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.CaptivePortal;
@@ -33,6 +35,7 @@
import android.net.Proxy;
import android.net.Uri;
import android.net.captiveportal.CaptivePortalProbeSpec;
+import android.net.http.SslCertificate;
import android.net.http.SslError;
import android.net.wifi.WifiInfo;
import android.os.Build;
@@ -42,8 +45,9 @@
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.Log;
-import android.util.TypedValue;
import android.util.SparseArray;
+import android.util.TypedValue;
+import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
@@ -52,8 +56,8 @@
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
-import android.webkit.WebView;
import android.webkit.WebViewClient;
+import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
@@ -276,6 +280,13 @@
@Override
public void onDestroy() {
super.onDestroy();
+ final WebView webview = (WebView) findViewById(R.id.webview);
+ if (webview != null) {
+ webview.stopLoading();
+ webview.setWebViewClient(null);
+ webview.setWebChromeClient(null);
+ webview.destroy();
+ }
if (mNetworkCallback != null) {
// mNetworkCallback is not null if mUrl is not null.
mCm.unregisterNetworkCallback(mNetworkCallback);
@@ -382,6 +393,7 @@
private static final String INTERNAL_ASSETS = "file:///android_asset/";
private final String mBrowserBailOutToken = Long.toString(new Random().nextLong());
+ private final String mCertificateOutToken = Long.toString(new Random().nextLong());
// How many Android device-independent-pixels per scaled-pixel
// dp/sp = (px/sp) / (px/dp) = (1/sp) / (1/dp)
private final float mDpPerSp = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 1,
@@ -397,6 +409,10 @@
return mPagesLoaded > 1;
}
+ private String mSslErrorTitle = null;
+ private SslErrorHandler mSslErrorHandler = null;
+ private SslError mSslError = null;
+
@Override
public void onPageStarted(WebView view, String urlString, Bitmap favicon) {
if (urlString.contains(mBrowserBailOutToken)) {
@@ -473,12 +489,16 @@
logMetricsEvent(MetricsEvent.CAPTIVE_PORTAL_LOGIN_ACTIVITY_SSL_ERROR);
final String sslErrorPage = makeSslErrorPage();
view.loadDataWithBaseURL(INTERNAL_ASSETS, sslErrorPage, "text/HTML", "UTF-8", null);
+ mSslErrorTitle = view.getTitle() == null ? "" : view.getTitle();
+ mSslErrorHandler = handler;
+ mSslError = error;
}
private String makeSslErrorPage() {
final String warningMsg = getString(R.string.ssl_error_warning);
final String exampleMsg = getString(R.string.ssl_error_example);
final String continueMsg = getString(R.string.ssl_error_continue);
+ final String certificateMsg = getString(R.string.ssl_error_view_certificate);
return String.join("\n",
"<html>",
"<head>",
@@ -516,13 +536,18 @@
" text-decoration:none;",
" text-transform:uppercase;",
" }",
+ " a.certificate {",
+ " margin-top:0px;",
+ " }",
" </style>",
"</head>",
"<body>",
" <p><img src=quantum_ic_warning_amber_96.png><br>",
" <div class=warn>" + warningMsg + "</div>",
" <div class=example>" + exampleMsg + "</div>",
- " <a href=" + mBrowserBailOutToken + ">" + continueMsg + "</a>",
+ " <a href=" + mBrowserBailOutToken + ">" + continueMsg + "</a><br>",
+ " <a class=certificate href=" + mCertificateOutToken + ">" + certificateMsg +
+ "</a>",
"</body>",
"</html>");
}
@@ -533,8 +558,50 @@
startActivity(new Intent(Intent.ACTION_DIAL, Uri.parse(url)));
return true;
}
+ if (url.contains(mCertificateOutToken) && mSslError != null) {
+ showSslAlertDialog(mSslErrorHandler, mSslError, mSslErrorTitle);
+ return true;
+ }
return false;
}
+ private void showSslAlertDialog(SslErrorHandler handler, SslError error, String title) {
+ final LayoutInflater factory = LayoutInflater.from(CaptivePortalLoginActivity.this);
+ final View sslWarningView = factory.inflate(R.layout.ssl_warning, null);
+
+ // Set Security certificate
+ setViewSecurityCertificate(sslWarningView.findViewById(R.id.certificate_layout), error);
+ ((TextView) sslWarningView.findViewById(R.id.ssl_error_type))
+ .setText(sslErrorName(error));
+ ((TextView) sslWarningView.findViewById(R.id.title)).setText(mSslErrorTitle);
+ ((TextView) sslWarningView.findViewById(R.id.address)).setText(error.getUrl());
+
+ AlertDialog sslAlertDialog = new AlertDialog.Builder(CaptivePortalLoginActivity.this)
+ .setTitle(R.string.ssl_security_warning_title)
+ .setView(sslWarningView)
+ .setPositiveButton(R.string.ok, (DialogInterface dialog, int whichButton) -> {
+ // handler.cancel is called via OnCancelListener.
+ dialog.cancel();
+ })
+ .setOnCancelListener((DialogInterface dialogInterface) -> handler.cancel())
+ .create();
+ sslAlertDialog.show();
+ }
+
+ private void setViewSecurityCertificate(LinearLayout certificateLayout, SslError error) {
+ SslCertificate cert = error.getCertificate();
+
+ View certificateView = cert.inflateCertificateView(CaptivePortalLoginActivity.this);
+ final LinearLayout placeholder = (LinearLayout) certificateView
+ .findViewById(com.android.internal.R.id.placeholder);
+ LayoutInflater factory = LayoutInflater.from(CaptivePortalLoginActivity.this);
+
+ TextView textView = (TextView) factory.inflate(
+ R.layout.ssl_error_msg, placeholder, false);
+ textView.setText(sslErrorMessage(error));
+ placeholder.addView(textView);
+
+ certificateLayout.addView(certificateView);
+ }
}
private class MyWebChromeClient extends WebChromeClient {
@@ -587,4 +654,18 @@
private static String sslErrorName(SslError error) {
return SSL_ERRORS.get(error.getPrimaryError(), "UNKNOWN");
}
+
+ private static final SparseArray<Integer> SSL_ERROR_MSGS = new SparseArray<>();
+ static {
+ SSL_ERROR_MSGS.put(SslError.SSL_NOTYETVALID, R.string.ssl_error_not_yet_valid);
+ SSL_ERROR_MSGS.put(SslError.SSL_EXPIRED, R.string.ssl_error_expired);
+ SSL_ERROR_MSGS.put(SslError.SSL_IDMISMATCH, R.string.ssl_error_mismatch);
+ SSL_ERROR_MSGS.put(SslError.SSL_UNTRUSTED, R.string.ssl_error_untrusted);
+ SSL_ERROR_MSGS.put(SslError.SSL_DATE_INVALID, R.string.ssl_error_date_invalid);
+ SSL_ERROR_MSGS.put(SslError.SSL_INVALID, R.string.ssl_error_invalid);
+ }
+
+ private static Integer sslErrorMessage(SslError error) {
+ return SSL_ERROR_MSGS.get(error.getPrimaryError(), R.string.ssl_error_unknown);
+ }
}
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index d11a74f..a3e6ea2 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -2602,24 +2602,35 @@
class AppFuseMountScope extends AppFuseBridge.MountScope {
boolean opened = false;
- public AppFuseMountScope(int uid, int pid, int mountId) {
- super(uid, pid, mountId);
+ public AppFuseMountScope(int uid, int mountId) {
+ super(uid, mountId);
}
@Override
public ParcelFileDescriptor open() throws NativeDaemonConnectorException {
try {
return new ParcelFileDescriptor(
- mVold.mountAppFuse(uid, Process.myPid(), mountId));
+ mVold.mountAppFuse(uid, mountId));
} catch (Exception e) {
throw new NativeDaemonConnectorException("Failed to mount", e);
}
}
@Override
+ public ParcelFileDescriptor openFile(int mountId, int fileId, int flags)
+ throws NativeDaemonConnectorException {
+ try {
+ return new ParcelFileDescriptor(
+ mVold.openAppFuseFile(uid, mountId, fileId, flags));
+ } catch (Exception e) {
+ throw new NativeDaemonConnectorException("Failed to open", e);
+ }
+ }
+
+ @Override
public void close() throws Exception {
if (opened) {
- mVold.unmountAppFuse(uid, Process.myPid(), mountId);
+ mVold.unmountAppFuse(uid, mountId);
opened = false;
}
}
@@ -2629,7 +2640,6 @@
public @Nullable AppFuseMount mountProxyFileDescriptorBridge() {
Slog.v(TAG, "mountProxyFileDescriptorBridge");
final int uid = Binder.getCallingUid();
- final int pid = Binder.getCallingPid();
while (true) {
synchronized (mAppFuseLock) {
@@ -2643,7 +2653,7 @@
final int name = mNextAppFuseName++;
try {
return new AppFuseMount(
- name, mAppFuseBridge.addBridge(new AppFuseMountScope(uid, pid, name)));
+ name, mAppFuseBridge.addBridge(new AppFuseMountScope(uid, name)));
} catch (FuseUnavailableMountException e) {
if (newlyCreated) {
// If newly created bridge fails, it's a real error.
@@ -2664,14 +2674,13 @@
public @Nullable ParcelFileDescriptor openProxyFileDescriptor(
int mountId, int fileId, int mode) {
Slog.v(TAG, "mountProxyFileDescriptor");
- final int pid = Binder.getCallingPid();
try {
synchronized (mAppFuseLock) {
if (mAppFuseBridge == null) {
Slog.e(TAG, "FuseBridge has not been created");
return null;
}
- return mAppFuseBridge.openFile(pid, mountId, fileId, mode);
+ return mAppFuseBridge.openFile(mountId, fileId, mode);
}
} catch (FuseUnavailableMountException | InterruptedException error) {
Slog.v(TAG, "The mount point has already been invalid", error);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index fa9c58e..a411af2 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -2919,8 +2919,7 @@
private String mExemptionsStr;
private List<String> mExemptions = Collections.emptyList();
private int mLogSampleRate = -1;
- @HiddenApiEnforcementPolicy private int mPolicyPreP = HIDDEN_API_ENFORCEMENT_DEFAULT;
- @HiddenApiEnforcementPolicy private int mPolicyP = HIDDEN_API_ENFORCEMENT_DEFAULT;
+ @HiddenApiEnforcementPolicy private int mPolicy = HIDDEN_API_ENFORCEMENT_DEFAULT;
public HiddenApiSettings(Handler handler, Context context) {
super(handler);
@@ -2937,11 +2936,7 @@
false,
this);
mContext.getContentResolver().registerContentObserver(
- Settings.Global.getUriFor(Settings.Global.HIDDEN_API_POLICY_PRE_P_APPS),
- false,
- this);
- mContext.getContentResolver().registerContentObserver(
- Settings.Global.getUriFor(Settings.Global.HIDDEN_API_POLICY_P_APPS),
+ Settings.Global.getUriFor(Settings.Global.HIDDEN_API_POLICY),
false,
this);
update();
@@ -2976,8 +2971,7 @@
mLogSampleRate = logSampleRate;
zygoteProcess.setHiddenApiAccessLogSampleRate(mLogSampleRate);
}
- mPolicyPreP = getValidEnforcementPolicy(Settings.Global.HIDDEN_API_POLICY_PRE_P_APPS);
- mPolicyP = getValidEnforcementPolicy(Settings.Global.HIDDEN_API_POLICY_P_APPS);
+ mPolicy = getValidEnforcementPolicy(Settings.Global.HIDDEN_API_POLICY);
}
private @HiddenApiEnforcementPolicy int getValidEnforcementPolicy(String settingsKey) {
@@ -2994,12 +2988,8 @@
return mBlacklistDisabled;
}
- @HiddenApiEnforcementPolicy int getPolicyForPrePApps() {
- return mPolicyPreP;
- }
-
- @HiddenApiEnforcementPolicy int getPolicyForPApps() {
- return mPolicyP;
+ @HiddenApiEnforcementPolicy int getPolicy() {
+ return mPolicy;
}
public void onChange(boolean selfChange) {
@@ -4328,9 +4318,7 @@
}
if (!disableHiddenApiChecks && !mHiddenApiBlacklist.isDisabled()) {
- app.info.maybeUpdateHiddenApiEnforcementPolicy(
- mHiddenApiBlacklist.getPolicyForPrePApps(),
- mHiddenApiBlacklist.getPolicyForPApps());
+ app.info.maybeUpdateHiddenApiEnforcementPolicy(mHiddenApiBlacklist.getPolicy());
@HiddenApiEnforcementPolicy int policy =
app.info.getHiddenApiEnforcementPolicy();
int policyBits = (policy << Zygote.API_ENFORCEMENT_POLICY_SHIFT);
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index cf49d2a..dc5213f 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -48,7 +48,7 @@
import dalvik.system.DexFile;
-import static android.content.pm.ApplicationInfo.HIDDEN_API_ENFORCEMENT_NONE;
+import static android.content.pm.ApplicationInfo.HIDDEN_API_ENFORCEMENT_DISABLED;
import static com.android.server.pm.Installer.DEXOPT_BOOTCOMPLETE;
import static com.android.server.pm.Installer.DEXOPT_DEBUGGABLE;
@@ -540,7 +540,7 @@
// Some apps are executed with restrictions on hidden API usage. If this app is one
// of them, pass a flag to dexopt to enable the same restrictions during compilation.
// TODO we should pass the actual flag value to dexopt, rather than assuming blacklist
- int hiddenApiFlag = info.getHiddenApiEnforcementPolicy() == HIDDEN_API_ENFORCEMENT_NONE
+ int hiddenApiFlag = info.getHiddenApiEnforcementPolicy() == HIDDEN_API_ENFORCEMENT_DISABLED
? 0
: DEXOPT_ENABLE_HIDDEN_API_CHECKS;
// Avoid generating CompactDex for modes that are latency critical.
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index f279f0e..2a605f5 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -83,6 +83,11 @@
import static android.content.pm.PackageManager.PERMISSION_DENIED;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.content.pm.PackageParser.isApkFile;
+import static android.content.pm.SharedLibraryNames.ANDROID_HIDL_BASE;
+import static android.content.pm.SharedLibraryNames.ANDROID_HIDL_MANAGER;
+import static android.content.pm.SharedLibraryNames.ANDROID_TEST_BASE;
+import static android.content.pm.SharedLibraryNames.ANDROID_TEST_MOCK;
+import static android.content.pm.SharedLibraryNames.ANDROID_TEST_RUNNER;
import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
import static android.os.storage.StorageManager.FLAG_STORAGE_CE;
import static android.os.storage.StorageManager.FLAG_STORAGE_DE;
@@ -367,6 +372,7 @@
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.BiConsumer;
import java.util.function.Predicate;
/**
@@ -901,23 +907,9 @@
final ParallelPackageParserCallback mParallelPackageParserCallback =
new ParallelPackageParserCallback();
- public static final class SharedLibraryEntry {
- public final @Nullable String path;
- public final @Nullable String apk;
- public final @NonNull SharedLibraryInfo info;
-
- SharedLibraryEntry(String _path, String _apk, String name, long version, int type,
- String declaringPackageName, long declaringPackageVersionCode) {
- path = _path;
- apk = _apk;
- info = new SharedLibraryInfo(name, version, type, new VersionedPackage(
- declaringPackageName, declaringPackageVersionCode), null);
- }
- }
-
// Currently known shared libraries.
- final ArrayMap<String, LongSparseArray<SharedLibraryEntry>> mSharedLibraries = new ArrayMap<>();
- final ArrayMap<String, LongSparseArray<SharedLibraryEntry>> mStaticLibsByDeclaringPackage =
+ final ArrayMap<String, LongSparseArray<SharedLibraryInfo>> mSharedLibraries = new ArrayMap<>();
+ final ArrayMap<String, LongSparseArray<SharedLibraryInfo>> mStaticLibsByDeclaringPackage =
new ArrayMap<>();
// All available activities, for your resolving pleasure.
@@ -2399,6 +2391,28 @@
}
}
+ @GuardedBy("mPackages")
+ private void setupBuiltinSharedLibraryDependenciesLocked() {
+ // Builtin libraries don't have versions.
+ long version = SharedLibraryInfo.VERSION_UNDEFINED;
+
+ SharedLibraryInfo libraryInfo = getSharedLibraryInfoLPr(ANDROID_HIDL_MANAGER, version);
+ if (libraryInfo != null) {
+ libraryInfo.addDependency(getSharedLibraryInfoLPr(ANDROID_HIDL_BASE, version));
+ }
+
+ libraryInfo = getSharedLibraryInfoLPr(ANDROID_TEST_RUNNER, version);
+ if (libraryInfo != null) {
+ libraryInfo.addDependency(getSharedLibraryInfoLPr(ANDROID_TEST_MOCK, version));
+ libraryInfo.addDependency(getSharedLibraryInfoLPr(ANDROID_TEST_BASE, version));
+ }
+
+ libraryInfo = getSharedLibraryInfoLPr(ANDROID_TEST_MOCK, version);
+ if (libraryInfo != null) {
+ libraryInfo.addDependency(getSharedLibraryInfoLPr(ANDROID_TEST_BASE, version));
+ }
+ }
+
public PackageManagerService(Context context, Installer installer,
boolean factoryTest, boolean onlyCore) {
LockGuard.installLock(mPackages, LockGuard.INDEX_PACKAGES);
@@ -2510,6 +2524,9 @@
addSharedLibraryLPw(path, null, name, SharedLibraryInfo.VERSION_UNDEFINED,
SharedLibraryInfo.TYPE_BUILTIN, PLATFORM_PACKAGE_NAME, 0);
}
+ // Builtin libraries cannot encode their dependency where they are
+ // defined, so fix that now.
+ setupBuiltinSharedLibraryDependenciesLocked();
SELinuxMMAC.readInstallPolicy();
@@ -3512,11 +3529,15 @@
private @NonNull String getRequiredSharedLibraryLPr(String name, int version) {
synchronized (mPackages) {
- SharedLibraryEntry libraryEntry = getSharedLibraryEntryLPr(name, version);
- if (libraryEntry == null) {
+ SharedLibraryInfo libraryInfo = getSharedLibraryInfoLPr(name, version);
+ if (libraryInfo == null) {
throw new IllegalStateException("Missing required shared library:" + name);
}
- return libraryEntry.apk;
+ String packageName = libraryInfo.getPackageName();
+ if (packageName == null) {
+ throw new IllegalStateException("Expected a package for shared library " + name);
+ }
+ return packageName;
}
}
@@ -4249,9 +4270,9 @@
return false;
}
- final SharedLibraryEntry libEntry = getSharedLibraryEntryLPr(ps.pkg.staticSharedLibName,
+ final SharedLibraryInfo libraryInfo = getSharedLibraryInfoLPr(ps.pkg.staticSharedLibName,
ps.pkg.staticSharedLibVersion);
- if (libEntry == null) {
+ if (libraryInfo == null) {
return false;
}
@@ -4268,11 +4289,11 @@
PackageSetting uidPs = mSettings.getPackageLPr(uidPackageName);
if (uidPs != null) {
final int index = ArrayUtils.indexOf(uidPs.usesStaticLibraries,
- libEntry.info.getName());
+ libraryInfo.getName());
if (index < 0) {
continue;
}
- if (uidPs.pkg.usesStaticLibrariesVersions[index] == libEntry.info.getLongVersion()) {
+ if (uidPs.pkg.usesStaticLibrariesVersions[index] == libraryInfo.getLongVersion()) {
return false;
}
}
@@ -4668,14 +4689,14 @@
final int[] allUsers = sUserManager.getUserIds();
final int libCount = mSharedLibraries.size();
for (int i = 0; i < libCount; i++) {
- final LongSparseArray<SharedLibraryEntry> versionedLib
+ final LongSparseArray<SharedLibraryInfo> versionedLib
= mSharedLibraries.valueAt(i);
if (versionedLib == null) {
continue;
}
final int versionCount = versionedLib.size();
for (int j = 0; j < versionCount; j++) {
- SharedLibraryInfo libInfo = versionedLib.valueAt(j).info;
+ SharedLibraryInfo libInfo = versionedLib.valueAt(j);
// Skip packages that are not static shared libs.
if (!libInfo.isStatic()) {
break;
@@ -5041,14 +5062,14 @@
final int libCount = mSharedLibraries.size();
for (int i = 0; i < libCount; i++) {
- LongSparseArray<SharedLibraryEntry> versionedLib = mSharedLibraries.valueAt(i);
+ LongSparseArray<SharedLibraryInfo> versionedLib = mSharedLibraries.valueAt(i);
if (versionedLib == null) {
continue;
}
final int versionCount = versionedLib.size();
for (int j = 0; j < versionCount; j++) {
- SharedLibraryInfo libInfo = versionedLib.valueAt(j).info;
+ SharedLibraryInfo libInfo = versionedLib.valueAt(j);
if (!canSeeStaticLibraries && libInfo.isStatic()) {
break;
}
@@ -5064,10 +5085,13 @@
Binder.restoreCallingIdentity(identity);
}
- SharedLibraryInfo resLibInfo = new SharedLibraryInfo(libInfo.getName(),
- libInfo.getLongVersion(), libInfo.getType(),
- libInfo.getDeclaringPackage(), getPackagesUsingSharedLibraryLPr(libInfo,
- flags, userId));
+ SharedLibraryInfo resLibInfo = new SharedLibraryInfo(libInfo.getPath(),
+ libInfo.getPackageName(), libInfo.getName(), libInfo.getLongVersion(),
+ libInfo.getType(), libInfo.getDeclaringPackage(),
+ getPackagesUsingSharedLibraryLPr(libInfo, flags, userId),
+ (libInfo.getDependencies() == null
+ ? null
+ : new ArrayList(libInfo.getDependencies())));
if (result == null) {
result = new ArrayList<>();
@@ -5182,28 +5206,28 @@
Set<String> libs = null;
final int libCount = mSharedLibraries.size();
for (int i = 0; i < libCount; i++) {
- LongSparseArray<SharedLibraryEntry> versionedLib = mSharedLibraries.valueAt(i);
+ LongSparseArray<SharedLibraryInfo> versionedLib = mSharedLibraries.valueAt(i);
if (versionedLib == null) {
continue;
}
final int versionCount = versionedLib.size();
for (int j = 0; j < versionCount; j++) {
- SharedLibraryEntry libEntry = versionedLib.valueAt(j);
- if (!libEntry.info.isStatic()) {
+ SharedLibraryInfo libraryInfo = versionedLib.valueAt(j);
+ if (!libraryInfo.isStatic()) {
if (libs == null) {
libs = new ArraySet<>();
}
- libs.add(libEntry.info.getName());
+ libs.add(libraryInfo.getName());
break;
}
- PackageSetting ps = mSettings.getPackageLPr(libEntry.apk);
+ PackageSetting ps = mSettings.getPackageLPr(libraryInfo.getPackageName());
if (ps != null && !filterSharedLibPackageLPr(ps, Binder.getCallingUid(),
UserHandle.getUserId(Binder.getCallingUid()),
PackageManager.MATCH_STATIC_SHARED_LIBRARIES)) {
if (libs == null) {
libs = new ArraySet<>();
}
- libs.add(libEntry.info.getName());
+ libs.add(libraryInfo.getName());
break;
}
}
@@ -9451,24 +9475,24 @@
private PackageParser.Package findSharedNonSystemLibrary(String name, long version) {
synchronized (mPackages) {
- SharedLibraryEntry libEntry = getSharedLibraryEntryLPr(name, version);
- if (libEntry != null) {
- return mPackages.get(libEntry.apk);
+ SharedLibraryInfo libraryInfo = getSharedLibraryInfoLPr(name, version);
+ if (libraryInfo != null) {
+ return mPackages.get(libraryInfo.getPackageName());
}
return null;
}
}
- private SharedLibraryEntry getSharedLibraryEntryLPr(String name, long version) {
- LongSparseArray<SharedLibraryEntry> versionedLib = mSharedLibraries.get(name);
+ private @Nullable SharedLibraryInfo getSharedLibraryInfoLPr(String name, long version) {
+ LongSparseArray<SharedLibraryInfo> versionedLib = mSharedLibraries.get(name);
if (versionedLib == null) {
return null;
}
return versionedLib.get(version);
}
- private SharedLibraryEntry getLatestSharedLibraVersionLPr(PackageParser.Package pkg) {
- LongSparseArray<SharedLibraryEntry> versionedLib = mSharedLibraries.get(
+ private SharedLibraryInfo getLatestSharedLibraVersionLPr(PackageParser.Package pkg) {
+ LongSparseArray<SharedLibraryInfo> versionedLib = mSharedLibraries.get(
pkg.staticSharedLibName);
if (versionedLib == null) {
return null;
@@ -9700,15 +9724,45 @@
}
}
- private void addSharedLibraryLPr(Set<String> usesLibraryFiles,
- SharedLibraryEntry file,
- PackageParser.Package changingLib) {
- if (file.path != null) {
- usesLibraryFiles.add(file.path);
+ @GuardedBy("mPackages")
+ private void applyDefiningSharedLibraryUpdateLocked(
+ PackageParser.Package pkg, SharedLibraryInfo libInfo,
+ BiConsumer<SharedLibraryInfo, SharedLibraryInfo> action) {
+ // Note that libraries defined by this package may be null if:
+ // - Package manager was unable to create the shared library. The package still
+ // gets installed, but the shared library does not get created.
+ // Or:
+ // - Package manager is in a state where package isn't scanned yet. This will
+ // get called again after scanning to fix the dependencies.
+ if (pkg.isLibrary()) {
+ if (pkg.staticSharedLibName != null) {
+ SharedLibraryInfo definedLibrary = getSharedLibraryInfoLPr(
+ pkg.staticSharedLibName, pkg.staticSharedLibVersion);
+ if (definedLibrary != null) {
+ action.accept(definedLibrary, libInfo);
+ }
+ } else {
+ for (String libraryName : pkg.libraryNames) {
+ SharedLibraryInfo definedLibrary = getSharedLibraryInfoLPr(
+ libraryName, SharedLibraryInfo.VERSION_UNDEFINED);
+ if (definedLibrary != null) {
+ action.accept(definedLibrary, libInfo);
+ }
+ }
+ }
+ }
+ }
+
+ @GuardedBy("mPackages")
+ private void addSharedLibraryLPr(PackageParser.Package pkg, Set<String> usesLibraryFiles,
+ SharedLibraryInfo libInfo, PackageParser.Package changingLib) {
+
+ if (libInfo.getPath() != null) {
+ usesLibraryFiles.add(libInfo.getPath());
return;
}
- PackageParser.Package p = mPackages.get(file.apk);
- if (changingLib != null && changingLib.packageName.equals(file.apk)) {
+ PackageParser.Package p = mPackages.get(libInfo.getPackageName());
+ if (changingLib != null && changingLib.packageName.equals(libInfo.getPackageName())) {
// If we are doing this while in the middle of updating a library apk,
// then we need to make sure to use that new apk for determining the
// dependencies here. (We haven't yet finished committing the new apk
@@ -9719,6 +9773,10 @@
}
if (p != null) {
usesLibraryFiles.addAll(p.getAllCodePaths());
+ // If the package provides libraries, add the dependency to them.
+ applyDefiningSharedLibraryUpdateLocked(pkg, libInfo, (definingLibrary, dependency) -> {
+ definingLibrary.addDependency(dependency);
+ });
if (p.usesLibraryFiles != null) {
Collections.addAll(usesLibraryFiles, p.usesLibraryFiles);
}
@@ -9730,45 +9788,61 @@
if (pkg == null) {
return;
}
+
+ // If the package provides libraries, clear their old dependencies.
+ // This method will set them up again.
+ applyDefiningSharedLibraryUpdateLocked(pkg, null, (definingLibrary, dependency) -> {
+ definingLibrary.clearDependencies();
+ });
// The collection used here must maintain the order of addition (so
// that libraries are searched in the correct order) and must have no
// duplicates.
- Set<String> usesLibraryFiles = null;
+ ArrayList<SharedLibraryInfo> usesLibraryInfos = null;
if (pkg.usesLibraries != null) {
- usesLibraryFiles = addSharedLibrariesLPw(pkg.usesLibraries,
- null, null, pkg.packageName, changingLib, true,
+ usesLibraryInfos = addSharedLibrariesLPw(pkg.usesLibraries,
+ null, null, pkg.packageName, true,
pkg.applicationInfo.targetSdkVersion, null);
}
if (pkg.usesStaticLibraries != null) {
- usesLibraryFiles = addSharedLibrariesLPw(pkg.usesStaticLibraries,
+ usesLibraryInfos = addSharedLibrariesLPw(pkg.usesStaticLibraries,
pkg.usesStaticLibrariesVersions, pkg.usesStaticLibrariesCertDigests,
- pkg.packageName, changingLib, true,
- pkg.applicationInfo.targetSdkVersion, usesLibraryFiles);
+ pkg.packageName, true,
+ pkg.applicationInfo.targetSdkVersion, usesLibraryInfos);
}
if (pkg.usesOptionalLibraries != null) {
- usesLibraryFiles = addSharedLibrariesLPw(pkg.usesOptionalLibraries,
- null, null, pkg.packageName, changingLib, false,
- pkg.applicationInfo.targetSdkVersion, usesLibraryFiles);
+ usesLibraryInfos = addSharedLibrariesLPw(pkg.usesOptionalLibraries,
+ null, null, pkg.packageName, false,
+ pkg.applicationInfo.targetSdkVersion, usesLibraryInfos);
}
- if (!ArrayUtils.isEmpty(usesLibraryFiles)) {
+ if (usesLibraryInfos != null) {
+ pkg.usesLibraryInfos = usesLibraryInfos;
+ // Use LinkedHashSet to preserve the order of files added to
+ // usesLibraryFiles while eliminating duplicates.
+ Set<String> usesLibraryFiles = new LinkedHashSet<>();
+ for (SharedLibraryInfo libInfo : usesLibraryInfos) {
+ addSharedLibraryLPr(pkg, usesLibraryFiles, libInfo, changingLib);
+ }
pkg.usesLibraryFiles = usesLibraryFiles.toArray(new String[usesLibraryFiles.size()]);
} else {
+ pkg.usesLibraryInfos = null;
pkg.usesLibraryFiles = null;
}
}
- private Set<String> addSharedLibrariesLPw(@NonNull List<String> requestedLibraries,
+ @GuardedBy("mPackages")
+ private ArrayList<SharedLibraryInfo> addSharedLibrariesLPw(
+ @NonNull List<String> requestedLibraries,
@Nullable long[] requiredVersions, @Nullable String[][] requiredCertDigests,
- @NonNull String packageName, @Nullable PackageParser.Package changingLib,
- boolean required, int targetSdk, @Nullable Set<String> outUsedLibraries)
+ @NonNull String packageName, boolean required, int targetSdk,
+ @Nullable ArrayList<SharedLibraryInfo> outUsedLibraries)
throws PackageManagerException {
final int libCount = requestedLibraries.size();
for (int i = 0; i < libCount; i++) {
final String libName = requestedLibraries.get(i);
final long libVersion = requiredVersions != null ? requiredVersions[i]
: SharedLibraryInfo.VERSION_UNDEFINED;
- final SharedLibraryEntry libEntry = getSharedLibraryEntryLPr(libName, libVersion);
- if (libEntry == null) {
+ final SharedLibraryInfo libraryInfo = getSharedLibraryInfoLPr(libName, libVersion);
+ if (libraryInfo == null) {
if (required) {
throw new PackageManagerException(INSTALL_FAILED_MISSING_SHARED_LIBRARY,
"Package " + packageName + " requires unavailable shared library "
@@ -9780,14 +9854,14 @@
}
} else {
if (requiredVersions != null && requiredCertDigests != null) {
- if (libEntry.info.getLongVersion() != requiredVersions[i]) {
+ if (libraryInfo.getLongVersion() != requiredVersions[i]) {
throw new PackageManagerException(INSTALL_FAILED_MISSING_SHARED_LIBRARY,
"Package " + packageName + " requires unavailable static shared"
+ " library " + libName + " version "
- + libEntry.info.getLongVersion() + "; failing!");
+ + libraryInfo.getLongVersion() + "; failing!");
}
- PackageParser.Package libPkg = mPackages.get(libEntry.apk);
+ PackageParser.Package libPkg = mPackages.get(libraryInfo.getPackageName());
if (libPkg == null) {
throw new PackageManagerException(INSTALL_FAILED_MISSING_SHARED_LIBRARY,
"Package " + packageName + " requires unavailable static shared"
@@ -9844,11 +9918,9 @@
}
if (outUsedLibraries == null) {
- // Use LinkedHashSet to preserve the order of files added to
- // usesLibraryFiles while eliminating duplicates.
- outUsedLibraries = new LinkedHashSet<>();
+ outUsedLibraries = new ArrayList<>();
}
- addSharedLibraryLPr(outUsedLibraries, libEntry, changingLib);
+ outUsedLibraries.add(libraryInfo);
}
}
return outUsedLibraries;
@@ -10230,9 +10302,9 @@
// library in order to compare signatures.
PackageSetting signatureCheckPs = pkgSetting;
if (pkg.applicationInfo.isStaticSharedLibrary()) {
- SharedLibraryEntry libraryEntry = getLatestSharedLibraVersionLPr(pkg);
- if (libraryEntry != null) {
- signatureCheckPs = mSettings.getPackageLPr(libraryEntry.apk);
+ SharedLibraryInfo libraryInfo = getLatestSharedLibraVersionLPr(pkg);
+ if (libraryInfo != null) {
+ signatureCheckPs = mSettings.getPackageLPr(libraryInfo.getPackageName());
}
}
@@ -11061,12 +11133,12 @@
long minVersionCode = Long.MIN_VALUE;
long maxVersionCode = Long.MAX_VALUE;
- LongSparseArray<SharedLibraryEntry> versionedLib = mSharedLibraries.get(
+ LongSparseArray<SharedLibraryInfo> versionedLib = mSharedLibraries.get(
pkg.staticSharedLibName);
if (versionedLib != null) {
final int versionCount = versionedLib.size();
for (int i = 0; i < versionCount; i++) {
- SharedLibraryInfo libInfo = versionedLib.valueAt(i).info;
+ SharedLibraryInfo libInfo = versionedLib.valueAt(i);
final long libVersionCode = libInfo.getDeclaringPackage()
.getLongVersionCode();
if (libInfo.getLongVersion() < pkg.staticSharedLibVersion) {
@@ -11254,7 +11326,7 @@
private boolean addSharedLibraryLPw(String path, String apk, String name, long version,
int type, String declaringPackageName, long declaringVersionCode) {
- LongSparseArray<SharedLibraryEntry> versionedLib = mSharedLibraries.get(name);
+ LongSparseArray<SharedLibraryInfo> versionedLib = mSharedLibraries.get(name);
if (versionedLib == null) {
versionedLib = new LongSparseArray<>();
mSharedLibraries.put(name, versionedLib);
@@ -11264,14 +11336,15 @@
} else if (versionedLib.indexOfKey(version) >= 0) {
return false;
}
- SharedLibraryEntry libEntry = new SharedLibraryEntry(path, apk, name,
- version, type, declaringPackageName, declaringVersionCode);
- versionedLib.put(version, libEntry);
+ SharedLibraryInfo libraryInfo = new SharedLibraryInfo(path, apk, name,
+ version, type, new VersionedPackage(declaringPackageName, declaringVersionCode),
+ null, null);
+ versionedLib.put(version, libraryInfo);
return true;
}
private boolean removeSharedLibraryLPw(String name, long version) {
- LongSparseArray<SharedLibraryEntry> versionedLib = mSharedLibraries.get(name);
+ LongSparseArray<SharedLibraryInfo> versionedLib = mSharedLibraries.get(name);
if (versionedLib == null) {
return false;
}
@@ -11279,12 +11352,12 @@
if (libIdx < 0) {
return false;
}
- SharedLibraryEntry libEntry = versionedLib.valueAt(libIdx);
+ SharedLibraryInfo libraryInfo = versionedLib.valueAt(libIdx);
versionedLib.remove(version);
if (versionedLib.size() <= 0) {
mSharedLibraries.remove(name);
- if (libEntry.info.getType() == SharedLibraryInfo.TYPE_STATIC) {
- mStaticLibsByDeclaringPackage.remove(libEntry.info.getDeclaringPackage()
+ if (libraryInfo.getType() == SharedLibraryInfo.TYPE_STATIC) {
+ mStaticLibsByDeclaringPackage.remove(libraryInfo.getDeclaringPackage()
.getPackageName());
}
}
@@ -17330,9 +17403,9 @@
// the package setting for the latest library version.
PackageSetting signatureCheckPs = ps;
if (pkg.applicationInfo.isStaticSharedLibrary()) {
- SharedLibraryEntry libraryEntry = getLatestSharedLibraVersionLPr(pkg);
- if (libraryEntry != null) {
- signatureCheckPs = mSettings.getPackageLPr(libraryEntry.apk);
+ SharedLibraryInfo libraryInfo = getLatestSharedLibraVersionLPr(pkg);
+ if (libraryInfo != null) {
+ signatureCheckPs = mSettings.getPackageLPr(libraryInfo.getPackageName());
}
}
@@ -18024,7 +18097,7 @@
packageName = normalizedPackageName != null ? normalizedPackageName : packageName;
// Is this a static library?
- LongSparseArray<SharedLibraryEntry> versionedLib =
+ LongSparseArray<SharedLibraryInfo> versionedLib =
mStaticLibsByDeclaringPackage.get(packageName);
if (versionedLib == null || versionedLib.size() <= 0) {
return packageName;
@@ -18036,7 +18109,7 @@
if (callingAppId != Process.SYSTEM_UID && callingAppId != Process.SHELL_UID
&& callingAppId != Process.ROOT_UID) {
versionsCallerCanSee = new LongSparseLongArray();
- String libName = versionedLib.valueAt(0).info.getName();
+ String libName = versionedLib.valueAt(0).getName();
String[] uidPackages = getPackagesForUid(Binder.getCallingUid());
if (uidPackages != null) {
for (String uidPackage : uidPackages) {
@@ -18056,29 +18129,29 @@
}
// Find the version the caller can see and the app version code
- SharedLibraryEntry highestVersion = null;
+ SharedLibraryInfo highestVersion = null;
final int versionCount = versionedLib.size();
for (int i = 0; i < versionCount; i++) {
- SharedLibraryEntry libEntry = versionedLib.valueAt(i);
+ SharedLibraryInfo libraryInfo = versionedLib.valueAt(i);
if (versionsCallerCanSee != null && versionsCallerCanSee.indexOfKey(
- libEntry.info.getLongVersion()) < 0) {
+ libraryInfo.getLongVersion()) < 0) {
continue;
}
- final long libVersionCode = libEntry.info.getDeclaringPackage().getLongVersionCode();
+ final long libVersionCode = libraryInfo.getDeclaringPackage().getLongVersionCode();
if (versionCode != PackageManager.VERSION_CODE_HIGHEST) {
if (libVersionCode == versionCode) {
- return libEntry.apk;
+ return libraryInfo.getPackageName();
}
} else if (highestVersion == null) {
- highestVersion = libEntry;
- } else if (libVersionCode > highestVersion.info
+ highestVersion = libraryInfo;
+ } else if (libVersionCode > highestVersion
.getDeclaringPackage().getLongVersionCode()) {
- highestVersion = libEntry;
+ highestVersion = libraryInfo;
}
}
if (highestVersion != null) {
- return highestVersion.apk;
+ return highestVersion.getPackageName();
}
return packageName;
@@ -18240,19 +18313,19 @@
allUsers = sUserManager.getUserIds();
if (pkg != null && pkg.staticSharedLibName != null) {
- SharedLibraryEntry libEntry = getSharedLibraryEntryLPr(pkg.staticSharedLibName,
+ SharedLibraryInfo libraryInfo = getSharedLibraryInfoLPr(pkg.staticSharedLibName,
pkg.staticSharedLibVersion);
- if (libEntry != null) {
+ if (libraryInfo != null) {
for (int currUserId : allUsers) {
if (removeUser != UserHandle.USER_ALL && removeUser != currUserId) {
continue;
}
List<VersionedPackage> libClientPackages = getPackagesUsingSharedLibraryLPr(
- libEntry.info, 0, currUserId);
+ libraryInfo, 0, currUserId);
if (!ArrayUtils.isEmpty(libClientPackages)) {
Slog.w(TAG, "Not removing package " + pkg.manifestPackageName
- + " hosting lib " + libEntry.info.getName() + " version "
- + libEntry.info.getLongVersion() + " used by " + libClientPackages
+ + " hosting lib " + libraryInfo.getName() + " version "
+ + libraryInfo.getLongVersion() + " used by " + libClientPackages
+ " for user " + currUserId);
return PackageManager.DELETE_FAILED_USED_SHARED_LIBRARY;
}
@@ -21593,14 +21666,14 @@
final Iterator<String> it = mSharedLibraries.keySet().iterator();
while (it.hasNext()) {
String libName = it.next();
- LongSparseArray<SharedLibraryEntry> versionedLib
+ LongSparseArray<SharedLibraryInfo> versionedLib
= mSharedLibraries.get(libName);
if (versionedLib == null) {
continue;
}
final int versionCount = versionedLib.size();
for (int i = 0; i < versionCount; i++) {
- SharedLibraryEntry libEntry = versionedLib.valueAt(i);
+ SharedLibraryInfo libraryInfo = versionedLib.valueAt(i);
if (!checkin) {
if (!printedHeader) {
if (dumpState.onTitlePrinted())
@@ -21612,19 +21685,19 @@
} else {
pw.print("lib,");
}
- pw.print(libEntry.info.getName());
- if (libEntry.info.isStatic()) {
- pw.print(" version=" + libEntry.info.getLongVersion());
+ pw.print(libraryInfo.getName());
+ if (libraryInfo.isStatic()) {
+ pw.print(" version=" + libraryInfo.getLongVersion());
}
if (!checkin) {
pw.print(" -> ");
}
- if (libEntry.path != null) {
+ if (libraryInfo.getPath() != null) {
pw.print(" (jar) ");
- pw.print(libEntry.path);
+ pw.print(libraryInfo.getPath());
} else {
pw.print(" (apk) ");
- pw.print(libEntry.apk);
+ pw.print(libraryInfo.getPackageName());
}
pw.println();
}
@@ -22024,22 +22097,24 @@
final int count = mSharedLibraries.size();
for (int i = 0; i < count; i++) {
final String libName = mSharedLibraries.keyAt(i);
- LongSparseArray<SharedLibraryEntry> versionedLib = mSharedLibraries.get(libName);
+ LongSparseArray<SharedLibraryInfo> versionedLib = mSharedLibraries.get(libName);
if (versionedLib == null) {
continue;
}
final int versionCount = versionedLib.size();
for (int j = 0; j < versionCount; j++) {
- final SharedLibraryEntry libEntry = versionedLib.valueAt(j);
+ final SharedLibraryInfo libraryInfo = versionedLib.valueAt(j);
final long sharedLibraryToken =
proto.start(PackageServiceDumpProto.SHARED_LIBRARIES);
- proto.write(PackageServiceDumpProto.SharedLibraryProto.NAME, libEntry.info.getName());
- final boolean isJar = (libEntry.path != null);
+ proto.write(PackageServiceDumpProto.SharedLibraryProto.NAME, libraryInfo.getName());
+ final boolean isJar = (libraryInfo.getPath() != null);
proto.write(PackageServiceDumpProto.SharedLibraryProto.IS_JAR, isJar);
if (isJar) {
- proto.write(PackageServiceDumpProto.SharedLibraryProto.PATH, libEntry.path);
+ proto.write(PackageServiceDumpProto.SharedLibraryProto.PATH,
+ libraryInfo.getPath());
} else {
- proto.write(PackageServiceDumpProto.SharedLibraryProto.APK, libEntry.apk);
+ proto.write(PackageServiceDumpProto.SharedLibraryProto.APK,
+ libraryInfo.getPackageName());
}
proto.end(sharedLibraryToken);
}
diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java b/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java
index a55b49f..f78d263 100644
--- a/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java
+++ b/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java
@@ -20,7 +20,7 @@
import android.content.Context;
import android.os.RemoteException;
import android.os.ServiceManager;
-import android.security.IKeystoreService;
+import android.security.keystore.IKeystoreService;
import android.util.Slog;
import com.android.internal.policy.IKeyguardService;
diff --git a/services/core/java/com/android/server/storage/AppFuseBridge.java b/services/core/java/com/android/server/storage/AppFuseBridge.java
index 6a0b648..9d6a647 100644
--- a/services/core/java/com/android/server/storage/AppFuseBridge.java
+++ b/services/core/java/com/android/server/storage/AppFuseBridge.java
@@ -16,6 +16,7 @@
package com.android.server.storage;
+import android.os.FileUtils;
import android.os.ParcelFileDescriptor;
import android.system.ErrnoException;
import android.system.Os;
@@ -25,8 +26,6 @@
import com.android.internal.util.Preconditions;
import com.android.server.NativeDaemonConnectorException;
import libcore.io.IoUtils;
-import java.io.File;
-import java.io.FileNotFoundException;
import java.util.concurrent.CountDownLatch;
/**
@@ -87,7 +86,7 @@
}
}
- public ParcelFileDescriptor openFile(int pid, int mountId, int fileId, int mode)
+ public ParcelFileDescriptor openFile(int mountId, int fileId, int mode)
throws FuseUnavailableMountException, InterruptedException {
final MountScope scope;
synchronized (this) {
@@ -96,17 +95,14 @@
throw new FuseUnavailableMountException(mountId);
}
}
- if (scope.pid != pid) {
- throw new SecurityException("PID does not match");
- }
final boolean result = scope.waitForMount();
if (result == false) {
throw new FuseUnavailableMountException(mountId);
}
try {
- return ParcelFileDescriptor.open(
- new File(scope.mountPoint, String.valueOf(fileId)), mode);
- } catch (FileNotFoundException error) {
+ int flags = FileUtils.translateModePfdToPosix(mode);
+ return scope.openFile(mountId, fileId, flags);
+ } catch (NativeDaemonConnectorException error) {
throw new FuseUnavailableMountException(mountId);
}
}
@@ -131,17 +127,13 @@
public static abstract class MountScope implements AutoCloseable {
public final int uid;
- public final int pid;
public final int mountId;
- public final File mountPoint;
private final CountDownLatch mMounted = new CountDownLatch(1);
private boolean mMountResult = false;
- public MountScope(int uid, int pid, int mountId) {
+ public MountScope(int uid, int mountId) {
this.uid = uid;
- this.pid = pid;
this.mountId = mountId;
- this.mountPoint = new File(String.format(APPFUSE_MOUNT_NAME_TEMPLATE, uid, mountId));
}
@GuardedBy("AppFuseBridge.this")
@@ -159,6 +151,8 @@
}
public abstract ParcelFileDescriptor open() throws NativeDaemonConnectorException;
+ public abstract ParcelFileDescriptor openFile(int mountId, int fileId, int flags)
+ throws NativeDaemonConnectorException;
}
private native long native_new();
diff --git a/services/robotests/Android.mk b/services/robotests/Android.mk
index de54c4b..c01c124 100644
--- a/services/robotests/Android.mk
+++ b/services/robotests/Android.mk
@@ -28,7 +28,8 @@
LOCAL_STATIC_JAVA_LIBRARIES := \
services.backup \
- services.core
+ services.core \
+ services.net
include $(BUILD_PACKAGE)
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
index 2f6e2c2..cdbc665 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
@@ -24,6 +24,7 @@
import android.content.pm.PackageParser;
import android.content.pm.ProviderInfo;
import android.content.pm.ServiceInfo;
+import android.content.pm.SharedLibraryInfo;
import android.content.pm.Signature;
import android.os.Bundle;
import android.os.Parcel;
@@ -487,6 +488,9 @@
pkg.usesLibraryFiles = new String[] { "foo13"};
+ pkg.usesLibraryInfos = new ArrayList<>();
+ pkg.usesLibraryInfos.add(new SharedLibraryInfo(null, null, null, 0L, 0, null, null, null));
+
pkg.mOriginalPackages = new ArrayList<>();
pkg.mOriginalPackages.add("foo14");
diff --git a/startop/view_compiler/dex_builder.cc b/startop/view_compiler/dex_builder.cc
index 33df6f9..906d64c 100644
--- a/startop/view_compiler/dex_builder.cc
+++ b/startop/view_compiler/dex_builder.cc
@@ -49,18 +49,27 @@
case Instruction::Op::kReturn:
out << "kReturn";
return out;
+ case Instruction::Op::kReturnObject:
+ out << "kReturnObject";
+ return out;
case Instruction::Op::kMove:
out << "kMove";
return out;
case Instruction::Op::kInvokeVirtual:
out << "kInvokeVirtual";
return out;
+ case Instruction::Op::kInvokeDirect:
+ out << "kInvokeDirect";
+ return out;
case Instruction::Op::kBindLabel:
out << "kBindLabel";
return out;
case Instruction::Op::kBranchEqz:
out << "kBranchEqz";
return out;
+ case Instruction::Op::kNew:
+ out << "kNew";
+ return out;
}
}
@@ -137,6 +146,9 @@
entry = Alloc<ir::String>();
// +1 for null terminator
entry->data = slicer::MemView{buffer.get(), header_length + string.size() + 1};
+ ::dex::u4 const new_index = dex_file_->strings_indexes.AllocateIndex();
+ dex_file_->strings_map[new_index] = entry;
+ entry->orig_index = new_index;
string_data_.push_back(std::move(buffer));
}
return entry;
@@ -161,6 +173,8 @@
ir::Type* type = Alloc<ir::Type>();
type->descriptor = GetOrAddString(descriptor);
types_by_descriptor_[descriptor] = type;
+ type->orig_index = dex_file_->types_indexes.AllocateIndex();
+ dex_file_->types_map[type->orig_index] = type;
return type;
}
@@ -217,9 +231,10 @@
decl_->prototype->param_types != nullptr ? decl_->prototype->param_types->types.size() : 0;
code->registers = num_registers_ + num_args;
code->ins_count = num_args;
- code->outs_count = decl_->prototype->return_type == dex_->GetOrAddType("V") ? 0 : 1;
EncodeInstructions();
code->instructions = slicer::ArrayView<const ::dex::u2>(buffer_.data(), buffer_.size());
+ size_t const return_count = decl_->prototype->return_type == dex_->GetOrAddType("V") ? 0 : 1;
+ code->outs_count = std::max(return_count, max_args_);
method->code = code;
class_->direct_methods.push_back(method);
@@ -240,8 +255,9 @@
void MethodBuilder::BuildReturn() { AddInstruction(Instruction::OpNoArgs(Op::kReturn)); }
-void MethodBuilder::BuildReturn(Value src) {
- AddInstruction(Instruction::OpWithArgs(Op::kReturn, /*destination=*/{}, src));
+void MethodBuilder::BuildReturn(Value src, bool is_object) {
+ AddInstruction(Instruction::OpWithArgs(
+ is_object ? Op::kReturnObject : Op::kReturn, /*destination=*/{}, src));
}
void MethodBuilder::BuildConst4(Value target, int value) {
@@ -249,6 +265,11 @@
AddInstruction(Instruction::OpWithArgs(Op::kMove, target, Value::Immediate(value)));
}
+void MethodBuilder::BuildConstString(Value target, const std::string& value) {
+ const ir::String* const dex_string = dex_->GetOrAddString(value);
+ AddInstruction(Instruction::OpWithArgs(Op::kMove, target, Value::String(dex_string->orig_index)));
+}
+
void MethodBuilder::EncodeInstructions() {
buffer_.clear();
for (const auto& instruction : instructions_) {
@@ -259,27 +280,32 @@
void MethodBuilder::EncodeInstruction(const Instruction& instruction) {
switch (instruction.opcode()) {
case Instruction::Op::kReturn:
- return EncodeReturn(instruction);
+ return EncodeReturn(instruction, ::art::Instruction::RETURN);
+ case Instruction::Op::kReturnObject:
+ return EncodeReturn(instruction, ::art::Instruction::RETURN_OBJECT);
case Instruction::Op::kMove:
return EncodeMove(instruction);
case Instruction::Op::kInvokeVirtual:
- return EncodeInvokeVirtual(instruction);
+ return EncodeInvoke(instruction, art::Instruction::INVOKE_VIRTUAL);
+ case Instruction::Op::kInvokeDirect:
+ return EncodeInvoke(instruction, art::Instruction::INVOKE_DIRECT);
case Instruction::Op::kBindLabel:
return BindLabel(instruction.args()[0]);
case Instruction::Op::kBranchEqz:
return EncodeBranch(art::Instruction::IF_EQZ, instruction);
+ case Instruction::Op::kNew:
+ return EncodeNew(instruction);
}
}
-void MethodBuilder::EncodeReturn(const Instruction& instruction) {
- DCHECK_EQ(Instruction::Op::kReturn, instruction.opcode());
+void MethodBuilder::EncodeReturn(const Instruction& instruction, ::art::Instruction::Code opcode) {
DCHECK(!instruction.dest().has_value());
if (instruction.args().size() == 0) {
- buffer_.push_back(art::Instruction::RETURN_VOID);
+ Encode10x(art::Instruction::RETURN_VOID);
} else {
- DCHECK(instruction.args().size() == 1);
+ DCHECK_EQ(1, instruction.args().size());
size_t source = RegisterValue(instruction.args()[0]);
- buffer_.push_back(art::Instruction::RETURN | source << 8);
+ Encode11x(opcode, source);
}
}
@@ -294,31 +320,43 @@
if (source.is_immediate()) {
// TODO: support more registers
DCHECK_LT(RegisterValue(*instruction.dest()), 16);
- DCHECK_LT(source.value(), 16);
- buffer_.push_back(art::Instruction::CONST_4 | (source.value() << 12) |
- (RegisterValue(*instruction.dest()) << 8));
+ Encode11n(art::Instruction::CONST_4, RegisterValue(*instruction.dest()), source.value());
+ } else if (source.is_string()) {
+ constexpr size_t kMaxRegisters = 256;
+ DCHECK_LT(RegisterValue(*instruction.dest()), kMaxRegisters);
+ DCHECK_LT(source.value(), 65536); // make sure we don't need a jumbo string
+ Encode21c(::art::Instruction::CONST_STRING, RegisterValue(*instruction.dest()), source.value());
} else {
UNIMPLEMENTED(FATAL);
}
}
-void MethodBuilder::EncodeInvokeVirtual(const Instruction& instruction) {
- DCHECK_EQ(Instruction::Op::kInvokeVirtual, instruction.opcode());
+void MethodBuilder::EncodeInvoke(const Instruction& instruction, ::art::Instruction::Code opcode) {
+ constexpr size_t kMaxArgs = 5;
- // TODO: support more than one argument (i.e. the this argument) and change this to DCHECK_GE
- DCHECK_EQ(1, instruction.args().size());
+ CHECK_LE(instruction.args().size(), kMaxArgs);
- const Value& this_arg = instruction.args()[0];
-
- size_t real_reg = RegisterValue(this_arg) & 0xf;
- buffer_.push_back(1 << 12 | art::Instruction::INVOKE_VIRTUAL);
- buffer_.push_back(instruction.method_id());
- buffer_.push_back(real_reg);
-
- if (instruction.dest().has_value()) {
- real_reg = RegisterValue(*instruction.dest());
- buffer_.push_back(real_reg << 8 | art::Instruction::MOVE_RESULT);
+ uint8_t arguments[kMaxArgs]{};
+ for (size_t i = 0; i < instruction.args().size(); ++i) {
+ CHECK(instruction.args()[i].is_variable());
+ arguments[i] = RegisterValue(instruction.args()[i]);
}
+
+ Encode35c(opcode,
+ instruction.args().size(),
+ instruction.method_id(),
+ arguments[0],
+ arguments[1],
+ arguments[2],
+ arguments[3],
+ arguments[4]);
+
+ // If there is a return value, add a move-result instruction
+ if (instruction.dest().has_value()) {
+ Encode11x(art::Instruction::MOVE_RESULT, RegisterValue(*instruction.dest()));
+ }
+
+ max_args_ = std::max(max_args_, instruction.args().size());
}
// Encodes a conditional branch that tests a single argument.
@@ -331,9 +369,21 @@
CHECK(branch_target.is_label());
size_t instruction_offset = buffer_.size();
- buffer_.push_back(op | (RegisterValue(test_value) << 8));
- size_t field_offset = buffer_.size();
- buffer_.push_back(LabelValue(branch_target, instruction_offset, field_offset));
+ size_t field_offset = buffer_.size() + 1;
+ Encode21c(
+ op, RegisterValue(test_value), LabelValue(branch_target, instruction_offset, field_offset));
+}
+
+void MethodBuilder::EncodeNew(const Instruction& instruction) {
+ DCHECK_EQ(Instruction::Op::kNew, instruction.opcode());
+ DCHECK(instruction.dest().has_value());
+ DCHECK(instruction.dest()->is_variable());
+ DCHECK_EQ(1, instruction.args().size());
+
+ const Value& type = instruction.args()[0];
+ DCHECK_LT(RegisterValue(*instruction.dest()), 256);
+ DCHECK(type.is_type());
+ Encode21c(::art::Instruction::NEW_INSTANCE, RegisterValue(*instruction.dest()), type.value());
}
size_t MethodBuilder::RegisterValue(const Value& value) const {
diff --git a/startop/view_compiler/dex_builder.h b/startop/view_compiler/dex_builder.h
index 0744151..adf82bf 100644
--- a/startop/view_compiler/dex_builder.h
+++ b/startop/view_compiler/dex_builder.h
@@ -110,18 +110,22 @@
static constexpr Value Local(size_t id) { return Value{id, Kind::kLocalRegister}; }
static constexpr Value Parameter(size_t id) { return Value{id, Kind::kParameter}; }
static constexpr Value Immediate(size_t value) { return Value{value, Kind::kImmediate}; }
+ static constexpr Value String(size_t value) { return Value{value, Kind::kString}; }
static constexpr Value Label(size_t id) { return Value{id, Kind::kLabel}; }
+ static constexpr Value Type(size_t id) { return Value{id, Kind::kType}; }
bool is_register() const { return kind_ == Kind::kLocalRegister; }
bool is_parameter() const { return kind_ == Kind::kParameter; }
bool is_variable() const { return is_register() || is_parameter(); }
bool is_immediate() const { return kind_ == Kind::kImmediate; }
+ bool is_string() const { return kind_ == Kind::kString; }
bool is_label() const { return kind_ == Kind::kLabel; }
+ bool is_type() const { return kind_ == Kind::kType; }
size_t value() const { return value_; }
private:
- enum class Kind { kLocalRegister, kParameter, kImmediate, kLabel };
+ enum class Kind { kLocalRegister, kParameter, kImmediate, kString, kLabel, kType };
const size_t value_;
const Kind kind_;
@@ -137,7 +141,16 @@
public:
// The operation performed by this instruction. These are virtual instructions that do not
// correspond exactly to DEX instructions.
- enum class Op { kReturn, kMove, kInvokeVirtual, kBindLabel, kBranchEqz };
+ enum class Op {
+ kReturn,
+ kReturnObject,
+ kMove,
+ kInvokeVirtual,
+ kInvokeDirect,
+ kBindLabel,
+ kBranchEqz,
+ kNew
+ };
////////////////////////
// Named Constructors //
@@ -158,6 +171,12 @@
Value this_arg, T... args) {
return Instruction{Op::kInvokeVirtual, method_id, dest, this_arg, args...};
}
+ // For direct calls (basically, constructors).
+ template <typename... T>
+ static inline Instruction InvokeDirect(size_t method_id, std::optional<const Value> dest,
+ Value this_arg, T... args) {
+ return Instruction{Op::kInvokeDirect, method_id, dest, this_arg, args...};
+ }
///////////////
// Accessors //
@@ -187,6 +206,12 @@
// Needed for CHECK_EQ, DCHECK_EQ, etc.
std::ostream& operator<<(std::ostream& out, const Instruction::Op& opcode);
+// Keeps track of information needed to manipulate or call a method.
+struct MethodDeclData {
+ size_t id;
+ ir::MethodDecl* decl;
+};
+
// Tools to help build methods and their bodies.
class MethodBuilder {
public:
@@ -210,19 +235,74 @@
// return-void
void BuildReturn();
- void BuildReturn(Value src);
+ void BuildReturn(Value src, bool is_object = false);
// const/4
void BuildConst4(Value target, int value);
+ void BuildConstString(Value target, const std::string& value);
+ template <typename... T>
+ void BuildNew(Value target, TypeDescriptor type, Prototype constructor, T... args);
// TODO: add builders for more instructions
private:
void EncodeInstructions();
void EncodeInstruction(const Instruction& instruction);
- void EncodeReturn(const Instruction& instruction);
+
+ // Encodes a return instruction. For instructions with no return value, the opcode field is
+ // ignored. Otherwise, this specifies which return instruction will be used (return,
+ // return-object, etc.)
+ void EncodeReturn(const Instruction& instruction, ::art::Instruction::Code opcode);
+
void EncodeMove(const Instruction& instruction);
- void EncodeInvokeVirtual(const Instruction& instruction);
+ void EncodeInvoke(const Instruction& instruction, ::art::Instruction::Code opcode);
void EncodeBranch(art::Instruction::Code op, const Instruction& instruction);
+ void EncodeNew(const Instruction& instruction);
+
+ // Low-level instruction format encoding. See
+ // https://source.android.com/devices/tech/dalvik/instruction-formats for documentation of
+ // formats.
+
+ inline void Encode10x(art::Instruction::Code opcode) {
+ // 00|op
+ buffer_.push_back(opcode);
+ }
+
+ inline void Encode11x(art::Instruction::Code opcode, uint8_t a) {
+ // aa|op
+ buffer_.push_back((a << 8) | opcode);
+ }
+
+ inline void Encode11n(art::Instruction::Code opcode, uint8_t a, int8_t b) {
+ // b|a|op
+
+ // Make sure the fields are in bounds (4 bits for a, 4 bits for b).
+ CHECK_LT(a, 16);
+ CHECK_LE(-8, b);
+ CHECK_LT(b, 8);
+
+ buffer_.push_back(((b & 0xf) << 12) | (a << 8) | opcode);
+ }
+
+ inline void Encode21c(art::Instruction::Code opcode, uint8_t a, uint16_t b) {
+ // aa|op|bbbb
+ buffer_.push_back((a << 8) | opcode);
+ buffer_.push_back(b);
+ }
+
+ inline void Encode35c(art::Instruction::Code opcode, size_t a, uint16_t b, uint8_t c, uint8_t d,
+ uint8_t e, uint8_t f, uint8_t g) {
+ // a|g|op|bbbb|f|e|d|c
+
+ CHECK_LE(a, 5);
+ CHECK_LT(c, 16);
+ CHECK_LT(d, 16);
+ CHECK_LT(e, 16);
+ CHECK_LT(f, 16);
+ CHECK_LT(g, 16);
+ buffer_.push_back((a << 12) | (g << 8) | opcode);
+ buffer_.push_back(b);
+ buffer_.push_back((f << 12) | (e << 8) | (d << 4) | c);
+ }
// Converts a register or parameter to its DEX register number.
size_t RegisterValue(const Value& value) const;
@@ -262,6 +342,10 @@
};
std::vector<LabelData> labels_;
+
+ // During encoding, keep track of the largest number of arguments needed, so we can use it for our
+ // outs count
+ size_t max_args_{0};
};
// A helper to build class definitions.
@@ -281,12 +365,6 @@
ir::Class* const class_;
};
-// Keeps track of information needed to manipulate or call a method.
-struct MethodDeclData {
- size_t id;
- ir::MethodDecl* decl;
-};
-
// Builds Dex files from scratch.
class DexBuilder {
public:
@@ -355,6 +433,17 @@
std::map<Prototype, ir::Proto*> proto_map_;
};
+template <typename... T>
+void MethodBuilder::BuildNew(Value target, TypeDescriptor type, Prototype constructor, T... args) {
+ MethodDeclData constructor_data{dex_->GetOrDeclareMethod(type, "<init>", constructor)};
+ // allocate the object
+ ir::Type* type_def = dex_->GetOrAddType(type.descriptor());
+ AddInstruction(
+ Instruction::OpWithArgs(Instruction::Op::kNew, target, Value::Type(type_def->orig_index)));
+ // call the constructor
+ AddInstruction(Instruction::InvokeDirect(constructor_data.id, /*dest=*/{}, target, args...));
+};
+
} // namespace dex
} // namespace startop
diff --git a/startop/view_compiler/dex_builder_test/src/android/startop/test/DexBuilderTest.java b/startop/view_compiler/dex_builder_test/src/android/startop/test/DexBuilderTest.java
index 169c633..e20f3a9 100644
--- a/startop/view_compiler/dex_builder_test/src/android/startop/test/DexBuilderTest.java
+++ b/startop/view_compiler/dex_builder_test/src/android/startop/test/DexBuilderTest.java
@@ -50,6 +50,14 @@
}
@Test
+ public void returnInteger5() throws Exception {
+ ClassLoader loader = loadDexFile("simple.dex");
+ Class clazz = loader.loadClass("android.startop.test.testcases.SimpleTests");
+ Method method = clazz.getMethod("returnInteger5");
+ Assert.assertEquals(5, method.invoke(null));
+ }
+
+ @Test
public void returnParam() throws Exception {
ClassLoader loader = loadDexFile("simple.dex");
Class clazz = loader.loadClass("android.startop.test.testcases.SimpleTests");
@@ -82,4 +90,38 @@
Method method = clazz.getMethod("backwardsBranch");
Assert.assertEquals(2, method.invoke(null));
}
+
+ @Test
+ public void returnNull() throws Exception {
+ ClassLoader loader = loadDexFile("simple.dex");
+ Class clazz = loader.loadClass("android.startop.test.testcases.SimpleTests");
+ Method method = clazz.getMethod("returnNull");
+ Assert.assertEquals(null, method.invoke(null));
+ }
+
+ @Test
+ public void makeString() throws Exception {
+ ClassLoader loader = loadDexFile("simple.dex");
+ Class clazz = loader.loadClass("android.startop.test.testcases.SimpleTests");
+ Method method = clazz.getMethod("makeString");
+ Assert.assertEquals("Hello, World!", method.invoke(null));
+ }
+
+ @Test
+ public void returnStringIfZeroAB() throws Exception {
+ ClassLoader loader = loadDexFile("simple.dex");
+ Class clazz = loader.loadClass("android.startop.test.testcases.SimpleTests");
+ Method method = clazz.getMethod("returnStringIfZeroAB", int.class);
+ Assert.assertEquals("a", method.invoke(null, 0));
+ Assert.assertEquals("b", method.invoke(null, 1));
+ }
+
+ @Test
+ public void returnStringIfZeroBA() throws Exception {
+ ClassLoader loader = loadDexFile("simple.dex");
+ Class clazz = loader.loadClass("android.startop.test.testcases.SimpleTests");
+ Method method = clazz.getMethod("returnStringIfZeroBA", int.class);
+ Assert.assertEquals("b", method.invoke(null, 0));
+ Assert.assertEquals("a", method.invoke(null, 1));
+ }
}
diff --git a/startop/view_compiler/dex_testcase_generator.cc b/startop/view_compiler/dex_testcase_generator.cc
index c521bf2..e2bf43bc 100644
--- a/startop/view_compiler/dex_testcase_generator.cc
+++ b/startop/view_compiler/dex_testcase_generator.cc
@@ -53,6 +53,19 @@
}
return5.Encode();
+ // int return5() { return 5; }
+ auto integer_type{TypeDescriptor::FromClassname("java.lang.Integer")};
+ auto returnInteger5{cbuilder.CreateMethod("returnInteger5", Prototype{integer_type})};
+ [&](MethodBuilder& method) {
+ Value five{method.MakeRegister()};
+ method.BuildConst4(five, 5);
+ Value object{method.MakeRegister()};
+ method.BuildNew(
+ object, integer_type, Prototype{TypeDescriptor::Void(), TypeDescriptor::Int()}, five);
+ method.BuildReturn(object, /*is_object=*/true);
+ }(returnInteger5);
+ returnInteger5.Encode();
+
// // int returnParam(int x) { return x; }
auto returnParam{cbuilder.CreateMethod("returnParam",
Prototype{TypeDescriptor::Int(), TypeDescriptor::Int()})};
@@ -138,6 +151,71 @@
}(backwardsBranch);
backwardsBranch.Encode();
+ // Test that we can make a null value. Basically:
+ //
+ // public static String returnNull() { return null; }
+ MethodBuilder returnNull{cbuilder.CreateMethod("returnNull", Prototype{string_type})};
+ [](MethodBuilder& method) {
+ Value zero = method.MakeRegister();
+ method.BuildConst4(zero, 0);
+ method.BuildReturn(zero, /*is_object=*/true);
+ }(returnNull);
+ returnNull.Encode();
+
+ // Test that we can make String literals. Basically:
+ //
+ // public static String makeString() { return "Hello, World!"; }
+ MethodBuilder makeString{cbuilder.CreateMethod("makeString", Prototype{string_type})};
+ [](MethodBuilder& method) {
+ Value string = method.MakeRegister();
+ method.BuildConstString(string, "Hello, World!");
+ method.BuildReturn(string, /*is_object=*/true);
+ }(makeString);
+ makeString.Encode();
+
+ // Make sure strings are sorted correctly.
+ //
+ // int returnStringIfZeroAB(int x) { if (x == 0) { return "a"; } else { return "b"; } }
+ MethodBuilder returnStringIfZeroAB{
+ cbuilder.CreateMethod("returnStringIfZeroAB", Prototype{string_type, TypeDescriptor::Int()})};
+ [&](MethodBuilder& method) {
+ Value resultIfZero{method.MakeRegister()};
+ Value else_target{method.MakeLabel()};
+ method.AddInstruction(Instruction::OpWithArgs(
+ Instruction::Op::kBranchEqz, /*dest=*/{}, Value::Parameter(0), else_target));
+ // else branch
+ method.BuildConstString(resultIfZero, "b");
+ method.AddInstruction(
+ Instruction::OpWithArgs(Instruction::Op::kReturnObject, /*dest=*/{}, resultIfZero));
+ // then branch
+ method.AddInstruction(
+ Instruction::OpWithArgs(Instruction::Op::kBindLabel, /*dest=*/{}, else_target));
+ method.BuildConstString(resultIfZero, "a");
+ method.AddInstruction(
+ Instruction::OpWithArgs(Instruction::Op::kReturnObject, /*dest=*/{}, resultIfZero));
+ method.Encode();
+ }(returnStringIfZeroAB);
+ // int returnStringIfZeroAB(int x) { if (x == 0) { return "b"; } else { return "a"; } }
+ MethodBuilder returnStringIfZeroBA{
+ cbuilder.CreateMethod("returnStringIfZeroBA", Prototype{string_type, TypeDescriptor::Int()})};
+ [&](MethodBuilder& method) {
+ Value resultIfZero{method.MakeRegister()};
+ Value else_target{method.MakeLabel()};
+ method.AddInstruction(Instruction::OpWithArgs(
+ Instruction::Op::kBranchEqz, /*dest=*/{}, Value::Parameter(0), else_target));
+ // else branch
+ method.BuildConstString(resultIfZero, "a");
+ method.AddInstruction(
+ Instruction::OpWithArgs(Instruction::Op::kReturnObject, /*dest=*/{}, resultIfZero));
+ // then branch
+ method.AddInstruction(
+ Instruction::OpWithArgs(Instruction::Op::kBindLabel, /*dest=*/{}, else_target));
+ method.BuildConstString(resultIfZero, "b");
+ method.AddInstruction(
+ Instruction::OpWithArgs(Instruction::Op::kReturnObject, /*dest=*/{}, resultIfZero));
+ method.Encode();
+ }(returnStringIfZeroBA);
+
slicer::MemView image{dex_file.CreateImage()};
std::ofstream out_file(outdir + "/simple.dex");
out_file.write(image.ptr<const char>(), image.size());
diff --git a/telephony/java/android/provider/Telephony.java b/telephony/java/android/provider/Telephony.java
index 6d3345e..efea817 100644
--- a/telephony/java/android/provider/Telephony.java
+++ b/telephony/java/android/provider/Telephony.java
@@ -16,6 +16,7 @@
package android.provider;
+import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
@@ -1209,6 +1210,30 @@
"android.provider.extra.IS_INITIAL_CREATE";
/**
+ * Broadcast intent action indicating that the telephony provider SMS MMS database is
+ * corrupted. A boolean is specified in {@link #EXTRA_IS_CORRUPTED} to indicate if the
+ * database is corrupted. Requires the
+ * {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE permission.
+ *
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ public static final String ACTION_SMS_MMS_DB_LOST =
+ "android.provider.action.SMS_MMS_DB_LOST";
+
+ /**
+ * Boolean flag passed as an extra with {@link #ACTION_SMS_MMS_DB_LOST} to indicate
+ * whether the DB got corrupted or not.
+ *
+ * @see #ACTION_SMS_MMS_DB_LOST
+ *
+ * @hide
+ */
+ public static final String EXTRA_IS_CORRUPTED =
+ "android.provider.extra.IS_CORRUPTED";
+
+ /**
* Read the PDUs out of an {@link #SMS_RECEIVED_ACTION} or a
* {@link #DATA_SMS_RECEIVED_ACTION} intent.
*
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 0280a75..90c15ff 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -1277,20 +1277,11 @@
public static final String KEY_WORLD_MODE_ENABLED_BOOL = "world_mode_enabled_bool";
/**
- * Package name of the carrier settings activity.
- * @see {@link #KEY_CARRIER_SETTINGS_ACTIVITY_CLASS_NAME_STRING}.
+ * Flatten {@link android.content.ComponentName} of the carrier's settings activity.
* @hide
*/
- public static final String KEY_CARRIER_SETTINGS_ACTIVITY_PACKAGE_NAME_STRING =
- "carrier_settings_activity_package_name_string";
-
- /**
- * Class name of the carrier settings activity.
- * @see {@link #KEY_CARRIER_SETTINGS_ACTIVITY_PACKAGE_NAME_STRING}.
- * @hide
- */
- public static final String KEY_CARRIER_SETTINGS_ACTIVITY_CLASS_NAME_STRING =
- "carrier_settings_activity_class_name_string";
+ public static final String KEY_CARRIER_SETTINGS_ACTIVITY_COMPONENT_NAME_STRING =
+ "carrier_settings_activity_component_name_string";
// These variables are used by the MMS service and exposed through another API,
// SmsManager. The variable names and string values are copied from there.
@@ -1329,18 +1320,13 @@
public static final String KEY_MMS_CLOSE_CONNECTION_BOOL = "mmsCloseConnection";
/**
- * If carriers require differentiate un-provisioned status: cold sim or out of credit sim
- * a package name and activity name can be provided to launch a supported carrier application
- * that check the sim provisioning status
- * The first element is the package name and the second element is the activity name
- * of the provisioning app
- * example:
- * <item>com.google.android.carrierPackageName</item>
- * <item>com.google.android.carrierPackageName.CarrierActivityName</item>
- * The ComponentName of the carrier activity that can setup the device and activate with the
- * network as part of the Setup Wizard flow.
+ * The flatten {@link android.content.ComponentName componentName} of the activity that can
+ * setup the device and activate with the network per carrier requirements.
+ *
+ * e.g, com.google.android.carrierPackageName/.CarrierActivityName
* @hide
*/
+ @SystemApi
public static final String KEY_CARRIER_SETUP_APP_STRING = "carrier_setup_app_string";
/**
@@ -2637,8 +2623,7 @@
sDefaults.putBoolean(KEY_SUPPORT_TDSCDMA_BOOL, false);
sDefaults.putStringArray(KEY_SUPPORT_TDSCDMA_ROAMING_NETWORKS_STRING_ARRAY, null);
sDefaults.putBoolean(KEY_WORLD_MODE_ENABLED_BOOL, false);
- sDefaults.putString(KEY_CARRIER_SETTINGS_ACTIVITY_PACKAGE_NAME_STRING, "");
- sDefaults.putString(KEY_CARRIER_SETTINGS_ACTIVITY_CLASS_NAME_STRING, "");
+ sDefaults.putString(KEY_CARRIER_SETTINGS_ACTIVITY_COMPONENT_NAME_STRING, "");
sDefaults.putBoolean(KEY_CARRIER_CONFIG_APPLIED_BOOL, false);
sDefaults.putBoolean(KEY_CHECK_PRICING_WITH_CARRIER_FOR_DATA_ROAMING_BOOL, false);
sDefaults.putIntArray(KEY_LTE_RSRP_THRESHOLDS_INT_ARRAY,
diff --git a/telephony/java/android/telephony/CellConfigLte.java b/telephony/java/android/telephony/CellConfigLte.java
new file mode 100644
index 0000000..35769f0
--- /dev/null
+++ b/telephony/java/android/telephony/CellConfigLte.java
@@ -0,0 +1,105 @@
+/*
+ * 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;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/**
+ * The container of LTE cell related configs.
+ * @hide
+ */
+public class CellConfigLte implements Parcelable {
+ private final boolean mIsEndcAvailable;
+
+ /** @hide */
+ public CellConfigLte() {
+ mIsEndcAvailable = false;
+ }
+
+ /** @hide */
+ public CellConfigLte(boolean isEndcAvailable) {
+ mIsEndcAvailable = isEndcAvailable;
+ }
+
+ /** @hide */
+ public CellConfigLte(CellConfigLte config) {
+ mIsEndcAvailable = config.mIsEndcAvailable;
+ }
+
+ /**
+ * Indicates that if E-UTRA-NR Dual Connectivity (EN-DC) is supported by the LTE cell.
+ *
+ * Reference: 3GPP TS 36.331 v15.2.2 6.3.1 System information blocks.
+ *
+ * @return {@code true} if E-UTRA-NR Dual Connectivity (EN-DC) is supported by the LTE cell.
+ *
+ */
+ boolean isEndcAvailable() {
+ return mIsEndcAvailable;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mIsEndcAvailable);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (!(other instanceof CellConfigLte)) return false;
+
+ CellConfigLte o = (CellConfigLte) other;
+ return mIsEndcAvailable == o.mIsEndcAvailable;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeBoolean(mIsEndcAvailable);
+ }
+
+ @Override
+ public String toString() {
+ return new StringBuilder().append(this.getClass().getName())
+ .append(" :{")
+ .append(" isEndcAvailable = " + mIsEndcAvailable)
+ .append(" }")
+ .toString();
+ }
+
+ private CellConfigLte(Parcel in) {
+ mIsEndcAvailable = in.readBoolean();
+ }
+
+ public static final Creator<CellConfigLte> CREATOR = new Creator<CellConfigLte>() {
+ @Override
+ public CellConfigLte createFromParcel(Parcel in) {
+ return new CellConfigLte(in);
+ }
+
+ @Override
+ public CellConfigLte[] newArray(int size) {
+ return new CellConfigLte[0];
+ }
+ };
+}
diff --git a/telephony/java/android/telephony/CellInfoLte.java b/telephony/java/android/telephony/CellInfoLte.java
index 389f643..7d5388b 100644
--- a/telephony/java/android/telephony/CellInfoLte.java
+++ b/telephony/java/android/telephony/CellInfoLte.java
@@ -19,7 +19,8 @@
import android.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
-import android.telephony.Rlog;
+
+import java.util.Objects;
/**
* A {@link CellInfo} representing an LTE cell that provides identity and measurement info.
@@ -31,6 +32,7 @@
private CellIdentityLte mCellIdentityLte;
private CellSignalStrengthLte mCellSignalStrengthLte;
+ private CellConfigLte mCellConfig;
/** @hide */
@UnsupportedAppUsage
@@ -38,6 +40,7 @@
super();
mCellIdentityLte = new CellIdentityLte();
mCellSignalStrengthLte = new CellSignalStrengthLte();
+ mCellConfig = new CellConfigLte();
}
/** @hide */
@@ -45,6 +48,7 @@
super(ci);
this.mCellIdentityLte = ci.mCellIdentityLte.copy();
this.mCellSignalStrengthLte = ci.mCellSignalStrengthLte.copy();
+ this.mCellConfig = new CellConfigLte(ci.mCellConfig);
}
@Override
@@ -71,26 +75,37 @@
mCellSignalStrengthLte = css;
}
+ /** @hide */
+ public void setCellConfig(CellConfigLte cellConfig) {
+ if (DBG) log("setCellConfig: " + cellConfig);
+ mCellConfig = cellConfig;
+ }
+
+ /** @hide */
+ public CellConfigLte getCellConfig() {
+ if (DBG) log("getCellConfig: " + mCellConfig);
+ return mCellConfig;
+ }
+
/**
* @return hash code
*/
@Override
public int hashCode() {
- return super.hashCode() + mCellIdentityLte.hashCode() + mCellSignalStrengthLte.hashCode();
+ return Objects.hash(
+ super.hashCode(),
+ mCellIdentityLte.hashCode(),
+ mCellSignalStrengthLte.hashCode(),
+ mCellConfig.hashCode());
}
@Override
public boolean equals(Object other) {
- if (!super.equals(other)) {
- return false;
- }
- try {
- CellInfoLte o = (CellInfoLte) other;
- return mCellIdentityLte.equals(o.mCellIdentityLte)
- && mCellSignalStrengthLte.equals(o.mCellSignalStrengthLte);
- } catch (ClassCastException e) {
- return false;
- }
+ if (!(other instanceof CellInfoLte)) return false;
+ CellInfoLte o = (CellInfoLte) other;
+ return super.equals(o) && mCellIdentityLte.equals(o.mCellIdentityLte)
+ && mCellSignalStrengthLte.equals(o.mCellSignalStrengthLte)
+ && mCellConfig.equals(o.mCellConfig);
}
@Override
@@ -101,6 +116,7 @@
sb.append(super.toString());
sb.append(" ").append(mCellIdentityLte);
sb.append(" ").append(mCellSignalStrengthLte);
+ sb.append(" ").append(mCellConfig);
sb.append("}");
return sb.toString();
@@ -119,6 +135,7 @@
super.writeToParcel(dest, flags, TYPE_LTE);
mCellIdentityLte.writeToParcel(dest, flags);
mCellSignalStrengthLte.writeToParcel(dest, flags);
+ mCellConfig.writeToParcel(dest, flags);
}
/**
@@ -129,6 +146,7 @@
super(in);
mCellIdentityLte = CellIdentityLte.CREATOR.createFromParcel(in);
mCellSignalStrengthLte = CellSignalStrengthLte.CREATOR.createFromParcel(in);
+ mCellConfig = CellConfigLte.CREATOR.createFromParcel(in);
if (DBG) log("CellInfoLte(Parcel): " + toString());
}
diff --git a/telephony/java/android/telephony/CellSignalStrength.java b/telephony/java/android/telephony/CellSignalStrength.java
index 2a3ef21..afa4922 100644
--- a/telephony/java/android/telephony/CellSignalStrength.java
+++ b/telephony/java/android/telephony/CellSignalStrength.java
@@ -21,15 +21,20 @@
*/
public abstract class CellSignalStrength {
- public static final int SIGNAL_STRENGTH_NONE_OR_UNKNOWN = 0;
+ public static final int SIGNAL_STRENGTH_NONE_OR_UNKNOWN =
+ TelephonyProtoEnums.SIGNAL_STRENGTH_NONE_OR_UNKNOWN; // 0
- public static final int SIGNAL_STRENGTH_POOR = 1;
+ public static final int SIGNAL_STRENGTH_POOR =
+ TelephonyProtoEnums.SIGNAL_STRENGTH_POOR; // 1
- public static final int SIGNAL_STRENGTH_MODERATE = 2;
+ public static final int SIGNAL_STRENGTH_MODERATE =
+ TelephonyProtoEnums.SIGNAL_STRENGTH_MODERATE; // 2
- public static final int SIGNAL_STRENGTH_GOOD = 3;
+ public static final int SIGNAL_STRENGTH_GOOD =
+ TelephonyProtoEnums.SIGNAL_STRENGTH_GOOD; // 3
- public static final int SIGNAL_STRENGTH_GREAT = 4;
+ public static final int SIGNAL_STRENGTH_GREAT =
+ TelephonyProtoEnums.SIGNAL_STRENGTH_GREAT; // 4
/** @hide */
public static final int NUM_SIGNAL_STRENGTH_BINS = 5;
diff --git a/telephony/java/android/telephony/DataSpecificRegistrationStates.java b/telephony/java/android/telephony/DataSpecificRegistrationStates.java
index 97e3037b..b6e6cba 100644
--- a/telephony/java/android/telephony/DataSpecificRegistrationStates.java
+++ b/telephony/java/android/telephony/DataSpecificRegistrationStates.java
@@ -17,17 +17,40 @@
*/
public final int maxDataCalls;
- DataSpecificRegistrationStates(int maxDataCalls) {
+ /**
+ * Indicates if the use of dual connectivity with NR is restricted.
+ * Reference: 3GPP TS 24.301 v15.03 section 9.3.3.12A.
+ */
+ public final boolean isDcNrRestricted;
+
+ /**
+ * Indicates if NR is supported by the selected PLMN.
+ *
+ * {@code true} if the bit N is in the PLMN-InfoList-r15 is true and the selected PLMN is
+ * present in plmn-IdentityList at position N.
+ * Reference: 3GPP TS 36.331 v15.2.2 section 6.3.1 PLMN-InfoList-r15.
+ * 3GPP TS 36.331 v15.2.2 section 6.2.2 SystemInformationBlockType1 message.
+ */
+ public final boolean isNrAvailable;
+
+ DataSpecificRegistrationStates(
+ int maxDataCalls, boolean isDcNrRestricted, boolean isNrAvailable) {
this.maxDataCalls = maxDataCalls;
+ this.isDcNrRestricted = isDcNrRestricted;
+ this.isNrAvailable = isNrAvailable;
}
private DataSpecificRegistrationStates(Parcel source) {
maxDataCalls = source.readInt();
+ isDcNrRestricted = source.readBoolean();
+ isNrAvailable = source.readBoolean();
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(maxDataCalls);
+ dest.writeBoolean(isDcNrRestricted);
+ dest.writeBoolean(isNrAvailable);
}
@Override
@@ -37,24 +60,30 @@
@Override
public String toString() {
- return "DataSpecificRegistrationStates {" + " mMaxDataCalls=" + maxDataCalls + "}";
+ return new StringBuilder().append(this.getClass().getName())
+ .append(" :{")
+ .append(" maxDataCalls = " + maxDataCalls)
+ .append(" isDcNrRestricted = " + isDcNrRestricted)
+ .append(" isNrAvailable = " + isNrAvailable)
+ .append(" }")
+ .toString();
}
@Override
public int hashCode() {
- return Objects.hash(maxDataCalls);
+ return Objects.hash(maxDataCalls, isDcNrRestricted, isNrAvailable);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
- if (o == null || !(o instanceof DataSpecificRegistrationStates)) {
- return false;
- }
+ if (!(o instanceof DataSpecificRegistrationStates)) return false;
DataSpecificRegistrationStates other = (DataSpecificRegistrationStates) o;
- return this.maxDataCalls == other.maxDataCalls;
+ return this.maxDataCalls == other.maxDataCalls
+ && this.isDcNrRestricted == other.isDcNrRestricted
+ && this.isNrAvailable == other.isNrAvailable;
}
public static final Parcelable.Creator<DataSpecificRegistrationStates> CREATOR =
diff --git a/telephony/java/android/telephony/NetworkRegistrationState.java b/telephony/java/android/telephony/NetworkRegistrationState.java
index 68e512e..75e8eda 100644
--- a/telephony/java/android/telephony/NetworkRegistrationState.java
+++ b/telephony/java/android/telephony/NetworkRegistrationState.java
@@ -161,11 +161,9 @@
* @hide
*/
public NetworkRegistrationState(int domain, int transportType, int regState,
- int accessNetworkTechnology, int rejectCause,
- boolean emergencyOnly, int[] availableServices,
- @Nullable CellIdentity cellIdentity, boolean cssSupported,
- int roamingIndicator, int systemIsInPrl,
- int defaultRoamingIndicator) {
+ int accessNetworkTechnology, int rejectCause, boolean emergencyOnly,
+ int[] availableServices, @Nullable CellIdentity cellIdentity, boolean cssSupported,
+ int roamingIndicator, int systemIsInPrl, int defaultRoamingIndicator) {
this(domain, transportType, regState, accessNetworkTechnology, rejectCause, emergencyOnly,
availableServices, cellIdentity);
@@ -178,13 +176,14 @@
* @hide
*/
public NetworkRegistrationState(int domain, int transportType, int regState,
- int accessNetworkTechnology, int rejectCause,
- boolean emergencyOnly, int[] availableServices,
- @Nullable CellIdentity cellIdentity, int maxDataCalls) {
+ int accessNetworkTechnology, int rejectCause, boolean emergencyOnly,
+ int[] availableServices, @Nullable CellIdentity cellIdentity, int maxDataCalls,
+ boolean isDcNrRestricted, boolean isNrAvailable) {
this(domain, transportType, regState, accessNetworkTechnology, rejectCause, emergencyOnly,
availableServices, cellIdentity);
- mDataSpecificStates = new DataSpecificRegistrationStates(maxDataCalls);
+ mDataSpecificStates = new DataSpecificRegistrationStates(
+ maxDataCalls, isDcNrRestricted, isNrAvailable);
}
protected NetworkRegistrationState(Parcel source) {
@@ -345,7 +344,7 @@
public boolean equals(Object o) {
if (this == o) return true;
- if (o == null || !(o instanceof NetworkRegistrationState)) {
+ if (!(o instanceof NetworkRegistrationState)) {
return false;
}
@@ -357,11 +356,10 @@
&& mAccessNetworkTechnology == other.mAccessNetworkTechnology
&& mRejectCause == other.mRejectCause
&& mEmergencyOnly == other.mEmergencyOnly
- && (mAvailableServices == other.mAvailableServices
- || Arrays.equals(mAvailableServices, other.mAvailableServices))
- && equals(mCellIdentity, other.mCellIdentity)
- && equals(mVoiceSpecificStates, other.mVoiceSpecificStates)
- && equals(mDataSpecificStates, other.mDataSpecificStates);
+ && Arrays.equals(mAvailableServices, other.mAvailableServices)
+ && Objects.equals(mCellIdentity, other.mCellIdentity)
+ && Objects.equals(mVoiceSpecificStates, other.mVoiceSpecificStates)
+ && Objects.equals(mDataSpecificStates, other.mDataSpecificStates);
}
@Override
@@ -391,14 +389,4 @@
return new NetworkRegistrationState[size];
}
};
-
- private static boolean equals(Object o1, Object o2) {
- if (o1 == o2) {
- return true;
- } else if (o1 == null) {
- return false;
- } else {
- return o1.equals(o2);
- }
- }
}
diff --git a/telephony/java/android/telephony/PhoneStateListener.java b/telephony/java/android/telephony/PhoneStateListener.java
index f5dff20..3c5ad84 100644
--- a/telephony/java/android/telephony/PhoneStateListener.java
+++ b/telephony/java/android/telephony/PhoneStateListener.java
@@ -21,16 +21,18 @@
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.UnsupportedAppUsage;
+import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
+import android.os.HandlerExecutor;
import android.os.Looper;
-import android.os.Message;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.IPhoneStateListener;
import java.lang.ref.WeakReference;
import java.util.List;
+import java.util.concurrent.Executor;
/**
* A listener class for monitoring changes in specific telephony states
@@ -231,34 +233,35 @@
public static final int LISTEN_CARRIER_NETWORK_CHANGE = 0x00010000;
/**
- * Listen for changes to the sim voice activation state
- * @see TelephonyManager#SIM_ACTIVATION_STATE_ACTIVATING
- * @see TelephonyManager#SIM_ACTIVATION_STATE_ACTIVATED
- * @see TelephonyManager#SIM_ACTIVATION_STATE_DEACTIVATED
- * @see TelephonyManager#SIM_ACTIVATION_STATE_RESTRICTED
- * @see TelephonyManager#SIM_ACTIVATION_STATE_UNKNOWN
- * {@more}
- * Example: TelephonyManager#SIM_ACTIVATION_STATE_ACTIVATED indicates voice service has been
- * fully activated
+ * Listen for changes to the sim voice activation state
+ * @see TelephonyManager#SIM_ACTIVATION_STATE_ACTIVATING
+ * @see TelephonyManager#SIM_ACTIVATION_STATE_ACTIVATED
+ * @see TelephonyManager#SIM_ACTIVATION_STATE_DEACTIVATED
+ * @see TelephonyManager#SIM_ACTIVATION_STATE_RESTRICTED
+ * @see TelephonyManager#SIM_ACTIVATION_STATE_UNKNOWN
+ * {@more}
+ * Example: TelephonyManager#SIM_ACTIVATION_STATE_ACTIVATED indicates voice service has been
+ * fully activated
*
- * @see #onVoiceActivationStateChanged
- * @hide
+ * @see #onVoiceActivationStateChanged
+ * @hide
*/
+ @SystemApi
public static final int LISTEN_VOICE_ACTIVATION_STATE = 0x00020000;
/**
- * Listen for changes to the sim data activation state
- * @see TelephonyManager#SIM_ACTIVATION_STATE_ACTIVATING
- * @see TelephonyManager#SIM_ACTIVATION_STATE_ACTIVATED
- * @see TelephonyManager#SIM_ACTIVATION_STATE_DEACTIVATED
- * @see TelephonyManager#SIM_ACTIVATION_STATE_RESTRICTED
- * @see TelephonyManager#SIM_ACTIVATION_STATE_UNKNOWN
- * {@more}
- * Example: TelephonyManager#SIM_ACTIVATION_STATE_ACTIVATED indicates data service has been
- * fully activated
+ * Listen for changes to the sim data activation state
+ * @see TelephonyManager#SIM_ACTIVATION_STATE_ACTIVATING
+ * @see TelephonyManager#SIM_ACTIVATION_STATE_ACTIVATED
+ * @see TelephonyManager#SIM_ACTIVATION_STATE_DEACTIVATED
+ * @see TelephonyManager#SIM_ACTIVATION_STATE_RESTRICTED
+ * @see TelephonyManager#SIM_ACTIVATION_STATE_UNKNOWN
+ * {@more}
+ * Example: TelephonyManager#SIM_ACTIVATION_STATE_ACTIVATED indicates data service has been
+ * fully activated
*
- * @see #onDataActivationStateChanged
- * @hide
+ * @see #onDataActivationStateChanged
+ * @hide
*/
public static final int LISTEN_DATA_ACTIVATION_STATE = 0x00040000;
@@ -320,7 +323,12 @@
@UnsupportedAppUsage
protected Integer mSubId;
- private final Handler mHandler;
+ /**
+ * @hide
+ */
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+ @UnsupportedAppUsage
+ public final IPhoneStateListener callback;
/**
* Create a PhoneStateListener for the Phone with the default subscription.
@@ -358,95 +366,27 @@
*/
@UnsupportedAppUsage
public PhoneStateListener(Integer subId, Looper looper) {
- if (DBG) log("ctor: subId=" + subId + " looper=" + looper);
+ this(subId, new HandlerExecutor(new Handler(looper)));
+ }
+
+ /**
+ * Create a PhoneStateListener for the Phone using the specified Executor
+ *
+ * <p>Create a PhoneStateListener with a specified Executor for handling necessary callbacks.
+ * The Executor must not be null.
+ *
+ * @param executor a non-null Executor that will execute callbacks for the PhoneStateListener.
+ */
+ public PhoneStateListener(@NonNull Executor executor) {
+ this(null, executor);
+ }
+
+ private PhoneStateListener(Integer subId, Executor e) {
+ if (e == null) {
+ throw new IllegalArgumentException("PhoneStateListener Executor must be non-null");
+ }
mSubId = subId;
- mHandler = new Handler(looper) {
- public void handleMessage(Message msg) {
- if (DBG) {
- log("mSubId=" + mSubId + " what=0x" + Integer.toHexString(msg.what)
- + " msg=" + msg);
- }
- switch (msg.what) {
- case LISTEN_SERVICE_STATE:
- PhoneStateListener.this.onServiceStateChanged((ServiceState)msg.obj);
- break;
- case LISTEN_SIGNAL_STRENGTH:
- PhoneStateListener.this.onSignalStrengthChanged(msg.arg1);
- break;
- case LISTEN_MESSAGE_WAITING_INDICATOR:
- PhoneStateListener.this.onMessageWaitingIndicatorChanged(msg.arg1 != 0);
- break;
- case LISTEN_CALL_FORWARDING_INDICATOR:
- PhoneStateListener.this.onCallForwardingIndicatorChanged(msg.arg1 != 0);
- break;
- case LISTEN_CELL_LOCATION:
- PhoneStateListener.this.onCellLocationChanged((CellLocation)msg.obj);
- break;
- case LISTEN_CALL_STATE:
- PhoneStateListener.this.onCallStateChanged(msg.arg1, (String)msg.obj);
- break;
- case LISTEN_DATA_CONNECTION_STATE:
- PhoneStateListener.this.onDataConnectionStateChanged(msg.arg1, msg.arg2);
- PhoneStateListener.this.onDataConnectionStateChanged(msg.arg1);
- break;
- case LISTEN_DATA_ACTIVITY:
- PhoneStateListener.this.onDataActivity(msg.arg1);
- break;
- case LISTEN_SIGNAL_STRENGTHS:
- PhoneStateListener.this.onSignalStrengthsChanged((SignalStrength)msg.obj);
- break;
- case LISTEN_OTASP_CHANGED:
- PhoneStateListener.this.onOtaspChanged(msg.arg1);
- break;
- case LISTEN_CELL_INFO:
- PhoneStateListener.this.onCellInfoChanged((List<CellInfo>)msg.obj);
- break;
- case LISTEN_PRECISE_CALL_STATE:
- PhoneStateListener.this.onPreciseCallStateChanged((PreciseCallState)msg.obj);
- break;
- case LISTEN_PRECISE_DATA_CONNECTION_STATE:
- PhoneStateListener.this.onPreciseDataConnectionStateChanged(
- (PreciseDataConnectionState)msg.obj);
- break;
- case LISTEN_DATA_CONNECTION_REAL_TIME_INFO:
- PhoneStateListener.this.onDataConnectionRealTimeInfoChanged(
- (DataConnectionRealTimeInfo)msg.obj);
- break;
- case LISTEN_SRVCC_STATE_CHANGED:
- PhoneStateListener.this.onSrvccStateChanged((int) msg.obj);
- break;
- case LISTEN_VOICE_ACTIVATION_STATE:
- PhoneStateListener.this.onVoiceActivationStateChanged((int)msg.obj);
- break;
- 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_OEM_HOOK_RAW_EVENT:
- PhoneStateListener.this.onOemHookRawEvent((byte[])msg.obj);
- break;
- case LISTEN_CARRIER_NETWORK_CHANGE:
- PhoneStateListener.this.onCarrierNetworkChange((boolean)msg.obj);
- break;
- case LISTEN_PHYSICAL_CHANNEL_CONFIGURATION:
- PhoneStateListener.this.onPhysicalChannelConfigurationChanged(
- (List<PhysicalChannelConfig>)msg.obj);
- break;
- case LISTEN_PHONE_CAPABILITY_CHANGE:
- PhoneStateListener.this.onPhoneCapabilityChanged(
- (PhoneCapability) msg.obj);
- break;
- case LISTEN_PREFERRED_DATA_SUBID_CHANGE:
- PhoneStateListener.this.onPreferredDataSubIdChanged((int) msg.obj);
- break;
- case LISTEN_RADIO_POWER_STATE_CHANGED:
- PhoneStateListener.this.onRadioPowerStateChanged((int) msg.obj);
- break;
- }
- }
- };
+ callback = new IPhoneStateListenerStub(this, e);
}
/**
@@ -630,8 +570,8 @@
* @param state is the current SIM voice activation state
* @hide
*/
- public void onVoiceActivationStateChanged(int state) {
-
+ @SystemApi
+ public void onVoiceActivationStateChanged(@TelephonyManager.SimActivationState int state) {
}
/**
@@ -639,8 +579,7 @@
* @param state is the current SIM data activation state
* @hide
*/
- public void onDataActivationStateChanged(int state) {
-
+ public void onDataActivationStateChanged(@TelephonyManager.SimActivationState int state) {
}
/**
@@ -735,127 +674,217 @@
*/
private static class IPhoneStateListenerStub extends IPhoneStateListener.Stub {
private WeakReference<PhoneStateListener> mPhoneStateListenerWeakRef;
+ private Executor mExecutor;
- public IPhoneStateListenerStub(PhoneStateListener phoneStateListener) {
+ IPhoneStateListenerStub(PhoneStateListener phoneStateListener, Executor executor) {
mPhoneStateListenerWeakRef = new WeakReference<PhoneStateListener>(phoneStateListener);
- }
-
- private void send(int what, int arg1, int arg2, Object obj) {
- PhoneStateListener listener = mPhoneStateListenerWeakRef.get();
- if (listener != null) {
- Message.obtain(listener.mHandler, what, arg1, arg2, obj).sendToTarget();
- }
+ mExecutor = executor;
}
public void onServiceStateChanged(ServiceState serviceState) {
- send(LISTEN_SERVICE_STATE, 0, 0, serviceState);
+ PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+ if (psl == null) return;
+
+ Binder.withCleanCallingIdentity(
+ () -> mExecutor.execute(() -> psl.onServiceStateChanged(serviceState)));
}
public void onSignalStrengthChanged(int asu) {
- send(LISTEN_SIGNAL_STRENGTH, asu, 0, null);
+ PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+ if (psl == null) return;
+
+ Binder.withCleanCallingIdentity(
+ () -> mExecutor.execute(() -> psl.onSignalStrengthChanged(asu)));
}
public void onMessageWaitingIndicatorChanged(boolean mwi) {
- send(LISTEN_MESSAGE_WAITING_INDICATOR, mwi ? 1 : 0, 0, null);
+ PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+ if (psl == null) return;
+
+ Binder.withCleanCallingIdentity(
+ () -> mExecutor.execute(() -> psl.onMessageWaitingIndicatorChanged(mwi)));
}
public void onCallForwardingIndicatorChanged(boolean cfi) {
- send(LISTEN_CALL_FORWARDING_INDICATOR, cfi ? 1 : 0, 0, null);
+ PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+ if (psl == null) return;
+
+ Binder.withCleanCallingIdentity(
+ () -> mExecutor.execute(() -> psl.onCallForwardingIndicatorChanged(cfi)));
}
public void onCellLocationChanged(Bundle bundle) {
CellLocation location = CellLocation.newFromBundle(bundle);
- send(LISTEN_CELL_LOCATION, 0, 0, location);
+ PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+ if (psl == null) return;
+
+ Binder.withCleanCallingIdentity(
+ () -> mExecutor.execute(() -> psl.onCellLocationChanged(location)));
}
public void onCallStateChanged(int state, String incomingNumber) {
- send(LISTEN_CALL_STATE, state, 0, incomingNumber);
+ PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+ if (psl == null) return;
+
+ Binder.withCleanCallingIdentity(
+ () -> mExecutor.execute(() -> psl.onCallStateChanged(state, incomingNumber)));
}
public void onDataConnectionStateChanged(int state, int networkType) {
- send(LISTEN_DATA_CONNECTION_STATE, state, networkType, null);
+ PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+ if (psl == null) return;
+
+ Binder.withCleanCallingIdentity(
+ () -> mExecutor.execute(
+ () -> psl.onDataConnectionStateChanged(state, networkType)));
}
public void onDataActivity(int direction) {
- send(LISTEN_DATA_ACTIVITY, direction, 0, null);
+ PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+ if (psl == null) return;
+
+ Binder.withCleanCallingIdentity(
+ () -> mExecutor.execute(() -> psl.onDataActivity(direction)));
}
public void onSignalStrengthsChanged(SignalStrength signalStrength) {
- send(LISTEN_SIGNAL_STRENGTHS, 0, 0, signalStrength);
+ PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+ if (psl == null) return;
+
+ Binder.withCleanCallingIdentity(
+ () -> mExecutor.execute(() -> psl.onSignalStrengthsChanged(signalStrength)));
}
public void onOtaspChanged(int otaspMode) {
- send(LISTEN_OTASP_CHANGED, otaspMode, 0, null);
+ PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+ if (psl == null) return;
+
+ Binder.withCleanCallingIdentity(
+ () -> mExecutor.execute(() -> psl.onOtaspChanged(otaspMode)));
}
public void onCellInfoChanged(List<CellInfo> cellInfo) {
- send(LISTEN_CELL_INFO, 0, 0, cellInfo);
+ PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+ if (psl == null) return;
+
+ Binder.withCleanCallingIdentity(
+ () -> mExecutor.execute(() -> psl.onCellInfoChanged(cellInfo)));
}
public void onPreciseCallStateChanged(PreciseCallState callState) {
- send(LISTEN_PRECISE_CALL_STATE, 0, 0, callState);
+ PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+ if (psl == null) return;
+
+ Binder.withCleanCallingIdentity(
+ () -> mExecutor.execute(() -> psl.onPreciseCallStateChanged(callState)));
}
public void onPreciseDataConnectionStateChanged(
PreciseDataConnectionState dataConnectionState) {
- send(LISTEN_PRECISE_DATA_CONNECTION_STATE, 0, 0, dataConnectionState);
+ PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+ if (psl == null) return;
+
+ Binder.withCleanCallingIdentity(
+ () -> mExecutor.execute(
+ () -> psl.onPreciseDataConnectionStateChanged(dataConnectionState)));
}
- public void onDataConnectionRealTimeInfoChanged(
- DataConnectionRealTimeInfo dcRtInfo) {
- send(LISTEN_DATA_CONNECTION_REAL_TIME_INFO, 0, 0, dcRtInfo);
+ public void onDataConnectionRealTimeInfoChanged(DataConnectionRealTimeInfo dcRtInfo) {
+ PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+ if (psl == null) return;
+
+ Binder.withCleanCallingIdentity(
+ () -> mExecutor.execute(
+ () -> psl.onDataConnectionRealTimeInfoChanged(dcRtInfo)));
}
public void onSrvccStateChanged(int state) {
- send(LISTEN_SRVCC_STATE_CHANGED, 0, 0, state);
+ PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+ if (psl == null) return;
+
+ Binder.withCleanCallingIdentity(
+ () -> mExecutor.execute(() -> psl.onSrvccStateChanged(state)));
}
public void onVoiceActivationStateChanged(int activationState) {
- send(LISTEN_VOICE_ACTIVATION_STATE, 0, 0, activationState);
+ PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+ if (psl == null) return;
+
+ Binder.withCleanCallingIdentity(
+ () -> mExecutor.execute(
+ () -> psl.onVoiceActivationStateChanged(activationState)));
}
public void onDataActivationStateChanged(int activationState) {
- send(LISTEN_DATA_ACTIVATION_STATE, 0, 0, activationState);
+ PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+ if (psl == null) return;
+
+ Binder.withCleanCallingIdentity(
+ () -> mExecutor.execute(
+ () -> psl.onDataActivationStateChanged(activationState)));
}
public void onUserMobileDataStateChanged(boolean enabled) {
- send(LISTEN_USER_MOBILE_DATA_STATE, 0, 0, enabled);
+ PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+ if (psl == null) return;
+
+ Binder.withCleanCallingIdentity(
+ () -> mExecutor.execute(
+ () -> psl.onUserMobileDataStateChanged(enabled)));
}
public void onOemHookRawEvent(byte[] rawData) {
- send(LISTEN_OEM_HOOK_RAW_EVENT, 0, 0, rawData);
+ PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+ if (psl == null) return;
+
+ Binder.withCleanCallingIdentity(
+ () -> mExecutor.execute(() -> psl.onOemHookRawEvent(rawData)));
}
public void onCarrierNetworkChange(boolean active) {
- send(LISTEN_CARRIER_NETWORK_CHANGE, 0, 0, active);
+ PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+ if (psl == null) return;
+
+ Binder.withCleanCallingIdentity(
+ () -> mExecutor.execute(() -> psl.onCarrierNetworkChange(active)));
}
public void onPhysicalChannelConfigurationChanged(List<PhysicalChannelConfig> configs) {
- send(LISTEN_PHYSICAL_CHANNEL_CONFIGURATION, 0, 0, configs);
+ PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+ if (psl == null) return;
+
+ Binder.withCleanCallingIdentity(
+ () -> mExecutor.execute(
+ () -> psl.onPhysicalChannelConfigurationChanged(configs)));
}
public void onPhoneCapabilityChanged(PhoneCapability capability) {
- send(LISTEN_PHONE_CAPABILITY_CHANGE, 0, 0, capability);
- }
+ PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+ if (psl == null) return;
- public void onPreferredDataSubIdChanged(int subId) {
- send(LISTEN_PREFERRED_DATA_SUBID_CHANGE, 0, 0, subId);
+ Binder.withCleanCallingIdentity(
+ () -> mExecutor.execute(() -> psl.onPhoneCapabilityChanged(capability)));
}
public void onRadioPowerStateChanged(@TelephonyManager.RadioPowerState int state) {
- send(LISTEN_RADIO_POWER_STATE_CHANGED, 0, 0, state);
+ PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+ if (psl == null) return;
+
+ Binder.withCleanCallingIdentity(
+ () -> mExecutor.execute(() -> psl.onRadioPowerStateChanged(state)));
}
+ public void onPreferredDataSubIdChanged(int subId) {
+ PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+ if (psl == null) return;
+
+ Binder.withCleanCallingIdentity(
+ () -> mExecutor.execute(() -> psl.onPreferredDataSubIdChanged(subId)));
+ }
}
- /**
- * @hide
- */
- @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
- @UnsupportedAppUsage
- public final IPhoneStateListener callback = new IPhoneStateListenerStub(this);
private void log(String s) {
Rlog.d(LOG_TAG, s);
}
-}
\ No newline at end of file
+}
diff --git a/telephony/java/android/telephony/SignalStrength.java b/telephony/java/android/telephony/SignalStrength.java
index bc832c3..240b8a9 100644
--- a/telephony/java/android/telephony/SignalStrength.java
+++ b/telephony/java/android/telephony/SignalStrength.java
@@ -17,12 +17,12 @@
package android.telephony;
import android.annotation.UnsupportedAppUsage;
+import android.os.Build;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.telephony.CarrierConfigManager;
import android.util.Log;
-import android.content.res.Resources;
import java.util.ArrayList;
import java.util.Arrays;
@@ -37,25 +37,25 @@
private static final boolean DBG = false;
/** @hide */
- @UnsupportedAppUsage
- public static final int SIGNAL_STRENGTH_NONE_OR_UNKNOWN
- = TelephonyProtoEnums.SIGNAL_STRENGTH_NONE_OR_UNKNOWN; // = 0
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ public static final int SIGNAL_STRENGTH_NONE_OR_UNKNOWN =
+ CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN; // = 0
/** @hide */
- @UnsupportedAppUsage
- public static final int SIGNAL_STRENGTH_POOR
- = TelephonyProtoEnums.SIGNAL_STRENGTH_POOR; // = 1
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ public static final int SIGNAL_STRENGTH_POOR =
+ CellSignalStrength.SIGNAL_STRENGTH_POOR; // = 1
/** @hide */
- @UnsupportedAppUsage
- public static final int SIGNAL_STRENGTH_MODERATE
- = TelephonyProtoEnums.SIGNAL_STRENGTH_MODERATE; // = 2
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ public static final int SIGNAL_STRENGTH_MODERATE =
+ CellSignalStrength.SIGNAL_STRENGTH_MODERATE; // = 2
/** @hide */
- @UnsupportedAppUsage
- public static final int SIGNAL_STRENGTH_GOOD
- = TelephonyProtoEnums.SIGNAL_STRENGTH_GOOD; // = 3
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ public static final int SIGNAL_STRENGTH_GOOD =
+ CellSignalStrength.SIGNAL_STRENGTH_GOOD; // = 3
/** @hide */
- @UnsupportedAppUsage
- public static final int SIGNAL_STRENGTH_GREAT
- = TelephonyProtoEnums.SIGNAL_STRENGTH_GREAT; // = 4
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ public static final int SIGNAL_STRENGTH_GREAT =
+ CellSignalStrength.SIGNAL_STRENGTH_GREAT; // = 4
/** @hide */
@UnsupportedAppUsage
public static final int NUM_SIGNAL_STRENGTH_BINS = 5;
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 5c8b90f..22f63a7 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -6417,7 +6417,6 @@
/**
* Set the preferred network type.
- * Used for device configuration by some CDMA operators.
*
* <p>Requires Permission:
* {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
diff --git a/telephony/java/android/telephony/euicc/EuiccCardManager.java b/telephony/java/android/telephony/euicc/EuiccCardManager.java
index 1141177..3b1ef3f 100644
--- a/telephony/java/android/telephony/euicc/EuiccCardManager.java
+++ b/telephony/java/android/telephony/euicc/EuiccCardManager.java
@@ -15,6 +15,7 @@
*/
package android.telephony.euicc;
+import android.annotation.CallbackExecutor;
import android.annotation.IntDef;
import android.annotation.Nullable;
import android.annotation.SystemApi;
@@ -50,7 +51,6 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
-import android.annotation.CallbackExecutor;
import java.util.concurrent.Executor;
/**
@@ -119,6 +119,9 @@
/** Result code when the eUICC card with the given card Id is not found. */
public static final int RESULT_EUICC_NOT_FOUND = -2;
+ /** Result code indicating the caller is not the active LPA. */
+ public static final int RESULT_CALLER_NOT_ALLOWED = -3;
+
/**
* Callback to receive the result of an eUICC card API.
*
@@ -152,7 +155,7 @@
* Requests all the profiles on eUicc.
*
* @param cardId The Id of the eUICC.
- * @param executor The executor through which the callback should be invode.
+ * @param executor The executor through which the callback should be invoke.
* @param callback The callback to get the result code and all the profiles.
*/
public void requestAllProfiles(String cardId, @CallbackExecutor Executor executor,
@@ -176,7 +179,7 @@
*
* @param cardId The Id of the eUICC.
* @param iccid The iccid of the profile.
- * @param executor The executor through which the callback should be invode.
+ * @param executor The executor through which the callback should be invoke.
* @param callback The callback to get the result code and profile.
*/
public void requestProfile(String cardId, String iccid, @CallbackExecutor Executor executor,
@@ -201,7 +204,7 @@
* @param cardId The Id of the eUICC.
* @param iccid The iccid of the profile.
* @param refresh Whether sending the REFRESH command to modem.
- * @param executor The executor through which the callback should be invode.
+ * @param executor The executor through which the callback should be invoke.
* @param callback The callback to get the result code.
*/
public void disableProfile(String cardId, String iccid, boolean refresh,
@@ -227,7 +230,7 @@
* @param cardId The Id of the eUICC.
* @param iccid The iccid of the profile to switch to.
* @param refresh Whether sending the REFRESH command to modem.
- * @param executor The executor through which the callback should be invode.
+ * @param executor The executor through which the callback should be invoke.
* @param callback The callback to get the result code and the EuiccProfileInfo enabled.
*/
public void switchToProfile(String cardId, String iccid, boolean refresh,
@@ -252,7 +255,7 @@
* @param cardId The Id of the eUICC.
* @param iccid The iccid of the profile.
* @param nickname The nickname of the profile.
- * @param executor The executor through which the callback should be invode.
+ * @param executor The executor through which the callback should be invoke.
* @param callback The callback to get the result code.
*/
public void setNickname(String cardId, String iccid, String nickname,
@@ -276,7 +279,7 @@
*
* @param cardId The Id of the eUICC.
* @param iccid The iccid of the profile.
- * @param executor The executor through which the callback should be invode.
+ * @param executor The executor through which the callback should be invoke.
* @param callback The callback to get the result code.
*/
public void deleteProfile(String cardId, String iccid, @CallbackExecutor Executor executor,
@@ -301,7 +304,7 @@
* @param cardId The Id of the eUICC.
* @param options Bits of the options of resetting which parts of the eUICC memory. See
* EuiccCard for details.
- * @param executor The executor through which the callback should be invode.
+ * @param executor The executor through which the callback should be invoke.
* @param callback The callback to get the result code.
*/
public void resetMemory(String cardId, @ResetOption int options,
@@ -324,7 +327,7 @@
* Requests the default SM-DP+ address from eUICC.
*
* @param cardId The Id of the eUICC.
- * @param executor The executor through which the callback should be invode.
+ * @param executor The executor through which the callback should be invoke.
* @param callback The callback to get the result code and the default SM-DP+ address.
*/
public void requestDefaultSmdpAddress(String cardId, @CallbackExecutor Executor executor,
@@ -347,7 +350,7 @@
* Requests the SM-DS address from eUICC.
*
* @param cardId The Id of the eUICC.
- * @param executor The executor through which the callback should be invode.
+ * @param executor The executor through which the callback should be invoke.
* @param callback The callback to get the result code and the SM-DS address.
*/
public void requestSmdsAddress(String cardId, @CallbackExecutor Executor executor,
@@ -371,7 +374,7 @@
*
* @param cardId The Id of the eUICC.
* @param defaultSmdpAddress The default SM-DP+ address to set.
- * @param executor The executor through which the callback should be invode.
+ * @param executor The executor through which the callback should be invoke.
* @param callback The callback to get the result code.
*/
public void setDefaultSmdpAddress(String cardId, String defaultSmdpAddress,
@@ -395,7 +398,7 @@
* Requests Rules Authorisation Table.
*
* @param cardId The Id of the eUICC.
- * @param executor The executor through which the callback should be invode.
+ * @param executor The executor through which the callback should be invoke.
* @param callback the callback to get the result code and the rule authorisation table.
*/
public void requestRulesAuthTable(String cardId, @CallbackExecutor Executor executor,
@@ -418,7 +421,7 @@
* Requests the eUICC challenge for new profile downloading.
*
* @param cardId The Id of the eUICC.
- * @param executor The executor through which the callback should be invode.
+ * @param executor The executor through which the callback should be invoke.
* @param callback the callback to get the result code and the challenge.
*/
public void requestEuiccChallenge(String cardId, @CallbackExecutor Executor executor,
@@ -441,7 +444,7 @@
* Requests the eUICC info1 defined in GSMA RSP v2.0+ for new profile downloading.
*
* @param cardId The Id of the eUICC.
- * @param executor The executor through which the callback should be invode.
+ * @param executor The executor through which the callback should be invoke.
* @param callback the callback to get the result code and the info1.
*/
public void requestEuiccInfo1(String cardId, @CallbackExecutor Executor executor,
@@ -464,7 +467,7 @@
* Gets the eUICC info2 defined in GSMA RSP v2.0+ for new profile downloading.
*
* @param cardId The Id of the eUICC.
- * @param executor The executor through which the callback should be invode.
+ * @param executor The executor through which the callback should be invoke.
* @param callback the callback to get the result code and the info2.
*/
public void requestEuiccInfo2(String cardId, @CallbackExecutor Executor executor,
@@ -497,7 +500,7 @@
* GSMA RSP v2.0+.
* @param serverCertificate ASN.1 data in byte array indicating SM-DP+ Certificate returned by
* SM-DP+ server.
- * @param executor The executor through which the callback should be invode.
+ * @param executor The executor through which the callback should be invoke.
* @param callback the callback to get the result code and a byte array which represents a
* {@code AuthenticateServerResponse} defined in GSMA RSP v2.0+.
*/
@@ -537,7 +540,7 @@
* SM-DP+ server.
* @param smdpCertificate ASN.1 data in byte array indicating the SM-DP+ Certificate returned
* by SM-DP+ server.
- * @param executor The executor through which the callback should be invode.
+ * @param executor The executor through which the callback should be invoke.
* @param callback the callback to get the result code and a byte array which represents a
* {@code PrepareDownloadResponse} defined in GSMA RSP v2.0+
*/
@@ -569,7 +572,7 @@
*
* @param cardId The Id of the eUICC.
* @param boundProfilePackage the Bound Profile Package data returned by SM-DP+ server.
- * @param executor The executor through which the callback should be invode.
+ * @param executor The executor through which the callback should be invoke.
* @param callback the callback to get the result code and a byte array which represents a
* {@code LoadBoundProfilePackageResponse} defined in GSMA RSP v2.0+.
*/
@@ -598,7 +601,7 @@
* @param cardId The Id of the eUICC.
* @param transactionId the transaction ID returned by SM-DP+ server.
* @param reason the cancel reason.
- * @param executor The executor through which the callback should be invode.
+ * @param executor The executor through which the callback should be invoke.
* @param callback the callback to get the result code and an byte[] which represents a
* {@code CancelSessionResponse} defined in GSMA RSP v2.0+.
*/
@@ -627,7 +630,7 @@
*
* @param cardId The Id of the eUICC.
* @param events bits of the event types ({@link EuiccNotification.Event}) to list.
- * @param executor The executor through which the callback should be invode.
+ * @param executor The executor through which the callback should be invoke.
* @param callback the callback to get the result code and the list of notifications.
*/
public void listNotifications(String cardId, @EuiccNotification.Event int events,
@@ -651,7 +654,7 @@
*
* @param cardId The Id of the eUICC.
* @param events bits of the event types ({@link EuiccNotification.Event}) to list.
- * @param executor The executor through which the callback should be invode.
+ * @param executor The executor through which the callback should be invoke.
* @param callback the callback to get the result code and the list of notifications.
*/
public void retrieveNotificationList(String cardId, @EuiccNotification.Event int events,
@@ -675,7 +678,7 @@
*
* @param cardId The Id of the eUICC.
* @param seqNumber the sequence number of the notification.
- * @param executor The executor through which the callback should be invode.
+ * @param executor The executor through which the callback should be invoke.
* @param callback the callback to get the result code and the notification.
*/
public void retrieveNotification(String cardId, int seqNumber,
@@ -699,7 +702,7 @@
*
* @param cardId The Id of the eUICC.
* @param seqNumber the sequence number of the notification.
- * @param executor The executor through which the callback should be invode.
+ * @param executor The executor through which the callback should be invoke.
* @param callback the callback to get the result code.
*/
public void removeNotificationFromList(String cardId, int seqNumber,
diff --git a/telephony/java/android/telephony/ims/ImsMmTelManager.java b/telephony/java/android/telephony/ims/ImsMmTelManager.java
index c9cf473..e06c372 100644
--- a/telephony/java/android/telephony/ims/ImsMmTelManager.java
+++ b/telephony/java/android/telephony/ims/ImsMmTelManager.java
@@ -292,7 +292,7 @@
* Create an instance of ImsManager for the subscription id specified.
*
* @param context
- * @param subId The ID of the subscription that this ImsManager will use.
+ * @param subId The ID of the subscription that this ImsMmTelManager will use.
* @see android.telephony.SubscriptionManager#getActiveSubscriptionInfoList()
* @throws IllegalArgumentException if the subscription is invalid or
* the subscription ID is not an active subscription.
diff --git a/telephony/java/android/telephony/ims/ProvisioningManager.java b/telephony/java/android/telephony/ims/ProvisioningManager.java
new file mode 100644
index 0000000..916e282
--- /dev/null
+++ b/telephony/java/android/telephony/ims/ProvisioningManager.java
@@ -0,0 +1,252 @@
+/*
+ * 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.ims;
+
+import android.Manifest;
+import android.annotation.CallbackExecutor;
+import android.annotation.NonNull;
+import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
+import android.content.Context;
+import android.os.Binder;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.telephony.SubscriptionManager;
+import android.telephony.ims.aidl.IImsConfigCallback;
+import android.telephony.ims.stub.ImsConfigImplBase;
+
+import com.android.internal.telephony.ITelephony;
+
+import java.util.concurrent.Executor;
+
+/**
+ * Manages IMS provisioning and configuration parameters, as well as callbacks for apps to listen
+ * to changes in these configurations.
+ *
+ * Note: IMS provisioning keys are defined per carrier or OEM using OMA-DM or other provisioning
+ * applications and may vary.
+ * @hide
+ */
+@SystemApi
+public class ProvisioningManager {
+
+ /**
+ * Callback for IMS provisioning changes.
+ */
+ public static class Callback {
+
+ private static class CallbackBinder extends IImsConfigCallback.Stub {
+
+ private final Callback mLocalConfigurationCallback;
+ private Executor mExecutor;
+
+ private CallbackBinder(Callback localConfigurationCallback) {
+ mLocalConfigurationCallback = localConfigurationCallback;
+ }
+
+ @Override
+ public final void onIntConfigChanged(int item, int value) {
+ Binder.withCleanCallingIdentity(() ->
+ mExecutor.execute(() ->
+ mLocalConfigurationCallback.onProvisioningIntChanged(item, value)));
+ }
+
+ @Override
+ public final void onStringConfigChanged(int item, String value) {
+ Binder.withCleanCallingIdentity(() ->
+ mExecutor.execute(() ->
+ mLocalConfigurationCallback.onProvisioningStringChanged(item,
+ value)));
+ }
+
+ private void setExecutor(Executor executor) {
+ mExecutor = executor;
+ }
+ }
+
+ private final CallbackBinder mBinder = new CallbackBinder(this);
+
+ /**
+ * Called when a provisioning item has changed.
+ * @param item the IMS provisioning key constant, as defined by the OEM.
+ * @param value the new integer value of the IMS provisioning key.
+ */
+ public void onProvisioningIntChanged(int item, int value) {
+ // Base Implementation
+ }
+
+ /**
+ * Called when a provisioning item has changed.
+ * @param item the IMS provisioning key constant, as defined by the OEM.
+ * @param value the new String value of the IMS configuration constant.
+ */
+ public void onProvisioningStringChanged(int item, String value) {
+ // Base Implementation
+ }
+
+ /**@hide*/
+ public final IImsConfigCallback getBinder() {
+ return mBinder;
+ }
+
+ /**@hide*/
+ public void setExecutor(Executor executor) {
+ mBinder.setExecutor(executor);
+ }
+ }
+
+ private int mSubId;
+
+ /**
+ * Create a new {@link ProvisioningManager} for the subscription specified.
+ * @param context The context that this manager will use.
+ * @param subId The ID of the subscription that this ProvisioningManager will use.
+ * @see android.telephony.SubscriptionManager#getActiveSubscriptionInfoList()
+ * @throws IllegalArgumentException if the subscription is invalid or
+ * the subscription ID is not an active subscription.
+ */
+ public static ProvisioningManager createForSubscriptionId(Context context, int subId) {
+ if (!SubscriptionManager.isValidSubscriptionId(subId)
+ || !getSubscriptionManager(context).isActiveSubscriptionId(subId)) {
+ throw new IllegalArgumentException("Invalid subscription ID");
+ }
+
+ return new ProvisioningManager(subId);
+ }
+
+ private ProvisioningManager(int subId) {
+ mSubId = subId;
+ }
+
+ /**
+ * Register a new {@link Callback} to listen to changes to changes in
+ * IMS provisioning. Use {@link SubscriptionManager.OnSubscriptionsChangedListener} to listen to
+ * Subscription changed events and call
+ * {@link #unregisterProvisioningChangedCallback(Callback)} to clean up after a
+ * subscription is removed.
+ * @param executor The {@link Executor} to call the callback methods on
+ * @param callback The provisioning callbackto be registered.
+ * @see #unregisterProvisioningChangedCallback(Callback)
+ * @see SubscriptionManager.OnSubscriptionsChangedListener
+ */
+ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ public void registerProvisioningChangedCallback(@CallbackExecutor Executor executor,
+ @NonNull Callback callback) {
+ callback.setExecutor(executor);
+ try {
+ getITelephony().registerImsProvisioningChangedCallback(mSubId,
+ callback.getBinder());
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
+ }
+
+ /**
+ * Unregister an existing {@link Callback}. Ensure to call this method when cleaning
+ * up to avoid memory leaks or when the subscription is removed.
+ * @param callback The existing {@link Callback} to be removed.
+ * @see #registerProvisioningChangedCallback(Executor, Callback)
+ */
+ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ public void unregisterProvisioningChangedCallback(@NonNull Callback callback) {
+ try {
+ getITelephony().unregisterImsProvisioningChangedCallback(mSubId,
+ callback.getBinder());
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
+ }
+
+ /**
+ * Query for the integer value associated with the provided key.
+ * @param key An integer that represents the provisioning key, which is defined by the OEM.
+ * @return an integer value for the provided key.
+ * @throws IllegalArgumentException if the key provided was invalid.
+ */
+ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ public int getProvisioningIntValue(int key) {
+ try {
+ return getITelephony().getImsProvisioningInt(mSubId, key);
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
+ }
+
+ /**
+ * Query for the String value associated with the provided key.
+ * @param key An integer that represents the provisioning key, which is defined by the OEM.
+ * @return a String value for the provided key, or {@code null} if the key doesn't exist.
+ * @throws IllegalArgumentException if the key provided was invalid.
+ */
+ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ public String getProvisioningStringValue(int key) {
+ try {
+ return getITelephony().getImsProvisioningString(mSubId, key);
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
+ }
+
+ /**
+ * Set the integer value associated with the provided key.
+ * @param key An integer that represents the provisioning key, which is defined by the OEM.
+ * @param value a integer value for the provided key.
+ * @return the result of setting the configuration value.
+ */
+ @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
+ public @ImsConfigImplBase.SetConfigResult int setProvisioningIntValue(int key, int value) {
+ try {
+ return getITelephony().setImsProvisioningInt(mSubId, key, value);
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
+ }
+
+ /**
+ * Set the String value associated with the provided key.
+ *
+ * @param key An integer that represents the provisioning key, which is defined by the OEM.
+ * @param value a String value for the provided key.
+ * @return the result of setting the configuration value.
+ */
+ @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
+ public @ImsConfigImplBase.SetConfigResult int setProvisioningStringValue(int key,
+ String value) {
+ try {
+ return getITelephony().setImsProvisioningString(mSubId, key, value);
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
+ }
+
+ private static SubscriptionManager getSubscriptionManager(Context context) {
+ SubscriptionManager manager = context.getSystemService(SubscriptionManager.class);
+ if (manager == null) {
+ throw new RuntimeException("Could not find SubscriptionManager.");
+ }
+ return manager;
+ }
+
+ private static ITelephony getITelephony() {
+ ITelephony binder = ITelephony.Stub.asInterface(
+ ServiceManager.getService(Context.TELEPHONY_SERVICE));
+ if (binder == null) {
+ throw new RuntimeException("Could not find Telephony Service.");
+ }
+ return binder;
+ }
+}
diff --git a/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java b/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java
index dcd7ea7..321bfff 100644
--- a/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java
@@ -16,9 +16,9 @@
package android.telephony.ims.stub;
+import android.annotation.IntDef;
import android.annotation.SystemApi;
import android.content.Context;
-import android.content.Intent;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.telephony.ims.aidl.IImsConfig;
@@ -28,6 +28,8 @@
import com.android.ims.ImsConfig;
import com.android.internal.annotations.VisibleForTesting;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.lang.ref.WeakReference;
import java.util.HashMap;
@@ -215,41 +217,6 @@
}
/**
- * Callback that the framework uses for receiving Configuration change updates.
- * {@hide}
- */
- public static class Callback extends IImsConfigCallback.Stub {
-
- @Override
- public final void onIntConfigChanged(int item, int value) throws RemoteException {
- onConfigChanged(item, value);
- }
-
- @Override
- public final void onStringConfigChanged(int item, String value) throws RemoteException {
- onConfigChanged(item, value);
- }
-
- /**
- * Called when the IMS configuration has changed.
- * @param item the IMS configuration key constant, as defined in ImsConfig.
- * @param value the new integer value of the IMS configuration constant.
- */
- public void onConfigChanged(int item, int value) {
- // Base Implementation
- }
-
- /**
- * Called when the IMS configuration has changed.
- * @param item the IMS configuration key constant, as defined in ImsConfig.
- * @param value the new String value of the IMS configuration constant.
- */
- public void onConfigChanged(int item, String value) {
- // Base Implementation
- }
- }
-
- /**
* The configuration requested resulted in an unknown result. This may happen if the
* IMS configurations are unavailable.
*/
@@ -263,6 +230,16 @@
*/
public static final int CONFIG_RESULT_FAILED = 1;
+ /**
+ * @hide
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = "CONFIG_RESULT_", value = {
+ CONFIG_RESULT_SUCCESS,
+ CONFIG_RESULT_FAILED
+ })
+ public @interface SetConfigResult {}
+
private final RemoteCallbackList<IImsConfigCallback> mCallbacks = new RemoteCallbackList<>();
ImsConfigStub mImsConfigStub;
@@ -279,17 +256,16 @@
}
/**
- * Adds a {@link Callback} to the list of callbacks notified when a value in the configuration
- * changes.
+ * Adds a {@link android.telephony.ims.ProvisioningManager.Callback} to the list of callbacks
+ * notified when a value in the configuration changes.
* @param c callback to add.
*/
private void addImsConfigCallback(IImsConfigCallback c) {
mCallbacks.register(c);
}
/**
- * Removes a {@link Callback} to the list of callbacks notified when a value in the
- * configuration changes.
- *
+ * Removes a {@link android.telephony.ims.ProvisioningManager.Callback} to the list of callbacks
+ * notified when a value in the configuration changes.
* @param c callback to remove.
*/
private void removeImsConfigCallback(IImsConfigCallback c) {
@@ -370,10 +346,9 @@
*
* @param item an integer key.
* @param value an integer containing the configuration value.
- * @return the result of setting the configuration value, defined as either
- * {@link #CONFIG_RESULT_FAILED} or {@link #CONFIG_RESULT_SUCCESS}.
+ * @return the result of setting the configuration value.
*/
- public int setConfig(int item, int value) {
+ public @SetConfigResult int setConfig(int item, int value) {
// Base Implementation - To be overridden.
return CONFIG_RESULT_FAILED;
}
@@ -383,10 +358,9 @@
*
* @param item an integer key.
* @param value a String containing the new configuration value.
- * @return Result of setting the configuration value, defined as either
- * {@link #CONFIG_RESULT_FAILED} or {@link #CONFIG_RESULT_SUCCESS}.
+ * @return Result of setting the configuration value.
*/
- public int setConfig(int item, String value) {
+ public @SetConfigResult int setConfig(int item, String value) {
// Base Implementation - To be overridden.
return CONFIG_RESULT_FAILED;
}
diff --git a/telephony/java/android/telephony/rcs/RcsManager.java b/telephony/java/android/telephony/rcs/RcsManager.java
new file mode 100644
index 0000000..0ef4e15
--- /dev/null
+++ b/telephony/java/android/telephony/rcs/RcsManager.java
@@ -0,0 +1,56 @@
+/*
+ * 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.rcs;
+
+import android.annotation.SystemService;
+import android.content.Context;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.telephony.Rlog;
+
+import com.android.internal.telephony.rcs.IRcs;
+
+/**
+ * RcsManager is the application interface to RcsProvider and provides access methods to
+ * RCS related database tables.
+ * @hide - TODO make this public
+ */
+@SystemService(Context.TELEPHONY_RCS_SERVICE)
+public class RcsManager {
+ private static final String TAG = "RcsManager";
+ private static final boolean VDBG = false;
+
+ /**
+ * Delete the RcsThread identified by the given threadId.
+ * @param threadId threadId of the thread to be deleted.
+ */
+ public void deleteThread(int threadId) {
+ if (VDBG) logd("deleteThread: threadId: " + threadId);
+ try {
+ IRcs iRcs = IRcs.Stub.asInterface(ServiceManager.getService("ircs"));
+ if (iRcs != null) {
+ iRcs.deleteThread(threadId);
+ }
+ } catch (RemoteException re) {
+
+ }
+ }
+
+ private static void logd(String msg) {
+ Rlog.d(TAG, msg);
+ }
+}
diff --git a/telephony/java/android/telephony/rcs/RcsThread.aidl b/telephony/java/android/telephony/rcs/RcsThread.aidl
new file mode 100644
index 0000000..e2e0da5d
--- /dev/null
+++ b/telephony/java/android/telephony/rcs/RcsThread.aidl
@@ -0,0 +1,20 @@
+/*
+**
+** Copyright 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;
+
+parcelable RcsThread;
\ No newline at end of file
diff --git a/telephony/java/android/telephony/rcs/RcsThread.java b/telephony/java/android/telephony/rcs/RcsThread.java
new file mode 100644
index 0000000..83eb973
--- /dev/null
+++ b/telephony/java/android/telephony/rcs/RcsThread.java
@@ -0,0 +1,75 @@
+/*
+ * 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.rcs;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+
+import com.android.internal.telephony.rcs.IRcs;
+
+/**
+ * RcsThread represents a single RCS conversation thread. It holds messages that were sent and
+ * received and events that occured on that thread.
+ * @hide - TODO(sahinc) make this public
+ */
+public class RcsThread implements Parcelable {
+ public static final Creator<RcsThread> CREATOR = new Creator<RcsThread>() {
+ @Override
+ public RcsThread createFromParcel(Parcel in) {
+ return new RcsThread(in);
+ }
+
+ @Override
+ public RcsThread[] newArray(int size) {
+ return new RcsThread[size];
+ }
+ };
+
+ protected RcsThread(Parcel in) {
+ }
+
+ /**
+ * Returns the number of messages in this RCS thread.
+ *
+ * @hide
+ */
+ public int getMessageCount() {
+ try {
+ IRcs iRcs = IRcs.Stub.asInterface(ServiceManager.getService("ircs"));
+ if (iRcs != null) {
+ // TODO(sahinc): substitute to the regular thread id once we have database
+ // TODO(sahinc): connection in place
+ return iRcs.getMessageCount(/* rcsThreadId= */ 123);
+ }
+ } catch (RemoteException re) {
+ // TODO(sahinc): Log something meaningful
+ }
+ return 0;
+ }
+
+ /** Implement the Parcelable interface */
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ }
+}
diff --git a/telephony/java/com/android/ims/ImsConfig.java b/telephony/java/com/android/ims/ImsConfig.java
index 90e9880..71a2174 100644
--- a/telephony/java/com/android/ims/ImsConfig.java
+++ b/telephony/java/com/android/ims/ImsConfig.java
@@ -16,12 +16,17 @@
package com.android.ims;
-import android.content.Context;
+import android.os.Handler;
+import android.os.HandlerExecutor;
+import android.os.Looper;
import android.os.RemoteException;
import android.telephony.Rlog;
import android.telephony.ims.ImsReasonInfo;
+import android.telephony.ims.ProvisioningManager;
import android.telephony.ims.aidl.IImsConfig;
-import android.telephony.ims.stub.ImsConfigImplBase;
+import android.telephony.ims.aidl.IImsConfigCallback;
+
+import java.util.concurrent.Executor;
/**
* Provides APIs to get/set the IMS service feature/capability/parameters.
@@ -29,8 +34,10 @@
* 1) Items provisioned by the operator.
* 2) Items configured by user. Mainly service feature class.
*
+ * @deprecated Use {@link ProvisioningManager} to change these configurations in the ImsService.
* @hide
*/
+@Deprecated
public class ImsConfig {
private static final String TAG = "ImsConfig";
private boolean DBG = true;
@@ -46,7 +53,7 @@
/**
* Broadcast action: the configuration was changed
- * @deprecated Use {@link ImsConfig#addConfigCallback(ImsConfigImplBase.Callback)} instead.
+ * @deprecated Use {@link android.telephony.ims.ProvisioningManager.Callback} instead.
* @hide
*/
public static final String ACTION_IMS_CONFIG_CHANGED =
@@ -673,13 +680,25 @@
}
/**
- * Adds a {@link ImsConfigImplBase.Callback} to the ImsService to notify when a Configuration
+ * Adds a {@link ProvisioningManager.Callback} to the ImsService to notify when a Configuration
* item has changed.
*
- * Make sure to call {@link #removeConfigCallback(ImsConfigImplBase.Callback)} when finished
+ * Make sure to call {@link #removeConfigCallback(IImsConfigCallback)} when finished
* using this callback.
*/
- public void addConfigCallback(ImsConfigImplBase.Callback callback) throws ImsException {
+ public void addConfigCallback(ProvisioningManager.Callback callback) throws ImsException {
+ callback.setExecutor(getThreadExecutor());
+ addConfigCallback(callback.getBinder());
+ }
+
+ /**
+ * Adds a {@link IImsConfigCallback} to the ImsService to notify when a Configuration
+ * item has changed.
+ *
+ * Make sure to call {@link #removeConfigCallback(IImsConfigCallback)} when finished
+ * using this callback.
+ */
+ public void addConfigCallback(IImsConfigCallback callback) throws ImsException {
if (DBG) Rlog.d(TAG, "addConfigCallback: " + callback);
try {
miConfig.addImsConfigCallback(callback);
@@ -690,10 +709,9 @@
}
/**
- * Removes a {@link ImsConfigImplBase.Callback} from the ImsService that was previously added
- * by {@link #addConfigCallback(ImsConfigImplBase.Callback)}.
+ * Removes an existing {@link IImsConfigCallback} from the ImsService.
*/
- public void removeConfigCallback(ImsConfigImplBase.Callback callback) throws ImsException {
+ public void removeConfigCallback(IImsConfigCallback callback) throws ImsException {
if (DBG) Rlog.d(TAG, "removeConfigCallback: " + callback);
try {
miConfig.removeImsConfigCallback(callback);
@@ -709,4 +727,11 @@
public boolean isBinderAlive() {
return miConfig.asBinder().isBinderAlive();
}
+
+ private Executor getThreadExecutor() {
+ if (Looper.myLooper() == null) {
+ Looper.prepare();
+ }
+ return new HandlerExecutor(new Handler(Looper.myLooper()));
+ }
}
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 193855b..20fde396 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -42,6 +42,7 @@
import android.telephony.VisualVoicemailSmsFilterSettings;
import android.telephony.ims.aidl.IImsCapabilityCallback;
import android.telephony.ims.aidl.IImsConfig;
+import android.telephony.ims.aidl.IImsConfigCallback;
import android.telephony.ims.aidl.IImsMmTelFeature;
import android.telephony.ims.aidl.IImsRcsFeature;
import android.telephony.ims.aidl.IImsRegistration;
@@ -1586,24 +1587,24 @@
/**
* Adds an IMS registration status callback for the subscription id specified.
*/
- oneway void addImsRegistrationCallback(int subId, IImsRegistrationCallback c,
+ void addImsRegistrationCallback(int subId, IImsRegistrationCallback c,
String callingPackage);
/**
* Removes an existing IMS registration status callback for the subscription specified.
*/
- oneway void removeImsRegistrationCallback(int subId, IImsRegistrationCallback c,
+ void removeImsRegistrationCallback(int subId, IImsRegistrationCallback c,
String callingPackage);
/**
* Adds an IMS MmTel capabilities callback for the subscription specified.
*/
- oneway void addMmTelCapabilityCallback(int subId, IImsCapabilityCallback c,
+ void addMmTelCapabilityCallback(int subId, IImsCapabilityCallback c,
String callingPackage);
/**
* Removes an existing IMS MmTel capabilities callback for the subscription specified.
*/
- oneway void removeMmTelCapabilityCallback(int subId, IImsCapabilityCallback c,
+ void removeMmTelCapabilityCallback(int subId, IImsCapabilityCallback c,
String callingPackage);
/**
@@ -1708,4 +1709,34 @@
* Return a list of certs in hex string from loaded carrier privileges access rules.
*/
List<String> getCertsFromCarrierPrivilegeAccessRules(int subId);
+
+ /**
+ * Register an IMS provisioning change callback with Telephony.
+ */
+ void registerImsProvisioningChangedCallback(int subId, IImsConfigCallback callback);
+
+ /**
+ * unregister an existing IMS provisioning change callback.
+ */
+ void unregisterImsProvisioningChangedCallback(int subId, IImsConfigCallback callback);
+
+ /**
+ * Return an integer containing the provisioning value for the specified provisioning key.
+ */
+ int getImsProvisioningInt(int subId, int key);
+
+ /**
+ * return a String containing the provisioning value for the provisioning key specified.
+ */
+ String getImsProvisioningString(int subId, int key);
+
+ /**
+ * Set the integer provisioning value for the provisioning key specified.
+ */
+ int setImsProvisioningInt(int subId, int key, int value);
+
+ /**
+ * Set the String provisioning value for the provisioning key specified.
+ */
+ int setImsProvisioningString(int subId, int key, String value);
}
diff --git a/telephony/java/com/android/internal/telephony/TelephonyIntents.java b/telephony/java/com/android/internal/telephony/TelephonyIntents.java
index 5ecb43e..2a648bd 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyIntents.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyIntents.java
@@ -480,9 +480,9 @@
public static final String EXTRA_PCO_VALUE_KEY = "pcoValue";
public static final String EXTRA_DEFAULT_NETWORK_AVAILABLE_KEY = "defaultNetworkAvailable";
- /**
+ /**
* Broadcast action to trigger CI OMA-DM Session.
- */
+ */
public static final String ACTION_REQUEST_OMADM_CONFIGURATION_UPDATE =
"com.android.omadm.service.CONFIGURATION_UPDATE";
@@ -491,4 +491,14 @@
*/
public static final String ACTION_CARRIER_CERTIFICATE_DOWNLOAD =
"com.android.internal.telephony.ACTION_CARRIER_CERTIFICATE_DOWNLOAD";
+
+ /**
+ * Broadcast action to indicate an error related to Line1Number has been detected.
+ *
+ * Requires the READ_PRIVILEGED_PHONE_STATE permission.
+ *
+ * @hide
+ */
+ public static final String ACTION_LINE1_NUMBER_ERROR_DETECTED =
+ "com.android.internal.telephony.ACTION_LINE1_NUMBER_ERROR_DETECTED";
}
diff --git a/telephony/java/com/android/internal/telephony/rcs/IRcs.aidl b/telephony/java/com/android/internal/telephony/rcs/IRcs.aidl
new file mode 100644
index 0000000..4c289ac
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/rcs/IRcs.aidl
@@ -0,0 +1,25 @@
+/*
+ * 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.internal.telephony.rcs;
+
+interface IRcs {
+ // RcsManager APIs
+ void deleteThread(int threadId);
+
+ // RcsThread APIs
+ int getMessageCount(int rcsThreadId);
+}
\ No newline at end of file
diff --git a/tests/RcsTests/Android.mk b/tests/RcsTests/Android.mk
new file mode 100644
index 0000000..adc7cab
--- /dev/null
+++ b/tests/RcsTests/Android.mk
@@ -0,0 +1,19 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+# Only compile source java files in this apk.
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := RcsTests
+LOCAL_PRIVATE_PLATFORM_APIS := true
+
+LOCAL_CERTIFICATE := platform
+LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base
+LOCAL_STATIC_JAVA_LIBRARIES := junit android-support-test mockito-target-minus-junit4
+
+include $(BUILD_PACKAGE)
+
+# Use the following include to make our test apk.
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/RcsTests/AndroidManifest.xml b/tests/RcsTests/AndroidManifest.xml
new file mode 100644
index 0000000..a7e7d47
--- /dev/null
+++ b/tests/RcsTests/AndroidManifest.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.tests.rcs">
+ <application android:label="RCS Test">
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.android.tests.rcs"/>
+</manifest>
diff --git a/tests/RcsTests/src/com/android/tests/rcs/RcsManagerTest.java b/tests/RcsTests/src/com/android/tests/rcs/RcsManagerTest.java
new file mode 100644
index 0000000..7f5f03e0d
--- /dev/null
+++ b/tests/RcsTests/src/com/android/tests/rcs/RcsManagerTest.java
@@ -0,0 +1,32 @@
+/*
+ * 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.tests.rcs;
+
+import android.support.test.runner.AndroidJUnit4;
+import android.telephony.rcs.RcsManager;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class RcsManagerTest {
+ //TODO(sahinc): Add meaningful tests once we have more of the implementation in place
+ @Test
+ public void testDeleteThreadDoesntCrash() {
+ RcsManager mRcsManager = new RcsManager();
+ mRcsManager.deleteThread(0);
+ }
+}