diff options
193 files changed, 3086 insertions, 1193 deletions
diff --git a/Android.bp b/Android.bp index a10f8de13c8d..bba6185739fd 100644 --- a/Android.bp +++ b/Android.bp @@ -642,13 +642,13 @@ filegroup { name: "framework-tethering-shared-srcs", srcs: [ "core/java/android/util/LocalLog.java", - "core/java/com/android/internal/util/BitUtils.java", "core/java/com/android/internal/util/IndentingPrintWriter.java", "core/java/com/android/internal/util/IState.java", "core/java/com/android/internal/util/MessageUtils.java", "core/java/com/android/internal/util/Preconditions.java", "core/java/com/android/internal/util/State.java", "core/java/com/android/internal/util/StateMachine.java", + "core/java/android/net/shared/Inet4AddressUtils.java", ], } diff --git a/api/current.txt b/api/current.txt index d83440b5ef75..51641f23a49e 100644 --- a/api/current.txt +++ b/api/current.txt @@ -6790,6 +6790,7 @@ package android.app.admin { method @Nullable public java.util.List<java.lang.String> getPermittedAccessibilityServices(@NonNull android.content.ComponentName); method @Nullable public java.util.List<java.lang.String> getPermittedCrossProfileNotificationListeners(@NonNull android.content.ComponentName); method @Nullable public java.util.List<java.lang.String> getPermittedInputMethods(@NonNull android.content.ComponentName); + method @NonNull public java.util.List<java.lang.String> getProtectedPackages(@NonNull android.content.ComponentName); method public long getRequiredStrongAuthTimeout(@Nullable android.content.ComponentName); method public boolean getScreenCaptureDisabled(@Nullable android.content.ComponentName); method public java.util.List<android.os.UserHandle> getSecondaryUsers(@NonNull android.content.ComponentName); @@ -6911,6 +6912,7 @@ package android.app.admin { method public boolean setPermittedInputMethods(@NonNull android.content.ComponentName, java.util.List<java.lang.String>); method public void setProfileEnabled(@NonNull android.content.ComponentName); method public void setProfileName(@NonNull android.content.ComponentName, String); + method public void setProtectedPackages(@NonNull android.content.ComponentName, @NonNull java.util.List<java.lang.String>); method public void setRecommendedGlobalProxy(@NonNull android.content.ComponentName, @Nullable android.net.ProxyInfo); method public void setRequiredStrongAuthTimeout(@NonNull android.content.ComponentName, long); method public boolean setResetPasswordToken(android.content.ComponentName, byte[]); @@ -28679,6 +28681,7 @@ package android.media.tv { method public int getVideoHeight(); method public float getVideoPixelAspectRatio(); method public int getVideoWidth(); + method public boolean isAudioDescription(); method public boolean isEncrypted(); method public void writeToParcel(android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.media.tv.TvTrackInfo> CREATOR; @@ -28691,6 +28694,7 @@ package android.media.tv { ctor public TvTrackInfo.Builder(int, @NonNull String); method public android.media.tv.TvTrackInfo build(); method public android.media.tv.TvTrackInfo.Builder setAudioChannelCount(int); + method @NonNull public android.media.tv.TvTrackInfo.Builder setAudioDescription(boolean); method public android.media.tv.TvTrackInfo.Builder setAudioSampleRate(int); method public android.media.tv.TvTrackInfo.Builder setDescription(CharSequence); method @NonNull public android.media.tv.TvTrackInfo.Builder setEncrypted(boolean); @@ -30353,6 +30357,7 @@ package android.net.wifi { method public String getPlmn(); method public String getRealm(); method @Deprecated public String getSubjectMatch(); + method public boolean isAuthenticationSimBased(); method public void setAltSubjectMatch(String); method public void setAnonymousIdentity(String); method public void setCaCertificate(@Nullable java.security.cert.X509Certificate); diff --git a/api/system-current.txt b/api/system-current.txt index fc1b5b604a3a..41ded16bff08 100755 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -1532,6 +1532,14 @@ package android.bluetooth { method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int); } + public final class BluetoothHidHost implements android.bluetooth.BluetoothProfile { + method @NonNull public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices(); + method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public int getConnectionPolicy(@Nullable android.bluetooth.BluetoothDevice); + method public int getConnectionState(@Nullable android.bluetooth.BluetoothDevice); + method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean setConnectionPolicy(@Nullable android.bluetooth.BluetoothDevice, int); + field public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.input.profile.action.CONNECTION_STATE_CHANGED"; + } + public final class BluetoothPan implements android.bluetooth.BluetoothProfile { method protected void finalize(); method @NonNull public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices(); @@ -1675,6 +1683,7 @@ package android.content { field public static final String EUICC_CARD_SERVICE = "euicc_card"; field public static final String HDMI_CONTROL_SERVICE = "hdmi_control"; field public static final String NETD_SERVICE = "netd"; + field public static final String NETWORK_POLICY_SERVICE = "netpolicy"; field public static final String NETWORK_SCORE_SERVICE = "network_score"; field public static final String OEM_LOCK_SERVICE = "oem_lock"; field public static final String PERMISSION_SERVICE = "permission"; @@ -2132,6 +2141,7 @@ package android.content.pm { field public static final String EXTRA_REQUEST_PERMISSIONS_NAMES = "android.content.pm.extra.REQUEST_PERMISSIONS_NAMES"; field public static final String EXTRA_REQUEST_PERMISSIONS_RESULTS = "android.content.pm.extra.REQUEST_PERMISSIONS_RESULTS"; field public static final String FEATURE_BROADCAST_RADIO = "android.hardware.broadcastradio"; + field public static final String FEATURE_REBOOT_ESCROW = "android.hardware.reboot_escrow"; field public static final String FEATURE_TELEPHONY_CARRIERLOCK = "android.hardware.telephony.carrierlock"; field public static final int FLAG_PERMISSION_APPLY_RESTRICTION = 16384; // 0x4000 field public static final int FLAG_PERMISSION_GRANTED_BY_DEFAULT = 32; // 0x20 @@ -5737,6 +5747,7 @@ package android.net.wifi { field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.SoftApCapability> CREATOR; field public static final int SOFTAP_FEATURE_ACS_OFFLOAD = 1; // 0x1 field public static final int SOFTAP_FEATURE_CLIENT_FORCE_DISCONNECT = 2; // 0x2 + field public static final int SOFTAP_FEATURE_WPA3_SAE = 4; // 0x4 } public final class SoftApConfiguration implements android.os.Parcelable { @@ -5745,6 +5756,7 @@ package android.net.wifi { method @Nullable public android.net.MacAddress getBssid(); method public int getChannel(); method public int getMaxNumberOfClients(); + method @Nullable public String getPassphrase(); method public int getSecurityType(); method @Nullable public String getSsid(); method @Nullable public String getWpa2Passphrase(); @@ -5757,6 +5769,8 @@ package android.net.wifi { field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.SoftApConfiguration> CREATOR; field public static final int SECURITY_TYPE_OPEN = 0; // 0x0 field public static final int SECURITY_TYPE_WPA2_PSK = 1; // 0x1 + field public static final int SECURITY_TYPE_WPA3_SAE = 3; // 0x3 + field public static final int SECURITY_TYPE_WPA3_SAE_TRANSITION = 2; // 0x2 } public static final class SoftApConfiguration.Builder { @@ -5768,6 +5782,7 @@ package android.net.wifi { method @NonNull public android.net.wifi.SoftApConfiguration.Builder setChannel(int, int); method @NonNull public android.net.wifi.SoftApConfiguration.Builder setHiddenSsid(boolean); method @NonNull public android.net.wifi.SoftApConfiguration.Builder setMaxNumberOfClients(int); + method @NonNull public android.net.wifi.SoftApConfiguration.Builder setPassphrase(@Nullable String, int); method @NonNull public android.net.wifi.SoftApConfiguration.Builder setSsid(@Nullable String); method @NonNull public android.net.wifi.SoftApConfiguration.Builder setWpa2Passphrase(@Nullable String); } @@ -6974,9 +6989,12 @@ package android.os { public class RecoverySystem { method @RequiresPermission(android.Manifest.permission.RECOVERY) public static void cancelScheduledUpdate(android.content.Context) throws java.io.IOException; + method @RequiresPermission(android.Manifest.permission.RECOVERY) public static boolean clearPrepareForUnattendedUpdate(@NonNull android.content.Context) throws java.io.IOException; method @RequiresPermission(android.Manifest.permission.RECOVERY) public static void installPackage(android.content.Context, java.io.File, boolean) throws java.io.IOException; + method @RequiresPermission(android.Manifest.permission.RECOVERY) public static void prepareForUnattendedUpdate(@NonNull android.content.Context, @NonNull String, @Nullable android.content.IntentSender) throws java.io.IOException; method @RequiresPermission(android.Manifest.permission.RECOVERY) public static void processPackage(android.content.Context, java.io.File, android.os.RecoverySystem.ProgressListener, android.os.Handler) throws java.io.IOException; method @RequiresPermission(android.Manifest.permission.RECOVERY) public static void processPackage(android.content.Context, java.io.File, android.os.RecoverySystem.ProgressListener) throws java.io.IOException; + method @RequiresPermission(android.Manifest.permission.RECOVERY) public static boolean rebootAndApply(@NonNull android.content.Context, @NonNull String, @NonNull String) throws java.io.IOException; method @RequiresPermission(allOf={android.Manifest.permission.RECOVERY, android.Manifest.permission.REBOOT}) public static void rebootWipeAb(android.content.Context, java.io.File, String) throws java.io.IOException; method @RequiresPermission(android.Manifest.permission.RECOVERY) public static void scheduleUpdateOnBoot(android.content.Context, java.io.File) throws java.io.IOException; method public static boolean verifyPackageCompatibility(java.io.File) throws java.io.IOException; diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java index de7cc9d53f2f..032e8245ca42 100644 --- a/core/java/android/app/ActivityManagerInternal.java +++ b/core/java/android/app/ActivityManagerInternal.java @@ -278,6 +278,9 @@ public abstract class ActivityManagerInternal { public abstract boolean isBackgroundActivityStartsEnabled(); public abstract void reportCurKeyguardUsageEvent(boolean keyguardShowing); + /** @see com.android.server.am.ActivityManagerService#monitor */ + public abstract void monitor(); + /** Input dispatch timeout to a window, start the ANR process. */ public abstract long inputDispatchingTimedOut(int pid, boolean aboveSystem, String reason); public abstract boolean inputDispatchingTimedOut(Object proc, String activityShortComponentName, diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index d3132d85ad2f..f3028a10bb10 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -11338,4 +11338,39 @@ public class DevicePolicyManager { } return false; } + + /** + * Called by Device owner to set packages as protected. User will not be able to clear app + * data or force-stop protected packages. + * + * @param admin which {@link DeviceAdminReceiver} this request is associated with + * @param packages The package names to protect. + * @throws SecurityException if {@code admin} is not a device owner. + */ + public void setProtectedPackages(@NonNull ComponentName admin, @NonNull List<String> packages) { + if (mService != null) { + try { + mService.setProtectedPackages(admin, packages); + } catch (RemoteException re) { + throw re.rethrowFromSystemServer(); + } + } + } + + /** + * Returns the list of packages protected by the device owner. + * + * @param admin which {@link DeviceAdminReceiver} this request is associated with + * @throws SecurityException if {@code admin} is not a device owner. + */ + public @NonNull List<String> getProtectedPackages(@NonNull ComponentName admin) { + if (mService != null) { + try { + return mService.getProtectedPackages(admin); + } catch (RemoteException re) { + throw re.rethrowFromSystemServer(); + } + } + return Collections.emptyList(); + } } diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index 08c5dff97884..55dfe2fec4c9 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -452,4 +452,8 @@ interface IDevicePolicyManager { boolean startViewCalendarEventInManagedProfile(String packageName, long eventId, long start, long end, boolean allDay, int flags); boolean setKeyGrantForApp(in ComponentName admin, String callerPackage, String alias, String packageName, boolean hasGrant); + + void setProtectedPackages(in ComponentName admin, in List<String> packages); + + List<String> getProtectedPackages(in ComponentName admin); } diff --git a/core/java/android/bluetooth/BluetoothHidHost.java b/core/java/android/bluetooth/BluetoothHidHost.java index 8f5cdf01f572..c1233b800a51 100644 --- a/core/java/android/bluetooth/BluetoothHidHost.java +++ b/core/java/android/bluetooth/BluetoothHidHost.java @@ -17,9 +17,12 @@ package android.bluetooth; import android.Manifest; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; +import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.content.Context; import android.os.Binder; @@ -43,6 +46,7 @@ import java.util.List; * * @hide */ +@SystemApi public final class BluetoothHidHost implements BluetoothProfile { private static final String TAG = "BluetoothHidHost"; private static final boolean DBG = true; @@ -66,6 +70,7 @@ public final class BluetoothHidHost implements BluetoothProfile { * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to * receive. */ + @SuppressLint("ActionValue") @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.input.profile.action.CONNECTION_STATE_CHANGED"; @@ -325,7 +330,7 @@ public final class BluetoothHidHost implements BluetoothProfile { * {@inheritDoc} */ @Override - public List<BluetoothDevice> getConnectedDevices() { + public @NonNull List<BluetoothDevice> getConnectedDevices() { if (VDBG) log("getConnectedDevices()"); final IBluetoothHidHost service = getService(); if (service != null && isEnabled()) { @@ -342,6 +347,8 @@ public final class BluetoothHidHost implements BluetoothProfile { /** * {@inheritDoc} + * + * @hide */ @Override public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { @@ -363,7 +370,7 @@ public final class BluetoothHidHost implements BluetoothProfile { * {@inheritDoc} */ @Override - public int getConnectionState(BluetoothDevice device) { + public int getConnectionState(@Nullable BluetoothDevice device) { if (VDBG) log("getState(" + device + ")"); final IBluetoothHidHost service = getService(); if (service != null && isEnabled() && isValidDevice(device)) { @@ -409,7 +416,7 @@ public final class BluetoothHidHost implements BluetoothProfile { */ @SystemApi @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) - public boolean setConnectionPolicy(BluetoothDevice device, int connectionPolicy) { + public boolean setConnectionPolicy(@Nullable BluetoothDevice device, int connectionPolicy) { if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")"); final IBluetoothHidHost service = getService(); if (service != null && isEnabled() && isValidDevice(device)) { @@ -457,7 +464,7 @@ public final class BluetoothHidHost implements BluetoothProfile { */ @SystemApi @RequiresPermission(Manifest.permission.BLUETOOTH) - public int getConnectionPolicy(BluetoothDevice device) { + public int getConnectionPolicy(@Nullable BluetoothDevice device) { if (VDBG) log("getConnectionPolicy(" + device + ")"); final IBluetoothHidHost service = getService(); if (service != null && isEnabled() && isValidDevice(device)) { diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 4815d7847115..a28868ef38f8 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -3992,6 +3992,7 @@ public abstract class Context { */ public static final String NETWORK_STATS_SERVICE = "netstats"; /** {@hide} */ + @SystemApi public static final String NETWORK_POLICY_SERVICE = "netpolicy"; /** {@hide} */ public static final String NETWORK_WATCHLIST_SERVICE = "network_watchlist"; diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index f792127bc075..b85c58ad0e2f 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -2918,6 +2918,18 @@ public abstract class PackageManager { public static final String FEATURE_IPSEC_TUNNELS = "android.software.ipsec_tunnels"; /** + * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}: The device has + * the requisite hardware support to support reboot escrow of synthetic password for updates. + * + * <p>This feature implies that the device has the RebootEscrow HAL implementation. + * + * @hide + */ + @SystemApi + @SdkConstant(SdkConstantType.FEATURE) + public static final String FEATURE_REBOOT_ESCROW = "android.hardware.reboot_escrow"; + + /** * Extra field name for the URI to a verification file. Passed to a package * verifier. * diff --git a/core/java/android/os/IRecoverySystem.aidl b/core/java/android/os/IRecoverySystem.aidl index c5ceecd7c8b9..2561e1ea69c6 100644 --- a/core/java/android/os/IRecoverySystem.aidl +++ b/core/java/android/os/IRecoverySystem.aidl @@ -17,6 +17,7 @@ package android.os; +import android.content.IntentSender; import android.os.IRecoverySystemProgressListener; /** @hide */ @@ -26,4 +27,7 @@ interface IRecoverySystem { boolean setupBcb(in String command); boolean clearBcb(); void rebootRecoveryWithCommand(in String command); + boolean requestLskf(in String updateToken, in IntentSender sender); + boolean clearLskf(); + boolean rebootWithLskf(in String updateToken, in String reason); } diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java index 190182072356..cdcb3ff94264 100644 --- a/core/java/android/os/RecoverySystem.java +++ b/core/java/android/os/RecoverySystem.java @@ -18,6 +18,8 @@ package android.os; import static java.nio.charset.StandardCharsets.UTF_8; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SuppressLint; import android.annotation.SystemApi; @@ -29,6 +31,7 @@ import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.IntentSender; import android.content.pm.PackageManager; import android.provider.Settings; import android.telephony.SubscriptionInfo; @@ -624,22 +627,91 @@ public class RecoverySystem { } /** - * Schedule to install the given package on next boot. The caller needs to - * ensure that the package must have been processed (uncrypt'd) if needed. - * It sets up the command in BCB (bootloader control block), which will - * be read by the bootloader and the recovery image. + * Prepare to apply an unattended update by asking the user for their Lock Screen Knowledge + * Factor (LSKF). If supplied, the {@code intentSender} will be called when the system is setup + * and ready to apply the OTA. + * <p> + * When the system is already prepared for update and this API is called again with the same + * {@code updateToken}, it will not call the intent sender nor request the user enter their Lock + * Screen Knowledge Factor. + * <p> + * When this API is called again with a different {@code updateToken}, the prepared-for-update + * status is reset and process repeats as though it's the initial call to this method as + * described in the first paragraph. * - * @param Context the Context to use. - * @param packageFile the package to be installed. - * - * @throws IOException if there were any errors setting up the BCB. + * @param context the Context to use. + * @param updateToken token used to indicate which update was prepared + * @param intentSender the intent to call when the update is prepared; may be {@code null} + * @throws IOException if there were any errors setting up unattended update + * @hide + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.RECOVERY) + public static void prepareForUnattendedUpdate(@NonNull Context context, + @NonNull String updateToken, @Nullable IntentSender intentSender) throws IOException { + if (updateToken == null) { + throw new NullPointerException("updateToken == null"); + } + RecoverySystem rs = (RecoverySystem) context.getSystemService(Context.RECOVERY_SERVICE); + if (!rs.requestLskf(updateToken, intentSender)) { + throw new IOException("preparation for update failed"); + } + } + + /** + * Request that any previously requested Lock Screen Knowledge Factor (LSKF) is cleared and + * the preparation for unattended update is reset. * + * @param context the Context to use. + * @throws IOException if there were any errors setting up unattended update * @hide */ @SystemApi @RequiresPermission(android.Manifest.permission.RECOVERY) - public static void scheduleUpdateOnBoot(Context context, File packageFile) + public static boolean clearPrepareForUnattendedUpdate(@NonNull Context context) throws IOException { + RecoverySystem rs = (RecoverySystem) context.getSystemService(Context.RECOVERY_SERVICE); + return rs.clearLskf(); + } + + /** + * Request that the device reboot and apply the update that has been prepared. The + * {@code updateToken} must match what was given for {@link #prepareForUnattendedUpdate} or + * this will return {@code false}. + * + * @param context the Context to use. + * @param updateToken the token used to call {@link #prepareForUnattendedUpdate} before + * @param reason the reboot reason to give to the {@link PowerManager} + * @throws IOException if there were any errors setting up unattended update + * @return false if the reboot couldn't proceed because the device wasn't ready for an + * unattended reboot or if the {@code updateToken} did not match the previously + * given token + * @hide + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.RECOVERY) + public static boolean rebootAndApply(@NonNull Context context, @NonNull String updateToken, + @NonNull String reason) throws IOException { + if (updateToken == null) { + throw new NullPointerException("updateToken == null"); + } + RecoverySystem rs = (RecoverySystem) context.getSystemService(Context.RECOVERY_SERVICE); + return rs.rebootWithLskf(updateToken, reason); + } + + /** + * Schedule to install the given package on next boot. The caller needs to ensure that the + * package must have been processed (uncrypt'd) if needed. It sets up the command in BCB + * (bootloader control block), which will be read by the bootloader and the recovery image. + * + * @param context the Context to use. + * @param packageFile the package to be installed. + * @throws IOException if there were any errors setting up the BCB. + * @hide + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.RECOVERY) + public static void scheduleUpdateOnBoot(Context context, File packageFile) throws IOException { String filename = packageFile.getCanonicalPath(); boolean securityUpdate = filename.endsWith("_s.zip"); @@ -1204,6 +1276,49 @@ public class RecoverySystem { } /** + * Begins the process of asking the user for the Lock Screen Knowledge Factor. + * + * @param updateToken token that will be used in calls to {@link #rebootAndApply} to ensure + * that the preparation was for the correct update + * @return true if the request was correct + * @throws IOException if the recovery system service could not be contacted + */ + private boolean requestLskf(String updateToken, IntentSender sender) throws IOException { + try { + return mService.requestLskf(updateToken, sender); + } catch (RemoteException e) { + throw new IOException("could request update"); + } + } + + /** + * Calls the recovery system service and clears the setup for the OTA. + * + * @return true if the setup for OTA was cleared + * @throws IOException if the recovery system service could not be contacted + */ + private boolean clearLskf() throws IOException { + try { + return mService.clearLskf(); + } catch (RemoteException e) { + throw new IOException("could not clear LSKF"); + } + } + + /** + * Calls the recovery system service to reboot and apply update. + * + * @param updateToken the update token for which the update was prepared + */ + private boolean rebootWithLskf(String updateToken, String reason) throws IOException { + try { + return mService.rebootWithLskf(updateToken, reason); + } catch (RemoteException e) { + throw new IOException("could not reboot for update"); + } + } + + /** * Internally, recovery treats each line of the command file as a separate * argv, so we only need to protect against newlines and nulls. */ diff --git a/core/java/android/telephony/TelephonyRegistryManager.java b/core/java/android/telephony/TelephonyRegistryManager.java index b94475ac05ce..9387a2c79c6c 100644 --- a/core/java/android/telephony/TelephonyRegistryManager.java +++ b/core/java/android/telephony/TelephonyRegistryManager.java @@ -24,6 +24,7 @@ import android.content.Context; import android.os.Binder; import android.os.RemoteException; import android.os.ServiceManager; +import android.telephony.Annotation.ApnType; import android.telephony.Annotation.CallState; import android.telephony.Annotation.DataActivityType; import android.telephony.Annotation.DataFailureCause; @@ -352,7 +353,7 @@ public class TelephonyRegistryManager { * @param subId for which data connection state changed. * @param slotIndex for which data connections state changed. Can be derived from subId except * when subId is invalid. - * @param apnType the APN type that triggered this update + * @param apnType the apn type bitmask, defined with {@code ApnSetting#TYPE_*} flags. * @param preciseState the PreciseDataConnectionState * * @see android.telephony.PreciseDataConnection @@ -360,7 +361,7 @@ public class TelephonyRegistryManager { * @hide */ public void notifyDataConnectionForSubscriber(int slotIndex, int subId, - String apnType, PreciseDataConnectionState preciseState) { + @ApnType int apnType, PreciseDataConnectionState preciseState) { try { sRegistry.notifyDataConnectionForSubscriber( slotIndex, subId, apnType, preciseState); @@ -553,13 +554,13 @@ public class TelephonyRegistryManager { * @param subId for which data connection failed. * @param slotIndex for which data conenction failed. Can be derived from subId except when * subId is invalid. - * @param apnType the apnType, "ims" for IMS APN, "emergency" for EMERGENCY APN. + * @param apnType the apn type bitmask, defined with {@code ApnSetting#TYPE_*} flags. * @param apn the APN {@link ApnSetting#getApnName()} of this data connection. * @param failCause data fail cause. * * @hide */ - public void notifyPreciseDataConnectionFailed(int subId, int slotIndex, String apnType, + public void notifyPreciseDataConnectionFailed(int subId, int slotIndex, @ApnType int apnType, String apn, @DataFailureCause int failCause) { try { sRegistry.notifyPreciseDataConnectionFailed(slotIndex, subId, apnType, apn, failCause); diff --git a/core/java/com/android/internal/os/RuntimeInit.java b/core/java/com/android/internal/os/RuntimeInit.java index a86d702ba323..179828c4b456 100644 --- a/core/java/com/android/internal/os/RuntimeInit.java +++ b/core/java/com/android/internal/os/RuntimeInit.java @@ -35,7 +35,6 @@ import com.android.internal.logging.AndroidConfig; import com.android.server.NetworkManagementSocketTagger; import dalvik.system.RuntimeHooks; -import dalvik.system.ThreadPrioritySetter; import dalvik.system.VMRuntime; import libcore.content.type.MimeMap; @@ -205,7 +204,6 @@ public class RuntimeInit { */ public static void preForkInit() { if (DEBUG) Slog.d(TAG, "Entered preForkInit."); - RuntimeHooks.setThreadPrioritySetter(new RuntimeThreadPrioritySetter()); RuntimeInit.enableDdms(); // TODO(b/142019040#comment13): Decide whether to load the default instance eagerly, i.e. // MimeMap.setDefault(DefaultMimeMapFactory.create()); @@ -218,35 +216,6 @@ public class RuntimeInit { MimeMap.setDefaultSupplier(DefaultMimeMapFactory::create); } - private static class RuntimeThreadPrioritySetter implements ThreadPrioritySetter { - // Should remain consistent with kNiceValues[] in system/libartpalette/palette_android.cc - private static final int[] NICE_VALUES = { - Process.THREAD_PRIORITY_LOWEST, // 1 (MIN_PRIORITY) - Process.THREAD_PRIORITY_BACKGROUND + 6, - Process.THREAD_PRIORITY_BACKGROUND + 3, - Process.THREAD_PRIORITY_BACKGROUND, - Process.THREAD_PRIORITY_DEFAULT, // 5 (NORM_PRIORITY) - Process.THREAD_PRIORITY_DEFAULT - 2, - Process.THREAD_PRIORITY_DEFAULT - 4, - Process.THREAD_PRIORITY_URGENT_DISPLAY + 3, - Process.THREAD_PRIORITY_URGENT_DISPLAY + 2, - Process.THREAD_PRIORITY_URGENT_DISPLAY // 10 (MAX_PRIORITY) - }; - - @Override - public void setPriority(int priority) { - // Check NICE_VALUES[] length first. - if (NICE_VALUES.length != (1 + Thread.MAX_PRIORITY - Thread.MIN_PRIORITY)) { - throw new AssertionError("Unexpected NICE_VALUES.length=" + NICE_VALUES.length); - } - // Priority should be in the range of MIN_PRIORITY (1) to MAX_PRIORITY (10). - if (priority < Thread.MIN_PRIORITY || priority > Thread.MAX_PRIORITY) { - throw new IllegalArgumentException("Priority out of range: " + priority); - } - Process.setThreadPriority(NICE_VALUES[priority - Thread.MIN_PRIORITY]); - } - } - @UnsupportedAppUsage protected static final void commonInit() { if (DEBUG) Slog.d(TAG, "Entered RuntimeInit!"); diff --git a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl index 6933f166a06d..8e97ae1e4bd1 100644 --- a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl +++ b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl @@ -63,7 +63,7 @@ interface ITelephonyRegistry { void notifyDataActivity(int state); void notifyDataActivityForSubscriber(in int subId, int state); void notifyDataConnectionForSubscriber( - int phoneId, int subId, String apnType, in PreciseDataConnectionState preciseState); + int phoneId, int subId, int apnType, in PreciseDataConnectionState preciseState); @UnsupportedAppUsage void notifyDataConnectionFailed(String apnType); // Uses CellIdentity which is Parcelable here; will convert to CellLocation in client. @@ -75,7 +75,7 @@ interface ITelephonyRegistry { int foregroundCallState, int backgroundCallState); void notifyDisconnectCause(int phoneId, int subId, int disconnectCause, int preciseDisconnectCause); - void notifyPreciseDataConnectionFailed(int phoneId, int subId, String apnType, String apn, + void notifyPreciseDataConnectionFailed(int phoneId, int subId, int apnType, String apn, int failCause); void notifyCellInfoForSubscriber(in int subId, in List<CellInfo> cellInfo); void notifySrvccStateChanged(in int subId, in int lteState); diff --git a/core/java/com/android/internal/util/GrowingArrayUtils.java b/core/java/com/android/internal/util/GrowingArrayUtils.java index 9f563667e019..597fe6b53d11 100644 --- a/core/java/com/android/internal/util/GrowingArrayUtils.java +++ b/core/java/com/android/internal/util/GrowingArrayUtils.java @@ -16,7 +16,7 @@ package com.android.internal.util; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; /** * A helper class that aims to provide comparable growth performance to ArrayList, but on primitive diff --git a/core/java/com/android/internal/util/HexDump.java b/core/java/com/android/internal/util/HexDump.java index 6ffc92853b08..ad88dd6deec6 100644 --- a/core/java/com/android/internal/util/HexDump.java +++ b/core/java/com/android/internal/util/HexDump.java @@ -17,7 +17,7 @@ package com.android.internal.util; import android.annotation.Nullable; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; public class HexDump { diff --git a/core/java/com/android/internal/util/IState.java b/core/java/com/android/internal/util/IState.java index eb66e2ce94d7..07837bf8f587 100644 --- a/core/java/com/android/internal/util/IState.java +++ b/core/java/com/android/internal/util/IState.java @@ -16,7 +16,7 @@ package com.android.internal.util; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.os.Message; /** diff --git a/core/java/com/android/internal/util/IndentingPrintWriter.java b/core/java/com/android/internal/util/IndentingPrintWriter.java index 03a555edf4a8..34c6a055d5bd 100644 --- a/core/java/com/android/internal/util/IndentingPrintWriter.java +++ b/core/java/com/android/internal/util/IndentingPrintWriter.java @@ -16,7 +16,8 @@ package com.android.internal.util; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; + import java.io.PrintWriter; import java.io.Writer; import java.util.Arrays; diff --git a/core/java/com/android/internal/util/JournaledFile.java b/core/java/com/android/internal/util/JournaledFile.java index 065cc5b2416b..a9d8f7239d03 100644 --- a/core/java/com/android/internal/util/JournaledFile.java +++ b/core/java/com/android/internal/util/JournaledFile.java @@ -16,7 +16,7 @@ package com.android.internal.util; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.os.Build; import java.io.File; diff --git a/core/java/com/android/internal/util/MemInfoReader.java b/core/java/com/android/internal/util/MemInfoReader.java index 580c2fa66de2..5de77d9b0545 100644 --- a/core/java/com/android/internal/util/MemInfoReader.java +++ b/core/java/com/android/internal/util/MemInfoReader.java @@ -16,7 +16,7 @@ package com.android.internal.util; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.os.Debug; import android.os.StrictMode; diff --git a/core/java/com/android/internal/util/Preconditions.java b/core/java/com/android/internal/util/Preconditions.java index 3fff5c233890..5bc96d8ee1d3 100644 --- a/core/java/com/android/internal/util/Preconditions.java +++ b/core/java/com/android/internal/util/Preconditions.java @@ -18,7 +18,7 @@ package com.android.internal.util; import android.annotation.IntRange; import android.annotation.NonNull; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.text.TextUtils; import java.util.Collection; diff --git a/core/java/com/android/internal/util/State.java b/core/java/com/android/internal/util/State.java index 3c61e035e886..636378e32091 100644 --- a/core/java/com/android/internal/util/State.java +++ b/core/java/com/android/internal/util/State.java @@ -16,7 +16,7 @@ package com.android.internal.util; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.os.Message; /** diff --git a/core/java/com/android/internal/util/StateMachine.java b/core/java/com/android/internal/util/StateMachine.java index 6c217e5a37bf..0c2406559dcc 100644 --- a/core/java/com/android/internal/util/StateMachine.java +++ b/core/java/com/android/internal/util/StateMachine.java @@ -16,7 +16,7 @@ package com.android.internal.util; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.os.Handler; import android.os.HandlerThread; import android.os.Looper; diff --git a/core/java/com/android/internal/util/XmlUtils.java b/core/java/com/android/internal/util/XmlUtils.java index 8799e3d4c6bf..c1be33a215b8 100644 --- a/core/java/com/android/internal/util/XmlUtils.java +++ b/core/java/com/android/internal/util/XmlUtils.java @@ -16,10 +16,10 @@ package com.android.internal.util; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.graphics.Bitmap; -import android.graphics.BitmapFactory; import android.graphics.Bitmap.CompressFormat; +import android.graphics.BitmapFactory; import android.net.Uri; import android.text.TextUtils; import android.util.ArrayMap; diff --git a/core/java/com/android/internal/view/ActionBarPolicy.java b/core/java/com/android/internal/view/ActionBarPolicy.java index d18c35e703da..d16cb4362f1b 100644 --- a/core/java/com/android/internal/view/ActionBarPolicy.java +++ b/core/java/com/android/internal/view/ActionBarPolicy.java @@ -16,15 +16,15 @@ package com.android.internal.view; -import com.android.internal.R; - -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.content.res.Configuration; import android.content.res.Resources; import android.content.res.TypedArray; import android.os.Build; +import com.android.internal.R; + /** * Allows components to query for various configuration policy decisions * about how the action bar should lay out and behave on the current device. diff --git a/core/java/com/android/internal/view/BaseIWindow.java b/core/java/com/android/internal/view/BaseIWindow.java index 2ac2975d0a44..5dd3389b5d4c 100644 --- a/core/java/com/android/internal/view/BaseIWindow.java +++ b/core/java/com/android/internal/view/BaseIWindow.java @@ -16,6 +16,7 @@ package com.android.internal.view; +import android.compat.annotation.UnsupportedAppUsage; import android.graphics.Point; import android.graphics.Rect; import android.hardware.input.InputManager; @@ -34,8 +35,6 @@ import android.view.WindowInsets.Type.InsetsType; import com.android.internal.os.IResultReceiver; -import dalvik.annotation.compat.UnsupportedAppUsage; - import java.io.IOException; public class BaseIWindow extends IWindow.Stub { diff --git a/core/java/com/android/internal/view/IInputConnectionWrapper.java b/core/java/com/android/internal/view/IInputConnectionWrapper.java index ececba13c760..6278d4a35329 100644 --- a/core/java/com/android/internal/view/IInputConnectionWrapper.java +++ b/core/java/com/android/internal/view/IInputConnectionWrapper.java @@ -18,7 +18,7 @@ package com.android.internal.view; import android.annotation.NonNull; import android.annotation.Nullable; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.os.Build; import android.os.Bundle; import android.os.Handler; diff --git a/core/java/com/android/internal/view/InputBindResult.java b/core/java/com/android/internal/view/InputBindResult.java index 1b133d2a8393..a5964b509b3c 100644 --- a/core/java/com/android/internal/view/InputBindResult.java +++ b/core/java/com/android/internal/view/InputBindResult.java @@ -20,7 +20,7 @@ import static java.lang.annotation.RetentionPolicy.SOURCE; import android.annotation.IntDef; import android.annotation.Nullable; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.content.ComponentName; import android.content.Intent; import android.content.ServiceConnection; diff --git a/core/java/com/android/internal/view/InputConnectionWrapper.java b/core/java/com/android/internal/view/InputConnectionWrapper.java index 0c057ea6df59..a41048c0f426 100644 --- a/core/java/com/android/internal/view/InputConnectionWrapper.java +++ b/core/java/com/android/internal/view/InputConnectionWrapper.java @@ -19,7 +19,7 @@ package com.android.internal.view; import android.annotation.AnyThread; import android.annotation.BinderThread; import android.annotation.NonNull; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.inputmethodservice.AbstractInputMethodService; import android.os.Bundle; import android.os.Handler; diff --git a/core/java/com/android/internal/view/WindowManagerPolicyThread.java b/core/java/com/android/internal/view/WindowManagerPolicyThread.java index b009a2d8ca30..6d691fce4fb0 100644 --- a/core/java/com/android/internal/view/WindowManagerPolicyThread.java +++ b/core/java/com/android/internal/view/WindowManagerPolicyThread.java @@ -16,7 +16,7 @@ package com.android.internal.view; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.os.Looper; /** diff --git a/core/java/com/android/internal/view/menu/ActionMenu.java b/core/java/com/android/internal/view/menu/ActionMenu.java index 977c1f6fda7b..648262965ab1 100644 --- a/core/java/com/android/internal/view/menu/ActionMenu.java +++ b/core/java/com/android/internal/view/menu/ActionMenu.java @@ -16,10 +16,7 @@ package com.android.internal.view.menu; -import java.util.ArrayList; -import java.util.List; - -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.content.ComponentName; import android.content.Context; import android.content.Intent; @@ -30,6 +27,9 @@ import android.view.Menu; import android.view.MenuItem; import android.view.SubMenu; +import java.util.ArrayList; +import java.util.List; + /** * @hide */ diff --git a/core/java/com/android/internal/view/menu/ActionMenuItem.java b/core/java/com/android/internal/view/menu/ActionMenuItem.java index ed253d58fb82..bd8bcb9cf81e 100644 --- a/core/java/com/android/internal/view/menu/ActionMenuItem.java +++ b/core/java/com/android/internal/view/menu/ActionMenuItem.java @@ -17,7 +17,7 @@ package com.android.internal.view.menu; import android.annotation.Nullable; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.content.Intent; import android.content.res.ColorStateList; diff --git a/core/java/com/android/internal/view/menu/ActionMenuItemView.java b/core/java/com/android/internal/view/menu/ActionMenuItemView.java index eb94db33ba1a..7622b939b6eb 100644 --- a/core/java/com/android/internal/view/menu/ActionMenuItemView.java +++ b/core/java/com/android/internal/view/menu/ActionMenuItemView.java @@ -16,7 +16,7 @@ package com.android.internal.view.menu; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.content.res.Configuration; import android.content.res.Resources; diff --git a/core/java/com/android/internal/view/menu/ContextMenuBuilder.java b/core/java/com/android/internal/view/menu/ContextMenuBuilder.java index 3d3aceb4a85f..a9f5e47fc83f 100644 --- a/core/java/com/android/internal/view/menu/ContextMenuBuilder.java +++ b/core/java/com/android/internal/view/menu/ContextMenuBuilder.java @@ -16,7 +16,7 @@ package com.android.internal.view.menu; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.graphics.drawable.Drawable; import android.os.IBinder; diff --git a/core/java/com/android/internal/view/menu/IconMenuItemView.java b/core/java/com/android/internal/view/menu/IconMenuItemView.java index 3d888d347d65..539c71e5c473 100644 --- a/core/java/com/android/internal/view/menu/IconMenuItemView.java +++ b/core/java/com/android/internal/view/menu/IconMenuItemView.java @@ -16,13 +16,12 @@ package com.android.internal.view.menu; -import com.android.internal.view.menu.MenuBuilder.ItemInvoker; - -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Rect; import android.graphics.drawable.Drawable; +import android.text.Layout; import android.text.TextUtils; import android.util.AttributeSet; import android.view.Gravity; @@ -30,7 +29,8 @@ import android.view.SoundEffectConstants; import android.view.View; import android.view.ViewDebug; import android.widget.TextView; -import android.text.Layout; + +import com.android.internal.view.menu.MenuBuilder.ItemInvoker; /** * The item view for each item in the {@link IconMenuView}. diff --git a/core/java/com/android/internal/view/menu/IconMenuView.java b/core/java/com/android/internal/view/menu/IconMenuView.java index 6f264341f7b4..9e240dbd8a21 100644 --- a/core/java/com/android/internal/view/menu/IconMenuView.java +++ b/core/java/com/android/internal/view/menu/IconMenuView.java @@ -16,9 +16,7 @@ package com.android.internal.view.menu; -import com.android.internal.view.menu.MenuBuilder.ItemInvoker; - -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.content.res.Resources; import android.content.res.TypedArray; @@ -29,10 +27,12 @@ import android.os.Parcel; import android.os.Parcelable; import android.util.AttributeSet; import android.view.KeyEvent; +import android.view.LayoutInflater; import android.view.View; import android.view.ViewConfiguration; import android.view.ViewGroup; -import android.view.LayoutInflater; + +import com.android.internal.view.menu.MenuBuilder.ItemInvoker; import java.util.ArrayList; diff --git a/core/java/com/android/internal/view/menu/MenuBuilder.java b/core/java/com/android/internal/view/menu/MenuBuilder.java index 0e07ca79faf7..b31ae38b4566 100644 --- a/core/java/com/android/internal/view/menu/MenuBuilder.java +++ b/core/java/com/android/internal/view/menu/MenuBuilder.java @@ -18,7 +18,7 @@ package com.android.internal.view.menu; import android.annotation.NonNull; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.content.ComponentName; import android.content.Context; import android.content.Intent; diff --git a/core/java/com/android/internal/view/menu/MenuDialogHelper.java b/core/java/com/android/internal/view/menu/MenuDialogHelper.java index 88d0a03bd55f..d02b8f6ceb63 100644 --- a/core/java/com/android/internal/view/menu/MenuDialogHelper.java +++ b/core/java/com/android/internal/view/menu/MenuDialogHelper.java @@ -16,9 +16,9 @@ package com.android.internal.view.menu; -import android.annotation.UnsupportedAppUsage; import android.app.AlertDialog; import android.app.Dialog; +import android.compat.annotation.UnsupportedAppUsage; import android.content.DialogInterface; import android.os.IBinder; import android.view.KeyEvent; diff --git a/core/java/com/android/internal/view/menu/MenuItemImpl.java b/core/java/com/android/internal/view/menu/MenuItemImpl.java index 994a9c117ce9..218f5185ec47 100644 --- a/core/java/com/android/internal/view/menu/MenuItemImpl.java +++ b/core/java/com/android/internal/view/menu/MenuItemImpl.java @@ -16,10 +16,8 @@ package com.android.internal.view.menu; -import com.android.internal.view.menu.MenuView.ItemView; - import android.annotation.Nullable; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.content.ActivityNotFoundException; import android.content.Context; import android.content.Intent; @@ -39,6 +37,8 @@ import android.view.ViewConfiguration; import android.view.ViewDebug; import android.widget.LinearLayout; +import com.android.internal.view.menu.MenuView.ItemView; + /** * @hide */ diff --git a/core/java/com/android/internal/view/menu/MenuPopupHelper.java b/core/java/com/android/internal/view/menu/MenuPopupHelper.java index d00108edefd0..bac602509148 100644 --- a/core/java/com/android/internal/view/menu/MenuPopupHelper.java +++ b/core/java/com/android/internal/view/menu/MenuPopupHelper.java @@ -20,7 +20,7 @@ import android.annotation.AttrRes; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.StyleRes; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.graphics.Point; import android.graphics.Rect; diff --git a/core/java/com/android/internal/view/menu/MenuPresenter.java b/core/java/com/android/internal/view/menu/MenuPresenter.java index c5df8ad6edc6..35b8fefe75ab 100644 --- a/core/java/com/android/internal/view/menu/MenuPresenter.java +++ b/core/java/com/android/internal/view/menu/MenuPresenter.java @@ -18,7 +18,7 @@ package com.android.internal.view.menu; import android.annotation.NonNull; import android.annotation.Nullable; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.os.Parcelable; import android.view.ViewGroup; diff --git a/core/java/com/android/internal/view/menu/MenuView.java b/core/java/com/android/internal/view/menu/MenuView.java index 67a55308938d..a31c820cd2a6 100644 --- a/core/java/com/android/internal/view/menu/MenuView.java +++ b/core/java/com/android/internal/view/menu/MenuView.java @@ -16,10 +16,7 @@ package com.android.internal.view.menu; -import com.android.internal.view.menu.MenuBuilder; -import com.android.internal.view.menu.MenuItemImpl; - -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.graphics.drawable.Drawable; /** diff --git a/core/java/com/android/internal/view/menu/SubMenuBuilder.java b/core/java/com/android/internal/view/menu/SubMenuBuilder.java index cf6d9746bb93..6eb215e94093 100644 --- a/core/java/com/android/internal/view/menu/SubMenuBuilder.java +++ b/core/java/com/android/internal/view/menu/SubMenuBuilder.java @@ -16,7 +16,7 @@ package com.android.internal.view.menu; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.graphics.drawable.Drawable; import android.view.Menu; diff --git a/core/java/com/android/internal/widget/AbsActionBarView.java b/core/java/com/android/internal/widget/AbsActionBarView.java index 9ccee7fc32ff..0f0c1a3de3a2 100644 --- a/core/java/com/android/internal/widget/AbsActionBarView.java +++ b/core/java/com/android/internal/widget/AbsActionBarView.java @@ -15,26 +15,25 @@ */ package com.android.internal.widget; -import com.android.internal.R; - -import android.util.TypedValue; -import android.view.ContextThemeWrapper; -import android.view.MotionEvent; -import android.widget.ActionMenuPresenter; -import android.widget.ActionMenuView; - import android.animation.Animator; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.animation.TimeInterpolator; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.content.res.Configuration; import android.content.res.TypedArray; import android.util.AttributeSet; +import android.util.TypedValue; +import android.view.ContextThemeWrapper; +import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.animation.DecelerateInterpolator; +import android.widget.ActionMenuPresenter; +import android.widget.ActionMenuView; + +import com.android.internal.R; public abstract class AbsActionBarView extends ViewGroup { private static final TimeInterpolator sAlphaInterpolator = new DecelerateInterpolator(); diff --git a/core/java/com/android/internal/widget/ActionBarContextView.java b/core/java/com/android/internal/widget/ActionBarContextView.java index 78ed53fa918c..051526ef2da7 100644 --- a/core/java/com/android/internal/widget/ActionBarContextView.java +++ b/core/java/com/android/internal/widget/ActionBarContextView.java @@ -15,13 +15,7 @@ */ package com.android.internal.widget; -import com.android.internal.R; - -import android.widget.ActionMenuPresenter; -import android.widget.ActionMenuView; -import com.android.internal.view.menu.MenuBuilder; - -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.content.res.TypedArray; import android.graphics.drawable.Drawable; @@ -32,9 +26,14 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.accessibility.AccessibilityEvent; +import android.widget.ActionMenuPresenter; +import android.widget.ActionMenuView; import android.widget.LinearLayout; import android.widget.TextView; +import com.android.internal.R; +import com.android.internal.view.menu.MenuBuilder; + /** * @hide */ diff --git a/core/java/com/android/internal/widget/ActionBarOverlayLayout.java b/core/java/com/android/internal/widget/ActionBarOverlayLayout.java index e9e3cdab7a10..aca0b713686f 100644 --- a/core/java/com/android/internal/widget/ActionBarOverlayLayout.java +++ b/core/java/com/android/internal/widget/ActionBarOverlayLayout.java @@ -18,7 +18,7 @@ package com.android.internal.widget; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.content.pm.ActivityInfo; import android.content.res.Configuration; @@ -41,6 +41,7 @@ import android.view.Window; import android.view.WindowInsets; import android.widget.OverScroller; import android.widget.Toolbar; + import com.android.internal.view.menu.MenuPresenter; /** diff --git a/core/java/com/android/internal/widget/AlertDialogLayout.java b/core/java/com/android/internal/widget/AlertDialogLayout.java index 7a0174946671..d879b6d569f3 100644 --- a/core/java/com/android/internal/widget/AlertDialogLayout.java +++ b/core/java/com/android/internal/widget/AlertDialogLayout.java @@ -18,8 +18,8 @@ package com.android.internal.widget; import android.annotation.AttrRes; import android.annotation.Nullable; -import android.annotation.UnsupportedAppUsage; import android.annotation.StyleRes; +import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.graphics.drawable.Drawable; import android.util.AttributeSet; diff --git a/core/java/com/android/internal/widget/ButtonBarLayout.java b/core/java/com/android/internal/widget/ButtonBarLayout.java index 0ca67438c5c3..ff131071efef 100644 --- a/core/java/com/android/internal/widget/ButtonBarLayout.java +++ b/core/java/com/android/internal/widget/ButtonBarLayout.java @@ -16,7 +16,7 @@ package com.android.internal.widget; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.content.res.TypedArray; import android.util.AttributeSet; diff --git a/core/java/com/android/internal/widget/CachingIconView.java b/core/java/com/android/internal/widget/CachingIconView.java index 35bff6d7c430..74ad81566ef4 100644 --- a/core/java/com/android/internal/widget/CachingIconView.java +++ b/core/java/com/android/internal/widget/CachingIconView.java @@ -18,7 +18,7 @@ package com.android.internal.widget; import android.annotation.DrawableRes; import android.annotation.Nullable; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.content.res.Configuration; import android.graphics.Bitmap; diff --git a/core/java/com/android/internal/widget/DialogTitle.java b/core/java/com/android/internal/widget/DialogTitle.java index 405436c53ff0..0bfd684317fd 100644 --- a/core/java/com/android/internal/widget/DialogTitle.java +++ b/core/java/com/android/internal/widget/DialogTitle.java @@ -16,7 +16,7 @@ package com.android.internal.widget; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.content.res.TypedArray; import android.text.Layout; diff --git a/core/java/com/android/internal/widget/EditableInputConnection.java b/core/java/com/android/internal/widget/EditableInputConnection.java index 2b648e90f7dd..ff3543c837eb 100644 --- a/core/java/com/android/internal/widget/EditableInputConnection.java +++ b/core/java/com/android/internal/widget/EditableInputConnection.java @@ -16,7 +16,7 @@ package com.android.internal.widget; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.os.Bundle; import android.text.Editable; import android.text.method.KeyListener; diff --git a/core/java/com/android/internal/widget/LinearLayoutWithDefaultTouchRecepient.java b/core/java/com/android/internal/widget/LinearLayoutWithDefaultTouchRecepient.java index cc7911da0b96..9ef9f697c46c 100644 --- a/core/java/com/android/internal/widget/LinearLayoutWithDefaultTouchRecepient.java +++ b/core/java/com/android/internal/widget/LinearLayoutWithDefaultTouchRecepient.java @@ -16,12 +16,12 @@ package com.android.internal.widget; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.graphics.Rect; import android.util.AttributeSet; -import android.view.View; import android.view.MotionEvent; +import android.view.View; import android.widget.LinearLayout; diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java index 4f4c8c3ec377..f37a46811b81 100644 --- a/core/java/com/android/internal/widget/LockPatternUtils.java +++ b/core/java/com/android/internal/widget/LockPatternUtils.java @@ -25,11 +25,11 @@ import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; -import android.annotation.UnsupportedAppUsage; import android.app.admin.DevicePolicyManager; import android.app.admin.PasswordMetrics; import android.app.trust.IStrongAuthTracker; import android.app.trust.TrustManager; +import android.compat.annotation.UnsupportedAppUsage; import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; @@ -55,10 +55,10 @@ import android.util.SparseLongArray; import com.android.internal.annotations.VisibleForTesting; import com.android.server.LocalServices; -import com.google.android.collect.Lists; - import libcore.util.HexEncoding; +import com.google.android.collect.Lists; + import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.security.MessageDigest; @@ -1599,6 +1599,11 @@ public class LockPatternUtils { public static final int STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN = 0x20; /** + * Strong authentication is required to prepare for unattended upgrade. + */ + public static final int STRONG_AUTH_REQUIRED_FOR_UNATTENDED_UPDATE = 0x40; + + /** * Strong auth flags that do not prevent biometric methods from being accepted as auth. * If any other flags are set, biometric authentication is disabled. */ diff --git a/core/java/com/android/internal/widget/LockPatternView.java b/core/java/com/android/internal/widget/LockPatternView.java index 74a0aa37dafb..4ddc782aacb4 100644 --- a/core/java/com/android/internal/widget/LockPatternView.java +++ b/core/java/com/android/internal/widget/LockPatternView.java @@ -19,7 +19,7 @@ package com.android.internal.widget; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.content.res.Resources; import android.content.res.TypedArray; diff --git a/core/java/com/android/internal/widget/LockSettingsInternal.java b/core/java/com/android/internal/widget/LockSettingsInternal.java index dd05576338ef..90a18ef87ee2 100644 --- a/core/java/com/android/internal/widget/LockSettingsInternal.java +++ b/core/java/com/android/internal/widget/LockSettingsInternal.java @@ -77,4 +77,34 @@ public abstract class LockSettingsInternal { * @return the user password metrics. */ public abstract @Nullable PasswordMetrics getUserPasswordMetrics(int userHandle); + + /** + * Prepare for reboot escrow. This triggers the strong auth to be required. After the escrow + * is complete as indicated by calling to the listener registered with {@link + * #setRebootEscrowListener}, then {@link #armRebootEscrow()} should be called before + * rebooting to apply the update. + */ + public abstract void prepareRebootEscrow(); + + /** + * Registers a listener for when the RebootEscrow HAL has stored its data needed for rebooting + * for an OTA. + * + * @see RebootEscrowListener + * @param listener + */ + public abstract void setRebootEscrowListener(RebootEscrowListener listener); + + /** + * Requests that any data needed for rebooting is cleared from the RebootEscrow HAL. + */ + public abstract void clearRebootEscrow(); + + /** + * Should be called immediately before rebooting for an update. This depends on {@link + * #prepareRebootEscrow()} having been called and the escrow completing. + * + * @return true if the arming worked + */ + public abstract boolean armRebootEscrow(); } diff --git a/core/java/com/android/internal/widget/NumericTextView.java b/core/java/com/android/internal/widget/NumericTextView.java index d2156704a655..c8f901133be6 100644 --- a/core/java/com/android/internal/widget/NumericTextView.java +++ b/core/java/com/android/internal/widget/NumericTextView.java @@ -16,7 +16,7 @@ package com.android.internal.widget; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.graphics.Rect; import android.util.AttributeSet; diff --git a/core/java/com/android/internal/widget/PointerLocationView.java b/core/java/com/android/internal/widget/PointerLocationView.java index 37046afaaa85..dc8d57ab709e 100644 --- a/core/java/com/android/internal/widget/PointerLocationView.java +++ b/core/java/com/android/internal/widget/PointerLocationView.java @@ -16,7 +16,7 @@ package com.android.internal.widget; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.graphics.Canvas; import android.graphics.Paint; diff --git a/core/java/com/android/internal/widget/PreferenceImageView.java b/core/java/com/android/internal/widget/PreferenceImageView.java index 02a0b8d436b9..43b6b5a169c5 100644 --- a/core/java/com/android/internal/widget/PreferenceImageView.java +++ b/core/java/com/android/internal/widget/PreferenceImageView.java @@ -16,7 +16,7 @@ package com.android.internal.widget; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.util.AttributeSet; import android.widget.ImageView; diff --git a/core/java/com/android/internal/widget/RebootEscrowListener.java b/core/java/com/android/internal/widget/RebootEscrowListener.java new file mode 100644 index 000000000000..165453200d8b --- /dev/null +++ b/core/java/com/android/internal/widget/RebootEscrowListener.java @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.widget; + +/** + * Private API to be notified about reboot escrow events. + * + * {@hide} + */ +public interface RebootEscrowListener { + /** + * Called when the preparation status has changed. When {@code prepared} is {@code true} the + * user has entered their lock screen knowledge factor (LSKF) and the HAL has confirmed that + * it is ready to retrieve the secret after a reboot. When {@code prepared} is {@code false} + * then those conditions are not true. + */ + void onPreparedForReboot(boolean prepared); +} diff --git a/core/java/com/android/internal/widget/RecyclerView.java b/core/java/com/android/internal/widget/RecyclerView.java index b66a7b44f05d..43a227a32346 100644 --- a/core/java/com/android/internal/widget/RecyclerView.java +++ b/core/java/com/android/internal/widget/RecyclerView.java @@ -20,7 +20,7 @@ import android.annotation.CallSuper; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.content.res.TypedArray; import android.database.Observable; diff --git a/core/java/com/android/internal/widget/ScrollBarUtils.java b/core/java/com/android/internal/widget/ScrollBarUtils.java index 982e3152fc7c..3e9d697a0ace 100644 --- a/core/java/com/android/internal/widget/ScrollBarUtils.java +++ b/core/java/com/android/internal/widget/ScrollBarUtils.java @@ -16,7 +16,7 @@ package com.android.internal.widget; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; public class ScrollBarUtils { diff --git a/core/java/com/android/internal/widget/ScrollingTabContainerView.java b/core/java/com/android/internal/widget/ScrollingTabContainerView.java index 5d48ab910439..aa0b0bbd4c19 100644 --- a/core/java/com/android/internal/widget/ScrollingTabContainerView.java +++ b/core/java/com/android/internal/widget/ScrollingTabContainerView.java @@ -15,13 +15,11 @@ */ package com.android.internal.widget; -import com.android.internal.view.ActionBarPolicy; - import android.animation.Animator; import android.animation.ObjectAnimator; import android.animation.TimeInterpolator; -import android.annotation.UnsupportedAppUsage; import android.app.ActionBar; +import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.content.res.Configuration; import android.graphics.drawable.Drawable; @@ -42,6 +40,8 @@ import android.widget.ListView; import android.widget.Spinner; import android.widget.TextView; +import com.android.internal.view.ActionBarPolicy; + /** * This widget implements the dynamic action bar tab behavior that can change * across different configurations or circumstances. diff --git a/core/java/com/android/internal/widget/SlidingTab.java b/core/java/com/android/internal/widget/SlidingTab.java index 4b5d62467af0..5e6f3a46de7d 100644 --- a/core/java/com/android/internal/widget/SlidingTab.java +++ b/core/java/com/android/internal/widget/SlidingTab.java @@ -16,7 +16,7 @@ package com.android.internal.widget; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.content.res.Resources; import android.content.res.TypedArray; @@ -34,12 +34,12 @@ import android.view.View; import android.view.ViewGroup; import android.view.animation.AlphaAnimation; import android.view.animation.Animation; +import android.view.animation.Animation.AnimationListener; import android.view.animation.LinearInterpolator; import android.view.animation.TranslateAnimation; -import android.view.animation.Animation.AnimationListener; import android.widget.ImageView; -import android.widget.TextView; import android.widget.ImageView.ScaleType; +import android.widget.TextView; import com.android.internal.R; diff --git a/core/java/com/android/internal/widget/TextViewInputDisabler.java b/core/java/com/android/internal/widget/TextViewInputDisabler.java index 8d8f0fe52d64..57806eb21dcf 100644 --- a/core/java/com/android/internal/widget/TextViewInputDisabler.java +++ b/core/java/com/android/internal/widget/TextViewInputDisabler.java @@ -16,7 +16,7 @@ package com.android.internal.widget; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.text.InputFilter; import android.text.Spanned; import android.widget.TextView; diff --git a/core/java/com/android/internal/widget/ViewPager.java b/core/java/com/android/internal/widget/ViewPager.java index 7d36b02d4157..c8a86d108134 100644 --- a/core/java/com/android/internal/widget/ViewPager.java +++ b/core/java/com/android/internal/widget/ViewPager.java @@ -18,7 +18,7 @@ package com.android.internal.widget; import android.annotation.DrawableRes; import android.annotation.NonNull; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.content.res.Resources; import android.content.res.TypedArray; diff --git a/core/java/com/android/server/ResettableTimeout.java b/core/java/com/android/server/ResettableTimeout.java index 64083f72aff5..511af941bf76 100644 --- a/core/java/com/android/server/ResettableTimeout.java +++ b/core/java/com/android/server/ResettableTimeout.java @@ -16,10 +16,9 @@ package com.android.server; -import android.os.SystemClock; - -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.os.ConditionVariable; +import android.os.SystemClock; /** * Utility class that you can call on with a timeout, and get called back diff --git a/core/java/com/android/server/net/BaseNetworkObserver.java b/core/java/com/android/server/net/BaseNetworkObserver.java index e1a10a5805f5..2a9c0b44b45e 100644 --- a/core/java/com/android/server/net/BaseNetworkObserver.java +++ b/core/java/com/android/server/net/BaseNetworkObserver.java @@ -16,7 +16,7 @@ package com.android.server.net; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.net.INetworkManagementEventObserver; import android.net.LinkAddress; import android.net.RouteInfo; diff --git a/core/java/com/android/server/net/NetlinkTracker.java b/core/java/com/android/server/net/NetlinkTracker.java index 647fb5b9d079..b57397f46a7e 100644 --- a/core/java/com/android/server/net/NetlinkTracker.java +++ b/core/java/com/android/server/net/NetlinkTracker.java @@ -16,7 +16,7 @@ package com.android.server.net; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.net.LinkAddress; import android.net.LinkProperties; import android.net.RouteInfo; diff --git a/core/java/com/google/android/collect/Lists.java b/core/java/com/google/android/collect/Lists.java index 8f6594aefb0a..585847da566c 100644 --- a/core/java/com/google/android/collect/Lists.java +++ b/core/java/com/google/android/collect/Lists.java @@ -16,7 +16,8 @@ package com.google.android.collect; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; + import java.util.ArrayList; import java.util.Collections; diff --git a/core/java/com/google/android/collect/Maps.java b/core/java/com/google/android/collect/Maps.java index 6ba33207631a..cd4c1280545e 100644 --- a/core/java/com/google/android/collect/Maps.java +++ b/core/java/com/google/android/collect/Maps.java @@ -16,7 +16,7 @@ package com.google.android.collect; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.util.ArrayMap; import java.util.HashMap; diff --git a/core/java/com/google/android/collect/Sets.java b/core/java/com/google/android/collect/Sets.java index 09b5e51ae2c6..c67a88a19080 100644 --- a/core/java/com/google/android/collect/Sets.java +++ b/core/java/com/google/android/collect/Sets.java @@ -16,7 +16,7 @@ package com.google.android.collect; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.util.ArraySet; import java.util.Collections; diff --git a/core/java/com/google/android/util/AbstractMessageParser.java b/core/java/com/google/android/util/AbstractMessageParser.java index f11e6b2342b7..0da7607cba6e 100644 --- a/core/java/com/google/android/util/AbstractMessageParser.java +++ b/core/java/com/google/android/util/AbstractMessageParser.java @@ -16,7 +16,7 @@ package com.google.android.util; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import java.util.ArrayList; import java.util.HashMap; diff --git a/core/java/org/apache/http/conn/ssl/AbstractVerifier.java b/core/java/org/apache/http/conn/ssl/AbstractVerifier.java index 36d6e22ca847..2848ad7796af 100644 --- a/core/java/org/apache/http/conn/ssl/AbstractVerifier.java +++ b/core/java/org/apache/http/conn/ssl/AbstractVerifier.java @@ -31,7 +31,7 @@ package org.apache.http.conn.ssl; -import java.util.regex.Pattern; +import android.compat.annotation.UnsupportedAppUsage; import java.io.IOException; import java.security.cert.Certificate; @@ -43,10 +43,10 @@ import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Locale; -import java.util.logging.Logger; import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.regex.Pattern; -import android.annotation.UnsupportedAppUsage; import javax.net.ssl.SSLException; import javax.net.ssl.SSLSession; import javax.net.ssl.SSLSocket; diff --git a/core/java/org/apache/http/conn/ssl/SSLSocketFactory.java b/core/java/org/apache/http/conn/ssl/SSLSocketFactory.java index b2e8b5e7af05..ffae7570ea79 100644 --- a/core/java/org/apache/http/conn/ssl/SSLSocketFactory.java +++ b/core/java/org/apache/http/conn/ssl/SSLSocketFactory.java @@ -31,20 +31,14 @@ package org.apache.http.conn.ssl; +import android.compat.annotation.UnsupportedAppUsage; +import android.os.Build; + import org.apache.http.conn.scheme.HostNameResolver; import org.apache.http.conn.scheme.LayeredSocketFactory; import org.apache.http.params.HttpConnectionParams; import org.apache.http.params.HttpParams; -import android.annotation.UnsupportedAppUsage; -import android.os.Build; -import javax.net.ssl.HttpsURLConnection; -import javax.net.ssl.KeyManager; -import javax.net.ssl.KeyManagerFactory; -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLSocket; -import javax.net.ssl.TrustManager; -import javax.net.ssl.TrustManagerFactory; import java.io.IOException; import java.net.InetAddress; import java.net.InetSocketAddress; @@ -57,6 +51,14 @@ import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.security.UnrecoverableKeyException; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.KeyManager; +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.TrustManager; +import javax.net.ssl.TrustManagerFactory; + /** * Layered socket factory for TLS/SSL connections, based on JSSE. *. diff --git a/core/proto/android/stats/devicepolicy/device_policy_enums.proto b/core/proto/android/stats/devicepolicy/device_policy_enums.proto index ee5144c0f91a..9054d5462da5 100644 --- a/core/proto/android/stats/devicepolicy/device_policy_enums.proto +++ b/core/proto/android/stats/devicepolicy/device_policy_enums.proto @@ -153,4 +153,5 @@ enum EventId { CROSS_PROFILE_APPS_START_ACTIVITY_AS_USER = 126; SET_AUTO_TIME = 127; SET_AUTO_TIME_ZONE = 128; + SET_PACKAGES_PROTECTED = 129; } diff --git a/graphics/java/android/graphics/BaseCanvas.java b/graphics/java/android/graphics/BaseCanvas.java index 6e7f286d19a7..bee8d5efc933 100644 --- a/graphics/java/android/graphics/BaseCanvas.java +++ b/graphics/java/android/graphics/BaseCanvas.java @@ -21,7 +21,7 @@ import android.annotation.ColorLong; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.Size; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.graphics.Canvas.VertexMode; import android.graphics.text.MeasuredText; import android.text.GraphicsOperations; diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java index d900a42b1e66..ac094ba5d5d2 100644 --- a/graphics/java/android/graphics/Bitmap.java +++ b/graphics/java/android/graphics/Bitmap.java @@ -21,8 +21,8 @@ import android.annotation.ColorInt; import android.annotation.ColorLong; import android.annotation.NonNull; import android.annotation.Nullable; -import android.annotation.UnsupportedAppUsage; import android.annotation.WorkerThread; +import android.compat.annotation.UnsupportedAppUsage; import android.content.res.ResourcesImpl; import android.hardware.HardwareBuffer; import android.os.Build; diff --git a/graphics/java/android/graphics/BitmapFactory.java b/graphics/java/android/graphics/BitmapFactory.java index 5623a8a49b35..bad487b47682 100644 --- a/graphics/java/android/graphics/BitmapFactory.java +++ b/graphics/java/android/graphics/BitmapFactory.java @@ -20,7 +20,7 @@ import static android.graphics.BitmapFactory.Options.validate; import android.annotation.NonNull; import android.annotation.Nullable; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.content.res.AssetManager; import android.content.res.Resources; import android.os.Trace; diff --git a/graphics/java/android/graphics/BitmapRegionDecoder.java b/graphics/java/android/graphics/BitmapRegionDecoder.java index 629d8c131b68..34eba97819aa 100644 --- a/graphics/java/android/graphics/BitmapRegionDecoder.java +++ b/graphics/java/android/graphics/BitmapRegionDecoder.java @@ -15,7 +15,7 @@ package android.graphics; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.content.res.AssetManager; import android.os.Build; diff --git a/graphics/java/android/graphics/BitmapShader.java b/graphics/java/android/graphics/BitmapShader.java index 198d1e7bc956..edf53c491311 100644 --- a/graphics/java/android/graphics/BitmapShader.java +++ b/graphics/java/android/graphics/BitmapShader.java @@ -17,7 +17,7 @@ package android.graphics; import android.annotation.NonNull; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; /** * Shader used to draw a bitmap as a texture. The bitmap can be repeated or diff --git a/graphics/java/android/graphics/Camera.java b/graphics/java/android/graphics/Camera.java index cbd4eadca30a..80a3740d2f4e 100644 --- a/graphics/java/android/graphics/Camera.java +++ b/graphics/java/android/graphics/Camera.java @@ -16,7 +16,7 @@ package android.graphics; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; /** * A camera instance can be used to compute 3D transformations and diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java index a815f20293c5..9a0ca3e4ad9b 100644 --- a/graphics/java/android/graphics/Canvas.java +++ b/graphics/java/android/graphics/Canvas.java @@ -22,7 +22,7 @@ import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.Size; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.graphics.text.MeasuredText; import android.os.Build; diff --git a/graphics/java/android/graphics/CanvasProperty.java b/graphics/java/android/graphics/CanvasProperty.java index 1275e0827580..4263772c1c2c 100644 --- a/graphics/java/android/graphics/CanvasProperty.java +++ b/graphics/java/android/graphics/CanvasProperty.java @@ -16,7 +16,8 @@ package android.graphics; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; + import com.android.internal.util.VirtualRefBasePtr; /** diff --git a/graphics/java/android/graphics/ColorMatrixColorFilter.java b/graphics/java/android/graphics/ColorMatrixColorFilter.java index 0f7980cc32e4..a8b18a9fcb1f 100644 --- a/graphics/java/android/graphics/ColorMatrixColorFilter.java +++ b/graphics/java/android/graphics/ColorMatrixColorFilter.java @@ -18,7 +18,7 @@ package android.graphics; import android.annotation.NonNull; import android.annotation.Nullable; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; /** * A color filter that transforms colors through a 4x5 color matrix. This filter diff --git a/graphics/java/android/graphics/FontFamily.java b/graphics/java/android/graphics/FontFamily.java index 5ad93f411393..ae90995573dc 100644 --- a/graphics/java/android/graphics/FontFamily.java +++ b/graphics/java/android/graphics/FontFamily.java @@ -17,7 +17,7 @@ package android.graphics; import android.annotation.Nullable; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.content.res.AssetManager; import android.graphics.fonts.FontVariationAxis; import android.text.TextUtils; diff --git a/graphics/java/android/graphics/FontListParser.java b/graphics/java/android/graphics/FontListParser.java index 21cc3757a40e..c146bbd4441b 100644 --- a/graphics/java/android/graphics/FontListParser.java +++ b/graphics/java/android/graphics/FontListParser.java @@ -16,7 +16,7 @@ package android.graphics; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.graphics.fonts.FontVariationAxis; import android.text.FontConfig; import android.util.Xml; diff --git a/graphics/java/android/graphics/GraphicBuffer.java b/graphics/java/android/graphics/GraphicBuffer.java index 3b1fc70397ea..99fa5eef7bbd 100644 --- a/graphics/java/android/graphics/GraphicBuffer.java +++ b/graphics/java/android/graphics/GraphicBuffer.java @@ -16,7 +16,7 @@ package android.graphics; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.os.Parcel; import android.os.Parcelable; diff --git a/graphics/java/android/graphics/ImageDecoder.java b/graphics/java/android/graphics/ImageDecoder.java index bcb313e1c227..83432c362672 100644 --- a/graphics/java/android/graphics/ImageDecoder.java +++ b/graphics/java/android/graphics/ImageDecoder.java @@ -28,8 +28,8 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.Px; import android.annotation.TestApi; -import android.annotation.UnsupportedAppUsage; import android.annotation.WorkerThread; +import android.compat.annotation.UnsupportedAppUsage; import android.content.ContentResolver; import android.content.res.AssetFileDescriptor; import android.content.res.AssetManager; diff --git a/graphics/java/android/graphics/LightingColorFilter.java b/graphics/java/android/graphics/LightingColorFilter.java index 62a890ff4f0b..221dfa192795 100644 --- a/graphics/java/android/graphics/LightingColorFilter.java +++ b/graphics/java/android/graphics/LightingColorFilter.java @@ -22,7 +22,7 @@ package android.graphics; import android.annotation.ColorInt; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; /** * A color filter that can be used to simulate simple lighting effects. diff --git a/graphics/java/android/graphics/LinearGradient.java b/graphics/java/android/graphics/LinearGradient.java index 12e63c09d76b..3f3ad967fe97 100644 --- a/graphics/java/android/graphics/LinearGradient.java +++ b/graphics/java/android/graphics/LinearGradient.java @@ -20,7 +20,7 @@ import android.annotation.ColorInt; import android.annotation.ColorLong; import android.annotation.NonNull; import android.annotation.Nullable; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; public class LinearGradient extends Shader { diff --git a/graphics/java/android/graphics/Matrix.java b/graphics/java/android/graphics/Matrix.java index 22b6401fdc2e..cf914c2c3eae 100644 --- a/graphics/java/android/graphics/Matrix.java +++ b/graphics/java/android/graphics/Matrix.java @@ -16,7 +16,7 @@ package android.graphics; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import dalvik.annotation.optimization.CriticalNative; import dalvik.annotation.optimization.FastNative; diff --git a/graphics/java/android/graphics/Movie.java b/graphics/java/android/graphics/Movie.java index 6f030ffac2df..4b3924f0d55f 100644 --- a/graphics/java/android/graphics/Movie.java +++ b/graphics/java/android/graphics/Movie.java @@ -16,7 +16,7 @@ package android.graphics; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.content.res.AssetManager; import android.os.Build; diff --git a/graphics/java/android/graphics/NinePatch.java b/graphics/java/android/graphics/NinePatch.java index c4c1eaceb4fc..ff3239348240 100644 --- a/graphics/java/android/graphics/NinePatch.java +++ b/graphics/java/android/graphics/NinePatch.java @@ -16,7 +16,7 @@ package android.graphics; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; /** * The NinePatch class permits drawing a bitmap in nine or more sections. diff --git a/graphics/java/android/graphics/Outline.java b/graphics/java/android/graphics/Outline.java index 1fc056c3652f..91a60c327bf0 100644 --- a/graphics/java/android/graphics/Outline.java +++ b/graphics/java/android/graphics/Outline.java @@ -19,7 +19,7 @@ package android.graphics; import android.annotation.FloatRange; import android.annotation.IntDef; import android.annotation.NonNull; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.graphics.drawable.Drawable; import java.lang.annotation.Retention; diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java index 109d8631284d..3b586242e5b1 100644 --- a/graphics/java/android/graphics/Paint.java +++ b/graphics/java/android/graphics/Paint.java @@ -24,7 +24,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.Px; import android.annotation.Size; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.graphics.fonts.FontVariationAxis; import android.os.Build; import android.os.LocaleList; diff --git a/graphics/java/android/graphics/Path.java b/graphics/java/android/graphics/Path.java index 7282d52d6e23..1362fd864d29 100644 --- a/graphics/java/android/graphics/Path.java +++ b/graphics/java/android/graphics/Path.java @@ -20,7 +20,7 @@ import android.annotation.FloatRange; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.Size; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import dalvik.annotation.optimization.CriticalNative; import dalvik.annotation.optimization.FastNative; diff --git a/graphics/java/android/graphics/Picture.java b/graphics/java/android/graphics/Picture.java index 8d12cbffc793..390d3d414346 100644 --- a/graphics/java/android/graphics/Picture.java +++ b/graphics/java/android/graphics/Picture.java @@ -17,7 +17,7 @@ package android.graphics; import android.annotation.NonNull; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import java.io.InputStream; import java.io.OutputStream; diff --git a/graphics/java/android/graphics/PorterDuff.java b/graphics/java/android/graphics/PorterDuff.java index bc1f66fdd5c0..1275cb9ca4f9 100644 --- a/graphics/java/android/graphics/PorterDuff.java +++ b/graphics/java/android/graphics/PorterDuff.java @@ -16,7 +16,7 @@ package android.graphics; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; /** * <p>This class contains the list of alpha compositing and blending modes diff --git a/graphics/java/android/graphics/PorterDuffColorFilter.java b/graphics/java/android/graphics/PorterDuffColorFilter.java index cc2d3a8969fc..50ecb62e7fcc 100644 --- a/graphics/java/android/graphics/PorterDuffColorFilter.java +++ b/graphics/java/android/graphics/PorterDuffColorFilter.java @@ -18,7 +18,7 @@ package android.graphics; import android.annotation.ColorInt; import android.annotation.NonNull; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; /** * A color filter that can be used to tint the source pixels using a single diff --git a/graphics/java/android/graphics/RadialGradient.java b/graphics/java/android/graphics/RadialGradient.java index acbe3da75247..96b7b9a78ba8 100644 --- a/graphics/java/android/graphics/RadialGradient.java +++ b/graphics/java/android/graphics/RadialGradient.java @@ -20,7 +20,7 @@ import android.annotation.ColorInt; import android.annotation.ColorLong; import android.annotation.NonNull; import android.annotation.Nullable; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; public class RadialGradient extends Shader { @UnsupportedAppUsage diff --git a/graphics/java/android/graphics/Rect.java b/graphics/java/android/graphics/Rect.java index 9e1946c557d2..081b851d1333 100644 --- a/graphics/java/android/graphics/Rect.java +++ b/graphics/java/android/graphics/Rect.java @@ -19,7 +19,7 @@ package android.graphics; import android.annotation.CheckResult; import android.annotation.NonNull; import android.annotation.Nullable; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; diff --git a/graphics/java/android/graphics/Region.java b/graphics/java/android/graphics/Region.java index ec7f7a05b685..d8d96413a93d 100644 --- a/graphics/java/android/graphics/Region.java +++ b/graphics/java/android/graphics/Region.java @@ -17,7 +17,7 @@ package android.graphics; import android.annotation.NonNull; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.os.Parcel; import android.os.Parcelable; import android.util.Pools.SynchronizedPool; diff --git a/graphics/java/android/graphics/Shader.java b/graphics/java/android/graphics/Shader.java index 3050d1dae5e4..5335aa4725ad 100644 --- a/graphics/java/android/graphics/Shader.java +++ b/graphics/java/android/graphics/Shader.java @@ -20,7 +20,7 @@ import android.annotation.ColorInt; import android.annotation.ColorLong; import android.annotation.NonNull; import android.annotation.Nullable; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import libcore.util.NativeAllocationRegistry; diff --git a/graphics/java/android/graphics/SurfaceTexture.java b/graphics/java/android/graphics/SurfaceTexture.java index 99f440d599cb..697daa8b7b70 100644 --- a/graphics/java/android/graphics/SurfaceTexture.java +++ b/graphics/java/android/graphics/SurfaceTexture.java @@ -17,7 +17,7 @@ package android.graphics; import android.annotation.Nullable; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.os.Handler; import android.os.Looper; import android.os.Message; diff --git a/graphics/java/android/graphics/SweepGradient.java b/graphics/java/android/graphics/SweepGradient.java index 667f45afe500..08520048b787 100644 --- a/graphics/java/android/graphics/SweepGradient.java +++ b/graphics/java/android/graphics/SweepGradient.java @@ -20,7 +20,7 @@ import android.annotation.ColorInt; import android.annotation.ColorLong; import android.annotation.NonNull; import android.annotation.Nullable; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; public class SweepGradient extends Shader { @UnsupportedAppUsage diff --git a/graphics/java/android/graphics/TableMaskFilter.java b/graphics/java/android/graphics/TableMaskFilter.java index d81c491e07e0..204f9705852a 100644 --- a/graphics/java/android/graphics/TableMaskFilter.java +++ b/graphics/java/android/graphics/TableMaskFilter.java @@ -16,7 +16,7 @@ package android.graphics; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; /** * @hide diff --git a/graphics/java/android/graphics/TemporaryBuffer.java b/graphics/java/android/graphics/TemporaryBuffer.java index 0ae2c703c21c..ef3f7f704e0d 100644 --- a/graphics/java/android/graphics/TemporaryBuffer.java +++ b/graphics/java/android/graphics/TemporaryBuffer.java @@ -16,7 +16,8 @@ package android.graphics; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; + import com.android.internal.util.ArrayUtils; /** diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java index 6d20ec32cdc4..a2dd9a8322b6 100644 --- a/graphics/java/android/graphics/Typeface.java +++ b/graphics/java/android/graphics/Typeface.java @@ -25,7 +25,7 @@ import android.annotation.IntDef; import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.content.res.AssetManager; import android.graphics.fonts.Font; import android.graphics.fonts.FontFamily; diff --git a/graphics/java/android/graphics/Xfermode.java b/graphics/java/android/graphics/Xfermode.java index 6f4adfde7ff9..e79fb76d806e 100644 --- a/graphics/java/android/graphics/Xfermode.java +++ b/graphics/java/android/graphics/Xfermode.java @@ -21,7 +21,7 @@ package android.graphics; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; /** * Xfermode is the base class for objects that are called to implement custom diff --git a/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java b/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java index 82f587086428..d8946009483c 100644 --- a/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java +++ b/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java @@ -19,7 +19,7 @@ package android.graphics.drawable; import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.content.res.AssetFileDescriptor; import android.content.res.Resources; import android.content.res.Resources.Theme; diff --git a/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java b/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java index b29fd4db5803..686f146e9c18 100644 --- a/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java +++ b/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java @@ -18,23 +18,23 @@ package android.graphics.drawable; import android.annotation.NonNull; import android.annotation.Nullable; -import android.annotation.UnsupportedAppUsage; -import android.graphics.Canvas; -import android.graphics.Rect; +import android.compat.annotation.UnsupportedAppUsage; import android.content.res.Resources; -import android.content.res.TypedArray; import android.content.res.Resources.Theme; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.Rect; +import android.os.SystemClock; import android.util.AttributeSet; import android.util.TypedValue; -import android.os.SystemClock; + +import com.android.internal.R; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import java.io.IOException; -import com.android.internal.R; - /** * @hide */ diff --git a/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java b/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java index 11a46c4ba9b9..06159d8a0558 100644 --- a/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java +++ b/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java @@ -20,7 +20,7 @@ import android.animation.ObjectAnimator; import android.animation.TimeInterpolator; import android.annotation.NonNull; import android.annotation.Nullable; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.content.res.Resources; import android.content.res.Resources.Theme; import android.content.res.TypedArray; diff --git a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java index 66947da9166f..1acf6c512fbd 100644 --- a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java +++ b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java @@ -25,9 +25,9 @@ import android.animation.TimeInterpolator; import android.animation.ValueAnimator; import android.annotation.NonNull; import android.annotation.Nullable; -import android.annotation.UnsupportedAppUsage; import android.app.ActivityThread; import android.app.Application; +import android.compat.annotation.UnsupportedAppUsage; import android.content.pm.ActivityInfo.Config; import android.content.res.ColorStateList; import android.content.res.Resources; diff --git a/graphics/java/android/graphics/drawable/AnimationDrawable.java b/graphics/java/android/graphics/drawable/AnimationDrawable.java index 57764c2cb693..8c3fa441cbb0 100644 --- a/graphics/java/android/graphics/drawable/AnimationDrawable.java +++ b/graphics/java/android/graphics/drawable/AnimationDrawable.java @@ -16,21 +16,21 @@ package android.graphics.drawable; -import com.android.internal.R; - -import java.io.IOException; - -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; - import android.annotation.NonNull; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.content.res.Resources; -import android.content.res.TypedArray; import android.content.res.Resources.Theme; +import android.content.res.TypedArray; import android.os.SystemClock; import android.util.AttributeSet; +import com.android.internal.R; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + +import java.io.IOException; + /** * An object used to create frame-by-frame animations, defined by a series of * Drawable objects, which can be used as a View object's background. diff --git a/graphics/java/android/graphics/drawable/BitmapDrawable.java b/graphics/java/android/graphics/drawable/BitmapDrawable.java index e4aa774fd434..4e768c9eddfb 100644 --- a/graphics/java/android/graphics/drawable/BitmapDrawable.java +++ b/graphics/java/android/graphics/drawable/BitmapDrawable.java @@ -17,7 +17,7 @@ package android.graphics.drawable; import android.annotation.NonNull; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.content.pm.ActivityInfo.Config; import android.content.res.ColorStateList; import android.content.res.Resources; diff --git a/graphics/java/android/graphics/drawable/ClipDrawable.java b/graphics/java/android/graphics/drawable/ClipDrawable.java index 31fdb025bbc5..69ed9b423d48 100644 --- a/graphics/java/android/graphics/drawable/ClipDrawable.java +++ b/graphics/java/android/graphics/drawable/ClipDrawable.java @@ -16,20 +16,22 @@ package android.graphics.drawable; -import com.android.internal.R; - -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; - import android.annotation.NonNull; import android.annotation.Nullable; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.content.res.Resources; -import android.content.res.TypedArray; import android.content.res.Resources.Theme; -import android.graphics.*; -import android.view.Gravity; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.PixelFormat; +import android.graphics.Rect; import android.util.AttributeSet; +import android.view.Gravity; + +import com.android.internal.R; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; import java.io.IOException; diff --git a/media/java/android/media/tv/TvTrackInfo.java b/media/java/android/media/tv/TvTrackInfo.java index ea00d6eff12e..ab7bbca1d01c 100644 --- a/media/java/android/media/tv/TvTrackInfo.java +++ b/media/java/android/media/tv/TvTrackInfo.java @@ -61,6 +61,7 @@ public final class TvTrackInfo implements Parcelable { private final boolean mEncrypted; private final int mAudioChannelCount; private final int mAudioSampleRate; + private final boolean mAudioDescription; private final int mVideoWidth; private final int mVideoHeight; private final float mVideoFrameRate; @@ -70,8 +71,8 @@ public final class TvTrackInfo implements Parcelable { private final Bundle mExtra; private TvTrackInfo(int type, String id, String language, CharSequence description, - boolean encrypted, int audioChannelCount, int audioSampleRate, int videoWidth, - int videoHeight, float videoFrameRate, float videoPixelAspectRatio, + boolean encrypted, int audioChannelCount, int audioSampleRate, boolean audioDescription, + int videoWidth, int videoHeight, float videoFrameRate, float videoPixelAspectRatio, byte videoActiveFormatDescription, Bundle extra) { mType = type; mId = id; @@ -80,6 +81,7 @@ public final class TvTrackInfo implements Parcelable { mEncrypted = encrypted; mAudioChannelCount = audioChannelCount; mAudioSampleRate = audioSampleRate; + mAudioDescription = audioDescription; mVideoWidth = videoWidth; mVideoHeight = videoHeight; mVideoFrameRate = videoFrameRate; @@ -96,6 +98,7 @@ public final class TvTrackInfo implements Parcelable { mEncrypted = in.readInt() != 0; mAudioChannelCount = in.readInt(); mAudioSampleRate = in.readInt(); + mAudioDescription = in.readInt() != 0; mVideoWidth = in.readInt(); mVideoHeight = in.readInt(); mVideoFrameRate = in.readFloat(); @@ -172,6 +175,23 @@ public final class TvTrackInfo implements Parcelable { } /** + * Returns {@code true} if the track is an audio description intended for people with visual + * impairment, {@code false} otherwise. Valid only for {@link #TYPE_AUDIO} tracks. + * + * <p>For example of broadcast, audio description information may be referred to broadcast + * standard (e.g. ISO 639 Language Descriptor of ISO/IEC 13818-1, Supplementary Audio Language + * Descriptor, AC-3 Descriptor, Enhanced AC-3 Descriptor, AAC Descriptor of ETSI EN 300 468). + * + * @throws IllegalStateException if not called on an audio track + */ + public boolean isAudioDescription() { + if (mType != TYPE_AUDIO) { + throw new IllegalStateException("Not an audio track"); + } + return mAudioDescription; + } + + /** * Returns the width of the video, in the unit of pixels. Valid only for {@link #TYPE_VIDEO} * tracks. * @@ -266,6 +286,7 @@ public final class TvTrackInfo implements Parcelable { dest.writeInt(mEncrypted ? 1 : 0); dest.writeInt(mAudioChannelCount); dest.writeInt(mAudioSampleRate); + dest.writeInt(mAudioDescription ? 1 : 0); dest.writeInt(mVideoWidth); dest.writeInt(mVideoHeight); dest.writeFloat(mVideoFrameRate); @@ -296,7 +317,8 @@ public final class TvTrackInfo implements Parcelable { switch (mType) { case TYPE_AUDIO: return mAudioChannelCount == obj.mAudioChannelCount - && mAudioSampleRate == obj.mAudioSampleRate; + && mAudioSampleRate == obj.mAudioSampleRate + && mAudioDescription == obj.mAudioDescription; case TYPE_VIDEO: return mVideoWidth == obj.mVideoWidth @@ -338,6 +360,7 @@ public final class TvTrackInfo implements Parcelable { private boolean mEncrypted; private int mAudioChannelCount; private int mAudioSampleRate; + private boolean mAudioDescription; private int mVideoWidth; private int mVideoHeight; private float mVideoFrameRate; @@ -430,6 +453,27 @@ public final class TvTrackInfo implements Parcelable { } /** + * Sets the audio description attribute of the audio. Valid only for {@link #TYPE_AUDIO} + * tracks. + * + * <p>For example of broadcast, audio description information may be referred to broadcast + * standard (e.g. ISO 639 Language Descriptor of ISO/IEC 13818-1, Supplementary Audio + * Language Descriptor, AC-3 Descriptor, Enhanced AC-3 Descriptor, AAC Descriptor of ETSI EN + * 300 468). + * + * @param audioDescription The audio description attribute of the audio. + * @throws IllegalStateException if not called on an audio track + */ + @NonNull + public Builder setAudioDescription(boolean audioDescription) { + if (mType != TYPE_AUDIO) { + throw new IllegalStateException("Not an audio track"); + } + mAudioDescription = audioDescription; + return this; + } + + /** * Sets the width of the video, in the unit of pixels. Valid only for {@link #TYPE_VIDEO} * tracks. * @@ -531,8 +575,9 @@ public final class TvTrackInfo implements Parcelable { */ public TvTrackInfo build() { return new TvTrackInfo(mType, mId, mLanguage, mDescription, mEncrypted, - mAudioChannelCount, mAudioSampleRate, mVideoWidth, mVideoHeight, - mVideoFrameRate, mVideoPixelAspectRatio, mVideoActiveFormatDescription, mExtra); + mAudioChannelCount, mAudioSampleRate, mAudioDescription, mVideoWidth, + mVideoHeight, mVideoFrameRate, mVideoPixelAspectRatio, + mVideoActiveFormatDescription, mExtra); } } } diff --git a/media/java/android/media/tv/tuner/FrontendSettings.java b/media/java/android/media/tv/tuner/FrontendSettings.java index 531e21038bfc..e2e9910f53ee 100644 --- a/media/java/android/media/tv/tuner/FrontendSettings.java +++ b/media/java/android/media/tv/tuner/FrontendSettings.java @@ -19,8 +19,6 @@ package android.media.tv.tuner; import android.annotation.SystemApi; import android.media.tv.tuner.TunerConstants.FrontendSettingsType; -import java.util.List; - /** * Frontend settings for tune and scan operations. * @hide @@ -29,7 +27,8 @@ import java.util.List; public abstract class FrontendSettings { private final int mFrequency; - FrontendSettings(int frequency) { + /** @hide */ + public FrontendSettings(int frequency) { mFrequency = frequency; } @@ -48,282 +47,4 @@ public abstract class FrontendSettings { return mFrequency; } - // TODO: use hal constants for enum fields - // TODO: javaDoc - // TODO: add builders and getters for other settings type - - /** - * Frontend settings for analog. - * @hide - */ - public static class FrontendAnalogSettings extends FrontendSettings { - private int mAnalogType; - private int mSifStandard; - - @Override - public int getType() { - return TunerConstants.FRONTEND_TYPE_ANALOG; - } - - public int getAnalogType() { - return mAnalogType; - } - - public int getSifStandard() { - return mSifStandard; - } - - /** - * Creates a new builder object. - */ - public static Builder newBuilder() { - return new Builder(); - } - - private FrontendAnalogSettings(int frequency, int analogType, int sifStandard) { - super(frequency); - mAnalogType = analogType; - mSifStandard = sifStandard; - } - - /** - * Builder for FrontendAnalogSettings. - */ - public static class Builder { - private int mFrequency; - private int mAnalogType; - private int mSifStandard; - - private Builder() {} - - /** - * Sets frequency. - */ - public Builder setFrequency(int frequency) { - mFrequency = frequency; - return this; - } - - /** - * Sets analog type. - */ - public Builder setAnalogType(int analogType) { - mAnalogType = analogType; - return this; - } - - /** - * Sets sif standard. - */ - public Builder setSifStandard(int sifStandard) { - mSifStandard = sifStandard; - return this; - } - - /** - * Builds a FrontendAnalogSettings instance. - */ - public FrontendAnalogSettings build() { - return new FrontendAnalogSettings(mFrequency, mAnalogType, mSifStandard); - } - } - } - - /** - * Frontend settings for ATSC. - * @hide - */ - public static class FrontendAtscSettings extends FrontendSettings { - public int modulation; - - FrontendAtscSettings(int frequency) { - super(frequency); - } - - @Override - public int getType() { - return TunerConstants.FRONTEND_TYPE_ATSC; - } - } - - /** - * Frontend settings for ATSC-3. - * @hide - */ - public static class FrontendAtsc3Settings extends FrontendSettings { - public int bandwidth; - public byte demodOutputFormat; - public List<FrontendAtsc3PlpSettings> plpSettings; - - FrontendAtsc3Settings(int frequency) { - super(frequency); - } - - @Override - public int getType() { - return TunerConstants.FRONTEND_TYPE_ATSC3; - } - } - - /** - * Frontend settings for DVBS. - * @hide - */ - public static class FrontendDvbsSettings extends FrontendSettings { - public int modulation; - public FrontendDvbsCodeRate coderate; - public int symbolRate; - public int rolloff; - public int pilot; - public int inputStreamId; - public byte standard; - - FrontendDvbsSettings(int frequency) { - super(frequency); - } - - @Override - public int getType() { - return TunerConstants.FRONTEND_TYPE_DVBS; - } - } - - /** - * Frontend settings for DVBC. - * @hide - */ - public static class FrontendDvbcSettings extends FrontendSettings { - public int modulation; - public long fec; - public int symbolRate; - public int outerFec; - public byte annex; - public int spectralInversion; - - FrontendDvbcSettings(int frequency) { - super(frequency); - } - - @Override - public int getType() { - return TunerConstants.FRONTEND_TYPE_DVBC; - } - } - - /** - * Frontend settings for DVBT. - * @hide - */ - public static class FrontendDvbtSettings extends FrontendSettings { - public int transmissionMode; - public int bandwidth; - public int constellation; - public int hierarchy; - public int hpCoderate; - public int lpCoderate; - public int guardInterval; - public boolean isHighPriority; - public byte standard; - public boolean isMiso; - public int plpMode; - public byte plpId; - public byte plpGroupId; - - FrontendDvbtSettings(int frequency) { - super(frequency); - } - - @Override - public int getType() { - return TunerConstants.FRONTEND_TYPE_DVBT; - } - } - - /** - * Frontend settings for ISDBS. - * @hide - */ - public static class FrontendIsdbsSettings extends FrontendSettings { - public int streamId; - public int streamIdType; - public int modulation; - public int coderate; - public int symbolRate; - public int rolloff; - - FrontendIsdbsSettings(int frequency) { - super(frequency); - } - - @Override - public int getType() { - return TunerConstants.FRONTEND_TYPE_ISDBS; - } - } - - /** - * Frontend settings for ISDBS-3. - * @hide - */ - public static class FrontendIsdbs3Settings extends FrontendSettings { - public int streamId; - public int streamIdType; - public int modulation; - public int coderate; - public int symbolRate; - public int rolloff; - - FrontendIsdbs3Settings(int frequency) { - super(frequency); - } - - @Override - public int getType() { - return TunerConstants.FRONTEND_TYPE_ISDBS3; - } - } - - /** - * Frontend settings for ISDBT. - * @hide - */ - public static class FrontendIsdbtSettings extends FrontendSettings { - public int modulation; - public int bandwidth; - public int coderate; - public int guardInterval; - public int serviceAreaId; - - FrontendIsdbtSettings(int frequency) { - super(frequency); - } - - @Override - public int getType() { - return TunerConstants.FRONTEND_TYPE_ISDBT; - } - } - - /** - * PLP settings for ATSC-3. - * @hide - */ - public static class FrontendAtsc3PlpSettings { - public byte plpId; - public int modulation; - public int interleaveMode; - public int codeRate; - public int fec; - } - - /** - * Code rate for DVBS. - * @hide - */ - public static class FrontendDvbsCodeRate { - public long fec; - public boolean isLinear; - public boolean isShortFrames; - public int bitsPer1000Symbol; - } } diff --git a/media/java/android/media/tv/tuner/Tuner.java b/media/java/android/media/tv/tuner/Tuner.java index 914dd83ddbaf..43f9a8973e80 100644 --- a/media/java/android/media/tv/tuner/Tuner.java +++ b/media/java/android/media/tv/tuner/Tuner.java @@ -33,6 +33,8 @@ import android.media.tv.tuner.TunerConstants.LnbVoltage; import android.media.tv.tuner.TunerConstants.Result; import android.media.tv.tuner.filter.FilterEvent; import android.media.tv.tuner.frontend.FrontendCallback; +import android.media.tv.tuner.frontend.FrontendInfo; +import android.media.tv.tuner.frontend.FrontendStatus; import android.os.Handler; import android.os.Looper; import android.os.Message; diff --git a/media/java/android/media/tv/tuner/filter/MediaEvent.java b/media/java/android/media/tv/tuner/filter/MediaEvent.java index 5e45350950b6..7703248535e5 100644 --- a/media/java/android/media/tv/tuner/filter/MediaEvent.java +++ b/media/java/android/media/tv/tuner/filter/MediaEvent.java @@ -22,7 +22,7 @@ import android.os.NativeHandle; * Media event. * @hide */ -public class MediaEvent { +public class MediaEvent extends FilterEvent { private int mStreamId; private boolean mIsPtsPresent; private long mPts; diff --git a/media/java/android/media/tv/tuner/frontend/AnalogFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/AnalogFrontendSettings.java new file mode 100644 index 000000000000..16308ced2300 --- /dev/null +++ b/media/java/android/media/tv/tuner/frontend/AnalogFrontendSettings.java @@ -0,0 +1,97 @@ +/* + * Copyright 2019 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.media.tv.tuner.frontend; + +import android.media.tv.tuner.FrontendSettings; +import android.media.tv.tuner.TunerConstants; + +/** + * Frontend settings for analog. + * @hide + */ +public class AnalogFrontendSettings extends FrontendSettings { + private int mAnalogType; + private int mSifStandard; + + @Override + public int getType() { + return TunerConstants.FRONTEND_TYPE_ANALOG; + } + + public int getAnalogType() { + return mAnalogType; + } + + public int getSifStandard() { + return mSifStandard; + } + + /** + * Creates a new builder object. + */ + public static Builder newBuilder() { + return new Builder(); + } + + private AnalogFrontendSettings(int frequency, int analogType, int sifStandard) { + super(frequency); + mAnalogType = analogType; + mSifStandard = sifStandard; + } + + /** + * Builder for FrontendAnalogSettings. + */ + public static class Builder { + private int mFrequency; + private int mAnalogType; + private int mSifStandard; + + private Builder() {} + + /** + * Sets frequency. + */ + public Builder setFrequency(int frequency) { + mFrequency = frequency; + return this; + } + + /** + * Sets analog type. + */ + public Builder setAnalogType(int analogType) { + mAnalogType = analogType; + return this; + } + + /** + * Sets sif standard. + */ + public Builder setSifStandard(int sifStandard) { + mSifStandard = sifStandard; + return this; + } + + /** + * Builds a FrontendAnalogSettings instance. + */ + public AnalogFrontendSettings build() { + return new AnalogFrontendSettings(mFrequency, mAnalogType, mSifStandard); + } + } +} diff --git a/media/java/android/media/tv/tuner/frontend/Atsc3FrontendSettings.java b/media/java/android/media/tv/tuner/frontend/Atsc3FrontendSettings.java new file mode 100644 index 000000000000..bce8a640c7f2 --- /dev/null +++ b/media/java/android/media/tv/tuner/frontend/Atsc3FrontendSettings.java @@ -0,0 +1,42 @@ +/* + * Copyright 2019 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.media.tv.tuner.frontend; + + +import android.media.tv.tuner.FrontendSettings; +import android.media.tv.tuner.TunerConstants; + +import java.util.List; + +/** + * Frontend settings for ATSC-3. + * @hide + */ +public class Atsc3FrontendSettings extends FrontendSettings { + public int bandwidth; + public byte demodOutputFormat; + public List<Atsc3PlpSettings> plpSettings; + + Atsc3FrontendSettings(int frequency) { + super(frequency); + } + + @Override + public int getType() { + return TunerConstants.FRONTEND_TYPE_ATSC3; + } +} diff --git a/media/java/android/media/tv/tuner/frontend/Atsc3PlpSettings.java b/media/java/android/media/tv/tuner/frontend/Atsc3PlpSettings.java new file mode 100644 index 000000000000..61c6fec154a8 --- /dev/null +++ b/media/java/android/media/tv/tuner/frontend/Atsc3PlpSettings.java @@ -0,0 +1,29 @@ +/* + * Copyright 2019 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.media.tv.tuner.frontend; + +/** + * PLP settings for ATSC-3. + * @hide + */ +public class Atsc3PlpSettings { + public byte plpId; + public int modulation; + public int interleaveMode; + public int codeRate; + public int fec; +} diff --git a/media/java/android/media/tv/tuner/frontend/AtscFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/AtscFrontendSettings.java new file mode 100644 index 000000000000..14c5cdd112e1 --- /dev/null +++ b/media/java/android/media/tv/tuner/frontend/AtscFrontendSettings.java @@ -0,0 +1,37 @@ +/* + * Copyright 2019 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.media.tv.tuner.frontend; + +import android.media.tv.tuner.FrontendSettings; +import android.media.tv.tuner.TunerConstants; + +/** + * Frontend settings for ATSC. + * @hide + */ +public class AtscFrontendSettings extends FrontendSettings { + public int modulation; + + AtscFrontendSettings(int frequency) { + super(frequency); + } + + @Override + public int getType() { + return TunerConstants.FRONTEND_TYPE_ATSC; + } +} diff --git a/media/java/android/media/tv/tuner/frontend/DvbcFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/DvbcFrontendSettings.java new file mode 100644 index 000000000000..07e49ff24de1 --- /dev/null +++ b/media/java/android/media/tv/tuner/frontend/DvbcFrontendSettings.java @@ -0,0 +1,42 @@ +/* + * Copyright 2019 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.media.tv.tuner.frontend; + +import android.media.tv.tuner.FrontendSettings; +import android.media.tv.tuner.TunerConstants; + +/** + * Frontend settings for DVBC. + * @hide + */ +public class DvbcFrontendSettings extends FrontendSettings { + public int modulation; + public long fec; + public int symbolRate; + public int outerFec; + public byte annex; + public int spectralInversion; + + DvbcFrontendSettings(int frequency) { + super(frequency); + } + + @Override + public int getType() { + return TunerConstants.FRONTEND_TYPE_DVBC; + } +} diff --git a/media/java/android/media/tv/tuner/frontend/DvbsCodeRate.java b/media/java/android/media/tv/tuner/frontend/DvbsCodeRate.java new file mode 100644 index 000000000000..bfa439154172 --- /dev/null +++ b/media/java/android/media/tv/tuner/frontend/DvbsCodeRate.java @@ -0,0 +1,28 @@ +/* + * Copyright 2019 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.media.tv.tuner.frontend; + +/** + * Code rate for DVBS. + * @hide + */ +public class DvbsCodeRate { + public long fec; + public boolean isLinear; + public boolean isShortFrames; + public int bitsPer1000Symbol; +} diff --git a/media/java/android/media/tv/tuner/frontend/DvbsFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/DvbsFrontendSettings.java new file mode 100644 index 000000000000..23c0a7b15e52 --- /dev/null +++ b/media/java/android/media/tv/tuner/frontend/DvbsFrontendSettings.java @@ -0,0 +1,43 @@ +/* + * Copyright 2019 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.media.tv.tuner.frontend; + +import android.media.tv.tuner.FrontendSettings; +import android.media.tv.tuner.TunerConstants; + +/** + * Frontend settings for DVBS. + * @hide + */ +public class DvbsFrontendSettings extends FrontendSettings { + public int modulation; + public DvbsCodeRate coderate; + public int symbolRate; + public int rolloff; + public int pilot; + public int inputStreamId; + public byte standard; + + DvbsFrontendSettings(int frequency) { + super(frequency); + } + + @Override + public int getType() { + return TunerConstants.FRONTEND_TYPE_DVBS; + } +} diff --git a/media/java/android/media/tv/tuner/frontend/DvbtFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/DvbtFrontendSettings.java new file mode 100644 index 000000000000..eec00f3fab80 --- /dev/null +++ b/media/java/android/media/tv/tuner/frontend/DvbtFrontendSettings.java @@ -0,0 +1,50 @@ +/* + * Copyright 2019 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.media.tv.tuner.frontend; + + +import android.media.tv.tuner.FrontendSettings; +import android.media.tv.tuner.TunerConstants; + +/** + * Frontend settings for DVBT. + * @hide + */ +public class DvbtFrontendSettings extends FrontendSettings { + public int transmissionMode; + public int bandwidth; + public int constellation; + public int hierarchy; + public int hpCoderate; + public int lpCoderate; + public int guardInterval; + public boolean isHighPriority; + public byte standard; + public boolean isMiso; + public int plpMode; + public byte plpId; + public byte plpGroupId; + + DvbtFrontendSettings(int frequency) { + super(frequency); + } + + @Override + public int getType() { + return TunerConstants.FRONTEND_TYPE_DVBT; + } +} diff --git a/media/java/android/media/tv/tuner/FrontendInfo.java b/media/java/android/media/tv/tuner/frontend/FrontendInfo.java index 2ab100dc3b08..ef6c029fe626 100644 --- a/media/java/android/media/tv/tuner/FrontendInfo.java +++ b/media/java/android/media/tv/tuner/frontend/FrontendInfo.java @@ -14,8 +14,9 @@ * limitations under the License. */ -package android.media.tv.tuner; +package android.media.tv.tuner.frontend; +import android.media.tv.tuner.FrontendCapabilities; import android.media.tv.tuner.TunerConstants.FrontendType; /** diff --git a/media/java/android/media/tv/tuner/FrontendStatus.java b/media/java/android/media/tv/tuner/frontend/FrontendStatus.java index f8b2d128d657..89ec536a1d6c 100644 --- a/media/java/android/media/tv/tuner/FrontendStatus.java +++ b/media/java/android/media/tv/tuner/frontend/FrontendStatus.java @@ -14,8 +14,9 @@ * limitations under the License. */ -package android.media.tv.tuner; +package android.media.tv.tuner.frontend; +import android.media.tv.tuner.TunerConstants; import android.media.tv.tuner.TunerConstants.FrontendDvbcSpectralInversion; import android.media.tv.tuner.TunerConstants.FrontendDvbtHierarchy; import android.media.tv.tuner.TunerConstants.FrontendInnerFec; diff --git a/media/java/android/media/tv/tuner/frontend/Isdbs3FrontendSettings.java b/media/java/android/media/tv/tuner/frontend/Isdbs3FrontendSettings.java new file mode 100644 index 000000000000..736d0b199d29 --- /dev/null +++ b/media/java/android/media/tv/tuner/frontend/Isdbs3FrontendSettings.java @@ -0,0 +1,42 @@ +/* + * Copyright 2019 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.media.tv.tuner.frontend; + +import android.media.tv.tuner.FrontendSettings; +import android.media.tv.tuner.TunerConstants; + +/** + * Frontend settings for ISDBS-3. + * @hide + */ +public class Isdbs3FrontendSettings extends FrontendSettings { + public int streamId; + public int streamIdType; + public int modulation; + public int coderate; + public int symbolRate; + public int rolloff; + + Isdbs3FrontendSettings(int frequency) { + super(frequency); + } + + @Override + public int getType() { + return TunerConstants.FRONTEND_TYPE_ISDBS3; + } +} diff --git a/media/java/android/media/tv/tuner/frontend/IsdbsFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/IsdbsFrontendSettings.java new file mode 100644 index 000000000000..7fd5da78c600 --- /dev/null +++ b/media/java/android/media/tv/tuner/frontend/IsdbsFrontendSettings.java @@ -0,0 +1,42 @@ +/* + * Copyright 2019 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.media.tv.tuner.frontend; + +import android.media.tv.tuner.FrontendSettings; +import android.media.tv.tuner.TunerConstants; + +/** + * Frontend settings for ISDBS. + * @hide + */ +public class IsdbsFrontendSettings extends FrontendSettings { + public int streamId; + public int streamIdType; + public int modulation; + public int coderate; + public int symbolRate; + public int rolloff; + + IsdbsFrontendSettings(int frequency) { + super(frequency); + } + + @Override + public int getType() { + return TunerConstants.FRONTEND_TYPE_ISDBS; + } +} diff --git a/media/java/android/media/tv/tuner/frontend/IsdbtFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/IsdbtFrontendSettings.java new file mode 100644 index 000000000000..3f83267fe5b4 --- /dev/null +++ b/media/java/android/media/tv/tuner/frontend/IsdbtFrontendSettings.java @@ -0,0 +1,42 @@ +/* + * Copyright 2019 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.media.tv.tuner.frontend; + + +import android.media.tv.tuner.FrontendSettings; +import android.media.tv.tuner.TunerConstants; + +/** + * Frontend settings for ISDBT. + * @hide + */ +public class IsdbtFrontendSettings extends FrontendSettings { + public int modulation; + public int bandwidth; + public int coderate; + public int guardInterval; + public int serviceAreaId; + + IsdbtFrontendSettings(int frequency) { + super(frequency); + } + + @Override + public int getType() { + return TunerConstants.FRONTEND_TYPE_ISDBT; + } +} diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java index 9e49826f70c3..c2ce84023869 100644 --- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java +++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java @@ -262,10 +262,11 @@ public class DynamicSystemInstallationService extends Service return; } + stopForeground(true); mJustCancelledByUser = true; if (mInstallTask.cancel(false)) { - // Will cleanup and post status in onResult() + // Will stopSelf() in onResult() Log.d(TAG, "Cancel request filed successfully"); } else { Log.e(TAG, "Trying to cancel installation while it's already completed."); diff --git a/packages/SystemUI/res-keyguard/values/strings.xml b/packages/SystemUI/res-keyguard/values/strings.xml index f7e9fedd5f66..4d184d5758d3 100644 --- a/packages/SystemUI/res-keyguard/values/strings.xml +++ b/packages/SystemUI/res-keyguard/values/strings.xml @@ -240,6 +240,15 @@ <!-- Description of airplane mode --> <string name="airplane_mode">Airplane mode</string> + <!-- An explanation text that the PIN needs to be entered to prepare for an operating system update. [CHAR LIMIT=80] --> + <string name="kg_prompt_reason_prepare_for_update_pin">PIN required to prepare for update</string> + + <!-- An explanation text that the pattern needs to be entered to prepare for an operating system update. [CHAR LIMIT=80] --> + <string name="kg_prompt_reason_prepare_for_update_pattern">Pattern required to prepare for update</string> + + <!-- An explanation text that the password needs to be entered to prepare for an operating system update. [CHAR LIMIT=80] --> + <string name="kg_prompt_reason_prepare_for_update_password">Password required to prepare for update</string> + <!-- An explanation text that the pattern needs to be solved since the device has just been restarted. [CHAR LIMIT=80] --> <string name="kg_prompt_reason_restart_pattern">Pattern required after device restarts</string> diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java index 2c8f23889a17..ed1cd8191092 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java @@ -168,8 +168,9 @@ public class KeyguardHostView extends FrameLayout implements SecurityCallback { * * @param reason a flag indicating which string should be shown, see * {@link KeyguardSecurityView#PROMPT_REASON_NONE}, - * {@link KeyguardSecurityView#PROMPT_REASON_RESTART} and - * {@link KeyguardSecurityView#PROMPT_REASON_TIMEOUT}. + * {@link KeyguardSecurityView#PROMPT_REASON_RESTART}, + * {@link KeyguardSecurityView#PROMPT_REASON_TIMEOUT}, and + * {@link KeyguardSecurityView#PROMPT_REASON_PREPARE_FOR_UPDATE}. */ public void showPromptReason(int reason) { mSecurityContainer.showPromptReason(reason); diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java index f8f3dc8d6ecd..718bcf16c832 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java @@ -137,6 +137,8 @@ public class KeyguardPasswordView extends KeyguardAbsKeyInputView return R.string.kg_prompt_reason_device_admin; case PROMPT_REASON_USER_REQUEST: return R.string.kg_prompt_reason_user_request; + case PROMPT_REASON_PREPARE_FOR_UPDATE: + return R.string.kg_prompt_reason_prepare_for_update_password; case PROMPT_REASON_NONE: return 0; default: diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java index 9eb168a7b567..48c6bd114d4a 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java @@ -438,6 +438,10 @@ public class KeyguardPatternView extends LinearLayout implements KeyguardSecurit case PROMPT_REASON_USER_REQUEST: mSecurityMessageDisplay.setMessage(R.string.kg_prompt_reason_user_request); break; + case PROMPT_REASON_PREPARE_FOR_UPDATE: + mSecurityMessageDisplay.setMessage( + R.string.kg_prompt_reason_prepare_for_update_pattern); + break; case PROMPT_REASON_NONE: break; default: diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java index c67deccb1f62..6d865ab525f3 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java @@ -116,6 +116,8 @@ public abstract class KeyguardPinBasedInputView extends KeyguardAbsKeyInputView return R.string.kg_prompt_reason_device_admin; case PROMPT_REASON_USER_REQUEST: return R.string.kg_prompt_reason_user_request; + case PROMPT_REASON_PREPARE_FOR_UPDATE: + return R.string.kg_prompt_reason_prepare_for_update_pin; case PROMPT_REASON_NONE: return 0; default: diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityView.java index e10819473dea..09d4d5fcbde9 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityView.java @@ -51,6 +51,11 @@ public interface KeyguardSecurityView { */ int PROMPT_REASON_AFTER_LOCKOUT = 5; + /*** + * Strong auth is require to prepare for an unattended update. + */ + int PROMPT_REASON_PREPARE_FOR_UPDATE = 6; + /** * Interface back to keyguard to tell it when security * @param callback diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java index c1934c609f5a..e13c3e087893 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java @@ -22,6 +22,7 @@ import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.SOM import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW; import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT; import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_TIMEOUT; +import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_FOR_UNATTENDED_UPDATE; import static com.android.systemui.DejankUtils.whitelistIpcs; import android.app.ActivityManager; @@ -670,6 +671,8 @@ public class KeyguardViewMediator extends SystemUI { return KeyguardSecurityView.PROMPT_REASON_USER_REQUEST; } else if (any && (strongAuth & STRONG_AUTH_REQUIRED_AFTER_LOCKOUT) != 0) { return KeyguardSecurityView.PROMPT_REASON_AFTER_LOCKOUT; + } else if (any && (strongAuth & STRONG_AUTH_REQUIRED_FOR_UNATTENDED_UPDATE) != 0) { + return KeyguardSecurityView.PROMPT_REASON_PREPARE_FOR_UPDATE; } return KeyguardSecurityView.PROMPT_REASON_NONE; } diff --git a/packages/Tethering/jarjar-rules.txt b/packages/Tethering/jarjar-rules.txt index dd9eab74e851..d93531bac58e 100644 --- a/packages/Tethering/jarjar-rules.txt +++ b/packages/Tethering/jarjar-rules.txt @@ -13,3 +13,5 @@ rule com.android.internal.util.State* com.android.networkstack.tethering.util.St rule com.android.internal.util.StateMachine* com.android.networkstack.tethering.util.StateMachine@1 rule android.net.LocalLog* com.android.networkstack.tethering.LocalLog@1 + +rule android.net.shared.Inet4AddressUtils* com.android.networkstack.tethering.shared.Inet4AddressUtils@1 diff --git a/packages/Tethering/src/android/net/dhcp/DhcpServingParamsParcelExt.java b/packages/Tethering/src/android/net/dhcp/DhcpServingParamsParcelExt.java index 1fe2328f1cdb..d6bc063210b3 100644 --- a/packages/Tethering/src/android/net/dhcp/DhcpServingParamsParcelExt.java +++ b/packages/Tethering/src/android/net/dhcp/DhcpServingParamsParcelExt.java @@ -20,11 +20,11 @@ import static android.net.shared.Inet4AddressUtils.inet4AddressToIntHTH; import android.annotation.NonNull; import android.net.LinkAddress; - -import com.google.android.collect.Sets; +import android.util.ArraySet; import java.net.Inet4Address; import java.util.Collection; +import java.util.Collections; import java.util.Set; /** @@ -68,7 +68,7 @@ public class DhcpServingParamsParcelExt extends DhcpServingParamsParcel { * but it must always be set explicitly. */ public DhcpServingParamsParcelExt setDefaultRouters(@NonNull Inet4Address... defaultRouters) { - return setDefaultRouters(Sets.newArraySet(defaultRouters)); + return setDefaultRouters(newArraySet(defaultRouters)); } /** @@ -96,7 +96,7 @@ public class DhcpServingParamsParcelExt extends DhcpServingParamsParcel { * <p>This may be an empty list of servers, but it must always be set explicitly. */ public DhcpServingParamsParcelExt setDnsServers(@NonNull Inet4Address... dnsServers) { - return setDnsServers(Sets.newArraySet(dnsServers)); + return setDnsServers(newArraySet(dnsServers)); } /** @@ -126,7 +126,7 @@ public class DhcpServingParamsParcelExt extends DhcpServingParamsParcel { * and do not need to be set here. */ public DhcpServingParamsParcelExt setExcludedAddrs(@NonNull Inet4Address... excludedAddrs) { - return setExcludedAddrs(Sets.newArraySet(excludedAddrs)); + return setExcludedAddrs(newArraySet(excludedAddrs)); } /** @@ -169,4 +169,10 @@ public class DhcpServingParamsParcelExt extends DhcpServingParamsParcel { } return res; } + + private static ArraySet<Inet4Address> newArraySet(Inet4Address... addrs) { + ArraySet<Inet4Address> addrSet = new ArraySet<>(addrs.length); + Collections.addAll(addrSet, addrs); + return addrSet; + } } diff --git a/packages/Tethering/src/android/net/ip/IpServer.java b/packages/Tethering/src/android/net/ip/IpServer.java index 8fde52040ecc..abfb33c7af9e 100644 --- a/packages/Tethering/src/android/net/ip/IpServer.java +++ b/packages/Tethering/src/android/net/ip/IpServer.java @@ -17,10 +17,12 @@ package android.net.ip; import static android.net.InetAddresses.parseNumericAddress; +import static android.net.RouteInfo.RTN_UNICAST; import static android.net.dhcp.IDhcpServer.STATUS_SUCCESS; import static android.net.util.NetworkConstants.FF; import static android.net.util.NetworkConstants.RFC7421_PREFIX_LENGTH; import static android.net.util.NetworkConstants.asByte; +import static android.net.util.TetheringMessageBase.BASE_IPSERVER; import android.net.ConnectivityManager; import android.net.INetd; @@ -46,11 +48,9 @@ import android.os.Message; import android.os.RemoteException; import android.os.ServiceSpecificException; import android.util.Log; -import android.util.Slog; import android.util.SparseArray; import com.android.internal.util.MessageUtils; -import com.android.internal.util.Protocol; import com.android.internal.util.State; import com.android.internal.util.StateMachine; @@ -153,27 +153,26 @@ public class IpServer extends StateMachine { DhcpServerCallbacks cb); } - private static final int BASE_IFACE = Protocol.BASE_TETHERING + 100; // request from the user that it wants to tether - public static final int CMD_TETHER_REQUESTED = BASE_IFACE + 2; + public static final int CMD_TETHER_REQUESTED = BASE_IPSERVER + 1; // request from the user that it wants to untether - public static final int CMD_TETHER_UNREQUESTED = BASE_IFACE + 3; + public static final int CMD_TETHER_UNREQUESTED = BASE_IPSERVER + 2; // notification that this interface is down - public static final int CMD_INTERFACE_DOWN = BASE_IFACE + 4; + public static final int CMD_INTERFACE_DOWN = BASE_IPSERVER + 3; // notification from the master SM that it had trouble enabling IP Forwarding - public static final int CMD_IP_FORWARDING_ENABLE_ERROR = BASE_IFACE + 7; + public static final int CMD_IP_FORWARDING_ENABLE_ERROR = BASE_IPSERVER + 4; // notification from the master SM that it had trouble disabling IP Forwarding - public static final int CMD_IP_FORWARDING_DISABLE_ERROR = BASE_IFACE + 8; + public static final int CMD_IP_FORWARDING_DISABLE_ERROR = BASE_IPSERVER + 5; // notification from the master SM that it had trouble starting tethering - public static final int CMD_START_TETHERING_ERROR = BASE_IFACE + 9; + public static final int CMD_START_TETHERING_ERROR = BASE_IPSERVER + 6; // notification from the master SM that it had trouble stopping tethering - public static final int CMD_STOP_TETHERING_ERROR = BASE_IFACE + 10; + public static final int CMD_STOP_TETHERING_ERROR = BASE_IPSERVER + 7; // notification from the master SM that it had trouble setting the DNS forwarders - public static final int CMD_SET_DNS_FORWARDERS_ERROR = BASE_IFACE + 11; + public static final int CMD_SET_DNS_FORWARDERS_ERROR = BASE_IPSERVER + 8; // the upstream connection has changed - public static final int CMD_TETHER_CONNECTION_CHANGED = BASE_IFACE + 12; + public static final int CMD_TETHER_CONNECTION_CHANGED = BASE_IPSERVER + 9; // new IPv6 tethering parameters need to be processed - public static final int CMD_IPV6_TETHER_UPDATE = BASE_IFACE + 13; + public static final int CMD_IPV6_TETHER_UPDATE = BASE_IPSERVER + 10; private final State mInitialState; private final State mLocalHotspotState; @@ -486,7 +485,9 @@ public class IpServer extends StateMachine { } // Directly-connected route. - final RouteInfo route = new RouteInfo(linkAddr); + final IpPrefix ipv4Prefix = new IpPrefix(linkAddr.getAddress(), + linkAddr.getPrefixLength()); + final RouteInfo route = new RouteInfo(ipv4Prefix, null, null, RTN_UNICAST); if (enabled) { mLinkProperties.addLinkAddress(linkAddr); mLinkProperties.addRoute(route); @@ -1007,7 +1008,7 @@ public class IpServer extends StateMachine { String ifname, HashSet<IpPrefix> prefixes) { final ArrayList<RouteInfo> localRoutes = new ArrayList<RouteInfo>(); for (IpPrefix ipp : prefixes) { - localRoutes.add(new RouteInfo(ipp, null, ifname)); + localRoutes.add(new RouteInfo(ipp, null, ifname, RTN_UNICAST)); } return localRoutes; } @@ -1019,7 +1020,7 @@ public class IpServer extends StateMachine { try { return Inet6Address.getByAddress(null, dnsBytes, 0); } catch (UnknownHostException e) { - Slog.wtf(TAG, "Failed to construct Inet6Address from: " + localPrefix); + Log.wtf(TAG, "Failed to construct Inet6Address from: " + localPrefix); return null; } } diff --git a/packages/Tethering/src/android/net/ip/RouterAdvertisementDaemon.java b/packages/Tethering/src/android/net/ip/RouterAdvertisementDaemon.java index 4396cdb92621..bba61d72d8d6 100644 --- a/packages/Tethering/src/android/net/ip/RouterAdvertisementDaemon.java +++ b/packages/Tethering/src/android/net/ip/RouterAdvertisementDaemon.java @@ -22,14 +22,13 @@ import static android.system.OsConstants.AF_INET6; import static android.system.OsConstants.IPPROTO_ICMPV6; import static android.system.OsConstants.SOCK_RAW; import static android.system.OsConstants.SOL_SOCKET; -import static android.system.OsConstants.SO_BINDTODEVICE; import static android.system.OsConstants.SO_SNDTIMEO; import android.net.IpPrefix; import android.net.LinkAddress; -import android.net.NetworkUtils; import android.net.TrafficStats; import android.net.util.InterfaceParams; +import android.net.util.SocketUtils; import android.net.util.TetheringUtils; import android.system.ErrnoException; import android.system.Os; @@ -39,8 +38,6 @@ import android.util.Log; import com.android.internal.annotations.GuardedBy; import com.android.internal.util.TrafficStatsConstants; -import libcore.io.IoBridge; - import java.io.FileDescriptor; import java.io.IOException; import java.net.Inet6Address; @@ -612,8 +609,7 @@ public class RouterAdvertisementDaemon { // Setting SNDTIMEO is purely for defensive purposes. Os.setsockoptTimeval( mSocket, SOL_SOCKET, SO_SNDTIMEO, StructTimeval.fromMillis(send_timout_ms)); - Os.setsockoptIfreq(mSocket, SOL_SOCKET, SO_BINDTODEVICE, mInterface.name); - NetworkUtils.protectFromVpn(mSocket); + SocketUtils.bindSocketToInterface(mSocket, mInterface.name); TetheringUtils.setupRaSocket(mSocket, mInterface.index); } catch (ErrnoException | IOException e) { Log.e(TAG, "Failed to create RA daemon socket: " + e); @@ -628,7 +624,7 @@ public class RouterAdvertisementDaemon { private void closeSocket() { if (mSocket != null) { try { - IoBridge.closeAndSignalBlockedThreads(mSocket); + SocketUtils.closeSocket(mSocket); } catch (IOException ignored) { } } mSocket = null; diff --git a/packages/Tethering/src/android/net/util/TetheringMessageBase.java b/packages/Tethering/src/android/net/util/TetheringMessageBase.java new file mode 100644 index 000000000000..1b763ce920da --- /dev/null +++ b/packages/Tethering/src/android/net/util/TetheringMessageBase.java @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.net.util; + +/** + * This class defines Message.what base addresses for various state machine. + */ +public class TetheringMessageBase { + public static final int BASE_MASTER = 0; + public static final int BASE_IPSERVER = 100; + +} diff --git a/packages/Tethering/src/android/net/util/TetheringUtils.java b/packages/Tethering/src/android/net/util/TetheringUtils.java index 2fb73ced8884..fa543bdce735 100644 --- a/packages/Tethering/src/android/net/util/TetheringUtils.java +++ b/packages/Tethering/src/android/net/util/TetheringUtils.java @@ -39,4 +39,11 @@ public class TetheringUtils { */ public static native void setupRaSocket(FileDescriptor fd, int ifIndex) throws SocketException; + + /** + * Read s as an unsigned 16-bit integer. + */ + public static int uint16(short s) { + return s & 0xffff; + } } diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/EntitlementManager.java b/packages/Tethering/src/com/android/server/connectivity/tethering/EntitlementManager.java index ba5d08dce4ca..7e685fbe97f1 100644 --- a/packages/Tethering/src/com/android/server/connectivity/tethering/EntitlementManager.java +++ b/packages/Tethering/src/com/android/server/connectivity/tethering/EntitlementManager.java @@ -38,7 +38,6 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.res.Resources; import android.net.util.SharedLog; -import android.os.Binder; import android.os.Bundle; import android.os.Handler; import android.os.Looper; @@ -48,7 +47,6 @@ import android.os.PersistableBundle; import android.os.ResultReceiver; import android.os.SystemClock; import android.os.SystemProperties; -import android.os.UserHandle; import android.provider.Settings; import android.telephony.CarrierConfigManager; import android.util.ArraySet; @@ -196,9 +194,9 @@ public class EntitlementManager { // till upstream change to cellular. if (mUsingCellularAsUpstream) { if (showProvisioningUi) { - runUiTetherProvisioning(type, config.subId); + runUiTetherProvisioning(type, config.activeDataSubId); } else { - runSilentTetherProvisioning(type, config.subId); + runSilentTetherProvisioning(type, config.activeDataSubId); } mNeedReRunProvisioningUi = false; } else { @@ -270,9 +268,9 @@ public class EntitlementManager { if (mCellularPermitted.indexOfKey(downstream) < 0) { if (mNeedReRunProvisioningUi) { mNeedReRunProvisioningUi = false; - runUiTetherProvisioning(downstream, config.subId); + runUiTetherProvisioning(downstream, config.activeDataSubId); } else { - runSilentTetherProvisioning(downstream, config.subId); + runSilentTetherProvisioning(downstream, config.activeDataSubId); } } } @@ -336,7 +334,8 @@ public class EntitlementManager { .getSystemService(Context.CARRIER_CONFIG_SERVICE); if (configManager == null) return null; - final PersistableBundle carrierConfig = configManager.getConfigForSubId(config.subId); + final PersistableBundle carrierConfig = configManager.getConfigForSubId( + config.activeDataSubId); if (CarrierConfigManager.isConfigForIdentifiedCarrier(carrierConfig)) { return carrierConfig; @@ -379,12 +378,9 @@ public class EntitlementManager { intent.putExtra(EXTRA_PROVISION_CALLBACK, receiver); intent.putExtra(EXTRA_SUBID, subId); intent.setComponent(TETHER_SERVICE); - final long ident = Binder.clearCallingIdentity(); - try { - mContext.startServiceAsUser(intent, UserHandle.CURRENT); - } finally { - Binder.restoreCallingIdentity(ident); - } + // Only admin user can change tethering and SilentTetherProvisioning don't need to + // show UI, it is fine to always start setting's background service as system user. + mContext.startService(intent); } private void runUiTetherProvisioning(int type, int subId) { @@ -407,12 +403,9 @@ public class EntitlementManager { intent.putExtra(EXTRA_PROVISION_CALLBACK, receiver); intent.putExtra(EXTRA_SUBID, subId); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - final long ident = Binder.clearCallingIdentity(); - try { - mContext.startActivityAsUser(intent, UserHandle.CURRENT); - } finally { - Binder.restoreCallingIdentity(ident); - } + // Only launch entitlement UI for system user. Entitlement UI should not appear for other + // user because only admin user is allowed to change tethering. + mContext.startActivity(intent); } // Not needed to check if this don't run on the handler thread because it's private. @@ -671,7 +664,7 @@ public class EntitlementManager { receiver.send(cacheValue, null); } else { ResultReceiver proxy = buildProxyReceiver(downstream, false/* notifyFail */, receiver); - runUiTetherProvisioning(downstream, config.subId, proxy); + runUiTetherProvisioning(downstream, config.activeDataSubId, proxy); } } } diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/IPv6TetheringCoordinator.java b/packages/Tethering/src/com/android/server/connectivity/tethering/IPv6TetheringCoordinator.java index 93054140213d..66b9ade81019 100644 --- a/packages/Tethering/src/com/android/server/connectivity/tethering/IPv6TetheringCoordinator.java +++ b/packages/Tethering/src/com/android/server/connectivity/tethering/IPv6TetheringCoordinator.java @@ -29,6 +29,7 @@ import android.util.Log; import java.net.Inet6Address; import java.net.InetAddress; +import java.net.UnknownHostException; import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedList; @@ -257,7 +258,7 @@ public class IPv6TetheringCoordinator { final LinkProperties lp = new LinkProperties(); final IpPrefix local48 = makeUniqueLocalPrefix(ulp, (short) 0, 48); - lp.addRoute(new RouteInfo(local48, null, null)); + lp.addRoute(new RouteInfo(local48, null, null, RouteInfo.RTN_UNICAST)); final IpPrefix local64 = makeUniqueLocalPrefix(ulp, subnetId, 64); // Because this is a locally-generated ULA, we don't have an upstream @@ -273,7 +274,13 @@ public class IPv6TetheringCoordinator { final byte[] bytes = Arrays.copyOf(in6addr, in6addr.length); bytes[7] = (byte) (subnetId >> 8); bytes[8] = (byte) subnetId; - return new IpPrefix(bytes, prefixlen); + final InetAddress addr; + try { + addr = InetAddress.getByAddress(bytes); + } catch (UnknownHostException e) { + throw new IllegalStateException("Invalid address length: " + bytes.length, e); + } + return new IpPrefix(addr, prefixlen); } // Generates a Unique Locally-assigned Prefix: diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/OffloadController.java b/packages/Tethering/src/com/android/server/connectivity/tethering/OffloadController.java index 16734d83e3aa..38fa91e7387e 100644 --- a/packages/Tethering/src/com/android/server/connectivity/tethering/OffloadController.java +++ b/packages/Tethering/src/com/android/server/connectivity/tethering/OffloadController.java @@ -25,6 +25,7 @@ import static android.provider.Settings.Global.TETHER_OFFLOAD_DISABLED; import android.content.ContentResolver; import android.net.ITetheringStatsProvider; +import android.net.InetAddresses; import android.net.IpPrefix; import android.net.LinkAddress; import android.net.LinkProperties; @@ -33,7 +34,6 @@ import android.net.RouteInfo; import android.net.netlink.ConntrackMessage; import android.net.netlink.NetlinkConstants; import android.net.netlink.NetlinkSocket; -import android.net.util.IpUtils; import android.net.util.SharedLog; import android.os.Handler; import android.os.INetworkManagementService; @@ -477,9 +477,10 @@ public class OffloadController { if (!ri.hasGateway()) continue; final String gateway = ri.getGateway().getHostAddress(); - if (ri.isIPv4Default()) { + final InetAddress address = ri.getDestination().getAddress(); + if (ri.isDefaultRoute() && address instanceof Inet4Address) { v4gateway = gateway; - } else if (ri.isIPv6Default()) { + } else if (ri.isDefaultRoute() && address instanceof Inet6Address) { v6gateways.add(gateway); } } @@ -547,7 +548,10 @@ public class OffloadController { private static boolean shouldIgnoreDownstreamRoute(RouteInfo route) { // Ignore any link-local routes. - if (!route.getDestinationLinkAddress().isGlobalPreferred()) return true; + final IpPrefix destination = route.getDestination(); + final LinkAddress linkAddr = new LinkAddress(destination.getAddress(), + destination.getPrefixLength()); + if (!linkAddr.isGlobalPreferred()) return true; return false; } @@ -588,7 +592,7 @@ public class OffloadController { return; } - if (!IpUtils.isValidUdpOrTcpPort(srcPort)) { + if (!isValidUdpOrTcpPort(srcPort)) { mLog.e("Invalid src port: " + srcPort); return; } @@ -599,7 +603,7 @@ public class OffloadController { return; } - if (!IpUtils.isValidUdpOrTcpPort(dstPort)) { + if (!isValidUdpOrTcpPort(dstPort)) { mLog.e("Invalid dst port: " + dstPort); return; } @@ -628,7 +632,7 @@ public class OffloadController { private static Inet4Address parseIPv4Address(String addrString) { try { - final InetAddress ip = InetAddress.parseNumericAddress(addrString); + final InetAddress ip = InetAddresses.parseNumericAddress(addrString); // TODO: Consider other sanitization steps here, including perhaps: // not eql to 0.0.0.0 // not within 169.254.0.0/16 @@ -668,4 +672,8 @@ public class OffloadController { return 180; } } + + private static boolean isValidUdpOrTcpPort(int port) { + return port > 0 && port < 65536; + } } diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/OffloadHardwareInterface.java b/packages/Tethering/src/com/android/server/connectivity/tethering/OffloadHardwareInterface.java index 85164edf3c5b..4a8ef1f92754 100644 --- a/packages/Tethering/src/com/android/server/connectivity/tethering/OffloadHardwareInterface.java +++ b/packages/Tethering/src/com/android/server/connectivity/tethering/OffloadHardwareInterface.java @@ -16,7 +16,7 @@ package com.android.server.connectivity.tethering; -import static com.android.internal.util.BitUtils.uint16; +import static android.net.util.TetheringUtils.uint16; import android.hardware.tetheroffload.control.V1_0.IOffloadControl; import android.hardware.tetheroffload.control.V1_0.ITetheringOffloadCallback; diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java b/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java index 0b5759ba539f..5b267046a851 100644 --- a/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java +++ b/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java @@ -37,6 +37,7 @@ import static android.net.ConnectivityManager.TETHER_ERROR_NO_ERROR; import static android.net.ConnectivityManager.TETHER_ERROR_SERVICE_UNAVAIL; import static android.net.ConnectivityManager.TETHER_ERROR_UNAVAIL_IFACE; import static android.net.ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE; +import static android.net.util.TetheringMessageBase.BASE_MASTER; import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_INTERFACE_NAME; import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_MODE; import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_STATE; @@ -106,7 +107,6 @@ import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; import com.android.internal.notification.SystemNotificationChannels; import com.android.internal.util.IndentingPrintWriter; import com.android.internal.util.MessageUtils; -import com.android.internal.util.Protocol; import com.android.internal.util.State; import com.android.internal.util.StateMachine; import com.android.networkstack.tethering.R; @@ -120,6 +120,8 @@ import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.Set; +import java.util.concurrent.Executor; +import java.util.concurrent.RejectedExecutionException; /** * @@ -185,10 +187,10 @@ public class Tethering { private final TetheringDependencies mDeps; private final EntitlementManager mEntitlementMgr; private final Handler mHandler; - private final PhoneStateListener mPhoneStateListener; private final INetd mNetd; private final NetdCallback mNetdCallback; private final UserRestrictionActionListener mTetheringRestriction; + private final ActiveDataSubIdListener mActiveDataSubIdListener; private int mActiveDataSubId = INVALID_SUBSCRIPTION_ID; // All the usage of mTetheringEventCallback should run in the same thread. private ITetheringEventCallback mTetheringEventCallback = null; @@ -252,26 +254,6 @@ public class Tethering { mEntitlementMgr.reevaluateSimCardProvisioning(mConfig); }); - mPhoneStateListener = new PhoneStateListener(mLooper) { - @Override - public void onActiveDataSubscriptionIdChanged(int subId) { - mLog.log("OBSERVED active data subscription change, from " + mActiveDataSubId - + " to " + subId); - if (subId == mActiveDataSubId) return; - - mActiveDataSubId = subId; - updateConfiguration(); - // To avoid launching unexpected provisioning checks, ignore re-provisioning when - // no CarrierConfig loaded yet. Assume reevaluateSimCardProvisioning() will be - // triggered again when CarrierConfig is loaded. - if (mEntitlementMgr.getCarrierConfig(mConfig) != null) { - mEntitlementMgr.reevaluateSimCardProvisioning(mConfig); - } else { - mLog.log("IGNORED reevaluate provisioning due to no carrier config loaded"); - } - } - }; - mStateReceiver = new StateReceiver(); mNetdCallback = new NetdCallback(); @@ -284,6 +266,8 @@ public class Tethering { final UserManager userManager = (UserManager) mContext.getSystemService( Context.USER_SERVICE); mTetheringRestriction = new UserRestrictionActionListener(userManager, this); + final TetheringThreadExecutor executor = new TetheringThreadExecutor(mHandler); + mActiveDataSubIdListener = new ActiveDataSubIdListener(executor); // Load tethering configuration. updateConfiguration(); @@ -294,8 +278,8 @@ public class Tethering { private void startStateMachineUpdaters(Handler handler) { mCarrierConfigChange.startListening(); - mContext.getSystemService(TelephonyManager.class).listen( - mPhoneStateListener, PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE); + mContext.getSystemService(TelephonyManager.class).listen(mActiveDataSubIdListener, + PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE); IntentFilter filter = new IntentFilter(); filter.addAction(UsbManager.ACTION_USB_STATE); @@ -314,6 +298,43 @@ public class Tethering { } + private class TetheringThreadExecutor implements Executor { + private final Handler mTetherHandler; + TetheringThreadExecutor(Handler handler) { + mTetherHandler = handler; + } + @Override + public void execute(Runnable command) { + if (!mTetherHandler.post(command)) { + throw new RejectedExecutionException(mTetherHandler + " is shutting down"); + } + } + } + + private class ActiveDataSubIdListener extends PhoneStateListener { + ActiveDataSubIdListener(Executor executor) { + super(executor); + } + + @Override + public void onActiveDataSubscriptionIdChanged(int subId) { + mLog.log("OBSERVED active data subscription change, from " + mActiveDataSubId + + " to " + subId); + if (subId == mActiveDataSubId) return; + + mActiveDataSubId = subId; + updateConfiguration(); + // To avoid launching unexpected provisioning checks, ignore re-provisioning + // when no CarrierConfig loaded yet. Assume reevaluateSimCardProvisioning() + // ill be triggered again when CarrierConfig is loaded. + if (mEntitlementMgr.getCarrierConfig(mConfig) != null) { + mEntitlementMgr.reevaluateSimCardProvisioning(mConfig); + } else { + mLog.log("IGNORED reevaluate provisioning, no carrier config loaded"); + } + } + } + private WifiManager getWifiManager() { return (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE); } @@ -326,8 +347,7 @@ public class Tethering { } private void maybeDunSettingChanged() { - final boolean isDunRequired = TetheringConfiguration.checkDunRequired( - mContext, mActiveDataSubId); + final boolean isDunRequired = TetheringConfiguration.checkDunRequired(mContext); if (isDunRequired == mConfig.isDunRequired) return; updateConfiguration(); } @@ -1162,7 +1182,6 @@ public class Tethering { } class TetherMasterSM extends StateMachine { - private static final int BASE_MASTER = Protocol.BASE_TETHERING; // an interface SM has requested Tethering/Local Hotspot static final int EVENT_IFACE_SERVING_STATE_ACTIVE = BASE_MASTER + 1; // an interface SM has unrequested Tethering/Local Hotspot @@ -1179,7 +1198,6 @@ public class Tethering { static final int EVENT_IFACE_UPDATE_LINKPROPERTIES = BASE_MASTER + 7; // Events from EntitlementManager to choose upstream again. static final int EVENT_UPSTREAM_PERMISSION_CHANGED = BASE_MASTER + 8; - private final State mInitialState; private final State mTetherModeAliveState; diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringConfiguration.java b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringConfiguration.java index 0ab4d634e84d..490614b03149 100644 --- a/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringConfiguration.java +++ b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringConfiguration.java @@ -100,13 +100,13 @@ public class TetheringConfiguration { public final String provisioningAppNoUi; public final int provisioningCheckPeriod; - public final int subId; + public final int activeDataSubId; public TetheringConfiguration(Context ctx, SharedLog log, int id) { final SharedLog configLog = log.forSubComponent("config"); - subId = id; - Resources res = getResources(ctx, subId); + activeDataSubId = id; + Resources res = getResources(ctx, activeDataSubId); tetherableUsbRegexs = getResourceStringArray(res, config_tether_usb_regexs); // TODO: Evaluate deleting this altogether now that Wi-Fi always passes @@ -116,7 +116,7 @@ public class TetheringConfiguration { tetherableWifiP2pRegexs = getResourceStringArray(res, config_tether_wifi_p2p_regexs); tetherableBluetoothRegexs = getResourceStringArray(res, config_tether_bluetooth_regexs); - isDunRequired = checkDunRequired(ctx, subId); + isDunRequired = checkDunRequired(ctx); chooseUpstreamAutomatically = getResourceBoolean(res, config_tether_upstream_automatic); preferredUpstreamIfaceTypes = getUpstreamIfaceTypes(res, isDunRequired); @@ -166,8 +166,8 @@ public class TetheringConfiguration { /** Does the dumping.*/ public void dump(PrintWriter pw) { - pw.print("subId: "); - pw.println(subId); + pw.print("activeDataSubId: "); + pw.println(activeDataSubId); dumpStringArray(pw, "tetherableUsbRegexs", tetherableUsbRegexs); dumpStringArray(pw, "tetherableWifiRegexs", tetherableWifiRegexs); @@ -196,7 +196,7 @@ public class TetheringConfiguration { /** Returns the string representation of this object.*/ public String toString() { final StringJoiner sj = new StringJoiner(" "); - sj.add(String.format("subId:%d", subId)); + sj.add(String.format("activeDataSubId:%d", activeDataSubId)); sj.add(String.format("tetherableUsbRegexs:%s", makeString(tetherableUsbRegexs))); sj.add(String.format("tetherableWifiRegexs:%s", makeString(tetherableWifiRegexs))); sj.add(String.format("tetherableWifiP2pRegexs:%s", makeString(tetherableWifiP2pRegexs))); @@ -250,9 +250,11 @@ public class TetheringConfiguration { } /** Check whether dun is required. */ - public static boolean checkDunRequired(Context ctx, int id) { + public static boolean checkDunRequired(Context ctx) { final TelephonyManager tm = (TelephonyManager) ctx.getSystemService(TELEPHONY_SERVICE); - return (tm != null) ? tm.isTetheringApnRequired(id) : false; + // TelephonyManager would uses the active data subscription, which should be the one used + // by tethering. + return (tm != null) ? tm.isTetheringApnRequired() : false; } private static Collection<Integer> getUpstreamIfaceTypes(Resources res, boolean dunRequired) { @@ -391,7 +393,7 @@ public class TetheringConfiguration { */ public TetheringConfigurationParcel toStableParcelable() { final TetheringConfigurationParcel parcel = new TetheringConfigurationParcel(); - parcel.subId = subId; + parcel.subId = activeDataSubId; parcel.tetherableUsbRegexs = tetherableUsbRegexs; parcel.tetherableWifiRegexs = tetherableWifiRegexs; parcel.tetherableBluetoothRegexs = tetherableBluetoothRegexs; diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringService.java b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringService.java index 1d5998680287..775484eabfa3 100644 --- a/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringService.java +++ b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringService.java @@ -21,6 +21,7 @@ import static android.net.TetheringManager.TETHER_ERROR_NO_ACCESS_TETHERING_PERM import static android.net.TetheringManager.TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION; import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR; import static android.net.TetheringManager.TETHER_ERROR_UNSUPPORTED; +import static android.net.dhcp.IDhcpServer.STATUS_UNKNOWN_ERROR; import android.app.Service; import android.content.Context; @@ -340,7 +341,10 @@ public class TetheringService extends Service { service.makeDhcpServer(ifName, params, cb); } catch (RemoteException e) { - e.rethrowFromSystemServer(); + Log.e(TAG, "Fail to make dhcp server"); + try { + cb.onDhcpServerCreated(STATUS_UNKNOWN_ERROR, null); + } catch (RemoteException re) { } } } }; diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java b/packages/Tethering/src/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java index dc38c49a0c12..22150f623a35 100644 --- a/packages/Tethering/src/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java +++ b/packages/Tethering/src/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java @@ -328,13 +328,6 @@ public class UpstreamNetworkMonitor { network, newNc)); } - // Log changes in upstream network signal strength, if available. - if (network.equals(mTetheringUpstreamNetwork) && newNc.hasSignalStrength()) { - final int newSignal = newNc.getSignalStrength(); - final String prevSignal = getSignalStrength(prev.networkCapabilities); - mLog.logf("upstream network signal strength: %s -> %s", prevSignal, newSignal); - } - mNetworkMap.put(network, new UpstreamNetworkState( prev.linkProperties, newNc, network)); // TODO: If sufficient information is available to select a more @@ -557,11 +550,6 @@ public class UpstreamNetworkMonitor { return prefixSet; } - private static String getSignalStrength(NetworkCapabilities nc) { - if (nc == null || !nc.hasSignalStrength()) return "unknown"; - return Integer.toString(nc.getSignalStrength()); - } - private static boolean isCellular(UpstreamNetworkState ns) { return (ns != null) && isCellular(ns.networkCapabilities); } diff --git a/packages/Tethering/tests/unit/src/android/net/dhcp/DhcpServingParamsParcelExtTest.java b/packages/Tethering/tests/unit/src/android/net/dhcp/DhcpServingParamsParcelExtTest.java index e01ac7f08c2f..e8add9830b5f 100644 --- a/packages/Tethering/tests/unit/src/android/net/dhcp/DhcpServingParamsParcelExtTest.java +++ b/packages/Tethering/tests/unit/src/android/net/dhcp/DhcpServingParamsParcelExtTest.java @@ -18,8 +18,6 @@ package android.net.dhcp; import static android.net.InetAddresses.parseNumericAddress; -import static com.google.android.collect.Sets.newHashSet; - import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -34,6 +32,8 @@ import org.junit.Test; import org.junit.runner.RunWith; import java.net.Inet4Address; +import java.util.Arrays; +import java.util.HashSet; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.IntStream; @@ -47,9 +47,10 @@ public class DhcpServingParamsParcelExtTest { private static final int TEST_LEASE_TIME_SECS = 120; private static final int TEST_MTU = 1000; private static final Set<Inet4Address> TEST_ADDRESS_SET = - newHashSet(inet4Addr("192.168.1.123"), inet4Addr("192.168.1.124")); + new HashSet<Inet4Address>(Arrays.asList( + new Inet4Address[] {inet4Addr("192.168.1.123"), inet4Addr("192.168.1.124")})); private static final Set<Integer> TEST_ADDRESS_SET_PARCELED = - newHashSet(0xc0a8017b, 0xc0a8017c); + new HashSet<Integer>(Arrays.asList(new Integer[] {0xc0a8017b, 0xc0a8017c})); private DhcpServingParamsParcelExt mParcel; diff --git a/packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java b/packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java index 4358cd6966f1..fd2f708aea30 100644 --- a/packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java +++ b/packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java @@ -510,8 +510,10 @@ public class IpServerTest { } assertNotNull("missing IPv4 address", addr4); + final IpPrefix destination = new IpPrefix(addr4.getAddress(), addr4.getPrefixLength()); // Assert the presence of the associated directly connected route. - final RouteInfo directlyConnected = new RouteInfo(addr4, null, lp.getInterfaceName()); + final RouteInfo directlyConnected = new RouteInfo(destination, null, lp.getInterfaceName(), + RouteInfo.RTN_UNICAST); assertTrue("missing directly connected route: '" + directlyConnected.toString() + "'", lp.getRoutes().contains(directlyConnected)); } diff --git a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/OffloadControllerTest.java b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/OffloadControllerTest.java index 8574f5401496..7886ca6c132d 100644 --- a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/OffloadControllerTest.java +++ b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/OffloadControllerTest.java @@ -21,6 +21,7 @@ import static android.net.NetworkStats.STATS_PER_IFACE; import static android.net.NetworkStats.STATS_PER_UID; import static android.net.NetworkStats.TAG_NONE; import static android.net.NetworkStats.UID_ALL; +import static android.net.RouteInfo.RTN_UNICAST; import static android.net.TrafficStats.UID_TETHERING; import static android.provider.Settings.Global.TETHER_OFFLOAD_DISABLED; @@ -269,7 +270,7 @@ public class OffloadControllerTest { final String ipv4Addr = "192.0.2.5"; final String linkAddr = ipv4Addr + "/24"; lp.addLinkAddress(new LinkAddress(linkAddr)); - lp.addRoute(new RouteInfo(new IpPrefix("192.0.2.0/24"))); + lp.addRoute(new RouteInfo(new IpPrefix("192.0.2.0/24"), null, null, RTN_UNICAST)); offload.setUpstreamLinkProperties(lp); // IPv4 prefixes and addresses on the upstream are simply left as whole // prefixes (already passed in from UpstreamNetworkMonitor code). If a @@ -285,7 +286,7 @@ public class OffloadControllerTest { inOrder.verifyNoMoreInteractions(); final String ipv4Gateway = "192.0.2.1"; - lp.addRoute(new RouteInfo(InetAddress.getByName(ipv4Gateway))); + lp.addRoute(new RouteInfo(null, InetAddress.getByName(ipv4Gateway), null, RTN_UNICAST)); offload.setUpstreamLinkProperties(lp); // No change in local addresses means no call to setLocalPrefixes(). inOrder.verify(mHardware, never()).setLocalPrefixes(mStringArrayCaptor.capture()); @@ -296,7 +297,7 @@ public class OffloadControllerTest { inOrder.verifyNoMoreInteractions(); final String ipv6Gw1 = "fe80::cafe"; - lp.addRoute(new RouteInfo(InetAddress.getByName(ipv6Gw1))); + lp.addRoute(new RouteInfo(null, InetAddress.getByName(ipv6Gw1), null, RTN_UNICAST)); offload.setUpstreamLinkProperties(lp); // No change in local addresses means no call to setLocalPrefixes(). inOrder.verify(mHardware, never()).setLocalPrefixes(mStringArrayCaptor.capture()); @@ -310,7 +311,7 @@ public class OffloadControllerTest { inOrder.verifyNoMoreInteractions(); final String ipv6Gw2 = "fe80::d00d"; - lp.addRoute(new RouteInfo(InetAddress.getByName(ipv6Gw2))); + lp.addRoute(new RouteInfo(null, InetAddress.getByName(ipv6Gw2), null, RTN_UNICAST)); offload.setUpstreamLinkProperties(lp); // No change in local addresses means no call to setLocalPrefixes(). inOrder.verify(mHardware, never()).setLocalPrefixes(mStringArrayCaptor.capture()); @@ -327,8 +328,10 @@ public class OffloadControllerTest { final LinkProperties stacked = new LinkProperties(); stacked.setInterfaceName("stacked"); stacked.addLinkAddress(new LinkAddress("192.0.2.129/25")); - stacked.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254"))); - stacked.addRoute(new RouteInfo(InetAddress.getByName("fe80::bad:f00"))); + stacked.addRoute(new RouteInfo(null, InetAddress.getByName("192.0.2.254"), null, + RTN_UNICAST)); + stacked.addRoute(new RouteInfo(null, InetAddress.getByName("fe80::bad:f00"), null, + RTN_UNICAST)); assertTrue(lp.addStackedLink(stacked)); offload.setUpstreamLinkProperties(lp); // No change in local addresses means no call to setLocalPrefixes(). @@ -348,7 +351,7 @@ public class OffloadControllerTest { // removed from "local prefixes" and /128s added for the upstream IPv6 // addresses. This is not yet implemented, and for now we simply // expect to see these /128s. - lp.addRoute(new RouteInfo(new IpPrefix("2001:db8::/64"))); + lp.addRoute(new RouteInfo(new IpPrefix("2001:db8::/64"), null, null, RTN_UNICAST)); // "2001:db8::/64" plus "assigned" ASCII in hex lp.addLinkAddress(new LinkAddress("2001:db8::6173:7369:676e:6564/64")); // "2001:db8::/64" plus "random" ASCII in hex @@ -574,13 +577,15 @@ public class OffloadControllerTest { final LinkProperties usbLinkProperties = new LinkProperties(); usbLinkProperties.setInterfaceName(RNDIS0); usbLinkProperties.addLinkAddress(new LinkAddress("192.168.42.1/24")); - usbLinkProperties.addRoute(new RouteInfo(new IpPrefix(USB_PREFIX))); + usbLinkProperties.addRoute( + new RouteInfo(new IpPrefix(USB_PREFIX), null, null, RTN_UNICAST)); offload.notifyDownstreamLinkProperties(usbLinkProperties); inOrder.verify(mHardware, times(1)).addDownstreamPrefix(RNDIS0, USB_PREFIX); inOrder.verifyNoMoreInteractions(); // [2] Routes for IPv6 link-local prefixes should never be added. - usbLinkProperties.addRoute(new RouteInfo(new IpPrefix(IPV6_LINKLOCAL))); + usbLinkProperties.addRoute( + new RouteInfo(new IpPrefix(IPV6_LINKLOCAL), null, null, RTN_UNICAST)); offload.notifyDownstreamLinkProperties(usbLinkProperties); inOrder.verify(mHardware, never()).addDownstreamPrefix(eq(RNDIS0), anyString()); inOrder.verifyNoMoreInteractions(); @@ -588,7 +593,8 @@ public class OffloadControllerTest { // [3] Add an IPv6 prefix for good measure. Only new offload-able // prefixes should be passed to the HAL. usbLinkProperties.addLinkAddress(new LinkAddress("2001:db8::1/64")); - usbLinkProperties.addRoute(new RouteInfo(new IpPrefix(IPV6_DOC_PREFIX))); + usbLinkProperties.addRoute( + new RouteInfo(new IpPrefix(IPV6_DOC_PREFIX), null, null, RTN_UNICAST)); offload.notifyDownstreamLinkProperties(usbLinkProperties); inOrder.verify(mHardware, times(1)).addDownstreamPrefix(RNDIS0, IPV6_DOC_PREFIX); inOrder.verifyNoMoreInteractions(); @@ -601,8 +607,10 @@ public class OffloadControllerTest { // [5] Differences in local routes are converted into addDownstream() // and removeDownstream() invocations accordingly. - usbLinkProperties.removeRoute(new RouteInfo(new IpPrefix(IPV6_DOC_PREFIX), null, RNDIS0)); - usbLinkProperties.addRoute(new RouteInfo(new IpPrefix(IPV6_DISCARD_PREFIX))); + usbLinkProperties.removeRoute( + new RouteInfo(new IpPrefix(IPV6_DOC_PREFIX), null, RNDIS0, RTN_UNICAST)); + usbLinkProperties.addRoute( + new RouteInfo(new IpPrefix(IPV6_DISCARD_PREFIX), null, null, RTN_UNICAST)); offload.notifyDownstreamLinkProperties(usbLinkProperties); inOrder.verify(mHardware, times(1)).removeDownstreamPrefix(RNDIS0, IPV6_DOC_PREFIX); inOrder.verify(mHardware, times(1)).addDownstreamPrefix(RNDIS0, IPV6_DISCARD_PREFIX); @@ -680,19 +688,23 @@ public class OffloadControllerTest { final LinkProperties usbLinkProperties = new LinkProperties(); usbLinkProperties.setInterfaceName(RNDIS0); usbLinkProperties.addLinkAddress(new LinkAddress("192.168.42.1/24")); - usbLinkProperties.addRoute(new RouteInfo(new IpPrefix(USB_PREFIX))); + usbLinkProperties.addRoute( + new RouteInfo(new IpPrefix(USB_PREFIX), null, null, RTN_UNICAST)); offload.notifyDownstreamLinkProperties(usbLinkProperties); final LinkProperties wifiLinkProperties = new LinkProperties(); wifiLinkProperties.setInterfaceName(WLAN0); wifiLinkProperties.addLinkAddress(new LinkAddress("192.168.43.1/24")); - wifiLinkProperties.addRoute(new RouteInfo(new IpPrefix(WIFI_PREFIX))); - wifiLinkProperties.addRoute(new RouteInfo(new IpPrefix(IPV6_LINKLOCAL))); + wifiLinkProperties.addRoute( + new RouteInfo(new IpPrefix(WIFI_PREFIX), null, null, RTN_UNICAST)); + wifiLinkProperties.addRoute( + new RouteInfo(new IpPrefix(IPV6_LINKLOCAL), null, null, RTN_UNICAST)); // Use a benchmark prefix (RFC 5180 + erratum), since the documentation // prefix is included in the excluded prefix list. wifiLinkProperties.addLinkAddress(new LinkAddress("2001:2::1/64")); wifiLinkProperties.addLinkAddress(new LinkAddress("2001:2::2/64")); - wifiLinkProperties.addRoute(new RouteInfo(new IpPrefix("2001:2::/64"))); + wifiLinkProperties.addRoute( + new RouteInfo(new IpPrefix("2001:2::/64"), null, null, RTN_UNICAST)); offload.notifyDownstreamLinkProperties(wifiLinkProperties); offload.removeDownstreamInterface(RNDIS0); diff --git a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringConfigurationTest.java b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringConfigurationTest.java index 30bff3560955..7799da4b94a7 100644 --- a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringConfigurationTest.java +++ b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringConfigurationTest.java @@ -34,7 +34,6 @@ import static com.android.internal.R.array.config_tether_wifi_regexs; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; -import static org.mockito.Matchers.anyInt; import static org.mockito.Mockito.when; import android.content.ContentResolver; @@ -145,7 +144,7 @@ public class TetheringConfigurationTest { @Test public void testDunFromTelephonyManagerMeansDun() { - when(mTelephonyManager.isTetheringApnRequired(anyInt())).thenReturn(true); + when(mTelephonyManager.isTetheringApnRequired()).thenReturn(true); final TetheringConfiguration cfgWifi = getTetheringConfiguration(TYPE_WIFI); final TetheringConfiguration cfgMobileWifiHipri = getTetheringConfiguration( @@ -169,7 +168,7 @@ public class TetheringConfigurationTest { @Test public void testDunNotRequiredFromTelephonyManagerMeansNoDun() { - when(mTelephonyManager.isTetheringApnRequired(anyInt())).thenReturn(false); + when(mTelephonyManager.isTetheringApnRequired()).thenReturn(false); final TetheringConfiguration cfgWifi = getTetheringConfiguration(TYPE_WIFI); final TetheringConfiguration cfgMobileWifiHipri = getTetheringConfiguration( @@ -212,7 +211,7 @@ public class TetheringConfigurationTest { @Test public void testNoDefinedUpstreamTypesAddsEthernet() { when(mResources.getIntArray(config_tether_upstream_types)).thenReturn(new int[]{}); - when(mTelephonyManager.isTetheringApnRequired(anyInt())).thenReturn(false); + when(mTelephonyManager.isTetheringApnRequired()).thenReturn(false); final TetheringConfiguration cfg = new TetheringConfiguration( mMockContext, mLog, INVALID_SUBSCRIPTION_ID); @@ -235,7 +234,7 @@ public class TetheringConfigurationTest { public void testDefinedUpstreamTypesSansEthernetAddsEthernet() { when(mResources.getIntArray(config_tether_upstream_types)).thenReturn( new int[]{TYPE_WIFI, TYPE_MOBILE_HIPRI}); - when(mTelephonyManager.isTetheringApnRequired(anyInt())).thenReturn(false); + when(mTelephonyManager.isTetheringApnRequired()).thenReturn(false); final TetheringConfiguration cfg = new TetheringConfiguration( mMockContext, mLog, INVALID_SUBSCRIPTION_ID); @@ -253,7 +252,7 @@ public class TetheringConfigurationTest { public void testDefinedUpstreamTypesWithEthernetDoesNotAddEthernet() { when(mResources.getIntArray(config_tether_upstream_types)) .thenReturn(new int[]{TYPE_WIFI, TYPE_ETHERNET, TYPE_MOBILE_HIPRI}); - when(mTelephonyManager.isTetheringApnRequired(anyInt())).thenReturn(false); + when(mTelephonyManager.isTetheringApnRequired()).thenReturn(false); final TetheringConfiguration cfg = new TetheringConfiguration( mMockContext, mLog, INVALID_SUBSCRIPTION_ID); diff --git a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java index 9d9ad10af5b3..04b2eb411c9d 100644 --- a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java +++ b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java @@ -28,6 +28,7 @@ import static android.net.ConnectivityManager.TETHERING_WIFI; import static android.net.ConnectivityManager.TETHER_ERROR_NO_ERROR; import static android.net.ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE; import static android.net.ConnectivityManager.TYPE_WIFI_P2P; +import static android.net.RouteInfo.RTN_UNICAST; import static android.net.dhcp.IDhcpServer.STATUS_SUCCESS; import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_INTERFACE_NAME; import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_MODE; @@ -72,6 +73,7 @@ import android.net.INetd; import android.net.INetworkPolicyManager; import android.net.INetworkStatsService; import android.net.ITetheringEventCallback; +import android.net.InetAddresses; import android.net.InterfaceConfiguration; import android.net.IpPrefix; import android.net.LinkAddress; @@ -81,7 +83,6 @@ import android.net.Network; import android.net.NetworkCapabilities; import android.net.NetworkInfo; import android.net.NetworkRequest; -import android.net.NetworkUtils; import android.net.RouteInfo; import android.net.TetherStatesParcel; import android.net.TetheringConfigurationParcel; @@ -365,23 +366,26 @@ public class TetheringTest { if (withIPv4) { prop.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), - NetworkUtils.numericToInetAddress("10.0.0.1"), TEST_MOBILE_IFNAME)); + InetAddresses.parseNumericAddress("10.0.0.1"), + TEST_MOBILE_IFNAME, RTN_UNICAST)); } if (withIPv6) { - prop.addDnsServer(NetworkUtils.numericToInetAddress("2001:db8::2")); + prop.addDnsServer(InetAddresses.parseNumericAddress("2001:db8::2")); prop.addLinkAddress( - new LinkAddress(NetworkUtils.numericToInetAddress("2001:db8::"), + new LinkAddress(InetAddresses.parseNumericAddress("2001:db8::"), NetworkConstants.RFC7421_PREFIX_LENGTH)); prop.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), - NetworkUtils.numericToInetAddress("2001:db8::1"), TEST_MOBILE_IFNAME)); + InetAddresses.parseNumericAddress("2001:db8::1"), + TEST_MOBILE_IFNAME, RTN_UNICAST)); } if (with464xlat) { final LinkProperties stackedLink = new LinkProperties(); stackedLink.setInterfaceName(TEST_XLAT_MOBILE_IFNAME); stackedLink.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), - NetworkUtils.numericToInetAddress("192.0.0.1"), TEST_XLAT_MOBILE_IFNAME)); + InetAddresses.parseNumericAddress("192.0.0.1"), + TEST_XLAT_MOBILE_IFNAME, RTN_UNICAST)); prop.addStackedLink(stackedLink); } @@ -1210,12 +1214,12 @@ public class TetheringTest { @Test public void testMultiSimAware() throws Exception { final TetheringConfiguration initailConfig = mTethering.getTetheringConfiguration(); - assertEquals(INVALID_SUBSCRIPTION_ID, initailConfig.subId); + assertEquals(INVALID_SUBSCRIPTION_ID, initailConfig.activeDataSubId); final int fakeSubId = 1234; mPhoneStateListener.onActiveDataSubscriptionIdChanged(fakeSubId); final TetheringConfiguration newConfig = mTethering.getTetheringConfiguration(); - assertEquals(fakeSubId, newConfig.subId); + assertEquals(fakeSubId, newConfig.activeDataSubId); } private void workingWifiP2pGroupOwner( diff --git a/services/core/Android.bp b/services/core/Android.bp index 8d223003fe5b..a1f57cb51188 100644 --- a/services/core/Android.bp +++ b/services/core/Android.bp @@ -117,6 +117,7 @@ java_library_static { "android.hardware.oemlock-V1.0-java", "android.hardware.configstore-V1.0-java", "android.hardware.contexthub-V1.0-java", + "android.hardware.rebootescrow-java", "android.hardware.soundtrigger-V2.3-java", "android.hidl.manager-V1.2-java", "dnsresolver_aidl_interface-V2-java", diff --git a/services/core/java/android/content/pm/PackageManagerInternal.java b/services/core/java/android/content/pm/PackageManagerInternal.java index 40a7dfcfc18d..312dd46fbc73 100644 --- a/services/core/java/android/content/pm/PackageManagerInternal.java +++ b/services/core/java/android/content/pm/PackageManagerInternal.java @@ -319,6 +319,12 @@ public abstract class PackageManagerInternal { int deviceOwnerUserId, String deviceOwner, SparseArray<String> profileOwners); /** + * Called by DevicePolicyManagerService to set the package names protected by the device + * owner. + */ + public abstract void setDeviceOwnerProtectedPackages(List<String> packageNames); + + /** * Returns {@code true} if a given package can't be wiped. Otherwise, returns {@code false}. */ public abstract boolean isPackageDataProtected(int userId, String packageName); diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java index 25bad641adf9..3e6ccb572860 100644 --- a/services/core/java/com/android/server/TelephonyRegistry.java +++ b/services/core/java/com/android/server/TelephonyRegistry.java @@ -42,6 +42,7 @@ import android.os.Message; import android.os.RemoteException; import android.os.UserHandle; import android.telephony.Annotation; +import android.telephony.Annotation.ApnType; import android.telephony.Annotation.DataFailureCause; import android.telephony.Annotation.RadioPowerState; import android.telephony.Annotation.SrvccState; @@ -82,7 +83,6 @@ import com.android.internal.app.IBatteryStats; import com.android.internal.telephony.IOnSubscriptionsChangedListener; import com.android.internal.telephony.IPhoneStateListener; import com.android.internal.telephony.ITelephonyRegistry; -import com.android.internal.telephony.PhoneConstants; import com.android.internal.telephony.TelephonyIntents; import com.android.internal.telephony.TelephonyPermissions; import com.android.internal.util.ArrayUtils; @@ -269,8 +269,8 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { private final LocalLog mListenLog = new LocalLog(100); // Per-phoneMap of APN Type to DataConnectionState - private List<Map<String, PreciseDataConnectionState>> mPreciseDataConnectionStates = - new ArrayList<Map<String, PreciseDataConnectionState>>(); + private List<Map<Integer, PreciseDataConnectionState>> mPreciseDataConnectionStates = + new ArrayList<Map<Integer, PreciseDataConnectionState>>(); // Nothing here yet, but putting it here in case we want to add more in the future. static final int ENFORCE_COARSE_LOCATION_PERMISSION_MASK = 0; @@ -467,7 +467,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { mRingingCallState[i] = PreciseCallState.PRECISE_CALL_STATE_IDLE; mForegroundCallState[i] = PreciseCallState.PRECISE_CALL_STATE_IDLE; mBackgroundCallState[i] = PreciseCallState.PRECISE_CALL_STATE_IDLE; - mPreciseDataConnectionStates.add(new HashMap<String, PreciseDataConnectionState>()); + mPreciseDataConnectionStates.add(new HashMap<Integer, PreciseDataConnectionState>()); } } @@ -551,7 +551,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { mRingingCallState[i] = PreciseCallState.PRECISE_CALL_STATE_IDLE; mForegroundCallState[i] = PreciseCallState.PRECISE_CALL_STATE_IDLE; mBackgroundCallState[i] = PreciseCallState.PRECISE_CALL_STATE_IDLE; - mPreciseDataConnectionStates.add(new HashMap<String, PreciseDataConnectionState>()); + mPreciseDataConnectionStates.add(new HashMap<Integer, PreciseDataConnectionState>()); } mAppOps = mContext.getSystemService(AppOpsManager.class); @@ -1496,11 +1496,12 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { * * @param phoneId the phoneId carrying the data connection * @param subId the subscriptionId for the data connection - * @param apnType the APN type that triggered a change in the data connection + * @param apnType the apn type bitmask, defined with {@code ApnSetting#TYPE_*} flags. * @param preciseState a PreciseDataConnectionState that has info about the data connection */ + @Override public void notifyDataConnectionForSubscriber( - int phoneId, int subId, String apnType, PreciseDataConnectionState preciseState) { + int phoneId, int subId, @ApnType int apnType, PreciseDataConnectionState preciseState) { if (!checkNotifyPermission("notifyDataConnection()" )) { return; } @@ -1526,7 +1527,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { synchronized (mRecords) { if (validatePhoneId(phoneId)) { // We only call the callback when the change is for default APN type. - if (PhoneConstants.APN_TYPE_DEFAULT.equals(apnType) + if ((ApnSetting.TYPE_DEFAULT & apnType) != 0 && (mDataConnectionState[phoneId] != state || mDataConnectionNetworkType[phoneId] != networkType)) { String str = "onDataConnectionStateChanged(" @@ -1595,7 +1596,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { loge("This function should not be invoked"); } - private void notifyDataConnectionFailedForSubscriber(int phoneId, int subId, String apnType) { + private void notifyDataConnectionFailedForSubscriber(int phoneId, int subId, int apnType) { if (!checkNotifyPermission("notifyDataConnectionFailed()")) { return; } @@ -1610,7 +1611,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { new PreciseDataConnectionState( TelephonyManager.DATA_UNKNOWN, TelephonyManager.NETWORK_TYPE_UNKNOWN, - ApnSetting.getApnTypesBitmaskFromString(apnType), null, null, + apnType, null, null, DataFailCause.NONE, null)); for (Record r : mRecords) { if (r.matchPhoneStateListenerEvent( @@ -1779,7 +1780,8 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { } } - public void notifyPreciseDataConnectionFailed(int phoneId, int subId, String apnType, + @Override + public void notifyPreciseDataConnectionFailed(int phoneId, int subId, @ApnType int apnType, String apn, @DataFailureCause int failCause) { if (!checkNotifyPermission("notifyPreciseDataConnectionFailed()")) { return; @@ -1795,7 +1797,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { new PreciseDataConnectionState( TelephonyManager.DATA_UNKNOWN, TelephonyManager.NETWORK_TYPE_UNKNOWN, - ApnSetting.getApnTypesBitmaskFromString(apnType), null, null, + apnType, null, null, failCause, null)); for (Record r : mRecords) { if (r.matchPhoneStateListenerEvent( @@ -2177,10 +2179,19 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { /** Fired when a subscription's phone state changes. */ private static final String ACTION_SUBSCRIPTION_PHONE_STATE_CHANGED = "android.intent.action.SUBSCRIPTION_PHONE_STATE"; + /** + * Broadcast Action: The data connection state has changed for any one of the + * phone's mobile data connections (eg, default, MMS or GPS specific connection). + */ + private static final String ACTION_ANY_DATA_CONNECTION_STATE_CHANGED = + "android.intent.action.ANY_DATA_STATE"; // Legacy intent extra keys, copied from PhoneConstants. // Used in legacy intents sent here, for backward compatibility. + private static final String PHONE_CONSTANTS_DATA_APN_TYPE_KEY = "apnType"; + private static final String PHONE_CONSTANTS_DATA_APN_KEY = "apn"; private static final String PHONE_CONSTANTS_SLOT_KEY = "slot"; + private static final String PHONE_CONSTANTS_STATE_KEY = "state"; private static final String PHONE_CONSTANTS_SUBSCRIPTION_KEY = "subscription"; private void broadcastServiceStateChanged(ServiceState state, int phoneId, int subId) { @@ -2318,19 +2329,50 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { } private void broadcastDataConnectionStateChanged(int state, String apn, - String apnType, int subId) { + int apnType, int subId) { // Note: not reporting to the battery stats service here, because the // status bar takes care of that after taking into account all of the // required info. - Intent intent = new Intent(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED); - intent.putExtra(TelephonyManager.EXTRA_STATE, dataStateToString(state)); - - intent.putExtra(PhoneConstants.DATA_APN_KEY, apn); - intent.putExtra(PhoneConstants.DATA_APN_TYPE_KEY, apnType); + Intent intent = new Intent(ACTION_ANY_DATA_CONNECTION_STATE_CHANGED); + intent.putExtra(PHONE_CONSTANTS_STATE_KEY, dataStateToString(state)); + intent.putExtra(PHONE_CONSTANTS_DATA_APN_KEY, apn); + intent.putExtra(PHONE_CONSTANTS_DATA_APN_TYPE_KEY, getApnTypesStringFromBitmask(apnType)); intent.putExtra(PHONE_CONSTANTS_SUBSCRIPTION_KEY, subId); mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); } + private static final Map<Integer, String> APN_TYPE_INT_MAP; + static { + APN_TYPE_INT_MAP = new android.util.ArrayMap<Integer, String>(); + APN_TYPE_INT_MAP.put(ApnSetting.TYPE_DEFAULT, "default"); + APN_TYPE_INT_MAP.put(ApnSetting.TYPE_MMS, "mms"); + APN_TYPE_INT_MAP.put(ApnSetting.TYPE_SUPL, "supl"); + APN_TYPE_INT_MAP.put(ApnSetting.TYPE_DUN, "dun"); + APN_TYPE_INT_MAP.put(ApnSetting.TYPE_HIPRI, "hipri"); + APN_TYPE_INT_MAP.put(ApnSetting.TYPE_FOTA, "fota"); + APN_TYPE_INT_MAP.put(ApnSetting.TYPE_IMS, "ims"); + APN_TYPE_INT_MAP.put(ApnSetting.TYPE_CBS, "cbs"); + APN_TYPE_INT_MAP.put(ApnSetting.TYPE_IA, "ia"); + APN_TYPE_INT_MAP.put(ApnSetting.TYPE_EMERGENCY, "emergency"); + APN_TYPE_INT_MAP.put(ApnSetting.TYPE_MCX, "mcx"); + APN_TYPE_INT_MAP.put(ApnSetting.TYPE_XCAP, "xcap"); + } + + /** + * Copy of ApnSetting#getApnTypesStringFromBitmask for legacy broadcast. + * @param apnTypeBitmask bitmask of APN types. + * @return comma delimited list of APN types. + */ + private static String getApnTypesStringFromBitmask(int apnTypeBitmask) { + List<String> types = new ArrayList<>(); + for (Integer type : APN_TYPE_INT_MAP.keySet()) { + if ((apnTypeBitmask & type) == type) { + types.add(APN_TYPE_INT_MAP.get(type)); + } + } + return android.text.TextUtils.join(",", types); + } + private void enforceNotifyPermissionOrCarrierPrivilege(String method) { if (checkNotifyPermission()) { return; diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 4bc02978da91..c21adb08270e 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -18673,6 +18673,11 @@ public class ActivityManagerService extends IActivityManager.Stub } @Override + public void monitor() { + ActivityManagerService.this.monitor(); + } + + @Override public long inputDispatchingTimedOut(int pid, boolean aboveSystem, String reason) { synchronized (ActivityManagerService.this) { return ActivityManagerService.this.inputDispatchingTimedOut( diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java index 4546ea4b9ebc..7233f3465d5b 100644 --- a/services/core/java/com/android/server/locksettings/LockSettingsService.java +++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java @@ -20,6 +20,7 @@ import static android.Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE; import static android.Manifest.permission.READ_CONTACTS; import static android.content.Context.KEYGUARD_SERVICE; import static android.content.pm.PackageManager.PERMISSION_GRANTED; +import static android.os.UserHandle.USER_ALL; import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_NONE; import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSWORD; @@ -29,6 +30,7 @@ import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PIN; import static com.android.internal.widget.LockPatternUtils.EscrowTokenStateChangeCallback; import static com.android.internal.widget.LockPatternUtils.SYNTHETIC_PASSWORD_HANDLE_KEY; import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT; +import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_FOR_UNATTENDED_UPDATE; import static com.android.internal.widget.LockPatternUtils.USER_FRP; import static com.android.internal.widget.LockPatternUtils.frpCredentialEnabled; import static com.android.internal.widget.LockPatternUtils.userOwnsFrpCredential; @@ -118,6 +120,7 @@ import com.android.internal.widget.ILockSettings; import com.android.internal.widget.LockPatternUtils; import com.android.internal.widget.LockSettingsInternal; import com.android.internal.widget.LockscreenCredential; +import com.android.internal.widget.RebootEscrowListener; import com.android.internal.widget.VerifyCredentialResponse; import com.android.server.LocalServices; import com.android.server.ServiceThread; @@ -222,7 +225,10 @@ public class LockSettingsService extends ILockSettings.Stub { private final RecoverableKeyStoreManager mRecoverableKeyStoreManager; + private final RebootEscrowManager mRebootEscrowManager; + private boolean mFirstCallToVold; + // Current password metric for all users on the device. Updated when user unlocks // the device or changes password. Removed when user is stopped. @GuardedBy("this") @@ -483,6 +489,11 @@ public class LockSettingsService extends ILockSettings.Stub { new PasswordSlotManager()); } + public RebootEscrowManager getRebootEscrowManager(RebootEscrowManager.Callbacks callbacks, + LockSettingsStorage storage) { + return new RebootEscrowManager(mContext, callbacks, storage); + } + public boolean hasEnrolledBiometrics(int userId) { BiometricManager bm = mContext.getSystemService(BiometricManager.class); return bm.hasEnrolledBiometrics(userId); @@ -550,6 +561,9 @@ public class LockSettingsService extends ILockSettings.Stub { mSpManager = injector.getSyntheticPasswordManager(mStorage); + mRebootEscrowManager = injector.getRebootEscrowManager(new RebootEscrowCallbacks(), + mStorage); + LocalServices.addService(LockSettingsInternal.class, new LocalService()); } @@ -782,7 +796,14 @@ public class LockSettingsService extends ILockSettings.Stub { migrateOldData(); getGateKeeperService(); mSpManager.initWeaverService(); - // Find the AuthSecret HAL + getAuthSecretHal(); + mDeviceProvisionedObserver.onSystemReady(); + mRebootEscrowManager.loadRebootEscrowDataIfAvailable(); + // TODO: maybe skip this for split system user mode. + mStorage.prefetchUser(UserHandle.USER_SYSTEM); + } + + private void getAuthSecretHal() { try { mAuthSecretService = IAuthSecret.getService(); } catch (NoSuchElementException e) { @@ -790,9 +811,6 @@ public class LockSettingsService extends ILockSettings.Stub { } catch (RemoteException e) { Slog.w(TAG, "Failed to get AuthSecret HAL", e); } - mDeviceProvisionedObserver.onSystemReady(); - // TODO: maybe skip this for split system user mode. - mStorage.prefetchUser(UserHandle.USER_SYSTEM); } private void migrateOldData() { @@ -2466,10 +2484,18 @@ public class LockSettingsService extends ILockSettings.Stub { private void onAuthTokenKnownForUser(@UserIdInt int userId, AuthenticationToken auth) { if (mInjector.isGsiRunning()) { - Slog.w(TAG, "AuthSecret disabled in GSI"); + Slog.w(TAG, "Running in GSI; skipping calls to AuthSecret and RebootEscrow"); return; } + mRebootEscrowManager.callToRebootEscrowIfNeeded(userId, auth.getVersion(), + auth.getSyntheticPassword()); + + callToAuthSecretIfNeeded(userId, auth); + } + + private void callToAuthSecretIfNeeded(@UserIdInt int userId, + AuthenticationToken auth) { // Pass the primary user's auth secret to the HAL if (mAuthSecretService != null && mUserManager.getUserInfo(userId).isPrimary()) { try { @@ -3288,5 +3314,46 @@ public class LockSettingsService extends ILockSettings.Stub { return LockSettingsService.this.getUserPasswordMetrics(userHandle); } + @Override + public void prepareRebootEscrow() { + if (!mRebootEscrowManager.prepareRebootEscrow()) { + return; + } + mStrongAuth.requireStrongAuth(STRONG_AUTH_REQUIRED_FOR_UNATTENDED_UPDATE, USER_ALL); + } + + @Override + public void setRebootEscrowListener(RebootEscrowListener listener) { + mRebootEscrowManager.setRebootEscrowListener(listener); + } + + @Override + public void clearRebootEscrow() { + if (!mRebootEscrowManager.clearRebootEscrow()) { + return; + } + mStrongAuth.noLongerRequireStrongAuth(STRONG_AUTH_REQUIRED_FOR_UNATTENDED_UPDATE, + USER_ALL); + } + + @Override + public boolean armRebootEscrow() { + return mRebootEscrowManager.armRebootEscrowIfNeeded(); + } + } + + private class RebootEscrowCallbacks implements RebootEscrowManager.Callbacks { + @Override + public boolean isUserSecure(int userId) { + return LockSettingsService.this.isUserSecure(userId); + } + + @Override + public void onRebootEscrowRestored(byte spVersion, byte[] syntheticPassword, int userId) { + SyntheticPasswordManager.AuthenticationToken + authToken = new SyntheticPasswordManager.AuthenticationToken(spVersion); + authToken.recreateDirectly(syntheticPassword); + onCredentialVerified(authToken, CHALLENGE_NONE, 0, null, userId); + } } } diff --git a/services/core/java/com/android/server/locksettings/LockSettingsStorage.java b/services/core/java/com/android/server/locksettings/LockSettingsStorage.java index 3dab3ce7116c..fec0189377c8 100644 --- a/services/core/java/com/android/server/locksettings/LockSettingsStorage.java +++ b/services/core/java/com/android/server/locksettings/LockSettingsStorage.java @@ -81,6 +81,8 @@ class LockSettingsStorage { private static final String LOCK_PASSWORD_FILE = "gatekeeper.password.key"; private static final String CHILD_PROFILE_LOCK_FILE = "gatekeeper.profile.key"; + private static final String REBOOT_ESCROW_FILE = "reboot.escrow.key"; + private static final String SYNTHETIC_PASSWORD_DIRECTORY = "spblob/"; private static final Object DEFAULT = new Object(); @@ -261,6 +263,22 @@ class LockSettingsStorage { return hasFile(getChildProfileLockFile(userId)); } + public void writeRebootEscrow(int userId, byte[] rebootEscrow) { + writeFile(getRebootEscrowFile(userId), rebootEscrow); + } + + public byte[] readRebootEscrow(int userId) { + return readFile(getRebootEscrowFile(userId)); + } + + public boolean hasRebootEscrow(int userId) { + return hasFile(getRebootEscrowFile(userId)); + } + + public void removeRebootEscrow(int userId) { + deleteFile(getRebootEscrowFile(userId)); + } + public boolean hasPassword(int userId) { return hasFile(getLockPasswordFilename(userId)); } @@ -384,6 +402,11 @@ class LockSettingsStorage { return getLockCredentialFilePathForUser(userId, CHILD_PROFILE_LOCK_FILE); } + @VisibleForTesting + String getRebootEscrowFile(int userId) { + return getLockCredentialFilePathForUser(userId, REBOOT_ESCROW_FILE); + } + private String getLockCredentialFilePathForUser(int userId, String basename) { String dataSystemDirectory = Environment.getDataDirectory().getAbsolutePath() + SYSTEM_DIRECTORY; @@ -479,18 +502,10 @@ class LockSettingsStorage { if (parentInfo == null) { // This user owns its lock settings files - safe to delete them synchronized (mFileWriteLock) { - String name = getLockPasswordFilename(userId); - File file = new File(name); - if (file.exists()) { - file.delete(); - mCache.putFile(name, null); - } - name = getLockPatternFilename(userId); - file = new File(name); - if (file.exists()) { - file.delete(); - mCache.putFile(name, null); - } + deleteFilesAndRemoveCache( + getLockPasswordFilename(userId), + getLockPatternFilename(userId), + getRebootEscrowFile(userId)); } } else { // Managed profile @@ -512,6 +527,16 @@ class LockSettingsStorage { } } + private void deleteFilesAndRemoveCache(String... names) { + for (String name : names) { + File file = new File(name); + if (file.exists()) { + file.delete(); + mCache.putFile(name, null); + } + } + } + @VisibleForTesting void closeDatabase() { mOpenHelper.close(); diff --git a/services/core/java/com/android/server/locksettings/LockSettingsStrongAuth.java b/services/core/java/com/android/server/locksettings/LockSettingsStrongAuth.java index a84306c97dc0..91cf53ee9a1f 100644 --- a/services/core/java/com/android/server/locksettings/LockSettingsStrongAuth.java +++ b/services/core/java/com/android/server/locksettings/LockSettingsStrongAuth.java @@ -16,10 +16,8 @@ package com.android.server.locksettings; -import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker - .STRONG_AUTH_NOT_REQUIRED; -import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker - .STRONG_AUTH_REQUIRED_AFTER_TIMEOUT; +import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_NOT_REQUIRED; +import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_TIMEOUT; import android.app.AlarmManager; import android.app.AlarmManager.OnAlarmListener; @@ -50,6 +48,7 @@ public class LockSettingsStrongAuth { private static final int MSG_UNREGISTER_TRACKER = 3; private static final int MSG_REMOVE_USER = 4; private static final int MSG_SCHEDULE_STRONG_AUTH_TIMEOUT = 5; + private static final int MSG_NO_LONGER_REQUIRE_STRONG_AUTH = 6; private static final String STRONG_AUTH_TIMEOUT_ALARM_TAG = "LockSettingsStrongAuth.timeoutForUser"; @@ -109,6 +108,26 @@ public class LockSettingsStrongAuth { } } + private void handleNoLongerRequireStrongAuth(int strongAuthReason, int userId) { + if (userId == UserHandle.USER_ALL) { + for (int i = 0; i < mStrongAuthForUser.size(); i++) { + int key = mStrongAuthForUser.keyAt(i); + handleNoLongerRequireStrongAuthOneUser(strongAuthReason, key); + } + } else { + handleNoLongerRequireStrongAuthOneUser(strongAuthReason, userId); + } + } + + private void handleNoLongerRequireStrongAuthOneUser(int strongAuthReason, int userId) { + int oldValue = mStrongAuthForUser.get(userId, mDefaultStrongAuthFlags); + int newValue = oldValue & ~strongAuthReason; + if (oldValue != newValue) { + mStrongAuthForUser.put(userId, newValue); + notifyStrongAuthTrackers(newValue, userId); + } + } + private void handleRemoveUser(int userId) { int index = mStrongAuthForUser.indexOfKey(userId); if (index >= 0) { @@ -174,6 +193,16 @@ public class LockSettingsStrongAuth { } } + void noLongerRequireStrongAuth(int strongAuthReason, int userId) { + if (userId == UserHandle.USER_ALL || userId >= UserHandle.USER_SYSTEM) { + mHandler.obtainMessage(MSG_NO_LONGER_REQUIRE_STRONG_AUTH, strongAuthReason, + userId).sendToTarget(); + } else { + throw new IllegalArgumentException( + "userId must be an explicit user id or USER_ALL"); + } + } + public void reportUnlock(int userId) { requireStrongAuth(STRONG_AUTH_NOT_REQUIRED, userId); } @@ -216,6 +245,9 @@ public class LockSettingsStrongAuth { case MSG_SCHEDULE_STRONG_AUTH_TIMEOUT: handleScheduleStrongAuthTimeout(msg.arg1); break; + case MSG_NO_LONGER_REQUIRE_STRONG_AUTH: + handleNoLongerRequireStrongAuth(msg.arg1, msg.arg2); + break; } } }; diff --git a/services/core/java/com/android/server/locksettings/RebootEscrowData.java b/services/core/java/com/android/server/locksettings/RebootEscrowData.java new file mode 100644 index 000000000000..aee608e8a544 --- /dev/null +++ b/services/core/java/com/android/server/locksettings/RebootEscrowData.java @@ -0,0 +1,178 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.locksettings; + +import com.android.internal.util.Preconditions; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; + +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.KeyGenerator; +import javax.crypto.NoSuchPaddingException; +import javax.crypto.SecretKey; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; + +/** + * Holds the data necessary to complete a reboot escrow of the Synthetic Password. + */ +class RebootEscrowData { + /** + * This is the current version of the escrow data format. This should be incremented if the + * format on disk is changed. + */ + private static final int CURRENT_VERSION = 1; + + /** The secret key will be of this format. */ + private static final String KEY_ALGO = "AES"; + + /** The key size used for encrypting the reboot escrow data. */ + private static final int KEY_SIZE_BITS = 256; + + /** The algorithm used for the encryption of the key blob. */ + private static final String CIPHER_ALGO = "AES/GCM/NoPadding"; + + private RebootEscrowData(byte spVersion, byte[] iv, byte[] syntheticPassword, byte[] blob, + byte[] key) { + mSpVersion = spVersion; + mIv = iv; + mSyntheticPassword = syntheticPassword; + mBlob = blob; + mKey = key; + } + + private final byte mSpVersion; + private final byte[] mIv; + private final byte[] mSyntheticPassword; + private final byte[] mBlob; + private final byte[] mKey; + + public byte getSpVersion() { + return mSpVersion; + } + + public byte[] getIv() { + return mIv; + } + + public byte[] getSyntheticPassword() { + return mSyntheticPassword; + } + + public byte[] getBlob() { + return mBlob; + } + + public byte[] getKey() { + return mKey; + } + + static SecretKeySpec fromKeyBytes(byte[] keyBytes) { + return new SecretKeySpec(keyBytes, KEY_ALGO); + } + + static RebootEscrowData fromEncryptedData(SecretKeySpec keySpec, byte[] blob) + throws IOException { + Preconditions.checkNotNull(keySpec); + Preconditions.checkNotNull(blob); + + DataInputStream dis = new DataInputStream(new ByteArrayInputStream(blob)); + int version = dis.readInt(); + if (version != CURRENT_VERSION) { + throw new IOException("Unsupported version " + version); + } + + byte spVersion = dis.readByte(); + + int ivSize = dis.readInt(); + if (ivSize < 0 || ivSize > 32) { + throw new IOException("IV out of range: " + ivSize); + } + byte[] iv = new byte[ivSize]; + dis.readFully(iv); + + int cipherTextSize = dis.readInt(); + if (cipherTextSize < 0) { + throw new IOException("Invalid cipher text size: " + cipherTextSize); + } + + byte[] cipherText = new byte[cipherTextSize]; + dis.readFully(cipherText); + + final byte[] syntheticPassword; + try { + Cipher c = Cipher.getInstance(CIPHER_ALGO); + c.init(Cipher.DECRYPT_MODE, keySpec, new IvParameterSpec(iv)); + syntheticPassword = c.doFinal(cipherText); + } catch (NoSuchAlgorithmException | InvalidKeyException | BadPaddingException + | IllegalBlockSizeException | NoSuchPaddingException + | InvalidAlgorithmParameterException e) { + throw new IOException("Could not decrypt ciphertext", e); + } + + return new RebootEscrowData(spVersion, iv, syntheticPassword, blob, keySpec.getEncoded()); + } + + static RebootEscrowData fromSyntheticPassword(byte spVersion, byte[] syntheticPassword) + throws IOException { + Preconditions.checkNotNull(syntheticPassword); + + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + DataOutputStream dos = new DataOutputStream(bos); + + final SecretKey secretKey; + try { + KeyGenerator keyGenerator = KeyGenerator.getInstance(KEY_ALGO); + keyGenerator.init(KEY_SIZE_BITS, new SecureRandom()); + secretKey = keyGenerator.generateKey(); + } catch (NoSuchAlgorithmException e) { + throw new IOException("Could not generate new secret key", e); + } + + final byte[] cipherText; + final byte[] iv; + try { + Cipher cipher = Cipher.getInstance(CIPHER_ALGO); + cipher.init(Cipher.ENCRYPT_MODE, secretKey); + cipherText = cipher.doFinal(syntheticPassword); + iv = cipher.getIV(); + } catch (NoSuchAlgorithmException | BadPaddingException | IllegalBlockSizeException + | NoSuchPaddingException | InvalidKeyException e) { + throw new IOException("Could not encrypt reboot escrow data", e); + } + + dos.writeInt(CURRENT_VERSION); + dos.writeByte(spVersion); + dos.writeInt(iv.length); + dos.write(iv); + dos.writeInt(cipherText.length); + dos.write(cipherText); + + return new RebootEscrowData(spVersion, iv, syntheticPassword, bos.toByteArray(), + secretKey.getEncoded()); + } +} diff --git a/services/core/java/com/android/server/locksettings/RebootEscrowManager.java b/services/core/java/com/android/server/locksettings/RebootEscrowManager.java new file mode 100644 index 000000000000..d2e54f9cd64c --- /dev/null +++ b/services/core/java/com/android/server/locksettings/RebootEscrowManager.java @@ -0,0 +1,275 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.locksettings; + +import android.annotation.Nullable; +import android.annotation.UserIdInt; +import android.content.Context; +import android.content.pm.UserInfo; +import android.hardware.rebootescrow.IRebootEscrow; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.os.UserManager; +import android.util.Slog; + +import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.widget.RebootEscrowListener; + +import java.io.IOException; +import java.util.List; +import java.util.NoSuchElementException; +import java.util.concurrent.atomic.AtomicBoolean; + +import javax.crypto.spec.SecretKeySpec; + +class RebootEscrowManager { + private static final String TAG = "RebootEscrowManager"; + + /** + * Used to track when the reboot escrow is wanted. Set to false when mRebootEscrowReady is + * true. + */ + private final AtomicBoolean mRebootEscrowWanted = new AtomicBoolean(false); + + /** Used to track when reboot escrow is ready. */ + private boolean mRebootEscrowReady; + + /** Notified when mRebootEscrowReady changes. */ + private RebootEscrowListener mRebootEscrowListener; + + /** + * Stores the reboot escrow data between when it's supplied and when + * {@link #armRebootEscrowIfNeeded()} is called. + */ + private RebootEscrowData mPendingRebootEscrowData; + + private final UserManager mUserManager; + + private final Injector mInjector; + + private final LockSettingsStorage mStorage; + + private final Callbacks mCallbacks; + + interface Callbacks { + boolean isUserSecure(int userId); + void onRebootEscrowRestored(byte spVersion, byte[] syntheticPassword, int userId); + } + + static class Injector { + protected Context mContext; + + Injector(Context context) { + mContext = context; + } + + public Context getContext() { + return mContext; + } + public UserManager getUserManager() { + return (UserManager) mContext.getSystemService(Context.USER_SERVICE); + } + + public @Nullable IRebootEscrow getRebootEscrow() { + try { + return IRebootEscrow.Stub.asInterface(ServiceManager.getService( + "android.hardware.rebootescrow.IRebootEscrow/default")); + } catch (NoSuchElementException e) { + Slog.i(TAG, "Device doesn't implement RebootEscrow HAL"); + } + return null; + } + } + + RebootEscrowManager(Context context, Callbacks callbacks, LockSettingsStorage storage) { + this(new Injector(context), callbacks, storage); + } + + @VisibleForTesting + RebootEscrowManager(Injector injector, Callbacks callbacks, + LockSettingsStorage storage) { + mInjector = injector; + mCallbacks = callbacks; + mStorage = storage; + mUserManager = injector.getUserManager(); + } + + void loadRebootEscrowDataIfAvailable() { + IRebootEscrow rebootEscrow = mInjector.getRebootEscrow(); + if (rebootEscrow == null) { + return; + } + + final SecretKeySpec escrowKey; + try { + byte[] escrowKeyBytes = rebootEscrow.retrieveKey(); + if (escrowKeyBytes == null) { + return; + } else if (escrowKeyBytes.length != 32) { + Slog.e(TAG, "IRebootEscrow returned key of incorrect size " + + escrowKeyBytes.length); + return; + } + + // Make sure we didn't get the null key. + int zero = 0; + for (int i = 0; i < escrowKeyBytes.length; i++) { + zero |= escrowKeyBytes[i]; + } + if (zero == 0) { + Slog.w(TAG, "IRebootEscrow returned an all-zeroes key"); + return; + } + + // Overwrite the existing key with the null key + rebootEscrow.storeKey(new byte[32]); + + escrowKey = RebootEscrowData.fromKeyBytes(escrowKeyBytes); + } catch (RemoteException e) { + Slog.w(TAG, "Could not retrieve escrow data"); + return; + } + + List<UserInfo> users = mUserManager.getUsers(); + for (UserInfo user : users) { + if (mCallbacks.isUserSecure(user.id)) { + restoreRebootEscrowForUser(user.id, escrowKey); + } + } + } + + private void restoreRebootEscrowForUser(@UserIdInt int userId, SecretKeySpec escrowKey) { + if (!mStorage.hasRebootEscrow(userId)) { + return; + } + + try { + byte[] blob = mStorage.readRebootEscrow(userId); + mStorage.removeRebootEscrow(userId); + + RebootEscrowData escrowData = RebootEscrowData.fromEncryptedData(escrowKey, blob); + + mCallbacks.onRebootEscrowRestored(escrowData.getSpVersion(), + escrowData.getSyntheticPassword(), userId); + } catch (IOException e) { + Slog.w(TAG, "Could not load reboot escrow data for user " + userId, e); + } + } + + void callToRebootEscrowIfNeeded(@UserIdInt int userId, byte spVersion, + byte[] syntheticPassword) { + if (!mRebootEscrowWanted.compareAndSet(true, false)) { + return; + } + + IRebootEscrow rebootEscrow = mInjector.getRebootEscrow(); + if (rebootEscrow == null) { + setRebootEscrowReady(false); + return; + } + + final RebootEscrowData escrowData; + try { + escrowData = RebootEscrowData.fromSyntheticPassword(spVersion, syntheticPassword); + } catch (IOException e) { + setRebootEscrowReady(false); + Slog.w(TAG, "Could not escrow reboot data", e); + return; + } + + mPendingRebootEscrowData = escrowData; + mStorage.writeRebootEscrow(userId, escrowData.getBlob()); + + setRebootEscrowReady(true); + } + + private void clearRebootEscrowIfNeeded() { + mRebootEscrowWanted.set(false); + setRebootEscrowReady(false); + + IRebootEscrow rebootEscrow = mInjector.getRebootEscrow(); + if (rebootEscrow == null) { + return; + } + + try { + rebootEscrow.storeKey(new byte[32]); + } catch (RemoteException e) { + Slog.w(TAG, "Could not call RebootEscrow HAL to shred key"); + } + + List<UserInfo> users = mUserManager.getUsers(); + for (UserInfo user : users) { + mStorage.removeRebootEscrow(user.id); + } + } + + boolean armRebootEscrowIfNeeded() { + if (!mRebootEscrowReady) { + return false; + } + + IRebootEscrow rebootEscrow = mInjector.getRebootEscrow(); + if (rebootEscrow == null) { + return false; + } + + RebootEscrowData escrowData = mPendingRebootEscrowData; + if (escrowData == null) { + return false; + } + + boolean armedRebootEscrow = false; + try { + rebootEscrow.storeKey(escrowData.getKey()); + armedRebootEscrow = true; + } catch (RemoteException e) { + Slog.w(TAG, "Failed escrow secret to RebootEscrow HAL", e); + } + return armedRebootEscrow; + } + + private void setRebootEscrowReady(boolean ready) { + if (mRebootEscrowReady != ready) { + mRebootEscrowListener.onPreparedForReboot(ready); + } + mRebootEscrowReady = ready; + } + + boolean prepareRebootEscrow() { + if (mInjector.getRebootEscrow() == null) { + return false; + } + + clearRebootEscrowIfNeeded(); + mRebootEscrowWanted.set(true); + return true; + } + + boolean clearRebootEscrow() { + if (mInjector.getRebootEscrow() == null) { + return false; + } + + clearRebootEscrowIfNeeded(); + return true; + } + + void setRebootEscrowListener(RebootEscrowListener listener) { + mRebootEscrowListener = listener; + } +} diff --git a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java index 0fe16be2188e..b726e571cf0c 100644 --- a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java +++ b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java @@ -38,7 +38,6 @@ import android.util.Slog; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.ArrayUtils; -import com.android.internal.util.Preconditions; import com.android.internal.widget.ICheckCredentialProgressCallback; import com.android.internal.widget.LockPatternUtils; import com.android.internal.widget.LockscreenCredential; @@ -285,6 +284,14 @@ public class SyntheticPasswordManager { public byte[] getSyntheticPassword() { return mSyntheticPassword; } + + /** + * Returns the version of this AuthenticationToken for use with reconstructing + * this with a synthetic password version. + */ + public byte getVersion() { + return mVersion; + } } static class PasswordData { diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java index 22ba1bf1a851..562a7200fb38 100644 --- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java +++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java @@ -79,7 +79,6 @@ class MediaRouter2ServiceImpl { @GuardedBy("mLock") private int mCurrentUserId = -1; - MediaRouter2ServiceImpl(Context context) { mContext = context; } @@ -89,17 +88,23 @@ class MediaRouter2ServiceImpl { final int uid = Binder.getCallingUid(); final int userId = UserHandle.getUserId(uid); - Collection<MediaRoute2Info> systemRoutes; - synchronized (mLock) { - UserRecord userRecord = mUserRecords.get(userId); - if (userRecord == null) { - userRecord = new UserRecord(userId); - mUserRecords.put(userId, userRecord); - initializeUserLocked(userRecord); + final long token = Binder.clearCallingIdentity(); + try { + Collection<MediaRoute2Info> systemRoutes; + synchronized (mLock) { + UserRecord userRecord = getOrCreateUserRecordLocked(userId); + MediaRoute2ProviderInfo providerInfo = + userRecord.mHandler.mSystemProvider.getProviderInfo(); + if (providerInfo != null) { + systemRoutes = providerInfo.getRoutes(); + } else { + systemRoutes = Collections.emptyList(); + } } - systemRoutes = userRecord.mHandler.mSystemProvider.getProviderInfo().getRoutes(); + return new ArrayList<>(systemRoutes); + } finally { + Binder.restoreCallingIdentity(token); } - return new ArrayList<>(systemRoutes); } public void registerClient(@NonNull IMediaRouter2Client client, @@ -400,12 +405,7 @@ class MediaRouter2ServiceImpl { int uid, int pid, String packageName, int userId, boolean trusted) { final IBinder binder = client.asBinder(); if (mAllClientRecords.get(binder) == null) { - UserRecord userRecord = mUserRecords.get(userId); - if (userRecord == null) { - userRecord = new UserRecord(userId); - mUserRecords.put(userId, userRecord); - initializeUserLocked(userRecord); - } + UserRecord userRecord = getOrCreateUserRecordLocked(userId); Client2Record clientRecord = new Client2Record(userRecord, client, uid, pid, packageName, trusted); try { @@ -556,12 +556,7 @@ class MediaRouter2ServiceImpl { final IBinder binder = manager.asBinder(); ManagerRecord managerRecord = mAllManagerRecords.get(binder); if (managerRecord == null) { - boolean newUser = false; - UserRecord userRecord = mUserRecords.get(userId); - if (userRecord == null) { - userRecord = new UserRecord(userId); - newUser = true; - } + UserRecord userRecord = getOrCreateUserRecordLocked(userId); managerRecord = new ManagerRecord(userRecord, manager, uid, pid, packageName, trusted); try { binder.linkToDeath(managerRecord, 0); @@ -569,11 +564,6 @@ class MediaRouter2ServiceImpl { throw new RuntimeException("Media router manager died prematurely.", ex); } - if (newUser) { - mUserRecords.put(userId, userRecord); - initializeUserLocked(userRecord); - } - userRecord.mManagerRecords.add(managerRecord); mAllManagerRecords.put(binder, managerRecord); @@ -661,14 +651,17 @@ class MediaRouter2ServiceImpl { return sessionInfos; } - private void initializeUserLocked(UserRecord userRecord) { - if (DEBUG) { - Slog.d(TAG, userRecord + ": Initialized"); - } - if (userRecord.mUserId == mCurrentUserId) { - userRecord.mHandler.sendMessage( - obtainMessage(UserHandler::start, userRecord.mHandler)); + private UserRecord getOrCreateUserRecordLocked(int userId) { + UserRecord userRecord = mUserRecords.get(userId); + if (userRecord == null) { + userRecord = new UserRecord(userId); + mUserRecords.put(userId, userRecord); + if (userId == mCurrentUserId) { + userRecord.mHandler.sendMessage( + obtainMessage(UserHandler::start, userRecord.mHandler)); + } } + return userRecord; } private void disposeUserIfNeededLocked(UserRecord userRecord) { diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index f42f4f7c5c61..a4f4d079df27 100755 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -236,7 +236,6 @@ import com.android.internal.util.ArrayUtils; import com.android.internal.util.CollectionUtils; import com.android.internal.util.DumpUtils; import com.android.internal.util.FastXmlSerializer; -import com.android.internal.util.Preconditions; import com.android.internal.util.XmlUtils; import com.android.internal.util.function.TriPredicate; import com.android.server.DeviceIdleInternal; @@ -1182,21 +1181,14 @@ public class NotificationManagerService extends SystemService { @Override public void onNotificationBubbleChanged(String key, boolean isBubble) { - String pkg; - synchronized (mNotificationLock) { - NotificationRecord r = mNotificationsByKey.get(key); - pkg = r != null && r.sbn != null ? r.sbn.getPackageName() : null; - } - boolean isAppForeground = pkg != null - && mActivityManager.getPackageImportance(pkg) == IMPORTANCE_FOREGROUND; synchronized (mNotificationLock) { NotificationRecord r = mNotificationsByKey.get(key); if (r != null) { final StatusBarNotification n = r.sbn; final int callingUid = n.getUid(); - pkg = n.getPackageName(); + final String pkg = n.getPackageName(); if (isBubble && isNotificationAppropriateToBubble(r, pkg, callingUid, - null /* oldEntry */, isAppForeground)) { + null /* oldEntry */)) { r.getNotification().flags |= FLAG_BUBBLE; } else { r.getNotification().flags &= ~FLAG_BUBBLE; @@ -5386,7 +5378,7 @@ public class NotificationManagerService extends SystemService { private void flagNotificationForBubbles(NotificationRecord r, String pkg, int userId, NotificationRecord oldRecord, boolean isAppForeground) { Notification notification = r.getNotification(); - if (isNotificationAppropriateToBubble(r, pkg, userId, oldRecord, isAppForeground)) { + if (isNotificationAppropriateToBubble(r, pkg, userId, oldRecord)) { notification.flags |= FLAG_BUBBLE; } else { notification.flags &= ~FLAG_BUBBLE; @@ -5406,7 +5398,7 @@ public class NotificationManagerService extends SystemService { * accounting for user choice & policy. */ private boolean isNotificationAppropriateToBubble(NotificationRecord r, String pkg, int userId, - NotificationRecord oldRecord, boolean isAppForeground) { + NotificationRecord oldRecord) { Notification notification = r.getNotification(); if (!canBubble(r, pkg, userId)) { // no log: canBubble has its own @@ -5418,11 +5410,6 @@ public class NotificationManagerService extends SystemService { return false; } - if (isAppForeground) { - // If the app is foreground it always gets to bubble - return true; - } - if (oldRecord != null && (oldRecord.getNotification().flags & FLAG_BUBBLE) != 0) { // This is an update to an active bubble return true; @@ -5438,7 +5425,7 @@ public class NotificationManagerService extends SystemService { boolean isMessageStyle = Notification.MessagingStyle.class.equals( notification.getNotificationStyle()); if (!isMessageStyle && (peopleList == null || peopleList.isEmpty())) { - logBubbleError(r.getKey(), "if not foreground, must have a person and be " + logBubbleError(r.getKey(), "Must have a person and be " + "Notification.MessageStyle or Notification.CATEGORY_CALL"); return false; } @@ -5446,6 +5433,11 @@ public class NotificationManagerService extends SystemService { // Communication is a message or a call boolean isCall = CATEGORY_CALL.equals(notification.category); boolean hasForegroundService = (notification.flags & FLAG_FOREGROUND_SERVICE) != 0; + if (hasForegroundService && !isCall) { + logBubbleError(r.getKey(), + "foreground services must be Notification.CATEGORY_CALL to bubble"); + return false; + } if (isMessageStyle) { if (hasValidRemoteInput(notification)) { return true; @@ -5459,7 +5451,7 @@ public class NotificationManagerService extends SystemService { logBubbleError(r.getKey(), "calls require foreground service"); return false; } - logBubbleError(r.getKey(), "if not foreground, must be " + logBubbleError(r.getKey(), "Must be " + "Notification.MessageStyle or Notification.CATEGORY_CALL"); return false; } diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java index f1947ac15645..b782ca96ae88 100644 --- a/services/core/java/com/android/server/om/OverlayManagerService.java +++ b/services/core/java/com/android/server/om/OverlayManagerService.java @@ -1154,6 +1154,10 @@ public final class OverlayManagerService extends SystemService { throws RemoteException, IOException { PackageInfo packageInfo = mPackageManager.getPackageInfo(targetPackageName, 0, userId); + if (packageInfo == null) { + throw new IOException("Unable to get target package"); + } + String baseCodePath = packageInfo.applicationInfo.getBaseCodePath(); ApkAssets apkAssets = null; diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 04e7372a92a7..6bd9c4847a77 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -13452,9 +13452,7 @@ public class PackageManagerService extends IPackageManager.Stub // Okay! targetPackageSetting.setInstallerPackageName(installerPackageName); - if (installerPackageName != null) { - mSettings.mInstallerPackages.add(installerPackageName); - } + mSettings.addInstallerPackageNames(targetPackageSetting.installSource); scheduleWriteSettingsLocked(); } } @@ -15160,7 +15158,8 @@ public class PackageManagerService extends IPackageManager.Stub Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "updateSettings"); final String pkgName = pkg.getPackageName(); - final String installerPackageName = installArgs.installSource.installerPackageName; + final InstallSource installSource = installArgs.installSource; + final String installerPackageName = installSource.installerPackageName; final int[] installedForUsers = res.origUsers; final int installReason = installArgs.installReason; @@ -15171,7 +15170,7 @@ public class PackageManagerService extends IPackageManager.Stub // For system-bundled packages, we assume that installing an upgraded version // of the package implies that the user actually wants to run that new code, // so we enable the package. - PackageSetting ps = mSettings.mPackages.get(pkgName); + final PackageSetting ps = mSettings.mPackages.get(pkgName); final int userId = installArgs.user.getIdentifier(); if (ps != null) { if (isSystemApp(pkg)) { @@ -15208,8 +15207,8 @@ public class PackageManagerService extends IPackageManager.Stub ps.setEnabled(COMPONENT_ENABLED_STATE_DEFAULT, userId, installerPackageName); } - ps.setInstallSource(installArgs.installSource); - + ps.setInstallSource(installSource); + mSettings.addInstallerPackageNames(installSource); // When replacing an existing package, preserve the original install reason for all // users that had the package installed before. @@ -15239,7 +15238,6 @@ public class PackageManagerService extends IPackageManager.Stub res.name = pkgName; res.uid = pkg.getUid(); res.pkg = pkg; - mSettings.setInstallerPackageName(pkgName, installerPackageName); res.setReturnCode(PackageManager.INSTALL_SUCCEEDED); //to update install status Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "writeSettings"); @@ -23057,6 +23055,11 @@ public class PackageManagerService extends IPackageManager.Stub } @Override + public void setDeviceOwnerProtectedPackages(List<String> packageNames) { + mProtectedPackages.setDeviceOwnerProtectedPackages(packageNames); + } + + @Override public boolean isPackageDataProtected(int userId, String packageName) { return mProtectedPackages.isPackageDataProtected(userId, packageName); } diff --git a/services/core/java/com/android/server/pm/ProtectedPackages.java b/services/core/java/com/android/server/pm/ProtectedPackages.java index 231168e9c660..4da3cc3be514 100644 --- a/services/core/java/com/android/server/pm/ProtectedPackages.java +++ b/services/core/java/com/android/server/pm/ProtectedPackages.java @@ -24,6 +24,10 @@ import android.util.SparseArray; import com.android.internal.R; import com.android.internal.annotations.GuardedBy; +import com.android.internal.util.ArrayUtils; + +import java.util.ArrayList; +import java.util.List; /** * Manages package names that need special protection. @@ -49,6 +53,10 @@ public class ProtectedPackages { @GuardedBy("this") private final String mDeviceProvisioningPackage; + @Nullable + @GuardedBy("this") + private List<String> mDeviceOwnerProtectedPackages; + private final Context mContext; public ProtectedPackages(Context context) { @@ -70,6 +78,10 @@ public class ProtectedPackages { : profileOwnerPackages.clone(); } + public synchronized void setDeviceOwnerProtectedPackages(List<String> packageNames) { + mDeviceOwnerProtectedPackages = new ArrayList<String>(packageNames); + } + private synchronized boolean hasDeviceOwnerOrProfileOwner(int userId, String packageName) { if (packageName == null) { return false; @@ -105,7 +117,8 @@ public class ProtectedPackages { * can modify its data or package state. */ private synchronized boolean isProtectedPackage(String packageName) { - return packageName != null && packageName.equals(mDeviceProvisioningPackage); + return packageName != null && (packageName.equals(mDeviceProvisioningPackage) + || ArrayUtils.contains(mDeviceOwnerProtectedPackages, packageName)); } /** diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java index 9642a1a21cf3..f9a336166825 100644 --- a/services/core/java/com/android/server/pm/Settings.java +++ b/services/core/java/com/android/server/pm/Settings.java @@ -280,8 +280,11 @@ public final class Settings { /** Map from package name to settings */ final ArrayMap<String, PackageSetting> mPackages = new ArrayMap<>(); - /** List of packages that installed other packages */ - final ArraySet<String> mInstallerPackages = new ArraySet<>(); + /** + * List of packages that were involved in installing other packages, i.e. are listed + * in at least one app's InstallSource. + */ + private final ArraySet<String> mInstallerPackages = new ArraySet<>(); /** Map from package name to appId and excluded userids */ private final ArrayMap<String, KernelPackageState> mKernelMapping = new ArrayMap<>(); @@ -441,16 +444,6 @@ public final class Settings { return mPermissions.canPropagatePermissionToInstantApp(permName); } - void setInstallerPackageName(String pkgName, String installerPkgName) { - PackageSetting p = mPackages.get(pkgName); - if (p != null) { - p.setInstallerPackageName(installerPkgName); - if (installerPkgName != null) { - mInstallerPackages.add(installerPkgName); - } - } - } - /** Gets and optionally creates a new shared user id. */ SharedUserSetting getSharedUserLPw(String name, int pkgFlags, int pkgPrivateFlags, boolean create) throws PackageManagerException { @@ -3777,9 +3770,10 @@ public final class Settings { } if (packageSetting != null) { packageSetting.uidError = "true".equals(uidError); - packageSetting.installSource = InstallSource.create( + InstallSource installSource = InstallSource.create( installInitiatingPackageName, installOriginatingPackageName, installerPackageName, "true".equals(isOrphaned)); + packageSetting.installSource = installSource; packageSetting.volumeUuid = volumeUuid; packageSetting.categoryHint = categoryHint; packageSetting.legacyNativeLibraryPathString = legacyNativeLibraryPathStr; @@ -3809,9 +3803,7 @@ public final class Settings { packageSetting.setEnabled(COMPONENT_ENABLED_STATE_DEFAULT, 0, null); } - if (installerPackageName != null) { - mInstallerPackages.add(installerPackageName); - } + addInstallerPackageNames(installSource); int outerDepth = parser.getDepth(); int type; @@ -3870,6 +3862,18 @@ public final class Settings { } } + void addInstallerPackageNames(InstallSource installSource) { + if (installSource.installerPackageName != null) { + mInstallerPackages.add(installSource.installerPackageName); + } + if (installSource.initiatingPackageName != null) { + mInstallerPackages.add(installSource.initiatingPackageName); + } + if (installSource.originatingPackageName != null) { + mInstallerPackages.add(installSource.originatingPackageName); + } + } + private void readDisabledComponentsLPw(PackageSettingBase packageSetting, XmlPullParser parser, int userId) throws IOException, XmlPullParserException { int outerDepth = parser.getDepth(); diff --git a/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java b/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java index fdb14be6b1a4..c36d5ef0415c 100644 --- a/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java +++ b/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java @@ -17,8 +17,10 @@ package com.android.server.recoverysystem; import android.content.Context; +import android.content.IntentSender; import android.net.LocalSocket; import android.net.LocalSocketAddress; +import android.os.Binder; import android.os.IRecoverySystem; import android.os.IRecoverySystemProgressListener; import android.os.PowerManager; @@ -28,6 +30,9 @@ import android.os.SystemProperties; import android.util.Slog; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.widget.LockSettingsInternal; +import com.android.internal.widget.RebootEscrowListener; +import com.android.server.LocalServices; import com.android.server.SystemService; import libcore.io.IoUtils; @@ -45,7 +50,7 @@ import java.nio.charset.StandardCharsets; * triggers /system/bin/uncrypt via init to de-encrypt an OTA package on the * /data partition so that it can be accessed under the recovery image. */ -public class RecoverySystemService extends IRecoverySystem.Stub { +public class RecoverySystemService extends IRecoverySystem.Stub implements RebootEscrowListener { private static final String TAG = "RecoverySystemService"; private static final boolean DEBUG = false; @@ -67,6 +72,10 @@ public class RecoverySystemService extends IRecoverySystem.Stub { private final Injector mInjector; private final Context mContext; + private boolean mPreparedForReboot; + private String mUnattendedRebootToken; + private IntentSender mPreparedForRebootIntentSender; + static class Injector { protected final Context mContext; @@ -78,6 +87,10 @@ public class RecoverySystemService extends IRecoverySystem.Stub { return mContext; } + public LockSettingsInternal getLockSettingsService() { + return LocalServices.getService(LockSettingsInternal.class); + } + public PowerManager getPowerManager() { return (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); } @@ -120,14 +133,23 @@ public class RecoverySystemService extends IRecoverySystem.Stub { * Handles the lifecycle events for the RecoverySystemService. */ public static final class Lifecycle extends SystemService { + private RecoverySystemService mRecoverySystemService; + public Lifecycle(Context context) { super(context); } @Override + public void onBootPhase(int phase) { + if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) { + mRecoverySystemService.onSystemServicesReady(); + } + } + + @Override public void onStart() { - RecoverySystemService recoverySystemService = new RecoverySystemService(getContext()); - publishBinderService(Context.RECOVERY_SERVICE, recoverySystemService); + mRecoverySystemService = new RecoverySystemService(getContext()); + publishBinderService(Context.RECOVERY_SERVICE, mRecoverySystemService); } } @@ -141,6 +163,11 @@ public class RecoverySystemService extends IRecoverySystem.Stub { mContext = injector.getContext(); } + @VisibleForTesting + void onSystemServicesReady() { + mInjector.getLockSettingsService().setRebootEscrowListener(this); + } + @Override // Binder call public boolean uncrypt(String filename, IRecoverySystemProgressListener listener) { if (DEBUG) Slog.d(TAG, "uncrypt: " + filename); @@ -255,6 +282,95 @@ public class RecoverySystemService extends IRecoverySystem.Stub { } } + @Override // Binder call + public boolean requestLskf(String updateToken, IntentSender intentSender) { + mContext.enforceCallingOrSelfPermission(android.Manifest.permission.RECOVERY, null); + + if (updateToken == null) { + return false; + } + + // No need to prepare again for the same token. + if (mPreparedForReboot && updateToken.equals(mUnattendedRebootToken)) { + return true; + } + + mPreparedForReboot = false; + mUnattendedRebootToken = updateToken; + mPreparedForRebootIntentSender = intentSender; + + final long origId = Binder.clearCallingIdentity(); + try { + mInjector.getLockSettingsService().prepareRebootEscrow(); + } finally { + Binder.restoreCallingIdentity(origId); + } + + return true; + } + + @Override + public void onPreparedForReboot(boolean ready) { + if (mUnattendedRebootToken == null) { + Slog.w(TAG, "onPreparedForReboot called when mUnattendedRebootToken is null"); + } + + mPreparedForReboot = ready; + if (ready) { + sendPreparedForRebootIntentIfNeeded(); + } + } + + private void sendPreparedForRebootIntentIfNeeded() { + final IntentSender intentSender = mPreparedForRebootIntentSender; + if (intentSender != null) { + try { + intentSender.sendIntent(null, 0, null, null, null); + } catch (IntentSender.SendIntentException e) { + Slog.w(TAG, "Could not send intent for prepared reboot: " + e.getMessage()); + } + } + } + + @Override // Binder call + public boolean clearLskf() { + mContext.enforceCallingOrSelfPermission(android.Manifest.permission.RECOVERY, null); + + mPreparedForReboot = false; + mUnattendedRebootToken = null; + mPreparedForRebootIntentSender = null; + + final long origId = Binder.clearCallingIdentity(); + try { + mInjector.getLockSettingsService().clearRebootEscrow(); + } finally { + Binder.restoreCallingIdentity(origId); + } + + return true; + } + + @Override // Binder call + public boolean rebootWithLskf(String updateToken, String reason) { + mContext.enforceCallingOrSelfPermission(android.Manifest.permission.RECOVERY, null); + + if (!mPreparedForReboot) { + return false; + } + + if (updateToken != null && updateToken.equals(mUnattendedRebootToken)) { + if (!mInjector.getLockSettingsService().armRebootEscrow()) { + return false; + } + + PowerManager pm = mInjector.getPowerManager(); + pm.reboot(reason); + return true; + } + + return false; + } + /** * Check if any of the init services is still running. If so, we cannot * start a new uncrypt/setup-bcb/clear-bcb service right away; otherwise diff --git a/services/core/java/com/android/server/soundtrigger_middleware/ConversionUtil.java b/services/core/java/com/android/server/soundtrigger_middleware/ConversionUtil.java index 9b22f33a20b0..0b89646bbed1 100644 --- a/services/core/java/com/android/server/soundtrigger_middleware/ConversionUtil.java +++ b/services/core/java/com/android/server/soundtrigger_middleware/ConversionUtil.java @@ -40,7 +40,6 @@ import android.media.soundtrigger_middleware.SoundTriggerModuleProperties; import android.os.HidlMemoryUtil; import java.util.regex.Matcher; -import java.util.regex.Pattern; /** * Utilities for type conversion between SoundTrigger HAL types and SoundTriggerMiddleware service @@ -60,7 +59,8 @@ class ConversionUtil { aidlProperties.maxSoundModels = hidlProperties.maxSoundModels; aidlProperties.maxKeyPhrases = hidlProperties.maxKeyPhrases; aidlProperties.maxUsers = hidlProperties.maxUsers; - aidlProperties.recognitionModes = hidlProperties.recognitionModes; + aidlProperties.recognitionModes = + hidl2aidlRecognitionModes(hidlProperties.recognitionModes); aidlProperties.captureTransition = hidlProperties.captureTransition; aidlProperties.maxBufferMs = hidlProperties.maxBufferMs; aidlProperties.concurrentCapture = hidlProperties.concurrentCapture; diff --git a/services/core/java/com/android/server/wm/InputManagerCallback.java b/services/core/java/com/android/server/wm/InputManagerCallback.java index 1f9f8830c34b..5b892f808e2f 100644 --- a/services/core/java/com/android/server/wm/InputManagerCallback.java +++ b/services/core/java/com/android/server/wm/InputManagerCallback.java @@ -10,23 +10,40 @@ import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; import static com.android.server.wm.WindowManagerService.H.ON_POINTER_DOWN_OUTSIDE_FOCUS; +import android.os.Build; import android.os.Debug; import android.os.IBinder; +import android.os.Process; import android.os.RemoteException; +import android.os.SystemClock; +import android.util.ArrayMap; import android.util.Slog; import android.view.IWindow; import android.view.InputApplicationHandle; import android.view.KeyEvent; import android.view.WindowManager; +import com.android.server.am.ActivityManagerService; import com.android.server.input.InputManagerService; import com.android.server.wm.EmbeddedWindowController.EmbeddedWindow; +import java.io.File; import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; final class InputManagerCallback implements InputManagerService.WindowManagerCallbacks { private static final String TAG = TAG_WITH_CLASS_NAME ? "InputManagerCallback" : TAG_WM; + + /** Prevent spamming the traces because pre-dump cannot aware duplicated ANR. */ + private static final long PRE_DUMP_MIN_INTERVAL_MS = TimeUnit.SECONDS.toMillis(20); + /** The timeout to detect if a monitor is held for a while. */ + private static final long PRE_DUMP_MONITOR_TIMEOUT_MS = TimeUnit.SECONDS.toMillis(1); + /** The last time pre-dump was executed. */ + private volatile long mLastPreDumpTimeMs; + private final WindowManagerService mService; // Set to true when the first input device configuration change notification @@ -77,6 +94,77 @@ final class InputManagerCallback implements InputManagerService.WindowManagerCal } /** + * Pre-dump stack trace if the locks of activity manager or window manager (they may be locked + * in the path of reporting ANR) cannot be acquired in time. That provides the stack traces + * before the real blocking symptom has gone. + * <p> + * Do not hold the {@link WindowManagerGlobalLock} while calling this method. + */ + private void preDumpIfLockTooSlow() { + if (!Build.IS_DEBUGGABLE) { + return; + } + final long now = SystemClock.uptimeMillis(); + if (mLastPreDumpTimeMs > 0 && now - mLastPreDumpTimeMs < PRE_DUMP_MIN_INTERVAL_MS) { + return; + } + + final boolean[] shouldDumpSf = { true }; + final ArrayMap<String, Runnable> monitors = new ArrayMap<>(2); + monitors.put(TAG_WM, mService::monitor); + monitors.put("ActivityManager", mService.mAmInternal::monitor); + final CountDownLatch latch = new CountDownLatch(monitors.size()); + // The pre-dump will execute if one of the monitors doesn't complete within the timeout. + for (int i = 0; i < monitors.size(); i++) { + final String name = monitors.keyAt(i); + final Runnable monitor = monitors.valueAt(i); + // Always create new thread to avoid noise of existing threads. Suppose here won't + // create too many threads because it means that watchdog will be triggered first. + new Thread() { + @Override + public void run() { + monitor.run(); + latch.countDown(); + final long elapsed = SystemClock.uptimeMillis() - now; + if (elapsed > PRE_DUMP_MONITOR_TIMEOUT_MS) { + Slog.i(TAG_WM, "Pre-dump acquired " + name + " in " + elapsed + "ms"); + } else if (TAG_WM.equals(name)) { + // Window manager is the main client of SurfaceFlinger. If window manager + // is responsive, the stack traces of SurfaceFlinger may not be important. + shouldDumpSf[0] = false; + } + }; + }.start(); + } + try { + if (latch.await(PRE_DUMP_MONITOR_TIMEOUT_MS, TimeUnit.MILLISECONDS)) { + return; + } + } catch (InterruptedException ignored) { } + mLastPreDumpTimeMs = now; + Slog.i(TAG_WM, "Pre-dump for unresponsive"); + + final ArrayList<Integer> firstPids = new ArrayList<>(1); + firstPids.add(ActivityManagerService.MY_PID); + ArrayList<Integer> nativePids = null; + final int[] pids = shouldDumpSf[0] + ? Process.getPidsForCommands(new String[] { "/system/bin/surfaceflinger" }) + : null; + if (pids != null) { + nativePids = new ArrayList<>(1); + for (int pid : pids) { + nativePids.add(pid); + } + } + + final File tracesFile = ActivityManagerService.dumpStackTraces(firstPids, + null /* processCpuTracker */, null /* lastPids */, nativePids); + if (tracesFile != null) { + tracesFile.renameTo(new File(tracesFile.getParent(), tracesFile.getName() + "_pre")); + } + } + + /** * Notifies the window manager about an application that is not responding. * Returns a new timeout to continue waiting in nanoseconds, or 0 to abort dispatch. * @@ -89,6 +177,9 @@ final class InputManagerCallback implements InputManagerService.WindowManagerCal WindowState windowState = null; boolean aboveSystem = false; int windowPid = INVALID_PID; + + preDumpIfLockTooSlow(); + //TODO(b/141764879) Limit scope of wm lock when input calls notifyANR synchronized (mService.mGlobalLock) { diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 398ce50101e5..13246ba9e587 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -367,6 +367,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { private static final String TAG_TRANSFER_OWNERSHIP_BUNDLE = "transfer-ownership-bundle"; + private static final String TAG_PROTECTED_PACKAGES = "protected-packages"; + private static final int REQUEST_EXPIRE_PASSWORD = 5571; private static final long MS_PER_DAY = TimeUnit.DAYS.toMillis(1); @@ -742,6 +744,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { // This is the list of component allowed to start lock task mode. List<String> mLockTaskPackages = new ArrayList<>(); + // List of packages protected by device owner + List<String> mProtectedPackages = new ArrayList<>(); + // Bitfield of feature flags to be enabled during LockTask mode. // We default on the power button menu, in order to be consistent with pre-P behaviour. int mLockTaskFeatures = DevicePolicyManager.LOCK_TASK_FEATURE_GLOBAL_ACTIONS; @@ -3245,6 +3250,13 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { out.endTag(null, TAG_OWNER_INSTALLED_CA_CERT); } + for (int i = 0, size = policy.mProtectedPackages.size(); i < size; i++) { + String packageName = policy.mProtectedPackages.get(i); + out.startTag(null, TAG_PROTECTED_PACKAGES); + out.attribute(null, ATTR_NAME, packageName); + out.endTag(null, TAG_PROTECTED_PACKAGES); + } + out.endTag(null, "policies"); out.endDocument(); @@ -3358,6 +3370,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { policy.mAdminMap.clear(); policy.mAffiliationIds.clear(); policy.mOwnerInstalledCaCerts.clear(); + policy.mProtectedPackages.clear(); while ((type=parser.next()) != XmlPullParser.END_DOCUMENT && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { @@ -3455,6 +3468,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { policy.mCurrentInputMethodSet = true; } else if (TAG_OWNER_INSTALLED_CA_CERT.equals(tag)) { policy.mOwnerInstalledCaCerts.add(parser.getAttributeValue(null, ATTR_ALIAS)); + } else if (TAG_PROTECTED_PACKAGES.equals(tag)) { + policy.mProtectedPackages.add(parser.getAttributeValue(null, ATTR_NAME)); } else { Slog.w(LOG_TAG, "Unknown tag: " + tag); XmlUtils.skipCurrentTag(parser); @@ -3486,6 +3501,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { updateMaximumTimeToLockLocked(userHandle); updateLockTaskPackagesLocked(policy.mLockTaskPackages, userHandle); updateLockTaskFeaturesLocked(policy.mLockTaskFeatures, userHandle); + updateProtectedPackagesLocked(policy.mProtectedPackages); if (policy.mStatusBarDisabled) { setStatusBarDisabledInternal(policy.mStatusBarDisabled, userHandle); } @@ -3511,6 +3527,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } } + private void updateProtectedPackagesLocked(List<String> packages) { + mInjector.getPackageManagerInternal().setDeviceOwnerProtectedPackages(packages); + } + private void updateLockTaskFeaturesLocked(int flags, int userId) { long ident = mInjector.binderClearCallingIdentity(); try { @@ -8349,6 +8369,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { policy.mLockTaskPackages.clear(); updateLockTaskPackagesLocked(policy.mLockTaskPackages, userId); policy.mLockTaskFeatures = DevicePolicyManager.LOCK_TASK_FEATURE_NONE; + policy.mProtectedPackages.clear(); + updateProtectedPackagesLocked(policy.mProtectedPackages); saveSettingsLocked(userId); try { @@ -9065,6 +9087,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { pw.increaseIndent(); pw.print("mPasswordOwner="); pw.println(policy.mPasswordOwner); pw.decreaseIndent(); + pw.println(); + pw.increaseIndent(); + pw.print("mProtectedPackages="); pw.println(policy.mProtectedPackages); + pw.decreaseIndent(); } } @@ -14698,4 +14724,42 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return DevicePolicyConstants.loadFromString( mInjector.settingsGlobalGetString(Global.DEVICE_POLICY_CONSTANTS)); } + + @Override + public void setProtectedPackages(ComponentName who, List<String> packages) { + Preconditions.checkNotNull(who, "ComponentName is null"); + Preconditions.checkNotNull(packages, "packages is null"); + + enforceDeviceOwner(who); + synchronized (getLockObject()) { + final int userHandle = mInjector.userHandleGetCallingUserId(); + setProtectedPackagesLocked(userHandle, packages); + DevicePolicyEventLogger + .createEvent(DevicePolicyEnums.SET_PACKAGES_PROTECTED) + .setAdmin(who) + .setStrings(packages.toArray(new String[packages.size()])) + .write(); + } + } + + private void setProtectedPackagesLocked(int userHandle, List<String> packages) { + final DevicePolicyData policy = getUserData(userHandle); + policy.mProtectedPackages = packages; + + // Store the settings persistently. + saveSettingsLocked(userHandle); + updateProtectedPackagesLocked(packages); + } + + @Override + public List<String> getProtectedPackages(ComponentName who) { + Preconditions.checkNotNull(who, "ComponentName is null"); + + enforceDeviceOwner(who); + final int userHandle = mInjector.binderGetCallingUserHandle().getIdentifier(); + synchronized (getLockObject()) { + final List<String> packages = getUserData(userHandle).mProtectedPackages; + return packages == null ? Collections.EMPTY_LIST : packages; + } + } } diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java index ee94dd698175..a16e14f61a66 100644 --- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java @@ -5525,6 +5525,36 @@ public class DevicePolicyManagerTest extends DpmTestBase { assertTrue(dpm.isPackageAllowedToAccessCalendar(testPackage)); } + public void testSetProtectedPackages_asDO() throws Exception { + final List<String> testPackages = new ArrayList<>(); + testPackages.add("package_1"); + testPackages.add("package_2"); + + mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS); + setDeviceOwner(); + + dpm.setProtectedPackages(admin1, testPackages); + + verify(getServices().packageManagerInternal).setDeviceOwnerProtectedPackages(testPackages); + + assertEquals(testPackages, dpm.getProtectedPackages(admin1)); + } + + public void testSetProtectedPackages_failingAsPO() throws Exception { + final List<String> testPackages = new ArrayList<>(); + testPackages.add("package_1"); + testPackages.add("package_2"); + + mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS); + setAsProfileOwner(admin1); + + assertExpectException(SecurityException.class, /* messageRegex= */ null, + () -> dpm.setProtectedPackages(admin1, testPackages)); + + assertExpectException(SecurityException.class, /* messageRegex= */ null, + () -> dpm.getProtectedPackages(admin1)); + } + private void configureProfileOwnerOfOrgOwnedDevice(ComponentName who, int userId) { when(getServices().userManager.getProfileParent(eq(UserHandle.of(userId)))) .thenReturn(UserHandle.SYSTEM); diff --git a/services/tests/servicestests/src/com/android/server/locksettings/RebootEscrowDataTest.java b/services/tests/servicestests/src/com/android/server/locksettings/RebootEscrowDataTest.java new file mode 100644 index 000000000000..54c552b06c23 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/locksettings/RebootEscrowDataTest.java @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.locksettings; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import javax.crypto.spec.SecretKeySpec; + +/** + * atest FrameworksServicesTests:RebootEscrowDataTest + */ +@RunWith(AndroidJUnit4.class) +public class RebootEscrowDataTest { + private static byte[] getTestSp() { + byte[] testSp = new byte[10]; + for (int i = 0; i < testSp.length; i++) { + testSp[i] = (byte) i; + } + return testSp; + } + + @Test(expected = NullPointerException.class) + public void fromEntries_failsOnNull() throws Exception { + RebootEscrowData.fromSyntheticPassword((byte) 2, null); + } + + @Test(expected = NullPointerException.class) + public void fromEncryptedData_failsOnNullData() throws Exception { + byte[] testSp = getTestSp(); + RebootEscrowData expected = RebootEscrowData.fromSyntheticPassword((byte) 2, testSp); + SecretKeySpec key = RebootEscrowData.fromKeyBytes(expected.getKey()); + RebootEscrowData.fromEncryptedData(key, null); + } + + @Test(expected = NullPointerException.class) + public void fromEncryptedData_failsOnNullKey() throws Exception { + byte[] testSp = getTestSp(); + RebootEscrowData expected = RebootEscrowData.fromSyntheticPassword((byte) 2, testSp); + RebootEscrowData.fromEncryptedData(null, expected.getBlob()); + } + + @Test + public void fromEntries_loopback_success() throws Exception { + byte[] testSp = getTestSp(); + RebootEscrowData expected = RebootEscrowData.fromSyntheticPassword((byte) 2, testSp); + + SecretKeySpec key = RebootEscrowData.fromKeyBytes(expected.getKey()); + RebootEscrowData actual = RebootEscrowData.fromEncryptedData(key, expected.getBlob()); + + assertThat(actual.getSpVersion(), is(expected.getSpVersion())); + assertThat(actual.getIv(), is(expected.getIv())); + assertThat(actual.getKey(), is(expected.getKey())); + assertThat(actual.getBlob(), is(expected.getBlob())); + assertThat(actual.getSyntheticPassword(), is(expected.getSyntheticPassword())); + } +} diff --git a/services/tests/servicestests/src/com/android/server/locksettings/RebootEscrowManagerTests.java b/services/tests/servicestests/src/com/android/server/locksettings/RebootEscrowManagerTests.java new file mode 100644 index 000000000000..78a5a0b69fff --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/locksettings/RebootEscrowManagerTests.java @@ -0,0 +1,171 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.locksettings; + +import static android.content.pm.UserInfo.FLAG_FULL; +import static android.content.pm.UserInfo.FLAG_PRIMARY; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.clearInvocations; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.content.pm.UserInfo; +import android.hardware.rebootescrow.IRebootEscrow; +import android.os.RemoteException; +import android.os.UserManager; +import android.platform.test.annotations.Presubmit; + +import androidx.test.InstrumentationRegistry; +import androidx.test.filters.SmallTest; +import androidx.test.runner.AndroidJUnit4; + +import com.android.internal.widget.RebootEscrowListener; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.io.File; +import java.util.ArrayList; + +@SmallTest +@Presubmit +@RunWith(AndroidJUnit4.class) +public class RebootEscrowManagerTests { + protected static final int PRIMARY_USER_ID = 0; + protected static final int NONSECURE_USER_ID = 10; + private static final byte FAKE_SP_VERSION = 1; + private static final byte[] FAKE_AUTH_TOKEN = new byte[] { + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + }; + + private Context mContext; + private UserManager mUserManager; + private RebootEscrowManager.Callbacks mCallbacks; + private IRebootEscrow mRebootEscrow; + + LockSettingsStorageTestable mStorage; + + private RebootEscrowManager mService; + + static class MockInjector extends RebootEscrowManager.Injector { + private final IRebootEscrow mRebootEscrow; + private final UserManager mUserManager; + + MockInjector(Context context, UserManager userManager, IRebootEscrow rebootEscrow) { + super(context); + mRebootEscrow = rebootEscrow; + mUserManager = userManager; + } + + @Override + public UserManager getUserManager() { + return mUserManager; + } + + @Override + public IRebootEscrow getRebootEscrow() { + return mRebootEscrow; + } + } + + @Before + public void setUp_baseServices() throws Exception { + mContext = mock(Context.class); + mUserManager = mock(UserManager.class); + mCallbacks = mock(RebootEscrowManager.Callbacks.class); + mRebootEscrow = mock(IRebootEscrow.class); + + mStorage = new LockSettingsStorageTestable(mContext, + new File(InstrumentationRegistry.getContext().getFilesDir(), "locksettings")); + + ArrayList<UserInfo> users = new ArrayList<>(); + users.add(new UserInfo(PRIMARY_USER_ID, "primary", FLAG_PRIMARY)); + users.add(new UserInfo(NONSECURE_USER_ID, "non-secure", FLAG_FULL)); + when(mUserManager.getUsers()).thenReturn(users); + when(mCallbacks.isUserSecure(PRIMARY_USER_ID)).thenReturn(true); + when(mCallbacks.isUserSecure(NONSECURE_USER_ID)).thenReturn(false); + mService = new RebootEscrowManager(new MockInjector(mContext, mUserManager, mRebootEscrow), + mCallbacks, mStorage); + } + + @Test + public void prepareRebootEscrow_Success() throws Exception { + RebootEscrowListener mockListener = mock(RebootEscrowListener.class); + mService.setRebootEscrowListener(mockListener); + mService.prepareRebootEscrow(); + + clearInvocations(mRebootEscrow); + mService.callToRebootEscrowIfNeeded(PRIMARY_USER_ID, FAKE_SP_VERSION, FAKE_AUTH_TOKEN); + verify(mockListener).onPreparedForReboot(eq(true)); + verify(mRebootEscrow, never()).storeKey(any()); + } + + @Test + public void prepareRebootEscrow_ClearCredentials_Success() throws Exception { + RebootEscrowListener mockListener = mock(RebootEscrowListener.class); + mService.setRebootEscrowListener(mockListener); + mService.prepareRebootEscrow(); + mService.callToRebootEscrowIfNeeded(PRIMARY_USER_ID, FAKE_SP_VERSION, FAKE_AUTH_TOKEN); + verify(mockListener).onPreparedForReboot(eq(true)); + + clearInvocations(mRebootEscrow); + mService.clearRebootEscrow(); + verify(mockListener).onPreparedForReboot(eq(false)); + verify(mRebootEscrow).storeKey(eq(new byte[32])); + } + + @Test + public void armService_Success() throws Exception { + RebootEscrowListener mockListener = mock(RebootEscrowListener.class); + mService.setRebootEscrowListener(mockListener); + mService.prepareRebootEscrow(); + + clearInvocations(mRebootEscrow); + mService.callToRebootEscrowIfNeeded(PRIMARY_USER_ID, FAKE_SP_VERSION, FAKE_AUTH_TOKEN); + verify(mockListener).onPreparedForReboot(eq(true)); + verify(mRebootEscrow, never()).storeKey(any()); + + assertTrue(mService.armRebootEscrowIfNeeded()); + verify(mRebootEscrow).storeKey(any()); + } + + @Test + public void armService_NoInitialization_Failure() throws Exception { + assertFalse(mService.armRebootEscrowIfNeeded()); + verifyNoMoreInteractions(mRebootEscrow); + } + + @Test + public void armService_RebootEscrowServiceException_Failure() throws Exception { + doThrow(RemoteException.class).when(mRebootEscrow).storeKey(any()); + assertFalse(mService.armRebootEscrowIfNeeded()); + verifyNoMoreInteractions(mRebootEscrow); + } +} diff --git a/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTest.java b/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTest.java index 1f312bf1296d..d5cdbeb121b0 100644 --- a/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTest.java @@ -20,16 +20,19 @@ import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; import android.content.Context; +import android.content.IntentSender; import android.os.Handler; import android.os.IPowerManager; import android.os.IRecoverySystemProgressListener; @@ -40,6 +43,8 @@ import androidx.test.InstrumentationRegistry; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; +import com.android.internal.widget.LockSettingsInternal; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -58,6 +63,7 @@ public class RecoverySystemServiceTest { private Context mContext; private IPowerManager mIPowerManager; private FileWriter mUncryptUpdateFileWriter; + private LockSettingsInternal mLockSettingsInternal; @Before public void setup() { @@ -65,6 +71,9 @@ public class RecoverySystemServiceTest { mSystemProperties = new RecoverySystemServiceTestable.FakeSystemProperties(); mUncryptSocket = mock(RecoverySystemService.UncryptSocket.class); mUncryptUpdateFileWriter = mock(FileWriter.class); + mLockSettingsInternal = mock(LockSettingsInternal.class); + + when(mLockSettingsInternal.armRebootEscrow()).thenReturn(true); Looper looper = InstrumentationRegistry.getContext().getMainLooper(); mIPowerManager = mock(IPowerManager.class); @@ -72,7 +81,7 @@ public class RecoverySystemServiceTest { new Handler(looper)); mRecoverySystemService = new RecoverySystemServiceTestable(mContext, mSystemProperties, - powerManager, mUncryptUpdateFileWriter, mUncryptSocket); + powerManager, mUncryptUpdateFileWriter, mUncryptSocket, mLockSettingsInternal); } @Test @@ -194,4 +203,100 @@ public class RecoverySystemServiceTest { verify(mUncryptSocket).sendAck(); verify(mUncryptSocket).close(); } + + @Test(expected = SecurityException.class) + public void requestLskf_protected() { + doThrow(SecurityException.class).when(mContext).enforceCallingOrSelfPermission( + eq(android.Manifest.permission.RECOVERY), any()); + mRecoverySystemService.requestLskf("test", null); + } + + + @Test + public void requestLskf_nullToken_failure() { + assertThat(mRecoverySystemService.requestLskf(null, null), is(false)); + } + + @Test + public void requestLskf_success() throws Exception { + IntentSender intentSender = mock(IntentSender.class); + assertThat(mRecoverySystemService.requestLskf("test", intentSender), is(true)); + mRecoverySystemService.onPreparedForReboot(true); + verify(intentSender).sendIntent(any(), anyInt(), any(), any(), any()); + } + + @Test + public void requestLskf_subsequentRequestClearsPrepared() throws Exception { + IntentSender intentSender = mock(IntentSender.class); + assertThat(mRecoverySystemService.requestLskf("test", intentSender), is(true)); + mRecoverySystemService.onPreparedForReboot(true); + verify(intentSender).sendIntent(any(), anyInt(), any(), any(), any()); + + assertThat(mRecoverySystemService.requestLskf("test2", null), is(true)); + assertThat(mRecoverySystemService.rebootWithLskf("test", null), is(false)); + assertThat(mRecoverySystemService.rebootWithLskf("test2", "foobar"), is(false)); + + mRecoverySystemService.onPreparedForReboot(true); + assertThat(mRecoverySystemService.rebootWithLskf("test2", "foobar"), is(true)); + verify(intentSender).sendIntent(any(), anyInt(), any(), any(), any()); + verify(mIPowerManager).reboot(anyBoolean(), eq("foobar"), anyBoolean()); + } + + + @Test + public void requestLskf_requestedButNotPrepared() throws Exception { + IntentSender intentSender = mock(IntentSender.class); + assertThat(mRecoverySystemService.requestLskf("test", intentSender), is(true)); + verify(intentSender, never()).sendIntent(any(), anyInt(), any(), any(), any()); + } + + @Test(expected = SecurityException.class) + public void clearLskf_protected() { + doThrow(SecurityException.class).when(mContext).enforceCallingOrSelfPermission( + eq(android.Manifest.permission.RECOVERY), any()); + mRecoverySystemService.clearLskf(); + } + + @Test + public void clearLskf_requestedThenCleared() throws Exception { + IntentSender intentSender = mock(IntentSender.class); + assertThat(mRecoverySystemService.requestLskf("test", intentSender), is(true)); + mRecoverySystemService.onPreparedForReboot(true); + verify(intentSender).sendIntent(any(), anyInt(), any(), any(), any()); + + assertThat(mRecoverySystemService.clearLskf(), is(true)); + verify(mLockSettingsInternal).clearRebootEscrow(); + } + + @Test + public void startup_setRebootEscrowListener() throws Exception { + mRecoverySystemService.onSystemServicesReady(); + verify(mLockSettingsInternal).setRebootEscrowListener(any()); + } + + @Test(expected = SecurityException.class) + public void rebootWithLskf_protected() { + doThrow(SecurityException.class).when(mContext).enforceCallingOrSelfPermission( + eq(android.Manifest.permission.RECOVERY), any()); + mRecoverySystemService.rebootWithLskf("test1", null); + } + + @Test + public void rebootWithLskf_Success() throws Exception { + assertThat(mRecoverySystemService.requestLskf("test", null), is(true)); + mRecoverySystemService.onPreparedForReboot(true); + assertThat(mRecoverySystemService.rebootWithLskf("test", "ab-update"), is(true)); + verify(mIPowerManager).reboot(anyBoolean(), eq("ab-update"), anyBoolean()); + } + + @Test + public void rebootWithLskf_withoutPrepare_Failure() throws Exception { + assertThat(mRecoverySystemService.rebootWithLskf("test1", null), is(false)); + } + + @Test + public void rebootWithLskf_withNullUpdateToken_Failure() throws Exception { + assertThat(mRecoverySystemService.rebootWithLskf(null, null), is(false)); + verifyNoMoreInteractions(mIPowerManager); + } } diff --git a/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTestable.java b/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTestable.java index a986b71d556f..131e4f321a6c 100644 --- a/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTestable.java +++ b/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTestable.java @@ -19,6 +19,8 @@ package com.android.server.recoverysystem; import android.content.Context; import android.os.PowerManager; +import com.android.internal.widget.LockSettingsInternal; + import java.io.FileWriter; public class RecoverySystemServiceTestable extends RecoverySystemService { @@ -27,15 +29,17 @@ public class RecoverySystemServiceTestable extends RecoverySystemService { private final PowerManager mPowerManager; private final FileWriter mUncryptPackageFileWriter; private final UncryptSocket mUncryptSocket; + private final LockSettingsInternal mLockSettingsInternal; MockInjector(Context context, FakeSystemProperties systemProperties, PowerManager powerManager, FileWriter uncryptPackageFileWriter, - UncryptSocket uncryptSocket) { + UncryptSocket uncryptSocket, LockSettingsInternal lockSettingsInternal) { super(context); mSystemProperties = systemProperties; mPowerManager = powerManager; mUncryptPackageFileWriter = uncryptPackageFileWriter; mUncryptSocket = uncryptSocket; + mLockSettingsInternal = lockSettingsInternal; } @Override @@ -76,13 +80,18 @@ public class RecoverySystemServiceTestable extends RecoverySystemService { @Override public void threadSleep(long millis) { } + + @Override + public LockSettingsInternal getLockSettingsService() { + return mLockSettingsInternal; + } } RecoverySystemServiceTestable(Context context, FakeSystemProperties systemProperties, PowerManager powerManager, FileWriter uncryptPackageFileWriter, - UncryptSocket uncryptSocket) { + UncryptSocket uncryptSocket, LockSettingsInternal lockSettingsInternal) { super(new MockInjector(context, systemProperties, powerManager, uncryptPackageFileWriter, - uncryptSocket)); + uncryptSocket, lockSettingsInternal)); } public static class FakeSystemProperties { diff --git a/services/tests/servicestests/src/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareImplTest.java b/services/tests/servicestests/src/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareImplTest.java index 82f32f88d3a2..f8915c06b555 100644 --- a/services/tests/servicestests/src/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareImplTest.java +++ b/services/tests/servicestests/src/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareImplTest.java @@ -60,8 +60,6 @@ import android.os.IHwBinder; import android.os.IHwInterface; import android.os.RemoteException; -import androidx.test.runner.AndroidJUnit4; - import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -144,7 +142,11 @@ public class SoundTriggerMiddlewareImplTest { properties.maxSoundModels = 456; properties.maxKeyPhrases = 567; properties.maxUsers = 678; - properties.recognitionModes = 789; + properties.recognitionModes = + android.hardware.soundtrigger.V2_0.RecognitionMode.VOICE_TRIGGER + | android.hardware.soundtrigger.V2_0.RecognitionMode.USER_IDENTIFICATION + | android.hardware.soundtrigger.V2_0.RecognitionMode.USER_AUTHENTICATION + | android.hardware.soundtrigger.V2_0.RecognitionMode.GENERIC_TRIGGER; properties.captureTransition = true; properties.maxBufferMs = 321; properties.concurrentCapture = supportConcurrentCapture; @@ -162,7 +164,10 @@ public class SoundTriggerMiddlewareImplTest { assertEquals(456, properties.maxSoundModels); assertEquals(567, properties.maxKeyPhrases); assertEquals(678, properties.maxUsers); - assertEquals(789, properties.recognitionModes); + assertEquals(RecognitionMode.GENERIC_TRIGGER + | RecognitionMode.USER_AUTHENTICATION + | RecognitionMode.USER_IDENTIFICATION + | RecognitionMode.VOICE_TRIGGER, properties.recognitionModes); assertTrue(properties.captureTransition); assertEquals(321, properties.maxBufferMs); assertEquals(supportConcurrentCapture, properties.concurrentCapture); diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java index 95617b1162a8..172df99921a0 100755 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java @@ -492,23 +492,13 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { return sbn; } - private NotificationRecord generateNotificationRecord(NotificationChannel channel, int id, String groupKey, boolean isSummary) { - return generateNotificationRecord(channel, id, groupKey, isSummary, false /* isBubble */); - } - - private NotificationRecord generateNotificationRecord(NotificationChannel channel, int id, - String groupKey, boolean isSummary, boolean isBubble) { Notification.Builder nb = new Notification.Builder(mContext, channel.getId()) .setContentTitle("foo") .setSmallIcon(android.R.drawable.sym_def_app_icon) .setGroup(groupKey) .setGroupSummary(isSummary); - if (isBubble) { - nb.setBubbleMetadata(getBasicBubbleMetadataBuilder().build()); - } - StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, id, "tag" + System.currentTimeMillis(), mUid, 0, nb.build(), new UserHandle(mUid), null, 0); @@ -521,11 +511,6 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { private NotificationRecord generateNotificationRecord(NotificationChannel channel, Notification.TvExtender extender) { - return generateNotificationRecord(channel, extender, false /* isBubble */); - } - - private NotificationRecord generateNotificationRecord(NotificationChannel channel, - Notification.TvExtender extender, boolean isBubble) { if (channel == null) { channel = mTestNotificationChannel; } @@ -535,9 +520,6 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { if (extender != null) { nb.extend(extender); } - if (isBubble) { - nb.setBubbleMetadata(getBasicBubbleMetadataBuilder().build()); - } StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0, nb.build(), new UserHandle(mUid), null, 0); return new NotificationRecord(mContext, sbn, channel); @@ -555,6 +537,26 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { return new NotificationRecord(mContext, sbn, channel); } + private NotificationRecord generateMessageBubbleNotifRecord(NotificationChannel channel, + String tag) { + return generateMessageBubbleNotifRecord(true, channel, 1, tag, null, false); + } + + private NotificationRecord generateMessageBubbleNotifRecord(boolean addMetadata, + NotificationChannel channel, int id, String tag, String groupKey, boolean isSummary) { + if (channel == null) { + channel = mTestNotificationChannel; + } + if (tag == null) { + tag = "tag"; + } + Notification.Builder nb = getMessageStyleNotifBuilder(addMetadata, groupKey, isSummary); + StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, id, + tag, mUid, 0, + nb.build(), new UserHandle(mUid), null, 0); + return new NotificationRecord(mContext, sbn, channel); + } + private Map<String, Answer> getSignalExtractorSideEffects() { Map<String, Answer> answers = new ArrayMap<>(); @@ -610,23 +612,57 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { false); } - private Notification.BubbleMetadata.Builder getBasicBubbleMetadataBuilder() { + private Notification.BubbleMetadata.Builder getBubbleMetadataBuilder() { PendingIntent pi = PendingIntent.getActivity(mContext, 0, new Intent(), 0); return new Notification.BubbleMetadata.Builder() .setIntent(pi) .setIcon(Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon)); } + private Notification.Builder getMessageStyleNotifBuilder(boolean addBubbleMetadata, + String groupKey, boolean isSummary) { + // Give it a person + Person person = new Person.Builder() + .setName("bubblebot") + .build(); + // It needs remote input to be bubble-able + RemoteInput remoteInput = new RemoteInput.Builder("reply_key").setLabel("reply").build(); + PendingIntent inputIntent = PendingIntent.getActivity(mContext, 0, new Intent(), 0); + Icon icon = Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon); + Notification.Action replyAction = new Notification.Action.Builder(icon, "Reply", + inputIntent).addRemoteInput(remoteInput) + .build(); + // Make it messaging style + Notification.Builder nb = new Notification.Builder(mContext, + mTestNotificationChannel.getId()) + .setContentTitle("foo") + .setStyle(new Notification.MessagingStyle(person) + .setConversationTitle("Bubble Chat") + .addMessage("Hello?", + SystemClock.currentThreadTimeMillis() - 300000, person) + .addMessage("Is it me you're looking for?", + SystemClock.currentThreadTimeMillis(), person) + ) + .setActions(replyAction) + .setSmallIcon(android.R.drawable.sym_def_app_icon) + .setGroupSummary(isSummary); + if (groupKey != null) { + nb.setGroup(groupKey); + } + if (addBubbleMetadata) { + nb.setBubbleMetadata(getBubbleMetadataBuilder().build()); + } + return nb; + } + private NotificationRecord addGroupWithBubblesAndValidateAdded(boolean summaryAutoCancel) throws RemoteException { - // Notification that has bubble metadata - NotificationRecord nrBubble = generateNotificationRecord(mTestNotificationChannel, 1, - "BUBBLE_GROUP", false /* isSummary */, true /* isBubble */); + String groupKey = "BUBBLE_GROUP"; - // Make the package foreground so that we're allowed to be a bubble - when(mActivityManager.getPackageImportance(nrBubble.sbn.getPackageName())).thenReturn( - IMPORTANCE_FOREGROUND); + // Notification that has bubble metadata + NotificationRecord nrBubble = generateMessageBubbleNotifRecord(true /* addMetadata */, + mTestNotificationChannel, 1 /* id */, "tag", groupKey, false /* isSummary */); mBinderService.enqueueNotificationWithTag(PKG, PKG, nrBubble.sbn.getTag(), nrBubble.sbn.getId(), nrBubble.sbn.getNotification(), nrBubble.sbn.getUserId()); @@ -637,9 +673,10 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { assertEquals(1, notifsAfter.length); assertTrue((notifsAfter[0].getNotification().flags & FLAG_BUBBLE) != 0); - // Plain notification without bubble metadata - NotificationRecord nrPlain = generateNotificationRecord(mTestNotificationChannel, 2, - "BUBBLE_GROUP", false /* isSummary */, false /* isBubble */); + // Notification without bubble metadata + NotificationRecord nrPlain = generateMessageBubbleNotifRecord(false /* addMetadata */, + mTestNotificationChannel, 2 /* id */, "tag", groupKey, false /* isSummary */); + mBinderService.enqueueNotificationWithTag(PKG, PKG, nrPlain.sbn.getTag(), nrPlain.sbn.getId(), nrPlain.sbn.getNotification(), nrPlain.sbn.getUserId()); waitForIdle(); @@ -648,8 +685,9 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { assertEquals(2, notifsAfter.length); // Summary notification for both of those - NotificationRecord nrSummary = generateNotificationRecord(mTestNotificationChannel, 3, - "BUBBLE_GROUP", true /* isSummary */, false /* isBubble */); + NotificationRecord nrSummary = generateMessageBubbleNotifRecord(false /* addMetadata */, + mTestNotificationChannel, 3 /* id */, "tag", groupKey, true /* isSummary */); + if (summaryAutoCancel) { nrSummary.getNotification().flags |= FLAG_AUTO_CANCEL; } @@ -4708,13 +4746,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { // Bubbles are allowed! setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */); - // Notif with bubble metadata but not our other misc requirements - NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, - null /* tvExtender */, true /* isBubble */); - - // Say we're foreground - when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn( - IMPORTANCE_FOREGROUND); + NotificationRecord nr = + generateMessageBubbleNotifRecord(mTestNotificationChannel, "testFlagBubble"); mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(), nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId()); @@ -4732,13 +4765,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { // Bubbles are allowed! setUpPrefsForBubbles(true /* global */, false /* app */, true /* channel */); - // Notif with bubble metadata but not our other misc requirements - NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, - null /* tvExtender */, true /* isBubble */); - - // Say we're foreground - when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn( - IMPORTANCE_FOREGROUND); + NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel, + "testFlagBubble_noFlag_appNotAllowed"); mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(), nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId()); @@ -4752,174 +4780,40 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { } @Test - public void testFlagBubbleNotifs_flag_appForeground() throws RemoteException { + public void testFlagBubbleNotifs_noFlag_whenAppForeground() throws RemoteException { // Bubbles are allowed! setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */); // Notif with bubble metadata but not our other misc requirements - NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, - null /* tvExtender */, true /* isBubble */); + Notification.Builder nb = new Notification.Builder(mContext, + mTestNotificationChannel.getId()) + .setContentTitle("foo") + .setSmallIcon(android.R.drawable.sym_def_app_icon) + .setBubbleMetadata(getBubbleMetadataBuilder().build()); + StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, "tag", mUid, 0, + nb.build(), new UserHandle(mUid), null, 0); + NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); // Say we're foreground when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn( IMPORTANCE_FOREGROUND); - - mBinderService.enqueueNotificationWithTag(PKG, PKG, - nr.sbn.getTag(), nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId()); - waitForIdle(); - - // yes allowed, yes foreground, yes bubble - assertTrue(mService.getNotificationRecord( - nr.sbn.getKey()).getNotification().isBubbleNotification()); - } - - @Test - public void testFlagBubbleNotifs_noFlag_appNotForeground() throws RemoteException { - // Bubbles are allowed! - setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */); - - // Notif with bubble metadata but not our other misc requirements - NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, - null /* tvExtender */, true /* isBubble */); - - // Make sure we're NOT foreground - when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn( - IMPORTANCE_VISIBLE); - mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(), nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId()); waitForIdle(); - // yes allowed but NOT foreground, no bubble + // if notif isn't configured properly it doesn't get to bubble just because app is + // foreground. assertFalse(mService.getNotificationRecord( nr.sbn.getKey()).getNotification().isBubbleNotification()); } @Test - public void testFlagBubbleNotifs_flag_previousForegroundFlag() throws RemoteException { - // Bubbles are allowed! - setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */); - - // Notif with bubble metadata but not our other misc requirements - NotificationRecord nr1 = generateNotificationRecord(mTestNotificationChannel, - null /* tvExtender */, true /* isBubble */); - - // Send notif when we're foreground - when(mActivityManager.getPackageImportance(nr1.sbn.getPackageName())).thenReturn( - IMPORTANCE_FOREGROUND); - mBinderService.enqueueNotificationWithTag(PKG, PKG, nr1.sbn.getTag(), - nr1.sbn.getId(), nr1.sbn.getNotification(), nr1.sbn.getUserId()); - waitForIdle(); - - // yes allowed, yes foreground, yes bubble - assertTrue(mService.getNotificationRecord( - nr1.sbn.getKey()).getNotification().isBubbleNotification()); - - // Send a new update when we're not foreground - NotificationRecord nr2 = generateNotificationRecord(mTestNotificationChannel, - null /* tvExtender */, true /* isBubble */); - - when(mActivityManager.getPackageImportance(nr2.sbn.getPackageName())).thenReturn( - IMPORTANCE_VISIBLE); - mBinderService.enqueueNotificationWithTag(PKG, PKG, nr2.sbn.getTag(), - nr2.sbn.getId(), nr2.sbn.getNotification(), nr2.sbn.getUserId()); - waitForIdle(); - - // yes allowed, previously foreground / flagged, yes bubble - assertTrue(mService.getNotificationRecord( - nr2.sbn.getKey()).getNotification().isBubbleNotification()); - - StatusBarNotification[] notifs2 = mBinderService.getActiveNotifications(PKG); - assertEquals(1, notifs2.length); - assertEquals(1, mService.getNotificationRecordCount()); - } - - @Test - public void testFlagBubbleNotifs_noFlag_previousForegroundFlag_afterRemoval() - throws RemoteException { - // Bubbles are allowed! - setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */); - - // Notif with bubble metadata but not our other misc requirements - NotificationRecord nr1 = generateNotificationRecord(mTestNotificationChannel, - null /* tvExtender */, true /* isBubble */); - - // Send notif when we're foreground - when(mActivityManager.getPackageImportance(nr1.sbn.getPackageName())).thenReturn( - IMPORTANCE_FOREGROUND); - mBinderService.enqueueNotificationWithTag(PKG, PKG, nr1.sbn.getTag(), - nr1.sbn.getId(), nr1.sbn.getNotification(), nr1.sbn.getUserId()); - waitForIdle(); - - // yes allowed, yes foreground, yes bubble - assertTrue(mService.getNotificationRecord( - nr1.sbn.getKey()).getNotification().isBubbleNotification()); - - // Remove the bubble - mBinderService.cancelNotificationWithTag(PKG, PKG, nr1.sbn.getTag(), nr1.sbn.getId(), - nr1.sbn.getUserId()); - waitForIdle(); - - StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG); - assertEquals(0, notifs.length); - assertEquals(0, mService.getNotificationRecordCount()); - - // Send a new update when we're not foreground - NotificationRecord nr2 = generateNotificationRecord(mTestNotificationChannel, - null /* tvExtender */, true /* isBubble */); - - when(mActivityManager.getPackageImportance(nr2.sbn.getPackageName())).thenReturn( - IMPORTANCE_VISIBLE); - mBinderService.enqueueNotificationWithTag(PKG, PKG, nr2.sbn.getTag(), - nr2.sbn.getId(), nr2.sbn.getNotification(), nr2.sbn.getUserId()); - waitForIdle(); - - // yes allowed, but was removed & no foreground, so no bubble - assertFalse(mService.getNotificationRecord( - nr2.sbn.getKey()).getNotification().isBubbleNotification()); - - StatusBarNotification[] notifs2 = mBinderService.getActiveNotifications(PKG); - assertEquals(1, notifs2.length); - assertEquals(1, mService.getNotificationRecordCount()); - } - - @Test public void testFlagBubbleNotifs_flag_messaging() throws RemoteException { // Bubbles are allowed! setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */); - // Give it bubble metadata - Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build(); - // Give it a person - Person person = new Person.Builder() - .setName("bubblebot") - .build(); - // It needs remote input to be bubble-able - RemoteInput remoteInput = new RemoteInput.Builder("reply_key").setLabel("reply").build(); - PendingIntent inputIntent = PendingIntent.getActivity(mContext, 0, new Intent(), 0); - Icon icon = Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon); - Notification.Action replyAction = new Notification.Action.Builder(icon, "Reply", - inputIntent).addRemoteInput(remoteInput) - .build(); - // Make it messaging style - Notification.Builder nb = new Notification.Builder(mContext, - mTestNotificationChannel.getId()) - .setContentTitle("foo") - .setBubbleMetadata(data) - .setStyle(new Notification.MessagingStyle(person) - .setConversationTitle("Bubble Chat") - .addMessage("Hello?", - SystemClock.currentThreadTimeMillis() - 300000, person) - .addMessage("Is it me you're looking for?", - SystemClock.currentThreadTimeMillis(), person) - ) - .setActions(replyAction) - .setSmallIcon(android.R.drawable.sym_def_app_icon); - - StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, - "testFlagBubbleNotifs_flag_messaging", mUid, 0, - nb.build(), new UserHandle(mUid), null, 0); - NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); + NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel, + "testFlagBubbleNotifs_flag_messaging"); mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(), nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId()); @@ -4927,7 +4821,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { // yes allowed, yes messaging, yes bubble assertTrue(mService.getNotificationRecord( - sbn.getKey()).getNotification().isBubbleNotification()); + nr.sbn.getKey()).getNotification().isBubbleNotification()); } @Test @@ -4936,7 +4830,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */); // Give it bubble metadata - Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build(); + Notification.BubbleMetadata data = getBubbleMetadataBuilder().build(); // Give it a person Person person = new Person.Builder() .setName("bubblebot") @@ -4972,7 +4866,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */); // Give it bubble metadata - Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build(); + Notification.BubbleMetadata data = getBubbleMetadataBuilder().build(); // Give it a person Person person = new Person.Builder() .setName("bubblebot") @@ -5005,7 +4899,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */); // Give it bubble metadata - Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build(); + Notification.BubbleMetadata data = getBubbleMetadataBuilder().build(); // Make it a phone call Notification.Builder nb = new Notification.Builder(mContext, mTestNotificationChannel.getId()) @@ -5036,7 +4930,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */); // Give it bubble metadata - Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build(); + Notification.BubbleMetadata data = getBubbleMetadataBuilder().build(); // Give it a person Person person = new Person.Builder() .setName("bubblebot") @@ -5070,30 +4964,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { // Bubbles are NOT allowed! setUpPrefsForBubbles(false /* global */, true /* app */, true /* channel */); - // Give it bubble metadata - Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build(); - // Give it a person - Person person = new Person.Builder() - .setName("bubblebot") - .build(); - // Make it messaging style - Notification.Builder nb = new Notification.Builder(mContext, - mTestNotificationChannel.getId()) - .setContentTitle("foo") - .setBubbleMetadata(data) - .setStyle(new Notification.MessagingStyle(person) - .setConversationTitle("Bubble Chat") - .addMessage("Hello?", - SystemClock.currentThreadTimeMillis() - 300000, person) - .addMessage("Is it me you're looking for?", - SystemClock.currentThreadTimeMillis(), person) - ) - .setSmallIcon(android.R.drawable.sym_def_app_icon); - - StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, - "testFlagBubbleNotifs_noFlag_messaging_appNotAllowed", mUid, 0, - nb.build(), new UserHandle(mUid), null, 0); - NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); + NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel, + "testFlagBubbleNotifs_noFlag_messaging_appNotAllowed"); // Post the notification mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(), @@ -5102,7 +4974,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { // not allowed, no bubble assertFalse(mService.getNotificationRecord( - sbn.getKey()).getNotification().isBubbleNotification()); + nr.sbn.getKey()).getNotification().isBubbleNotification()); } @Test @@ -5110,8 +4982,14 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { // Bubbles are allowed! setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */); - // Notif WITHOUT bubble metadata - NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel); + // Messaging notif WITHOUT bubble metadata + Notification.Builder nb = getMessageStyleNotifBuilder(false /* addBubbleMetadata */, + null /* groupKey */, false /* isSummary */); + + StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, + "testFlagBubbleNotifs_noFlag_notBubble", mUid, 0, + nb.build(), new UserHandle(mUid), null, 0); + NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); // Post the notification mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(), @@ -5128,39 +5006,17 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { // Bubbles are allowed except on this channel setUpPrefsForBubbles(true /* global */, true /* app */, false /* channel */); - // Give it bubble metadata - Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build(); - // Give it a person - Person person = new Person.Builder() - .setName("bubblebot") - .build(); - // Make it messaging style - Notification.Builder nb = new Notification.Builder(mContext, - mTestNotificationChannel.getId()) - .setContentTitle("foo") - .setBubbleMetadata(data) - .setStyle(new Notification.MessagingStyle(person) - .setConversationTitle("Bubble Chat") - .addMessage("Hello?", - SystemClock.currentThreadTimeMillis() - 300000, person) - .addMessage("Is it me you're looking for?", - SystemClock.currentThreadTimeMillis(), person) - ) - .setSmallIcon(android.R.drawable.sym_def_app_icon); - - StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, - "testFlagBubbleNotifs_noFlag_messaging_channelNotAllowed", mUid, 0, - nb.build(), new UserHandle(mUid), null, 0); - NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); + NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel, + "testFlagBubbleNotifs_noFlag_messaging_channelNotAllowed"); // Post the notification - mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(), + mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(), nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId()); waitForIdle(); // channel not allowed, no bubble assertFalse(mService.getNotificationRecord( - sbn.getKey()).getNotification().isBubbleNotification()); + nr.sbn.getKey()).getNotification().isBubbleNotification()); } @Test @@ -5169,7 +5025,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { setUpPrefsForBubbles(false /* global */, true /* app */, true /* channel */); // Give it bubble metadata - Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build(); + Notification.BubbleMetadata data = getBubbleMetadataBuilder().build(); // Give it a person Person person = new Person.Builder() .setName("bubblebot") @@ -5205,7 +5061,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { setUpPrefsForBubbles(true /* global */, true /* app */, false /* channel */); // Give it bubble metadata - Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build(); + Notification.BubbleMetadata data = getBubbleMetadataBuilder().build(); // Give it a person Person person = new Person.Builder() .setName("bubblebot") @@ -5412,13 +5268,9 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { // Bubbles are allowed! setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */); - // Notif with bubble metadata but not our other misc requirements - NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, - null /* tvExtender */, true /* isBubble */); - - // Say we're foreground - when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn( - IMPORTANCE_FOREGROUND); + // Notif with bubble metadata + NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel, + "testNotificationBubbleChanged_false"); mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(), nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId()); @@ -5447,9 +5299,9 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { // Bubbles are allowed! setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */); - // Plain notification that has bubble metadata + // Notif that is not a bubble NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, - null /* tvExtender */, true /* isBubble */); + 1, null, false); mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(), nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId()); waitForIdle(); @@ -5459,9 +5311,12 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { assertEquals(1, notifsBefore.length); assertEquals((notifsBefore[0].getNotification().flags & FLAG_BUBBLE), 0); - // Make the package foreground so that we're allowed to be a bubble - when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn( - IMPORTANCE_FOREGROUND); + // Update the notification to be message style / meet bubble requirements + NotificationRecord nr2 = generateMessageBubbleNotifRecord(mTestNotificationChannel, + nr.sbn.getTag()); + mBinderService.enqueueNotificationWithTag(PKG, PKG, nr2.sbn.getTag(), + nr2.sbn.getId(), nr2.sbn.getNotification(), nr2.sbn.getUserId()); + waitForIdle(); // Reset as this is called when the notif is first sent reset(mListeners); @@ -5482,8 +5337,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */); // Notif that is not a bubble - NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, - null /* tvExtender */, true /* isBubble */); + NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel); mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(), nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId()); waitForIdle(); @@ -5681,26 +5535,17 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { // Bubbles are allowed! setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */); - // Plain notification that has bubble metadata - NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, - null /* tvExtender */, true /* isBubble */); + // And we are low ram + when(mActivityManager.isLowRamDevice()).thenReturn(true); + + // Notification that would typically bubble + NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel, + "testNotificationBubbles_disabled_lowRamDevice"); mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(), nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId()); waitForIdle(); - // Would be a normal notification because wouldn't have met requirements to bubble - StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG); - assertEquals(1, notifsBefore.length); - assertEquals((notifsBefore[0].getNotification().flags & FLAG_BUBBLE), 0); - - // Make the package foreground so that we're allowed to be a bubble - when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn( - IMPORTANCE_FOREGROUND); - - // And we are low ram - when(mActivityManager.isLowRamDevice()).thenReturn(true); - - // We wouldn't be a bubble because the notification didn't meet requirements (low ram) + // But we wouldn't be a bubble because the device is low ram & all bubbles are disabled. StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG); assertEquals(1, notifsAfter.length); assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0); @@ -5774,50 +5619,23 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { // Bubbles are allowed! setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */); - // Give it bubble metadata - Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder() - .setSuppressNotification(true) - .setAutoExpandBubble(true).build(); - // Give it a person - Person person = new Person.Builder() - .setName("bubblebot") - .build(); - // It needs remote input to be bubble-able - RemoteInput remoteInput = new RemoteInput.Builder("reply_key").setLabel("reply").build(); - PendingIntent inputIntent = PendingIntent.getActivity(mContext, 0, new Intent(), 0); - Icon icon = Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon); - Notification.Action replyAction = new Notification.Action.Builder(icon, "Reply", - inputIntent).addRemoteInput(remoteInput) - .build(); - // Make it messaging style - Notification.Builder nb = new Notification.Builder(mContext, - mTestNotificationChannel.getId()) - .setContentTitle("foo") - .setBubbleMetadata(data) - .setStyle(new Notification.MessagingStyle(person) - .setConversationTitle("Bubble Chat") - .addMessage("Hello?", - SystemClock.currentThreadTimeMillis() - 300000, person) - .addMessage("Is it me you're looking for?", - SystemClock.currentThreadTimeMillis(), person) - ) - .setActions(replyAction) - .setSmallIcon(android.R.drawable.sym_def_app_icon); - - StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0, - nb.build(), new UserHandle(mUid), null, 0); - NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); + NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel, + "testNotificationBubbles_flagAutoExpandForeground_fails_notForeground"); + // Modify metadata flags + nr.sbn.getNotification().getBubbleMetadata().setFlags( + Notification.BubbleMetadata.FLAG_AUTO_EXPAND_BUBBLE + | Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION); // Ensure we're not foreground when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn( IMPORTANCE_VISIBLE); - mBinderService.enqueueNotificationWithTag(PKG, PKG, null, + mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(), nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId()); waitForIdle(); // yes allowed, yes messaging, yes bubble - Notification notif = mService.getNotificationRecord(sbn.getKey()).getNotification(); + Notification notif = mService.getNotificationRecord(nr.sbn.getKey()).getNotification(); assertTrue(notif.isBubbleNotification()); // Our flags should have failed since we're not foreground @@ -5831,53 +5649,26 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { // Bubbles are allowed! setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */); - // Give it bubble metadata - Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder() - .setSuppressNotification(true) - .setAutoExpandBubble(true).build(); - // Give it a person - Person person = new Person.Builder() - .setName("bubblebot") - .build(); - // It needs remote input to be bubble-able - RemoteInput remoteInput = new RemoteInput.Builder("reply_key").setLabel("reply").build(); - PendingIntent inputIntent = PendingIntent.getActivity(mContext, 0, new Intent(), 0); - Icon icon = Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon); - Notification.Action replyAction = new Notification.Action.Builder(icon, "Reply", - inputIntent).addRemoteInput(remoteInput) - .build(); - // Make it messaging style - Notification.Builder nb = new Notification.Builder(mContext, - mTestNotificationChannel.getId()) - .setContentTitle("foo") - .setBubbleMetadata(data) - .setStyle(new Notification.MessagingStyle(person) - .setConversationTitle("Bubble Chat") - .addMessage("Hello?", - SystemClock.currentThreadTimeMillis() - 300000, person) - .addMessage("Is it me you're looking for?", - SystemClock.currentThreadTimeMillis(), person) - ) - .setActions(replyAction) - .setSmallIcon(android.R.drawable.sym_def_app_icon); - - StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0, - nb.build(), new UserHandle(mUid), null, 0); - NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); + NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel, + "testNotificationBubbles_flagAutoExpandForeground_succeeds_foreground"); + // Modify metadata flags + nr.sbn.getNotification().getBubbleMetadata().setFlags( + Notification.BubbleMetadata.FLAG_AUTO_EXPAND_BUBBLE + | Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION); // Ensure we are in the foreground when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn( IMPORTANCE_FOREGROUND); - mBinderService.enqueueNotificationWithTag(PKG, PKG, null, + mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(), nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId()); waitForIdle(); // yes allowed, yes messaging, yes bubble - Notification notif = mService.getNotificationRecord(sbn.getKey()).getNotification(); + Notification notif = mService.getNotificationRecord(nr.sbn.getKey()).getNotification(); assertTrue(notif.isBubbleNotification()); - // Our flags should have failed since we are foreground + // Our flags should have passed since we are foreground assertTrue(notif.getBubbleMetadata().getAutoExpandBubble()); assertTrue(notif.getBubbleMetadata().isNotificationSuppressed()); } @@ -6004,7 +5795,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { @Test public void testNotificationHistory_addNoisyNotification() throws Exception { NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, - null /* tvExtender */, false); + null /* tvExtender */); mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(), nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId()); waitForIdle(); diff --git a/telephony/OWNERS b/telephony/OWNERS index 2a6e8deeb13e..58a7ea08da3f 100644 --- a/telephony/OWNERS +++ b/telephony/OWNERS @@ -14,4 +14,5 @@ shuoq@google.com refuhoo@google.com paulye@google.com nazaninb@google.com -sarahchin@google.com
\ No newline at end of file +sarahchin@google.com +dbright@google.com diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java index 8139330cfc59..5b12aed3e51b 100644 --- a/telephony/java/android/telephony/ServiceState.java +++ b/telephony/java/android/telephony/ServiceState.java @@ -545,7 +545,7 @@ public class ServiceState implements Parcelable { * @see #STATE_EMERGENCY_ONLY * @see #STATE_POWER_OFF * - * @return current data registration state {@link RegState} + * @return current data registration state * * @hide */ @@ -562,7 +562,7 @@ public class ServiceState implements Parcelable { * @see #STATE_EMERGENCY_ONLY * @see #STATE_POWER_OFF * - * @return current data registration state {@link RegState} + * @return current data registration state * * @hide */ diff --git a/wifi/java/android/net/wifi/SoftApCapability.java b/wifi/java/android/net/wifi/SoftApCapability.java index c4474e2bc9cc..2bbe7d2aa4ec 100644 --- a/wifi/java/android/net/wifi/SoftApCapability.java +++ b/wifi/java/android/net/wifi/SoftApCapability.java @@ -61,11 +61,20 @@ public final class SoftApCapability implements Parcelable { */ public static final int SOFTAP_FEATURE_CLIENT_FORCE_DISCONNECT = 1 << 1; + + /** + * Support for WPA3 Simultaneous Authentication of Equals (WPA3-SAE). + * + * flag when {@link config_wifi_softap_sae_supported)} is true. + */ + public static final int SOFTAP_FEATURE_WPA3_SAE = 1 << 2; + /** @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef(flag = true, prefix = { "SOFTAP_FEATURE_" }, value = { SOFTAP_FEATURE_ACS_OFFLOAD, SOFTAP_FEATURE_CLIENT_FORCE_DISCONNECT, + SOFTAP_FEATURE_WPA3_SAE, }) public @interface HotspotFeatures {} diff --git a/wifi/java/android/net/wifi/SoftApConfiguration.java b/wifi/java/android/net/wifi/SoftApConfiguration.java index 05e245b8eabc..65e9b7910e5e 100644 --- a/wifi/java/android/net/wifi/SoftApConfiguration.java +++ b/wifi/java/android/net/wifi/SoftApConfiguration.java @@ -25,6 +25,7 @@ import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; +import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.Preconditions; import java.lang.annotation.Retention; @@ -55,6 +56,11 @@ import java.util.concurrent.Executor; @SystemApi public final class SoftApConfiguration implements Parcelable { + @VisibleForTesting + static final int PSK_MIN_LEN = 8; + @VisibleForTesting + static final int PSK_MAX_LEN = 63; + /** * 2GHz band. * @hide @@ -142,9 +148,10 @@ public final class SoftApConfiguration implements Parcelable { private final @Nullable MacAddress mBssid; /** - * Pre-shared key for WPA2-PSK encryption (non-null enables WPA2-PSK). + * Pre-shared key for WPA2-PSK or WPA3-SAE-Transition or WPA3-SAE encryption which depends on + * the security type. */ - private final @Nullable String mWpa2Passphrase; + private final @Nullable String mPassphrase; /** * This is a network that does not broadcast its SSID, so an @@ -186,20 +193,30 @@ public final class SoftApConfiguration implements Parcelable { public static final int SECURITY_TYPE_WPA2_PSK = 1; /** @hide */ + @SystemApi + public static final int SECURITY_TYPE_WPA3_SAE_TRANSITION = 2; + + /** @hide */ + @SystemApi + public static final int SECURITY_TYPE_WPA3_SAE = 3; + + /** @hide */ @Retention(RetentionPolicy.SOURCE) - @IntDef(prefix = { "SECURITY_TYPE" }, value = { + @IntDef(prefix = { "SECURITY_TYPE_" }, value = { SECURITY_TYPE_OPEN, SECURITY_TYPE_WPA2_PSK, + SECURITY_TYPE_WPA3_SAE_TRANSITION, + SECURITY_TYPE_WPA3_SAE, }) public @interface SecurityType {} /** Private constructor for Builder and Parcelable implementation. */ private SoftApConfiguration(@Nullable String ssid, @Nullable MacAddress bssid, - @Nullable String wpa2Passphrase, boolean hiddenSsid, @BandType int band, int channel, + @Nullable String passphrase, boolean hiddenSsid, @BandType int band, int channel, @SecurityType int securityType, int maxNumberOfClients) { mSsid = ssid; mBssid = bssid; - mWpa2Passphrase = wpa2Passphrase; + mPassphrase = passphrase; mHiddenSsid = hiddenSsid; mBand = band; mChannel = channel; @@ -218,7 +235,7 @@ public final class SoftApConfiguration implements Parcelable { SoftApConfiguration other = (SoftApConfiguration) otherObj; return Objects.equals(mSsid, other.mSsid) && Objects.equals(mBssid, other.mBssid) - && Objects.equals(mWpa2Passphrase, other.mWpa2Passphrase) + && Objects.equals(mPassphrase, other.mPassphrase) && mHiddenSsid == other.mHiddenSsid && mBand == other.mBand && mChannel == other.mChannel @@ -228,7 +245,7 @@ public final class SoftApConfiguration implements Parcelable { @Override public int hashCode() { - return Objects.hash(mSsid, mBssid, mWpa2Passphrase, mHiddenSsid, + return Objects.hash(mSsid, mBssid, mPassphrase, mHiddenSsid, mBand, mChannel, mSecurityType, mMaxNumberOfClients); } @@ -237,8 +254,8 @@ public final class SoftApConfiguration implements Parcelable { StringBuilder sbuf = new StringBuilder(); sbuf.append("ssid=").append(mSsid); if (mBssid != null) sbuf.append(" \n bssid=").append(mBssid.toString()); - sbuf.append(" \n Wpa2Passphrase =").append( - TextUtils.isEmpty(mWpa2Passphrase) ? "<empty>" : "<non-empty>"); + sbuf.append(" \n Passphrase =").append( + TextUtils.isEmpty(mPassphrase) ? "<empty>" : "<non-empty>"); sbuf.append(" \n HiddenSsid =").append(mHiddenSsid); sbuf.append(" \n Band =").append(mBand); sbuf.append(" \n Channel =").append(mChannel); @@ -251,7 +268,7 @@ public final class SoftApConfiguration implements Parcelable { public void writeToParcel(@NonNull Parcel dest, int flags) { dest.writeString(mSsid); dest.writeParcelable(mBssid, flags); - dest.writeString(mWpa2Passphrase); + dest.writeString(mPassphrase); dest.writeBoolean(mHiddenSsid); dest.writeInt(mBand); dest.writeInt(mChannel); @@ -299,13 +316,26 @@ public final class SoftApConfiguration implements Parcelable { return mBssid; } + // TODO: Remove it after update the caller /** * Returns String set to be passphrase for the WPA2-PSK AP. - * {@link Builder#setWpa2Passphrase(String)}. + * {@link #setWpa2Passphrase(String)}. */ @Nullable public String getWpa2Passphrase() { - return mWpa2Passphrase; + if (mSecurityType == SECURITY_TYPE_WPA2_PSK) { + return mPassphrase; + } + return null; + } + + /** + * Returns String set to be passphrase for current AP. + * {@link #setPassphrase(String, @SecurityType int)}. + */ + @Nullable + public String getPassphrase() { + return mPassphrase; } /** @@ -360,23 +390,12 @@ public final class SoftApConfiguration implements Parcelable { public static final class Builder { private String mSsid; private MacAddress mBssid; - private String mWpa2Passphrase; + private String mPassphrase; private boolean mHiddenSsid; private int mBand; private int mChannel; private int mMaxNumberOfClients; - - private int setSecurityType() { - int securityType = SECURITY_TYPE_OPEN; - if (!TextUtils.isEmpty(mWpa2Passphrase)) { // WPA2-PSK network. - securityType = SECURITY_TYPE_WPA2_PSK; - } - return securityType; - } - - private void clearAllPassphrase() { - mWpa2Passphrase = null; - } + private int mSecurityType; /** * Constructs a Builder with default values (see {@link Builder}). @@ -384,11 +403,12 @@ public final class SoftApConfiguration implements Parcelable { public Builder() { mSsid = null; mBssid = null; - mWpa2Passphrase = null; + mPassphrase = null; mHiddenSsid = false; mBand = BAND_2GHZ; mChannel = 0; mMaxNumberOfClients = 0; + mSecurityType = SECURITY_TYPE_OPEN; } /** @@ -399,11 +419,12 @@ public final class SoftApConfiguration implements Parcelable { mSsid = other.mSsid; mBssid = other.mBssid; - mWpa2Passphrase = other.mWpa2Passphrase; + mPassphrase = other.mPassphrase; mHiddenSsid = other.mHiddenSsid; mBand = other.mBand; mChannel = other.mChannel; mMaxNumberOfClients = other.mMaxNumberOfClients; + mSecurityType = other.mSecurityType; } /** @@ -413,8 +434,8 @@ public final class SoftApConfiguration implements Parcelable { */ @NonNull public SoftApConfiguration build() { - return new SoftApConfiguration(mSsid, mBssid, mWpa2Passphrase, - mHiddenSsid, mBand, mChannel, setSecurityType(), mMaxNumberOfClients); + return new SoftApConfiguration(mSsid, mBssid, mPassphrase, + mHiddenSsid, mBand, mChannel, mSecurityType, mMaxNumberOfClients); } /** @@ -461,6 +482,7 @@ public final class SoftApConfiguration implements Parcelable { return this; } + // TODO: Remove it after update the caller /** * Specifies that this AP should use WPA2-PSK with the given ASCII WPA2 passphrase. * When set to null, an open network is created. @@ -473,15 +495,47 @@ public final class SoftApConfiguration implements Parcelable { */ @NonNull public Builder setWpa2Passphrase(@Nullable String passphrase) { - if (passphrase != null) { + return setPassphrase(passphrase, SECURITY_TYPE_WPA2_PSK); + } + + /** + * Specifies that this AP should use specific security type with the given ASCII passphrase. + * + * @param securityType one of the security types from {@link @SecurityType}. + * @param passphrase The passphrase to use for sepcific {@link @SecurityType} configuration + * or null with {@link @SecurityType#SECURITY_TYPE_OPEN}. + * + * @return Builder for chaining. + * @throws IllegalArgumentException when the passphrase length is invalid and + * {@code securityType} is not {@link @SecurityType#SECURITY_TYPE_OPEN} + * or non-null passphrase and {@code securityType} is + * {@link @SecurityType#SECURITY_TYPE_OPEN}. + */ + @NonNull + public Builder setPassphrase(@Nullable String passphrase, @SecurityType int securityType) { + if (securityType == SECURITY_TYPE_OPEN) { + if (passphrase != null) { + throw new IllegalArgumentException( + "passphrase should be null when security type is open"); + } + } else { + Preconditions.checkStringNotEmpty(passphrase); final CharsetEncoder asciiEncoder = StandardCharsets.US_ASCII.newEncoder(); if (!asciiEncoder.canEncode(passphrase)) { throw new IllegalArgumentException("passphrase not ASCII encodable"); } - Preconditions.checkStringNotEmpty(passphrase); + if (securityType == SECURITY_TYPE_WPA2_PSK + || securityType == SECURITY_TYPE_WPA3_SAE_TRANSITION) { + if (passphrase.length() < PSK_MIN_LEN || passphrase.length() > PSK_MAX_LEN) { + throw new IllegalArgumentException( + "Password size must be at least " + PSK_MIN_LEN + + " and no more than " + PSK_MAX_LEN + + " for WPA2_PSK and WPA3_SAE_TRANSITION Mode"); + } + } } - clearAllPassphrase(); - mWpa2Passphrase = passphrase; + mSecurityType = securityType; + mPassphrase = passphrase; return this; } diff --git a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java index 148e8a410aac..41f7c6e2bb0d 100644 --- a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java +++ b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java @@ -1336,20 +1336,18 @@ public class WifiEnterpriseConfig implements Parcelable { } /** - * If the current authentication method needs SIM card. - * @return true if the credential information require SIM card for current authentication + * Utility method to determine whether the configuration's authentication method is SIM-based. + * + * @return true if the credential information requires SIM card for current authentication * method, otherwise it returns false. - * @hide */ - public boolean requireSimCredential() { + public boolean isAuthenticationSimBased() { if (mEapMethod == Eap.SIM || mEapMethod == Eap.AKA || mEapMethod == Eap.AKA_PRIME) { return true; } if (mEapMethod == Eap.PEAP) { - if (mPhase2Method == Phase2.SIM || mPhase2Method == Phase2.AKA - || mPhase2Method == Phase2.AKA_PRIME) { - return true; - } + return mPhase2Method == Phase2.SIM || mPhase2Method == Phase2.AKA + || mPhase2Method == Phase2.AKA_PRIME; } return false; } diff --git a/wifi/tests/src/android/net/wifi/SoftApConfigurationTest.java b/wifi/tests/src/android/net/wifi/SoftApConfigurationTest.java index 1f601036a718..acd334355806 100644 --- a/wifi/tests/src/android/net/wifi/SoftApConfigurationTest.java +++ b/wifi/tests/src/android/net/wifi/SoftApConfigurationTest.java @@ -25,8 +25,12 @@ import androidx.test.filters.SmallTest; import org.junit.Test; +import java.util.Random; + @SmallTest public class SoftApConfigurationTest { + private static final String TEST_CHAR_SET_AS_STRING = "abcdefghijklmnopqrstuvwxyz0123456789"; + private SoftApConfiguration parcelUnparcel(SoftApConfiguration configIn) { Parcel parcel = Parcel.obtain(); parcel.writeParcelable(configIn, 0); @@ -37,6 +41,25 @@ public class SoftApConfigurationTest { return configOut; } + /** + * Helper method to generate random string. + * + * Note: this method has limited use as a random string generator. + * The characters used in this method do no not cover all valid inputs. + * @param length number of characters to generate for the string + * @return String generated string of random characters + */ + private String generateRandomString(int length) { + Random random = new Random(); + StringBuilder stringBuilder = new StringBuilder(length); + int index = -1; + while (stringBuilder.length() < length) { + index = random.nextInt(TEST_CHAR_SET_AS_STRING.length()); + stringBuilder.append(TEST_CHAR_SET_AS_STRING.charAt(index)); + } + return stringBuilder.toString(); + } + @Test public void testBasicSettings() { SoftApConfiguration original = new SoftApConfiguration.Builder() @@ -45,7 +68,7 @@ public class SoftApConfigurationTest { .build(); assertThat(original.getSsid()).isEqualTo("ssid"); assertThat(original.getBssid()).isEqualTo(MacAddress.fromString("11:22:33:44:55:66")); - assertThat(original.getWpa2Passphrase()).isNull(); + assertThat(original.getPassphrase()).isNull(); assertThat(original.getSecurityType()).isEqualTo(SoftApConfiguration.SECURITY_TYPE_OPEN); assertThat(original.getBand()).isEqualTo(SoftApConfiguration.BAND_2GHZ); assertThat(original.getChannel()).isEqualTo(0); @@ -66,9 +89,9 @@ public class SoftApConfigurationTest { @Test public void testWpa2() { SoftApConfiguration original = new SoftApConfiguration.Builder() - .setWpa2Passphrase("secretsecret") + .setPassphrase("secretsecret", SoftApConfiguration.SECURITY_TYPE_WPA2_PSK) .build(); - assertThat(original.getWpa2Passphrase()).isEqualTo("secretsecret"); + assertThat(original.getPassphrase()).isEqualTo("secretsecret"); assertThat(original.getSecurityType()).isEqualTo( SoftApConfiguration.SECURITY_TYPE_WPA2_PSK); assertThat(original.getBand()).isEqualTo(SoftApConfiguration.BAND_2GHZ); @@ -90,13 +113,12 @@ public class SoftApConfigurationTest { @Test public void testWpa2WithAllFieldCustomized() { SoftApConfiguration original = new SoftApConfiguration.Builder() - .setWpa2Passphrase("secretsecret") - .setBand(SoftApConfiguration.BAND_ANY) + .setPassphrase("secretsecret", SoftApConfiguration.SECURITY_TYPE_WPA2_PSK) .setChannel(149, SoftApConfiguration.BAND_5GHZ) .setHiddenSsid(true) .setMaxNumberOfClients(10) .build(); - assertThat(original.getWpa2Passphrase()).isEqualTo("secretsecret"); + assertThat(original.getPassphrase()).isEqualTo("secretsecret"); assertThat(original.getSecurityType()).isEqualTo( SoftApConfiguration.SECURITY_TYPE_WPA2_PSK); assertThat(original.getBand()).isEqualTo(SoftApConfiguration.BAND_5GHZ); @@ -114,4 +136,98 @@ public class SoftApConfigurationTest { assertThat(copy).isEqualTo(original); assertThat(copy.hashCode()).isEqualTo(original.hashCode()); } + + @Test + public void testWpa3Sae() { + SoftApConfiguration original = new SoftApConfiguration.Builder() + .setPassphrase("secretsecret", SoftApConfiguration.SECURITY_TYPE_WPA3_SAE) + .setChannel(149, SoftApConfiguration.BAND_5GHZ) + .setHiddenSsid(true) + .build(); + assertThat(original.getPassphrase()).isEqualTo("secretsecret"); + assertThat(original.getSecurityType()).isEqualTo( + SoftApConfiguration.SECURITY_TYPE_WPA3_SAE); + assertThat(original.getBand()).isEqualTo(SoftApConfiguration.BAND_5GHZ); + assertThat(original.getChannel()).isEqualTo(149); + assertThat(original.isHiddenSsid()).isEqualTo(true); + + + SoftApConfiguration unparceled = parcelUnparcel(original); + assertThat(unparceled).isNotSameAs(original); + assertThat(unparceled).isEqualTo(original); + assertThat(unparceled.hashCode()).isEqualTo(original.hashCode()); + + SoftApConfiguration copy = new SoftApConfiguration.Builder(original).build(); + assertThat(copy).isNotSameAs(original); + assertThat(copy).isEqualTo(original); + assertThat(copy.hashCode()).isEqualTo(original.hashCode()); + } + + @Test + public void testWpa3SaeTransition() { + SoftApConfiguration original = new SoftApConfiguration.Builder() + .setPassphrase("secretsecret", + SoftApConfiguration.SECURITY_TYPE_WPA3_SAE_TRANSITION) + .setChannel(149, SoftApConfiguration.BAND_5GHZ) + .setHiddenSsid(true) + .build(); + assertThat(original.getSecurityType()).isEqualTo( + SoftApConfiguration.SECURITY_TYPE_WPA3_SAE_TRANSITION); + assertThat(original.getPassphrase()).isEqualTo("secretsecret"); + assertThat(original.getBand()).isEqualTo(SoftApConfiguration.BAND_5GHZ); + assertThat(original.getChannel()).isEqualTo(149); + assertThat(original.isHiddenSsid()).isEqualTo(true); + + + SoftApConfiguration unparceled = parcelUnparcel(original); + assertThat(unparceled).isNotSameAs(original); + assertThat(unparceled).isEqualTo(original); + assertThat(unparceled.hashCode()).isEqualTo(original.hashCode()); + + SoftApConfiguration copy = new SoftApConfiguration.Builder(original).build(); + assertThat(copy).isNotSameAs(original); + assertThat(copy).isEqualTo(original); + assertThat(copy.hashCode()).isEqualTo(original.hashCode()); + } + + @Test(expected = IllegalArgumentException.class) + public void testInvalidShortPasswordLengthForWpa2() { + SoftApConfiguration original = new SoftApConfiguration.Builder() + .setPassphrase(generateRandomString(SoftApConfiguration.PSK_MIN_LEN - 1), + SoftApConfiguration.SECURITY_TYPE_WPA2_PSK) + .setChannel(149, SoftApConfiguration.BAND_5GHZ) + .setHiddenSsid(true) + .build(); + } + + @Test(expected = IllegalArgumentException.class) + public void testInvalidLongPasswordLengthForWpa2() { + SoftApConfiguration original = new SoftApConfiguration.Builder() + .setPassphrase(generateRandomString(SoftApConfiguration.PSK_MAX_LEN + 1), + SoftApConfiguration.SECURITY_TYPE_WPA2_PSK) + .setChannel(149, SoftApConfiguration.BAND_5GHZ) + .setHiddenSsid(true) + .build(); + } + + @Test(expected = IllegalArgumentException.class) + public void testInvalidShortPasswordLengthForWpa3SaeTransition() { + SoftApConfiguration original = new SoftApConfiguration.Builder() + .setPassphrase(generateRandomString(SoftApConfiguration.PSK_MIN_LEN - 1), + SoftApConfiguration.SECURITY_TYPE_WPA3_SAE_TRANSITION) + .setChannel(149, SoftApConfiguration.BAND_5GHZ) + .setHiddenSsid(true) + .build(); + } + + @Test(expected = IllegalArgumentException.class) + public void testInvalidLongPasswordLengthForWpa3SaeTransition() { + SoftApConfiguration original = new SoftApConfiguration.Builder() + .setPassphrase(generateRandomString(SoftApConfiguration.PSK_MAX_LEN + 1), + SoftApConfiguration.SECURITY_TYPE_WPA3_SAE_TRANSITION) + .setChannel(149, SoftApConfiguration.BAND_5GHZ) + .setHiddenSsid(true) + .build(); + } + } |