Merge "Adds client info in ContextHubService dump"
diff --git a/api/current.txt b/api/current.txt
index b8e4531..297835c 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -6726,7 +6726,8 @@
method @Nullable public String getAlwaysOnVpnPackage(@NonNull android.content.ComponentName);
method @NonNull @WorkerThread public android.os.Bundle getApplicationRestrictions(@Nullable android.content.ComponentName, String);
method @Deprecated @Nullable public String getApplicationRestrictionsManagingPackage(@NonNull android.content.ComponentName);
- method public boolean getAutoTimeRequired();
+ method public boolean getAutoTime(@NonNull android.content.ComponentName);
+ method @Deprecated public boolean getAutoTimeRequired();
method @NonNull public java.util.List<android.os.UserHandle> getBindDeviceAdminTargetUsers(@NonNull android.content.ComponentName);
method public boolean getBluetoothContactSharingDisabled(@NonNull android.content.ComponentName);
method public boolean getCameraDisabled(@Nullable android.content.ComponentName);
@@ -6842,7 +6843,8 @@
method public boolean setApplicationHidden(@NonNull android.content.ComponentName, String, boolean);
method @WorkerThread public void setApplicationRestrictions(@Nullable android.content.ComponentName, String, android.os.Bundle);
method @Deprecated public void setApplicationRestrictionsManagingPackage(@NonNull android.content.ComponentName, @Nullable String) throws android.content.pm.PackageManager.NameNotFoundException;
- method public void setAutoTimeRequired(@NonNull android.content.ComponentName, boolean);
+ method public void setAutoTime(@NonNull android.content.ComponentName, boolean);
+ method @Deprecated public void setAutoTimeRequired(@NonNull android.content.ComponentName, boolean);
method public void setBackupServiceEnabled(@NonNull android.content.ComponentName, boolean);
method public void setBluetoothContactSharingDisabled(@NonNull android.content.ComponentName, boolean);
method public void setCameraDisabled(@NonNull android.content.ComponentName, boolean);
@@ -44373,6 +44375,8 @@
public static final class AccessNetworkConstants.NgranBands {
field public static final int BAND_1 = 1; // 0x1
field public static final int BAND_12 = 12; // 0xc
+ field public static final int BAND_14 = 14; // 0xe
+ field public static final int BAND_18 = 18; // 0x12
field public static final int BAND_2 = 2; // 0x2
field public static final int BAND_20 = 20; // 0x14
field public static final int BAND_25 = 25; // 0x19
@@ -44381,15 +44385,19 @@
field public static final int BAND_260 = 260; // 0x104
field public static final int BAND_261 = 261; // 0x105
field public static final int BAND_28 = 28; // 0x1c
+ field public static final int BAND_29 = 29; // 0x1d
field public static final int BAND_3 = 3; // 0x3
+ field public static final int BAND_30 = 30; // 0x1e
field public static final int BAND_34 = 34; // 0x22
field public static final int BAND_38 = 38; // 0x26
field public static final int BAND_39 = 39; // 0x27
field public static final int BAND_40 = 40; // 0x28
field public static final int BAND_41 = 41; // 0x29
+ field public static final int BAND_48 = 48; // 0x30
field public static final int BAND_5 = 5; // 0x5
field public static final int BAND_50 = 50; // 0x32
field public static final int BAND_51 = 51; // 0x33
+ field public static final int BAND_65 = 65; // 0x41
field public static final int BAND_66 = 66; // 0x42
field public static final int BAND_7 = 7; // 0x7
field public static final int BAND_70 = 70; // 0x46
@@ -44407,6 +44415,7 @@
field public static final int BAND_83 = 83; // 0x53
field public static final int BAND_84 = 84; // 0x54
field public static final int BAND_86 = 86; // 0x56
+ field public static final int BAND_90 = 90; // 0x5a
}
public static final class AccessNetworkConstants.UtranBand {
@@ -44993,6 +45002,12 @@
field public static final int SCAN_TYPE_PERIODIC = 1; // 0x1
}
+ public final class PhoneCapability implements android.os.Parcelable {
+ method public int describeContents();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.PhoneCapability> CREATOR;
+ }
+
public class PhoneNumberFormattingTextWatcher implements android.text.TextWatcher {
ctor public PhoneNumberFormattingTextWatcher();
ctor public PhoneNumberFormattingTextWatcher(String);
@@ -46729,30 +46744,30 @@
public static class Layout.Directions {
}
- public abstract class LoginFilter implements android.text.InputFilter {
- method public CharSequence filter(CharSequence, int, int, android.text.Spanned, int, int);
- method public abstract boolean isAllowed(char);
- method public void onInvalidCharacter(char);
- method public void onStart();
- method public void onStop();
+ @Deprecated public abstract class LoginFilter implements android.text.InputFilter {
+ method @Deprecated public CharSequence filter(CharSequence, int, int, android.text.Spanned, int, int);
+ method @Deprecated public abstract boolean isAllowed(char);
+ method @Deprecated public void onInvalidCharacter(char);
+ method @Deprecated public void onStart();
+ method @Deprecated public void onStop();
}
- public static class LoginFilter.PasswordFilterGMail extends android.text.LoginFilter {
- ctor public LoginFilter.PasswordFilterGMail();
- ctor public LoginFilter.PasswordFilterGMail(boolean);
- method public boolean isAllowed(char);
+ @Deprecated public static class LoginFilter.PasswordFilterGMail extends android.text.LoginFilter {
+ ctor @Deprecated public LoginFilter.PasswordFilterGMail();
+ ctor @Deprecated public LoginFilter.PasswordFilterGMail(boolean);
+ method @Deprecated public boolean isAllowed(char);
}
- public static class LoginFilter.UsernameFilterGMail extends android.text.LoginFilter {
- ctor public LoginFilter.UsernameFilterGMail();
- ctor public LoginFilter.UsernameFilterGMail(boolean);
- method public boolean isAllowed(char);
+ @Deprecated public static class LoginFilter.UsernameFilterGMail extends android.text.LoginFilter {
+ ctor @Deprecated public LoginFilter.UsernameFilterGMail();
+ ctor @Deprecated public LoginFilter.UsernameFilterGMail(boolean);
+ method @Deprecated public boolean isAllowed(char);
}
- public static class LoginFilter.UsernameFilterGeneric extends android.text.LoginFilter {
- ctor public LoginFilter.UsernameFilterGeneric();
- ctor public LoginFilter.UsernameFilterGeneric(boolean);
- method public boolean isAllowed(char);
+ @Deprecated public static class LoginFilter.UsernameFilterGeneric extends android.text.LoginFilter {
+ ctor @Deprecated public LoginFilter.UsernameFilterGeneric();
+ ctor @Deprecated public LoginFilter.UsernameFilterGeneric(boolean);
+ method @Deprecated public boolean isAllowed(char);
}
public interface NoCopySpan {
diff --git a/api/system-current.txt b/api/system-current.txt
index 9c8bce6..8bb1983 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -1329,6 +1329,11 @@
package android.bluetooth {
+ public final class BluetoothA2dp implements android.bluetooth.BluetoothProfile {
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public int getConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice);
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int);
+ }
+
public final class BluetoothAdapter {
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean addOnMetadataChangedListener(@NonNull android.bluetooth.BluetoothDevice, @NonNull java.util.concurrent.Executor, @NonNull android.bluetooth.BluetoothAdapter.OnMetadataChangedListener);
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean connectAllEnabledProfiles(@NonNull android.bluetooth.BluetoothDevice);
@@ -1393,7 +1398,14 @@
public final class BluetoothHeadset implements android.bluetooth.BluetoothProfile {
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean connect(android.bluetooth.BluetoothDevice);
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean disconnect(android.bluetooth.BluetoothDevice);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean setPriority(android.bluetooth.BluetoothDevice, int);
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public int getConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice);
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean setPriority(android.bluetooth.BluetoothDevice, int);
+ }
+
+ public final class BluetoothHearingAid implements android.bluetooth.BluetoothProfile {
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public int getConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice);
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int);
}
public final class BluetoothPan implements android.bluetooth.BluetoothProfile {
@@ -1412,9 +1424,12 @@
}
public interface BluetoothProfile {
+ field public static final int CONNECTION_POLICY_ALLOWED = 100; // 0x64
+ field public static final int CONNECTION_POLICY_FORBIDDEN = 0; // 0x0
+ field public static final int CONNECTION_POLICY_UNKNOWN = -1; // 0xffffffff
field public static final int PAN = 5; // 0x5
- field public static final int PRIORITY_OFF = 0; // 0x0
- field public static final int PRIORITY_ON = 100; // 0x64
+ field @Deprecated public static final int PRIORITY_OFF = 0; // 0x0
+ field @Deprecated public static final int PRIORITY_ON = 100; // 0x64
}
}
@@ -8036,7 +8051,7 @@
}
public static class CallScreeningService.CallResponse.Builder {
- method public android.telecom.CallScreeningService.CallResponse.Builder setShouldScreenCallFurther(boolean);
+ method @NonNull public android.telecom.CallScreeningService.CallResponse.Builder setShouldScreenCallViaAudioProcessing(boolean);
}
public abstract class Conference extends android.telecom.Conferenceable {
diff --git a/api/test-current.txt b/api/test-current.txt
index 89fdb3f..2d35736 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -2944,7 +2944,7 @@
}
public static class CallScreeningService.CallResponse.Builder {
- method public android.telecom.CallScreeningService.CallResponse.Builder setShouldScreenCallFurther(boolean);
+ method @NonNull public android.telecom.CallScreeningService.CallResponse.Builder setShouldScreenCallViaAudioProcessing(boolean);
}
public abstract class Conference extends android.telecom.Conferenceable {
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 47fd87d..39dc51e 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -5001,14 +5001,15 @@
* <p>Device owner, profile owner and their delegated certificate installer can use
* {@link #ID_TYPE_BASE_INFO} to request inclusion of the general device information
* including manufacturer, model, brand, device and product in the attestation record.
- * Only device owner and their delegated certificate installer can use
- * {@link #ID_TYPE_SERIAL}, {@link #ID_TYPE_IMEI} and {@link #ID_TYPE_MEID} to request
- * unique device identifiers to be attested (the serial number, IMEI and MEID correspondingly),
- * if supported by the device (see {@link #isDeviceIdAttestationSupported()}).
- * Additionally, device owner and their delegated certificate installer can also request the
- * attestation record to be signed using an individual attestation certificate by specifying
- * the {@link #ID_TYPE_INDIVIDUAL_ATTESTATION} flag (if supported by the device, see
- * {@link #isUniqueDeviceAttestationSupported()}).
+ * Only device owner, profile owner on an organization-owned device and their delegated
+ * certificate installers can use {@link #ID_TYPE_SERIAL}, {@link #ID_TYPE_IMEI} and
+ * {@link #ID_TYPE_MEID} to request unique device identifiers to be attested (the serial number,
+ * IMEI and MEID correspondingly), if supported by the device
+ * (see {@link #isDeviceIdAttestationSupported()}).
+ * Additionally, device owner, profile owner on an organization-owned device and their delegated
+ * certificate installers can also request the attestation record to be signed using an
+ * individual attestation certificate by specifying the {@link #ID_TYPE_INDIVIDUAL_ATTESTATION}
+ * flag (if supported by the device, see {@link #isUniqueDeviceAttestationSupported()}).
* <p>
* If any of {@link #ID_TYPE_SERIAL}, {@link #ID_TYPE_IMEI} and {@link #ID_TYPE_MEID}
* is set, it is implicitly assumed that {@link #ID_TYPE_BASE_INFO} is also set.
@@ -5696,11 +5697,21 @@
* <p>
* The calling device admin must be a device owner, or alternatively a profile owner from
* Android 8.0 (API level 26) or higher. If it is not, a security exception will be thrown.
+ * <p>
+ * Staring from Android 11, this API switches to use
+ * {@link UserManager#DISALLOW_CONFIG_DATE_TIME} to enforce the auto time settings. Calling
+ * this API to enforce auto time will result in
+ * {@link UserManager#DISALLOW_CONFIG_DATE_TIME} being set, while calling this API to lift
+ * the requirement will result in {@link UserManager#DISALLOW_CONFIG_DATE_TIME} being cleared.
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @param required Whether auto time is set required or not.
* @throws SecurityException if {@code admin} is not a device owner.
+ * @deprecated From {@link android.os.Build.VERSION_CODES#R}. Use {@link #setAutoTime}
+ * to turn auto time on or off and use {@link UserManager#DISALLOW_CONFIG_DATE_TIME}
+ * to prevent the user from changing this setting.
*/
+ @Deprecated
public void setAutoTimeRequired(@NonNull ComponentName admin, boolean required) {
throwIfParentInstance("setAutoTimeRequired");
if (mService != null) {
@@ -5714,7 +5725,9 @@
/**
* @return true if auto time is required.
+ * @deprecated From {@link android.os.Build.VERSION_CODES#R}. Use {@link #getAutoTime}
*/
+ @Deprecated
public boolean getAutoTimeRequired() {
throwIfParentInstance("getAutoTimeRequired");
if (mService != null) {
@@ -5728,6 +5741,47 @@
}
/**
+ * Called by a device owner, a profile owner for the primary user or a profile
+ * owner of an organization-owned managed profile to turn auto time on and off.
+ * Callers are recommended to use {@link UserManager#DISALLOW_CONFIG_DATE_TIME}
+ * to prevent the user from changing this setting.
+ * <p>
+ * If user restriction {@link UserManager#DISALLOW_CONFIG_DATE_TIME} is used,
+ * no user will be able set the date and time. Instead, the network date
+ * and time will be used.
+ *
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+ * @param enabled Whether time should be obtained automatically from the network or not.
+ * @throws SecurityException if caller is not a device owner, a profile owner for the
+ * primary user, or a profile owner of an organization-owned managed profile.
+ */
+ public void setAutoTime(@NonNull ComponentName admin, boolean enabled) {
+ if (mService != null) {
+ try {
+ mService.setAutoTime(admin, enabled);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ }
+
+ /**
+ * @return true if auto time is enabled on the device.
+ * @throws SecurityException if caller is not a device owner, a profile owner for the
+ * primary user, or a profile owner of an organization-owned managed profile.
+ */
+ public boolean getAutoTime(@NonNull ComponentName admin) {
+ if (mService != null) {
+ try {
+ return mService.getAutoTime(admin);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ return false;
+ }
+
+ /**
* Called by a device owner to set whether all users created on the device should be ephemeral.
* <p>
* The system user is exempt from this policy - it is never ephemeral.
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index df4b554..f55026c 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -295,6 +295,9 @@
void setAutoTimeRequired(in ComponentName who, boolean required);
boolean getAutoTimeRequired();
+ void setAutoTime(in ComponentName who, boolean enabled);
+ boolean getAutoTime(in ComponentName who);
+
void setForceEphemeralUsers(in ComponentName who, boolean forceEpehemeralUsers);
boolean getForceEphemeralUsers(in ComponentName who);
diff --git a/core/java/android/bluetooth/BluetoothA2dp.java b/core/java/android/bluetooth/BluetoothA2dp.java
index 1fe1b10..accdd8d 100644
--- a/core/java/android/bluetooth/BluetoothA2dp.java
+++ b/core/java/android/bluetooth/BluetoothA2dp.java
@@ -17,10 +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.SystemApi;
import android.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Binder;
@@ -439,28 +441,45 @@
* Set priority of the profile
*
* <p> The device should already be paired.
- * Priority can be one of {@link #PRIORITY_ON} orgetBluetoothManager
- * {@link #PRIORITY_OFF},
- *
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
- * permission.
+ * Priority can be one of {@link #PRIORITY_ON} or {@link #PRIORITY_OFF},
*
* @param device Paired bluetooth device
* @param priority
* @return true if priority is set, false on error
* @hide
*/
+ @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
public boolean setPriority(BluetoothDevice device, int priority) {
if (DBG) log("setPriority(" + device + ", " + priority + ")");
+ return setConnectionPolicy(device, BluetoothAdapter.priorityToConnectionPolicy(priority));
+ }
+
+ /**
+ * Set connection policy of the profile
+ *
+ * <p> The device should already be paired.
+ * Connection policy can be one of {@link #CONNECTION_POLICY_ALLOWED},
+ * {@link #CONNECTION_POLICY_FORBIDDEN}, {@link #CONNECTION_POLICY_UNKNOWN}
+ *
+ * @param device Paired bluetooth device
+ * @param connectionPolicy is the connection policy to set to for this profile
+ * @return true if connectionPolicy is set, false on error
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
+ public boolean setConnectionPolicy(@NonNull BluetoothDevice device,
+ @ConnectionPolicy int connectionPolicy) {
+ if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
try {
final IBluetoothA2dp service = getService();
if (service != null && isEnabled()
&& isValidDevice(device)) {
- if (priority != BluetoothProfile.PRIORITY_OFF
- && priority != BluetoothProfile.PRIORITY_ON) {
+ if (connectionPolicy != BluetoothProfile.CONNECTION_POLICY_FORBIDDEN
+ && connectionPolicy != BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
return false;
}
- return service.setPriority(device, priority);
+ return service.setConnectionPolicy(device, connectionPolicy);
}
if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
@@ -474,8 +493,7 @@
* Get the priority of the profile.
*
* <p> The priority can be any of:
- * {@link #PRIORITY_AUTO_CONNECT}, {@link #PRIORITY_OFF},
- * {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
+ * {@link #PRIORITY_OFF}, {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
*
* @param device Bluetooth device
* @return priority of the device
@@ -485,17 +503,35 @@
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
public int getPriority(BluetoothDevice device) {
if (VDBG) log("getPriority(" + device + ")");
+ return BluetoothAdapter.connectionPolicyToPriority(getConnectionPolicy(device));
+ }
+
+ /**
+ * Get the connection policy of the profile.
+ *
+ * <p> The connection policy can be any of:
+ * {@link #CONNECTION_POLICY_ALLOWED}, {@link #CONNECTION_POLICY_FORBIDDEN},
+ * {@link #CONNECTION_POLICY_UNKNOWN}
+ *
+ * @param device Bluetooth device
+ * @return connection policy of the device
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
+ public @ConnectionPolicy int getConnectionPolicy(@NonNull BluetoothDevice device) {
+ if (VDBG) log("getConnectionPolicy(" + device + ")");
try {
final IBluetoothA2dp service = getService();
if (service != null && isEnabled()
&& isValidDevice(device)) {
- return service.getPriority(device);
+ return service.getConnectionPolicy(device);
}
if (service == null) Log.w(TAG, "Proxy not attached to service");
- return BluetoothProfile.PRIORITY_OFF;
+ return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
- return BluetoothProfile.PRIORITY_OFF;
+ return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
}
}
diff --git a/core/java/android/bluetooth/BluetoothA2dpSink.java b/core/java/android/bluetooth/BluetoothA2dpSink.java
index 5a8055a..c17834a 100755
--- a/core/java/android/bluetooth/BluetoothA2dpSink.java
+++ b/core/java/android/bluetooth/BluetoothA2dpSink.java
@@ -16,6 +16,9 @@
package android.bluetooth;
+import android.Manifest;
+import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
import android.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Binder;
@@ -317,27 +320,43 @@
* Set priority of the profile
*
* <p> The device should already be paired.
- * Priority can be one of {@link #PRIORITY_ON} orgetBluetoothManager
- * {@link #PRIORITY_OFF},
- *
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
- * permission.
+ * Priority can be one of {@link #PRIORITY_ON} or {@link #PRIORITY_OFF},
*
* @param device Paired bluetooth device
* @param priority
* @return true if priority is set, false on error
* @hide
*/
+ @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
public boolean setPriority(BluetoothDevice device, int priority) {
if (DBG) log("setPriority(" + device + ", " + priority + ")");
+ return setConnectionPolicy(device, BluetoothAdapter.priorityToConnectionPolicy(priority));
+ }
+
+ /**
+ * Set connection policy of the profile
+ *
+ * <p> The device should already be paired.
+ * Connection policy can be one of {@link #CONNECTION_POLICY_ALLOWED},
+ * {@link #CONNECTION_POLICY_FORBIDDEN}, {@link #CONNECTION_POLICY_UNKNOWN}
+ *
+ * @param device Paired bluetooth device
+ * @param connectionPolicy is the connection policy to set to for this profile
+ * @return true if connectionPolicy is set, false on error
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
+ public boolean setConnectionPolicy(BluetoothDevice device, int connectionPolicy) {
+ if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
final IBluetoothA2dpSink service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
- if (priority != BluetoothProfile.PRIORITY_OFF
- && priority != BluetoothProfile.PRIORITY_ON) {
+ if (connectionPolicy != BluetoothProfile.CONNECTION_POLICY_FORBIDDEN
+ && connectionPolicy != BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
return false;
}
try {
- return service.setPriority(device, priority);
+ return service.setConnectionPolicy(device, connectionPolicy);
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return false;
@@ -351,28 +370,44 @@
* Get the priority of the profile.
*
* <p> The priority can be any of:
- * {@link #PRIORITY_AUTO_CONNECT}, {@link #PRIORITY_OFF},
- * {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
- *
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+ * {@link #PRIORITY_OFF}, {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
*
* @param device Bluetooth device
* @return priority of the device
* @hide
*/
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
public int getPriority(BluetoothDevice device) {
if (VDBG) log("getPriority(" + device + ")");
+ return BluetoothAdapter.connectionPolicyToPriority(getConnectionPolicy(device));
+ }
+
+ /**
+ * Get the connection policy of the profile.
+ *
+ * <p> The connection policy can be any of:
+ * {@link #CONNECTION_POLICY_ALLOWED}, {@link #CONNECTION_POLICY_FORBIDDEN},
+ * {@link #CONNECTION_POLICY_UNKNOWN}
+ *
+ * @param device Bluetooth device
+ * @return connection policy of the device
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
+ public int getConnectionPolicy(BluetoothDevice device) {
+ if (VDBG) log("getConnectionPolicy(" + device + ")");
final IBluetoothA2dpSink service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return service.getPriority(device);
+ return service.getConnectionPolicy(device);
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
- return BluetoothProfile.PRIORITY_OFF;
+ return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
}
}
if (service == null) Log.w(TAG, "Proxy not attached to service");
- return BluetoothProfile.PRIORITY_OFF;
+ return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
}
/**
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 89f9cbc..9b5280d 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -27,6 +27,7 @@
import android.annotation.SystemApi;
import android.annotation.UnsupportedAppUsage;
import android.app.ActivityThread;
+import android.bluetooth.BluetoothProfile.ConnectionPolicy;
import android.bluetooth.le.BluetoothLeAdvertiser;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.PeriodicAdvertisingManager;
@@ -3447,4 +3448,48 @@
void onMetadataChanged(@NonNull BluetoothDevice device, int key,
@Nullable byte[] value);
}
+
+ /**
+ * Converts old constant of priority to the new for connection policy
+ *
+ * @param priority is the priority to convert to connection policy
+ * @return the equivalent connection policy constant to the priority
+ *
+ * @hide
+ */
+ public static @ConnectionPolicy int priorityToConnectionPolicy(int priority) {
+ switch(priority) {
+ case BluetoothProfile.PRIORITY_AUTO_CONNECT:
+ return BluetoothProfile.CONNECTION_POLICY_ALLOWED;
+ case BluetoothProfile.PRIORITY_ON:
+ return BluetoothProfile.CONNECTION_POLICY_ALLOWED;
+ case BluetoothProfile.PRIORITY_OFF:
+ return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
+ case BluetoothProfile.PRIORITY_UNDEFINED:
+ return BluetoothProfile.CONNECTION_POLICY_UNKNOWN;
+ default:
+ Log.e(TAG, "setPriority: Invalid priority: " + priority);
+ return BluetoothProfile.CONNECTION_POLICY_UNKNOWN;
+ }
+ }
+
+ /**
+ * Converts new constant of connection policy to the old for priority
+ *
+ * @param connectionPolicy is the connection policy to convert to priority
+ * @return the equivalent priority constant to the connectionPolicy
+ *
+ * @hide
+ */
+ public static int connectionPolicyToPriority(@ConnectionPolicy int connectionPolicy) {
+ switch(connectionPolicy) {
+ case BluetoothProfile.CONNECTION_POLICY_ALLOWED:
+ return BluetoothProfile.PRIORITY_ON;
+ case BluetoothProfile.CONNECTION_POLICY_FORBIDDEN:
+ return BluetoothProfile.PRIORITY_OFF;
+ case BluetoothProfile.CONNECTION_POLICY_UNKNOWN:
+ return BluetoothProfile.PRIORITY_UNDEFINED;
+ }
+ return BluetoothProfile.PRIORITY_UNDEFINED;
+ }
}
diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java
index 672174f..ea3831a 100644
--- a/core/java/android/bluetooth/BluetoothHeadset.java
+++ b/core/java/android/bluetooth/BluetoothHeadset.java
@@ -17,6 +17,7 @@
package android.bluetooth;
import android.Manifest;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
@@ -560,26 +561,45 @@
* Priority can be one of {@link BluetoothProfile#PRIORITY_ON} or
* {@link BluetoothProfile#PRIORITY_OFF},
*
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
- * permission.
- *
* @param device Paired bluetooth device
* @param priority
* @return true if priority is set, false on error
* @hide
+ * @deprecated Replaced with {@link #setConnectionPolicy(BluetoothDevice, int)}
*/
+ @Deprecated
@SystemApi
@RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN)
public boolean setPriority(BluetoothDevice device, int priority) {
if (DBG) log("setPriority(" + device + ", " + priority + ")");
+ return setConnectionPolicy(device, BluetoothAdapter.priorityToConnectionPolicy(priority));
+ }
+
+ /**
+ * Set connection policy of the profile
+ *
+ * <p> The device should already be paired.
+ * Connection policy can be one of {@link #CONNECTION_POLICY_ALLOWED},
+ * {@link #CONNECTION_POLICY_FORBIDDEN}, {@link #CONNECTION_POLICY_UNKNOWN}
+ *
+ * @param device Paired bluetooth device
+ * @param connectionPolicy is the connection policy to set to for this profile
+ * @return true if connectionPolicy is set, false on error
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
+ public boolean setConnectionPolicy(@NonNull BluetoothDevice device,
+ @ConnectionPolicy int connectionPolicy) {
+ if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
final IBluetoothHeadset service = mService;
if (service != null && isEnabled() && isValidDevice(device)) {
- if (priority != BluetoothProfile.PRIORITY_OFF
- && priority != BluetoothProfile.PRIORITY_ON) {
+ if (connectionPolicy != BluetoothProfile.CONNECTION_POLICY_FORBIDDEN
+ && connectionPolicy != BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
return false;
}
try {
- return service.setPriority(device, priority);
+ return service.setConnectionPolicy(device, connectionPolicy);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
return false;
@@ -596,26 +616,43 @@
* {@link #PRIORITY_AUTO_CONNECT}, {@link #PRIORITY_OFF},
* {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
*
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
* @param device Bluetooth device
* @return priority of the device
* @hide
*/
@UnsupportedAppUsage
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
public int getPriority(BluetoothDevice device) {
if (VDBG) log("getPriority(" + device + ")");
+ return BluetoothAdapter.connectionPolicyToPriority(getConnectionPolicy(device));
+ }
+
+ /**
+ * Get the connection policy of the profile.
+ *
+ * <p> The connection policy can be any of:
+ * {@link #CONNECTION_POLICY_ALLOWED}, {@link #CONNECTION_POLICY_FORBIDDEN},
+ * {@link #CONNECTION_POLICY_UNKNOWN}
+ *
+ * @param device Bluetooth device
+ * @return connection policy of the device
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
+ public @ConnectionPolicy int getConnectionPolicy(@NonNull BluetoothDevice device) {
+ if (VDBG) log("getConnectionPolicy(" + device + ")");
final IBluetoothHeadset service = mService;
if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return service.getPriority(device);
+ return service.getConnectionPolicy(device);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
- return PRIORITY_OFF;
+ return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
}
}
if (service == null) Log.w(TAG, "Proxy not attached to service");
- return PRIORITY_OFF;
+ return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
}
/**
diff --git a/core/java/android/bluetooth/BluetoothHeadsetClient.java b/core/java/android/bluetooth/BluetoothHeadsetClient.java
index 5d00f09..a8e1fd2 100644
--- a/core/java/android/bluetooth/BluetoothHeadsetClient.java
+++ b/core/java/android/bluetooth/BluetoothHeadsetClient.java
@@ -16,6 +16,9 @@
package android.bluetooth;
+import android.Manifest;
+import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
import android.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Binder;
@@ -553,19 +556,45 @@
/**
* Set priority of the profile
*
- * The device should already be paired.
+ * <p> The device should already be paired.
+ * Priority can be one of {@link #PRIORITY_ON} or {@link #PRIORITY_OFF},
+ *
+ * @param device Paired bluetooth device
+ * @param priority
+ * @return true if priority is set, false on error
+ * @hide
*/
+ @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
public boolean setPriority(BluetoothDevice device, int priority) {
if (DBG) log("setPriority(" + device + ", " + priority + ")");
+ return setConnectionPolicy(device, BluetoothAdapter.priorityToConnectionPolicy(priority));
+ }
+
+ /**
+ * Set connection policy of the profile
+ *
+ * <p> The device should already be paired.
+ * Connection policy can be one of {@link #CONNECTION_POLICY_ALLOWED},
+ * {@link #CONNECTION_POLICY_FORBIDDEN}, {@link #CONNECTION_POLICY_UNKNOWN}
+ *
+ * @param device Paired bluetooth device
+ * @param connectionPolicy is the connection policy to set to for this profile
+ * @return true if connectionPolicy is set, false on error
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
+ public boolean setConnectionPolicy(BluetoothDevice device, int connectionPolicy) {
+ if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
final IBluetoothHeadsetClient service =
getService();
if (service != null && isEnabled() && isValidDevice(device)) {
- if (priority != BluetoothProfile.PRIORITY_OFF
- && priority != BluetoothProfile.PRIORITY_ON) {
+ if (connectionPolicy != BluetoothProfile.CONNECTION_POLICY_FORBIDDEN
+ && connectionPolicy != BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
return false;
}
try {
- return service.setPriority(device, priority);
+ return service.setConnectionPolicy(device, connectionPolicy);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
return false;
@@ -577,21 +606,47 @@
/**
* Get the priority of the profile.
+ *
+ * <p> The priority can be any of:
+ * {@link #PRIORITY_OFF}, {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
+ *
+ * @param device Bluetooth device
+ * @return priority of the device
+ * @hide
*/
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
public int getPriority(BluetoothDevice device) {
if (VDBG) log("getPriority(" + device + ")");
+ return BluetoothAdapter.connectionPolicyToPriority(getConnectionPolicy(device));
+ }
+
+ /**
+ * Get the connection policy of the profile.
+ *
+ * <p> The connection policy can be any of:
+ * {@link #CONNECTION_POLICY_ALLOWED}, {@link #CONNECTION_POLICY_FORBIDDEN},
+ * {@link #CONNECTION_POLICY_UNKNOWN}
+ *
+ * @param device Bluetooth device
+ * @return connection policy of the device
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
+ public int getConnectionPolicy(BluetoothDevice device) {
+ if (VDBG) log("getConnectionPolicy(" + device + ")");
final IBluetoothHeadsetClient service =
getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return service.getPriority(device);
+ return service.getConnectionPolicy(device);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
- return PRIORITY_OFF;
+ return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
}
}
if (service == null) Log.w(TAG, "Proxy not attached to service");
- return PRIORITY_OFF;
+ return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
}
/**
diff --git a/core/java/android/bluetooth/BluetoothHearingAid.java b/core/java/android/bluetooth/BluetoothHearingAid.java
index a812c32..ead8429 100644
--- a/core/java/android/bluetooth/BluetoothHearingAid.java
+++ b/core/java/android/bluetooth/BluetoothHearingAid.java
@@ -22,6 +22,7 @@
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.SystemApi;
import android.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Binder;
@@ -355,28 +356,45 @@
* Set priority of the profile
*
* <p> The device should already be paired.
- * Priority can be one of {@link #PRIORITY_ON} orgetBluetoothManager
- * {@link #PRIORITY_OFF},
- *
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
- * permission.
+ * Priority can be one of {@link #PRIORITY_ON} or {@link #PRIORITY_OFF},
*
* @param device Paired bluetooth device
* @param priority
* @return true if priority is set, false on error
* @hide
*/
+ @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
public boolean setPriority(BluetoothDevice device, int priority) {
if (DBG) log("setPriority(" + device + ", " + priority + ")");
+ return setConnectionPolicy(device, BluetoothAdapter.priorityToConnectionPolicy(priority));
+ }
+
+ /**
+ * Set connection policy of the profile
+ *
+ * <p> The device should already be paired.
+ * Connection policy can be one of {@link #CONNECTION_POLICY_ALLOWED},
+ * {@link #CONNECTION_POLICY_FORBIDDEN}, {@link #CONNECTION_POLICY_UNKNOWN}
+ *
+ * @param device Paired bluetooth device
+ * @param connectionPolicy is the connection policy to set to for this profile
+ * @return true if connectionPolicy is set, false on error
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
+ public boolean setConnectionPolicy(@NonNull BluetoothDevice device,
+ @ConnectionPolicy int connectionPolicy) {
+ if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
final IBluetoothHearingAid service = getService();
try {
if (service != null && isEnabled()
&& isValidDevice(device)) {
- if (priority != BluetoothProfile.PRIORITY_OFF
- && priority != BluetoothProfile.PRIORITY_ON) {
+ if (connectionPolicy != BluetoothProfile.CONNECTION_POLICY_FORBIDDEN
+ && connectionPolicy != BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
return false;
}
- return service.setPriority(device, priority);
+ return service.setConnectionPolicy(device, connectionPolicy);
}
if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
@@ -390,8 +408,7 @@
* Get the priority of the profile.
*
* <p> The priority can be any of:
- * {@link #PRIORITY_AUTO_CONNECT}, {@link #PRIORITY_OFF},
- * {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
+ * {@link #PRIORITY_OFF}, {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
*
* @param device Bluetooth device
* @return priority of the device
@@ -400,17 +417,35 @@
@RequiresPermission(Manifest.permission.BLUETOOTH)
public int getPriority(BluetoothDevice device) {
if (VDBG) log("getPriority(" + device + ")");
+ return BluetoothAdapter.connectionPolicyToPriority(getConnectionPolicy(device));
+ }
+
+ /**
+ * Get the connection policy of the profile.
+ *
+ * <p> The connection policy can be any of:
+ * {@link #CONNECTION_POLICY_ALLOWED}, {@link #CONNECTION_POLICY_FORBIDDEN},
+ * {@link #CONNECTION_POLICY_UNKNOWN}
+ *
+ * @param device Bluetooth device
+ * @return connection policy of the device
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
+ public @ConnectionPolicy int getConnectionPolicy(@NonNull BluetoothDevice device) {
+ if (VDBG) log("getConnectionPolicy(" + device + ")");
final IBluetoothHearingAid service = getService();
try {
if (service != null && isEnabled()
&& isValidDevice(device)) {
- return service.getPriority(device);
+ return service.getConnectionPolicy(device);
}
if (service == null) Log.w(TAG, "Proxy not attached to service");
- return BluetoothProfile.PRIORITY_OFF;
+ return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
- return BluetoothProfile.PRIORITY_OFF;
+ return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
}
}
diff --git a/core/java/android/bluetooth/BluetoothHidHost.java b/core/java/android/bluetooth/BluetoothHidHost.java
index 4afb382..8f5cdf0 100644
--- a/core/java/android/bluetooth/BluetoothHidHost.java
+++ b/core/java/android/bluetooth/BluetoothHidHost.java
@@ -16,8 +16,11 @@
package android.bluetooth;
+import android.Manifest;
+import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.SystemApi;
import android.content.Context;
import android.os.Binder;
import android.os.IBinder;
@@ -379,27 +382,43 @@
* Set priority of the profile
*
* <p> The device should already be paired.
- * Priority can be one of {@link #PRIORITY_ON} or
- * {@link #PRIORITY_OFF},
- *
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
- * permission.
+ * Priority can be one of {@link #PRIORITY_ON} or {@link #PRIORITY_OFF},
*
* @param device Paired bluetooth device
* @param priority
* @return true if priority is set, false on error
* @hide
*/
+ @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
public boolean setPriority(BluetoothDevice device, int priority) {
if (DBG) log("setPriority(" + device + ", " + priority + ")");
+ return setConnectionPolicy(device, BluetoothAdapter.priorityToConnectionPolicy(priority));
+ }
+
+ /**
+ * Set connection policy of the profile
+ *
+ * <p> The device should already be paired.
+ * Connection policy can be one of {@link #CONNECTION_POLICY_ALLOWED},
+ * {@link #CONNECTION_POLICY_FORBIDDEN}, {@link #CONNECTION_POLICY_UNKNOWN}
+ *
+ * @param device Paired bluetooth device
+ * @param connectionPolicy is the connection policy to set to for this profile
+ * @return true if connectionPolicy is set, false on error
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
+ public boolean setConnectionPolicy(BluetoothDevice device, int connectionPolicy) {
+ if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
final IBluetoothHidHost service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
- if (priority != BluetoothProfile.PRIORITY_OFF
- && priority != BluetoothProfile.PRIORITY_ON) {
+ if (connectionPolicy != BluetoothProfile.CONNECTION_POLICY_FORBIDDEN
+ && connectionPolicy != BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
return false;
}
try {
- return service.setPriority(device, priority);
+ return service.setConnectionPolicy(device, connectionPolicy);
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return false;
@@ -413,28 +432,44 @@
* Get the priority of the profile.
*
* <p> The priority can be any of:
- * {@link #PRIORITY_AUTO_CONNECT}, {@link #PRIORITY_OFF},
- * {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
- *
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+ * {@link #PRIORITY_OFF}, {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
*
* @param device Bluetooth device
* @return priority of the device
* @hide
*/
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
public int getPriority(BluetoothDevice device) {
if (VDBG) log("getPriority(" + device + ")");
+ return BluetoothAdapter.connectionPolicyToPriority(getConnectionPolicy(device));
+ }
+
+ /**
+ * Get the connection policy of the profile.
+ *
+ * <p> The connection policy can be any of:
+ * {@link #CONNECTION_POLICY_ALLOWED}, {@link #CONNECTION_POLICY_FORBIDDEN},
+ * {@link #CONNECTION_POLICY_UNKNOWN}
+ *
+ * @param device Bluetooth device
+ * @return connection policy of the device
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
+ public int getConnectionPolicy(BluetoothDevice device) {
+ if (VDBG) log("getConnectionPolicy(" + device + ")");
final IBluetoothHidHost service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return service.getPriority(device);
+ return service.getConnectionPolicy(device);
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
- return BluetoothProfile.PRIORITY_OFF;
+ return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
}
}
if (service == null) Log.w(TAG, "Proxy not attached to service");
- return BluetoothProfile.PRIORITY_OFF;
+ return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
}
private boolean isEnabled() {
diff --git a/core/java/android/bluetooth/BluetoothMap.java b/core/java/android/bluetooth/BluetoothMap.java
index dd2f150..979dfd4 100644
--- a/core/java/android/bluetooth/BluetoothMap.java
+++ b/core/java/android/bluetooth/BluetoothMap.java
@@ -16,6 +16,9 @@
package android.bluetooth;
+import android.Manifest;
+import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
import android.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Binder;
@@ -271,23 +274,43 @@
* Set priority of the profile
*
* <p> The device should already be paired.
- * Priority can be one of {@link #PRIORITY_ON} or
- * {@link #PRIORITY_OFF},
+ * Priority can be one of {@link #PRIORITY_ON} or {@link #PRIORITY_OFF},
*
* @param device Paired bluetooth device
* @param priority
* @return true if priority is set, false on error
+ * @hide
*/
+ @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
public boolean setPriority(BluetoothDevice device, int priority) {
if (DBG) log("setPriority(" + device + ", " + priority + ")");
+ return setConnectionPolicy(device, BluetoothAdapter.priorityToConnectionPolicy(priority));
+ }
+
+ /**
+ * Set connection policy of the profile
+ *
+ * <p> The device should already be paired.
+ * Connection policy can be one of {@link #CONNECTION_POLICY_ALLOWED},
+ * {@link #CONNECTION_POLICY_FORBIDDEN}, {@link #CONNECTION_POLICY_UNKNOWN}
+ *
+ * @param device Paired bluetooth device
+ * @param connectionPolicy is the connection policy to set to for this profile
+ * @return true if connectionPolicy is set, false on error
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
+ public boolean setConnectionPolicy(BluetoothDevice device, int connectionPolicy) {
+ if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
final IBluetoothMap service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
- if (priority != BluetoothProfile.PRIORITY_OFF
- && priority != BluetoothProfile.PRIORITY_ON) {
+ if (connectionPolicy != BluetoothProfile.CONNECTION_POLICY_FORBIDDEN
+ && connectionPolicy != BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
return false;
}
try {
- return service.setPriority(device, priority);
+ return service.setConnectionPolicy(device, connectionPolicy);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
return false;
@@ -301,25 +324,44 @@
* Get the priority of the profile.
*
* <p> The priority can be any of:
- * {@link #PRIORITY_AUTO_CONNECT}, {@link #PRIORITY_OFF},
- * {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
+ * {@link #PRIORITY_OFF}, {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
*
* @param device Bluetooth device
* @return priority of the device
+ * @hide
*/
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
public int getPriority(BluetoothDevice device) {
if (VDBG) log("getPriority(" + device + ")");
+ return BluetoothAdapter.connectionPolicyToPriority(getConnectionPolicy(device));
+ }
+
+ /**
+ * Get the connection policy of the profile.
+ *
+ * <p> The connection policy can be any of:
+ * {@link #CONNECTION_POLICY_ALLOWED}, {@link #CONNECTION_POLICY_FORBIDDEN},
+ * {@link #CONNECTION_POLICY_UNKNOWN}
+ *
+ * @param device Bluetooth device
+ * @return connection policy of the device
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
+ public int getConnectionPolicy(BluetoothDevice device) {
+ if (VDBG) log("getConnectionPolicy(" + device + ")");
final IBluetoothMap service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return service.getPriority(device);
+ return service.getConnectionPolicy(device);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
- return PRIORITY_OFF;
+ return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
}
}
if (service == null) Log.w(TAG, "Proxy not attached to service");
- return PRIORITY_OFF;
+ return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
}
private static void log(String msg) {
diff --git a/core/java/android/bluetooth/BluetoothMapClient.java b/core/java/android/bluetooth/BluetoothMapClient.java
index 69682c6..0ec473c 100644
--- a/core/java/android/bluetooth/BluetoothMapClient.java
+++ b/core/java/android/bluetooth/BluetoothMapClient.java
@@ -16,6 +16,9 @@
package android.bluetooth;
+import android.Manifest;
+import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
import android.annotation.UnsupportedAppUsage;
import android.app.PendingIntent;
import android.content.Context;
@@ -240,22 +243,44 @@
/**
* Set priority of the profile
*
- * <p> The device should already be paired. Priority can be one of {@link #PRIORITY_ON} or
- * {@link #PRIORITY_OFF},
+ * <p> The device should already be paired.
+ * Priority can be one of {@link #PRIORITY_ON} or {@link #PRIORITY_OFF},
*
* @param device Paired bluetooth device
+ * @param priority
* @return true if priority is set, false on error
+ * @hide
*/
+ @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
public boolean setPriority(BluetoothDevice device, int priority) {
if (DBG) Log.d(TAG, "setPriority(" + device + ", " + priority + ")");
+ return setConnectionPolicy(device, BluetoothAdapter.priorityToConnectionPolicy(priority));
+ }
+
+ /**
+ * Set connection policy of the profile
+ *
+ * <p> The device should already be paired.
+ * Connection policy can be one of {@link #CONNECTION_POLICY_ALLOWED},
+ * {@link #CONNECTION_POLICY_FORBIDDEN}, {@link #CONNECTION_POLICY_UNKNOWN}
+ *
+ * @param device Paired bluetooth device
+ * @param connectionPolicy is the connection policy to set to for this profile
+ * @return true if connectionPolicy is set, false on error
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
+ public boolean setConnectionPolicy(BluetoothDevice device, int connectionPolicy) {
+ if (DBG) Log.d(TAG, "setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
final IBluetoothMapClient service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
- if (priority != BluetoothProfile.PRIORITY_OFF
- && priority != BluetoothProfile.PRIORITY_ON) {
+ if (connectionPolicy != BluetoothProfile.CONNECTION_POLICY_FORBIDDEN
+ && connectionPolicy != BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
return false;
}
try {
- return service.setPriority(device, priority);
+ return service.setConnectionPolicy(device, connectionPolicy);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
return false;
@@ -269,25 +294,44 @@
* Get the priority of the profile.
*
* <p> The priority can be any of:
- * {@link #PRIORITY_AUTO_CONNECT}, {@link #PRIORITY_OFF},
- * {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
+ * {@link #PRIORITY_OFF}, {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
*
* @param device Bluetooth device
* @return priority of the device
+ * @hide
*/
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
public int getPriority(BluetoothDevice device) {
if (VDBG) Log.d(TAG, "getPriority(" + device + ")");
+ return BluetoothAdapter.connectionPolicyToPriority(getConnectionPolicy(device));
+ }
+
+ /**
+ * Get the connection policy of the profile.
+ *
+ * <p> The connection policy can be any of:
+ * {@link #CONNECTION_POLICY_ALLOWED}, {@link #CONNECTION_POLICY_FORBIDDEN},
+ * {@link #CONNECTION_POLICY_UNKNOWN}
+ *
+ * @param device Bluetooth device
+ * @return connection policy of the device
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
+ public int getConnectionPolicy(BluetoothDevice device) {
+ if (VDBG) Log.d(TAG, "getConnectionPolicy(" + device + ")");
final IBluetoothMapClient service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return service.getPriority(device);
+ return service.getConnectionPolicy(device);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
- return PRIORITY_OFF;
+ return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
}
}
if (service == null) Log.w(TAG, "Proxy not attached to service");
- return PRIORITY_OFF;
+ return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
}
/**
diff --git a/core/java/android/bluetooth/BluetoothPbapClient.java b/core/java/android/bluetooth/BluetoothPbapClient.java
index d70e1e7..9618ba0 100644
--- a/core/java/android/bluetooth/BluetoothPbapClient.java
+++ b/core/java/android/bluetooth/BluetoothPbapClient.java
@@ -16,6 +16,9 @@
package android.bluetooth;
+import android.Manifest;
+import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
import android.content.Context;
import android.os.Binder;
import android.os.IBinder;
@@ -241,25 +244,45 @@
* Set priority of the profile
*
* <p> The device should already be paired.
- * Priority can be one of {@link #PRIORITY_ON} or
- * {@link #PRIORITY_OFF},
+ * Priority can be one of {@link #PRIORITY_ON} or {@link #PRIORITY_OFF},
*
* @param device Paired bluetooth device
- * @param priority Priority of this profile
+ * @param priority
* @return true if priority is set, false on error
+ * @hide
*/
+ @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
public boolean setPriority(BluetoothDevice device, int priority) {
+ if (DBG) log("setPriority(" + device + ", " + priority + ")");
+ return setConnectionPolicy(device, BluetoothAdapter.priorityToConnectionPolicy(priority));
+ }
+
+ /**
+ * Set connection policy of the profile
+ *
+ * <p> The device should already be paired.
+ * Connection policy can be one of {@link #CONNECTION_POLICY_ALLOWED},
+ * {@link #CONNECTION_POLICY_FORBIDDEN}, {@link #CONNECTION_POLICY_UNKNOWN}
+ *
+ * @param device Paired bluetooth device
+ * @param connectionPolicy is the connection policy to set to for this profile
+ * @return true if connectionPolicy is set, false on error
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
+ public boolean setConnectionPolicy(BluetoothDevice device, int connectionPolicy) {
if (DBG) {
- log("setPriority(" + device + ", " + priority + ")");
+ log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
}
final IBluetoothPbapClient service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
- if (priority != BluetoothProfile.PRIORITY_OFF
- && priority != BluetoothProfile.PRIORITY_ON) {
+ if (connectionPolicy != BluetoothProfile.CONNECTION_POLICY_FORBIDDEN
+ && connectionPolicy != BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
return false;
}
try {
- return service.setPriority(device, priority);
+ return service.setConnectionPolicy(device, connectionPolicy);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
return false;
@@ -275,28 +298,47 @@
* Get the priority of the profile.
*
* <p> The priority can be any of:
- * {@link #PRIORITY_AUTO_CONNECT}, {@link #PRIORITY_OFF},
- * {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
+ * {@link #PRIORITY_OFF}, {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
*
* @param device Bluetooth device
* @return priority of the device
+ * @hide
*/
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
public int getPriority(BluetoothDevice device) {
+ if (VDBG) log("getPriority(" + device + ")");
+ return BluetoothAdapter.connectionPolicyToPriority(getConnectionPolicy(device));
+ }
+
+ /**
+ * Get the connection policy of the profile.
+ *
+ * <p> The connection policy can be any of:
+ * {@link #CONNECTION_POLICY_ALLOWED}, {@link #CONNECTION_POLICY_FORBIDDEN},
+ * {@link #CONNECTION_POLICY_UNKNOWN}
+ *
+ * @param device Bluetooth device
+ * @return connection policy of the device
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
+ public int getConnectionPolicy(BluetoothDevice device) {
if (VDBG) {
- log("getPriority(" + device + ")");
+ log("getConnectionPolicy(" + device + ")");
}
final IBluetoothPbapClient service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return service.getPriority(device);
+ return service.getConnectionPolicy(device);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
- return PRIORITY_OFF;
+ return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
}
}
if (service == null) {
Log.w(TAG, "Proxy not attached to service");
}
- return PRIORITY_OFF;
+ return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
}
}
diff --git a/core/java/android/bluetooth/BluetoothProfile.java b/core/java/android/bluetooth/BluetoothProfile.java
index f1ac765..097a367 100644
--- a/core/java/android/bluetooth/BluetoothProfile.java
+++ b/core/java/android/bluetooth/BluetoothProfile.java
@@ -225,7 +225,9 @@
* and outgoing connections for the profile
*
* @hide
+ * @deprecated Replaced with {@link #CONNECTION_POLICY_ALLOWED}
**/
+ @Deprecated
@SystemApi
int PRIORITY_ON = 100;
@@ -234,7 +236,9 @@
* connections and outgoing connections for the profile.
*
* @hide
+ * @deprecated Replaced with {@link #CONNECTION_POLICY_FORBIDDEN}
**/
+ @Deprecated
@SystemApi
int PRIORITY_OFF = 0;
@@ -246,6 +250,38 @@
@UnsupportedAppUsage
int PRIORITY_UNDEFINED = -1;
+ /** @hide */
+ @IntDef(prefix = "CONNECTION_POLICY_", value = {CONNECTION_POLICY_ALLOWED,
+ CONNECTION_POLICY_FORBIDDEN, CONNECTION_POLICY_UNKNOWN})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ConnectionPolicy{}
+
+ /**
+ * Default connection policy for devices that allow incoming and outgoing connections
+ * for the profile
+ *
+ * @hide
+ **/
+ @SystemApi
+ int CONNECTION_POLICY_ALLOWED = 100;
+
+ /**
+ * Default connection policy for devices that do not allow incoming or outgoing connections
+ * for the profile.
+ *
+ * @hide
+ **/
+ @SystemApi
+ int CONNECTION_POLICY_FORBIDDEN = 0;
+
+ /**
+ * Default connection policy when not set or when the device is unpaired
+ *
+ * @hide
+ */
+ @SystemApi
+ int CONNECTION_POLICY_UNKNOWN = -1;
+
/**
* Get connected devices for this specific profile.
*
diff --git a/core/java/android/bluetooth/BluetoothSap.java b/core/java/android/bluetooth/BluetoothSap.java
index e0610c8..9b4dabc 100644
--- a/core/java/android/bluetooth/BluetoothSap.java
+++ b/core/java/android/bluetooth/BluetoothSap.java
@@ -16,6 +16,9 @@
package android.bluetooth;
+import android.Manifest;
+import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
import android.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Binder;
@@ -300,22 +303,43 @@
* Set priority of the profile
*
* <p> The device should already be paired.
+ * Priority can be one of {@link #PRIORITY_ON} or {@link #PRIORITY_OFF},
*
* @param device Paired bluetooth device
* @param priority
* @return true if priority is set, false on error
* @hide
*/
+ @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
public boolean setPriority(BluetoothDevice device, int priority) {
if (DBG) log("setPriority(" + device + ", " + priority + ")");
+ return setConnectionPolicy(device, BluetoothAdapter.priorityToConnectionPolicy(priority));
+ }
+
+ /**
+ * Set connection policy of the profile
+ *
+ * <p> The device should already be paired.
+ * Connection policy can be one of {@link #CONNECTION_POLICY_ALLOWED},
+ * {@link #CONNECTION_POLICY_FORBIDDEN}, {@link #CONNECTION_POLICY_UNKNOWN}
+ *
+ * @param device Paired bluetooth device
+ * @param connectionPolicy is the connection policy to set to for this profile
+ * @return true if connectionPolicy is set, false on error
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
+ public boolean setConnectionPolicy(BluetoothDevice device, int connectionPolicy) {
+ if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
final IBluetoothSap service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
- if (priority != BluetoothProfile.PRIORITY_OFF
- && priority != BluetoothProfile.PRIORITY_ON) {
+ if (connectionPolicy != BluetoothProfile.CONNECTION_POLICY_FORBIDDEN
+ && connectionPolicy != BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
return false;
}
try {
- return service.setPriority(device, priority);
+ return service.setConnectionPolicy(device, connectionPolicy);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
return false;
@@ -328,23 +352,45 @@
/**
* Get the priority of the profile.
*
+ * <p> The priority can be any of:
+ * {@link #PRIORITY_OFF}, {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
+ *
* @param device Bluetooth device
* @return priority of the device
* @hide
*/
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
public int getPriority(BluetoothDevice device) {
if (VDBG) log("getPriority(" + device + ")");
+ return BluetoothAdapter.connectionPolicyToPriority(getConnectionPolicy(device));
+ }
+
+ /**
+ * Get the connection policy of the profile.
+ *
+ * <p> The connection policy can be any of:
+ * {@link #CONNECTION_POLICY_ALLOWED}, {@link #CONNECTION_POLICY_FORBIDDEN},
+ * {@link #CONNECTION_POLICY_UNKNOWN}
+ *
+ * @param device Bluetooth device
+ * @return connection policy of the device
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
+ public int getConnectionPolicy(BluetoothDevice device) {
+ if (VDBG) log("getConnectionPolicy(" + device + ")");
final IBluetoothSap service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return service.getPriority(device);
+ return service.getConnectionPolicy(device);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
- return PRIORITY_OFF;
+ return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
}
}
if (service == null) Log.w(TAG, "Proxy not attached to service");
- return PRIORITY_OFF;
+ return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
}
private static void log(String msg) {
diff --git a/core/java/android/telephony/PhoneStateListener.java b/core/java/android/telephony/PhoneStateListener.java
index a65c8fd..716a522 100644
--- a/core/java/android/telephony/PhoneStateListener.java
+++ b/core/java/android/telephony/PhoneStateListener.java
@@ -286,14 +286,6 @@
public static final int LISTEN_USER_MOBILE_DATA_STATE = 0x00080000;
/**
- * Listen for changes to the physical channel configuration.
- *
- * @see #onPhysicalChannelConfigurationChanged
- * @hide
- */
- public static final int LISTEN_PHYSICAL_CHANNEL_CONFIGURATION = 0x00100000;
-
- /**
* Listen for changes to the phone capability.
*
* @see #onPhoneCapabilityChanged
@@ -831,24 +823,6 @@
}
/**
- * Callback invoked when the current physical channel configuration has changed on the
- * registered subscription.
- * Note, the registration subId comes from {@link TelephonyManager} object which registers
- * PhoneStateListener by {@link TelephonyManager#listen(PhoneStateListener, int)}.
- * If this TelephonyManager object was created with
- * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
- * subId. Otherwise, this callback applies to
- * {@link SubscriptionManager#getDefaultSubscriptionId()}.
- *
- * @param configs List of the current {@link PhysicalChannelConfig}s
- * @hide
- */
- public void onPhysicalChannelConfigurationChanged(
- @NonNull List<PhysicalChannelConfig> configs) {
- // default implementation empty
- }
-
- /**
* Callback invoked when the current emergency number list has changed on the registered
* subscription.
* Note, the registration subId comes from {@link TelephonyManager} object which registers
@@ -1194,15 +1168,6 @@
() -> mExecutor.execute(() -> psl.onCarrierNetworkChange(active)));
}
- public void onPhysicalChannelConfigurationChanged(List<PhysicalChannelConfig> configs) {
- PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
- if (psl == null) return;
-
- Binder.withCleanCallingIdentity(
- () -> mExecutor.execute(
- () -> psl.onPhysicalChannelConfigurationChanged(configs)));
- }
-
public void onEmergencyNumberListChanged(Map emergencyNumberList) {
PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
if (psl == null) return;
diff --git a/core/java/android/text/LoginFilter.java b/core/java/android/text/LoginFilter.java
index e2d1596..0e4eec44 100644
--- a/core/java/android/text/LoginFilter.java
+++ b/core/java/android/text/LoginFilter.java
@@ -19,7 +19,10 @@
/**
* Abstract class for filtering login-related text (user names and passwords)
*
+ * @deprecated Password requirements should not be hardcoded in clients. This class also does not
+ * handle non-BMP characters.
*/
+@Deprecated
public abstract class LoginFilter implements InputFilter {
private boolean mAppendInvalid; // whether to append or ignore invalid characters
/**
@@ -130,7 +133,9 @@
* account creation. It prevents the user from entering user names with characters other than
* [a-zA-Z0-9.].
*
+ * @deprecated Do not encode assumptions about Google account names into client applications.
*/
+ @Deprecated
public static class UsernameFilterGMail extends LoginFilter {
public UsernameFilterGMail() {
@@ -190,8 +195,12 @@
/**
* This filter is compatible with GMail passwords which restricts characters to
* the Latin-1 (ISO8859-1) char set.
- *
+ *
+ * @deprecated Do not handle a user's Google password. Refer to
+ * <a href="https://support.google.com/accounts/answer/32040">Google Help</a> for
+ * password restriction information.
*/
+ @Deprecated
public static class PasswordFilterGMail extends LoginFilter {
public PasswordFilterGMail() {
diff --git a/core/java/com/android/internal/telephony/IPhoneStateListener.aidl b/core/java/com/android/internal/telephony/IPhoneStateListener.aidl
index 084a3cc..01f5743 100644
--- a/core/java/com/android/internal/telephony/IPhoneStateListener.aidl
+++ b/core/java/com/android/internal/telephony/IPhoneStateListener.aidl
@@ -21,7 +21,6 @@
import android.telephony.CellInfo;
import android.telephony.DataConnectionRealTimeInfo;
import android.telephony.PhoneCapability;
-import android.telephony.PhysicalChannelConfig;
import android.telephony.PreciseCallState;
import android.telephony.PreciseDataConnectionState;
import android.telephony.ServiceState;
@@ -44,7 +43,6 @@
void onDataConnectionStateChanged(int state, int networkType);
void onDataActivity(int direction);
void onSignalStrengthsChanged(in SignalStrength signalStrength);
- void onPhysicalChannelConfigurationChanged(in List<PhysicalChannelConfig> configs);
void onOtaspChanged(in int otaspMode);
void onCellInfoChanged(in List<CellInfo> cellInfo);
void onPreciseCallStateChanged(in PreciseCallState callState);
diff --git a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
index 9ae0ba5..2f34aa0 100644
--- a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
+++ b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
@@ -24,7 +24,6 @@
import android.telephony.CellInfo;
import android.telephony.ims.ImsReasonInfo;
import android.telephony.PhoneCapability;
-import android.telephony.PhysicalChannelConfig;
import android.telephony.ServiceState;
import android.telephony.SignalStrength;
import android.telephony.emergency.EmergencyNumber;
@@ -78,8 +77,6 @@
void notifyOtaspChanged(in int subId, in int otaspMode);
@UnsupportedAppUsage
void notifyCellInfo(in List<CellInfo> cellInfo);
- void notifyPhysicalChannelConfigurationForSubscriber(in int phoneId, in int subId,
- in List<PhysicalChannelConfig> configs);
void notifyPreciseCallState(int phoneId, int subId, int ringingCallState,
int foregroundCallState, int backgroundCallState);
void notifyDisconnectCause(int phoneId, int subId, int disconnectCause,
diff --git a/core/proto/android/stats/devicepolicy/device_policy_enums.proto b/core/proto/android/stats/devicepolicy/device_policy_enums.proto
index 15813a1..f8c304c 100644
--- a/core/proto/android/stats/devicepolicy/device_policy_enums.proto
+++ b/core/proto/android/stats/devicepolicy/device_policy_enums.proto
@@ -151,4 +151,5 @@
PROVISIONING_FLOW_TYPE = 124;
CROSS_PROFILE_APPS_GET_TARGET_USER_PROFILES = 125;
CROSS_PROFILE_APPS_START_ACTIVITY_AS_USER = 126;
+ SET_AUTO_TIME = 127;
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtilsInternal.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtilsInternal.java
index 9672fea..9f16d03 100644
--- a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtilsInternal.java
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtilsInternal.java
@@ -408,23 +408,6 @@
}
/**
- * Checks if {@link android.app.admin.DevicePolicyManager#setAutoTimeRequired} is enforced
- * on the device.
- *
- * @return EnforcedAdmin Object containing the device owner component and
- * userId the device owner is running as, or {@code null} setAutoTimeRequired is not enforced.
- */
- public static EnforcedAdmin checkIfAutoTimeRequired(Context context) {
- DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(
- Context.DEVICE_POLICY_SERVICE);
- if (dpm == null || !dpm.getAutoTimeRequired()) {
- return null;
- }
- ComponentName adminComponent = dpm.getDeviceOwnerComponentOnCallingUser();
- return new EnforcedAdmin(adminComponent, getUserHandleOf(UserHandle.myUserId()));
- }
-
- /**
* Checks if an admin has enforced minimum password quality requirements on the given user.
*
* @return EnforcedAdmin Object containing the enforced admin component and admin user details,
diff --git a/packages/SystemUI/src/com/android/systemui/ForegroundServiceController.java b/packages/SystemUI/src/com/android/systemui/ForegroundServiceController.java
index c1a23c8..493186b 100644
--- a/packages/SystemUI/src/com/android/systemui/ForegroundServiceController.java
+++ b/packages/SystemUI/src/com/android/systemui/ForegroundServiceController.java
@@ -37,7 +37,7 @@
*/
@Singleton
public class ForegroundServiceController {
- private static final int[] APP_OPS = new int[] {AppOpsManager.OP_CAMERA,
+ public static final int[] APP_OPS = new int[] {AppOpsManager.OP_CAMERA,
AppOpsManager.OP_SYSTEM_ALERT_WINDOW,
AppOpsManager.OP_RECORD_AUDIO,
AppOpsManager.OP_COARSE_LOCATION,
diff --git a/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java b/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java
index b983966..c4e2762 100644
--- a/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java
+++ b/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java
@@ -27,6 +27,8 @@
import com.android.internal.statusbar.NotificationVisibility;
import com.android.systemui.statusbar.notification.NotificationEntryListener;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.collection.NotifCollection;
+import com.android.systemui.statusbar.notification.collection.NotifCollectionListener;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import javax.inject.Inject;
@@ -46,7 +48,8 @@
@Inject
public ForegroundServiceNotificationListener(Context context,
ForegroundServiceController foregroundServiceController,
- NotificationEntryManager notificationEntryManager) {
+ NotificationEntryManager notificationEntryManager,
+ NotifCollection notifCollection) {
mContext = context;
mForegroundServiceController = foregroundServiceController;
mEntryManager = notificationEntryManager;
@@ -69,8 +72,24 @@
removeNotification(entry.getSbn());
}
});
-
mEntryManager.addNotificationLifetimeExtender(new ForegroundServiceLifetimeExtender());
+
+ notifCollection.addCollectionListener(new NotifCollectionListener() {
+ @Override
+ public void onEntryAdded(NotificationEntry entry) {
+ addNotification(entry, entry.getImportance());
+ }
+
+ @Override
+ public void onEntryUpdated(NotificationEntry entry) {
+ updateNotification(entry, entry.getImportance());
+ }
+
+ @Override
+ public void onEntryRemoved(NotificationEntry entry, int reason, boolean removedByUser) {
+ removeNotification(entry.getSbn());
+ }
+ });
}
/**
@@ -152,6 +171,8 @@
true /* create if not found */);
}
+ // TODO: remove this when fully migrated to the NewNotifPipeline (work done in
+ // ForegroundCoordinator)
private void tagForeground(NotificationEntry entry) {
final StatusBarNotification sbn = entry.getSbn();
ArraySet<Integer> activeOps = mForegroundServiceController.getAppOps(
diff --git a/packages/SystemUI/src/com/android/systemui/ForegroundServicesUserState.java b/packages/SystemUI/src/com/android/systemui/ForegroundServicesUserState.java
index a8ae654..2ef46dc 100644
--- a/packages/SystemUI/src/com/android/systemui/ForegroundServicesUserState.java
+++ b/packages/SystemUI/src/com/android/systemui/ForegroundServicesUserState.java
@@ -24,7 +24,7 @@
/**
* Struct to track relevant packages and notifications for a userid's foreground services.
*/
-class ForegroundServicesUserState {
+public class ForegroundServicesUserState {
// shelf life of foreground services before they go bad
private static final long FG_SERVICE_GRACE_MILLIS = 5000;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManager.java
index 4cc5b21..ff4ce94 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManager.java
@@ -65,8 +65,18 @@
boolean needsRedaction(NotificationEntry entry);
+ /**
+ * Has the given user chosen to allow their private (full) notifications to be shown even
+ * when the lockscreen is in "public" (secure & locked) mode?
+ */
boolean userAllowsPrivateNotificationsInPublic(int currentUserId);
+ /**
+ * Has the given user chosen to allow notifications to be shown even when the lockscreen is in
+ * "public" (secure & locked) mode?
+ */
+ boolean userAllowsNotificationsInPublic(int userId);
+
/** Notified when the current user changes. */
interface UserChangedListener {
void onUserChanged(int userId);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
index f5710a8..0f3f6b7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
@@ -435,7 +435,7 @@
* Has the given user chosen to allow notifications to be shown even when the lockscreen is in
* "public" (secure & locked) mode?
*/
- private boolean userAllowsNotificationsInPublic(int userHandle) {
+ public boolean userAllowsNotificationsInPublic(int userHandle) {
if (isCurrentProfile(userHandle) && userHandle != mCurrentUserId) {
return true;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFilter.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFilter.java
index e5f44bd..b61c1ef 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFilter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFilter.java
@@ -36,7 +36,10 @@
import javax.inject.Inject;
import javax.inject.Singleton;
-/** Component which manages the various reasons a notification might be filtered out. */
+/** Component which manages the various reasons a notification might be filtered out.*/
+// TODO: delete NotificationFilter.java after migrating to new NotifPipeline b/145659174.
+// Notification filtering is taken care of across the different Coordinators (mostly
+// KeyguardCoordinator.java)
@Singleton
public class NotificationFilter {
@@ -109,7 +112,7 @@
return true;
}
- if (entry.isSuspended()) {
+ if (entry.getRanking().isSuspended()) {
return true;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/GroupEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/GroupEntry.java
index f9f3266..9ae3882 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/GroupEntry.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/GroupEntry.java
@@ -18,6 +18,8 @@
import android.annotation.Nullable;
+import com.android.internal.annotations.VisibleForTesting;
+
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
@@ -34,7 +36,8 @@
private final List<NotificationEntry> mUnmodifiableChildren =
Collections.unmodifiableList(mChildren);
- GroupEntry(String key) {
+ @VisibleForTesting
+ public GroupEntry(String key) {
super(key);
}
@@ -52,7 +55,8 @@
return mUnmodifiableChildren;
}
- void setSummary(@Nullable NotificationEntry summary) {
+ @VisibleForTesting
+ public void setSummary(@Nullable NotificationEntry summary) {
mSummary = summary;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListEntry.java
index dc68c4b..6ce7fd9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListEntry.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListEntry.java
@@ -18,6 +18,8 @@
import android.annotation.Nullable;
+import com.android.internal.annotations.VisibleForTesting;
+
/**
* Abstract superclass for top-level entries, i.e. things that can appear in the final notification
* list shown to users. In practice, this means either GroupEntries or NotificationEntries.
@@ -49,7 +51,8 @@
return mParent;
}
- void setParent(@Nullable GroupEntry parent) {
+ @VisibleForTesting
+ public void setParent(@Nullable GroupEntry parent) {
mParent = parent;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
index 3eb55ef..232fb6d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
@@ -275,10 +275,6 @@
return mRanking.getSuppressedVisualEffects();
}
- public boolean isSuspended() {
- return mRanking.isSuspended();
- }
-
/** @see Ranking#canBubble() */
public boolean canBubble() {
return mRanking.canBubble();
@@ -951,6 +947,15 @@
}
/**
+ * Whether or not this row represents a system notification. Note that if this is
+ * {@code null}, that means we were either unable to retrieve the info or have yet to
+ * retrieve the info.
+ */
+ public Boolean isSystemNotification() {
+ return mIsSystemNotification;
+ }
+
+ /**
* Set this notification to be sensitive.
*
* @param sensitive true if the content of this notification is sensitive right now
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/Coordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/Coordinator.java
new file mode 100644
index 0000000..898918e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/Coordinator.java
@@ -0,0 +1,42 @@
+/*
+ * 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.systemui.statusbar.notification.collection.coordinator;
+
+import com.android.systemui.statusbar.notification.collection.NotifCollection;
+import com.android.systemui.statusbar.notification.collection.NotifCollectionListener;
+import com.android.systemui.statusbar.notification.collection.NotifLifetimeExtender;
+import com.android.systemui.statusbar.notification.collection.init.NewNotifPipeline;
+import com.android.systemui.statusbar.notification.collection.listbuilder.NotifListBuilder;
+import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.Pluggable;
+
+/**
+ * Interface for registering callbacks to the {@link NewNotifPipeline}.
+ *
+ * This includes registering:
+ * {@link Pluggable}s to the {@link NotifListBuilder}
+ * {@link NotifCollectionListener}s and {@link NotifLifetimeExtender}s to {@link NotifCollection}
+ */
+public interface Coordinator {
+
+ /**
+ * Called after the NewNotifPipeline is initialized.
+ * Coordinators should register their {@link Pluggable}s to the notifListBuilder
+ * and their {@link NotifCollectionListener}s and {@link NotifLifetimeExtender}s
+ * to the notifCollection in this method.
+ */
+ void attach(NotifCollection notifCollection, NotifListBuilder notifListBuilder);
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DeviceProvisionedCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DeviceProvisionedCoordinator.java
new file mode 100644
index 0000000..511aafc
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DeviceProvisionedCoordinator.java
@@ -0,0 +1,96 @@
+/*
+ * 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.systemui.statusbar.notification.collection.coordinator;
+
+import android.Manifest;
+import android.app.AppGlobals;
+import android.app.Notification;
+import android.content.pm.IPackageManager;
+import android.content.pm.PackageManager;
+import android.os.RemoteException;
+import android.service.notification.StatusBarNotification;
+
+import com.android.systemui.statusbar.notification.collection.NotifCollection;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.listbuilder.NotifListBuilder;
+import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
+import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ * Filters out most notifications when the device is unprovisioned.
+ * Special notifications with extra permissions and tags won't be filtered out even when the
+ * device is unprovisioned.
+ */
+@Singleton
+public class DeviceProvisionedCoordinator implements Coordinator {
+ private static final String TAG = "DeviceProvisionedCoordinator";
+
+ private final DeviceProvisionedController mDeviceProvisionedController;
+
+ @Inject
+ public DeviceProvisionedCoordinator(DeviceProvisionedController deviceProvisionedController) {
+ mDeviceProvisionedController = deviceProvisionedController;
+ }
+
+ @Override
+ public void attach(NotifCollection notifCollection, NotifListBuilder notifListBuilder) {
+ mDeviceProvisionedController.addCallback(mDeviceProvisionedListener);
+
+ notifListBuilder.addFilter(mNotifFilter);
+ }
+
+ protected final NotifFilter mNotifFilter = new NotifFilter(TAG) {
+ @Override
+ public boolean shouldFilterOut(NotificationEntry entry, long now) {
+ return !mDeviceProvisionedController.isDeviceProvisioned()
+ && !showNotificationEvenIfUnprovisioned(entry.getSbn());
+ }
+ };
+
+ /**
+ * Only notifications coming from packages with permission
+ * android.permission.NOTIFICATION_DURING_SETUP that also have special tags
+ * marking them as relevant for setup are allowed to show when device is unprovisioned
+ */
+ private boolean showNotificationEvenIfUnprovisioned(StatusBarNotification sbn) {
+ final boolean hasPermission = checkUidPermission(AppGlobals.getPackageManager(),
+ Manifest.permission.NOTIFICATION_DURING_SETUP,
+ sbn.getUid()) == PackageManager.PERMISSION_GRANTED;
+ return hasPermission
+ && sbn.getNotification().extras.getBoolean(Notification.EXTRA_ALLOW_DURING_SETUP);
+ }
+
+ private static int checkUidPermission(IPackageManager packageManager, String permission,
+ int uid) {
+ try {
+ return packageManager.checkUidPermission(permission, uid);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ private final DeviceProvisionedController.DeviceProvisionedListener mDeviceProvisionedListener =
+ new DeviceProvisionedController.DeviceProvisionedListener() {
+ @Override
+ public void onDeviceProvisionedChanged() {
+ mNotifFilter.invalidateList();
+ }
+ };
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ForegroundCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ForegroundCoordinator.java
new file mode 100644
index 0000000..4803cf4
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ForegroundCoordinator.java
@@ -0,0 +1,243 @@
+/*
+ * 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.systemui.statusbar.notification.collection.coordinator;
+
+import android.app.Notification;
+import android.os.Handler;
+import android.os.UserHandle;
+import android.service.notification.StatusBarNotification;
+import android.util.ArraySet;
+
+import com.android.systemui.ForegroundServiceController;
+import com.android.systemui.appops.AppOpsController;
+import com.android.systemui.dagger.qualifiers.BgHandler;
+import com.android.systemui.dagger.qualifiers.MainHandler;
+import com.android.systemui.statusbar.notification.collection.NotifCollection;
+import com.android.systemui.statusbar.notification.collection.NotifCollectionListener;
+import com.android.systemui.statusbar.notification.collection.NotifLifetimeExtender;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.listbuilder.NotifListBuilder;
+import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ * Handles ForegroundService interactions with notifications.
+ * Tags notifications with appOps.
+ * Lifetime extends notifications associated with an ongoing ForegroundService.
+ * Filters out notifications that represent foreground services that are no longer running
+ *
+ * Previously this logic lived in
+ * frameworks/base/packages/SystemUI/src/com/android/systemui/ForegroundServiceController
+ * frameworks/base/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener
+ * frameworks/base/packages/SystemUI/src/com/android/systemui/ForegroundServiceLifetimeExtender
+ */
+@Singleton
+public class ForegroundCoordinator implements Coordinator {
+ private static final String TAG = "ForegroundNotificationCoordinator";
+
+ private final ForegroundServiceController mForegroundServiceController;
+ private final AppOpsController mAppOpsController;
+ private final Handler mMainHandler;
+ private final Handler mBgHandler;
+
+ private NotifCollection mNotifCollection;
+
+ @Inject
+ public ForegroundCoordinator(
+ ForegroundServiceController foregroundServiceController,
+ AppOpsController appOpsController,
+ @MainHandler Handler mainHandler,
+ @BgHandler Handler bgHandler) {
+ mForegroundServiceController = foregroundServiceController;
+ mAppOpsController = appOpsController;
+ mMainHandler = mainHandler;
+ mBgHandler = bgHandler;
+ }
+
+ @Override
+ public void attach(NotifCollection notifCollection, NotifListBuilder notifListBuilder) {
+ mNotifCollection = notifCollection;
+
+ // extend the lifetime of foreground notification services to show for at least 5 seconds
+ mNotifCollection.addNotificationLifetimeExtender(mForegroundLifetimeExtender);
+
+ // listen for new notifications to add appOps
+ mNotifCollection.addCollectionListener(mNotifCollectionListener);
+
+ // when appOps change, update any relevant notifications to update appOps for
+ mAppOpsController.addCallback(ForegroundServiceController.APP_OPS, this::onAppOpsChanged);
+
+ // filter out foreground service notifications that aren't necessary anymore
+ notifListBuilder.addFilter(mNotifFilter);
+ }
+
+ /**
+ * Filters out notifications that represent foreground services that are no longer running.
+ */
+ protected final NotifFilter mNotifFilter = new NotifFilter(TAG) {
+ @Override
+ public boolean shouldFilterOut(NotificationEntry entry, long now) {
+ StatusBarNotification sbn = entry.getSbn();
+ if (mForegroundServiceController.isDisclosureNotification(sbn)
+ && !mForegroundServiceController.isDisclosureNeededForUser(sbn.getUserId())) {
+ return true;
+ }
+
+ if (mForegroundServiceController.isSystemAlertNotification(sbn)) {
+ final String[] apps = sbn.getNotification().extras.getStringArray(
+ Notification.EXTRA_FOREGROUND_APPS);
+ if (apps != null && apps.length >= 1) {
+ if (!mForegroundServiceController.isSystemAlertWarningNeeded(
+ sbn.getUserId(), apps[0])) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+ };
+
+ /**
+ * Extends the lifetime of foreground notification services such that they show for at least
+ * five seconds
+ */
+ private final NotifLifetimeExtender mForegroundLifetimeExtender = new NotifLifetimeExtender() {
+ private static final int MIN_FGS_TIME_MS = 5000;
+ private OnEndLifetimeExtensionCallback mEndCallback;
+ private Map<String, Runnable> mEndRunnables = new HashMap<>();
+
+ @Override
+ public String getName() {
+ return TAG;
+ }
+
+ @Override
+ public void setCallback(OnEndLifetimeExtensionCallback callback) {
+ mEndCallback = callback;
+ }
+
+ @Override
+ public boolean shouldExtendLifetime(NotificationEntry entry, int reason) {
+ if ((entry.getSbn().getNotification().flags
+ & Notification.FLAG_FOREGROUND_SERVICE) == 0) {
+ return false;
+ }
+
+ final long currTime = System.currentTimeMillis();
+ final boolean extendLife = currTime - entry.getSbn().getPostTime() < MIN_FGS_TIME_MS;
+
+ if (extendLife) {
+ if (!mEndRunnables.containsKey(entry.getKey())) {
+ final Runnable runnable = new Runnable() {
+ @Override
+ public void run() {
+ mEndCallback.onEndLifetimeExtension(mForegroundLifetimeExtender, entry);
+ }
+ };
+ mEndRunnables.put(entry.getKey(), runnable);
+ mBgHandler.postDelayed(runnable, MIN_FGS_TIME_MS
+ - (currTime - entry.getSbn().getPostTime()));
+ }
+ }
+
+ return extendLife;
+ }
+
+ @Override
+ public void cancelLifetimeExtension(NotificationEntry entry) {
+ if (mEndRunnables.containsKey(entry.getKey())) {
+ Runnable endRunnable = mEndRunnables.remove(entry.getKey());
+ mBgHandler.removeCallbacks(endRunnable);
+ }
+ }
+ };
+
+ /**
+ * Adds appOps to incoming and updating notifications
+ */
+ private NotifCollectionListener mNotifCollectionListener = new NotifCollectionListener() {
+ @Override
+ public void onEntryAdded(NotificationEntry entry) {
+ tagForeground(entry);
+ }
+
+ @Override
+ public void onEntryUpdated(NotificationEntry entry) {
+ tagForeground(entry);
+ }
+
+ private void tagForeground(NotificationEntry entry) {
+ final StatusBarNotification sbn = entry.getSbn();
+ // note: requires that the ForegroundServiceController is updating their appOps first
+ ArraySet<Integer> activeOps = mForegroundServiceController.getAppOps(sbn.getUserId(),
+ sbn.getPackageName());
+ if (activeOps != null) {
+ synchronized (entry.mActiveAppOps) {
+ entry.mActiveAppOps.clear();
+ entry.mActiveAppOps.addAll(activeOps);
+ }
+ }
+ }
+ };
+
+ /**
+ * Update the appOp for the posted notification associated with the current foreground service
+ * @param code code for appOp to add/remove
+ * @param uid of user the notification is sent to
+ * @param packageName package that created the notification
+ * @param active whether the appOpCode is active or not
+ */
+ private void onAppOpsChanged(int code, int uid, String packageName, boolean active) {
+ int userId = UserHandle.getUserId(uid);
+
+ // Update appOp if there's an associated posted notification:
+ final String foregroundKey = mForegroundServiceController.getStandardLayoutKey(userId,
+ packageName);
+ if (foregroundKey != null) {
+ final NotificationEntry entry = findNotificationEntryWithKey(foregroundKey);
+ if (entry != null
+ && uid == entry.getSbn().getUid()
+ && packageName.equals(entry.getSbn().getPackageName())) {
+ boolean changed;
+ synchronized (entry.mActiveAppOps) {
+ if (active) {
+ changed = entry.mActiveAppOps.add(code);
+ } else {
+ changed = entry.mActiveAppOps.remove(code);
+ }
+ }
+ if (changed) {
+ mMainHandler.post(mNotifFilter::invalidateList);
+ }
+ }
+ }
+ }
+
+ private NotificationEntry findNotificationEntryWithKey(String key) {
+ for (NotificationEntry entry : mNotifCollection.getNotifs()) {
+ if (entry.getKey().equals(key)) {
+ return entry;
+ }
+ }
+ return null;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java
new file mode 100644
index 0000000..f5ed089
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java
@@ -0,0 +1,233 @@
+/*
+ * 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.systemui.statusbar.notification.collection.coordinator;
+
+import static android.app.Notification.VISIBILITY_SECRET;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.service.notification.StatusBarNotification;
+
+import androidx.annotation.MainThread;
+
+import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.NotificationLockscreenUserManager;
+import com.android.systemui.statusbar.notification.NotificationUtils;
+import com.android.systemui.statusbar.notification.collection.NotifCollection;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.listbuilder.NotifListBuilder;
+import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ * Filters low priority and privacy-sensitive notifications from the lockscreen.
+ */
+@Singleton
+public class KeyguardCoordinator implements Coordinator {
+ private static final String TAG = "KeyguardNotificationCoordinator";
+
+ private final Context mContext;
+ private final Handler mMainHandler;
+ private final KeyguardStateController mKeyguardStateController;
+ private final NotificationLockscreenUserManager mLockscreenUserManager;
+ private final BroadcastDispatcher mBroadcastDispatcher;
+ private final StatusBarStateController mStatusBarStateController;
+ private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+
+ @Inject
+ public KeyguardCoordinator(
+ Context context,
+ @MainThread Handler mainThreadHandler,
+ KeyguardStateController keyguardStateController,
+ NotificationLockscreenUserManager lockscreenUserManager,
+ BroadcastDispatcher broadcastDispatcher,
+ StatusBarStateController statusBarStateController,
+ KeyguardUpdateMonitor keyguardUpdateMonitor) {
+ mContext = context;
+ mMainHandler = mainThreadHandler;
+ mKeyguardStateController = keyguardStateController;
+ mLockscreenUserManager = lockscreenUserManager;
+
+ mBroadcastDispatcher = broadcastDispatcher;
+ mStatusBarStateController = statusBarStateController;
+ mKeyguardUpdateMonitor = keyguardUpdateMonitor;
+ }
+
+ @Override
+ public void attach(NotifCollection notifCollection, NotifListBuilder notifListBuilder) {
+ setupInvalidateNotifListCallbacks();
+ notifListBuilder.addFilter(mNotifFilter);
+ }
+
+ protected final NotifFilter mNotifFilter = new NotifFilter(TAG) {
+ @Override
+ public boolean shouldFilterOut(NotificationEntry entry, long now) {
+ final StatusBarNotification sbn = entry.getSbn();
+
+ // FILTER OUT the notification when the notification isn't for the current profile
+ if (!mLockscreenUserManager.isCurrentProfile(sbn.getUserId())) {
+ return true;
+ }
+
+ // FILTER OUT the notification when the keyguard is showing and...
+ if (mKeyguardStateController.isShowing()) {
+ // ... user settings or the device policy manager doesn't allow lockscreen
+ // notifications;
+ if (!mLockscreenUserManager.shouldShowLockscreenNotifications()) {
+ return true;
+ }
+
+ final int currUserId = mLockscreenUserManager.getCurrentUserId();
+ final int notifUserId = (sbn.getUser().getIdentifier() == UserHandle.USER_ALL)
+ ? currUserId : sbn.getUser().getIdentifier();
+
+ // ... user is in lockdown
+ if (mKeyguardUpdateMonitor.isUserInLockdown(currUserId)
+ || mKeyguardUpdateMonitor.isUserInLockdown(notifUserId)) {
+ return true;
+ }
+
+ // ... device is in public mode and the user's settings doesn't allow
+ // notifications to show in public mode
+ if (mLockscreenUserManager.isLockscreenPublicMode(currUserId)
+ || mLockscreenUserManager.isLockscreenPublicMode(notifUserId)) {
+ if (entry.getRanking().getVisibilityOverride() == VISIBILITY_SECRET) {
+ return true;
+ }
+
+ if (!mLockscreenUserManager.userAllowsNotificationsInPublic(currUserId)
+ || !mLockscreenUserManager.userAllowsNotificationsInPublic(
+ notifUserId)) {
+ return true;
+ }
+ }
+
+ // ... neither this notification nor its summary have high enough priority
+ // to be shown on the lockscreen
+ // TODO: grouping hasn't happened yet (b/145134683)
+ if (entry.getParent() != null) {
+ final NotificationEntry summary = entry.getParent().getRepresentativeEntry();
+ if (priorityExceedsLockscreenShowingThreshold(summary)) {
+ return false;
+ }
+ }
+ return !priorityExceedsLockscreenShowingThreshold(entry);
+ }
+ return false;
+ }
+ };
+
+ private boolean priorityExceedsLockscreenShowingThreshold(NotificationEntry entry) {
+ if (entry == null) {
+ return false;
+ }
+ if (NotificationUtils.useNewInterruptionModel(mContext)
+ && hideSilentNotificationsOnLockscreen()) {
+ // TODO: make sure in the NewNotifPipeline that entry.isHighPriority() has been
+ // correctly updated before reaching this point (b/145134683)
+ return entry.isHighPriority();
+ } else {
+ return !entry.getRanking().isAmbient();
+ }
+ }
+
+ private boolean hideSilentNotificationsOnLockscreen() {
+ return Settings.Secure.getInt(mContext.getContentResolver(),
+ Settings.Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS, 1) == 0;
+ }
+
+ private void setupInvalidateNotifListCallbacks() {
+ // register onKeyguardShowing callback
+ mKeyguardStateController.addCallback(mKeyguardCallback);
+
+ // register lockscreen settings changed callbacks:
+ final ContentObserver settingsObserver = new ContentObserver(mMainHandler) {
+ @Override
+ public void onChange(boolean selfChange, Uri uri) {
+ if (mKeyguardStateController.isShowing()) {
+ invalidateListFromFilter("Settings " + uri + " changed");
+ }
+ }
+ };
+
+ mContext.getContentResolver().registerContentObserver(
+ Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS),
+ false,
+ settingsObserver,
+ UserHandle.USER_ALL);
+
+ mContext.getContentResolver().registerContentObserver(
+ Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS),
+ true,
+ settingsObserver,
+ UserHandle.USER_ALL);
+
+ mContext.getContentResolver().registerContentObserver(
+ Settings.Global.getUriFor(Settings.Global.ZEN_MODE),
+ false,
+ settingsObserver);
+
+ // register (maybe) public mode changed callbacks:
+ mStatusBarStateController.addCallback(mStatusBarStateListener);
+ mBroadcastDispatcher.registerReceiver(new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (mKeyguardStateController.isShowing()) {
+ // maybe public mode changed
+ invalidateListFromFilter(intent.getAction());
+ }
+ }}, new IntentFilter(Intent.ACTION_USER_SWITCHED));
+ }
+
+ private void invalidateListFromFilter(String reason) {
+ mNotifFilter.invalidateList();
+ }
+
+ private final KeyguardStateController.Callback mKeyguardCallback =
+ new KeyguardStateController.Callback() {
+ @Override
+ public void onUnlockedChanged() {
+ invalidateListFromFilter("onUnlockedChanged");
+ }
+
+ @Override
+ public void onKeyguardShowingChanged() {
+ invalidateListFromFilter("onKeyguardShowingChanged");
+ }
+ };
+
+ private final StatusBarStateController.StateListener mStatusBarStateListener =
+ new StatusBarStateController.StateListener() {
+ @Override
+ public void onStateChanged(int newState) {
+ // maybe public mode changed
+ invalidateListFromFilter("onStatusBarStateChanged");
+ }
+ };
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.java
new file mode 100644
index 0000000..13247193
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.java
@@ -0,0 +1,78 @@
+/*
+ * 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.systemui.statusbar.notification.collection.coordinator;
+
+import com.android.systemui.Dumpable;
+import com.android.systemui.statusbar.notification.collection.NotifCollection;
+import com.android.systemui.statusbar.notification.collection.NotifCollectionListener;
+import com.android.systemui.statusbar.notification.collection.NotifLifetimeExtender;
+import com.android.systemui.statusbar.notification.collection.listbuilder.NotifListBuilder;
+import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.Pluggable;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ * Handles the attachment of the {@link NotifListBuilder} and {@link NotifCollection} to the
+ * {@link Coordinator}s, so that the Coordinators can register their respective callbacks.
+ */
+@Singleton
+public class NotifCoordinators implements Dumpable {
+ private static final String TAG = "NotifCoordinators";
+ private final List<Coordinator> mCoordinators = new ArrayList<>();
+
+ /**
+ * Creates all the coordinators.
+ */
+ @Inject
+ public NotifCoordinators(
+ KeyguardCoordinator keyguardCoordinator,
+ RankingCoordinator rankingCoordinator,
+ ForegroundCoordinator foregroundCoordinator,
+ DeviceProvisionedCoordinator deviceProvisionedCoordinator) {
+ mCoordinators.add(keyguardCoordinator);
+ mCoordinators.add(rankingCoordinator);
+ mCoordinators.add(foregroundCoordinator);
+ mCoordinators.add(deviceProvisionedCoordinator);
+ // TODO: add new Coordinators here! (b/145134683, b/112656837)
+ }
+
+ /**
+ * Sends the initialized notifListBuilder and notifCollection to each
+ * coordinator to indicate the notifListBuilder is ready to accept {@link Pluggable}s
+ * and the notifCollection is ready to accept {@link NotifCollectionListener}s and
+ * {@link NotifLifetimeExtender}s.
+ */
+ public void attach(NotifCollection notifCollection, NotifListBuilder notifListBuilder) {
+ for (Coordinator c : mCoordinators) {
+ c.attach(notifCollection, notifListBuilder);
+ }
+ }
+
+ @Override
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ pw.println(TAG + ":");
+ for (Coordinator c : mCoordinators) {
+ pw.println("\t" + c.getClass());
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java
new file mode 100644
index 0000000..c390f96
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java
@@ -0,0 +1,83 @@
+/*
+ * 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.systemui.statusbar.notification.collection.coordinator;
+
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.notification.collection.NotifCollection;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.listbuilder.NotifListBuilder;
+import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ * Filters out NotificationEntries based on its Ranking.
+ */
+@Singleton
+public class RankingCoordinator implements Coordinator {
+ private static final String TAG = "RankingNotificationCoordinator";
+
+ private final StatusBarStateController mStatusBarStateController;
+
+ @Inject
+ public RankingCoordinator(StatusBarStateController statusBarStateController) {
+ mStatusBarStateController = statusBarStateController;
+ }
+
+ @Override
+ public void attach(NotifCollection notifCollection, NotifListBuilder notifListBuilder) {
+ mStatusBarStateController.addCallback(mStatusBarStateCallback);
+
+ notifListBuilder.addFilter(mNotifFilter);
+ }
+
+ /**
+ * Checks whether to filter out the given notification based the notification's Ranking object.
+ * NotifListBuilder invalidates the notification list each time the ranking is updated,
+ * so we don't need to explicitly invalidate this filter on ranking update.
+ */
+ protected final NotifFilter mNotifFilter = new NotifFilter(TAG) {
+ @Override
+ public boolean shouldFilterOut(NotificationEntry entry, long now) {
+ // App suspended from Ranking
+ if (entry.getRanking().isSuspended()) {
+ return true;
+ }
+
+ // Dozing + DND Settings from Ranking object
+ if (mStatusBarStateController.isDozing() && entry.shouldSuppressAmbient()) {
+ return true;
+ }
+
+ if (!mStatusBarStateController.isDozing() && entry.shouldSuppressNotificationList()) {
+ return true;
+ }
+
+ return false;
+ }
+ };
+
+
+ private final StatusBarStateController.StateListener mStatusBarStateCallback =
+ new StatusBarStateController.StateListener() {
+ @Override
+ public void onDozingChanged(boolean isDozing) {
+ mNotifFilter.invalidateList();
+ }
+ };
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/init/NewNotifPipeline.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/init/NewNotifPipeline.java
index 3b3e7e2..5fc55da 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/init/NewNotifPipeline.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/init/NewNotifPipeline.java
@@ -23,6 +23,7 @@
import com.android.systemui.statusbar.NotificationListener;
import com.android.systemui.statusbar.notification.collection.NotifCollection;
import com.android.systemui.statusbar.notification.collection.NotifListBuilderImpl;
+import com.android.systemui.statusbar.notification.collection.coordinator.NotifCoordinators;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -37,6 +38,7 @@
public class NewNotifPipeline implements Dumpable {
private final NotifCollection mNotifCollection;
private final NotifListBuilderImpl mNotifPipeline;
+ private final NotifCoordinators mNotifPluggableCoordinators;
private final DumpController mDumpController;
private final FakePipelineConsumer mFakePipelineConsumer = new FakePipelineConsumer();
@@ -45,9 +47,11 @@
public NewNotifPipeline(
NotifCollection notifCollection,
NotifListBuilderImpl notifPipeline,
+ NotifCoordinators notifCoordinators,
DumpController dumpController) {
mNotifCollection = notifCollection;
mNotifPipeline = notifPipeline;
+ mNotifPluggableCoordinators = notifCoordinators;
mDumpController = dumpController;
}
@@ -57,6 +61,7 @@
mFakePipelineConsumer.attach(mNotifPipeline);
mNotifPipeline.attach(mNotifCollection);
mNotifCollection.attach(notificationService);
+ mNotifPluggableCoordinators.attach(mNotifCollection, mNotifPipeline);
Log.d(TAG, "Notif pipeline initialized");
@@ -66,6 +71,7 @@
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
mFakePipelineConsumer.dump(fd, pw, args);
+ mNotifPluggableCoordinators.dump(fd, pw, args);
}
private static final String TAG = "NewNotifPipeline";
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java
index 0990e22..4cb5472 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java
@@ -49,6 +49,7 @@
import com.android.systemui.statusbar.NotificationEntryBuilder;
import com.android.systemui.statusbar.notification.NotificationEntryListener;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.collection.NotifCollection;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import junit.framework.Assert;
@@ -70,6 +71,7 @@
@Mock private NotificationEntryManager mEntryManager;
@Mock private AppOpsController mAppOpsController;
@Mock private Handler mMainHandler;
+ @Mock private NotifCollection mNotifCollection;
@Before
public void setUp() throws Exception {
@@ -79,7 +81,7 @@
MockitoAnnotations.initMocks(this);
mFsc = new ForegroundServiceController(mEntryManager, mAppOpsController, mMainHandler);
mListener = new ForegroundServiceNotificationListener(
- mContext, mFsc, mEntryManager);
+ mContext, mFsc, mEntryManager, mNotifCollection);
ArgumentCaptor<NotificationEntryListener> entryListenerCaptor =
ArgumentCaptor.forClass(NotificationEntryListener.class);
verify(mEntryManager).addNotificationEntryListener(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.java
new file mode 100644
index 0000000..87b3783d
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.java
@@ -0,0 +1,243 @@
+/*
+ * 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.systemui.statusbar.notification.collection.coordinator;
+
+import static android.app.Notification.VISIBILITY_PUBLIC;
+import static android.app.Notification.VISIBILITY_SECRET;
+import static android.app.NotificationManager.IMPORTANCE_HIGH;
+import static android.app.NotificationManager.IMPORTANCE_MIN;
+
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+
+import static org.mockito.Mockito.when;
+
+import android.os.Handler;
+import android.os.UserHandle;
+import android.testing.AndroidTestingRunner;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.NotificationEntryBuilder;
+import com.android.systemui.statusbar.NotificationLockscreenUserManager;
+import com.android.systemui.statusbar.RankingBuilder;
+import com.android.systemui.statusbar.notification.collection.GroupEntry;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+public class KeyguardCoordinatorTest extends SysuiTestCase {
+ private static final int NOTIF_USER_ID = 0;
+ private static final int CURR_USER_ID = 1;
+
+ @Mock private Handler mMainHandler;
+ @Mock private KeyguardStateController mKeyguardStateController;
+ @Mock private NotificationLockscreenUserManager mLockscreenUserManager;
+ @Mock private BroadcastDispatcher mBroadcastDispatcher;
+ @Mock private StatusBarStateController mStatusBarStateController;
+ @Mock private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+
+ private NotificationEntry mEntry;
+ private KeyguardCoordinator mKeyguardNotificationCoordinator;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ mKeyguardNotificationCoordinator = new KeyguardCoordinator(
+ mContext, mMainHandler, mKeyguardStateController, mLockscreenUserManager,
+ mBroadcastDispatcher, mStatusBarStateController,
+ mKeyguardUpdateMonitor);
+
+ mEntry = new NotificationEntryBuilder()
+ .setUser(new UserHandle(NOTIF_USER_ID))
+ .build();
+ }
+
+ @Test
+ public void unfilteredState() {
+ // GIVEN an 'unfiltered-keyguard-showing' state
+ setupUnfilteredState();
+
+ // THEN don't filter out the entry
+ assertFalse(mKeyguardNotificationCoordinator.mNotifFilter.shouldFilterOut(mEntry, 0));
+ }
+
+ @Test
+ public void notificationNotForCurrentProfile() {
+ // GIVEN the notification isn't for the given user
+ setupUnfilteredState();
+ when(mLockscreenUserManager.isCurrentProfile(NOTIF_USER_ID)).thenReturn(false);
+
+ // THEN filter out the entry
+ assertTrue(mKeyguardNotificationCoordinator.mNotifFilter.shouldFilterOut(mEntry, 0));
+ }
+
+ @Test
+ public void keyguardNotShowing() {
+ // GIVEN the lockscreen isn't showing
+ setupUnfilteredState();
+ when(mKeyguardStateController.isShowing()).thenReturn(false);
+
+ // THEN don't filter out the entry
+ assertFalse(mKeyguardNotificationCoordinator.mNotifFilter.shouldFilterOut(mEntry, 0));
+ }
+
+ @Test
+ public void doNotShowLockscreenNotifications() {
+ // GIVEN an 'unfiltered-keyguard-showing' state
+ setupUnfilteredState();
+
+ // WHEN we shouldn't show any lockscreen notifications
+ when(mLockscreenUserManager.shouldShowLockscreenNotifications()).thenReturn(false);
+
+ // THEN filter out the entry
+ assertTrue(mKeyguardNotificationCoordinator.mNotifFilter.shouldFilterOut(mEntry, 0));
+ }
+
+ @Test
+ public void lockdown() {
+ // GIVEN an 'unfiltered-keyguard-showing' state
+ setupUnfilteredState();
+
+ // WHEN the notification's user is in lockdown:
+ when(mKeyguardUpdateMonitor.isUserInLockdown(NOTIF_USER_ID)).thenReturn(true);
+
+ // THEN filter out the entry
+ assertTrue(mKeyguardNotificationCoordinator.mNotifFilter.shouldFilterOut(mEntry, 0));
+ }
+
+ @Test
+ public void publicMode_settingsDisallow() {
+ // GIVEN an 'unfiltered-keyguard-showing' state
+ setupUnfilteredState();
+
+ // WHEN the notification's user is in public mode and settings are configured to disallow
+ // notifications in public mode
+ when(mLockscreenUserManager.isLockscreenPublicMode(NOTIF_USER_ID)).thenReturn(true);
+ when(mLockscreenUserManager.userAllowsNotificationsInPublic(NOTIF_USER_ID))
+ .thenReturn(false);
+
+ // THEN filter out the entry
+ assertTrue(mKeyguardNotificationCoordinator.mNotifFilter.shouldFilterOut(mEntry, 0));
+ }
+
+ @Test
+ public void publicMode_notifDisallowed() {
+ // GIVEN an 'unfiltered-keyguard-showing' state
+ setupUnfilteredState();
+
+ // WHEN the notification's user is in public mode and settings are configured to disallow
+ // notifications in public mode
+ when(mLockscreenUserManager.isLockscreenPublicMode(CURR_USER_ID)).thenReturn(true);
+ mEntry.setRanking(new RankingBuilder()
+ .setKey(mEntry.getKey())
+ .setVisibilityOverride(VISIBILITY_SECRET).build());
+
+ // THEN filter out the entry
+ assertTrue(mKeyguardNotificationCoordinator.mNotifFilter.shouldFilterOut(mEntry, 0));
+ }
+
+ @Test
+ public void doesNotExceedThresholdToShow() {
+ // GIVEN an 'unfiltered-keyguard-showing' state
+ setupUnfilteredState();
+
+ // WHEN the notification doesn't exceed the threshold to show on the lockscreen
+ mEntry.setRanking(new RankingBuilder()
+ .setKey(mEntry.getKey())
+ .setImportance(IMPORTANCE_MIN)
+ .build());
+
+ // THEN filter out the entry
+ assertTrue(mKeyguardNotificationCoordinator.mNotifFilter.shouldFilterOut(mEntry, 0));
+ }
+
+ @Test
+ public void summaryExceedsThresholdToShow() {
+ // GIVEN an 'unfiltered-keyguard-showing' state
+ setupUnfilteredState();
+
+ // WHEN the notification doesn't exceed the threshold to show on the lockscreen
+ // but its summary does
+ mEntry.setRanking(new RankingBuilder()
+ .setKey(mEntry.getKey())
+ .setImportance(IMPORTANCE_MIN)
+ .build());
+
+ final NotificationEntry summary = new NotificationEntryBuilder().build();
+ summary.setRanking(new RankingBuilder()
+ .setKey(summary.getKey())
+ .setImportance(IMPORTANCE_HIGH)
+ .build());
+ final GroupEntry group = new GroupEntry(mEntry.getSbn().getGroupKey());
+ group.setSummary(summary);
+ mEntry.setParent(group);
+
+ // THEN don't filter out the entry
+ assertFalse(mKeyguardNotificationCoordinator.mNotifFilter.shouldFilterOut(mEntry, 0));
+ }
+
+ /**
+ * setup a state where the notification will not be filtered by the
+ * KeyguardNotificationCoordinator when the keyguard is showing.
+ */
+ private void setupUnfilteredState() {
+ // notification is for current profile
+ when(mLockscreenUserManager.isCurrentProfile(NOTIF_USER_ID)).thenReturn(true);
+
+ // keyguard is showing
+ when(mKeyguardStateController.isShowing()).thenReturn(true);
+
+ // show notifications on the lockscreen
+ when(mLockscreenUserManager.shouldShowLockscreenNotifications()).thenReturn(true);
+
+ // neither the current user nor the notification's user is in lockdown
+ when(mLockscreenUserManager.getCurrentUserId()).thenReturn(CURR_USER_ID);
+ when(mKeyguardUpdateMonitor.isUserInLockdown(NOTIF_USER_ID)).thenReturn(false);
+ when(mKeyguardUpdateMonitor.isUserInLockdown(CURR_USER_ID)).thenReturn(false);
+
+ // not in public mode
+ when(mLockscreenUserManager.isLockscreenPublicMode(CURR_USER_ID)).thenReturn(false);
+ when(mLockscreenUserManager.isLockscreenPublicMode(NOTIF_USER_ID)).thenReturn(false);
+
+ // entry's ranking - should show on all lockscreens
+ // + priority of the notification exceeds the threshold to be shown on the lockscreen
+ mEntry.setRanking(new RankingBuilder()
+ .setKey(mEntry.getKey())
+ .setVisibilityOverride(VISIBILITY_PUBLIC)
+ .setImportance(IMPORTANCE_HIGH)
+ .build());
+
+ // settings allows notifications in public mode
+ when(mLockscreenUserManager.userAllowsNotificationsInPublic(CURR_USER_ID)).thenReturn(true);
+ when(mLockscreenUserManager.userAllowsNotificationsInPublic(NOTIF_USER_ID))
+ .thenReturn(true);
+
+ // notification doesn't have a summary
+ }
+}
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index d4889ea..822fc90 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -1556,8 +1556,6 @@
public StorageManagerService(Context context) {
sSelf = this;
- updateFusePropFromSettings();
-
// Snapshot feature flag used for this boot
SystemProperties.set(StorageManager.PROP_ISOLATED_STORAGE_SNAPSHOT, Boolean.toString(
SystemProperties.getBoolean(StorageManager.PROP_ISOLATED_STORAGE, true)));
@@ -1757,6 +1755,7 @@
private void bootCompleted() {
mBootCompleted = true;
mHandler.obtainMessage(H_BOOT_COMPLETED).sendToTarget();
+ updateFusePropFromSettings();
}
private void handleBootCompleted() {
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 24cd21e..9875f6d 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -51,7 +51,6 @@
import android.telephony.LocationAccessPolicy;
import android.telephony.PhoneCapability;
import android.telephony.PhoneStateListener;
-import android.telephony.PhysicalChannelConfig;
import android.telephony.PreciseCallState;
import android.telephony.PreciseDataConnectionState;
import android.telephony.PreciseDisconnectCause;
@@ -214,8 +213,6 @@
private ArrayList<List<CellInfo>> mCellInfo = null;
- private ArrayList<List<PhysicalChannelConfig>> mPhysicalChannelConfigs;
-
private Map<Integer, List<EmergencyNumber>> mEmergencyNumberList;
private EmergencyNumber[] mOutgoingSmsEmergencyNumber;
@@ -425,7 +422,6 @@
if (mNumPhones < oldNumPhones) {
cutListToSize(mCellInfo, mNumPhones);
cutListToSize(mImsReasonInfo, mNumPhones);
- cutListToSize(mPhysicalChannelConfigs, mNumPhones);
return;
}
@@ -446,7 +442,6 @@
mCellInfo.add(i, null);
mImsReasonInfo.add(i, null);
mSrvccState[i] = TelephonyManager.SRVCC_STATE_HANDOVER_NONE;
- mPhysicalChannelConfigs.add(i, new ArrayList<>());
mOtaspMode[i] = TelephonyManager.OTASP_UNKNOWN;
mCallDisconnectCause[i] = DisconnectCause.NOT_VALID;
mCallPreciseDisconnectCause[i] = PreciseDisconnectCause.NOT_VALID;
@@ -523,7 +518,6 @@
mPreciseDataConnectionState = new PreciseDataConnectionState[numPhones];
mCellInfo = new ArrayList<>();
mImsReasonInfo = new ArrayList<>();
- mPhysicalChannelConfigs = new ArrayList<>();
mEmergencyNumberList = new HashMap<>();
mOutgoingCallEmergencyNumber = new EmergencyNumber[numPhones];
mOutgoingSmsEmergencyNumber = new EmergencyNumber[numPhones];
@@ -543,7 +537,6 @@
mCellInfo.add(i, null);
mImsReasonInfo.add(i, null);
mSrvccState[i] = TelephonyManager.SRVCC_STATE_HANDOVER_NONE;
- mPhysicalChannelConfigs.add(i, new ArrayList<>());
mOtaspMode[i] = TelephonyManager.OTASP_UNKNOWN;
mCallDisconnectCause[i] = DisconnectCause.NOT_VALID;
mCallPreciseDisconnectCause[i] = PreciseDisconnectCause.NOT_VALID;
@@ -962,14 +955,6 @@
remove(r.binder);
}
}
- if ((events & PhoneStateListener.LISTEN_PHYSICAL_CHANNEL_CONFIGURATION) != 0) {
- try {
- r.callback.onPhysicalChannelConfigurationChanged(
- mPhysicalChannelConfigs.get(phoneId));
- } catch (RemoteException ex) {
- remove(r.binder);
- }
- }
if ((events & PhoneStateListener.LISTEN_EMERGENCY_NUMBER_LIST) != 0) {
try {
r.callback.onEmergencyNumberListChanged(mEmergencyNumberList);
@@ -1394,43 +1379,6 @@
}
}
- /**
- * Notify physical channel configuration according to subscripton ID and phone ID
- */
- public void notifyPhysicalChannelConfigurationForSubscriber(int phoneId, int subId,
- List<PhysicalChannelConfig> configs) {
- if (!checkNotifyPermission("notifyPhysicalChannelConfiguration()")) {
- return;
- }
-
- if (VDBG) {
- log("notifyPhysicalChannelConfiguration: subId=" + subId + " phoneId=" + phoneId
- + " configs=" + configs);
- }
-
- synchronized (mRecords) {
- if (validatePhoneId(phoneId)) {
- mPhysicalChannelConfigs.set(phoneId, configs);
- for (Record r : mRecords) {
- if (r.matchPhoneStateListenerEvent(
- PhoneStateListener.LISTEN_PHYSICAL_CHANNEL_CONFIGURATION)
- && idMatch(r.subId, subId, phoneId)) {
- try {
- if (DBG_LOC) {
- log("notifyPhysicalChannelConfiguration: mPhysicalChannelConfigs="
- + configs + " r=" + r);
- }
- r.callback.onPhysicalChannelConfigurationChanged(configs);
- } catch (RemoteException ex) {
- mRemoveList.add(r.binder);
- }
- }
- }
- }
- handleRemoveListLocked();
- }
- }
-
@Override
public void notifyMessageWaitingChangedForPhoneId(int phoneId, int subId, boolean mwi) {
if (!checkNotifyPermission("notifyMessageWaitingChanged()")) {
diff --git a/services/core/java/com/android/server/integrity/serializer/RuleBinarySerializer.java b/services/core/java/com/android/server/integrity/serializer/RuleBinarySerializer.java
index 7ecd624..d4f41eb 100644
--- a/services/core/java/com/android/server/integrity/serializer/RuleBinarySerializer.java
+++ b/services/core/java/com/android/server/integrity/serializer/RuleBinarySerializer.java
@@ -32,7 +32,7 @@
}
@Override
- public String serialize(List<Rule> rules, Optional<Integer> formatVersion) {
+ public byte[] serialize(List<Rule> rules, Optional<Integer> formatVersion) {
// TODO: Implement text serializer.
return null;
}
diff --git a/services/core/java/com/android/server/integrity/serializer/RuleSerializer.java b/services/core/java/com/android/server/integrity/serializer/RuleSerializer.java
index 1125f78..4fcff65 100644
--- a/services/core/java/com/android/server/integrity/serializer/RuleSerializer.java
+++ b/services/core/java/com/android/server/integrity/serializer/RuleSerializer.java
@@ -29,7 +29,7 @@
void serialize(List<Rule> rules, Optional<Integer> formatVersion, OutputStream outputStream)
throws RuleSerializeException;
- /** Serialize rules to a string. */
- String serialize(List<Rule> rule, Optional<Integer> formatVersion)
+ /** Serialize rules to a ByteArray. */
+ byte[] serialize(List<Rule> rule, Optional<Integer> formatVersion)
throws RuleSerializeException;
}
diff --git a/services/core/java/com/android/server/integrity/serializer/RuleXmlSerializer.java b/services/core/java/com/android/server/integrity/serializer/RuleXmlSerializer.java
index 254baba..3ec9cf2 100644
--- a/services/core/java/com/android/server/integrity/serializer/RuleXmlSerializer.java
+++ b/services/core/java/com/android/server/integrity/serializer/RuleXmlSerializer.java
@@ -62,14 +62,14 @@
}
@Override
- public String serialize(List<Rule> rules, Optional<Integer> formatVersion)
+ public byte[] serialize(List<Rule> rules, Optional<Integer> formatVersion)
throws RuleSerializeException {
try {
XmlSerializer xmlSerializer = Xml.newSerializer();
StringWriter writer = new StringWriter();
xmlSerializer.setOutput(writer);
serializeRules(rules, xmlSerializer);
- return writer.toString();
+ return writer.toString().getBytes(StandardCharsets.UTF_8);
} catch (Exception e) {
throw new RuleSerializeException(e.getMessage(), e);
}
diff --git a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
index 9b50307..0beff7a 100644
--- a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
+++ b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
@@ -20,7 +20,6 @@
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.AppGlobals;
-import android.app.admin.DevicePolicyManager;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
@@ -777,16 +776,6 @@
break;
case android.provider.Settings.Global.AUTO_TIME:
- DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class);
- if (dpm != null && dpm.getAutoTimeRequired()
- && "0".equals(value)) {
- return true;
- } else if (callingUid == Process.SYSTEM_UID) {
- return false;
- }
- restriction = UserManager.DISALLOW_CONFIG_DATE_TIME;
- break;
-
case android.provider.Settings.Global.AUTO_TIME_ZONE:
if (callingUid == Process.SYSTEM_UID) {
return false;
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index b264684..2499ad8 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -7366,6 +7366,7 @@
}
}
+ // TODO: (b/145604635) Add upgrade case
// Turn AUTO_TIME on in settings if it is required
if (required) {
long ident = mInjector.binderClearCallingIdentity();
@@ -7409,6 +7410,42 @@
}
}
+ /**
+ * Set whether auto time is enabled on the device.
+ */
+ @Override
+ public void setAutoTime(ComponentName who, boolean enabled) {
+ if (!mHasFeature) {
+ return;
+ }
+ Preconditions.checkNotNull(who, "ComponentName is null");
+ // TODO (b/145286957) Refactor security checks
+ enforceDeviceOwnerOrProfileOwnerOnUser0OrProfileOwnerOrganizationOwned();
+
+ mInjector.binderWithCleanCallingIdentity(() ->
+ mInjector.settingsGlobalPutInt(Settings.Global.AUTO_TIME, enabled ? 1 : 0));
+
+ DevicePolicyEventLogger
+ .createEvent(DevicePolicyEnums.SET_AUTO_TIME)
+ .setAdmin(who)
+ .setBoolean(enabled)
+ .write();
+ }
+
+ /**
+ * Returns whether or auto time is used on the device or not.
+ */
+ @Override
+ public boolean getAutoTime(ComponentName who) {
+ if (!mHasFeature) {
+ return false;
+ }
+ Preconditions.checkNotNull(who, "ComponentName is null");
+ enforceDeviceOwnerOrProfileOwnerOnUser0OrProfileOwnerOrganizationOwned();
+
+ return mInjector.settingsGlobalGetInt(Global.AUTO_TIME, 0) > 0;
+ }
+
@Override
public void setForceEphemeralUsers(ComponentName who, boolean forceEphemeralUsers) {
if (!mHasFeature) {
@@ -8599,20 +8636,42 @@
@Override
public boolean checkDeviceIdentifierAccess(String packageName, int pid, int uid) {
- // If the caller is not a system app then it should only be able to check its own device
- // identifier access.
- int callingUid = mInjector.binderGetCallingUid();
- int callingPid = mInjector.binderGetCallingPid();
- if (UserHandle.getAppId(callingUid) >= Process.FIRST_APPLICATION_UID
- && (callingUid != uid || callingPid != pid)) {
- String message = String.format(
- "Calling uid %d, pid %d cannot check device identifier access for package %s "
- + "(uid=%d, pid=%d)", callingUid, callingPid, packageName, uid, pid);
- Log.w(LOG_TAG, message);
- throw new SecurityException(message);
- }
+ ensureCallerIdentityMatchesIfNotSystem(packageName, pid, uid);
+
// Verify that the specified packages matches the provided uid.
- int userId = UserHandle.getUserId(uid);
+ if (!doesPackageMatchUid(packageName, uid)) {
+ return false;
+ }
+ // A device or profile owner must also have the READ_PHONE_STATE permission to access device
+ // identifiers. If the package being checked does not have this permission then deny access.
+ if (mContext.checkPermission(android.Manifest.permission.READ_PHONE_STATE, pid, uid)
+ != PackageManager.PERMISSION_GRANTED) {
+ return false;
+ }
+
+ // Allow access to the device owner or delegate cert installer.
+ ComponentName deviceOwner = getDeviceOwnerComponent(true);
+ if (deviceOwner != null && (deviceOwner.getPackageName().equals(packageName)
+ || isCallerDelegate(packageName, uid, DELEGATION_CERT_INSTALL))) {
+ return true;
+ }
+ final int userId = UserHandle.getUserId(uid);
+ // Allow access to the profile owner for the specified user, or delegate cert installer
+ // But only if this is an organization-owned device.
+ ComponentName profileOwner = getProfileOwnerAsUser(userId);
+ if (profileOwner != null && canProfileOwnerAccessDeviceIds(userId)
+ && (profileOwner.getPackageName().equals(packageName)
+ || isCallerDelegate(packageName, uid, DELEGATION_CERT_INSTALL))) {
+ return true;
+ }
+
+ Log.w(LOG_TAG, String.format("Package %s (uid=%d, pid=%d) cannot access Device IDs",
+ packageName, uid, pid));
+ return false;
+ }
+
+ private boolean doesPackageMatchUid(String packageName, int uid) {
+ final int userId = UserHandle.getUserId(uid);
try {
ApplicationInfo appInfo = mIPackageManager.getApplicationInfo(packageName, 0, userId);
// Since this call goes directly to PackageManagerService a NameNotFoundException is not
@@ -8634,29 +8693,22 @@
Log.e(LOG_TAG, "Exception caught obtaining appInfo for package " + packageName, e);
return false;
}
- // A device or profile owner must also have the READ_PHONE_STATE permission to access device
- // identifiers. If the package being checked does not have this permission then deny access.
- if (mContext.checkPermission(android.Manifest.permission.READ_PHONE_STATE, pid, uid)
- != PackageManager.PERMISSION_GRANTED) {
- return false;
- }
+ return true;
+ }
- // Allow access to the device owner or delegate cert installer.
- ComponentName deviceOwner = getDeviceOwnerComponent(true);
- if (deviceOwner != null && (deviceOwner.getPackageName().equals(packageName)
- || isCallerDelegate(packageName, uid, DELEGATION_CERT_INSTALL))) {
- return true;
+ private void ensureCallerIdentityMatchesIfNotSystem(String packageName, int pid, int uid) {
+ // If the caller is not a system app then it should only be able to check its own device
+ // identifier access.
+ int callingUid = mInjector.binderGetCallingUid();
+ int callingPid = mInjector.binderGetCallingPid();
+ if (UserHandle.getAppId(callingUid) >= Process.FIRST_APPLICATION_UID
+ && (callingUid != uid || callingPid != pid)) {
+ String message = String.format(
+ "Calling uid %d, pid %d cannot check device identifier access for package %s "
+ + "(uid=%d, pid=%d)", callingUid, callingPid, packageName, uid, pid);
+ Log.w(LOG_TAG, message);
+ throw new SecurityException(message);
}
- // Allow access to the profile owner for the specified user, or delegate cert installer
- ComponentName profileOwner = getProfileOwnerAsUser(userId);
- if (profileOwner != null && (profileOwner.getPackageName().equals(packageName)
- || isCallerDelegate(packageName, uid, DELEGATION_CERT_INSTALL))) {
- return true;
- }
-
- Log.w(LOG_TAG, String.format("Package %s (uid=%d, pid=%d) cannot access Device IDs",
- packageName, uid, pid));
- return false;
}
/**
@@ -8883,6 +8935,28 @@
"Only profile owner, device owner and system may call this method.");
}
+ private ActiveAdmin enforceDeviceOwnerOrProfileOwnerOnUser0OrProfileOwnerOrganizationOwned() {
+ synchronized (getLockObject()) {
+ // Check if there is a device owner
+ ActiveAdmin deviceOwner = getActiveAdminWithPolicyForUidLocked(null,
+ DeviceAdminInfo.USES_POLICY_DEVICE_OWNER, mInjector.binderGetCallingUid());
+ if (deviceOwner != null) return deviceOwner;
+
+ ActiveAdmin profileOwner = getActiveAdminWithPolicyForUidLocked(null,
+ DeviceAdminInfo.USES_POLICY_PROFILE_OWNER, mInjector.binderGetCallingUid());
+
+ // Check if there is a profile owner of an organization owned device
+ if (isProfileOwnerOfOrganizationOwnedDevice(profileOwner)) return profileOwner;
+
+ // Check if there is a profile owner called on user 0
+ if (profileOwner != null) {
+ enforceCallerSystemUserHandle();
+ return profileOwner;
+ }
+ }
+ throw new SecurityException("No active admin found");
+ }
+
private void enforceProfileOwnerOrFullCrossUsersPermission(int userId) {
if (userId == mInjector.userHandleGetCallingUserId()) {
synchronized (getLockObject()) {
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 162e766..0590020 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -2635,6 +2635,16 @@
mContext.callerPermissions.removeAll(OWNER_SETUP_PERMISSIONS);
}
+ private void setupProfileOwnerOnUser0() throws Exception {
+ mContext.callerPermissions.addAll(OWNER_SETUP_PERMISSIONS);
+
+ setUpPackageManagerForAdmin(admin1, DpmMockContext.CALLER_SYSTEM_USER_UID);
+ dpm.setActiveAdmin(admin1, false);
+ assertTrue(dpm.setProfileOwner(admin1, null, UserHandle.USER_SYSTEM));
+
+ mContext.callerPermissions.removeAll(OWNER_SETUP_PERMISSIONS);
+ }
+
private void setupDeviceOwner() throws Exception {
mContext.callerPermissions.addAll(OWNER_SETUP_PERMISSIONS);
@@ -3611,6 +3621,43 @@
Settings.System.SCREEN_BRIGHTNESS, "0", DpmMockContext.CALLER_USER_HANDLE);
}
+ public void testSetAutoTimeModifiesSetting() throws Exception {
+ mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
+ setupDeviceOwner();
+ dpm.setAutoTime(admin1, true);
+ verify(getServices().settings).settingsGlobalPutInt(Settings.Global.AUTO_TIME, 1);
+
+ dpm.setAutoTime(admin1, false);
+ verify(getServices().settings).settingsGlobalPutInt(Settings.Global.AUTO_TIME, 0);
+ }
+
+ public void testSetAutoTimeWithPOOnUser0() throws Exception {
+ mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
+ setupProfileOwnerOnUser0();
+ dpm.setAutoTime(admin1, true);
+ verify(getServices().settings).settingsGlobalPutInt(Settings.Global.AUTO_TIME, 1);
+
+ dpm.setAutoTime(admin1, false);
+ verify(getServices().settings).settingsGlobalPutInt(Settings.Global.AUTO_TIME, 0);
+ }
+
+ public void testSetAutoTimeFailWithPONotOnUser0() throws Exception {
+ setupProfileOwner();
+ assertExpectException(SecurityException.class, null, () -> dpm.setAutoTime(admin1, false));
+ verify(getServices().settings, never()).settingsGlobalPutInt(Settings.Global.AUTO_TIME, 0);
+ }
+
+ public void testSetAutoTimeWithPOOfOrganizationOwnedDevice() throws Exception {
+ setupProfileOwner();
+ configureProfileOwnerOfOrgOwnedDevice(admin1, DpmMockContext.CALLER_USER_HANDLE);
+
+ dpm.setAutoTime(admin1, true);
+ verify(getServices().settings).settingsGlobalPutInt(Settings.Global.AUTO_TIME, 1);
+
+ dpm.setAutoTime(admin1, false);
+ verify(getServices().settings).settingsGlobalPutInt(Settings.Global.AUTO_TIME, 0);
+ }
+
public void testSetTime() throws Exception {
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
setupDeviceOwner();
diff --git a/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleXmlSerializerTest.java b/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleXmlSerializerTest.java
index 180de2f..5903b5a 100644
--- a/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleXmlSerializerTest.java
+++ b/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleXmlSerializerTest.java
@@ -34,6 +34,7 @@
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
+import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashMap;
@@ -49,11 +50,11 @@
RuleSerializer xmlSerializer = new RuleXmlSerializer();
String expectedRules = "<RL />";
- String actualRules =
+ byte[] actualRules =
xmlSerializer.serialize(
Collections.singletonList(rule), /* formatVersion= */ Optional.empty());
- assertEquals(expectedRules, actualRules);
+ assertEquals(expectedRules, new String(actualRules, StandardCharsets.UTF_8));
}
@Test
@@ -82,11 +83,11 @@
+ "</R>"
+ "</RL>";
- String actualRules =
+ byte[] actualRules =
xmlSerializer.serialize(
Arrays.asList(rule1, rule2), /* formatVersion= */ Optional.empty());
- assertEquals(expectedRules, actualRules);
+ assertEquals(expectedRules, new String(actualRules, StandardCharsets.UTF_8));
}
@Test
@@ -128,8 +129,8 @@
/* formatVersion= */ Optional.empty(),
outputStream);
- String actualRules = outputStream.toString();
- assertEquals(expectedRules, actualRules);
+ byte[] actualRules = outputStream.toString().getBytes(StandardCharsets.UTF_8);
+ assertEquals(expectedRules, new String(actualRules, StandardCharsets.UTF_8));
}
@Test
@@ -165,11 +166,11 @@
+ "</R>"
+ "</RL>";
- String actualRules =
+ byte[] actualRules =
xmlSerializer.serialize(
Collections.singletonList(rule), /* formatVersion= */ Optional.empty());
- assertEquals(expectedRules, actualRules);
+ assertEquals(expectedRules, new String(actualRules, StandardCharsets.UTF_8));
}
@Test
@@ -215,11 +216,11 @@
+ "</R>"
+ "</RL>";
- String actualRules =
+ byte[] actualRules =
xmlSerializer.serialize(
Collections.singletonList(rule), /* formatVersion= */ Optional.empty());
- assertEquals(expectedRules, actualRules);
+ assertEquals(expectedRules, new String(actualRules, StandardCharsets.UTF_8));
}
@Test
@@ -265,11 +266,11 @@
+ "</R>"
+ "</RL>";
- String actualRules =
+ byte[] actualRules =
xmlSerializer.serialize(
Collections.singletonList(rule), /* formatVersion= */ Optional.empty());
- assertEquals(expectedRules, actualRules);
+ assertEquals(expectedRules, new String(actualRules, StandardCharsets.UTF_8));
}
@Test
@@ -297,11 +298,11 @@
+ "</R>"
+ "</RL>";
- String actualRules =
+ byte[] actualRules =
xmlSerializer.serialize(
Collections.singletonList(rule), /* formatVersion= */ Optional.empty());
- assertEquals(expectedRules, actualRules);
+ assertEquals(expectedRules, new String(actualRules, StandardCharsets.UTF_8));
}
@Test
@@ -327,11 +328,11 @@
+ "</R>"
+ "</RL>";
- String actualRules =
+ byte[] actualRules =
xmlSerializer.serialize(
Collections.singletonList(rule), /* formatVersion= */ Optional.empty());
- assertEquals(expectedRules, actualRules);
+ assertEquals(expectedRules, new String(actualRules, StandardCharsets.UTF_8));
}
@Test
@@ -355,11 +356,11 @@
+ "</R>"
+ "</RL>";
- String actualRules =
+ byte[] actualRules =
xmlSerializer.serialize(
Collections.singletonList(rule), /* formatVersion= */ Optional.empty());
- assertEquals(expectedRules, actualRules);
+ assertEquals(expectedRules, new String(actualRules, StandardCharsets.UTF_8));
}
@Test
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index 3ecf8d7..a0739c4 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -1512,7 +1512,6 @@
*/
@SystemApi
@TestApi
- //@RequiresPermission(android.Manifest.permission.BACKGROUND_CALL_AUDIO)
public void enterBackgroundAudioProcessing() {
if (mState != STATE_ACTIVE && mState != STATE_RINGING) {
throw new IllegalStateException("Call must be active or ringing");
@@ -1534,7 +1533,6 @@
*/
@SystemApi
@TestApi
- //@RequiresPermission(android.Manifest.permission.BACKGROUND_CALL_AUDIO)
public void exitBackgroundAudioProcessing(boolean shouldRing) {
if (mState != STATE_AUDIO_PROCESSING) {
throw new IllegalStateException("Call must in the audio processing state");
diff --git a/telecomm/java/android/telecom/CallScreeningService.java b/telecomm/java/android/telecom/CallScreeningService.java
index b91787c..f8722f4 100644
--- a/telecomm/java/android/telecom/CallScreeningService.java
+++ b/telecomm/java/android/telecom/CallScreeningService.java
@@ -144,7 +144,7 @@
private final boolean mShouldSilenceCall;
private final boolean mShouldSkipCallLog;
private final boolean mShouldSkipNotification;
- private final boolean mShouldScreenCallFurther;
+ private final boolean mShouldScreenCallViaAudioProcessing;
private CallResponse(
boolean shouldDisallowCall,
@@ -152,13 +152,13 @@
boolean shouldSilenceCall,
boolean shouldSkipCallLog,
boolean shouldSkipNotification,
- boolean shouldScreenCallFurther) {
+ boolean shouldScreenCallViaAudioProcessing) {
if (!shouldDisallowCall
&& (shouldRejectCall || shouldSkipCallLog || shouldSkipNotification)) {
throw new IllegalStateException("Invalid response state for allowed call.");
}
- if (shouldDisallowCall && shouldScreenCallFurther) {
+ if (shouldDisallowCall && shouldScreenCallViaAudioProcessing) {
throw new IllegalStateException("Invalid response state for allowed call.");
}
@@ -167,7 +167,7 @@
mShouldSkipCallLog = shouldSkipCallLog;
mShouldSkipNotification = shouldSkipNotification;
mShouldSilenceCall = shouldSilenceCall;
- mShouldScreenCallFurther = shouldScreenCallFurther;
+ mShouldScreenCallViaAudioProcessing = shouldScreenCallViaAudioProcessing;
}
/*
@@ -211,8 +211,8 @@
* for further screening of the call.
* @hide
*/
- public boolean getShouldScreenCallFurther() {
- return mShouldScreenCallFurther;
+ public boolean getShouldScreenCallViaAudioProcessing() {
+ return mShouldScreenCallViaAudioProcessing;
}
public static class Builder {
@@ -221,7 +221,7 @@
private boolean mShouldSilenceCall;
private boolean mShouldSkipCallLog;
private boolean mShouldSkipNotification;
- private boolean mShouldScreenCallFurther;
+ private boolean mShouldScreenCallViaAudioProcessing;
/**
* Sets whether the incoming call should be blocked.
@@ -285,13 +285,14 @@
* This request will only be honored if the {@link CallScreeningService} shares the same
* uid as the default dialer app. Otherwise, the call will go through as usual.
*
- * @param shouldScreenCallFurther Whether to request further call screening.
+ * @param shouldScreenCallViaAudioProcessing Whether to request further call screening.
* @hide
*/
@SystemApi
@TestApi
- public Builder setShouldScreenCallFurther(boolean shouldScreenCallFurther) {
- mShouldScreenCallFurther = shouldScreenCallFurther;
+ public @NonNull Builder setShouldScreenCallViaAudioProcessing(
+ boolean shouldScreenCallViaAudioProcessing) {
+ mShouldScreenCallViaAudioProcessing = shouldScreenCallViaAudioProcessing;
return this;
}
@@ -302,7 +303,7 @@
mShouldSilenceCall,
mShouldSkipCallLog,
mShouldSkipNotification,
- mShouldScreenCallFurther);
+ mShouldScreenCallViaAudioProcessing);
}
}
}
@@ -380,7 +381,7 @@
new ComponentName(getPackageName(), getClass().getName()));
} else if (response.getSilenceCall()) {
mCallScreeningAdapter.silenceCall(callDetails.getTelecomCallId());
- } else if (response.getShouldScreenCallFurther()) {
+ } else if (response.getShouldScreenCallViaAudioProcessing()) {
mCallScreeningAdapter.screenCallFurther(callDetails.getTelecomCallId());
} else {
mCallScreeningAdapter.allowCall(callDetails.getTelecomCallId());
diff --git a/telephony/java/android/telephony/AccessNetworkConstants.java b/telephony/java/android/telephony/AccessNetworkConstants.java
index 0320f75..bb28df2 100644
--- a/telephony/java/android/telephony/AccessNetworkConstants.java
+++ b/telephony/java/android/telephony/AccessNetworkConstants.java
@@ -261,16 +261,22 @@
public static final int BAND_7 = 7;
public static final int BAND_8 = 8;
public static final int BAND_12 = 12;
+ public static final int BAND_14 = 14;
+ public static final int BAND_18 = 18;
public static final int BAND_20 = 20;
public static final int BAND_25 = 25;
public static final int BAND_28 = 28;
+ public static final int BAND_29 = 29;
+ public static final int BAND_30 = 30;
public static final int BAND_34 = 34;
public static final int BAND_38 = 38;
public static final int BAND_39 = 39;
public static final int BAND_40 = 40;
public static final int BAND_41 = 41;
+ public static final int BAND_48 = 48;
public static final int BAND_50 = 50;
public static final int BAND_51 = 51;
+ public static final int BAND_65 = 65;
public static final int BAND_66 = 66;
public static final int BAND_70 = 70;
public static final int BAND_71 = 71;
@@ -286,6 +292,7 @@
public static final int BAND_83 = 83;
public static final int BAND_84 = 84;
public static final int BAND_86 = 86;
+ public static final int BAND_90 = 90;
/** FR2 bands */
public static final int BAND_257 = 257;
diff --git a/telephony/java/android/telephony/PhoneCapability.java b/telephony/java/android/telephony/PhoneCapability.java
index 17b7963f..8a75831 100644
--- a/telephony/java/android/telephony/PhoneCapability.java
+++ b/telephony/java/android/telephony/PhoneCapability.java
@@ -16,6 +16,8 @@
package android.telephony;
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -27,12 +29,13 @@
/**
* Define capability of a modem group. That is, the capabilities
* are shared between those modems defined by list of modem IDs.
- * @hide
*/
-public class PhoneCapability implements Parcelable {
+public final class PhoneCapability implements Parcelable {
// Hardcoded default DSDS capability.
+ /** @hide */
public static final PhoneCapability DEFAULT_DSDS_CAPABILITY;
// Hardcoded default Single SIM single standby capability.
+ /** @hide */
public static final PhoneCapability DEFAULT_SSSS_CAPABILITY;
static {
@@ -48,13 +51,18 @@
logicalModemList.add(modemInfo1);
DEFAULT_SSSS_CAPABILITY = new PhoneCapability(1, 1, 0, logicalModemList, false);
}
-
+ /** @hide */
public final int maxActiveVoiceCalls;
+ /** @hide */
public final int maxActiveData;
+ /** @hide */
public final int max5G;
+ /** @hide */
public final boolean validationBeforeSwitchSupported;
+ /** @hide */
public final List<ModemInfo> logicalModemList;
+ /** @hide */
public PhoneCapability(int maxActiveVoiceCalls, int maxActiveData, int max5G,
List<ModemInfo> logicalModemList, boolean validationBeforeSwitchSupported) {
this.maxActiveVoiceCalls = maxActiveVoiceCalls;
@@ -116,7 +124,7 @@
/**
* {@link Parcelable#writeToParcel}
*/
- public void writeToParcel(Parcel dest, @Parcelable.WriteFlags int flags) {
+ public void writeToParcel(@NonNull Parcel dest, @Parcelable.WriteFlags int flags) {
dest.writeInt(maxActiveVoiceCalls);
dest.writeInt(maxActiveData);
dest.writeInt(max5G);