diff options
119 files changed, 3108 insertions, 642 deletions
diff --git a/Android.bp b/Android.bp index 170e22e1cbde..d9330f70aae6 100644 --- a/Android.bp +++ b/Android.bp @@ -576,6 +576,7 @@ java_defaults {          "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 8704ddc850e4..ff4e00fa6f26 100755 --- a/api/current.txt +++ b/api/current.txt @@ -42581,6 +42581,7 @@ package android.telephony {    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 4a58b7567bde..b81d59d00039 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -5094,6 +5094,7 @@ package android.telephony {      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 @@ package android.telephony {    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 { @@ -5590,6 +5593,7 @@ package android.telephony.euicc {      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 @@ -6232,6 +6236,22 @@ package android.telephony.ims {      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 ce0f9450030a..374a336dccef 100644 --- a/config/hiddenapi-light-greylist.txt +++ b/config/hiddenapi-light-greylist.txt @@ -1392,18 +1392,6 @@ Landroid/R$styleable;->Window_windowFrame:I  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/KeymasterIntArgument;->value:I  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 fdda85d5122a..83c43e7b83e1 100644 --- a/core/java/android/app/SystemServiceRegistry.java +++ b/core/java/android/app/SystemServiceRegistry.java @@ -143,6 +143,7 @@ import android.telephony.SubscriptionManager;  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 @@ final class SystemServiceRegistry {                  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 4630ad258cf2..5cbb1f8895c5 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -4250,6 +4250,13 @@ public abstract class Context {      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 d818228cb2b6..0ec509e1164e 100644 --- a/core/java/android/content/pm/ApplicationInfo.java +++ b/core/java/android/content/pm/ApplicationInfo.java @@ -27,7 +27,6 @@ import android.content.Context;  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 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {       * 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 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {       * 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 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {       */      @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 class ApplicationInfo extends PackageItemInfo implements Parcelable {       */      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 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {       * 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 7b076f6881cc..7aea261a48f1 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -6317,6 +6317,7 @@ public class PackageParser {          public ArrayList<String> usesOptionalLibraries = null;          @UnsupportedAppUsage          public String[] usesLibraryFiles = null; +        public ArrayList<SharedLibraryInfo> usesLibraryInfos = null;          public ArrayList<ActivityIntentInfo> preferredActivityFilters = null; @@ -6846,6 +6847,8 @@ public class PackageParser {              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 @@ public class PackageParser {              dest.writeStringList(usesLibraries);              dest.writeStringList(usesOptionalLibraries);              dest.writeStringArray(usesLibraryFiles); +            dest.writeTypedList(usesLibraryInfos);              if (ArrayUtils.isEmpty(usesStaticLibraries)) {                  dest.writeInt(-1); @@ -7456,6 +7460,10 @@ public class PackageParser {                  && 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 33bc9515409f..096301c92faa 100644 --- a/core/java/android/content/pm/SharedLibraryInfo.java +++ b/core/java/android/content/pm/SharedLibraryInfo.java @@ -19,11 +19,13 @@ package android.content.pm;  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 final class SharedLibraryInfo implements Parcelable {       */      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 @@ public final class SharedLibraryInfo implements Parcelable {       *       * @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 @@ public final class SharedLibraryInfo implements Parcelable {      }      /** +     * 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 @@ public final class SharedLibraryInfo implements Parcelable {      @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 387d29e81dfc..5afc8a9721b4 100644 --- a/core/java/android/content/pm/SharedLibraryNames.java +++ b/core/java/android/content/pm/SharedLibraryNames.java @@ -22,15 +22,15 @@ package android.content.pm;   */  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 221abed92f81..517eaf83d336 100644 --- a/core/java/android/os/BatteryStats.java +++ b/core/java/android/os/BatteryStats.java @@ -2419,7 +2419,7 @@ public abstract class BatteryStats implements Parcelable {      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 88d6e847b644..ddeb8380c331 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 @@ public class FileUtils {          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 @@ public class FileUtils {          }      }  } + diff --git a/core/java/android/os/ParcelFileDescriptor.java b/core/java/android/os/ParcelFileDescriptor.java index 7409ca741c52..81fc5c0303d5 100644 --- a/core/java/android/os/ParcelFileDescriptor.java +++ b/core/java/android/os/ParcelFileDescriptor.java @@ -1092,6 +1092,9 @@ public class ParcelFileDescriptor implements Parcelable, Closeable {      /**       * 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 916676ae4c90..258426e34a49 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -12166,27 +12166,14 @@ public final class Settings {                  "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 c104671fc129..1ab79fbee0b6 100644 --- a/core/java/android/security/keymaster/ExportResult.java +++ b/core/java/android/security/keymaster/ExportResult.java @@ -28,6 +28,11 @@ public class ExportResult implements Parcelable {      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 555863efec91..a4fe75d6d0c0 100644 --- a/core/java/android/security/keymaster/KeyCharacteristics.java +++ b/core/java/android/security/keymaster/KeyCharacteristics.java @@ -52,6 +52,14 @@ public class KeyCharacteristics implements Parcelable {          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 243b9fe5f7c6..00a1a1c06e79 100644 --- a/core/java/android/security/keymaster/KeymasterCertificateChain.java +++ b/core/java/android/security/keymaster/KeymasterCertificateChain.java @@ -54,6 +54,14 @@ public class KeymasterCertificateChain implements Parcelable {          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 2943211a45f5..bc4f36000b85 100644 --- a/core/java/android/security/keymaster/OperationResult.java +++ b/core/java/android/security/keymaster/OperationResult.java @@ -59,6 +59,10 @@ public class OperationResult implements Parcelable {          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 8f87f9193c1f..8bdb000aad0e 100644 --- a/core/java/com/android/internal/os/ZygoteInit.java +++ b/core/java/com/android/internal/os/ZygoteInit.java @@ -173,12 +173,13 @@ public class ZygoteInit {      }      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 258a55c7123a..ac0e60030fc5 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 f599b1fbc206..9ce6044bcf3e 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 d4982681cde8..9d3085aa2f88 100644 --- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java +++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java @@ -256,8 +256,7 @@ public class SettingsBackupTest {                      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 936ad22d4fc5..d24c140ad19a 100644 --- a/data/etc/Android.mk +++ b/data/etc/Android.mk @@ -47,3 +47,11 @@ LOCAL_MODULE_CLASS := ETC  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 000000000000..60a66e22027d --- /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 4e018833f1ff..40570c1083b3 100644 --- a/keystore/java/android/security/KeyStore.java +++ b/keystore/java/android/security/KeyStore.java @@ -38,11 +38,13 @@ import android.security.keymaster.KeymasterBlob;  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.math.BigInteger;  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 @@ public class KeyStore {          }      } +    /** +     * 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 class KeyStore {      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 @@ public class KeyStore {          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 @@ public class KeyStore {          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 @@ public class KeyStore {          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 @@ public class KeyStore {          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 @@ public class KeyStore {          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 @@ public class KeyStore {              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 @@ public class KeyStore {          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 @@ public class KeyStore {          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 @@ public class KeyStore {              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 @@ public class KeyStore {              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 000000000000..3a229cb610a8 --- /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 942614815c3d..942eafdbc48d 100644 --- a/native/graphics/jni/Android.bp +++ b/native/graphics/jni/Android.bp @@ -37,6 +37,7 @@ cc_library_shared {              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 72e37ed4756e..c84f3ec68178 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 000000000000..d460041e59ae --- /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 000000000000..ffd57a430662 --- /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 fa6f3fae2e33..cf4dc824f597 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 36d5e19d8a84..cdcb5a54daed 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 8eb259b57b77..7773eeb22e04 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 2281ce7270ab..94c314772483 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 8ce9deb1eb78..4dd8aa0c536c 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 b75d76e69f7c..fb703cfaadc9 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 fe189edaf311..a2c9ed809ba3 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 09dcc5f5989f..be649a50f26c 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 dc0dd17c0bf4..8183105a1aff 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 d8f7be991846..a9b7415d8427 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 cb6171093f12..16bf6e22761d 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 2e8d1f082d1f..f940299af6a8 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 2e8d1f082d1f..f940299af6a8 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 5d7ba9163895..c01166474074 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 da2eae9038bf..65244e7e9156 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 41fcb9a6bd6a..e4c4c9801d5c 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 2e4cc5134e1b..27b9b7f15fab 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 1976f7d1c1e6..8086fbf96088 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 8f98bb5131ca..39fc5692bc21 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 1bacc4680f1c..d924fffb8c1a 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 e44cd3b22cf2..11b1dd3f50e9 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 f15fb49634e1..145e2abd0906 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 10e3de6b9f24..4a335dd38979 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 a01a55339da4..2cc4038fbe63 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 8e7915d83cc6..527e69247104 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 e275b95849c1..bcc8686f8c65 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 75f2b48d98c2..7a7f7e075b30 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 17da83fd15ce..158f7cea00d8 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 95b855884c11..a42cb220a0d1 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 933721ace248..aaa51c8fbe3f 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 0dd5b6ceefa5..29c23ed2ee61 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 1c5960155f4d..2cbca06c13dd 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 b7c832107193..80074c394b83 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 17f20df33717..9ba066ebb12d 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 94b9d60f69da..5bef235af136 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 3d1064cf98d9..ebe4148fcca9 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 cf1b6b5cd478..e2e4eac97876 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 6966bcd69290..c0153e6d7611 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 54763be28912..8ba24b1c4ed9 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 7dd0b374f483..b7d9a8a81b8b 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 f6042897e493..967c8ba87ac1 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 8cf70413ef67..75356f01d81f 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 1c8b6e1c9dcd..feb2ddeba9c1 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 9a3a626d7dbe..11a2131dc64c 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 565ef8f486e4..07a247992197 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 73d2455dcf3a..cdedd3306a01 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 0e818d3e3ca2..0f4cd1672427 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 e51d2aa6cf9e..9c702b953fd5 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 ce822e7f24bf..70c2a08682af 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 9010e1eebbb6..df1c700582ff 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 5b535e2a62cf..2a2e39729f2e 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 866ba187df16..794364588f94 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 f486fe4c5ddf..e9698dbbd784 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 774a035e4b52..7e20f2dde7f7 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.ConnectivityManager.EXTRA_CAPTIVE_PORTAL_PROBE_SPEC;  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.NetworkRequest;  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.support.v4.widget.SwipeRefreshLayout;  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.SslErrorHandler;  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 @@ public class CaptivePortalLoginActivity extends Activity {      @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 @@ public class CaptivePortalLoginActivity extends Activity {          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 @@ public class CaptivePortalLoginActivity extends Activity {              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 @@ public class CaptivePortalLoginActivity extends Activity {              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 @@ public class CaptivePortalLoginActivity extends Activity {                      "      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 @@ public class CaptivePortalLoginActivity extends Activity {                  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 @@ public class CaptivePortalLoginActivity extends Activity {      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 d11a74fd404c..a3e6ea2518a6 100644 --- a/services/core/java/com/android/server/StorageManagerService.java +++ b/services/core/java/com/android/server/StorageManagerService.java @@ -2602,24 +2602,35 @@ class StorageManagerService extends IStorageManager.Stub      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 @@ class StorageManagerService extends IStorageManager.Stub      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 @@ class StorageManagerService extends IStorageManager.Stub                      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 @@ class StorageManagerService extends IStorageManager.Stub      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 fa9c58e1955c..a411af254510 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 @@ public class ActivityManagerService extends IActivityManager.Stub          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 @@ public class ActivityManagerService extends IActivityManager.Stub                      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 @@ public class ActivityManagerService extends IActivityManager.Stub                  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 @@ public class ActivityManagerService extends IActivityManager.Stub              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 @@ public class ActivityManagerService extends IActivityManager.Stub              }              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 cf49d2a55d61..dc5213fa0cad 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 java.util.Map;  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 @@ public class PackageDexOptimizer {          // 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 f279f0ed73eb..2a605f555bdf 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.MOVE_FAILED_SYSTEM_PACKAGE;  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.Future;  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 @@ public class PackageManagerService extends IPackageManager.Stub      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 @@ public class PackageManagerService extends IPackageManager.Stub          }      } +    @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 @@ public class PackageManagerService extends IPackageManager.Stub                  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 @@ public class PackageManagerService extends IPackageManager.Stub      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 @@ public class PackageManagerService extends IPackageManager.Stub              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 @@ public class PackageManagerService extends IPackageManager.Stub              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 @@ public class PackageManagerService extends IPackageManager.Stub              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 @@ public class PackageManagerService extends IPackageManager.Stub              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 @@ public class PackageManagerService extends IPackageManager.Stub                          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 @@ public class PackageManagerService extends IPackageManager.Stub              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 @@ public class PackageManagerService extends IPackageManager.Stub      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 @@ public class PackageManagerService extends IPackageManager.Stub          }      } -    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 @@ public class PackageManagerService extends IPackageManager.Stub          }          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 @@ public class PackageManagerService extends IPackageManager.Stub          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); -        } -        if (!ArrayUtils.isEmpty(usesLibraryFiles)) { +            usesLibraryInfos = addSharedLibrariesLPw(pkg.usesOptionalLibraries, +                    null, null, pkg.packageName, false, +                    pkg.applicationInfo.targetSdkVersion, usesLibraryInfos); +        } +        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 @@ public class PackageManagerService extends IPackageManager.Stub                  }              } 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 @@ public class PackageManagerService extends IPackageManager.Stub                  }                  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 @@ public class PackageManagerService extends IPackageManager.Stub          // 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 @@ public class PackageManagerService extends IPackageManager.Stub                  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 @@ public class PackageManagerService extends IPackageManager.Stub      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 @@ public class PackageManagerService extends IPackageManager.Stub          } 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 @@ public class PackageManagerService extends IPackageManager.Stub          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 @@ public class PackageManagerService extends IPackageManager.Stub                  // 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 @@ public class PackageManagerService extends IPackageManager.Stub          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 @@ public class PackageManagerService extends IPackageManager.Stub          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 @@ public class PackageManagerService extends IPackageManager.Stub          }          // 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 @@ public class PackageManagerService extends IPackageManager.Stub              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 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());                  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 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());                          } 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 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());          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 a55b49fe028d..f78d2639df1a 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.app.ActivityManager;  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 6a0b6489f470..9d6a64701e85 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.os.FuseUnavailableMountException;  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 class AppFuseBridge implements Runnable {          }      } -    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 @@ public class AppFuseBridge implements Runnable {                  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 class AppFuseBridge implements Runnable {      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 class AppFuseBridge implements Runnable {          }          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 de54c4b537e4..c01c12465940 100644 --- a/services/robotests/Android.mk +++ b/services/robotests/Android.mk @@ -28,7 +28,8 @@ LOCAL_PRIVILEGED_MODULE := true  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 2f6e2c2ae6a3..cdbc665dc0c2 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.InstrumentationInfo;  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 @@ public class PackageParserTest {          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 33df6f9c37d7..906d64c1f619 100644 --- a/startop/view_compiler/dex_builder.cc +++ b/startop/view_compiler/dex_builder.cc @@ -49,18 +49,27 @@ std::ostream& operator<<(std::ostream& out, const Instruction::Op& opcode) {      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 @@ ir::String* DexBuilder::GetOrAddString(const std::string& string) {      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* DexBuilder::GetOrAddType(const std::string& descriptor) {    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 @@ ir::EncodedMethod* MethodBuilder::Encode() {        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::AddInstruction(Instruction instruction) {  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 @@ void MethodBuilder::BuildConst4(Value target, int value) {    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::EncodeInstructions() {  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 @@ void MethodBuilder::EncodeMove(const Instruction& instruction) {    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]; +  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]); +  } -  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); +  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()) { -    real_reg = RegisterValue(*instruction.dest()); -    buffer_.push_back(real_reg << 8 | art::Instruction::MOVE_RESULT); +    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 @@ void MethodBuilder::EncodeBranch(art::Instruction::Code op, const Instruction& i    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 07441518ea32..adf82bf9a01a 100644 --- a/startop/view_compiler/dex_builder.h +++ b/startop/view_compiler/dex_builder.h @@ -110,18 +110,22 @@ class Value {    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 @@ class Instruction {   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 @@ class Instruction {                                            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 @@ class Instruction {  // 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 @@ class MethodBuilder {    // 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 @@ class MethodBuilder {    };    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 @@ class ClassBuilder {    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 @@ class DexBuilder {    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 169c63374cb7..e20f3a9406c0 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 @@ public class DexBuilderTest {    }    @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 @@ public class DexBuilderTest {      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 c521bf2b8ccf..e2bf43bc1d0c 100644 --- a/startop/view_compiler/dex_testcase_generator.cc +++ b/startop/view_compiler/dex_testcase_generator.cc @@ -53,6 +53,19 @@ void GenerateSimpleTestCases(const string& outdir) {    }    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 @@ void GenerateSimpleTestCases(const string& outdir) {    }(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 6d3345e08a88..efea81763b9f 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 @@ public final class Telephony {                      "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 0280a759e943..90c15ffa44c1 100644 --- a/telephony/java/android/telephony/CarrierConfigManager.java +++ b/telephony/java/android/telephony/CarrierConfigManager.java @@ -1277,20 +1277,11 @@ public class CarrierConfigManager {      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 class CarrierConfigManager {      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 @@ public class CarrierConfigManager {          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 000000000000..35769f04c5ae --- /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 389f643e05a4..7d5388b7b7f4 100644 --- a/telephony/java/android/telephony/CellInfoLte.java +++ b/telephony/java/android/telephony/CellInfoLte.java @@ -19,7 +19,8 @@ package android.telephony;  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 @@ public final class CellInfoLte extends CellInfo implements Parcelable {      private CellIdentityLte mCellIdentityLte;      private CellSignalStrengthLte mCellSignalStrengthLte; +    private CellConfigLte mCellConfig;      /** @hide */      @UnsupportedAppUsage @@ -38,6 +40,7 @@ public final class CellInfoLte extends CellInfo implements Parcelable {          super();          mCellIdentityLte = new CellIdentityLte();          mCellSignalStrengthLte = new CellSignalStrengthLte(); +        mCellConfig = new CellConfigLte();      }      /** @hide */ @@ -45,6 +48,7 @@ public final class CellInfoLte extends CellInfo implements Parcelable {          super(ci);          this.mCellIdentityLte = ci.mCellIdentityLte.copy();          this.mCellSignalStrengthLte = ci.mCellSignalStrengthLte.copy(); +        this.mCellConfig = new CellConfigLte(ci.mCellConfig);      }      @Override @@ -71,26 +75,37 @@ public final class CellInfoLte extends CellInfo implements Parcelable {          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 @@ public final class CellInfoLte extends CellInfo implements Parcelable {          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 @@ public final class CellInfoLte extends CellInfo implements Parcelable {          super.writeToParcel(dest, flags, TYPE_LTE);          mCellIdentityLte.writeToParcel(dest, flags);          mCellSignalStrengthLte.writeToParcel(dest, flags); +        mCellConfig.writeToParcel(dest, flags);      }      /** @@ -129,6 +146,7 @@ public final class CellInfoLte extends CellInfo implements Parcelable {          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 2a3ef2197706..afa492226f65 100644 --- a/telephony/java/android/telephony/CellSignalStrength.java +++ b/telephony/java/android/telephony/CellSignalStrength.java @@ -21,15 +21,20 @@ package android.telephony;   */  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 97e3037b3c90..b6e6cbae8c26 100644 --- a/telephony/java/android/telephony/DataSpecificRegistrationStates.java +++ b/telephony/java/android/telephony/DataSpecificRegistrationStates.java @@ -17,17 +17,40 @@ public class DataSpecificRegistrationStates implements Parcelable{       */      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 @@ public class DataSpecificRegistrationStates implements Parcelable{      @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 68e512eaff37..75e8eda33cdc 100644 --- a/telephony/java/android/telephony/NetworkRegistrationState.java +++ b/telephony/java/android/telephony/NetworkRegistrationState.java @@ -161,11 +161,9 @@ public class NetworkRegistrationState implements Parcelable {       * @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 @@ public class NetworkRegistrationState implements Parcelable {       * @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 class NetworkRegistrationState implements Parcelable {      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 @@ public class NetworkRegistrationState implements Parcelable {                  && 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 @@ public class NetworkRegistrationState implements Parcelable {              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 f5dff20eedf2..3c5ad84a62b0 100644 --- a/telephony/java/android/telephony/PhoneStateListener.java +++ b/telephony/java/android/telephony/PhoneStateListener.java @@ -21,16 +21,18 @@ import android.annotation.NonNull;  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 class PhoneStateListener {      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 @@ public class PhoneStateListener {      @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 @@ public class PhoneStateListener {       */      @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 @@ public class PhoneStateListener {       * @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 @@ public class PhoneStateListener {       * @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 @@ public class PhoneStateListener {       */      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 bc832c3fbfa5..240b8a981e70 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 @@ public class SignalStrength implements Parcelable {      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/euicc/EuiccCardManager.java b/telephony/java/android/telephony/euicc/EuiccCardManager.java index 11411778a9ab..3b1ef3f45993 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 com.android.internal.telephony.euicc.ISwitchToProfileCallback;  import java.lang.annotation.Retention;  import java.lang.annotation.RetentionPolicy; -import android.annotation.CallbackExecutor;  import java.util.concurrent.Executor;  /** @@ -119,6 +119,9 @@ public class EuiccCardManager {      /** 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 @@ public class EuiccCardManager {       * 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 @@ public class EuiccCardManager {       *       * @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 @@ public class EuiccCardManager {       * @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 @@ public class EuiccCardManager {       * @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 @@ public class EuiccCardManager {       * @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 @@ public class EuiccCardManager {       *       * @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 @@ public class EuiccCardManager {       * @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 @@ public class EuiccCardManager {       * 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 @@ public class EuiccCardManager {       * 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 @@ public class EuiccCardManager {       *       * @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 @@ public class EuiccCardManager {       * 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 @@ public class EuiccCardManager {       * 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 @@ public class EuiccCardManager {       * 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 @@ public class EuiccCardManager {       * 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 @@ public class EuiccCardManager {       *     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 @@ public class EuiccCardManager {       *     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 @@ public class EuiccCardManager {       *       * @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 @@ public class EuiccCardManager {       * @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 @@ public class EuiccCardManager {       *       * @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 @@ public class EuiccCardManager {       *       * @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 @@ public class EuiccCardManager {       *       * @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 @@ public class EuiccCardManager {       *       * @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 c9cf473bb482..e06c3728836c 100644 --- a/telephony/java/android/telephony/ims/ImsMmTelManager.java +++ b/telephony/java/android/telephony/ims/ImsMmTelManager.java @@ -292,7 +292,7 @@ public class ImsMmTelManager {       * 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 000000000000..916e282f642e --- /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 dcd7ea714f8c..321bfff40652 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 android.util.Log;  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 @@ public class ImsConfigImplBase {      }      /** -     * 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 class ImsConfigImplBase {       */      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 @@ public class ImsConfigImplBase {      }      /** -     * 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 @@ public class ImsConfigImplBase {       *       * @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 @@ public class ImsConfigImplBase {       *       * @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 000000000000..0ef4e1552085 --- /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 000000000000..e2e0da5da347 --- /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 000000000000..83eb973ec12b --- /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 90e9880bd03e..71a21743a449 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 @@ import android.telephony.ims.stub.ImsConfigImplBase;   * 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 @@ public class ImsConfig {      /**       * 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 @@ public class ImsConfig {      }      /** -     * 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 @@ public class ImsConfig {      }      /** -     * 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 class ImsConfig {      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 1f3746668aa6..ddcd78070a47 100644 --- a/telephony/java/com/android/internal/telephony/ITelephony.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl @@ -40,6 +40,7 @@ import android.telephony.TelephonyHistogram;  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; @@ -1569,24 +1570,24 @@ interface ITelephony {      /**       * 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);      /** @@ -1691,4 +1692,34 @@ interface ITelephony {       * 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 5ecb43ebf112..2a648bd8b252 100644 --- a/telephony/java/com/android/internal/telephony/TelephonyIntents.java +++ b/telephony/java/com/android/internal/telephony/TelephonyIntents.java @@ -480,9 +480,9 @@ public class TelephonyIntents {      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 class TelephonyIntents {       */      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 000000000000..4c289acd15ef --- /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 000000000000..adc7cab91389 --- /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 000000000000..a7e7d479a4d9 --- /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 000000000000..7f5f03e0d5a4 --- /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); +    } +}  |