Merge "Eliminate potential deadlock in AccessibilityCache"
diff --git a/cmds/app_process/Android.bp b/cmds/app_process/Android.bp
index 0eff83c..a157517 100644
--- a/cmds/app_process/Android.bp
+++ b/cmds/app_process/Android.bp
@@ -29,7 +29,16 @@
         },
     },
 
-    ldflags: ["-Wl,--export-dynamic"],
+    // Symbols exported from the executable in .dynsym interpose symbols in every
+    // linker namespace, including an app's classloader namespace. Provide this
+    // version script to prevent unwanted interposition.
+    //
+    // By default, the static linker doesn't export most of an executable's symbols,
+    // but it will export a symbol that appears to override a symbol in a needed DSO.
+    // This commonly happens with C++ vaguely-linked entities, such as template
+    // functions or type_info variables. Hence, a version script is needed even for
+    // an executable.
+    version_script: "version-script.txt",
 
     shared_libs: [
         "libandroid_runtime",
diff --git a/cmds/app_process/version-script.txt b/cmds/app_process/version-script.txt
new file mode 100644
index 0000000..a98066a
--- /dev/null
+++ b/cmds/app_process/version-script.txt
@@ -0,0 +1,4 @@
+{
+  local:
+    *;
+};
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 63221c5..331fd07 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -17,6 +17,8 @@
 
 package android.bluetooth;
 
+import static java.util.Objects.requireNonNull;
+
 import android.Manifest;
 import android.annotation.CallbackExecutor;
 import android.annotation.IntDef;
@@ -53,8 +55,6 @@
 import android.util.Log;
 import android.util.Pair;
 
-import com.android.internal.util.Preconditions;
-
 import java.io.IOException;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -3091,8 +3091,8 @@
          */
         WrappedOobDataCallback(@NonNull OobDataCallback callback,
                 @NonNull @CallbackExecutor Executor executor) {
-            Preconditions.checkNotNull(callback);
-            Preconditions.checkNotNull(executor);
+            requireNonNull(callback);
+            requireNonNull(executor);
             mCallback = callback;
             mExecutor = executor;
         }
@@ -3158,7 +3158,7 @@
                 != BluetoothDevice.TRANSPORT_LE) {
             throw new IllegalArgumentException("Invalid transport '" + transport + "'!");
         }
