diff options
37 files changed, 785 insertions, 205 deletions
diff --git a/core/api/current.txt b/core/api/current.txt index d9753ab5e4a0..c3b5b943477f 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -42841,6 +42841,7 @@ package android.telephony { method public int getPhoneType(); method @RequiresPermission(anyOf={"android.permission.READ_PRIVILEGED_PHONE_STATE", android.Manifest.permission.READ_PHONE_STATE}) public int getPreferredOpportunisticDataSubscription(); method @Nullable @RequiresPermission(allOf={android.Manifest.permission.READ_PHONE_STATE, android.Manifest.permission.ACCESS_COARSE_LOCATION}) public android.telephony.ServiceState getServiceState(); + method @Nullable @RequiresPermission(allOf={android.Manifest.permission.READ_PHONE_STATE, android.Manifest.permission.ACCESS_COARSE_LOCATION}) public android.telephony.ServiceState getServiceState(boolean, boolean); method @Nullable public android.telephony.SignalStrength getSignalStrength(); method public int getSimCarrierId(); method @Nullable public CharSequence getSimCarrierIdName(); @@ -42893,8 +42894,10 @@ package android.telephony { method public boolean isWorldPhone(); method @Deprecated public void listen(android.telephony.PhoneStateListener, int); method public void registerTelephonyCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyCallback); + method public void registerTelephonyCallback(boolean, boolean, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyCallback); method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public void requestCellInfoUpdate(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CellInfoCallback); method @RequiresPermission(allOf={android.Manifest.permission.MODIFY_PHONE_STATE, android.Manifest.permission.ACCESS_FINE_LOCATION}) public android.telephony.NetworkScan requestNetworkScan(android.telephony.NetworkScanRequest, java.util.concurrent.Executor, android.telephony.TelephonyScanManager.NetworkScanCallback); + method @Nullable @RequiresPermission(allOf={android.Manifest.permission.MODIFY_PHONE_STATE, android.Manifest.permission.ACCESS_FINE_LOCATION}) public android.telephony.NetworkScan requestNetworkScan(boolean, @NonNull android.telephony.NetworkScanRequest, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyScanManager.NetworkScanCallback); method public void sendDialerSpecialCode(String); method public String sendEnvelopeWithStatus(String); method @RequiresPermission(android.Manifest.permission.CALL_PHONE) public void sendUssdRequest(String, android.telephony.TelephonyManager.UssdResponseCallback, android.os.Handler); diff --git a/core/api/system-current.txt b/core/api/system-current.txt index ca3c51152514..da9a4c50d3cb 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -11698,6 +11698,14 @@ package android.telephony { field public static final int ROAMING_TYPE_UNKNOWN = 1; // 0x1 } + public final class SignalStrengthUpdateRequest implements android.os.Parcelable { + method public boolean isSystemThresholdReportingRequestedWhileIdle(); + } + + public static final class SignalStrengthUpdateRequest.Builder { + method @NonNull @RequiresPermission("android.permission.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH") public android.telephony.SignalStrengthUpdateRequest.Builder setSystemThresholdReportingRequestedWhileIdle(boolean); + } + public final class SmsCbCmasInfo implements android.os.Parcelable { ctor public SmsCbCmasInfo(int, int, int, int, int, int); method public int describeContents(); @@ -13490,12 +13498,14 @@ package android.telephony.ims { } public final class RcsClientConfiguration implements android.os.Parcelable { - ctor public RcsClientConfiguration(@NonNull String, @NonNull String, @NonNull String, @NonNull String); + ctor @Deprecated public RcsClientConfiguration(@NonNull String, @NonNull String, @NonNull String, @NonNull String); + ctor public RcsClientConfiguration(@NonNull String, @NonNull String, @NonNull String, @NonNull String, boolean); method public int describeContents(); method @NonNull public String getClientVendor(); method @NonNull public String getClientVersion(); method @NonNull public String getRcsProfile(); method @NonNull public String getRcsVersion(); + method public boolean isRcsEnabledByUser(); method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.RcsClientConfiguration> CREATOR; field public static final String RCS_PROFILE_1_0 = "UP_1.0"; @@ -13632,6 +13642,7 @@ package android.telephony.ims { field public static final int PUBLISH_STATE_NOT_PUBLISHED = 2; // 0x2 field public static final int PUBLISH_STATE_OK = 1; // 0x1 field public static final int PUBLISH_STATE_OTHER_ERROR = 6; // 0x6 + field public static final int PUBLISH_STATE_PUBLISHING = 7; // 0x7 field public static final int PUBLISH_STATE_RCS_PROVISION_ERROR = 4; // 0x4 field public static final int PUBLISH_STATE_REQUEST_TIMEOUT = 5; // 0x5 field public static final int PUBLISH_STATE_VOICE_PROVISION_ERROR = 3; // 0x3 @@ -13894,6 +13905,7 @@ package android.telephony.ims.feature { package android.telephony.ims.stub { public interface CapabilityExchangeEventListener { + method public default void onPublishUpdated(int, @NonNull String, int, @NonNull String) throws android.telephony.ims.ImsException; method public void onRemoteCapabilityRequest(@NonNull android.net.Uri, @NonNull java.util.Set<java.lang.String>, @NonNull android.telephony.ims.stub.CapabilityExchangeEventListener.OptionsRequestCallback) throws android.telephony.ims.ImsException; method public void onRequestPublishCapabilities(int) throws android.telephony.ims.ImsException; method public void onUnpublish() throws android.telephony.ims.ImsException; diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java index b23c3eb0ceae..5612e7cf56ce 100644 --- a/core/java/android/bluetooth/BluetoothAdapter.java +++ b/core/java/android/bluetooth/BluetoothAdapter.java @@ -56,7 +56,7 @@ import android.os.ParcelUuid; import android.os.RemoteException; import android.os.ResultReceiver; import android.os.ServiceManager; -import android.os.SystemProperties; +import android.sysprop.BluetoothProperties; import android.util.Log; import android.util.Pair; @@ -1337,7 +1337,7 @@ public final class BluetoothAdapter { return true; } Log.e(TAG, "factoryReset(): Setting persist.bluetooth.factoryreset to retry later"); - SystemProperties.set("persist.bluetooth.factoryreset", "true"); + BluetoothProperties.factory_reset(true); } catch (RemoteException e) { Log.e(TAG, "", e); } finally { diff --git a/core/java/android/os/Trace.java b/core/java/android/os/Trace.java index ddb6533547bb..d974e0c0713a 100644 --- a/core/java/android/os/Trace.java +++ b/core/java/android/os/Trace.java @@ -131,6 +131,10 @@ public final class Trace { private static native void nativeAsyncTraceBegin(long tag, String name, int cookie); @FastNative private static native void nativeAsyncTraceEnd(long tag, String name, int cookie); + @FastNative + private static native void nativeInstant(long tag, String name); + @FastNative + private static native void nativeInstantForTrack(long tag, String trackName, String name); private Trace() { } @@ -258,6 +262,42 @@ public final class Trace { } /** + * Writes a trace message to indicate that a given section of code was invoked. + * + * @param traceTag The trace tag. + * @param methodName The method name to appear in the trace. + * @hide + */ + public static void instant(long traceTag, String methodName) { + if (methodName == null) { + throw new IllegalArgumentException("methodName cannot be null"); + } + if (isTagEnabled(traceTag)) { + nativeInstant(traceTag, methodName); + } + } + + /** + * Writes a trace message to indicate that a given section of code was invoked. + * + * @param traceTag The trace tag. + * @param trackName The track where the event should appear in the trace. + * @param methodName The method name to appear in the trace. + * @hide + */ + public static void instantForTrack(long traceTag, String trackName, String methodName) { + if (trackName == null) { + throw new IllegalArgumentException("trackName cannot be null"); + } + if (methodName == null) { + throw new IllegalArgumentException("methodName cannot be null"); + } + if (isTagEnabled(traceTag)) { + nativeInstantForTrack(traceTag, trackName, methodName); + } + } + + /** * Checks whether or not tracing is currently enabled. This is useful to avoid intermediate * string creation for trace sections that require formatting. It is not necessary * to guard all Trace method calls as they internally already check this. However it is diff --git a/core/java/android/telephony/TelephonyRegistryManager.java b/core/java/android/telephony/TelephonyRegistryManager.java index cb1cff9cda22..859fd804dea5 100644 --- a/core/java/android/telephony/TelephonyRegistryManager.java +++ b/core/java/android/telephony/TelephonyRegistryManager.java @@ -247,8 +247,8 @@ public class TelephonyRegistryManager { } else if (listener.mSubId != null) { subId = listener.mSubId; } - sRegistry.listenWithEventList( - subId, pkg, featureId, listener.callback, eventsList, notifyNow); + sRegistry.listenWithEventList(false, false, subId, pkg, featureId, + listener.callback, eventsList, notifyNow); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -263,11 +263,13 @@ public class TelephonyRegistryManager { * @param events List events * @param notifyNow Whether to notify instantly */ - private void listenFromCallback(int subId, @NonNull String pkg, @NonNull String featureId, + private void listenFromCallback(boolean renounceFineLocationAccess, + boolean renounceCoarseLocationAccess, int subId, + @NonNull String pkg, @NonNull String featureId, @NonNull TelephonyCallback telephonyCallback, @NonNull int[] events, boolean notifyNow) { try { - sRegistry.listenWithEventList( + sRegistry.listenWithEventList(renounceFineLocationAccess, renounceCoarseLocationAccess, subId, pkg, featureId, telephonyCallback.callback, events, notifyNow); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -1161,14 +1163,17 @@ public class TelephonyRegistryManager { * * @param callback The {@link TelephonyCallback} object to register. */ - public void registerTelephonyCallback(@NonNull @CallbackExecutor Executor executor, + public void registerTelephonyCallback(boolean renounceFineLocationAccess, + boolean renounceCoarseLocationAccess, + @NonNull @CallbackExecutor Executor executor, int subId, String pkgName, String attributionTag, @NonNull TelephonyCallback callback, boolean notifyNow) { if (callback == null) { throw new IllegalStateException("telephony service is null."); } callback.init(executor); - listenFromCallback(subId, pkgName, attributionTag, callback, + listenFromCallback(renounceFineLocationAccess, renounceCoarseLocationAccess, subId, + pkgName, attributionTag, callback, getEventsFromCallback(callback).stream().mapToInt(i -> i).toArray(), notifyNow); } @@ -1179,6 +1184,7 @@ public class TelephonyRegistryManager { */ public void unregisterTelephonyCallback(int subId, String pkgName, String attributionTag, @NonNull TelephonyCallback callback, boolean notifyNow) { - listenFromCallback(subId, pkgName, attributionTag, callback, new int[0], notifyNow); + listenFromCallback(false, false, subId, + pkgName, attributionTag, callback, new int[0], notifyNow); } } diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java index 6c3c38359957..546d6de82935 100644 --- a/core/java/android/util/FeatureFlagUtils.java +++ b/core/java/android/util/FeatureFlagUtils.java @@ -51,6 +51,10 @@ public class FeatureFlagUtils { /** @hide */ public static final String SETTINGS_ENABLE_SECURITY_HUB = "settings_enable_security_hub"; + /** @hide */ + public static final String SETTINGS_ENABLE_MONITOR_PHANTOM_PROCS = + "settings_enable_monitor_phantom_procs"; + private static final Map<String, String> DEFAULT_FLAGS; static { @@ -72,12 +76,14 @@ public class FeatureFlagUtils { DEFAULT_FLAGS.put(SETTINGS_PROVIDER_MODEL, "true"); DEFAULT_FLAGS.put(SETTINGS_USE_NEW_BACKUP_ELIGIBILITY_RULES, "true"); DEFAULT_FLAGS.put(SETTINGS_ENABLE_SECURITY_HUB, "true"); + DEFAULT_FLAGS.put(SETTINGS_ENABLE_MONITOR_PHANTOM_PROCS, "true"); } private static final Set<String> PERSISTENT_FLAGS; static { PERSISTENT_FLAGS = new HashSet<>(); PERSISTENT_FLAGS.add(SETTINGS_PROVIDER_MODEL); + PERSISTENT_FLAGS.add(SETTINGS_ENABLE_MONITOR_PHANTOM_PROCS); } /** diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index cf12955787b1..2320434f14f6 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -26842,44 +26842,38 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * Handles drag events sent by the system following a call to * {@link android.view.View#startDragAndDrop(ClipData,DragShadowBuilder,Object,int) * startDragAndDrop()}. - *<p> - * When the system calls this method, it passes a - * {@link android.view.DragEvent} object. A call to - * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined - * in DragEvent. The method uses these to determine what is happening in the drag and drop - * operation. - * </p> * <p> - * The default implementation returns false, except if an {@link OnReceiveContentListener} - * is {@link #setOnReceiveContentListener set} for this view. If an - * {@link OnReceiveContentListener} is set, the default implementation... + * The system calls this method and passes a {@link DragEvent} object in response to drag and + * drop events. This method can then call {@link DragEvent#getAction()} to determine the state + * of the drag and drop operation. + * <p> + * The default implementation returns {@code false} unless an {@link OnReceiveContentListener} + * has been set for this view (see {@link #setOnReceiveContentListener}), in which case + * the default implementation does the following: * <ul> - * <li>returns true for an - * {@link android.view.DragEvent#ACTION_DRAG_STARTED ACTION_DRAG_STARTED} event - * <li>calls {@link #performReceiveContent} for an - * {@link android.view.DragEvent#ACTION_DROP ACTION_DROP} event - * <li>returns true for an {@link android.view.DragEvent#ACTION_DROP ACTION_DROP} event, if - * the listener consumed some or all of the content + * <li>Returns {@code true} for an + * {@link DragEvent#ACTION_DRAG_STARTED ACTION_DRAG_STARTED} event + * <li>Calls {@link #performReceiveContent} for an + * {@link DragEvent#ACTION_DROP ACTION_DROP} event + * <li>Returns {@code true} for an {@link DragEvent#ACTION_DROP ACTION_DROP} event if the + * {@code OnReceiveContentListener} consumed some or all of the content * </ul> - * </p> * - * @param event The {@link android.view.DragEvent} sent by the system. - * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined - * in DragEvent, indicating the type of drag event represented by this object. - * @return {@code true} if the method was successful, otherwise {@code false}. - * <p> - * The method should return {@code true} in response to an action type of - * {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current - * operation. - * </p> - * <p> - * The method should also return {@code true} in response to an action type of - * {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or - * {@code false} if it didn't. - * </p> - * <p> - * For all other events, the return value is ignored. - * </p> + * @param event The {@link DragEvent} object sent by the system. The + * {@link DragEvent#getAction()} method returns an action type constant that indicates the + * type of drag event represented by this object. + * @return {@code true} if the method successfully handled the drag event, otherwise + * {@code false}. + * <p> + * The method must return {@code true} in response to an + * {@link DragEvent#ACTION_DRAG_STARTED ACTION_DRAG_STARTED} action type to continue to + * receive drag events for the current drag and drop operation. + * <p> + * The method should return {@code true} in response to an + * {@link DragEvent#ACTION_DROP ACTION_DROP} action type if the dropped data was consumed + * (at least partially); {@code false}, if none of the data was consumed. + * <p> + * For all other events, the return value is {@code false}. */ public boolean onDragEvent(DragEvent event) { if (mListenerInfo == null || mListenerInfo.mOnReceiveContentListener == null) { @@ -28844,27 +28838,27 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } /** - * Interface definition for a callback to be invoked when a drag is being dispatched - * to this view. The callback will be invoked before the hosting view's own - * onDrag(event) method. If the listener wants to fall back to the hosting view's - * onDrag(event) behavior, it should return 'false' from this callback. + * Interface definition for a listener that's invoked when a drag event is dispatched to this + * view. The listener is invoked before the view's own + * {@link #onDragEvent(DragEvent)} method. To fall back to the view's + * {@code onDragEvent(DragEvent)} behavior, return {@code false} from the listener method. * * <div class="special reference"> - * <h3>Developer Guides</h3> - * <p>For a guide to implementing drag and drop features, read the - * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p> + * <h3>Developer Guides</h3> + * <p>For a guide to implementing drag and drop features, see the + * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and drop</a> developer guide.</p> * </div> */ public interface OnDragListener { /** - * Called when a drag event is dispatched to a view. This allows listeners - * to get a chance to override base View behavior. + * Called when a drag event is dispatched to a view. Enables listeners to override the + * base behavior provided by {@link #onDragEvent(DragEvent)}. * - * @param v The View that received the drag event. - * @param event The {@link android.view.DragEvent} object for the drag event. - * @return {@code true} if the drag event was handled successfully, or {@code false} - * if the drag event was not handled. Note that {@code false} will trigger the View - * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler. + * @param v The {@code View} that received the drag event. + * @param event The event object for the drag event. + * @return {@code true} if the drag event was handled successfully; {@code false}, if the + * drag event was not handled. <b>Note:</b> A {@code false} return value triggers the + * view's {@link #onDragEvent(DragEvent)} handler. */ boolean onDrag(View v, DragEvent event); } diff --git a/core/java/android/view/inputmethod/InputConnection.java b/core/java/android/view/inputmethod/InputConnection.java index 5f036a348808..4d7d182f0013 100644 --- a/core/java/android/view/inputmethod/InputConnection.java +++ b/core/java/android/view/inputmethod/InputConnection.java @@ -770,20 +770,25 @@ public interface InputConnection { boolean beginBatchEdit(); /** - * Tell the editor that you are done with a batch edit previously - * initiated with {@link #beginBatchEdit}. This ends the latest - * batch only. - * - * <p><strong>IME authors:</strong> make sure you call this - * exactly once for each call to {@link #beginBatchEdit}.</p> - * - * <p><strong>Editor authors:</strong> please be careful about - * batch edit nesting. Updates still to be held back until the end - * of the last batch edit.</p> + * Tell the editor that you are done with a batch edit previously initiated with + * {@link #beginBatchEdit()}. This ends the latest batch only. + * + * <p><strong>IME authors:</strong> make sure you call this exactly once for each call to + * {@link #beginBatchEdit()}.</p> + * + * <p><strong>Editor authors:</strong> please be careful about batch edit nesting. Updates still + * to be held back until the end of the last batch edit. In case you are delegating this API + * call to the one obtained from + * {@link android.widget.EditText#onCreateInputConnection(EditorInfo)}, there was an off-by-one + * that had returned {@code true} when its nested batch edit count becomes {@code 0} as a result + * of invoking this API. This bug is fixed in {@link android.os.Build.VERSION_CODES#TIRAMISU}. + * </p> * - * @return true if there is still a batch edit in progress after closing - * the latest one (in other words, if the nesting count is > 0), false - * otherwise or if the input connection is no longer valid. + * @return For editor authors, you must return {@code true} if a batch edit is still in progress + * after closing the latest one (in other words, if the nesting count is still a + * positive number). Return {@code false} otherwise. For IME authors, you will + * always receive {@code true} as long as the request was sent to the editor, and + * receive {@code false} only if the input connection is no longer valid. */ boolean endBatchEdit(); diff --git a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl index a0a0f3276b99..6ba0279313b1 100644 --- a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl +++ b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl @@ -43,7 +43,8 @@ interface ITelephonyRegistry { void removeOnSubscriptionsChangedListener(String pkg, IOnSubscriptionsChangedListener callback); - void listenWithEventList(in int subId, String pkg, String featureId, + void listenWithEventList(in boolean renounceFineLocationAccess, + in boolean renounceCoarseLocationAccess, in int subId, String pkg, String featureId, IPhoneStateListener callback, in int[] events, boolean notifyNow); @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553) void notifyCallStateForAllSubs(int state, String incomingNumber); diff --git a/core/java/com/android/internal/widget/EditableInputConnection.java b/core/java/com/android/internal/widget/EditableInputConnection.java index 02ffe8c5268e..040d78b65afa 100644 --- a/core/java/com/android/internal/widget/EditableInputConnection.java +++ b/core/java/com/android/internal/widget/EditableInputConnection.java @@ -92,7 +92,7 @@ public class EditableInputConnection extends BaseInputConnection // contribution to mTextView's nested batch edit count is zero. mTextView.endBatchEdit(); mBatchEditNesting--; - return true; + return mBatchEditNesting > 0; } } return false; diff --git a/core/jni/android_os_Trace.cpp b/core/jni/android_os_Trace.cpp index f67007cda209..85fd5d99e473 100644 --- a/core/jni/android_os_Trace.cpp +++ b/core/jni/android_os_Trace.cpp @@ -90,6 +90,22 @@ static void android_os_Trace_nativeSetTracingEnabled(JNIEnv*, jclass, jboolean e atrace_set_tracing_enabled(enabled); } +static void android_os_Trace_nativeInstant(JNIEnv* env, jclass, + jlong tag, jstring nameStr) { + withString(env, nameStr, [tag](char* str) { + atrace_instant(tag, str); + }); +} + +static void android_os_Trace_nativeInstantForTrack(JNIEnv* env, jclass, + jlong tag, jstring trackStr, jstring nameStr) { + withString(env, trackStr, [env, tag, nameStr](char* track) { + withString(env, nameStr, [tag, track](char* name) { + atrace_instant_for_track(tag, track, name); + }); + }); +} + static const JNINativeMethod gTraceMethods[] = { /* name, signature, funcPtr */ { "nativeSetAppTracingAllowed", @@ -116,6 +132,12 @@ static const JNINativeMethod gTraceMethods[] = { { "nativeAsyncTraceEnd", "(JLjava/lang/String;I)V", (void*)android_os_Trace_nativeAsyncTraceEnd }, + { "nativeInstant", + "(JLjava/lang/String;)V", + (void*)android_os_Trace_nativeInstant }, + { "nativeInstantForTrack", + "(JLjava/lang/String;Ljava/lang/String;)V", + (void*)android_os_Trace_nativeInstantForTrack }, // ----------- @CriticalNative ---------------- { "nativeGetEnabledTags", diff --git a/core/jni/android_view_InputEventReceiver.cpp b/core/jni/android_view_InputEventReceiver.cpp index a699f912806d..7d0f60adeb5c 100644 --- a/core/jni/android_view_InputEventReceiver.cpp +++ b/core/jni/android_view_InputEventReceiver.cpp @@ -447,10 +447,6 @@ status_t NativeInputEventReceiver::consumeEvents(JNIEnv* env, skipCallbacks = true; } } - - if (skipCallbacks) { - mInputConsumer.sendFinishedSignal(seq, false); - } } } diff --git a/packages/ConnectivityT/framework-t/src/android/net/IpSecAlgorithm.java b/packages/ConnectivityT/framework-t/src/android/net/IpSecAlgorithm.java index 86052484eaf6..840af28b77e7 100644 --- a/packages/ConnectivityT/framework-t/src/android/net/IpSecAlgorithm.java +++ b/packages/ConnectivityT/framework-t/src/android/net/IpSecAlgorithm.java @@ -297,7 +297,7 @@ public final class IpSecAlgorithm implements Parcelable { return mTruncLenBits; } - /* Parcelable Implementation */ + /** Parcelable Implementation */ public int describeContents() { return 0; } diff --git a/packages/ConnectivityT/framework-t/src/android/net/IpSecManager.java b/packages/ConnectivityT/framework-t/src/android/net/IpSecManager.java index c10680761ff1..837629911ccd 100644 --- a/packages/ConnectivityT/framework-t/src/android/net/IpSecManager.java +++ b/packages/ConnectivityT/framework-t/src/android/net/IpSecManager.java @@ -99,9 +99,9 @@ public final class IpSecManager { /** @hide */ public interface Status { - public static final int OK = 0; - public static final int RESOURCE_UNAVAILABLE = 1; - public static final int SPI_UNAVAILABLE = 2; + int OK = 0; + int RESOURCE_UNAVAILABLE = 1; + int SPI_UNAVAILABLE = 2; } /** @hide */ @@ -276,7 +276,7 @@ public final class IpSecManager { * @param destinationAddress the destination address for traffic bearing the requested SPI. * For inbound traffic, the destination should be an address currently assigned on-device. * @return the reserved SecurityParameterIndex - * @throws {@link #ResourceUnavailableException} indicating that too many SPIs are + * @throws ResourceUnavailableException indicating that too many SPIs are * currently allocated for this user */ @NonNull @@ -307,9 +307,9 @@ public final class IpSecManager { * @param requestedSpi the requested SPI. The range 1-255 is reserved and may not be used. See * RFC 4303 Section 2.1. * @return the reserved SecurityParameterIndex - * @throws {@link #ResourceUnavailableException} indicating that too many SPIs are + * @throws ResourceUnavailableException indicating that too many SPIs are * currently allocated for this user - * @throws {@link #SpiUnavailableException} indicating that the requested SPI could not be + * @throws SpiUnavailableException indicating that the requested SPI could not be * reserved */ @NonNull diff --git a/packages/ConnectivityT/framework-t/src/android/net/IpSecTransformResponse.java b/packages/ConnectivityT/framework-t/src/android/net/IpSecTransformResponse.java index a38488954fc0..363f3165ee65 100644 --- a/packages/ConnectivityT/framework-t/src/android/net/IpSecTransformResponse.java +++ b/packages/ConnectivityT/framework-t/src/android/net/IpSecTransformResponse.java @@ -60,7 +60,8 @@ public final class IpSecTransformResponse implements Parcelable { resourceId = in.readInt(); } - public static final @android.annotation.NonNull Parcelable.Creator<IpSecTransformResponse> CREATOR = + @android.annotation.NonNull + public static final Parcelable.Creator<IpSecTransformResponse> CREATOR = new Parcelable.Creator<IpSecTransformResponse>() { public IpSecTransformResponse createFromParcel(Parcel in) { return new IpSecTransformResponse(in); diff --git a/packages/ConnectivityT/framework-t/src/android/net/IpSecTunnelInterfaceResponse.java b/packages/ConnectivityT/framework-t/src/android/net/IpSecTunnelInterfaceResponse.java index e3411e003d6b..127e30a69394 100644 --- a/packages/ConnectivityT/framework-t/src/android/net/IpSecTunnelInterfaceResponse.java +++ b/packages/ConnectivityT/framework-t/src/android/net/IpSecTunnelInterfaceResponse.java @@ -65,7 +65,8 @@ public final class IpSecTunnelInterfaceResponse implements Parcelable { interfaceName = in.readString(); } - public static final @android.annotation.NonNull Parcelable.Creator<IpSecTunnelInterfaceResponse> CREATOR = + @android.annotation.NonNull + public static final Parcelable.Creator<IpSecTunnelInterfaceResponse> CREATOR = new Parcelable.Creator<IpSecTunnelInterfaceResponse>() { public IpSecTunnelInterfaceResponse createFromParcel(Parcel in) { return new IpSecTunnelInterfaceResponse(in); diff --git a/packages/ConnectivityT/framework-t/src/android/net/IpSecUdpEncapResponse.java b/packages/ConnectivityT/framework-t/src/android/net/IpSecUdpEncapResponse.java index 4e7ba9b515d0..732cf198a9cc 100644 --- a/packages/ConnectivityT/framework-t/src/android/net/IpSecUdpEncapResponse.java +++ b/packages/ConnectivityT/framework-t/src/android/net/IpSecUdpEncapResponse.java @@ -18,6 +18,7 @@ package android.net; import android.os.Parcel; import android.os.ParcelFileDescriptor; import android.os.Parcelable; + import java.io.FileDescriptor; import java.io.IOException; @@ -83,7 +84,8 @@ public final class IpSecUdpEncapResponse implements Parcelable { fileDescriptor = in.readParcelable(ParcelFileDescriptor.class.getClassLoader()); } - public static final @android.annotation.NonNull Parcelable.Creator<IpSecUdpEncapResponse> CREATOR = + @android.annotation.NonNull + public static final Parcelable.Creator<IpSecUdpEncapResponse> CREATOR = new Parcelable.Creator<IpSecUdpEncapResponse>() { public IpSecUdpEncapResponse createFromParcel(Parcel in) { return new IpSecUdpEncapResponse(in); diff --git a/packages/ConnectivityT/service/src/com/android/server/IpSecService.java b/packages/ConnectivityT/service/src/com/android/server/IpSecService.java index aeb814327e66..f251b86b7a09 100644 --- a/packages/ConnectivityT/service/src/com/android/server/IpSecService.java +++ b/packages/ConnectivityT/service/src/com/android/server/IpSecService.java @@ -119,6 +119,7 @@ public class IpSecService extends IIpSecService.Stub { /* Binder context for this service */ private final Context mContext; + private final Dependencies mDeps; /** * The next non-repeating global ID for tracking resources between users, this service, and @@ -129,23 +130,24 @@ public class IpSecService extends IIpSecService.Stub { @GuardedBy("IpSecService.this") private int mNextResourceId = 1; - interface IpSecServiceConfiguration { - INetd getNetdInstance() throws RemoteException; - - static IpSecServiceConfiguration GETSRVINSTANCE = - new IpSecServiceConfiguration() { - @Override - public INetd getNetdInstance() throws RemoteException { - final INetd netd = NetdService.getInstance(); - if (netd == null) { - throw new RemoteException("Failed to Get Netd Instance"); - } - return netd; - } - }; + /** + * Dependencies of IpSecService, for injection in tests. + */ + @VisibleForTesting + public static class Dependencies { + /** + * Get a reference to INetd. + */ + public INetd getNetdInstance(Context context) throws RemoteException { + final INetd netd = INetd.Stub.asInterface((IBinder) + context.getSystemService(Context.NETD_SERVICE)); + if (netd == null) { + throw new RemoteException("Failed to Get Netd Instance"); + } + return netd; + } } - private final IpSecServiceConfiguration mSrvConfig; final UidFdTagger mUidFdTagger; /** @@ -491,8 +493,8 @@ public class IpSecService extends IIpSecService.Stub { * <p>This class associates kernel resources with the UID that owns and controls them. */ private abstract class OwnedResourceRecord implements IResource { - final int pid; - final int uid; + final int mPid; + final int mUid; protected final int mResourceId; OwnedResourceRecord(int resourceId) { @@ -501,8 +503,8 @@ public class IpSecService extends IIpSecService.Stub { throw new IllegalArgumentException("Resource ID must not be INVALID_RESOURCE_ID"); } mResourceId = resourceId; - pid = Binder.getCallingPid(); - uid = Binder.getCallingUid(); + mPid = Binder.getCallingPid(); + mUid = Binder.getCallingUid(); getResourceTracker().take(); } @@ -512,7 +514,7 @@ public class IpSecService extends IIpSecService.Stub { /** Convenience method; retrieves the user resource record for the stored UID. */ protected UserRecord getUserRecord() { - return mUserResourceTracker.getUserRecord(uid); + return mUserResourceTracker.getUserRecord(mUid); } @Override @@ -527,9 +529,9 @@ public class IpSecService extends IIpSecService.Stub { .append("{mResourceId=") .append(mResourceId) .append(", pid=") - .append(pid) + .append(mPid) .append(", uid=") - .append(uid) + .append(mUid) .append("}") .toString(); } @@ -545,7 +547,7 @@ public class IpSecService extends IIpSecService.Stub { SparseArray<RefcountedResource<T>> mArray = new SparseArray<>(); private final String mTypeName; - public RefcountedResourceArray(String typeName) { + RefcountedResourceArray(String typeName) { this.mTypeName = typeName; } @@ -625,10 +627,10 @@ public class IpSecService extends IIpSecService.Stub { public void freeUnderlyingResources() { int spi = mSpi.getSpi(); try { - mSrvConfig - .getNetdInstance() + mDeps + .getNetdInstance(mContext) .ipSecDeleteSecurityAssociation( - uid, + mUid, mConfig.getSourceAddress(), mConfig.getDestinationAddress(), spi, @@ -678,11 +680,14 @@ public class IpSecService extends IIpSecService.Stub { private final String mSourceAddress; private final String mDestinationAddress; private int mSpi; + private final Context mContext; private boolean mOwnedByTransform = false; - SpiRecord(int resourceId, String sourceAddress, String destinationAddress, int spi) { + SpiRecord(Context context, int resourceId, String sourceAddress, + String destinationAddress, int spi) { super(resourceId); + mContext = context; mSourceAddress = sourceAddress; mDestinationAddress = destinationAddress; mSpi = spi; @@ -693,10 +698,10 @@ public class IpSecService extends IIpSecService.Stub { public void freeUnderlyingResources() { try { if (!mOwnedByTransform) { - mSrvConfig - .getNetdInstance() + mDeps + .getNetdInstance(mContext) .ipSecDeleteSecurityAssociation( - uid, mSourceAddress, mDestinationAddress, mSpi, 0 /* mark */, + mUid, mSourceAddress, mDestinationAddress, mSpi, 0 /* mark */, 0 /* mask */, 0 /* if_id */); } } catch (ServiceSpecificException | RemoteException e) { @@ -816,8 +821,10 @@ public class IpSecService extends IIpSecService.Stub { private final int mIfId; private Network mUnderlyingNetwork; + private final Context mContext; TunnelInterfaceRecord( + Context context, int resourceId, String interfaceName, Network underlyingNetwork, @@ -828,6 +835,7 @@ public class IpSecService extends IIpSecService.Stub { int intfId) { super(resourceId); + mContext = context; mInterfaceName = interfaceName; mUnderlyingNetwork = underlyingNetwork; mLocalAddress = localAddr; @@ -844,19 +852,19 @@ public class IpSecService extends IIpSecService.Stub { // Teardown VTI // Delete global policies try { - final INetd netd = mSrvConfig.getNetdInstance(); + final INetd netd = mDeps.getNetdInstance(mContext); netd.ipSecRemoveTunnelInterface(mInterfaceName); for (int selAddrFamily : ADDRESS_FAMILIES) { netd.ipSecDeleteSecurityPolicy( - uid, + mUid, selAddrFamily, IpSecManager.DIRECTION_OUT, mOkey, 0xffffffff, mIfId); netd.ipSecDeleteSecurityPolicy( - uid, + mUid, selAddrFamily, IpSecManager.DIRECTION_IN, mIkey, @@ -1012,7 +1020,7 @@ public class IpSecService extends IIpSecService.Stub { * @param context Binder context for this service */ private IpSecService(Context context) { - this(context, IpSecServiceConfiguration.GETSRVINSTANCE); + this(context, new Dependencies()); } static IpSecService create(Context context) @@ -1025,16 +1033,16 @@ public class IpSecService extends IIpSecService.Stub { @NonNull private AppOpsManager getAppOpsManager() { AppOpsManager appOps = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE); - if(appOps == null) throw new RuntimeException("System Server couldn't get AppOps"); + if (appOps == null) throw new RuntimeException("System Server couldn't get AppOps"); return appOps; } /** @hide */ @VisibleForTesting - public IpSecService(Context context, IpSecServiceConfiguration config) { + public IpSecService(Context context, Dependencies deps) { this( context, - config, + deps, (fd, uid) -> { try { TrafficStats.setThreadStatsUid(uid); @@ -1047,13 +1055,13 @@ public class IpSecService extends IIpSecService.Stub { /** @hide */ @VisibleForTesting - public IpSecService(Context context, IpSecServiceConfiguration config, - UidFdTagger uidFdTagger) { + public IpSecService(Context context, Dependencies deps, UidFdTagger uidFdTagger) { mContext = context; - mSrvConfig = config; + mDeps = deps; mUidFdTagger = uidFdTagger; } + /** Called by system server when system is ready. */ public void systemReady() { if (isNetdAlive()) { Log.d(TAG, "IpSecService is ready"); @@ -1076,7 +1084,7 @@ public class IpSecService extends IIpSecService.Stub { synchronized boolean isNetdAlive() { try { - final INetd netd = mSrvConfig.getNetdInstance(); + final INetd netd = mDeps.getNetdInstance(mContext); if (netd == null) { return false; } @@ -1142,14 +1150,15 @@ public class IpSecService extends IIpSecService.Stub { } spi = - mSrvConfig - .getNetdInstance() + mDeps + .getNetdInstance(mContext) .ipSecAllocateSpi(callingUid, "", destinationAddress, requestedSpi); Log.d(TAG, "Allocated SPI " + spi); userRecord.mSpiRecords.put( resourceId, new RefcountedResource<SpiRecord>( - new SpiRecord(resourceId, "", destinationAddress, spi), binder)); + new SpiRecord(mContext, resourceId, "", + destinationAddress, spi), binder)); } catch (ServiceSpecificException e) { if (e.errorCode == OsConstants.ENOENT) { return new IpSecSpiResponse( @@ -1229,7 +1238,7 @@ public class IpSecService extends IIpSecService.Stub { * <p>Since the socket is created on behalf of an unprivileged application, all traffic * should be accounted to the UID of the unprivileged application. */ - public void tag(FileDescriptor fd, int uid) throws IOException; + void tag(FileDescriptor fd, int uid) throws IOException; } /** @@ -1266,7 +1275,7 @@ public class IpSecService extends IIpSecService.Stub { OsConstants.UDP_ENCAP, OsConstants.UDP_ENCAP_ESPINUDP); - mSrvConfig.getNetdInstance().ipSecSetEncapSocketOwner( + mDeps.getNetdInstance(mContext).ipSecSetEncapSocketOwner( new ParcelFileDescriptor(sockFd), callingUid); if (port != 0) { Log.v(TAG, "Binding to port " + port); @@ -1329,7 +1338,7 @@ public class IpSecService extends IIpSecService.Stub { // Create VTI // Add inbound/outbound global policies // (use reqid = 0) - final INetd netd = mSrvConfig.getNetdInstance(); + final INetd netd = mDeps.getNetdInstance(mContext); netd.ipSecAddTunnelInterface(intfName, localAddr, remoteAddr, ikey, okey, resourceId); BinderUtils.withCleanCallingIdentity(() -> { @@ -1384,6 +1393,7 @@ public class IpSecService extends IIpSecService.Stub { resourceId, new RefcountedResource<TunnelInterfaceRecord>( new TunnelInterfaceRecord( + mContext, resourceId, intfName, underlyingNetwork, @@ -1425,8 +1435,8 @@ public class IpSecService extends IIpSecService.Stub { try { // We can assume general validity of the IP address, since we get them as a // LinkAddress, which does some validation. - mSrvConfig - .getNetdInstance() + mDeps + .getNetdInstance(mContext) .interfaceAddAddress( tunnelInterfaceInfo.mInterfaceName, localAddr.getAddress().getHostAddress(), @@ -1454,8 +1464,8 @@ public class IpSecService extends IIpSecService.Stub { try { // We can assume general validity of the IP address, since we get them as a // LinkAddress, which does some validation. - mSrvConfig - .getNetdInstance() + mDeps + .getNetdInstance(mContext) .interfaceDelAddress( tunnelInterfaceInfo.mInterfaceName, localAddr.getAddress().getHostAddress(), @@ -1669,8 +1679,8 @@ public class IpSecService extends IIpSecService.Stub { cryptName = crypt.getName(); } - mSrvConfig - .getNetdInstance() + mDeps + .getNetdInstance(mContext) .ipSecAddSecurityAssociation( Binder.getCallingUid(), c.getMode(), @@ -1771,7 +1781,7 @@ public class IpSecService extends IIpSecService.Stub { TransformRecord info = userRecord.mTransformRecords.getResourceOrThrow(resourceId); // TODO: make this a function. - if (info.pid != getCallingPid() || info.uid != callingUid) { + if (info.mPid != getCallingPid() || info.mUid != callingUid) { throw new SecurityException("Only the owner of an IpSec Transform may apply it!"); } @@ -1781,8 +1791,8 @@ public class IpSecService extends IIpSecService.Stub { c.getMode() == IpSecTransform.MODE_TRANSPORT, "Transform mode was not Transport mode; cannot be applied to a socket"); - mSrvConfig - .getNetdInstance() + mDeps + .getNetdInstance(mContext) .ipSecApplyTransportModeTransform( socket, callingUid, @@ -1801,8 +1811,8 @@ public class IpSecService extends IIpSecService.Stub { @Override public synchronized void removeTransportModeTransforms(ParcelFileDescriptor socket) throws RemoteException { - mSrvConfig - .getNetdInstance() + mDeps + .getNetdInstance(mContext) .ipSecRemoveTransportModeTransform(socket); } @@ -1878,8 +1888,8 @@ public class IpSecService extends IIpSecService.Stub { // Always update the policy with the relevant XFRM_IF_ID for (int selAddrFamily : ADDRESS_FAMILIES) { - mSrvConfig - .getNetdInstance() + mDeps + .getNetdInstance(mContext) .ipSecUpdateSecurityPolicy( callingUid, selAddrFamily, diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java index b429fe6d4939..3debd9a179da 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java @@ -87,7 +87,7 @@ public class CachedBluetoothDeviceManager { } // Check the member devices for the coordinated set if it exists final Set<CachedBluetoothDevice> memberDevices = cachedDevice.getMemberDevice(); - if (memberDevices != null) { + if (!memberDevices.isEmpty()) { for (CachedBluetoothDevice memberDevice : memberDevices) { if (memberDevice.getDevice().equals(device)) { return memberDevice; @@ -141,7 +141,7 @@ public class CachedBluetoothDeviceManager { final Set<CachedBluetoothDevice> memberDevices = device.getMemberDevice(); // TODO: check the CSIP group size instead of the real member device set size, and adjust // the size restriction. - if (memberDevices.size() == 1) { + if (!memberDevices.isEmpty()) { for (CachedBluetoothDevice memberDevice : memberDevices) { if (memberDevice.isConnected()) { return memberDevice.getConnectionSummary(); @@ -166,7 +166,7 @@ public class CachedBluetoothDeviceManager { if (!cachedDevice.getDevice().equals(device)) { // Check the member devices of the coordinated set if it exists Set<CachedBluetoothDevice> memberDevices = cachedDevice.getMemberDevice(); - if (memberDevices != null) { + if (!memberDevices.isEmpty()) { for (CachedBluetoothDevice memberDevice : memberDevices) { if (memberDevice.getDevice().equals(device)) { return true; @@ -230,9 +230,10 @@ public class CachedBluetoothDeviceManager { private void clearNonBondedSubDevices() { for (int i = mCachedDevices.size() - 1; i >= 0; i--) { CachedBluetoothDevice cachedDevice = mCachedDevices.get(i); - final Set<CachedBluetoothDevice> memberDevices = cachedDevice.getMemberDevice(); - if (memberDevices != null) { - for (CachedBluetoothDevice memberDevice : memberDevices) { + Set<CachedBluetoothDevice> memberDevices = cachedDevice.getMemberDevice(); + if (!memberDevices.isEmpty()) { + for (Object it : memberDevices.toArray()) { + CachedBluetoothDevice memberDevice = (CachedBluetoothDevice) it; // Member device exists and it is not bonded if (memberDevice.getDevice().getBondState() == BluetoothDevice.BOND_NONE) { cachedDevice.removeMemberDevice(memberDevice); @@ -257,7 +258,7 @@ public class CachedBluetoothDeviceManager { CachedBluetoothDevice cachedDevice = mCachedDevices.get(i); cachedDevice.setJustDiscovered(false); final Set<CachedBluetoothDevice> memberDevices = cachedDevice.getMemberDevice(); - if (memberDevices != null) { + if (!memberDevices.isEmpty()) { for (CachedBluetoothDevice memberDevice : memberDevices) { memberDevice.setJustDiscovered(false); } @@ -277,7 +278,7 @@ public class CachedBluetoothDeviceManager { for (int i = mCachedDevices.size() - 1; i >= 0; i--) { CachedBluetoothDevice cachedDevice = mCachedDevices.get(i); final Set<CachedBluetoothDevice> memberDevices = cachedDevice.getMemberDevice(); - if (memberDevices != null) { + if (!memberDevices.isEmpty()) { for (CachedBluetoothDevice memberDevice : memberDevices) { if (memberDevice.getBondState() != BluetoothDevice.BOND_BONDED) { cachedDevice.removeMemberDevice(memberDevice); @@ -315,7 +316,7 @@ public class CachedBluetoothDeviceManager { public synchronized void onDeviceUnpaired(CachedBluetoothDevice device) { CachedBluetoothDevice mainDevice = mCsipDeviceManager.findMainDevice(device); final Set<CachedBluetoothDevice> memberDevices = device.getMemberDevice(); - if (memberDevices != null) { + if (!memberDevices.isEmpty()) { // Main device is unpaired, to unpair the member device for (CachedBluetoothDevice memberDevice : memberDevices) { memberDevice.unpair(); diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CsipDeviceManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CsipDeviceManager.java index 1d29966838d3..36d9cf83120a 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CsipDeviceManager.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CsipDeviceManager.java @@ -193,7 +193,7 @@ public class CsipDeviceManager { return true; } final Set<CachedBluetoothDevice> memberSet = cachedDevice.getMemberDevice(); - if (memberSet == null) { + if (memberSet.isEmpty()) { break; } @@ -225,7 +225,7 @@ public class CsipDeviceManager { for (CachedBluetoothDevice cachedDevice : mCachedDevices) { if (isValidGroupId(cachedDevice.getGroupId())) { Set<CachedBluetoothDevice> memberSet = cachedDevice.getMemberDevice(); - if (memberSet == null) { + if (memberSet.isEmpty()) { continue; } diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java index 2c4f57fa77be..d53a3e896868 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java @@ -26,7 +26,9 @@ import static org.mockito.Mockito.when; import android.bluetooth.BluetoothClass; import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothUuid; import android.content.Context; +import android.os.ParcelUuid; import org.junit.Before; import org.junit.Test; @@ -37,6 +39,8 @@ import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; import java.util.Collection; +import java.util.HashMap; +import java.util.Map; @RunWith(RobolectricTestRunner.class) public class CachedBluetoothDeviceManagerTest { @@ -51,6 +55,10 @@ public class CachedBluetoothDeviceManagerTest { private final static String DEVICE_ADDRESS_3 = "AA:BB:CC:DD:EE:33"; private final static long HISYNCID1 = 10; private final static long HISYNCID2 = 11; + private final static Map<Integer, ParcelUuid> CAP_GROUP1 = + Map.of(1, BluetoothUuid.CAP); + private final static Map<Integer, ParcelUuid> CAP_GROUP2 = + Map.of(2, BluetoothUuid.CAP); private final BluetoothClass DEVICE_CLASS_1 = new BluetoothClass(BluetoothClass.Device.AUDIO_VIDEO_HEADPHONES); private final BluetoothClass DEVICE_CLASS_2 = @@ -70,6 +78,8 @@ public class CachedBluetoothDeviceManagerTest { @Mock private HearingAidProfile mHearingAidProfile; @Mock + private CsipSetCoordinatorProfile mCsipSetCoordinatorProfile; + @Mock private BluetoothDevice mDevice1; @Mock private BluetoothDevice mDevice2; @@ -105,8 +115,12 @@ public class CachedBluetoothDeviceManagerTest { when(mA2dpProfile.isProfileReady()).thenReturn(true); when(mPanProfile.isProfileReady()).thenReturn(true); when(mHearingAidProfile.isProfileReady()).thenReturn(true); + when(mCsipSetCoordinatorProfile.isProfileReady()) + .thenReturn(true); doAnswer((invocation) -> mHearingAidProfile). when(mLocalProfileManager).getHearingAidProfile(); + doAnswer((invocation) -> mCsipSetCoordinatorProfile) + .when(mLocalProfileManager).getCsipSetCoordinatorProfile(); mCachedDeviceManager = new CachedBluetoothDeviceManager(mContext, mLocalBluetoothManager); mCachedDevice1 = spy(new CachedBluetoothDevice(mContext, mLocalProfileManager, mDevice1)); mCachedDevice2 = spy(new CachedBluetoothDevice(mContext, mLocalProfileManager, mDevice2)); @@ -298,7 +312,7 @@ public class CachedBluetoothDeviceManagerTest { * Test to verify OnDeviceUnpaired() for main hearing Aid device unpair. */ @Test - public void onDeviceUnpaired_unpairMainDevice() { + public void onDeviceUnpaired_unpairHearingAidMainDevice() { when(mDevice1.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED); CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1); CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mDevice2); @@ -398,4 +412,153 @@ public class CachedBluetoothDeviceManagerTest { when(mDevice1.getBondState()).thenReturn(BluetoothDevice.BOND_NONE); assertThat(mCachedDeviceManager.onDeviceDisappeared(cachedDevice1)).isTrue(); } + + /** + * Test to verify getMemberDevice(), new device has the same group id. + */ + @Test + public void addDevice_sameGroupId_validMemberDevice() { + doAnswer((invocation) -> CAP_GROUP1).when(mCsipSetCoordinatorProfile) + .getGroupUuidMapByDevice(mDevice1); + doAnswer((invocation) -> CAP_GROUP1).when(mCsipSetCoordinatorProfile) + .getGroupUuidMapByDevice(mDevice2); + doAnswer((invocation) -> CAP_GROUP1).when(mCsipSetCoordinatorProfile) + .getGroupUuidMapByDevice(mDevice3); + CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1); + CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mDevice2); + CachedBluetoothDevice cachedDevice3 = mCachedDeviceManager.addDevice(mDevice3); + + assertThat(cachedDevice1.getMemberDevice()).contains(cachedDevice2); + assertThat(cachedDevice1.getMemberDevice()).contains(cachedDevice3); + } + + /** + * Test to verify getMemberDevice(), new device has the different group id. + */ + @Test + public void addDevice_differentGroupId_validMemberDevice() { + doAnswer((invocation) -> CAP_GROUP1).when(mCsipSetCoordinatorProfile) + .getGroupUuidMapByDevice(mDevice1); + doAnswer((invocation) -> CAP_GROUP2).when(mCsipSetCoordinatorProfile) + .getGroupUuidMapByDevice(mDevice2); + CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1); + CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mDevice2); + + assertThat(cachedDevice1.getMemberDevice()).isEmpty(); + } + + /** + * Test to verify addDevice(), new device has the same group id. + */ + @Test + public void addDevice_sameGroupId_validCachedDevices_mainDevicesAdded_memberDevicesNotAdded() { + doAnswer((invocation) -> CAP_GROUP1).when(mCsipSetCoordinatorProfile) + .getGroupUuidMapByDevice(mDevice1); + doAnswer((invocation) -> CAP_GROUP1).when(mCsipSetCoordinatorProfile) + .getGroupUuidMapByDevice(mDevice2); + CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1); + CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mDevice2); + + Collection<CachedBluetoothDevice> devices = mCachedDeviceManager.getCachedDevicesCopy(); + assertThat(devices).contains(cachedDevice1); + assertThat(devices).doesNotContain(cachedDevice2); + } + + /** + * Test to verify addDevice(), new device has the different group id. + */ + @Test + public void addDevice_differentGroupId_validCachedDevices_bothAdded() { + doAnswer((invocation) -> CAP_GROUP1).when(mCsipSetCoordinatorProfile) + .getGroupUuidMapByDevice(mDevice1); + doAnswer((invocation) -> CAP_GROUP2).when(mCsipSetCoordinatorProfile) + .getGroupUuidMapByDevice(mDevice2); + CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1); + CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mDevice2); + + Collection<CachedBluetoothDevice> devices = mCachedDeviceManager.getCachedDevicesCopy(); + assertThat(devices).contains(cachedDevice1); + assertThat(devices).contains(cachedDevice2); + } + + /** + * Test to verify clearNonBondedDevices() for csip set member device. + */ + @Test + public void clearNonBondedDevices_nonBondedMemberDevice() { + when(mDevice1.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED); + when(mDevice2.getBondState()).thenReturn(BluetoothDevice.BOND_NONE); + when(mDevice3.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED); + CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1); + CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mDevice2); + CachedBluetoothDevice cachedDevice3 = mCachedDeviceManager.addDevice(mDevice3); + cachedDevice1.setMemberDevice(cachedDevice2); + cachedDevice1.setMemberDevice(cachedDevice3); + + assertThat(cachedDevice1.getMemberDevice()).contains(cachedDevice2); + assertThat(cachedDevice1.getMemberDevice()).contains(cachedDevice3); + mCachedDeviceManager.clearNonBondedDevices(); + + assertThat(cachedDevice1.getMemberDevice().contains(cachedDevice2)).isFalse(); + assertThat(cachedDevice1.getMemberDevice().contains(cachedDevice3)).isTrue(); + } + + /** + * Test to verify OnDeviceUnpaired() for csip device unpair. + */ + @Test + public void onDeviceUnpaired_unpairCsipMainDevice() { + when(mDevice1.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED); + CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1); + CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mDevice2); + cachedDevice1.setGroupId(1); + cachedDevice2.setGroupId(1); + cachedDevice1.setMemberDevice(cachedDevice2); + + // Call onDeviceUnpaired for the one in mCachedDevices. + mCachedDeviceManager.onDeviceUnpaired(cachedDevice1); + verify(mDevice2).removeBond(); + } + + /** + * Test to verify OnDeviceUnpaired() for csip device unpair. + */ + @Test + public void onDeviceUnpaired_unpairCsipSubDevice() { + when(mDevice1.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED); + CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1); + CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mDevice2); + cachedDevice1.setGroupId(1); + cachedDevice2.setGroupId(1); + cachedDevice1.setMemberDevice(cachedDevice2); + + // Call onDeviceUnpaired for the one in mCachedDevices. + mCachedDeviceManager.onDeviceUnpaired(cachedDevice2); + verify(mDevice1).removeBond(); + } + + /** + * Test to verify isSubDevice_validSubDevice(). + */ + @Test + public void isSubDevice_validMemberDevice() { + doReturn(CAP_GROUP1).when(mCsipSetCoordinatorProfile).getGroupUuidMapByDevice(mDevice1); + mCachedDeviceManager.addDevice(mDevice1); + + // Both device are not sub device in default value. + assertThat(mCachedDeviceManager.isSubDevice(mDevice1)).isFalse(); + assertThat(mCachedDeviceManager.isSubDevice(mDevice2)).isFalse(); + + // Add Device-2 as device with Device-1 with the same group id, and add Device-3 with + // the different group id. + doReturn(CAP_GROUP1).when(mCsipSetCoordinatorProfile).getGroupUuidMapByDevice(mDevice2); + doReturn(CAP_GROUP2).when(mCsipSetCoordinatorProfile).getGroupUuidMapByDevice(mDevice3); + mCachedDeviceManager.addDevice(mDevice2); + mCachedDeviceManager.addDevice(mDevice3); + + // Verify Device-2 is sub device, but Device-1, and Device-3 is not. + assertThat(mCachedDeviceManager.isSubDevice(mDevice1)).isFalse(); + assertThat(mCachedDeviceManager.isSubDevice(mDevice2)).isTrue(); + assertThat(mCachedDeviceManager.isSubDevice(mDevice3)).isFalse(); + } } diff --git a/packages/SystemUI/src/com/android/systemui/log/LogBuffer.kt b/packages/SystemUI/src/com/android/systemui/log/LogBuffer.kt index c1db8edf4119..90064172dd36 100644 --- a/packages/SystemUI/src/com/android/systemui/log/LogBuffer.kt +++ b/packages/SystemUI/src/com/android/systemui/log/LogBuffer.kt @@ -16,6 +16,7 @@ package com.android.systemui.log +import android.os.Trace import android.util.Log import com.android.systemui.log.dagger.LogModule import java.io.PrintWriter @@ -169,7 +170,7 @@ class LogBuffer( buffer.add(message as LogMessageImpl) if (logcatEchoTracker.isBufferLoggable(name, message.level) || logcatEchoTracker.isTagLoggable(message.tag, message.level)) { - echoToLogcat(message) + echo(message) } } @@ -219,7 +220,7 @@ class LogBuffer( pw.println(message.printer(message)) } - private fun echoToLogcat(message: LogMessage) { + private fun echo(message: LogMessage) { val strMessage = message.printer(message) when (message.level) { LogLevel.VERBOSE -> Log.v(message.tag, strMessage) @@ -229,6 +230,7 @@ class LogBuffer( LogLevel.ERROR -> Log.e(message.tag, strMessage) LogLevel.WTF -> Log.wtf(message.tag, strMessage) } + Trace.instantForTrack(Trace.TRACE_TAG_APP, "UI Events", strMessage) } } diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java index 4775127389d3..91cd2f6ad676 100644 --- a/services/core/java/com/android/server/TelephonyRegistry.java +++ b/services/core/java/com/android/server/TelephonyRegistry.java @@ -152,6 +152,8 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { int callerUid; int callerPid; + boolean renounceFineLocationAccess; + boolean renounceCoarseLocationAccess; Set<Integer> eventList; @@ -995,14 +997,25 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { } @Override - public void listenWithEventList(int subId, String callingPackage, String callingFeatureId, - IPhoneStateListener callback, int[] events, boolean notifyNow) { + public void listenWithEventList(boolean renounceFineLocationAccess, + boolean renounceCoarseLocationAccess, int subId, String callingPackage, + String callingFeatureId, IPhoneStateListener callback, + int[] events, boolean notifyNow) { Set<Integer> eventList = Arrays.stream(events).boxed().collect(Collectors.toSet()); - listen(callingPackage, callingFeatureId, callback, eventList, notifyNow, subId); + listen(renounceFineLocationAccess, renounceFineLocationAccess, callingPackage, + callingFeatureId, callback, eventList, notifyNow, subId); } private void listen(String callingPackage, @Nullable String callingFeatureId, IPhoneStateListener callback, Set<Integer> events, boolean notifyNow, int subId) { + listen(false, false, callingPackage, + callingFeatureId, callback, events, notifyNow, subId); + } + + private void listen(boolean renounceFineLocationAccess, + boolean renounceCoarseLocationAccess, String callingPackage, + @Nullable String callingFeatureId, IPhoneStateListener callback, + Set<Integer> events, boolean notifyNow, int subId) { int callerUserId = UserHandle.getCallingUserId(); mAppOps.checkPackage(Binder.getCallingUid(), callingPackage); String str = "listen: E pkg=" + pii(callingPackage) + " uid=" + Binder.getCallingUid() @@ -1047,6 +1060,8 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { r.callback = callback; r.callingPackage = callingPackage; r.callingFeatureId = callingFeatureId; + r.renounceCoarseLocationAccess = renounceCoarseLocationAccess; + r.renounceFineLocationAccess = renounceFineLocationAccess; r.callerUid = Binder.getCallingUid(); r.callerPid = Binder.getCallingPid(); // Legacy applications pass SubscriptionManager.DEFAULT_SUB_ID, @@ -3199,6 +3214,9 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { * If you don't need app compat logic, use {@link #checkFineLocationAccess(Record)}. */ private boolean checkFineLocationAccess(Record r, int minSdk) { + if (r.renounceFineLocationAccess) { + return false; + } LocationAccessPolicy.LocationPermissionQuery query = new LocationAccessPolicy.LocationPermissionQuery.Builder() .setCallingPackage(r.callingPackage) @@ -3225,6 +3243,9 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { * If you don't need app compat logic, use {@link #checkCoarseLocationAccess(Record)}. */ private boolean checkCoarseLocationAccess(Record r, int minSdk) { + if (r.renounceCoarseLocationAccess) { + return false; + } LocationAccessPolicy.LocationPermissionQuery query = new LocationAccessPolicy.LocationPermissionQuery.Builder() .setCallingPackage(r.callingPackage) diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index c9112578705e..dd5ba6e55bae 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -91,6 +91,7 @@ import static android.provider.Settings.Global.DEBUG_APP; import static android.provider.Settings.Global.NETWORK_ACCESS_TIMEOUT_MS; import static android.provider.Settings.Global.WAIT_FOR_DEBUGGER; import static android.text.format.DateUtils.DAY_IN_MILLIS; +import static android.util.FeatureFlagUtils.SETTINGS_ENABLE_MONITOR_PHANTOM_PROCS; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_CONFIGURATION; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ALL; @@ -300,6 +301,7 @@ import android.text.style.SuggestionSpan; import android.util.ArrayMap; import android.util.ArraySet; import android.util.EventLog; +import android.util.FeatureFlagUtils; import android.util.IntArray; import android.util.Log; import android.util.Pair; @@ -14257,6 +14259,8 @@ public class ActivityManagerService extends IActivityManager.Stub private void checkExcessivePowerUsage() { updateCpuStatsNow(); + final boolean monitorPhantomProcs = mSystemReady && FeatureFlagUtils.isEnabled(mContext, + SETTINGS_ENABLE_MONITOR_PHANTOM_PROCS); synchronized (mProcLock) { final boolean doCpuKills = mLastPowerCheckUptime != 0; final long curUptime = SystemClock.uptimeMillis(); @@ -14282,9 +14286,11 @@ public class ActivityManagerService extends IActivityManager.Stub updateAppProcessCpuTimeLPr(uptimeSince, doCpuKills, checkDur, cpuLimit, app); - // Also check the phantom processes if there is any - updatePhantomProcessCpuTimeLPr( - uptimeSince, doCpuKills, checkDur, cpuLimit, app); + if (monitorPhantomProcs) { + // Also check the phantom processes if there is any + updatePhantomProcessCpuTimeLPr( + uptimeSince, doCpuKills, checkDur, cpuLimit, app); + } } }); } diff --git a/services/core/java/com/android/server/am/AppProfiler.java b/services/core/java/com/android/server/am/AppProfiler.java index 36c0de919279..1496b30338f8 100644 --- a/services/core/java/com/android/server/am/AppProfiler.java +++ b/services/core/java/com/android/server/am/AppProfiler.java @@ -19,6 +19,7 @@ package com.android.server.am; import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT; import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_CRITICAL; import static android.os.Process.FIRST_APPLICATION_UID; +import static android.util.FeatureFlagUtils.SETTINGS_ENABLE_MONITOR_PHANTOM_PROCS; import static com.android.internal.app.procstats.ProcessStats.ADJ_MEM_FACTOR_CRITICAL; import static com.android.internal.app.procstats.ProcessStats.ADJ_MEM_FACTOR_LOW; @@ -77,6 +78,7 @@ import android.provider.DeviceConfig.Properties; import android.text.TextUtils; import android.util.ArrayMap; import android.util.DebugUtils; +import android.util.FeatureFlagUtils; import android.util.Pair; import android.util.Slog; import android.util.SparseArray; @@ -1792,6 +1794,8 @@ public class AppProfiler { } void updateCpuStatsNow() { + final boolean monitorPhantomProcs = mService.mSystemReady && FeatureFlagUtils.isEnabled( + mService.mContext, SETTINGS_ENABLE_MONITOR_PHANTOM_PROCS); synchronized (mProcessCpuTracker) { mProcessCpuMutexFree.set(false); final long now = SystemClock.uptimeMillis(); @@ -1830,7 +1834,7 @@ public class AppProfiler { } } - if (haveNewCpuStats) { + if (monitorPhantomProcs && haveNewCpuStats) { mService.mPhantomProcessList.updateProcessCpuStatesLocked(mProcessCpuTracker); } diff --git a/services/core/java/com/android/server/am/PhantomProcessList.java b/services/core/java/com/android/server/am/PhantomProcessList.java index b07684c9a004..2ec1aedd18f9 100644 --- a/services/core/java/com/android/server/am/PhantomProcessList.java +++ b/services/core/java/com/android/server/am/PhantomProcessList.java @@ -18,6 +18,7 @@ package com.android.server.am; import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_ERROR; import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_INPUT; +import static android.util.FeatureFlagUtils.SETTINGS_ENABLE_MONITOR_PHANTOM_PROCS; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PROCESSES; import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; @@ -28,6 +29,7 @@ import android.app.ApplicationExitInfo.SubReason; import android.os.Handler; import android.os.Process; import android.os.StrictMode; +import android.util.FeatureFlagUtils; import android.util.Slog; import android.util.SparseArray; @@ -419,6 +421,10 @@ public final class PhantomProcessList { * order of the oom adjs of their parent process. */ void trimPhantomProcessesIfNecessary() { + if (!mService.mSystemReady || !FeatureFlagUtils.isEnabled(mService.mContext, + SETTINGS_ENABLE_MONITOR_PHANTOM_PROCS)) { + return; + } synchronized (mService.mProcLock) { synchronized (mLock) { mTrimPhantomProcessScheduled = false; diff --git a/services/core/java/com/android/server/wm/RefreshRatePolicy.java b/services/core/java/com/android/server/wm/RefreshRatePolicy.java index b63843dd20d4..7bddb620c94d 100644 --- a/services/core/java/com/android/server/wm/RefreshRatePolicy.java +++ b/services/core/java/com/android/server/wm/RefreshRatePolicy.java @@ -164,7 +164,19 @@ class RefreshRatePolicy { return 0; } - return w.mAttrs.preferredMinDisplayRefreshRate; + if (w.mAttrs.preferredMinDisplayRefreshRate > 0) { + return w.mAttrs.preferredMinDisplayRefreshRate; + } + + String packageName = w.getOwningPackage(); + // If app is using Camera, we set both the min and max refresh rate to the camera's + // preferred refresh rate to make sure we don't end up with a refresh rate lower + // than the camera capture rate, which will lead to dropping camera frames. + if (mNonHighRefreshRatePackages.contains(packageName)) { + return mLowRefreshRateMode.getRefreshRate(); + } + + return 0; } float getPreferredMaxRefreshRate(WindowState w) { diff --git a/services/tests/wmtests/src/com/android/server/wm/RefreshRatePolicyTest.java b/services/tests/wmtests/src/com/android/server/wm/RefreshRatePolicyTest.java index c4cccf022322..19247604ad10 100644 --- a/services/tests/wmtests/src/com/android/server/wm/RefreshRatePolicyTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/RefreshRatePolicyTest.java @@ -104,7 +104,8 @@ public class RefreshRatePolicyTest extends WindowTestsBase { mPolicy.addNonHighRefreshRatePackage("com.android.test"); assertEquals(0, mPolicy.getPreferredModeId(cameraUsingWindow)); assertEquals(0, mPolicy.getPreferredRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE); - assertEquals(0, mPolicy.getPreferredMinRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE); + assertEquals(LOW_REFRESH_RATE, + mPolicy.getPreferredMinRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE); assertEquals(LOW_REFRESH_RATE, mPolicy.getPreferredMaxRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE); mPolicy.removeNonHighRefreshRatePackage("com.android.test"); @@ -165,7 +166,8 @@ public class RefreshRatePolicyTest extends WindowTestsBase { assertEquals(HI_MODE_ID, mPolicy.getPreferredModeId(overrideWindow)); assertEquals(HI_REFRESH_RATE, mPolicy.getPreferredRefreshRate(overrideWindow), FLOAT_TOLERANCE); - assertEquals(0, mPolicy.getPreferredMinRefreshRate(overrideWindow), FLOAT_TOLERANCE); + assertEquals(LOW_REFRESH_RATE, + mPolicy.getPreferredMinRefreshRate(overrideWindow), FLOAT_TOLERANCE); assertEquals(LOW_REFRESH_RATE, mPolicy.getPreferredMaxRefreshRate(overrideWindow), FLOAT_TOLERANCE); } @@ -180,7 +182,8 @@ public class RefreshRatePolicyTest extends WindowTestsBase { assertEquals(0, mPolicy.getPreferredModeId(overrideWindow)); assertEquals(HI_REFRESH_RATE, mPolicy.getPreferredRefreshRate(overrideWindow), FLOAT_TOLERANCE); - assertEquals(0, mPolicy.getPreferredMinRefreshRate(overrideWindow), FLOAT_TOLERANCE); + assertEquals(LOW_REFRESH_RATE, + mPolicy.getPreferredMinRefreshRate(overrideWindow), FLOAT_TOLERANCE); assertEquals(LOW_REFRESH_RATE, mPolicy.getPreferredMaxRefreshRate(overrideWindow), FLOAT_TOLERANCE); } @@ -257,7 +260,8 @@ public class RefreshRatePolicyTest extends WindowTestsBase { mPolicy.addNonHighRefreshRatePackage("com.android.test"); assertEquals(0, mPolicy.getPreferredModeId(cameraUsingWindow)); assertEquals(0, mPolicy.getPreferredRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE); - assertEquals(0, mPolicy.getPreferredMinRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE); + assertEquals(LOW_REFRESH_RATE, + mPolicy.getPreferredMinRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE); assertEquals(LOW_REFRESH_RATE, mPolicy.getPreferredMaxRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE); diff --git a/telephony/java/android/telephony/SignalStrengthUpdateRequest.java b/telephony/java/android/telephony/SignalStrengthUpdateRequest.java index 9cb80f1814f9..4884d549e2e0 100644 --- a/telephony/java/android/telephony/SignalStrengthUpdateRequest.java +++ b/telephony/java/android/telephony/SignalStrengthUpdateRequest.java @@ -19,6 +19,7 @@ package android.telephony; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; +import android.annotation.SystemApi; import android.os.Binder; import android.os.IBinder; import android.os.Parcel; @@ -130,7 +131,10 @@ public final class SignalStrengthUpdateRequest implements Parcelable { /** * Set the builder object if require reporting on the system thresholds when device is idle. * - * <p>This can only used by the system caller. Requires permission + * <p>This is intended to be used by the system privileged caller only. When setting to + * {@code true}, signal strength update request through + * {@link TelephonyManager#setSignalStrengthUpdateRequest(SignalStrengthUpdateRequest)} + * will require permission * {@link android.Manifest.permission#LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH}. * * @param isSystemThresholdReportingRequestedWhileIdle true if request reporting on the @@ -138,6 +142,7 @@ public final class SignalStrengthUpdateRequest implements Parcelable { * @return the builder to facilitate the chaining * @hide */ + @SystemApi @RequiresPermission(android.Manifest.permission.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH) public @NonNull Builder setSystemThresholdReportingRequestedWhileIdle( boolean isSystemThresholdReportingRequestedWhileIdle) { @@ -191,6 +196,7 @@ public final class SignalStrengthUpdateRequest implements Parcelable { * * @hide */ + @SystemApi public boolean isSystemThresholdReportingRequestedWhileIdle() { return mIsSystemThresholdReportingRequestedWhileIdle; } diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index 1029214b0222..6286390ba139 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -8321,12 +8321,58 @@ public class TelephonyManager { public NetworkScan requestNetworkScan( NetworkScanRequest request, Executor executor, TelephonyScanManager.NetworkScanCallback callback) { - synchronized (this) { + return requestNetworkScan(false, request, executor, callback); + } + + /** + * Request a network scan. + * + * This method is asynchronous, so the network scan results will be returned by callback. + * The returned NetworkScan will contain a callback method which can be used to stop the scan. + * + * <p>Requires Permission: + * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling + * app has carrier privileges (see {@link #hasCarrierPrivileges}) + * and {@link android.Manifest.permission#ACCESS_FINE_LOCATION}. + * + * If the system-wide location switch is off, apps may still call this API, with the + * following constraints: + * <ol> + * <li>The app must hold the {@code android.permission.NETWORK_SCAN} permission.</li> + * <li>The app must not supply any specific bands or channels to scan.</li> + * <li>The app must only specify MCC/MNC pairs that are + * associated to a SIM in the device.</li> + * <li>Returned results will have no meaningful info other than signal strength + * and MCC/MNC info.</li> + * </ol> + * + * @param renounceFineLocationAccess Set this to true if the caller would not like to receive + * location related information which will be sent if the caller already possess + * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} and do not renounce the permission + * @param request Contains all the RAT with bands/channels that need to be scanned. + * @param executor The executor through which the callback should be invoked. Since the scan + * request may trigger multiple callbacks and they must be invoked in the same order as + * they are received by the platform, the user should provide an executor which executes + * tasks one at a time in serial order. For example AsyncTask.SERIAL_EXECUTOR. + * @param callback Returns network scan results or errors. + * @return A NetworkScan obj which contains a callback which can be used to stop the scan. + */ + @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges + @RequiresPermission(allOf = { + android.Manifest.permission.MODIFY_PHONE_STATE, + Manifest.permission.ACCESS_FINE_LOCATION + }) + public @Nullable NetworkScan requestNetworkScan( + boolean renounceFineLocationAccess, @NonNull NetworkScanRequest request, + @NonNull Executor executor, + @NonNull TelephonyScanManager.NetworkScanCallback callback) { + synchronized (sCacheLock) { if (mTelephonyScanManager == null) { mTelephonyScanManager = new TelephonyScanManager(); } } - return mTelephonyScanManager.requestNetworkScan(getSubId(), request, executor, callback, + return mTelephonyScanManager.requestNetworkScan(getSubId(), renounceFineLocationAccess, + request, executor, callback, getOpPackageName(), getAttributionTag()); } @@ -11387,7 +11433,6 @@ public class TelephonyManager { * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}) * and {@link android.Manifest.permission#ACCESS_COARSE_LOCATION}. - * * May return {@code null} when the subscription is inactive or when there was an error * communicating with the phone process. */ @@ -11397,7 +11442,39 @@ public class TelephonyManager { Manifest.permission.ACCESS_COARSE_LOCATION }) public @Nullable ServiceState getServiceState() { - return getServiceStateForSubscriber(getSubId()); + return getServiceState(false, false); + } + + /** + * Returns the current {@link ServiceState} information. + * + * <p>If this object has been created with {@link #createForSubscriptionId}, applies to the + * given subId. Otherwise, applies to {@link SubscriptionManager#getDefaultSubscriptionId()} + * + * If you want continuous updates of service state info, register a {@link PhoneStateListener} + * via {@link #listen} with the {@link PhoneStateListener#LISTEN_SERVICE_STATE} event. + * + * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} + * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}) + * and {@link android.Manifest.permission#ACCESS_COARSE_LOCATION}. + * @param renounceFineLocationAccess Set this to true if the caller would not like to receive + * location related information which will be sent if the caller already possess + * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} and do not renounce the permission + * @param renounceCoarseLocationAccess Set this to true if the caller would not like to + * receive location related information which will be sent if the caller already possess + * {@link Manifest.permission#ACCESS_COARSE_LOCATION} and do not renounce the permissions. + * May return {@code null} when the subscription is inactive or when there was an error + * communicating with the phone process. + */ + @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges + @RequiresPermission(allOf = { + Manifest.permission.READ_PHONE_STATE, + Manifest.permission.ACCESS_COARSE_LOCATION + }) + public @Nullable ServiceState getServiceState(boolean renounceFineLocationAccess, + boolean renounceCoarseLocationAccess) { + return getServiceStateForSubscriber(getSubId(), renounceFineLocationAccess, + renounceCoarseLocationAccess); } /** @@ -11406,15 +11483,22 @@ public class TelephonyManager { * * May return {@code null} when the subscription is inactive or when there was an error * communicating with the phone process. - * @hide + * @param renounceFineLocationAccess Set this to true if the caller would not like to receive + * location related information which will be sent if the caller already possess + * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} and do not renounce the permission + * @param renounceCoarseLocationAccess Set this to true if the caller would not like to + * receive location related information which will be sent if the caller already possess + * {@link Manifest.permission#ACCESS_COARSE_LOCATION} and do not renounce the permissions. */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) - public ServiceState getServiceStateForSubscriber(int subId) { + private ServiceState getServiceStateForSubscriber(int subId, + boolean renounceFineLocationAccess, + boolean renounceCoarseLocationAccess) { try { ITelephony service = getITelephony(); if (service != null) { - return service.getServiceStateForSubscriber(subId, getOpPackageName(), - getAttributionTag()); + return service.getServiceStateForSubscriber(subId, renounceFineLocationAccess, + renounceCoarseLocationAccess, + getOpPackageName(), getAttributionTag()); } } catch (RemoteException e) { Log.e(TAG, "Error calling ITelephony#getServiceStateForSubscriber", e); @@ -11427,6 +11511,19 @@ public class TelephonyManager { } /** + * Returns the service state information on specified subscription. Callers require + * either READ_PRIVILEGED_PHONE_STATE or READ_PHONE_STATE to retrieve the information. + * + * May return {@code null} when the subscription is inactive or when there was an error + * communicating with the phone process. + * @hide + */ + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) + public ServiceState getServiceStateForSubscriber(int subId) { + return getServiceStateForSubscriber(getSubId(), false, false); + } + + /** * Returns the URI for the per-account voicemail ringtone set in Phone settings. * * @param accountHandle The handle for the {@link PhoneAccount} for which to retrieve the @@ -15274,7 +15371,49 @@ public class TelephonyManager { */ public void registerTelephonyCallback(@NonNull @CallbackExecutor Executor executor, @NonNull TelephonyCallback callback) { + registerTelephonyCallback(false, false, executor, callback); + } + /** + * Registers a callback object to receive notification of changes in specified telephony states. + * <p> + * To register a callback, pass a {@link TelephonyCallback} which implements + * interfaces of events. For example, + * FakeServiceStateCallback extends {@link TelephonyCallback} implements + * {@link TelephonyCallback.ServiceStateListener}. + * + * At registration, and when a specified telephony state changes, the telephony manager invokes + * the appropriate callback method on the callback object and passes the current (updated) + * values. + * <p> + * + * If this TelephonyManager object has been created with {@link #createForSubscriptionId}, + * applies to the given subId. Otherwise, applies to + * {@link SubscriptionManager#getDefaultSubscriptionId()}. To register events for multiple + * subIds, pass a separate callback object to each TelephonyManager object created with + * {@link #createForSubscriptionId}. + * + * Note: if you call this method while in the middle of a binder transaction, you <b>must</b> + * call {@link android.os.Binder#clearCallingIdentity()} before calling this method. A + * {@link SecurityException} will be thrown otherwise. + * + * This API should be used sparingly -- large numbers of callbacks will cause system + * instability. If a process has registered too many callbacks without unregistering them, it + * may encounter an {@link IllegalStateException} when trying to register more callbacks. + * + * @param renounceFineLocationAccess Set this to true if the caller would not like to receive + * location related information which will be sent if the caller already possess + * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} and do not renounce the permissions. + * @param renounceCoarseLocationAccess Set this to true if the caller would not like to + * receive location related information which will be sent if the caller already possess + * {@link Manifest.permission#ACCESS_COARSE_LOCATION} and do not renounce the permissions. + * @param executor The executor of where the callback will execute. + * @param callback The {@link TelephonyCallback} object to register. + */ + public void registerTelephonyCallback(boolean renounceFineLocationAccess, + boolean renounceCoarseLocationAccess, + @NonNull @CallbackExecutor Executor executor, + @NonNull TelephonyCallback callback) { if (mContext == null) { throw new IllegalStateException("telephony service is null."); } @@ -15285,7 +15424,8 @@ public class TelephonyManager { mTelephonyRegistryMgr = (TelephonyRegistryManager) mContext.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE); if (mTelephonyRegistryMgr != null) { - mTelephonyRegistryMgr.registerTelephonyCallback(executor, mSubId, getOpPackageName(), + mTelephonyRegistryMgr.registerTelephonyCallback(renounceFineLocationAccess, + renounceCoarseLocationAccess, executor, mSubId, getOpPackageName(), getAttributionTag(), callback, getITelephony() != null); } else { throw new IllegalStateException("telephony service is null."); diff --git a/telephony/java/android/telephony/TelephonyScanManager.java b/telephony/java/android/telephony/TelephonyScanManager.java index 9572154ec773..122662d3d7c8 100644 --- a/telephony/java/android/telephony/TelephonyScanManager.java +++ b/telephony/java/android/telephony/TelephonyScanManager.java @@ -228,7 +228,9 @@ public final class TelephonyScanManager { * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} and * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} * Or the calling app has carrier privileges. @see #hasCarrierPrivileges - * + * @param renounceFineLocationAccess Set this to true if the caller would not like to receive + * location related information which will be sent if the caller already possess + * {@link android.Manifest.permission.ACCESS_FINE_LOCATION} and do not renounce the permission * @param request Contains all the RAT with bands/channels that need to be scanned. * @param callback Returns network scan results or errors. * @param callingPackage The package name of the caller @@ -237,6 +239,7 @@ public final class TelephonyScanManager { * @hide */ public NetworkScan requestNetworkScan(int subId, + boolean renounceFineLocationAccess, NetworkScanRequest request, Executor executor, NetworkScanCallback callback, String callingPackage, @Nullable String callingFeatureId) { try { @@ -252,7 +255,8 @@ public final class TelephonyScanManager { // the record to the ScanInfo cache. synchronized (mScanInfo) { int scanId = telephony.requestNetworkScan( - subId, request, mMessenger, new Binder(), callingPackage, + subId, renounceFineLocationAccess, request, mMessenger, + new Binder(), callingPackage, callingFeatureId); if (scanId == INVALID_SCAN_ID) { Rlog.e(TAG, "Failed to initiate network scan"); diff --git a/telephony/java/android/telephony/ims/RcsClientConfiguration.java b/telephony/java/android/telephony/ims/RcsClientConfiguration.java index 793c37745de6..c25ace0c6a62 100644 --- a/telephony/java/android/telephony/ims/RcsClientConfiguration.java +++ b/telephony/java/android/telephony/ims/RcsClientConfiguration.java @@ -50,6 +50,7 @@ public final class RcsClientConfiguration implements Parcelable { private String mRcsProfile; private String mClientVendor; private String mClientVersion; + private boolean mRcsEnabledByUser; /** * Create a RcsClientConfiguration object. @@ -63,14 +64,41 @@ public final class RcsClientConfiguration implements Parcelable { * @param clientVersion Identifies the RCS client version. Refer to GSMA * RCC.07 "client_version" parameter. * Example:client_version=RCSAndrd-1.0 + * @deprecated Use {@link #RcsClientConfiguration(String, String, String, String, boolean)} + * instead. Deprecated prototype assumes that the user setting controlling RCS is enabled. */ + @Deprecated public RcsClientConfiguration(@NonNull String rcsVersion, @NonNull @StringRcsProfile String rcsProfile, @NonNull String clientVendor, @NonNull String clientVersion) { + this(rcsVersion, rcsProfile, clientVendor, clientVersion, true); + } + + /** + * Create a RcsClientConfiguration object. + * Default messaging application must pass a valid configuration object + * @param rcsVersion The parameter identifies the RCS version supported + * by the client. Refer to GSMA RCC.07 "rcs_version" parameter. + * @param rcsProfile Identifies a fixed set of RCS services that are + * supported by the client. See {@link #RCS_PROFILE_1_0 } or + * {@link #RCS_PROFILE_2_3 } + * @param clientVendor Identifies the vendor providing the RCS client. + * @param clientVersion Identifies the RCS client version. Refer to GSMA + * RCC.07 "client_version" parameter. + * Example:client_version=RCSAndrd-1.0 + * @param isRcsEnabledByUser The current user setting for whether or not the user has + * enabled or disabled RCS. Please refer to GSMA RCC.07 "rcs_state" parameter for how this + * can affect provisioning. + */ + public RcsClientConfiguration(@NonNull String rcsVersion, + @NonNull @StringRcsProfile String rcsProfile, + @NonNull String clientVendor, @NonNull String clientVersion, + boolean isRcsEnabledByUser) { mRcsVersion = rcsVersion; mRcsProfile = rcsProfile; mClientVendor = clientVendor; mClientVersion = clientVersion; + mRcsEnabledByUser = isRcsEnabledByUser; } /** @@ -102,6 +130,18 @@ public final class RcsClientConfiguration implements Parcelable { } /** + * The current user setting provided by the RCS messaging application that determines + * whether or not the user has enabled RCS. + * <p> + * See GSMA RCC.07 "rcs_state" parameter for more information about how this setting + * affects provisioning. + * @return true if RCS is enabled by the user, false if RCS is disabled by the user. + */ + public boolean isRcsEnabledByUser() { + return mRcsEnabledByUser; + } + + /** * {@link Parcelable#writeToParcel} */ @Override @@ -110,6 +150,7 @@ public final class RcsClientConfiguration implements Parcelable { out.writeString(mRcsProfile); out.writeString(mClientVendor); out.writeString(mClientVersion); + out.writeBoolean(mRcsEnabledByUser); } /** @@ -124,8 +165,9 @@ public final class RcsClientConfiguration implements Parcelable { String rcsProfile = in.readString(); String clientVendor = in.readString(); String clientVersion = in.readString(); + Boolean rcsEnabledByUser = in.readBoolean(); return new RcsClientConfiguration(rcsVersion, rcsProfile, - clientVendor, clientVersion); + clientVendor, clientVersion, rcsEnabledByUser); } @Override @@ -152,11 +194,13 @@ public final class RcsClientConfiguration implements Parcelable { return mRcsVersion.equals(other.mRcsVersion) && mRcsProfile.equals(other.mRcsProfile) && mClientVendor.equals(other.mClientVendor) - && mClientVersion.equals(other.mClientVersion); + && mClientVersion.equals(other.mClientVersion) + && (mRcsEnabledByUser == other.mRcsEnabledByUser); } @Override public int hashCode() { - return Objects.hash(mRcsVersion, mRcsProfile, mClientVendor, mClientVersion); + return Objects.hash(mRcsVersion, mRcsProfile, mClientVendor, mClientVersion, + mRcsEnabledByUser); } } diff --git a/telephony/java/android/telephony/ims/RcsUceAdapter.java b/telephony/java/android/telephony/ims/RcsUceAdapter.java index 7a1c09275a6d..61de3ac2b25e 100644 --- a/telephony/java/android/telephony/ims/RcsUceAdapter.java +++ b/telephony/java/android/telephony/ims/RcsUceAdapter.java @@ -28,13 +28,10 @@ import android.os.Binder; import android.os.IBinder; import android.os.RemoteException; import android.os.ServiceSpecificException; -import android.telephony.CarrierConfigManager; -import android.telephony.SubscriptionManager; import android.telephony.TelephonyFrameworkInitializer; import android.telephony.ims.aidl.IImsRcsController; import android.telephony.ims.aidl.IRcsUceControllerCallback; import android.telephony.ims.aidl.IRcsUcePublishStateCallback; -import android.telephony.ims.feature.RcsFeature; import android.util.Log; import java.lang.annotation.Retention; @@ -337,6 +334,14 @@ public class RcsUceAdapter { @SystemApi public static final int PUBLISH_STATE_OTHER_ERROR = 6; + /** + * The device is currently trying to publish its capabilities to the network. + * @hide + */ + @SystemApi + public static final int PUBLISH_STATE_PUBLISHING = 7; + + /**@hide*/ @Retention(RetentionPolicy.SOURCE) @IntDef(prefix = "PUBLISH_STATE_", value = { @@ -345,7 +350,8 @@ public class RcsUceAdapter { PUBLISH_STATE_VOICE_PROVISION_ERROR, PUBLISH_STATE_RCS_PROVISION_ERROR, PUBLISH_STATE_REQUEST_TIMEOUT, - PUBLISH_STATE_OTHER_ERROR + PUBLISH_STATE_OTHER_ERROR, + PUBLISH_STATE_PUBLISHING }) public @interface PublishState {} @@ -480,9 +486,12 @@ public class RcsUceAdapter { * <p> * Be sure to check the availability of this feature using * {@link ImsRcsManager#isAvailable(int, int)} and ensuring - * {@link RcsFeature.RcsImsCapabilities#CAPABILITY_TYPE_OPTIONS_UCE} or - * {@link RcsFeature.RcsImsCapabilities#CAPABILITY_TYPE_PRESENCE_UCE} is enabled or else - * this operation will fail with {@link #ERROR_NOT_AVAILABLE} or {@link #ERROR_NOT_ENABLED}. + * {@link + * android.telephony.ims.feature.RcsFeature.RcsImsCapabilities#CAPABILITY_TYPE_OPTIONS_UCE} or + * {@link + * android.telephony.ims.feature.RcsFeature.RcsImsCapabilities#CAPABILITY_TYPE_PRESENCE_UCE} is + * enabled or else this operation will fail with {@link #ERROR_NOT_AVAILABLE} or + * {@link #ERROR_NOT_ENABLED}. * * @param contactNumbers A list of numbers that the capabilities are being requested for. * @param executor The executor that will be used when the request is completed and the @@ -573,8 +582,10 @@ public class RcsUceAdapter { * <p> * Be sure to check the availability of this feature using * {@link ImsRcsManager#isAvailable(int, int)} and ensuring - * {@link RcsFeature.RcsImsCapabilities#CAPABILITY_TYPE_OPTIONS_UCE} or - * {@link RcsFeature.RcsImsCapabilities#CAPABILITY_TYPE_PRESENCE_UCE} is + * {@link + * android.telephony.ims.feature.RcsFeature.RcsImsCapabilities#CAPABILITY_TYPE_OPTIONS_UCE} or + * {@link + * android.telephony.ims.feature.RcsFeature.RcsImsCapabilities#CAPABILITY_TYPE_PRESENCE_UCE} is * enabled or else this operation will fail with * {@link #ERROR_NOT_AVAILABLE} or {@link #ERROR_NOT_ENABLED}. * @@ -690,7 +701,8 @@ public class RcsUceAdapter { * Registers a {@link OnPublishStateChangedListener} with the system, which will provide publish * state updates for the subscription specified in {@link ImsManager@getRcsManager(subid)}. * <p> - * Use {@link SubscriptionManager.OnSubscriptionsChangedListener} to listen to subscription + * Use {@link android.telephony.SubscriptionManager.OnSubscriptionsChangedListener} to listen + * to subscription * changed events and call * {@link #removeOnPublishStateChangedListener(OnPublishStateChangedListener)} to clean up. * <p> @@ -792,7 +804,8 @@ public class RcsUceAdapter { * cache associated with those contacts as the local cache becomes stale. * <p> * This setting will only enable this feature if - * {@link CarrierConfigManager.Ims#KEY_RCS_BULK_CAPABILITY_EXCHANGE_BOOL} is also enabled. + * {@link android.telephony.CarrierConfigManager.Ims#KEY_RCS_BULK_CAPABILITY_EXCHANGE_BOOL} is + * also enabled. * <p> * Note: This setting does not affect whether or not the device publishes its service * capabilities if the subscription supports presence publication. @@ -843,7 +856,8 @@ public class RcsUceAdapter { * session. * <p> * This setting will only enable this feature if - * {@link CarrierConfigManager.Ims#KEY_RCS_BULK_CAPABILITY_EXCHANGE_BOOL} is also enabled. + * {@link android.telephony.CarrierConfigManager.Ims#KEY_RCS_BULK_CAPABILITY_EXCHANGE_BOOL} is + * also enabled. * <p> * Note: This setting does not affect whether or not the device publishes its service * capabilities if the subscription supports presence publication. diff --git a/telephony/java/android/telephony/ims/aidl/CapabilityExchangeAidlWrapper.java b/telephony/java/android/telephony/ims/aidl/CapabilityExchangeAidlWrapper.java index c3d7325f2e0a..c27fa4fc882d 100644 --- a/telephony/java/android/telephony/ims/aidl/CapabilityExchangeAidlWrapper.java +++ b/telephony/java/android/telephony/ims/aidl/CapabilityExchangeAidlWrapper.java @@ -81,6 +81,26 @@ public class CapabilityExchangeAidlWrapper implements CapabilityExchangeEventLis } /** + * Receives the status of changes in the publishing connection from ims service + * and deliver this callback to the framework. + */ + public void onPublishUpdated(int reasonCode, @NonNull String reasonPhrase, + int reasonHeaderCause, @NonNull String reasonHeaderText) throws ImsException { + ICapabilityExchangeEventListener listener = mListenerBinder; + if (listener == null) { + return; + } + try { + listener.onPublishUpdated(reasonCode, reasonPhrase, + reasonHeaderCause, reasonHeaderText); + } catch (RemoteException e) { + Log.w(LOG_TAG, "onPublishUpdated exception: " + e); + throw new ImsException("Remote is not available", + ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); + } + } + + /** * Receives the callback of the remote capability request from the network and deliver this * request to the framework. */ diff --git a/telephony/java/android/telephony/ims/aidl/ICapabilityExchangeEventListener.aidl b/telephony/java/android/telephony/ims/aidl/ICapabilityExchangeEventListener.aidl index 078ac919b75e..c675bc3204f6 100644 --- a/telephony/java/android/telephony/ims/aidl/ICapabilityExchangeEventListener.aidl +++ b/telephony/java/android/telephony/ims/aidl/ICapabilityExchangeEventListener.aidl @@ -31,6 +31,8 @@ import java.util.List; oneway interface ICapabilityExchangeEventListener { void onRequestPublishCapabilities(int publishTriggerType); void onUnpublish(); + void onPublishUpdated(int reasonCode, String reasonPhrase, int reasonHeaderCause, + String reasonHeaderText); void onRemoteCapabilityRequest(in Uri contactUri, in List<String> remoteCapabilities, IOptionsRequestCallback cb); } diff --git a/telephony/java/android/telephony/ims/stub/CapabilityExchangeEventListener.java b/telephony/java/android/telephony/ims/stub/CapabilityExchangeEventListener.java index a3be8dab2891..9293a40d9a33 100644 --- a/telephony/java/android/telephony/ims/stub/CapabilityExchangeEventListener.java +++ b/telephony/java/android/telephony/ims/stub/CapabilityExchangeEventListener.java @@ -90,6 +90,30 @@ public interface CapabilityExchangeEventListener { void onUnpublish() throws ImsException; /** + * Notify the framework that the ImsService has refreshed the PUBLISH + * internally, which has resulted in a new PUBLISH result. + * <p> + * This method must return both SUCCESS (200 OK) and FAILURE (300+) codes in order to + * keep the AOSP stack up to date. + * @param reasonCode The SIP response code sent from the network. + * @param reasonPhrase The optional reason response from the network. If the + * network provided no reason with the sip code, the string should be empty. + * @param reasonHeaderCause The “cause” parameter of the “reason” header + * included in the SIP message. + * @param reasonHeaderText The “text” parameter of the “reason” header + * included in the SIP message. + * @throws ImsException If this {@link RcsCapabilityExchangeImplBase} instance is not + * currently connected to the framework. This can happen if the {@link RcsFeature} is not + * {@link ImsFeature#STATE_READY} and the {@link RcsFeature} has not received + * the {@link ImsFeature#onFeatureReady()} callback. This may also happen in rare + * cases when the Telephony stack has crashed. + * + */ + default void onPublishUpdated(int reasonCode, @NonNull String reasonPhrase, + int reasonHeaderCause, @NonNull String reasonHeaderText) throws ImsException { + } + + /** * Inform the framework of an OPTIONS query from a remote device for this device's UCE * capabilities. * <p> diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl index 2df5f53147bc..03010f6b27b6 100644 --- a/telephony/java/com/android/internal/telephony/ITelephony.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl @@ -900,6 +900,8 @@ interface ITelephony { * Perform a radio network scan and return the id of this scan. * * @param subId the id of the subscription. + * @param renounceFineLocationAccess Set this to true if the caller would not like to + * receive fine location related information * @param request Defines all the configs for network scan. * @param messenger Callback messages will be sent using this messenger. * @param binder the binder object instantiated in TelephonyManager. @@ -907,8 +909,9 @@ interface ITelephony { * @param callingFeatureId The feature in the package * @return An id for this scan. */ - int requestNetworkScan(int subId, in NetworkScanRequest request, in Messenger messenger, - in IBinder binder, in String callingPackage, String callingFeatureId); + int requestNetworkScan(int subId, in boolean renounceFineLocationAccess, + in NetworkScanRequest request, in Messenger messenger, in IBinder binder, + in String callingPackage, String callingFeatureId); /** * Stop an existing radio network scan. @@ -1387,12 +1390,17 @@ interface ITelephony { /** * Get the service state on specified subscription * @param subId Subscription id + * @param renounceFineLocationAccess Set this to true if the caller would not like to + * receive fine location related information + * @param renounceCoarseLocationAccess Set this to true if the caller would not like to + * receive coarse location related information * @param callingPackage The package making the call * @param callingFeatureId The feature in the package * @return Service state on specified subscription. */ - ServiceState getServiceStateForSubscriber(int subId, String callingPackage, - String callingFeatureId); + ServiceState getServiceStateForSubscriber(int subId, boolean renounceFineLocationAccess, + boolean renounceCoarseLocationAccess, + String callingPackage, String callingFeatureId); /** * Returns the URI for the per-account voicemail ringtone set in Phone settings. |