Merge "Simplify HIDDEN_API_ENFORCEMENT_ flags"
diff --git a/api/current.txt b/api/current.txt
index 8704ddc..ff4e00f 100755
--- a/api/current.txt
+++ b/api/current.txt
@@ -42581,6 +42581,7 @@
 
   public class PhoneStateListener {
     ctor public PhoneStateListener();
+    ctor public PhoneStateListener(java.util.concurrent.Executor);
     method public void onCallForwardingIndicatorChanged(boolean);
     method public void onCallStateChanged(int, java.lang.String);
     method public void onCellInfoChanged(java.util.List<android.telephony.CellInfo>);
diff --git a/api/system-current.txt b/api/system-current.txt
index 4a58b75..f9d6701 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -5590,6 +5590,7 @@
     field public static final int RESET_OPTION_DELETE_FIELD_LOADED_TEST_PROFILES = 2; // 0x2
     field public static final int RESET_OPTION_DELETE_OPERATIONAL_PROFILES = 1; // 0x1
     field public static final int RESET_OPTION_RESET_DEFAULT_SMDP_ADDRESS = 4; // 0x4
+    field public static final int RESULT_CALLER_NOT_ALLOWED = -3; // 0xfffffffd
     field public static final int RESULT_EUICC_NOT_FOUND = -2; // 0xfffffffe
     field public static final int RESULT_OK = 0; // 0x0
     field public static final int RESULT_UNKNOWN_ERROR = -1; // 0xffffffff
diff --git a/config/hiddenapi-light-greylist.txt b/config/hiddenapi-light-greylist.txt
index ce0f945..374a336 100644
--- a/config/hiddenapi-light-greylist.txt
+++ b/config/hiddenapi-light-greylist.txt
@@ -1392,18 +1392,6 @@
 Landroid/security/Credentials;->convertToPem([Ljava/security/cert/Certificate;)[B
 Landroid/security/IKeyChainService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/security/IKeyChainService;
 Landroid/security/IKeyChainService;->requestPrivateKey(Ljava/lang/String;)Ljava/lang/String;
-Landroid/security/IKeystoreService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/security/IKeystoreService;
-Landroid/security/IKeystoreService;->clear_uid(J)I
-Landroid/security/IKeystoreService;->del(Ljava/lang/String;I)I
-Landroid/security/IKeystoreService;->exist(Ljava/lang/String;I)I
-Landroid/security/IKeystoreService;->generateKey(Ljava/lang/String;Landroid/security/keymaster/KeymasterArguments;[BIILandroid/security/keymaster/KeyCharacteristics;)I
-Landroid/security/IKeystoreService;->get(Ljava/lang/String;I)[B
-Landroid/security/IKeystoreService;->getState(I)I
-Landroid/security/IKeystoreService;->insert(Ljava/lang/String;[BII)I
-Landroid/security/IKeystoreService;->is_hardware_backed(Ljava/lang/String;)I
-Landroid/security/IKeystoreService;->list(Ljava/lang/String;I)[Ljava/lang/String;
-Landroid/security/IKeystoreService;->reset()I
-Landroid/security/IKeystoreService;->ungrant(Ljava/lang/String;I)I
 Landroid/security/keymaster/KeymasterBlobArgument;-><init>(ILandroid/os/Parcel;)V
 Landroid/security/keymaster/KeymasterBlobArgument;-><init>(I[B)V
 Landroid/security/keymaster/KeymasterBlobArgument;->blob:[B
@@ -1415,6 +1403,17 @@
 Landroid/security/keymaster/KeymasterLongArgument;-><init>(IJ)V
 Landroid/security/keymaster/KeymasterLongArgument;-><init>(ILandroid/os/Parcel;)V
 Landroid/security/keymaster/KeymasterLongArgument;->value:J
+Landroid/security/keystore/IKeystoreService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/security/keystore/IKeystoreService;
+Landroid/security/keystore/IKeystoreService;->clear_uid(J)I
+Landroid/security/keystore/IKeystoreService;->del(Ljava/lang/String;I)I
+Landroid/security/keystore/IKeystoreService;->exist(Ljava/lang/String;I)I
+Landroid/security/keystore/IKeystoreService;->get(Ljava/lang/String;I)[B
+Landroid/security/keystore/IKeystoreService;->getState(I)I
+Landroid/security/keystore/IKeystoreService;->insert(Ljava/lang/String;[BII)I
+Landroid/security/keystore/IKeystoreService;->is_hardware_backed(Ljava/lang/String;)I
+Landroid/security/keystore/IKeystoreService;->list(Ljava/lang/String;I)[Ljava/lang/String;
+Landroid/security/keystore/IKeystoreService;->reset()I
+Landroid/security/keystore/IKeystoreService;->ungrant(Ljava/lang/String;I)I
 Landroid/service/carrier/ICarrierMessagingCallback$Stub;-><init>()V
 Landroid/service/carrier/ICarrierMessagingService;->filterSms(Landroid/service/carrier/MessagePdu;Ljava/lang/String;IILandroid/service/carrier/ICarrierMessagingCallback;)V
 Landroid/service/dreams/IDreamManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/service/dreams/IDreamManager;
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 7b076f6..7aea261 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -6317,6 +6317,7 @@
         public ArrayList<String> usesOptionalLibraries = null;
         @UnsupportedAppUsage
         public String[] usesLibraryFiles = null;
+        public ArrayList<SharedLibraryInfo> usesLibraryInfos = null;
 
         public ArrayList<ActivityIntentInfo> preferredActivityFilters = null;
 
@@ -6846,6 +6847,8 @@
             internStringArrayList(usesOptionalLibraries);
             usesLibraryFiles = dest.readStringArray();
 
+            usesLibraryInfos = dest.createTypedArrayList(SharedLibraryInfo.CREATOR);
+
             final int libCount = dest.readInt();
             if (libCount > 0) {
                 usesStaticLibraries = new ArrayList<>(libCount);
@@ -6996,6 +6999,7 @@
             dest.writeStringList(usesLibraries);
             dest.writeStringList(usesOptionalLibraries);
             dest.writeStringArray(usesLibraryFiles);
+            dest.writeTypedList(usesLibraryInfos);
 
             if (ArrayUtils.isEmpty(usesStaticLibraries)) {
                 dest.writeInt(-1);
@@ -7456,6 +7460,10 @@
                 && p.usesLibraryFiles != null) {
             return true;
         }
+        if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0
+                && p.usesLibraryInfos != null) {
+            return true;
+        }
         if (p.staticSharedLibName != null) {
             return true;
         }
diff --git a/core/java/android/content/pm/SharedLibraryInfo.java b/core/java/android/content/pm/SharedLibraryInfo.java
index 33bc951..a8bbeab0 100644
--- a/core/java/android/content/pm/SharedLibraryInfo.java
+++ b/core/java/android/content/pm/SharedLibraryInfo.java
@@ -19,6 +19,7 @@
 import android.annotation.IntDef;
 import android.annotation.IntRange;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -69,6 +70,8 @@
      */
     public static final int VERSION_UNDEFINED = -1;
 
+    private final String mPath;
+    private final String mPackageName;
     private final String mName;
 
     private final long mVersion;
@@ -87,8 +90,10 @@
      *
      * @hide
      */
-    public SharedLibraryInfo(String name, long version, int type,
+    public SharedLibraryInfo(String path, String packageName, String name, long version, int type,
             VersionedPackage declaringPackage, List<VersionedPackage> dependentPackages) {
+        mPath = path;
+        mPackageName = packageName;
         mName = name;
         mVersion = version;
         mType = type;
@@ -97,8 +102,8 @@
     }
 
     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));
     }
 
     /**
@@ -121,6 +126,30 @@
     }
 
     /**
+     * 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;
+    }
+
+    /**
      * @deprecated Use {@link #getLongVersion()} instead.
      */
     @Deprecated
@@ -196,6 +225,8 @@
 
     @Override
     public void writeToParcel(Parcel parcel, int flags) {
+        parcel.writeString(mPath);
+        parcel.writeString(mPackageName);
         parcel.writeString(mName);
         parcel.writeLong(mVersion);
         parcel.writeInt(mType);
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 221abed..517eaf8 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -2419,7 +2419,7 @@
 
     public static final IntToString[] HISTORY_EVENT_INT_FORMATTERS = new IntToString[] {
             sUidToString, sUidToString, sUidToString, sUidToString, sUidToString, sUidToString,
-            sUidToString, sUidToString, sUidToString, sUidToString, sUidToString, sUidToString,
+            sUidToString, sUidToString, sUidToString, sUidToString, sUidToString, sIntToString,
             sUidToString, sUidToString, sUidToString, sUidToString, sUidToString, sUidToString,
             sUidToString, sUidToString, sUidToString, sIntToString
     };
diff --git a/core/java/android/os/ParcelFileDescriptor.java b/core/java/android/os/ParcelFileDescriptor.java
index 7409ca7..81fc5c0 100644
--- a/core/java/android/os/ParcelFileDescriptor.java
+++ b/core/java/android/os/ParcelFileDescriptor.java
@@ -1092,6 +1092,9 @@
     /**
      * Internal class representing a remote status read by
      * {@link ParcelFileDescriptor#readCommStatus(FileDescriptor, byte[])}.
+     *
+     * Warning: this must be kept in sync with ParcelFileDescriptorStatus at
+     * frameworks/native/libs/binder/Parcel.cpp
      */
     private static class Status {
         /** Special value indicating remote side died. */
diff --git a/core/java/android/security/keymaster/ExportResult.java b/core/java/android/security/keymaster/ExportResult.java
index c104671..1ab79fb 100644
--- a/core/java/android/security/keymaster/ExportResult.java
+++ b/core/java/android/security/keymaster/ExportResult.java
@@ -28,6 +28,11 @@
     public final int resultCode;
     public final byte[] exportData;
 
+    public ExportResult(int resultCode) {
+        this.resultCode = resultCode;
+        this.exportData = new byte[0];
+    }
+
     @UnsupportedAppUsage
     public static final Parcelable.Creator<ExportResult> CREATOR = new
             Parcelable.Creator<ExportResult>() {
diff --git a/core/java/android/security/keymaster/KeyCharacteristics.java b/core/java/android/security/keymaster/KeyCharacteristics.java
index 555863e..a4fe75d 100644
--- a/core/java/android/security/keymaster/KeyCharacteristics.java
+++ b/core/java/android/security/keymaster/KeyCharacteristics.java
@@ -52,6 +52,14 @@
         readFromParcel(in);
     }
 
+    /**
+     * Makes a shallow copy of other by copying the other's references to the KeymasterArguments
+     */
+    public void shallowCopyFrom(KeyCharacteristics other) {
+        this.swEnforced = other.swEnforced;
+        this.hwEnforced = other.hwEnforced;
+    }
+
     @Override
     public int describeContents() {
         return 0;
diff --git a/core/java/android/security/keymaster/KeymasterCertificateChain.java b/core/java/android/security/keymaster/KeymasterCertificateChain.java
index 243b9fe..00a1a1c 100644
--- a/core/java/android/security/keymaster/KeymasterCertificateChain.java
+++ b/core/java/android/security/keymaster/KeymasterCertificateChain.java
@@ -54,6 +54,14 @@
         readFromParcel(in);
     }
 
+    /**
+     * Makes a shallow copy of other by copying the reference to the certificate chain list.
+     * @param other
+     */
+    public void shallowCopyFrom(KeymasterCertificateChain other) {
+        this.mCertificates = other.mCertificates;
+    }
+
     public List<byte[]> getCertificates() {
         return mCertificates;
     }
diff --git a/core/java/android/security/keymaster/OperationResult.java b/core/java/android/security/keymaster/OperationResult.java
index 2943211..bc4f360 100644
--- a/core/java/android/security/keymaster/OperationResult.java
+++ b/core/java/android/security/keymaster/OperationResult.java
@@ -59,6 +59,10 @@
         this.outParams = outParams;
     }
 
+    public OperationResult(int resultCode) {
+        this(resultCode, null, 0, 0, null, null);
+    }
+
     protected OperationResult(Parcel in) {
         resultCode = in.readInt();
         token = in.readStrongBinder();
diff --git a/data/etc/Android.mk b/data/etc/Android.mk
index 936ad22..d24c140a 100644
--- a/data/etc/Android.mk
+++ b/data/etc/Android.mk
@@ -47,3 +47,11 @@
 LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/sysconfig
 LOCAL_SRC_FILES := $(LOCAL_MODULE)
 include $(BUILD_PREBUILT)
+
+########################
+include $(CLEAR_VARS)
+LOCAL_MODULE := com.android.timezone.updater.xml
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_RELATIVE_PATH := permissions
+LOCAL_SRC_FILES := $(LOCAL_MODULE)
+include $(BUILD_PREBUILT)
diff --git a/data/etc/com.android.timezone.updater.xml b/data/etc/com.android.timezone.updater.xml
new file mode 100644
index 0000000..60a66e2
--- /dev/null
+++ b/data/etc/com.android.timezone.updater.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2018 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<permissions>
+    <privapp-permissions package="com.android.timezone.updater">
+        <permission name="android.permission.QUERY_TIME_ZONE_RULES" />
+        <permission name="android.permission.UPDATE_TIME_ZONE_RULES" />
+    </privapp-permissions>
+</permissions>
diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java
index 4e01883..2d214a7 100644
--- a/keystore/java/android/security/KeyStore.java
+++ b/keystore/java/android/security/KeyStore.java
@@ -38,11 +38,13 @@
 import android.security.keymaster.KeymasterCertificateChain;
 import android.security.keymaster.KeymasterDefs;
 import android.security.keymaster.OperationResult;
+import android.security.keystore.IKeystoreService;
 import android.security.keystore.KeyExpiredException;
 import android.security.keystore.KeyNotYetValidException;
 import android.security.keystore.KeyPermanentlyInvalidatedException;
 import android.security.keystore.KeyProperties;
 import android.security.keystore.KeyProtection;
+import android.security.keystore.KeystoreResponse;
 import android.security.keystore.StrongBoxUnavailableException;
 import android.security.keystore.UserNotAuthenticatedException;
 import android.util.Log;
@@ -54,6 +56,8 @@
 import java.security.InvalidKeyException;
 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;
 
@@ -440,27 +444,107 @@
 
     public boolean addRngEntropy(byte[] data, int flags) {
         try {
-            return mBinder.addRngEntropy(data, flags) == NO_ERROR;
+            KeystoreResultPromise promise = new KeystoreResultPromise();
+            int errorCode = mBinder.addRngEntropy(promise, data, flags);
+            if (errorCode == NO_ERROR) {
+                return promise.getFuture().get().getErrorCode() == NO_ERROR;
+            } else {
+                return false;
+            }
         } catch (RemoteException e) {
             Log.w(TAG, "Cannot connect to keystore", e);
             return false;
+        } catch (ExecutionException | InterruptedException e) {
+            Log.e(TAG, "AddRngEntropy completed with exception", e);
+            return false;
         }
     }
 
+    private class KeyCharacteristicsCallbackResult {
+        private KeystoreResponse keystoreResponse;
+        private KeyCharacteristics keyCharacteristics;
+
+        public KeyCharacteristicsCallbackResult(KeystoreResponse keystoreResponse,
+                                                KeyCharacteristics keyCharacteristics) {
+            this.keystoreResponse = keystoreResponse;
+            this.keyCharacteristics = keyCharacteristics;
+        }
+
+        public KeystoreResponse getKeystoreResponse() {
+            return keystoreResponse;
+        }
+
+        public void setKeystoreResponse(KeystoreResponse keystoreResponse) {
+            this.keystoreResponse = keystoreResponse;
+        }
+
+        public KeyCharacteristics getKeyCharacteristics() {
+            return keyCharacteristics;
+        }
+
+        public void setKeyCharacteristics(KeyCharacteristics keyCharacteristics) {
+            this.keyCharacteristics = keyCharacteristics;
+        }
+    }
+
+    private class KeyCharacteristicsPromise
+    extends android.security.keystore.IKeystoreKeyCharacteristicsCallback.Stub {
+        final private CompletableFuture<KeyCharacteristicsCallbackResult> future =
+                new CompletableFuture<KeyCharacteristicsCallbackResult>();
+        @Override
+        public void onFinished(KeystoreResponse keystoreResponse,
+                               KeyCharacteristics keyCharacteristics)
+                                       throws android.os.RemoteException {
+            future.complete(
+                    new KeyCharacteristicsCallbackResult(keystoreResponse, keyCharacteristics));
+        }
+        public final CompletableFuture<KeyCharacteristicsCallbackResult> getFuture() {
+            return future;
+        }
+    };
+
+    private int generateKeyInternal(String alias, KeymasterArguments args, byte[] entropy, int uid,
+            int flags, KeyCharacteristics outCharacteristics)
+                    throws RemoteException, ExecutionException, InterruptedException {
+        KeyCharacteristicsPromise promise = new KeyCharacteristicsPromise();
+        int error = mBinder.generateKey(promise, alias, args, entropy, uid, flags);
+        if (error != NO_ERROR) {
+            Log.e(TAG, "generateKeyInternal failed on request " + error);
+            return error;
+        }
+
+        KeyCharacteristicsCallbackResult result = promise.getFuture().get();
+        error = result.getKeystoreResponse().getErrorCode();
+        if (error != NO_ERROR) {
+            Log.e(TAG, "generateKeyInternal failed on response " + error);
+            return error;
+        }
+        KeyCharacteristics characteristics = result.getKeyCharacteristics();
+        if (characteristics == null) {
+            Log.e(TAG, "generateKeyInternal got empty key cheractariestics " + error);
+            return SYSTEM_ERROR;
+        }
+        outCharacteristics.shallowCopyFrom(characteristics);
+        return NO_ERROR;
+    }
+
     public int generateKey(String alias, KeymasterArguments args, byte[] entropy, int uid,
             int flags, KeyCharacteristics outCharacteristics) {
         try {
             entropy = entropy != null ? entropy : new byte[0];
             args = args != null ? args : new KeymasterArguments();
-            int error = mBinder.generateKey(alias, args, entropy, uid, flags, outCharacteristics);
+            int error = generateKeyInternal(alias, args, entropy, uid, flags, outCharacteristics);
             if (error == KEY_ALREADY_EXISTS) {
                 mBinder.del(alias, uid);
-                error = mBinder.generateKey(alias, args, entropy, uid, flags, outCharacteristics);
+                error = generateKeyInternal(alias, args, entropy, uid, flags, outCharacteristics);
             }
             return error;
         } catch (RemoteException e) {
             Log.w(TAG, "Cannot connect to keystore", e);
             return SYSTEM_ERROR;
+        } catch (ExecutionException | InterruptedException e) {
+            Log.e(TAG, "generateKey completed with exception", e);
+            return SYSTEM_ERROR;
         }
     }
 
@@ -474,10 +558,24 @@
         try {
             clientId = clientId != null ? clientId : new KeymasterBlob(new byte[0]);
             appId = appId != null ? appId : new KeymasterBlob(new byte[0]);
-            return mBinder.getKeyCharacteristics(alias, clientId, appId, uid, outCharacteristics);
+            KeyCharacteristicsPromise promise = new KeyCharacteristicsPromise();
+            int error = mBinder.getKeyCharacteristics(promise, alias, clientId, appId, uid);
+            if (error != NO_ERROR) return error;
+
+            KeyCharacteristicsCallbackResult result = promise.getFuture().get();
+            error = result.getKeystoreResponse().getErrorCode();
+            if (error != NO_ERROR) return error;
+
+            KeyCharacteristics characteristics = result.getKeyCharacteristics();
+            if (characteristics == null) return SYSTEM_ERROR;
+            outCharacteristics.shallowCopyFrom(characteristics);
+            return NO_ERROR;
         } catch (RemoteException e) {
             Log.w(TAG, "Cannot connect to keystore", e);
             return SYSTEM_ERROR;
+        } catch (ExecutionException | InterruptedException e) {
+            Log.e(TAG, "GetKeyCharacteristics completed with exception", e);
+            return SYSTEM_ERROR;
         }
     }
 
@@ -486,20 +584,40 @@
         return getKeyCharacteristics(alias, clientId, appId, UID_SELF, outCharacteristics);
     }
 
+    private int importKeyInternal(String alias, KeymasterArguments args, int format, byte[] keyData,
+            int uid, int flags, KeyCharacteristics outCharacteristics)
+                    throws RemoteException, ExecutionException, InterruptedException {
+        KeyCharacteristicsPromise promise = new KeyCharacteristicsPromise();
+        int error = mBinder.importKey(promise, alias, args, format, keyData, uid, flags);
+        if (error != NO_ERROR) return error;
+
+        KeyCharacteristicsCallbackResult result = promise.getFuture().get();
+        error = result.getKeystoreResponse().getErrorCode();
+        if (error != NO_ERROR) return error;
+
+        KeyCharacteristics characteristics = result.getKeyCharacteristics();
+        if (characteristics == null) return SYSTEM_ERROR;
+        outCharacteristics.shallowCopyFrom(characteristics);
+        return NO_ERROR;
+    }
+
     public int importKey(String alias, KeymasterArguments args, int format, byte[] keyData,
             int uid, int flags, KeyCharacteristics outCharacteristics) {
         try {
-            int error = mBinder.importKey(alias, args, format, keyData, uid, flags,
+            int error = importKeyInternal(alias, args, format, keyData, uid, flags,
                     outCharacteristics);
             if (error == KEY_ALREADY_EXISTS) {
                 mBinder.del(alias, uid);
-                error = mBinder.importKey(alias, args, format, keyData, uid, flags,
+                error = importKeyInternal(alias, args, format, keyData, uid, flags,
                         outCharacteristics);
             }
             return error;
         } catch (RemoteException e) {
             Log.w(TAG, "Cannot connect to keystore", e);
             return SYSTEM_ERROR;
+        } catch (ExecutionException | InterruptedException e) {
+            Log.e(TAG, "ImportKey completed with exception", e);
+            return SYSTEM_ERROR;
         }
     }
 
@@ -567,34 +685,79 @@
         return true;
     }
 
+    private int importWrappedKeyInternal(String wrappedKeyAlias, byte[] wrappedKey,
+            String wrappingKeyAlias,
+            byte[] maskingKey, KeymasterArguments args, long rootSid, long fingerprintSid,
+            KeyCharacteristics outCharacteristics)
+                    throws RemoteException, ExecutionException, InterruptedException {
+        KeyCharacteristicsPromise promise = new KeyCharacteristicsPromise();
+        int error = mBinder.importWrappedKey(promise, wrappedKeyAlias, wrappedKey, wrappingKeyAlias,
+                maskingKey, args, rootSid, fingerprintSid);
+        if (error != NO_ERROR) return error;
+
+        KeyCharacteristicsCallbackResult result = promise.getFuture().get();
+        error = result.getKeystoreResponse().getErrorCode();
+        if (error != NO_ERROR) return error;
+
+        KeyCharacteristics characteristics = result.getKeyCharacteristics();
+        if (characteristics == null) return SYSTEM_ERROR;
+        outCharacteristics.shallowCopyFrom(characteristics);
+        return NO_ERROR;
+    }
+
     public int importWrappedKey(String wrappedKeyAlias, byte[] wrappedKey,
             String wrappingKeyAlias,
             byte[] maskingKey, KeymasterArguments args, long rootSid, long fingerprintSid, int uid,
             KeyCharacteristics outCharacteristics) {
+        // TODO b/119217337 uid parameter gets silently ignored.
         try {
-            int error = mBinder.importWrappedKey(wrappedKeyAlias, wrappedKey, wrappingKeyAlias,
+            int error = importWrappedKeyInternal(wrappedKeyAlias, wrappedKey, wrappingKeyAlias,
                     maskingKey, args, rootSid, fingerprintSid, outCharacteristics);
             if (error == KEY_ALREADY_EXISTS) {
-                mBinder.del(wrappedKeyAlias, -1);
-                error = mBinder.importWrappedKey(wrappedKeyAlias, wrappedKey, wrappingKeyAlias,
+                mBinder.del(wrappedKeyAlias, UID_SELF);
+                error = importWrappedKeyInternal(wrappedKeyAlias, wrappedKey, wrappingKeyAlias,
                         maskingKey, args, rootSid, fingerprintSid, outCharacteristics);
             }
             return error;
         } catch (RemoteException e) {
             Log.w(TAG, "Cannot connect to keystore", e);
             return SYSTEM_ERROR;
+        } catch (ExecutionException | InterruptedException e) {
+            Log.e(TAG, "ImportWrappedKey completed with exception", e);
+            return SYSTEM_ERROR;
         }
     }
 
+    private class ExportKeyPromise
+    extends android.security.keystore.IKeystoreExportKeyCallback.Stub {
+        final private CompletableFuture<ExportResult> future = new CompletableFuture<ExportResult>();
+        @Override
+        public void onFinished(ExportResult exportKeyResult) throws android.os.RemoteException {
+            future.complete(exportKeyResult);
+        }
+        public final CompletableFuture<ExportResult> getFuture() {
+            return future;
+        }
+    };
+
     public ExportResult exportKey(String alias, int format, KeymasterBlob clientId,
             KeymasterBlob appId, int uid) {
         try {
             clientId = clientId != null ? clientId : new KeymasterBlob(new byte[0]);
             appId = appId != null ? appId : new KeymasterBlob(new byte[0]);
-            return mBinder.exportKey(alias, format, clientId, appId, uid);
+            ExportKeyPromise promise = new ExportKeyPromise();
+            int error = mBinder.exportKey(promise, alias, format, clientId, appId, uid);
+            if (error == NO_ERROR) {
+                return promise.getFuture().get();
+            } else {
+                return new ExportResult(error);
+            }
         } catch (RemoteException e) {
             Log.w(TAG, "Cannot connect to keystore", e);
             return null;
+        } catch (ExecutionException | InterruptedException e) {
+            Log.e(TAG, "ExportKey completed with exception", e);
+            return null;
         }
     }
     public ExportResult exportKey(String alias, int format, KeymasterBlob clientId,
@@ -602,15 +765,37 @@
         return exportKey(alias, format, clientId, appId, UID_SELF);
     }
 
+    private class OperationPromise
+    extends android.security.keystore.IKeystoreOperationResultCallback.Stub {
+        final private CompletableFuture<OperationResult> future = new CompletableFuture<OperationResult>();
+        @Override
+        public void onFinished(OperationResult operationResult) throws android.os.RemoteException {
+            future.complete(operationResult);
+        }
+        public final CompletableFuture<OperationResult> getFuture() {
+            return future;
+        }
+    };
+
     public OperationResult begin(String alias, int purpose, boolean pruneable,
             KeymasterArguments args, byte[] entropy, int uid) {
         try {
             args = args != null ? args : new KeymasterArguments();
             entropy = entropy != null ? entropy : new byte[0];
-            return mBinder.begin(getToken(), alias, purpose, pruneable, args, entropy, uid);
+            OperationPromise promise = new OperationPromise();
+            int errorCode =  mBinder.begin(promise, getToken(), alias, purpose, pruneable, args,
+                                           entropy, uid);
+            if (errorCode == NO_ERROR) {
+                return promise.getFuture().get();
+            } else {
+                return new OperationResult(errorCode);
+            }
         } catch (RemoteException e) {
             Log.w(TAG, "Cannot connect to keystore", e);
             return null;
+        } catch (ExecutionException | InterruptedException e) {
+            Log.e(TAG, "Begin completed with exception", e);
+            return null;
         }
     }
 
@@ -625,10 +810,19 @@
         try {
             arguments = arguments != null ? arguments : new KeymasterArguments();
             input = input != null ? input : new byte[0];
-            return mBinder.update(token, arguments, input);
+            OperationPromise promise = new OperationPromise();
+            int errorCode =  mBinder.update(promise, token, arguments, input);
+            if (errorCode == NO_ERROR) {
+                return promise.getFuture().get();
+            } else {
+                return new OperationResult(errorCode);
+            }
         } catch (RemoteException e) {
             Log.w(TAG, "Cannot connect to keystore", e);
             return null;
+        } catch (ExecutionException | InterruptedException e) {
+            Log.e(TAG, "Update completed with exception", e);
+            return null;
         }
     }
 
@@ -638,10 +832,19 @@
             arguments = arguments != null ? arguments : new KeymasterArguments();
             entropy = entropy != null ? entropy : new byte[0];
             signature = signature != null ? signature : new byte[0];
-            return mBinder.finish(token, arguments, signature, entropy);
+            OperationPromise promise = new OperationPromise();
+            int errorCode = mBinder.finish(promise, token, arguments, signature, entropy);
+            if (errorCode == NO_ERROR) {
+                return promise.getFuture().get();
+            } else {
+                return new OperationResult(errorCode);
+            }
         } catch (RemoteException e) {
             Log.w(TAG, "Cannot connect to keystore", e);
             return null;
+        } catch (ExecutionException | InterruptedException e) {
+            Log.e(TAG, "Finish completed with exception", e);
+            return null;
         }
     }
 
@@ -649,12 +852,33 @@
         return finish(token, arguments, signature, null);
     }
 
+    private class KeystoreResultPromise
+    extends android.security.keystore.IKeystoreResponseCallback.Stub {
+        final private CompletableFuture<KeystoreResponse> future = new CompletableFuture<KeystoreResponse>();
+        @Override
+        public void onFinished(KeystoreResponse keystoreResponse) throws android.os.RemoteException {
+            future.complete(keystoreResponse);
+        }
+        public final CompletableFuture<KeystoreResponse> getFuture() {
+            return future;
+        }
+    };
+
     public int abort(IBinder token) {
         try {
-            return mBinder.abort(token);
+            KeystoreResultPromise promise = new KeystoreResultPromise();
+            int errorCode = mBinder.abort(promise, token);
+            if (errorCode == NO_ERROR) {
+                return promise.getFuture().get().getErrorCode();
+            } else {
+                return errorCode;
+            }
         } catch (RemoteException e) {
             Log.w(TAG, "Cannot connect to keystore", e);
             return SYSTEM_ERROR;
+        } catch (ExecutionException | InterruptedException e) {
+            Log.e(TAG, "Abort completed with exception", e);
+            return SYSTEM_ERROR;
         }
     }
 
@@ -736,6 +960,47 @@
         return onUserPasswordChanged(UserHandle.getUserId(Process.myUid()), newPassword);
     }
 
+    private class KeyAttestationCallbackResult {
+        private KeystoreResponse keystoreResponse;
+        private KeymasterCertificateChain certificateChain;
+
+        public KeyAttestationCallbackResult(KeystoreResponse keystoreResponse,
+                KeymasterCertificateChain certificateChain) {
+            this.keystoreResponse = keystoreResponse;
+            this.certificateChain = certificateChain;
+        }
+
+        public KeystoreResponse getKeystoreResponse() {
+            return keystoreResponse;
+        }
+
+        public void setKeystoreResponse(KeystoreResponse keystoreResponse) {
+            this.keystoreResponse = keystoreResponse;
+        }
+
+        public KeymasterCertificateChain getCertificateChain() {
+            return certificateChain;
+        }
+
+        public void setCertificateChain(KeymasterCertificateChain certificateChain) {
+            this.certificateChain = certificateChain;
+        }
+    }
+
+    private class CertificateChainPromise
+    extends android.security.keystore.IKeystoreCertificateChainCallback.Stub {
+        final private CompletableFuture<KeyAttestationCallbackResult> future = new CompletableFuture<KeyAttestationCallbackResult>();
+        @Override
+        public void onFinished(KeystoreResponse keystoreResponse,
+                KeymasterCertificateChain certificateChain) throws android.os.RemoteException {
+            future.complete(new KeyAttestationCallbackResult(keystoreResponse, certificateChain));
+        }
+        public final CompletableFuture<KeyAttestationCallbackResult> getFuture() {
+            return future;
+        }
+    };
+
+
     public int attestKey(
             String alias, KeymasterArguments params, KeymasterCertificateChain outChain) {
         try {
@@ -745,10 +1010,21 @@
             if (outChain == null) {
                 outChain = new KeymasterCertificateChain();
             }
-            return mBinder.attestKey(alias, params, outChain);
+            CertificateChainPromise promise = new CertificateChainPromise();
+            int error = mBinder.attestKey(promise, alias, params);
+            if (error != NO_ERROR) return error;
+            KeyAttestationCallbackResult result = promise.getFuture().get();
+            error = result.getKeystoreResponse().getErrorCode();
+            if (error == NO_ERROR) {
+                outChain.shallowCopyFrom(result.getCertificateChain());
+            }
+            return error;
         } catch (RemoteException e) {
             Log.w(TAG, "Cannot connect to keystore", e);
             return SYSTEM_ERROR;
+        } catch (ExecutionException | InterruptedException e) {
+            Log.e(TAG, "AttestKey completed with exception", e);
+            return SYSTEM_ERROR;
         }
     }
 
@@ -760,10 +1036,21 @@
             if (outChain == null) {
                 outChain = new KeymasterCertificateChain();
             }
-            return mBinder.attestDeviceIds(params, outChain);
+            CertificateChainPromise promise = new CertificateChainPromise();
+            int error = mBinder.attestDeviceIds(promise, params);
+            if (error != NO_ERROR) return error;
+            KeyAttestationCallbackResult result = promise.getFuture().get();
+            error = result.getKeystoreResponse().getErrorCode();
+            if (error == NO_ERROR) {
+                outChain.shallowCopyFrom(result.getCertificateChain());
+            }
+            return error;
         } catch (RemoteException e) {
             Log.w(TAG, "Cannot connect to keystore", e);
             return SYSTEM_ERROR;
+        } catch (ExecutionException | InterruptedException e) {
+            Log.e(TAG, "AttestDevicdeIds completed with exception", e);
+            return SYSTEM_ERROR;
         }
     }
 
diff --git a/keystore/java/android/security/keystore/KeystoreResponse.java b/keystore/java/android/security/keystore/KeystoreResponse.java
new file mode 100644
index 0000000..3a229cb
--- /dev/null
+++ b/keystore/java/android/security/keystore/KeystoreResponse.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.keystore;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.ParcelFormatException;
+
+/**
+ * The Java side of the KeystoreResponse.
+ * <p>
+ * Serialization code for this and subclasses must be kept in sync with system/security/keystore.
+ * @hide
+ */
+public class KeystoreResponse implements Parcelable {
+    public final int error_code_;
+    public final String error_msg_;
+
+    public static final Parcelable.Creator<KeystoreResponse> CREATOR = new
+            Parcelable.Creator<KeystoreResponse>() {
+                @Override
+                public KeystoreResponse createFromParcel(Parcel in) {
+                    final int error_code = in.readInt();
+                    final String error_msg = in.readString();
+                    return new KeystoreResponse(error_code, error_msg);
+                }
+
+                @Override
+                public KeystoreResponse[] newArray(int size) {
+                    return new KeystoreResponse[size];
+                }
+            };
+
+    protected KeystoreResponse(int error_code, String error_msg) {
+        this.error_code_ = error_code;
+        this.error_msg_ = error_msg;
+    }
+
+    /**
+     * @return the error_code_
+     */
+    public final int getErrorCode() {
+        return error_code_;
+    }
+
+    /**
+     * @return the error_msg_
+     */
+    public final String getErrorMessage() {
+        return error_msg_;
+    }
+
+    
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeInt(error_code_);
+        out.writeString(error_msg_);
+    }
+}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index f279f0e..724d207 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -901,23 +901,9 @@
     final ParallelPackageParserCallback mParallelPackageParserCallback =
             new ParallelPackageParserCallback();
 
-    public static final class SharedLibraryEntry {
-        public final @Nullable String path;
-        public final @Nullable String apk;
-        public final @NonNull SharedLibraryInfo info;
-
-        SharedLibraryEntry(String _path, String _apk, String name, long version, int type,
-                String declaringPackageName, long declaringPackageVersionCode) {
-            path = _path;
-            apk = _apk;
-            info = new SharedLibraryInfo(name, version, type, new VersionedPackage(
-                    declaringPackageName, declaringPackageVersionCode), null);
-        }
-    }
-
     // Currently known shared libraries.
-    final ArrayMap<String, LongSparseArray<SharedLibraryEntry>> mSharedLibraries = new ArrayMap<>();
-    final ArrayMap<String, LongSparseArray<SharedLibraryEntry>> mStaticLibsByDeclaringPackage =
+    final ArrayMap<String, LongSparseArray<SharedLibraryInfo>> mSharedLibraries = new ArrayMap<>();
+    final ArrayMap<String, LongSparseArray<SharedLibraryInfo>> mStaticLibsByDeclaringPackage =
             new ArrayMap<>();
 
     // All available activities, for your resolving pleasure.
@@ -3512,11 +3498,15 @@
 
     private @NonNull String getRequiredSharedLibraryLPr(String name, int version) {
         synchronized (mPackages) {
-            SharedLibraryEntry libraryEntry = getSharedLibraryEntryLPr(name, version);
-            if (libraryEntry == null) {
+            SharedLibraryInfo libraryInfo = getSharedLibraryInfoLPr(name, version);
+            if (libraryInfo == null) {
                 throw new IllegalStateException("Missing required shared library:" + name);
             }
-            return libraryEntry.apk;
+            String packageName = libraryInfo.getPackageName();
+            if (packageName == null) {
+                throw new IllegalStateException("Expected a package for shared library " + name);
+            }
+            return packageName;
         }
     }
 
@@ -4249,9 +4239,9 @@
             return false;
         }
 
-        final SharedLibraryEntry libEntry = getSharedLibraryEntryLPr(ps.pkg.staticSharedLibName,
+        final SharedLibraryInfo libraryInfo = getSharedLibraryInfoLPr(ps.pkg.staticSharedLibName,
                 ps.pkg.staticSharedLibVersion);
-        if (libEntry == null) {
+        if (libraryInfo == null) {
             return false;
         }
 
@@ -4268,11 +4258,11 @@
             PackageSetting uidPs = mSettings.getPackageLPr(uidPackageName);
             if (uidPs != null) {
                 final int index = ArrayUtils.indexOf(uidPs.usesStaticLibraries,
-                        libEntry.info.getName());
+                        libraryInfo.getName());
                 if (index < 0) {
                     continue;
                 }
-                if (uidPs.pkg.usesStaticLibrariesVersions[index] == libEntry.info.getLongVersion()) {
+                if (uidPs.pkg.usesStaticLibrariesVersions[index] == libraryInfo.getLongVersion()) {
                     return false;
                 }
             }
@@ -4668,14 +4658,14 @@
             final int[] allUsers = sUserManager.getUserIds();
             final int libCount = mSharedLibraries.size();
             for (int i = 0; i < libCount; i++) {
-                final LongSparseArray<SharedLibraryEntry> versionedLib
+                final LongSparseArray<SharedLibraryInfo> versionedLib
                         = mSharedLibraries.valueAt(i);
                 if (versionedLib == null) {
                     continue;
                 }
                 final int versionCount = versionedLib.size();
                 for (int j = 0; j < versionCount; j++) {
-                    SharedLibraryInfo libInfo = versionedLib.valueAt(j).info;
+                    SharedLibraryInfo libInfo = versionedLib.valueAt(j);
                     // Skip packages that are not static shared libs.
                     if (!libInfo.isStatic()) {
                         break;
@@ -5041,14 +5031,14 @@
 
             final int libCount = mSharedLibraries.size();
             for (int i = 0; i < libCount; i++) {
-                LongSparseArray<SharedLibraryEntry> versionedLib = mSharedLibraries.valueAt(i);
+                LongSparseArray<SharedLibraryInfo> versionedLib = mSharedLibraries.valueAt(i);
                 if (versionedLib == null) {
                     continue;
                 }
 
                 final int versionCount = versionedLib.size();
                 for (int j = 0; j < versionCount; j++) {
-                    SharedLibraryInfo libInfo = versionedLib.valueAt(j).info;
+                    SharedLibraryInfo libInfo = versionedLib.valueAt(j);
                     if (!canSeeStaticLibraries && libInfo.isStatic()) {
                         break;
                     }
@@ -5064,10 +5054,10 @@
                         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));
 
                     if (result == null) {
                         result = new ArrayList<>();
@@ -5182,28 +5172,28 @@
             Set<String> libs = null;
             final int libCount = mSharedLibraries.size();
             for (int i = 0; i < libCount; i++) {
-                LongSparseArray<SharedLibraryEntry> versionedLib = mSharedLibraries.valueAt(i);
+                LongSparseArray<SharedLibraryInfo> versionedLib = mSharedLibraries.valueAt(i);
                 if (versionedLib == null) {
                     continue;
                 }
                 final int versionCount = versionedLib.size();
                 for (int j = 0; j < versionCount; j++) {
-                    SharedLibraryEntry libEntry = versionedLib.valueAt(j);
-                    if (!libEntry.info.isStatic()) {
+                    SharedLibraryInfo libraryInfo = versionedLib.valueAt(j);
+                    if (!libraryInfo.isStatic()) {
                         if (libs == null) {
                             libs = new ArraySet<>();
                         }
-                        libs.add(libEntry.info.getName());
+                        libs.add(libraryInfo.getName());
                         break;
                     }
-                    PackageSetting ps = mSettings.getPackageLPr(libEntry.apk);
+                    PackageSetting ps = mSettings.getPackageLPr(libraryInfo.getPackageName());
                     if (ps != null && !filterSharedLibPackageLPr(ps, Binder.getCallingUid(),
                             UserHandle.getUserId(Binder.getCallingUid()),
                             PackageManager.MATCH_STATIC_SHARED_LIBRARIES)) {
                         if (libs == null) {
                             libs = new ArraySet<>();
                         }
-                        libs.add(libEntry.info.getName());
+                        libs.add(libraryInfo.getName());
                         break;
                     }
                 }
@@ -9451,24 +9441,24 @@
 
     private PackageParser.Package findSharedNonSystemLibrary(String name, long version) {
         synchronized (mPackages) {
-            SharedLibraryEntry libEntry = getSharedLibraryEntryLPr(name, version);
-            if (libEntry != null) {
-                return mPackages.get(libEntry.apk);
+            SharedLibraryInfo libraryInfo = getSharedLibraryInfoLPr(name, version);
+            if (libraryInfo != null) {
+                return mPackages.get(libraryInfo.getPackageName());
             }
             return null;
         }
     }
 
-    private SharedLibraryEntry getSharedLibraryEntryLPr(String name, long version) {
-        LongSparseArray<SharedLibraryEntry> versionedLib = mSharedLibraries.get(name);
+    private 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;
@@ -9701,14 +9691,15 @@
     }
 
     private void addSharedLibraryLPr(Set<String> usesLibraryFiles,
-            SharedLibraryEntry file,
+            SharedLibraryInfo file,
             PackageParser.Package changingLib) {
-        if (file.path != null) {
-            usesLibraryFiles.add(file.path);
+
+        if (file.getPath() != null) {
+            usesLibraryFiles.add(file.getPath());
             return;
         }
-        PackageParser.Package p = mPackages.get(file.apk);
-        if (changingLib != null && changingLib.packageName.equals(file.apk)) {
+        PackageParser.Package p = mPackages.get(file.getPackageName());
+        if (changingLib != null && changingLib.packageName.equals(file.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
@@ -9733,42 +9724,52 @@
         // The collection used here must maintain the order of addition (so
         // that libraries are searched in the correct order) and must have no
         // duplicates.
-        Set<String> usesLibraryFiles = null;
+        ArrayList<SharedLibraryInfo> usesLibraryInfos = null;
         if (pkg.usesLibraries != null) {
-            usesLibraryFiles = addSharedLibrariesLPw(pkg.usesLibraries,
-                    null, null, pkg.packageName, changingLib, true,
+            usesLibraryInfos = addSharedLibrariesLPw(pkg.usesLibraries,
+                    null, null, pkg.packageName, true,
                     pkg.applicationInfo.targetSdkVersion, null);
         }
         if (pkg.usesStaticLibraries != null) {
-            usesLibraryFiles = addSharedLibrariesLPw(pkg.usesStaticLibraries,
+            usesLibraryInfos = addSharedLibrariesLPw(pkg.usesStaticLibraries,
                     pkg.usesStaticLibrariesVersions, pkg.usesStaticLibrariesCertDigests,
-                    pkg.packageName, changingLib, true,
-                    pkg.applicationInfo.targetSdkVersion, usesLibraryFiles);
+                    pkg.packageName, true,
+                    pkg.applicationInfo.targetSdkVersion, usesLibraryInfos);
         }
         if (pkg.usesOptionalLibraries != null) {
-            usesLibraryFiles = addSharedLibrariesLPw(pkg.usesOptionalLibraries,
-                    null, null, pkg.packageName, changingLib, false,
-                    pkg.applicationInfo.targetSdkVersion, usesLibraryFiles);
+            usesLibraryInfos = addSharedLibrariesLPw(pkg.usesOptionalLibraries,
+                    null, null, pkg.packageName, false,
+                    pkg.applicationInfo.targetSdkVersion, usesLibraryInfos);
         }
-        if (!ArrayUtils.isEmpty(usesLibraryFiles)) {
+        if (usesLibraryInfos != null) {
+            pkg.usesLibraryInfos = usesLibraryInfos;
+            // Use LinkedHashSet to preserve the order of files added to
+            // usesLibraryFiles while eliminating duplicates.
+            Set<String> usesLibraryFiles = new LinkedHashSet<>();
+            for (SharedLibraryInfo libInfo : usesLibraryInfos) {
+                addSharedLibraryLPr(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 +9781,14 @@
                 }
             } else {
                 if (requiredVersions != null && requiredCertDigests != null) {
-                    if (libEntry.info.getLongVersion() != requiredVersions[i]) {
+                    if (libraryInfo.getLongVersion() != requiredVersions[i]) {
                         throw new PackageManagerException(INSTALL_FAILED_MISSING_SHARED_LIBRARY,
                             "Package " + packageName + " requires unavailable static shared"
                                     + " library " + libName + " version "
-                                    + libEntry.info.getLongVersion() + "; failing!");
+                                    + libraryInfo.getLongVersion() + "; failing!");
                     }
 
-                    PackageParser.Package libPkg = mPackages.get(libEntry.apk);
+                    PackageParser.Package libPkg = mPackages.get(libraryInfo.getPackageName());
                     if (libPkg == null) {
                         throw new PackageManagerException(INSTALL_FAILED_MISSING_SHARED_LIBRARY,
                                 "Package " + packageName + " requires unavailable static shared"
@@ -9844,11 +9845,9 @@
                 }
 
                 if (outUsedLibraries == null) {
-                    // Use LinkedHashSet to preserve the order of files added to
-                    // usesLibraryFiles while eliminating duplicates.
-                    outUsedLibraries = new LinkedHashSet<>();
+                    outUsedLibraries = new ArrayList<>();
                 }
-                addSharedLibraryLPr(outUsedLibraries, libEntry, changingLib);
+                outUsedLibraries.add(libraryInfo);
             }
         }
         return outUsedLibraries;
@@ -10230,9 +10229,9 @@
         // library in order to compare signatures.
         PackageSetting signatureCheckPs = pkgSetting;
         if (pkg.applicationInfo.isStaticSharedLibrary()) {
-            SharedLibraryEntry libraryEntry = getLatestSharedLibraVersionLPr(pkg);
-            if (libraryEntry != null) {
-                signatureCheckPs = mSettings.getPackageLPr(libraryEntry.apk);
+            SharedLibraryInfo libraryInfo = getLatestSharedLibraVersionLPr(pkg);
+            if (libraryInfo != null) {
+                signatureCheckPs = mSettings.getPackageLPr(libraryInfo.getPackageName());
             }
         }
 
@@ -11061,12 +11060,12 @@
                 long minVersionCode = Long.MIN_VALUE;
                 long maxVersionCode = Long.MAX_VALUE;
 
-                LongSparseArray<SharedLibraryEntry> versionedLib = mSharedLibraries.get(
+                LongSparseArray<SharedLibraryInfo> versionedLib = mSharedLibraries.get(
                         pkg.staticSharedLibName);
                 if (versionedLib != null) {
                     final int versionCount = versionedLib.size();
                     for (int i = 0; i < versionCount; i++) {
-                        SharedLibraryInfo libInfo = versionedLib.valueAt(i).info;
+                        SharedLibraryInfo libInfo = versionedLib.valueAt(i);
                         final long libVersionCode = libInfo.getDeclaringPackage()
                                 .getLongVersionCode();
                         if (libInfo.getLongVersion() <  pkg.staticSharedLibVersion) {
@@ -11254,7 +11253,7 @@
 
     private boolean addSharedLibraryLPw(String path, String apk, String name, long version,
             int type, String declaringPackageName, long declaringVersionCode) {
-        LongSparseArray<SharedLibraryEntry> versionedLib = mSharedLibraries.get(name);
+        LongSparseArray<SharedLibraryInfo> versionedLib = mSharedLibraries.get(name);
         if (versionedLib == null) {
             versionedLib = new LongSparseArray<>();
             mSharedLibraries.put(name, versionedLib);
@@ -11264,14 +11263,15 @@
         } else if (versionedLib.indexOfKey(version) >= 0) {
             return false;
         }
-        SharedLibraryEntry libEntry = new SharedLibraryEntry(path, apk, name,
-                version, type, declaringPackageName, declaringVersionCode);
-        versionedLib.put(version, libEntry);
+        SharedLibraryInfo libraryInfo = new SharedLibraryInfo(path, apk, name,
+                version, type, new VersionedPackage(declaringPackageName, declaringVersionCode),
+                null);
+        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 +11279,12 @@
         if (libIdx < 0) {
             return false;
         }
-        SharedLibraryEntry libEntry = versionedLib.valueAt(libIdx);
+        SharedLibraryInfo libraryInfo = versionedLib.valueAt(libIdx);
         versionedLib.remove(version);
         if (versionedLib.size() <= 0) {
             mSharedLibraries.remove(name);
-            if (libEntry.info.getType() == SharedLibraryInfo.TYPE_STATIC) {
-                mStaticLibsByDeclaringPackage.remove(libEntry.info.getDeclaringPackage()
+            if (libraryInfo.getType() == SharedLibraryInfo.TYPE_STATIC) {
+                mStaticLibsByDeclaringPackage.remove(libraryInfo.getDeclaringPackage()
                         .getPackageName());
             }
         }
@@ -17330,9 +17330,9 @@
                 // the package setting for the latest library version.
                 PackageSetting signatureCheckPs = ps;
                 if (pkg.applicationInfo.isStaticSharedLibrary()) {
-                    SharedLibraryEntry libraryEntry = getLatestSharedLibraVersionLPr(pkg);
-                    if (libraryEntry != null) {
-                        signatureCheckPs = mSettings.getPackageLPr(libraryEntry.apk);
+                    SharedLibraryInfo libraryInfo = getLatestSharedLibraVersionLPr(pkg);
+                    if (libraryInfo != null) {
+                        signatureCheckPs = mSettings.getPackageLPr(libraryInfo.getPackageName());
                     }
                 }
 
@@ -18024,7 +18024,7 @@
         packageName = normalizedPackageName != null ? normalizedPackageName : packageName;
 
         // Is this a static library?
-        LongSparseArray<SharedLibraryEntry> versionedLib =
+        LongSparseArray<SharedLibraryInfo> versionedLib =
                 mStaticLibsByDeclaringPackage.get(packageName);
         if (versionedLib == null || versionedLib.size() <= 0) {
             return packageName;
@@ -18036,7 +18036,7 @@
         if (callingAppId != Process.SYSTEM_UID && callingAppId != Process.SHELL_UID
                 && callingAppId != Process.ROOT_UID) {
             versionsCallerCanSee = new LongSparseLongArray();
-            String libName = versionedLib.valueAt(0).info.getName();
+            String libName = versionedLib.valueAt(0).getName();
             String[] uidPackages = getPackagesForUid(Binder.getCallingUid());
             if (uidPackages != null) {
                 for (String uidPackage : uidPackages) {
@@ -18056,29 +18056,29 @@
         }
 
         // Find the version the caller can see and the app version code
-        SharedLibraryEntry highestVersion = null;
+        SharedLibraryInfo highestVersion = null;
         final int versionCount = versionedLib.size();
         for (int i = 0; i < versionCount; i++) {
-            SharedLibraryEntry libEntry = versionedLib.valueAt(i);
+            SharedLibraryInfo libraryInfo = versionedLib.valueAt(i);
             if (versionsCallerCanSee != null && versionsCallerCanSee.indexOfKey(
-                    libEntry.info.getLongVersion()) < 0) {
+                    libraryInfo.getLongVersion()) < 0) {
                 continue;
             }
-            final long libVersionCode = libEntry.info.getDeclaringPackage().getLongVersionCode();
+            final long libVersionCode = libraryInfo.getDeclaringPackage().getLongVersionCode();
             if (versionCode != PackageManager.VERSION_CODE_HIGHEST) {
                 if (libVersionCode == versionCode) {
-                    return libEntry.apk;
+                    return libraryInfo.getPackageName();
                 }
             } else if (highestVersion == null) {
-                highestVersion = libEntry;
-            } else if (libVersionCode  > highestVersion.info
+                highestVersion = libraryInfo;
+            } else if (libVersionCode  > highestVersion
                     .getDeclaringPackage().getLongVersionCode()) {
-                highestVersion = libEntry;
+                highestVersion = libraryInfo;
             }
         }
 
         if (highestVersion != null) {
-            return highestVersion.apk;
+            return highestVersion.getPackageName();
         }
 
         return packageName;
@@ -18240,19 +18240,19 @@
             allUsers = sUserManager.getUserIds();
 
             if (pkg != null && pkg.staticSharedLibName != null) {
-                SharedLibraryEntry libEntry = getSharedLibraryEntryLPr(pkg.staticSharedLibName,
+                SharedLibraryInfo libraryInfo = getSharedLibraryInfoLPr(pkg.staticSharedLibName,
                         pkg.staticSharedLibVersion);
-                if (libEntry != null) {
+                if (libraryInfo != null) {
                     for (int currUserId : allUsers) {
                         if (removeUser != UserHandle.USER_ALL && removeUser != currUserId) {
                             continue;
                         }
                         List<VersionedPackage> libClientPackages = getPackagesUsingSharedLibraryLPr(
-                                libEntry.info, 0, currUserId);
+                                libraryInfo, 0, currUserId);
                         if (!ArrayUtils.isEmpty(libClientPackages)) {
                             Slog.w(TAG, "Not removing package " + pkg.manifestPackageName
-                                    + " hosting lib " + libEntry.info.getName() + " version "
-                                    + libEntry.info.getLongVersion() + " used by " + libClientPackages
+                                    + " hosting lib " + libraryInfo.getName() + " version "
+                                    + libraryInfo.getLongVersion() + " used by " + libClientPackages
                                     + " for user " + currUserId);
                             return PackageManager.DELETE_FAILED_USED_SHARED_LIBRARY;
                         }
@@ -21593,14 +21593,14 @@
                 final Iterator<String> it = mSharedLibraries.keySet().iterator();
                 while (it.hasNext()) {
                     String libName = it.next();
-                    LongSparseArray<SharedLibraryEntry> versionedLib
+                    LongSparseArray<SharedLibraryInfo> versionedLib
                             = mSharedLibraries.get(libName);
                     if (versionedLib == null) {
                         continue;
                     }
                     final int versionCount = versionedLib.size();
                     for (int i = 0; i < versionCount; i++) {
-                        SharedLibraryEntry libEntry = versionedLib.valueAt(i);
+                        SharedLibraryInfo libraryInfo = versionedLib.valueAt(i);
                         if (!checkin) {
                             if (!printedHeader) {
                                 if (dumpState.onTitlePrinted())
@@ -21612,19 +21612,19 @@
                         } else {
                             pw.print("lib,");
                         }
-                        pw.print(libEntry.info.getName());
-                        if (libEntry.info.isStatic()) {
-                            pw.print(" version=" + libEntry.info.getLongVersion());
+                        pw.print(libraryInfo.getName());
+                        if (libraryInfo.isStatic()) {
+                            pw.print(" version=" + libraryInfo.getLongVersion());
                         }
                         if (!checkin) {
                             pw.print(" -> ");
                         }
-                        if (libEntry.path != null) {
+                        if (libraryInfo.getPath() != null) {
                             pw.print(" (jar) ");
-                            pw.print(libEntry.path);
+                            pw.print(libraryInfo.getPath());
                         } else {
                             pw.print(" (apk) ");
-                            pw.print(libEntry.apk);
+                            pw.print(libraryInfo.getPackageName());
                         }
                         pw.println();
                     }
@@ -22024,22 +22024,24 @@
         final int count = mSharedLibraries.size();
         for (int i = 0; i < count; i++) {
             final String libName = mSharedLibraries.keyAt(i);
-            LongSparseArray<SharedLibraryEntry> versionedLib = mSharedLibraries.get(libName);
+            LongSparseArray<SharedLibraryInfo> versionedLib = mSharedLibraries.get(libName);
             if (versionedLib == null) {
                 continue;
             }
             final int versionCount = versionedLib.size();
             for (int j = 0; j < versionCount; j++) {
-                final SharedLibraryEntry libEntry = versionedLib.valueAt(j);
+                final SharedLibraryInfo libraryInfo = versionedLib.valueAt(j);
                 final long sharedLibraryToken =
                         proto.start(PackageServiceDumpProto.SHARED_LIBRARIES);
-                proto.write(PackageServiceDumpProto.SharedLibraryProto.NAME, libEntry.info.getName());
-                final boolean isJar = (libEntry.path != null);
+                proto.write(PackageServiceDumpProto.SharedLibraryProto.NAME, libraryInfo.getName());
+                final boolean isJar = (libraryInfo.getPath() != null);
                 proto.write(PackageServiceDumpProto.SharedLibraryProto.IS_JAR, isJar);
                 if (isJar) {
-                    proto.write(PackageServiceDumpProto.SharedLibraryProto.PATH, libEntry.path);
+                    proto.write(PackageServiceDumpProto.SharedLibraryProto.PATH,
+                            libraryInfo.getPath());
                 } else {
-                    proto.write(PackageServiceDumpProto.SharedLibraryProto.APK, libEntry.apk);
+                    proto.write(PackageServiceDumpProto.SharedLibraryProto.APK,
+                            libraryInfo.getPackageName());
                 }
                 proto.end(sharedLibraryToken);
             }
diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java b/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java
index a55b49f..f78d263 100644
--- a/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java
+++ b/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java
@@ -20,7 +20,7 @@
 import android.content.Context;
 import android.os.RemoteException;
 import android.os.ServiceManager;
-import android.security.IKeystoreService;
+import android.security.keystore.IKeystoreService;
 import android.util.Slog;
 
 import com.android.internal.policy.IKeyguardService;
diff --git a/services/robotests/Android.mk b/services/robotests/Android.mk
index de54c4b..c01c124 100644
--- a/services/robotests/Android.mk
+++ b/services/robotests/Android.mk
@@ -28,7 +28,8 @@
 
 LOCAL_STATIC_JAVA_LIBRARIES := \
     services.backup \
-    services.core
+    services.core \
+    services.net
 
 include $(BUILD_PACKAGE)
 
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
index 2f6e2c2..952abfa 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
@@ -24,6 +24,7 @@
 import android.content.pm.PackageParser;
 import android.content.pm.ProviderInfo;
 import android.content.pm.ServiceInfo;
+import android.content.pm.SharedLibraryInfo;
 import android.content.pm.Signature;
 import android.os.Bundle;
 import android.os.Parcel;
@@ -487,6 +488,9 @@
 
         pkg.usesLibraryFiles = new String[] { "foo13"};
 
+        pkg.usesLibraryInfos = new ArrayList<>();
+        pkg.usesLibraryInfos.add(new SharedLibraryInfo(null, null, null, 0L, 0, null, null));
+
         pkg.mOriginalPackages = new ArrayList<>();
         pkg.mOriginalPackages.add("foo14");
 
diff --git a/startop/view_compiler/dex_builder.cc b/startop/view_compiler/dex_builder.cc
index 33df6f9..85357bb 100644
--- a/startop/view_compiler/dex_builder.cc
+++ b/startop/view_compiler/dex_builder.cc
@@ -49,6 +49,9 @@
     case Instruction::Op::kReturn:
       out << "kReturn";
       return out;
+    case Instruction::Op::kReturnObject:
+      out << "kReturnObject";
+      return out;
     case Instruction::Op::kMove:
       out << "kMove";
       return out;
@@ -137,6 +140,9 @@
     entry = Alloc<ir::String>();
     // +1 for null terminator
     entry->data = slicer::MemView{buffer.get(), header_length + string.size() + 1};
+    ::dex::u4 const new_index = dex_file_->strings_indexes.AllocateIndex();
+    dex_file_->strings_map[new_index] = entry;
+    entry->orig_index = new_index;
     string_data_.push_back(std::move(buffer));
   }
   return entry;
@@ -240,8 +246,9 @@
 
 void MethodBuilder::BuildReturn() { AddInstruction(Instruction::OpNoArgs(Op::kReturn)); }
 
-void MethodBuilder::BuildReturn(Value src) {
-  AddInstruction(Instruction::OpWithArgs(Op::kReturn, /*destination=*/{}, src));
+void MethodBuilder::BuildReturn(Value src, bool is_object) {
+  AddInstruction(Instruction::OpWithArgs(
+      is_object ? Op::kReturnObject : Op::kReturn, /*destination=*/{}, src));
 }
 
 void MethodBuilder::BuildConst4(Value target, int value) {
@@ -249,6 +256,11 @@
   AddInstruction(Instruction::OpWithArgs(Op::kMove, target, Value::Immediate(value)));
 }
 
+void MethodBuilder::BuildConstString(Value target, const std::string& value) {
+  const ir::String* const dex_string = dex_->GetOrAddString(value);
+  AddInstruction(Instruction::OpWithArgs(Op::kMove, target, Value::String(dex_string->orig_index)));
+}
+
 void MethodBuilder::EncodeInstructions() {
   buffer_.clear();
   for (const auto& instruction : instructions_) {
@@ -259,7 +271,9 @@
 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:
@@ -271,15 +285,14 @@
   }
 }
 
-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);
   } 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);
+    buffer_.push_back(opcode | source << 8);
   }
 }
 
@@ -297,6 +310,12 @@
     DCHECK_LT(source.value(), 16);
     buffer_.push_back(art::Instruction::CONST_4 | (source.value() << 12) |
                       (RegisterValue(*instruction.dest()) << 8));
+  } 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
+    buffer_.push_back(::art::Instruction::CONST_STRING | (RegisterValue(*instruction.dest()) << 8));
+    buffer_.push_back(source.value());
   } else {
     UNIMPLEMENTED(FATAL);
   }
diff --git a/startop/view_compiler/dex_builder.h b/startop/view_compiler/dex_builder.h
index 0744151..31414c8 100644
--- a/startop/view_compiler/dex_builder.h
+++ b/startop/view_compiler/dex_builder.h
@@ -110,18 +110,20 @@
   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}; }
 
   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; }
 
   size_t value() const { return value_; }
 
  private:
-  enum class Kind { kLocalRegister, kParameter, kImmediate, kLabel };
+  enum class Kind { kLocalRegister, kParameter, kImmediate, kString, kLabel };
 
   const size_t value_;
   const Kind kind_;
@@ -137,7 +139,7 @@
  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, kBindLabel, kBranchEqz };
 
   ////////////////////////
   // Named Constructors //
@@ -210,16 +212,22 @@
 
   // 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);
 
   // 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 EncodeBranch(art::Instruction::Code op, const Instruction& instruction);
diff --git a/startop/view_compiler/dex_builder_test/src/android/startop/test/DexBuilderTest.java b/startop/view_compiler/dex_builder_test/src/android/startop/test/DexBuilderTest.java
index 169c633..2ccdc6d5 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
@@ -82,4 +82,38 @@
     Method method = clazz.getMethod("backwardsBranch");
     Assert.assertEquals(2, method.invoke(null));
   }
+
+  @Test
+  public void returnNull() throws Exception {
+    ClassLoader loader = loadDexFile("simple.dex");
+    Class clazz = loader.loadClass("android.startop.test.testcases.SimpleTests");
+    Method method = clazz.getMethod("returnNull");
+    Assert.assertEquals(null, method.invoke(null));
+  }
+
+  @Test
+  public void makeString() throws Exception {
+    ClassLoader loader = loadDexFile("simple.dex");
+    Class clazz = loader.loadClass("android.startop.test.testcases.SimpleTests");
+    Method method = clazz.getMethod("makeString");
+    Assert.assertEquals("Hello, World!", method.invoke(null));
+  }
+
+  @Test
+  public void returnStringIfZeroAB() throws Exception {
+    ClassLoader loader = loadDexFile("simple.dex");
+    Class clazz = loader.loadClass("android.startop.test.testcases.SimpleTests");
+    Method method = clazz.getMethod("returnStringIfZeroAB", int.class);
+    Assert.assertEquals("a", method.invoke(null, 0));
+    Assert.assertEquals("b", method.invoke(null, 1));
+  }
+
+  @Test
+  public void returnStringIfZeroBA() throws Exception {
+    ClassLoader loader = loadDexFile("simple.dex");
+    Class clazz = loader.loadClass("android.startop.test.testcases.SimpleTests");
+    Method method = clazz.getMethod("returnStringIfZeroBA", int.class);
+    Assert.assertEquals("b", method.invoke(null, 0));
+    Assert.assertEquals("a", method.invoke(null, 1));
+  }
 }
diff --git a/startop/view_compiler/dex_testcase_generator.cc b/startop/view_compiler/dex_testcase_generator.cc
index c521bf2..063a0cf 100644
--- a/startop/view_compiler/dex_testcase_generator.cc
+++ b/startop/view_compiler/dex_testcase_generator.cc
@@ -138,6 +138,71 @@
   }(backwardsBranch);
   backwardsBranch.Encode();
 
+  // Test that we can make a null value. Basically:
+  //
+  // public static String returnNull() { return null; }
+  MethodBuilder returnNull{cbuilder.CreateMethod("returnNull", Prototype{string_type})};
+  [](MethodBuilder& method) {
+    Value zero = method.MakeRegister();
+    method.BuildConst4(zero, 0);
+    method.BuildReturn(zero, /*is_object=*/true);
+  }(returnNull);
+  returnNull.Encode();
+
+  // Test that we can make String literals. Basically:
+  //
+  // public static String makeString() { return "Hello, World!"; }
+  MethodBuilder makeString{cbuilder.CreateMethod("makeString", Prototype{string_type})};
+  [](MethodBuilder& method) {
+    Value string = method.MakeRegister();
+    method.BuildConstString(string, "Hello, World!");
+    method.BuildReturn(string, /*is_object=*/true);
+  }(makeString);
+  makeString.Encode();
+
+  // Make sure strings are sorted correctly.
+  //
+  // int returnStringIfZeroAB(int x) { if (x == 0) { return "a"; } else { return "b"; } }
+  MethodBuilder returnStringIfZeroAB{
+      cbuilder.CreateMethod("returnStringIfZeroAB", Prototype{string_type, TypeDescriptor::Int()})};
+  [&](MethodBuilder& method) {
+    Value resultIfZero{method.MakeRegister()};
+    Value else_target{method.MakeLabel()};
+    method.AddInstruction(Instruction::OpWithArgs(
+        Instruction::Op::kBranchEqz, /*dest=*/{}, Value::Parameter(0), else_target));
+    // else branch
+    method.BuildConstString(resultIfZero, "b");
+    method.AddInstruction(
+        Instruction::OpWithArgs(Instruction::Op::kReturnObject, /*dest=*/{}, resultIfZero));
+    // then branch
+    method.AddInstruction(
+        Instruction::OpWithArgs(Instruction::Op::kBindLabel, /*dest=*/{}, else_target));
+    method.BuildConstString(resultIfZero, "a");
+    method.AddInstruction(
+        Instruction::OpWithArgs(Instruction::Op::kReturnObject, /*dest=*/{}, resultIfZero));
+    method.Encode();
+  }(returnStringIfZeroAB);
+  // int returnStringIfZeroAB(int x) { if (x == 0) { return "b"; } else { return "a"; } }
+  MethodBuilder returnStringIfZeroBA{
+      cbuilder.CreateMethod("returnStringIfZeroBA", Prototype{string_type, TypeDescriptor::Int()})};
+  [&](MethodBuilder& method) {
+    Value resultIfZero{method.MakeRegister()};
+    Value else_target{method.MakeLabel()};
+    method.AddInstruction(Instruction::OpWithArgs(
+        Instruction::Op::kBranchEqz, /*dest=*/{}, Value::Parameter(0), else_target));
+    // else branch
+    method.BuildConstString(resultIfZero, "a");
+    method.AddInstruction(
+        Instruction::OpWithArgs(Instruction::Op::kReturnObject, /*dest=*/{}, resultIfZero));
+    // then branch
+    method.AddInstruction(
+        Instruction::OpWithArgs(Instruction::Op::kBindLabel, /*dest=*/{}, else_target));
+    method.BuildConstString(resultIfZero, "b");
+    method.AddInstruction(
+        Instruction::OpWithArgs(Instruction::Op::kReturnObject, /*dest=*/{}, resultIfZero));
+    method.Encode();
+  }(returnStringIfZeroBA);
+
   slicer::MemView image{dex_file.CreateImage()};
   std::ofstream out_file(outdir + "/simple.dex");
   out_file.write(image.ptr<const char>(), image.size());
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 0280a75..5b739ba 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -1277,20 +1277,11 @@
     public static final String KEY_WORLD_MODE_ENABLED_BOOL = "world_mode_enabled_bool";
 
     /**
-     * Package name of the carrier settings activity.
-     * @see {@link #KEY_CARRIER_SETTINGS_ACTIVITY_CLASS_NAME_STRING}.
+     * Flatten {@link android.content.ComponentName} of the carrier's settings activity.
      * @hide
      */
-    public static final String KEY_CARRIER_SETTINGS_ACTIVITY_PACKAGE_NAME_STRING =
-            "carrier_settings_activity_package_name_string";
-
-    /**
-     * Class name of the carrier settings activity.
-     * @see {@link #KEY_CARRIER_SETTINGS_ACTIVITY_PACKAGE_NAME_STRING}.
-     * @hide
-     */
-    public static final String KEY_CARRIER_SETTINGS_ACTIVITY_CLASS_NAME_STRING =
-            "carrier_settings_activity_class_name_string";
+    public static final String KEY_CARRIER_SETTINGS_ACTIVITY_COMPONENT_NAME_STRING =
+            "carrier_settings_activity_component_name_string";
 
     // These variables are used by the MMS service and exposed through another API,
     // SmsManager. The variable names and string values are copied from there.
@@ -2637,8 +2628,7 @@
         sDefaults.putBoolean(KEY_SUPPORT_TDSCDMA_BOOL, false);
         sDefaults.putStringArray(KEY_SUPPORT_TDSCDMA_ROAMING_NETWORKS_STRING_ARRAY, null);
         sDefaults.putBoolean(KEY_WORLD_MODE_ENABLED_BOOL, false);
-        sDefaults.putString(KEY_CARRIER_SETTINGS_ACTIVITY_PACKAGE_NAME_STRING, "");
-        sDefaults.putString(KEY_CARRIER_SETTINGS_ACTIVITY_CLASS_NAME_STRING, "");
+        sDefaults.putString(KEY_CARRIER_SETTINGS_ACTIVITY_COMPONENT_NAME_STRING, "");
         sDefaults.putBoolean(KEY_CARRIER_CONFIG_APPLIED_BOOL, false);
         sDefaults.putBoolean(KEY_CHECK_PRICING_WITH_CARRIER_FOR_DATA_ROAMING_BOOL, false);
         sDefaults.putIntArray(KEY_LTE_RSRP_THRESHOLDS_INT_ARRAY,
diff --git a/telephony/java/android/telephony/CellConfigLte.java b/telephony/java/android/telephony/CellConfigLte.java
new file mode 100644
index 0000000..35769f0
--- /dev/null
+++ b/telephony/java/android/telephony/CellConfigLte.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/**
+ * The container of LTE cell related configs.
+ * @hide
+ */
+public class CellConfigLte implements Parcelable {
+    private final boolean mIsEndcAvailable;
+
+    /** @hide */
+    public CellConfigLte() {
+        mIsEndcAvailable = false;
+    }
+
+    /** @hide */
+    public CellConfigLte(boolean isEndcAvailable) {
+        mIsEndcAvailable = isEndcAvailable;
+    }
+
+    /** @hide */
+    public CellConfigLte(CellConfigLte config) {
+        mIsEndcAvailable = config.mIsEndcAvailable;
+    }
+
+    /**
+     * Indicates that if E-UTRA-NR Dual Connectivity (EN-DC) is supported by the LTE cell.
+     *
+     * Reference: 3GPP TS 36.331 v15.2.2 6.3.1 System information blocks.
+     *
+     * @return {@code true} if E-UTRA-NR Dual Connectivity (EN-DC) is supported by the LTE cell.
+     *
+     */
+    boolean isEndcAvailable() {
+        return mIsEndcAvailable;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mIsEndcAvailable);
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        if (!(other instanceof CellConfigLte)) return false;
+
+        CellConfigLte o = (CellConfigLte) other;
+        return mIsEndcAvailable == o.mIsEndcAvailable;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeBoolean(mIsEndcAvailable);
+    }
+
+    @Override
+    public String toString() {
+        return new StringBuilder().append(this.getClass().getName())
+                .append(" :{")
+                .append(" isEndcAvailable = " + mIsEndcAvailable)
+                .append(" }")
+                .toString();
+    }
+
+    private CellConfigLte(Parcel in) {
+        mIsEndcAvailable = in.readBoolean();
+    }
+
+    public static final Creator<CellConfigLte> CREATOR = new Creator<CellConfigLte>() {
+        @Override
+        public CellConfigLte createFromParcel(Parcel in) {
+            return new CellConfigLte(in);
+        }
+
+        @Override
+        public CellConfigLte[] newArray(int size) {
+            return new CellConfigLte[0];
+        }
+    };
+}
diff --git a/telephony/java/android/telephony/CellInfoLte.java b/telephony/java/android/telephony/CellInfoLte.java
index 389f643..7d5388b 100644
--- a/telephony/java/android/telephony/CellInfoLte.java
+++ b/telephony/java/android/telephony/CellInfoLte.java
@@ -19,7 +19,8 @@
 import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
-import android.telephony.Rlog;
+
+import java.util.Objects;
 
 /**
  * A {@link CellInfo} representing an LTE cell that provides identity and measurement info.
@@ -31,6 +32,7 @@
 
     private CellIdentityLte mCellIdentityLte;
     private CellSignalStrengthLte mCellSignalStrengthLte;
+    private CellConfigLte mCellConfig;
 
     /** @hide */
     @UnsupportedAppUsage
@@ -38,6 +40,7 @@
         super();
         mCellIdentityLte = new CellIdentityLte();
         mCellSignalStrengthLte = new CellSignalStrengthLte();
+        mCellConfig = new CellConfigLte();
     }
 
     /** @hide */
@@ -45,6 +48,7 @@
         super(ci);
         this.mCellIdentityLte = ci.mCellIdentityLte.copy();
         this.mCellSignalStrengthLte = ci.mCellSignalStrengthLte.copy();
+        this.mCellConfig = new CellConfigLte(ci.mCellConfig);
     }
 
     @Override
@@ -71,26 +75,37 @@
         mCellSignalStrengthLte = css;
     }
 
+    /** @hide */
+    public void setCellConfig(CellConfigLte cellConfig) {
+        if (DBG) log("setCellConfig: " + cellConfig);
+        mCellConfig = cellConfig;
+    }
+
+    /** @hide */
+    public CellConfigLte getCellConfig() {
+        if (DBG) log("getCellConfig: " + mCellConfig);
+        return mCellConfig;
+    }
+
     /**
      * @return hash code
      */
     @Override
     public int hashCode() {
-        return super.hashCode() + mCellIdentityLte.hashCode() + mCellSignalStrengthLte.hashCode();
+        return Objects.hash(
+                super.hashCode(),
+                mCellIdentityLte.hashCode(),
+                mCellSignalStrengthLte.hashCode(),
+                mCellConfig.hashCode());
     }
 
     @Override
     public boolean equals(Object other) {
-        if (!super.equals(other)) {
-            return false;
-        }
-        try {
-            CellInfoLte o = (CellInfoLte) other;
-            return mCellIdentityLte.equals(o.mCellIdentityLte)
-                    && mCellSignalStrengthLte.equals(o.mCellSignalStrengthLte);
-        } catch (ClassCastException e) {
-            return false;
-        }
+        if (!(other instanceof CellInfoLte)) return false;
+        CellInfoLte o = (CellInfoLte) other;
+        return super.equals(o) && mCellIdentityLte.equals(o.mCellIdentityLte)
+                && mCellSignalStrengthLte.equals(o.mCellSignalStrengthLte)
+                && mCellConfig.equals(o.mCellConfig);
     }
 
     @Override
@@ -101,6 +116,7 @@
         sb.append(super.toString());
         sb.append(" ").append(mCellIdentityLte);
         sb.append(" ").append(mCellSignalStrengthLte);
+        sb.append(" ").append(mCellConfig);
         sb.append("}");
 
         return sb.toString();
@@ -119,6 +135,7 @@
         super.writeToParcel(dest, flags, TYPE_LTE);
         mCellIdentityLte.writeToParcel(dest, flags);
         mCellSignalStrengthLte.writeToParcel(dest, flags);
+        mCellConfig.writeToParcel(dest, flags);
     }
 
     /**
@@ -129,6 +146,7 @@
         super(in);
         mCellIdentityLte = CellIdentityLte.CREATOR.createFromParcel(in);
         mCellSignalStrengthLte = CellSignalStrengthLte.CREATOR.createFromParcel(in);
+        mCellConfig = CellConfigLte.CREATOR.createFromParcel(in);
         if (DBG) log("CellInfoLte(Parcel): " + toString());
     }
 
diff --git a/telephony/java/android/telephony/DataSpecificRegistrationStates.java b/telephony/java/android/telephony/DataSpecificRegistrationStates.java
index 97e3037..b6e6cba 100644
--- a/telephony/java/android/telephony/DataSpecificRegistrationStates.java
+++ b/telephony/java/android/telephony/DataSpecificRegistrationStates.java
@@ -17,17 +17,40 @@
      */
     public final int maxDataCalls;
 
-    DataSpecificRegistrationStates(int maxDataCalls) {
+    /**
+     * Indicates if the use of dual connectivity with NR is restricted.
+     * Reference: 3GPP TS 24.301 v15.03 section 9.3.3.12A.
+     */
+    public final boolean isDcNrRestricted;
+
+    /**
+     * Indicates if NR is supported by the selected PLMN.
+     *
+     * {@code true} if the bit N is in the PLMN-InfoList-r15 is true and the selected PLMN is
+     * present in plmn-IdentityList at position N.
+     * Reference: 3GPP TS 36.331 v15.2.2 section 6.3.1 PLMN-InfoList-r15.
+     *            3GPP TS 36.331 v15.2.2 section 6.2.2 SystemInformationBlockType1 message.
+     */
+    public final boolean isNrAvailable;
+
+    DataSpecificRegistrationStates(
+            int maxDataCalls, boolean isDcNrRestricted, boolean isNrAvailable) {
         this.maxDataCalls = maxDataCalls;
+        this.isDcNrRestricted = isDcNrRestricted;
+        this.isNrAvailable = isNrAvailable;
     }
 
     private DataSpecificRegistrationStates(Parcel source) {
         maxDataCalls = source.readInt();
+        isDcNrRestricted = source.readBoolean();
+        isNrAvailable = source.readBoolean();
     }
 
     @Override
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeInt(maxDataCalls);
+        dest.writeBoolean(isDcNrRestricted);
+        dest.writeBoolean(isNrAvailable);
     }
 
     @Override
@@ -37,24 +60,30 @@
 
     @Override
     public String toString() {
-        return "DataSpecificRegistrationStates {" + " mMaxDataCalls=" + maxDataCalls + "}";
+        return new StringBuilder().append(this.getClass().getName())
+                .append(" :{")
+                .append(" maxDataCalls = " + maxDataCalls)
+                .append(" isDcNrRestricted = " + isDcNrRestricted)
+                .append(" isNrAvailable = " + isNrAvailable)
+                .append(" }")
+                .toString();
     }
 
     @Override
     public int hashCode() {
-        return Objects.hash(maxDataCalls);
+        return Objects.hash(maxDataCalls, isDcNrRestricted, isNrAvailable);
     }
 
     @Override
     public boolean equals(Object o) {
         if (this == o) return true;
 
-        if (o == null || !(o instanceof DataSpecificRegistrationStates)) {
-            return false;
-        }
+        if (!(o instanceof DataSpecificRegistrationStates)) return false;
 
         DataSpecificRegistrationStates other = (DataSpecificRegistrationStates) o;
-        return this.maxDataCalls == other.maxDataCalls;
+        return this.maxDataCalls == other.maxDataCalls
+                && this.isDcNrRestricted == other.isDcNrRestricted
+                && this.isNrAvailable == other.isNrAvailable;
     }
 
     public static final Parcelable.Creator<DataSpecificRegistrationStates> CREATOR =
diff --git a/telephony/java/android/telephony/NetworkRegistrationState.java b/telephony/java/android/telephony/NetworkRegistrationState.java
index 68e512e..75e8eda 100644
--- a/telephony/java/android/telephony/NetworkRegistrationState.java
+++ b/telephony/java/android/telephony/NetworkRegistrationState.java
@@ -161,11 +161,9 @@
      * @hide
      */
     public NetworkRegistrationState(int domain, int transportType, int regState,
-                                    int accessNetworkTechnology, int rejectCause,
-                                    boolean emergencyOnly, int[] availableServices,
-                                    @Nullable CellIdentity cellIdentity, boolean cssSupported,
-                                    int roamingIndicator, int systemIsInPrl,
-                                    int defaultRoamingIndicator) {
+            int accessNetworkTechnology, int rejectCause, boolean emergencyOnly,
+            int[] availableServices, @Nullable CellIdentity cellIdentity, boolean cssSupported,
+            int roamingIndicator, int systemIsInPrl, int defaultRoamingIndicator) {
         this(domain, transportType, regState, accessNetworkTechnology, rejectCause, emergencyOnly,
                 availableServices, cellIdentity);
 
@@ -178,13 +176,14 @@
      * @hide
      */
     public NetworkRegistrationState(int domain, int transportType, int regState,
-                                    int accessNetworkTechnology, int rejectCause,
-                                    boolean emergencyOnly, int[] availableServices,
-                                    @Nullable CellIdentity cellIdentity, int maxDataCalls) {
+            int accessNetworkTechnology, int rejectCause, boolean emergencyOnly,
+            int[] availableServices, @Nullable CellIdentity cellIdentity, int maxDataCalls,
+            boolean isDcNrRestricted, boolean isNrAvailable) {
         this(domain, transportType, regState, accessNetworkTechnology, rejectCause, emergencyOnly,
                 availableServices, cellIdentity);
 
-        mDataSpecificStates = new DataSpecificRegistrationStates(maxDataCalls);
+        mDataSpecificStates = new DataSpecificRegistrationStates(
+                maxDataCalls, isDcNrRestricted, isNrAvailable);
     }
 
     protected NetworkRegistrationState(Parcel source) {
@@ -345,7 +344,7 @@
     public boolean equals(Object o) {
         if (this == o) return true;
 
-        if (o == null || !(o instanceof NetworkRegistrationState)) {
+        if (!(o instanceof NetworkRegistrationState)) {
             return false;
         }
 
@@ -357,11 +356,10 @@
                 && mAccessNetworkTechnology == other.mAccessNetworkTechnology
                 && mRejectCause == other.mRejectCause
                 && mEmergencyOnly == other.mEmergencyOnly
-                && (mAvailableServices == other.mAvailableServices
-                    || Arrays.equals(mAvailableServices, other.mAvailableServices))
-                && equals(mCellIdentity, other.mCellIdentity)
-                && equals(mVoiceSpecificStates, other.mVoiceSpecificStates)
-                && equals(mDataSpecificStates, other.mDataSpecificStates);
+                && Arrays.equals(mAvailableServices, other.mAvailableServices)
+                && Objects.equals(mCellIdentity, other.mCellIdentity)
+                && Objects.equals(mVoiceSpecificStates, other.mVoiceSpecificStates)
+                && Objects.equals(mDataSpecificStates, other.mDataSpecificStates);
     }
 
     @Override
@@ -391,14 +389,4 @@
             return new NetworkRegistrationState[size];
         }
     };
-
-    private static boolean equals(Object o1, Object o2) {
-        if (o1 == o2) {
-            return true;
-        } else if (o1 == null) {
-            return false;
-        } else {
-            return o1.equals(o2);
-        }
-    }
 }
diff --git a/telephony/java/android/telephony/PhoneStateListener.java b/telephony/java/android/telephony/PhoneStateListener.java
index f5dff20..0c8d581 100644
--- a/telephony/java/android/telephony/PhoneStateListener.java
+++ b/telephony/java/android/telephony/PhoneStateListener.java
@@ -21,16 +21,18 @@
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.annotation.UnsupportedAppUsage;
+import android.os.Binder;
 import android.os.Bundle;
 import android.os.Handler;
+import android.os.HandlerExecutor;
 import android.os.Looper;
-import android.os.Message;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telephony.IPhoneStateListener;
 
 import java.lang.ref.WeakReference;
 import java.util.List;
+import java.util.concurrent.Executor;
 
 /**
  * A listener class for monitoring changes in specific telephony states
@@ -320,7 +322,12 @@
     @UnsupportedAppUsage
     protected Integer mSubId;
 
-    private final Handler mHandler;
+    /**
+     * @hide
+     */
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+    @UnsupportedAppUsage
+    public final IPhoneStateListener callback;
 
     /**
      * Create a PhoneStateListener for the Phone with the default subscription.
@@ -358,95 +365,27 @@
      */
     @UnsupportedAppUsage
     public PhoneStateListener(Integer subId, Looper looper) {
-        if (DBG) log("ctor: subId=" + subId + " looper=" + looper);
+        this(subId, new HandlerExecutor(new Handler(looper)));
+    }
+
+    /**
+     * Create a PhoneStateListener for the Phone using the specified Executor
+     *
+     * <p>Create a PhoneStateListener with a specified Executor for handling necessary callbacks.
+     * The Executor must not be null.
+     *
+     * @param executor a non-null Executor that will execute callbacks for the PhoneStateListener.
+     */
+    public PhoneStateListener(@NonNull Executor executor) {
+        this(null, executor);
+    }
+
+    private PhoneStateListener(Integer subId, Executor e) {
+        if (e == null) {
+            throw new IllegalArgumentException("PhoneStateListener Executor must be non-null");
+        }
         mSubId = subId;
-        mHandler = new Handler(looper) {
-            public void handleMessage(Message msg) {
-                if (DBG) {
-                    log("mSubId=" + mSubId + " what=0x" + Integer.toHexString(msg.what)
-                            + " msg=" + msg);
-                }
-                switch (msg.what) {
-                    case LISTEN_SERVICE_STATE:
-                        PhoneStateListener.this.onServiceStateChanged((ServiceState)msg.obj);
-                        break;
-                    case LISTEN_SIGNAL_STRENGTH:
-                        PhoneStateListener.this.onSignalStrengthChanged(msg.arg1);
-                        break;
-                    case LISTEN_MESSAGE_WAITING_INDICATOR:
-                        PhoneStateListener.this.onMessageWaitingIndicatorChanged(msg.arg1 != 0);
-                        break;
-                    case LISTEN_CALL_FORWARDING_INDICATOR:
-                        PhoneStateListener.this.onCallForwardingIndicatorChanged(msg.arg1 != 0);
-                        break;
-                    case LISTEN_CELL_LOCATION:
-                        PhoneStateListener.this.onCellLocationChanged((CellLocation)msg.obj);
-                        break;
-                    case LISTEN_CALL_STATE:
-                        PhoneStateListener.this.onCallStateChanged(msg.arg1, (String)msg.obj);
-                        break;
-                    case LISTEN_DATA_CONNECTION_STATE:
-                        PhoneStateListener.this.onDataConnectionStateChanged(msg.arg1, msg.arg2);
-                        PhoneStateListener.this.onDataConnectionStateChanged(msg.arg1);
-                        break;
-                    case LISTEN_DATA_ACTIVITY:
-                        PhoneStateListener.this.onDataActivity(msg.arg1);
-                        break;
-                    case LISTEN_SIGNAL_STRENGTHS:
-                        PhoneStateListener.this.onSignalStrengthsChanged((SignalStrength)msg.obj);
-                        break;
-                    case LISTEN_OTASP_CHANGED:
-                        PhoneStateListener.this.onOtaspChanged(msg.arg1);
-                        break;
-                    case LISTEN_CELL_INFO:
-                        PhoneStateListener.this.onCellInfoChanged((List<CellInfo>)msg.obj);
-                        break;
-                    case LISTEN_PRECISE_CALL_STATE:
-                        PhoneStateListener.this.onPreciseCallStateChanged((PreciseCallState)msg.obj);
-                        break;
-                    case LISTEN_PRECISE_DATA_CONNECTION_STATE:
-                        PhoneStateListener.this.onPreciseDataConnectionStateChanged(
-                                (PreciseDataConnectionState)msg.obj);
-                        break;
-                    case LISTEN_DATA_CONNECTION_REAL_TIME_INFO:
-                        PhoneStateListener.this.onDataConnectionRealTimeInfoChanged(
-                                (DataConnectionRealTimeInfo)msg.obj);
-                        break;
-                    case LISTEN_SRVCC_STATE_CHANGED:
-                        PhoneStateListener.this.onSrvccStateChanged((int) msg.obj);
-                        break;
-                    case LISTEN_VOICE_ACTIVATION_STATE:
-                        PhoneStateListener.this.onVoiceActivationStateChanged((int)msg.obj);
-                        break;
-                    case LISTEN_DATA_ACTIVATION_STATE:
-                        PhoneStateListener.this.onDataActivationStateChanged((int)msg.obj);
-                        break;
-                    case LISTEN_USER_MOBILE_DATA_STATE:
-                        PhoneStateListener.this.onUserMobileDataStateChanged((boolean)msg.obj);
-                        break;
-                    case LISTEN_OEM_HOOK_RAW_EVENT:
-                        PhoneStateListener.this.onOemHookRawEvent((byte[])msg.obj);
-                        break;
-                    case LISTEN_CARRIER_NETWORK_CHANGE:
-                        PhoneStateListener.this.onCarrierNetworkChange((boolean)msg.obj);
-                        break;
-                    case LISTEN_PHYSICAL_CHANNEL_CONFIGURATION:
-                        PhoneStateListener.this.onPhysicalChannelConfigurationChanged(
-                                (List<PhysicalChannelConfig>)msg.obj);
-                        break;
-                    case LISTEN_PHONE_CAPABILITY_CHANGE:
-                        PhoneStateListener.this.onPhoneCapabilityChanged(
-                                (PhoneCapability) msg.obj);
-                        break;
-                    case LISTEN_PREFERRED_DATA_SUBID_CHANGE:
-                        PhoneStateListener.this.onPreferredDataSubIdChanged((int) msg.obj);
-                        break;
-                    case LISTEN_RADIO_POWER_STATE_CHANGED:
-                        PhoneStateListener.this.onRadioPowerStateChanged((int) msg.obj);
-                        break;
-                }
-            }
-        };
+        callback = new IPhoneStateListenerStub(this, e);
     }
 
     /**
@@ -735,127 +674,217 @@
      */
     private static class IPhoneStateListenerStub extends IPhoneStateListener.Stub {
         private WeakReference<PhoneStateListener> mPhoneStateListenerWeakRef;
+        private Executor mExecutor;
 
-        public IPhoneStateListenerStub(PhoneStateListener phoneStateListener) {
+        IPhoneStateListenerStub(PhoneStateListener phoneStateListener, Executor executor) {
             mPhoneStateListenerWeakRef = new WeakReference<PhoneStateListener>(phoneStateListener);
-        }
-
-        private void send(int what, int arg1, int arg2, Object obj) {
-            PhoneStateListener listener = mPhoneStateListenerWeakRef.get();
-            if (listener != null) {
-                Message.obtain(listener.mHandler, what, arg1, arg2, obj).sendToTarget();
-            }
+            mExecutor = executor;
         }
 
         public void onServiceStateChanged(ServiceState serviceState) {
-            send(LISTEN_SERVICE_STATE, 0, 0, serviceState);
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(() -> psl.onServiceStateChanged(serviceState)));
         }
 
         public void onSignalStrengthChanged(int asu) {
-            send(LISTEN_SIGNAL_STRENGTH, asu, 0, null);
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(() -> psl.onSignalStrengthChanged(asu)));
         }
 
         public void onMessageWaitingIndicatorChanged(boolean mwi) {
-            send(LISTEN_MESSAGE_WAITING_INDICATOR, mwi ? 1 : 0, 0, null);
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(() -> psl.onMessageWaitingIndicatorChanged(mwi)));
         }
 
         public void onCallForwardingIndicatorChanged(boolean cfi) {
-            send(LISTEN_CALL_FORWARDING_INDICATOR, cfi ? 1 : 0, 0, null);
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(() -> psl.onCallForwardingIndicatorChanged(cfi)));
         }
 
         public void onCellLocationChanged(Bundle bundle) {
             CellLocation location = CellLocation.newFromBundle(bundle);
-            send(LISTEN_CELL_LOCATION, 0, 0, location);
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(() -> psl.onCellLocationChanged(location)));
         }
 
         public void onCallStateChanged(int state, String incomingNumber) {
-            send(LISTEN_CALL_STATE, state, 0, incomingNumber);
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(() -> psl.onCallStateChanged(state, incomingNumber)));
         }
 
         public void onDataConnectionStateChanged(int state, int networkType) {
-            send(LISTEN_DATA_CONNECTION_STATE, state, networkType, null);
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(
+                            () -> psl.onDataConnectionStateChanged(state, networkType)));
         }
 
         public void onDataActivity(int direction) {
-            send(LISTEN_DATA_ACTIVITY, direction, 0, null);
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(() -> psl.onDataActivity(direction)));
         }
 
         public void onSignalStrengthsChanged(SignalStrength signalStrength) {
-            send(LISTEN_SIGNAL_STRENGTHS, 0, 0, signalStrength);
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(() -> psl.onSignalStrengthsChanged(signalStrength)));
         }
 
         public void onOtaspChanged(int otaspMode) {
-            send(LISTEN_OTASP_CHANGED, otaspMode, 0, null);
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(() -> psl.onOtaspChanged(otaspMode)));
         }
 
         public void onCellInfoChanged(List<CellInfo> cellInfo) {
-            send(LISTEN_CELL_INFO, 0, 0, cellInfo);
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(() -> psl.onCellInfoChanged(cellInfo)));
         }
 
         public void onPreciseCallStateChanged(PreciseCallState callState) {
-            send(LISTEN_PRECISE_CALL_STATE, 0, 0, callState);
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(() -> psl.onPreciseCallStateChanged(callState)));
         }
 
         public void onPreciseDataConnectionStateChanged(
                 PreciseDataConnectionState dataConnectionState) {
-            send(LISTEN_PRECISE_DATA_CONNECTION_STATE, 0, 0, dataConnectionState);
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(
+                            () -> psl.onPreciseDataConnectionStateChanged(dataConnectionState)));
         }
 
-        public void onDataConnectionRealTimeInfoChanged(
-                DataConnectionRealTimeInfo dcRtInfo) {
-            send(LISTEN_DATA_CONNECTION_REAL_TIME_INFO, 0, 0, dcRtInfo);
+        public void onDataConnectionRealTimeInfoChanged(DataConnectionRealTimeInfo dcRtInfo) {
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(
+                            () -> psl.onDataConnectionRealTimeInfoChanged(dcRtInfo)));
         }
 
         public void onSrvccStateChanged(int state) {
-            send(LISTEN_SRVCC_STATE_CHANGED, 0, 0, state);
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(() -> psl.onSrvccStateChanged(state)));
         }
 
         public void onVoiceActivationStateChanged(int activationState) {
-            send(LISTEN_VOICE_ACTIVATION_STATE, 0, 0, activationState);
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(
+                            () -> psl.onVoiceActivationStateChanged(activationState)));
         }
 
         public void onDataActivationStateChanged(int activationState) {
-            send(LISTEN_DATA_ACTIVATION_STATE, 0, 0, activationState);
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(
+                            () -> psl.onDataActivationStateChanged(activationState)));
         }
 
         public void onUserMobileDataStateChanged(boolean enabled) {
-            send(LISTEN_USER_MOBILE_DATA_STATE, 0, 0, enabled);
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(
+                            () -> psl.onUserMobileDataStateChanged(enabled)));
         }
 
         public void onOemHookRawEvent(byte[] rawData) {
-            send(LISTEN_OEM_HOOK_RAW_EVENT, 0, 0, rawData);
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(() -> psl.onOemHookRawEvent(rawData)));
         }
 
         public void onCarrierNetworkChange(boolean active) {
-            send(LISTEN_CARRIER_NETWORK_CHANGE, 0, 0, active);
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(() -> psl.onCarrierNetworkChange(active)));
         }
 
         public void onPhysicalChannelConfigurationChanged(List<PhysicalChannelConfig> configs) {
-            send(LISTEN_PHYSICAL_CHANNEL_CONFIGURATION, 0, 0, configs);
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(
+                            () -> psl.onPhysicalChannelConfigurationChanged(configs)));
         }
 
         public void onPhoneCapabilityChanged(PhoneCapability capability) {
-            send(LISTEN_PHONE_CAPABILITY_CHANGE, 0, 0, capability);
-        }
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
 
-        public void onPreferredDataSubIdChanged(int subId) {
-            send(LISTEN_PREFERRED_DATA_SUBID_CHANGE, 0, 0, subId);
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(() -> psl.onPhoneCapabilityChanged(capability)));
         }
 
         public void onRadioPowerStateChanged(@TelephonyManager.RadioPowerState int state) {
-            send(LISTEN_RADIO_POWER_STATE_CHANGED, 0, 0, state);
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(() -> psl.onRadioPowerStateChanged(state)));
         }
 
+        public void onPreferredDataSubIdChanged(int subId) {
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(() -> psl.onPreferredDataSubIdChanged(subId)));
+        }
     }
 
-    /**
-     * @hide
-     */
-    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
-    @UnsupportedAppUsage
-    public final IPhoneStateListener callback = new IPhoneStateListenerStub(this);
 
     private void log(String s) {
         Rlog.d(LOG_TAG, s);
     }
-}
\ No newline at end of file
+}
diff --git a/telephony/java/android/telephony/euicc/EuiccCardManager.java b/telephony/java/android/telephony/euicc/EuiccCardManager.java
index 1141177..3b1ef3f 100644
--- a/telephony/java/android/telephony/euicc/EuiccCardManager.java
+++ b/telephony/java/android/telephony/euicc/EuiccCardManager.java
@@ -15,6 +15,7 @@
  */
 package android.telephony.euicc;
 
+import android.annotation.CallbackExecutor;
 import android.annotation.IntDef;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
@@ -50,7 +51,6 @@
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
-import android.annotation.CallbackExecutor;
 import java.util.concurrent.Executor;
 
 /**
@@ -119,6 +119,9 @@
     /** Result code when the eUICC card with the given card Id is not found. */
     public static final int RESULT_EUICC_NOT_FOUND = -2;
 
+    /** Result code indicating the caller is not the active LPA. */
+    public static final int RESULT_CALLER_NOT_ALLOWED = -3;
+
     /**
      * Callback to receive the result of an eUICC card API.
      *
@@ -152,7 +155,7 @@
      * Requests all the profiles on eUicc.
      *
      * @param cardId The Id of the eUICC.
-     * @param executor The executor through which the callback should be invode.
+     * @param executor The executor through which the callback should be invoke.
      * @param callback The callback to get the result code and all the profiles.
      */
     public void requestAllProfiles(String cardId, @CallbackExecutor Executor executor,
@@ -176,7 +179,7 @@
      *
      * @param cardId The Id of the eUICC.
      * @param iccid The iccid of the profile.
-     * @param executor The executor through which the callback should be invode.
+     * @param executor The executor through which the callback should be invoke.
      * @param callback The callback to get the result code and profile.
      */
     public void requestProfile(String cardId, String iccid, @CallbackExecutor Executor executor,
@@ -201,7 +204,7 @@
      * @param cardId The Id of the eUICC.
      * @param iccid The iccid of the profile.
      * @param refresh Whether sending the REFRESH command to modem.
-     * @param executor The executor through which the callback should be invode.
+     * @param executor The executor through which the callback should be invoke.
      * @param callback The callback to get the result code.
      */
     public void disableProfile(String cardId, String iccid, boolean refresh,
@@ -227,7 +230,7 @@
      * @param cardId The Id of the eUICC.
      * @param iccid The iccid of the profile to switch to.
      * @param refresh Whether sending the REFRESH command to modem.
-     * @param executor The executor through which the callback should be invode.
+     * @param executor The executor through which the callback should be invoke.
      * @param callback The callback to get the result code and the EuiccProfileInfo enabled.
      */
     public void switchToProfile(String cardId, String iccid, boolean refresh,
@@ -252,7 +255,7 @@
      * @param cardId The Id of the eUICC.
      * @param iccid The iccid of the profile.
      * @param nickname The nickname of the profile.
-     * @param executor The executor through which the callback should be invode.
+     * @param executor The executor through which the callback should be invoke.
      * @param callback The callback to get the result code.
      */
     public void setNickname(String cardId, String iccid, String nickname,
@@ -276,7 +279,7 @@
      *
      * @param cardId The Id of the eUICC.
      * @param iccid The iccid of the profile.
-     * @param executor The executor through which the callback should be invode.
+     * @param executor The executor through which the callback should be invoke.
      * @param callback The callback to get the result code.
      */
     public void deleteProfile(String cardId, String iccid, @CallbackExecutor Executor executor,
@@ -301,7 +304,7 @@
      * @param cardId The Id of the eUICC.
      * @param options Bits of the options of resetting which parts of the eUICC memory. See
      *     EuiccCard for details.
-     * @param executor The executor through which the callback should be invode.
+     * @param executor The executor through which the callback should be invoke.
      * @param callback The callback to get the result code.
      */
     public void resetMemory(String cardId, @ResetOption int options,
@@ -324,7 +327,7 @@
      * Requests the default SM-DP+ address from eUICC.
      *
      * @param cardId The Id of the eUICC.
-     * @param executor The executor through which the callback should be invode.
+     * @param executor The executor through which the callback should be invoke.
      * @param callback The callback to get the result code and the default SM-DP+ address.
      */
     public void requestDefaultSmdpAddress(String cardId, @CallbackExecutor Executor executor,
@@ -347,7 +350,7 @@
      * Requests the SM-DS address from eUICC.
      *
      * @param cardId The Id of the eUICC.
-     * @param executor The executor through which the callback should be invode.
+     * @param executor The executor through which the callback should be invoke.
      * @param callback The callback to get the result code and the SM-DS address.
      */
     public void requestSmdsAddress(String cardId, @CallbackExecutor Executor executor,
@@ -371,7 +374,7 @@
      *
      * @param cardId The Id of the eUICC.
      * @param defaultSmdpAddress The default SM-DP+ address to set.
-     * @param executor The executor through which the callback should be invode.
+     * @param executor The executor through which the callback should be invoke.
      * @param callback The callback to get the result code.
      */
     public void setDefaultSmdpAddress(String cardId, String defaultSmdpAddress,
@@ -395,7 +398,7 @@
      * Requests Rules Authorisation Table.
      *
      * @param cardId The Id of the eUICC.
-     * @param executor The executor through which the callback should be invode.
+     * @param executor The executor through which the callback should be invoke.
      * @param callback the callback to get the result code and the rule authorisation table.
      */
     public void requestRulesAuthTable(String cardId, @CallbackExecutor Executor executor,
@@ -418,7 +421,7 @@
      * Requests the eUICC challenge for new profile downloading.
      *
      * @param cardId The Id of the eUICC.
-     * @param executor The executor through which the callback should be invode.
+     * @param executor The executor through which the callback should be invoke.
      * @param callback the callback to get the result code and the challenge.
      */
     public void requestEuiccChallenge(String cardId, @CallbackExecutor Executor executor,
@@ -441,7 +444,7 @@
      * Requests the eUICC info1 defined in GSMA RSP v2.0+ for new profile downloading.
      *
      * @param cardId The Id of the eUICC.
-     * @param executor The executor through which the callback should be invode.
+     * @param executor The executor through which the callback should be invoke.
      * @param callback the callback to get the result code and the info1.
      */
     public void requestEuiccInfo1(String cardId, @CallbackExecutor Executor executor,
@@ -464,7 +467,7 @@
      * Gets the eUICC info2 defined in GSMA RSP v2.0+ for new profile downloading.
      *
      * @param cardId The Id of the eUICC.
-     * @param executor The executor through which the callback should be invode.
+     * @param executor The executor through which the callback should be invoke.
      * @param callback the callback to get the result code and the info2.
      */
     public void requestEuiccInfo2(String cardId, @CallbackExecutor Executor executor,
@@ -497,7 +500,7 @@
      *     GSMA RSP v2.0+.
      * @param serverCertificate ASN.1 data in byte array indicating SM-DP+ Certificate returned by
      *     SM-DP+ server.
-     * @param executor The executor through which the callback should be invode.
+     * @param executor The executor through which the callback should be invoke.
      * @param callback the callback to get the result code and a byte array which represents a
      *     {@code AuthenticateServerResponse} defined in GSMA RSP v2.0+.
      */
@@ -537,7 +540,7 @@
      *     SM-DP+ server.
      * @param smdpCertificate ASN.1 data in byte array indicating the SM-DP+ Certificate returned
      *     by SM-DP+ server.
-     * @param executor The executor through which the callback should be invode.
+     * @param executor The executor through which the callback should be invoke.
      * @param callback the callback to get the result code and a byte array which represents a
      *     {@code PrepareDownloadResponse} defined in GSMA RSP v2.0+
      */
@@ -569,7 +572,7 @@
      *
      * @param cardId The Id of the eUICC.
      * @param boundProfilePackage the Bound Profile Package data returned by SM-DP+ server.
-     * @param executor The executor through which the callback should be invode.
+     * @param executor The executor through which the callback should be invoke.
      * @param callback the callback to get the result code and a byte array which represents a
      *     {@code LoadBoundProfilePackageResponse} defined in GSMA RSP v2.0+.
      */
@@ -598,7 +601,7 @@
      * @param cardId The Id of the eUICC.
      * @param transactionId the transaction ID returned by SM-DP+ server.
      * @param reason the cancel reason.
-     * @param executor The executor through which the callback should be invode.
+     * @param executor The executor through which the callback should be invoke.
      * @param callback the callback to get the result code and an byte[] which represents a
      *     {@code CancelSessionResponse} defined in GSMA RSP v2.0+.
      */
@@ -627,7 +630,7 @@
      *
      * @param cardId The Id of the eUICC.
      * @param events bits of the event types ({@link EuiccNotification.Event}) to list.
-     * @param executor The executor through which the callback should be invode.
+     * @param executor The executor through which the callback should be invoke.
      * @param callback the callback to get the result code and the list of notifications.
      */
     public void listNotifications(String cardId, @EuiccNotification.Event int events,
@@ -651,7 +654,7 @@
      *
      * @param cardId The Id of the eUICC.
      * @param events bits of the event types ({@link EuiccNotification.Event}) to list.
-     * @param executor The executor through which the callback should be invode.
+     * @param executor The executor through which the callback should be invoke.
      * @param callback the callback to get the result code and the list of notifications.
      */
     public void retrieveNotificationList(String cardId, @EuiccNotification.Event int events,
@@ -675,7 +678,7 @@
      *
      * @param cardId The Id of the eUICC.
      * @param seqNumber the sequence number of the notification.
-     * @param executor The executor through which the callback should be invode.
+     * @param executor The executor through which the callback should be invoke.
      * @param callback the callback to get the result code and the notification.
      */
     public void retrieveNotification(String cardId, int seqNumber,
@@ -699,7 +702,7 @@
      *
      * @param cardId The Id of the eUICC.
      * @param seqNumber the sequence number of the notification.
-     * @param executor The executor through which the callback should be invode.
+     * @param executor The executor through which the callback should be invoke.
      * @param callback the callback to get the result code.
      */
     public void removeNotificationFromList(String cardId, int seqNumber,