-        Preconditions.checkNotNull(callback);
+        requireNonNull(callback);
         if (!isEnabled()) {
             Log.w(TAG, "generateLocalOobData(): Adapter isn't enabled!");
             callback.onError(OOB_ERROR_ADAPTER_DISABLED);
@@ -3293,7 +3293,7 @@
      * @hide
      */
     public static boolean isAddressRandomStatic(@NonNull String address) {
-        Preconditions.checkNotNull(address);
+        requireNonNull(address);
         return checkBluetoothAddress(address)
                 && (Integer.parseInt(address.split(":")[5], 16) & 0b11) == 0b11;
     }
diff --git a/core/java/android/bluetooth/OobData.java b/core/java/android/bluetooth/OobData.java
index 2dfa91d..4e5ede7 100644
--- a/core/java/android/bluetooth/OobData.java
+++ b/core/java/android/bluetooth/OobData.java
@@ -16,6 +16,8 @@
 
 package android.bluetooth;
 
+import static java.util.Objects.requireNonNull;
+
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -23,8 +25,6 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 
-import com.android.internal.util.Preconditions;
-
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 
@@ -214,7 +214,7 @@
         @NonNull
         @SystemApi
         public LeBuilder setDeviceName(@NonNull byte[] deviceName) {
-            Preconditions.checkNotNull(deviceName);
+            requireNonNull(deviceName);
             this.mDeviceName = deviceName;
             return this;
         }
@@ -308,8 +308,8 @@
         @SystemApi
         public LeBuilder(@NonNull byte[] confirmationHash, @NonNull byte[] deviceAddressWithType,
                 @LeRole int leDeviceRole) {
-            Preconditions.checkNotNull(confirmationHash);
-            Preconditions.checkNotNull(deviceAddressWithType);
+            requireNonNull(confirmationHash);
+            requireNonNull(deviceAddressWithType);
             if (confirmationHash.length != OobData.CONFIRMATION_OCTETS) {
                 throw new IllegalArgumentException("confirmationHash must be "
                     + OobData.CONFIRMATION_OCTETS + " octets in length.");
@@ -344,7 +344,7 @@
         @NonNull
         @SystemApi
         public LeBuilder setLeTemporaryKey(@NonNull byte[] leTemporaryKey) {
-            Preconditions.checkNotNull(leTemporaryKey);
+            requireNonNull(leTemporaryKey);
             if (leTemporaryKey.length != LE_TK_OCTETS) {
                 throw new IllegalArgumentException("leTemporaryKey must be "
                         + LE_TK_OCTETS + " octets in length.");
@@ -366,7 +366,7 @@
         @NonNull
         @SystemApi
         public LeBuilder setRandomizerHash(@NonNull byte[] randomizerHash) {
-            Preconditions.checkNotNull(randomizerHash);
+            requireNonNull(randomizerHash);
             if (randomizerHash.length != OobData.RANDOMIZER_OCTETS) {
                 throw new IllegalArgumentException("randomizerHash must be "
                     + OobData.RANDOMIZER_OCTETS + " octets in length.");
@@ -534,9 +534,9 @@
         @SystemApi
         public ClassicBuilder(@NonNull byte[] confirmationHash, @NonNull byte[] classicLength,
                 @NonNull byte[] deviceAddressWithType) {
-            Preconditions.checkNotNull(confirmationHash);
-            Preconditions.checkNotNull(classicLength);
-            Preconditions.checkNotNull(deviceAddressWithType);
+            requireNonNull(confirmationHash);
+            requireNonNull(classicLength);
+            requireNonNull(deviceAddressWithType);
             if (confirmationHash.length != OobData.CONFIRMATION_OCTETS) {
                 throw new IllegalArgumentException("confirmationHash must be "
                     + OobData.CONFIRMATION_OCTETS + " octets in length.");
@@ -567,7 +567,7 @@
         @NonNull
         @SystemApi
         public ClassicBuilder setRandomizerHash(@NonNull byte[] randomizerHash) {
-            Preconditions.checkNotNull(randomizerHash);
+            requireNonNull(randomizerHash);
             if (randomizerHash.length != OobData.RANDOMIZER_OCTETS) {
                 throw new IllegalArgumentException("randomizerHash must be "
                     + OobData.RANDOMIZER_OCTETS + " octets in length.");
@@ -592,7 +592,7 @@
         @NonNull
         @SystemApi
         public ClassicBuilder setDeviceName(@NonNull byte[] deviceName) {
-            Preconditions.checkNotNull(deviceName);
+            requireNonNull(deviceName);
             this.mDeviceName = deviceName;
             return this;
         }
@@ -617,7 +617,7 @@
         @NonNull
         @SystemApi
         public ClassicBuilder setClassOfDevice(@NonNull byte[] classOfDevice) {
-            Preconditions.checkNotNull(classOfDevice);
+            requireNonNull(classOfDevice);
             if (classOfDevice.length != OobData.CLASS_OF_DEVICE_OCTETS) {
                 throw new IllegalArgumentException("classOfDevice must be "
                         + OobData.CLASS_OF_DEVICE_OCTETS + " octets in length.");
diff --git a/core/java/android/bluetooth/le/ScanFilter.java b/core/java/android/bluetooth/le/ScanFilter.java
index a74c663..ddc93327 100644
--- a/core/java/android/bluetooth/le/ScanFilter.java
+++ b/core/java/android/bluetooth/le/ScanFilter.java
@@ -16,7 +16,8 @@
 
 package android.bluetooth.le;
 
-import android.annotation.IntDef;
+import static java.util.Objects.requireNonNull;
+
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
@@ -28,7 +29,6 @@
 import android.os.Parcelable;
 
 import com.android.internal.util.BitUtils;
-import com.android.internal.util.Preconditions;
 
 import java.util.Arrays;
 import java.util.List;
@@ -647,7 +647,7 @@
         public Builder setDeviceAddress(@NonNull String deviceAddress,
                                         @AddressType int addressType,
                                         @NonNull byte[] irk) {
-            Preconditions.checkNotNull(irk);
+            requireNonNull(irk);
             if (irk.length != LEN_IRK_OCTETS) {
                 throw new IllegalArgumentException("'irk' is invalid length!");
             }
@@ -679,7 +679,7 @@
                                                  @Nullable byte[] irk) {
 
             // Make sure our deviceAddress is valid!
-            Preconditions.checkNotNull(deviceAddress);
+            requireNonNull(deviceAddress);
             if (!BluetoothAdapter.checkBluetoothAddress(deviceAddress)) {
                 throw new IllegalArgumentException("invalid device address " + deviceAddress);
             }
diff --git a/services/core/java/com/android/server/compat/CompatConfig.java b/services/core/java/com/android/server/compat/CompatConfig.java
index 909ed11..6dca001 100644
--- a/services/core/java/com/android/server/compat/CompatConfig.java
+++ b/services/core/java/com/android/server/compat/CompatConfig.java
@@ -235,13 +235,11 @@
      * @param packageName app for which the overrides will be applied.
      */
     void addOverrides(CompatibilityOverrideConfig overrides, String packageName) {
-        synchronized (mChanges) {
-            for (Long changeId : overrides.overrides.keySet()) {
-                addOverrideUnsafe(changeId, packageName, overrides.overrides.get(changeId));
-            }
-            saveOverrides();
-            invalidateCache();
+        for (Long changeId : overrides.overrides.keySet()) {
+            addOverrideUnsafe(changeId, packageName, overrides.overrides.get(changeId));
         }
+        saveOverrides();
+        invalidateCache();
     }
 
     private boolean addOverrideUnsafe(long changeId, String packageName,
@@ -335,27 +333,38 @@
 
     /**
      * Unsafe version of {@link #removeOverride(long, String)}.
-     * It does not invalidate the cache nor save the overrides.
+     * It does not save the overrides.
      */
     private boolean removeOverrideUnsafe(long changeId, String packageName) {
         Long versionCode = getVersionCodeOrNull(packageName);
         synchronized (mChanges) {
             CompatChange c = mChanges.get(changeId);
             if (c != null) {
-                OverrideAllowedState allowedState =
-                        mOverrideValidator.getOverrideAllowedState(changeId, packageName);
-                if (c.hasPackageOverride(packageName)) {
-                    allowedState.enforce(changeId, packageName);
-                    c.removePackageOverride(packageName, allowedState, versionCode);
-                    invalidateCache();
-                    return true;
-                }
+                return removeOverrideUnsafe(c, packageName, versionCode);
             }
         }
         return false;
     }
 
     /**
+     * Similar to {@link #removeOverrideUnsafe(long, String)} except this method receives a {@link
+     * CompatChange} directly as well as the package's version code.
+     */
+    private boolean removeOverrideUnsafe(CompatChange change, String packageName,
+            @Nullable Long versionCode) {
+        long changeId = change.getId();
+        OverrideAllowedState allowedState =
+                mOverrideValidator.getOverrideAllowedState(changeId, packageName);
+        if (change.hasPackageOverride(packageName)) {
+            allowedState.enforce(changeId, packageName);
+            change.removePackageOverride(packageName, allowedState, versionCode);
+            invalidateCache();
+            return true;
+        }
+        return false;
+    }
+
+    /**
      * Removes all overrides previously added via {@link #addOverride(long, String, boolean)} or
      * {@link #addOverrides(CompatibilityOverrideConfig, String)} for a certain package.
      *
@@ -364,10 +373,11 @@
      * @param packageName the package for which the overrides should be purged
      */
     void removePackageOverrides(String packageName) {
+        Long versionCode = getVersionCodeOrNull(packageName);
         synchronized (mChanges) {
             for (int i = 0; i < mChanges.size(); ++i) {
                 CompatChange change = mChanges.valueAt(i);
-                removeOverrideUnsafe(change.getId(), packageName);
+                removeOverrideUnsafe(change, packageName, versionCode);
             }
             saveOverrides();
             invalidateCache();
@@ -386,13 +396,11 @@
      */
     void removePackageOverrides(CompatibilityOverridesToRemoveConfig overridesToRemove,
             String packageName) {
-        synchronized (mChanges) {
-            for (Long changeId : overridesToRemove.changeIds) {
-                removeOverrideUnsafe(changeId, packageName);
-            }
-            saveOverrides();
-            invalidateCache();
+        for (Long changeId : overridesToRemove.changeIds) {
+            removeOverrideUnsafe(changeId, packageName);
         }
+        saveOverrides();
+        invalidateCache();
     }
 
     private long[] getAllowedChangesSinceTargetSdkForPackage(String packageName,
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index fd53a10..bf0dda7 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -1248,6 +1248,8 @@
         updateState(DetailedState.CONNECTING, "agentConnect");
 
         final NetworkAgentConfig networkAgentConfig = new NetworkAgentConfig.Builder()
+                .setLegacyType(ConnectivityManager.TYPE_VPN)
+                .setLegacyTypeName("VPN")
                 .setBypassableVpn(mConfig.allowBypass && !mLockdown)
                 .build();
 
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index a90dcab..05ba9da 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -348,6 +348,7 @@
 import com.android.server.SystemConfig;
 import com.android.server.SystemServerInitThreadPool;
 import com.android.server.Watchdog;
+import com.android.server.compat.CompatChange;
 import com.android.server.compat.PlatformCompat;
 import com.android.server.net.NetworkPolicyManagerInternal;
 import com.android.server.pm.Installer.InstallerException;
@@ -2612,39 +2613,43 @@
         PackageManagerService m = new PackageManagerService(injector, onlyCore, factoryTest);
         t.traceEnd(); // "create package manager"
 
-        injector.getCompatibility().registerListener(SELinuxMMAC.SELINUX_LATEST_CHANGES,
-                packageName -> {
-                    synchronized (m.mInstallLock) {
-                        final AndroidPackage pkg;
-                        final PackageSetting ps;
-                        final SharedUserSetting sharedUser;
-                        final String oldSeInfo;
-                        synchronized (m.mLock) {
-                            ps = m.mSettings.getPackageLPr(packageName);
-                            if (ps == null) {
-                                Slog.e(TAG, "Failed to find package setting " + packageName);
-                                return;
-                            }
-                            pkg = ps.pkg;
-                            sharedUser = ps.getSharedUser();
-                            oldSeInfo = AndroidPackageUtils.getSeInfo(pkg, ps);
-                        }
-
-                        if (pkg == null) {
-                            Slog.e(TAG, "Failed to find package " + packageName);
-                            return;
-                        }
-                        final String newSeInfo = SELinuxMMAC.getSeInfo(pkg, sharedUser,
-                                m.mInjector.getCompatibility());
-
-                        if (!newSeInfo.equals(oldSeInfo)) {
-                            Slog.i(TAG, "Updating seInfo for package " + packageName + " from: "
-                                    + oldSeInfo + " to: " + newSeInfo);
-                            ps.getPkgState().setOverrideSeInfo(newSeInfo);
-                            m.prepareAppDataAfterInstallLIF(pkg);
-                        }
+        final CompatChange.ChangeListener selinuxChangeListener = packageName -> {
+            synchronized (m.mInstallLock) {
+                final AndroidPackage pkg;
+                final PackageSetting ps;
+                final SharedUserSetting sharedUser;
+                final String oldSeInfo;
+                synchronized (m.mLock) {
+                    ps = m.mSettings.getPackageLPr(packageName);
+                    if (ps == null) {
+                        Slog.e(TAG, "Failed to find package setting " + packageName);
+                        return;
                     }
-                });
+                    pkg = ps.pkg;
+                    sharedUser = ps.getSharedUser();
+                    oldSeInfo = AndroidPackageUtils.getSeInfo(pkg, ps);
+                }
+
+                if (pkg == null) {
+                    Slog.e(TAG, "Failed to find package " + packageName);
+                    return;
+                }
+                final String newSeInfo = SELinuxMMAC.getSeInfo(pkg, sharedUser,
+                        m.mInjector.getCompatibility());
+
+                if (!newSeInfo.equals(oldSeInfo)) {
+                    Slog.i(TAG, "Updating seInfo for package " + packageName + " from: "
+                            + oldSeInfo + " to: " + newSeInfo);
+                    ps.getPkgState().setOverrideSeInfo(newSeInfo);
+                    m.prepareAppDataAfterInstallLIF(pkg);
+                }
+            }
+        };
+
+        injector.getCompatibility().registerListener(SELinuxMMAC.SELINUX_LATEST_CHANGES,
+                selinuxChangeListener);
+        injector.getCompatibility().registerListener(SELinuxMMAC.SELINUX_R_CHANGES,
+                selinuxChangeListener);
 
         m.installWhitelistedSystemPackages();
         ServiceManager.addService("package", m);
diff --git a/services/core/java/com/android/server/pm/SELinuxMMAC.java b/services/core/java/com/android/server/pm/SELinuxMMAC.java
index fdd9636..c5fbfba 100644
--- a/services/core/java/com/android/server/pm/SELinuxMMAC.java
+++ b/services/core/java/com/android/server/pm/SELinuxMMAC.java
@@ -18,6 +18,7 @@
 
 import android.compat.annotation.ChangeId;
 import android.compat.annotation.EnabledAfter;
+import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageParser.SigningDetails;
 import android.content.pm.Signature;
 import android.os.Environment;
@@ -77,9 +78,21 @@
     private static final String TARGETSDKVERSION_STR = ":targetSdkVersion=";
 
     /**
-     * This change gates apps access to untrusted_app_R-targetSDk SELinux domain. Allows opt-in
+     * Allows opt-in to the latest targetSdkVersion enforced changes without changing target SDK.
+     * Turning this change off for an app targeting the latest SDK is a no-op.
+     *
+     * <p>Has no effect for apps using shared user id.
+     *
+     * TODO(b/143539591): Update description with relevant SELINUX changes this opts in to.
+     */
+    @EnabledAfter(targetSdkVersion = android.os.Build.VERSION_CODES.R)
+    @ChangeId
+    static final long SELINUX_LATEST_CHANGES = 143539591L;
+
+    /**
+     * This change gates apps access to untrusted_app_R-targetSDK SELinux domain. Allows opt-in
      * to R targetSdkVersion enforced changes without changing target SDK. Turning this change
-     * off for an app targeting R is a no-op.
+     * off for an app targeting S is a no-op.
      *
      * <p>Has no effect for apps using shared user id.
      *
@@ -87,7 +100,7 @@
      */
     @EnabledAfter(targetSdkVersion = android.os.Build.VERSION_CODES.Q)
     @ChangeId
-    static final long SELINUX_LATEST_CHANGES = 143539591L;
+    static final long SELINUX_R_CHANGES = 168782947L;
 
     // Only initialize sMacPermissions once.
     static {
@@ -349,9 +362,11 @@
         if ((sharedUserSetting != null) && (sharedUserSetting.packages.size() != 0)) {
             return sharedUserSetting.seInfoTargetSdkVersion;
         }
-        if (compatibility.isChangeEnabledInternal(SELINUX_LATEST_CHANGES,
-                pkg.toAppInfoWithoutState())) {
-            return android.os.Build.VERSION_CODES.R;
+        final ApplicationInfo appInfo = pkg.toAppInfoWithoutState();
+        if (compatibility.isChangeEnabledInternal(SELINUX_LATEST_CHANGES, appInfo)) {
+            return android.os.Build.VERSION_CODES.S;
+        } else if (compatibility.isChangeEnabledInternal(SELINUX_R_CHANGES, appInfo)) {
+            return Math.max(android.os.Build.VERSION_CODES.R, pkg.getTargetSdkVersion());
         }
 
         return pkg.getTargetSdkVersion();
diff --git a/services/tests/servicestests/src/com/android/server/pm/SELinuxMMACTest.java b/services/tests/servicestests/src/com/android/server/pm/SELinuxMMACTest.java
index a550b27..f1930d7 100644
--- a/services/tests/servicestests/src/com/android/server/pm/SELinuxMMACTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/SELinuxMMACTest.java
@@ -44,7 +44,8 @@
 public class SELinuxMMACTest {
 
     private static final String PACKAGE_NAME = "my.package";
-    private static final int OPT_IN_VERSION = Build.VERSION_CODES.R;
+    private static final int LATEST_OPT_IN_VERSION = Build.VERSION_CODES.S;
+    private static final int R_OPT_IN_VERSION = Build.VERSION_CODES.R;
 
     @Mock
     PlatformCompat mMockCompatibility;
@@ -56,7 +57,17 @@
                 argThat(argument -> argument.packageName.equals(pkg.getPackageName()))))
                 .thenReturn(true);
         assertThat(SELinuxMMAC.getSeInfo(pkg, null, mMockCompatibility),
-                is("default:targetSdkVersion=" + OPT_IN_VERSION));
+                is("default:targetSdkVersion=" + LATEST_OPT_IN_VERSION));
+    }
+
+    @Test
+    public void getSeInfoOptInToR() {
+        AndroidPackage pkg = makePackage(Build.VERSION_CODES.P);
+        when(mMockCompatibility.isChangeEnabledInternal(eq(SELinuxMMAC.SELINUX_R_CHANGES),
+                argThat(argument -> argument.packageName.equals(pkg.getPackageName()))))
+                .thenReturn(true);
+        assertThat(SELinuxMMAC.getSeInfo(pkg, null, mMockCompatibility),
+                is("default:targetSdkVersion=" + R_OPT_IN_VERSION));
     }
 
     @Test
@@ -70,13 +81,33 @@
     }
 
     @Test
-    public void getSeInfoNoOptInButAlreadyR() {
-        AndroidPackage pkg = makePackage(OPT_IN_VERSION);
+    public void getSeInfoNoOptInButAlreadyLatest() {
+        AndroidPackage pkg = makePackage(LATEST_OPT_IN_VERSION);
         when(mMockCompatibility.isChangeEnabledInternal(eq(SELinuxMMAC.SELINUX_LATEST_CHANGES),
                 argThat(argument -> argument.packageName.equals(pkg.getPackageName()))))
                 .thenReturn(false);
         assertThat(SELinuxMMAC.getSeInfo(pkg, null, mMockCompatibility),
-                is("default:targetSdkVersion=" + OPT_IN_VERSION));
+                is("default:targetSdkVersion=" + LATEST_OPT_IN_VERSION));
+    }
+
+    @Test
+    public void getSeInfoNoOptInButAlreadyR() {
+        AndroidPackage pkg = makePackage(R_OPT_IN_VERSION);
+        when(mMockCompatibility.isChangeEnabledInternal(eq(SELinuxMMAC.SELINUX_R_CHANGES),
+                argThat(argument -> argument.packageName.equals(pkg.getPackageName()))))
+                .thenReturn(false);
+        assertThat(SELinuxMMAC.getSeInfo(pkg, null, mMockCompatibility),
+                is("default:targetSdkVersion=" + R_OPT_IN_VERSION));
+    }
+
+    @Test
+    public void getSeInfoOptInRButLater() {
+        AndroidPackage pkg = makePackage(R_OPT_IN_VERSION + 1);
+        when(mMockCompatibility.isChangeEnabledInternal(eq(SELinuxMMAC.SELINUX_R_CHANGES),
+                argThat(argument -> argument.packageName.equals(pkg.getPackageName()))))
+                .thenReturn(true);
+        assertThat(SELinuxMMAC.getSeInfo(pkg, null, mMockCompatibility),
+                is("default:targetSdkVersion=" + (R_OPT_IN_VERSION + 1)));
     }
 
     private AndroidPackage makePackage(int targetSdkVersion) {
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index ae5db3d..52d560c 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -1718,11 +1718,13 @@
         public abstract void onSetDeviceOrientation(int rotation);
 
         /**
-         * Sets camera zoom ratio.
+         * Sets the camera zoom ratio.
          * <p>
          * Sent from the {@link InCallService} via {@link InCallService.VideoCall#setZoom(float)}.
          *
-         * @param value The camera zoom ratio.
+         * @param value The camera zoom ratio; for the current camera, should be a value in the
+         * range defined by
+         * {@link android.hardware.camera2.CameraCharacteristics#CONTROL_ZOOM_RATIO_RANGE}.
          */
         public abstract void onSetZoom(float value);
 
diff --git a/telecomm/java/android/telecom/InCallService.java b/telecomm/java/android/telecom/InCallService.java
index 0ff288b..5e3d26a 100644
--- a/telecomm/java/android/telecom/InCallService.java
+++ b/telecomm/java/android/telecom/InCallService.java
@@ -764,11 +764,13 @@
         public abstract void setDeviceOrientation(int rotation);
 
         /**
-         * Sets camera zoom ratio.
+         * Sets the camera zoom ratio.
          * <p>
          * Handled by {@link Connection.VideoProvider#onSetZoom(float)}.
          *
-         * @param value The camera zoom ratio.
+         * @param value The camera zoom ratio; for the current camera, should be a value in the
+         * range defined by
+         * {@link android.hardware.camera2.CameraCharacteristics#CONTROL_ZOOM_RATIO_RANGE}.
          */
         public abstract void setZoom(float value);