diff options
64 files changed, 1032 insertions, 677 deletions
diff --git a/apct-tests/perftests/multiuser/Android.bp b/apct-tests/perftests/multiuser/Android.bp index 04432f25e337..fc45d4adcc15 100644 --- a/apct-tests/perftests/multiuser/Android.bp +++ b/apct-tests/perftests/multiuser/Android.bp @@ -22,5 +22,6 @@ android_test { ], platform_apis: true, test_suites: ["device-tests"], + data: [":perfetto_artifacts"], certificate: "platform", } diff --git a/apct-tests/perftests/multiuser/AndroidManifest.xml b/apct-tests/perftests/multiuser/AndroidManifest.xml index e4196dd6cf12..cb05651a3eec 100644 --- a/apct-tests/perftests/multiuser/AndroidManifest.xml +++ b/apct-tests/perftests/multiuser/AndroidManifest.xml @@ -17,7 +17,6 @@ <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.perftests.multiuser"> - <uses-sdk android:targetSdkVersion="28" /> <uses-permission android:name="android.permission.CONTROL_KEYGUARD" /> <uses-permission android:name="android.permission.MANAGE_USERS" /> @@ -25,8 +24,6 @@ <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" /> <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" /> <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" /> - <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> - <uses-permission android:name="android.permission.REAL_GET_TASKS" /> <application> <uses-library android:name="android.test.runner" /> diff --git a/apct-tests/perftests/multiuser/AndroidTest.xml b/apct-tests/perftests/multiuser/AndroidTest.xml index 9117561fe1e5..c7929af6077f 100644 --- a/apct-tests/perftests/multiuser/AndroidTest.xml +++ b/apct-tests/perftests/multiuser/AndroidTest.xml @@ -16,14 +16,48 @@ <configuration description="Runs MultiUserPerfTests metric instrumentation."> <option name="test-suite-tag" value="apct" /> <option name="test-suite-tag" value="apct-metric-instrumentation" /> + <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller"> <option name="cleanup-apks" value="true" /> <option name="test-file-name" value="MultiUserPerfTests.apk" /> <option name="test-file-name" value="MultiUserPerfDummyApp.apk" /> </target_preparer> + <!-- Needed for pushing the trace config file --> + <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/> + <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer"> + <option name="push-file" key="trace_config_detailed.textproto" value="/data/misc/perfetto-traces/trace_config.textproto" /> + </target_preparer> + + <!-- Needed for pulling the collected trace config on to the host --> + <metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector"> + <option name="pull-pattern-keys" value="perfetto_file_path" /> + </metrics_collector> + + <!-- Needed for storing the perfetto trace files in the sdcard/test_results--> + <option name="isolated-storage" value="false" /> + <test class="com.android.tradefed.testtype.AndroidJUnitTest" > <option name="package" value="com.android.perftests.multiuser" /> <option name="hidden-api-checks" value="false"/> + + <!-- Listener related args for collecting the traces and waiting for the device to stabilize. --> + <option name="device-listeners" value="android.device.collectors.ProcLoadListener,android.device.collectors.PerfettoListener" /> + <!-- Guarantee that user defined RunListeners will be running before any of the default listeners defined in this runner. --> + <option name="instrumentation-arg" key="newRunListenerMode" value="true" /> + + <!-- ProcLoadListener related arguments --> + <!-- Wait for device last minute threshold to reach 3 with 2 minute timeout before starting the test run --> + <option name="instrumentation-arg" key="procload-collector:per_run" value="true" /> + <option name="instrumentation-arg" key="proc-loadavg-threshold" value="3" /> + <option name="instrumentation-arg" key="proc-loadavg-timeout" value="120000" /> + <option name="instrumentation-arg" key="proc-loadavg-interval" value="10000" /> + + <!-- PerfettoListener related arguments --> + <option name="instrumentation-arg" key="perfetto_config_text_proto" value="true" /> + <option name="instrumentation-arg" key="perfetto_config_file" value="trace_config.textproto" /> + + <option name="instrumentation-arg" key="newRunListenerMode" value="true" /> + </test> </configuration> diff --git a/api/current.txt b/api/current.txt index a59c7b85e608..09de005c008c 100644 --- a/api/current.txt +++ b/api/current.txt @@ -24207,6 +24207,7 @@ package android.media { method @NonNull public java.util.List<android.media.AudioPlaybackConfiguration> getActivePlaybackConfigurations(); method @NonNull public java.util.List<android.media.AudioRecordingConfiguration> getActiveRecordingConfigurations(); method public int getAllowedCapturePolicy(); + method public int getAudioHwSyncForSession(int); method public android.media.AudioDeviceInfo[] getDevices(int); method public java.util.List<android.media.MicrophoneInfo> getMicrophones() throws java.io.IOException; method public int getMode(); @@ -47864,6 +47865,7 @@ package android.telephony { method @Nullable public android.net.LinkProperties getLinkProperties(); method public int getNetworkType(); method public int getState(); + method public int getTransportType(); method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.telephony.PreciseDataConnectionState> CREATOR; } diff --git a/api/system-current.txt b/api/system-current.txt index 11db781dd42f..fb0d924673b8 100755 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -10838,6 +10838,7 @@ package android.telephony { method @Deprecated public int getDataConnectionApnTypeBitMask(); method @Deprecated public int getDataConnectionFailCause(); method @Deprecated public int getDataConnectionState(); + method public int getId(); } public final class PreciseDisconnectCause { diff --git a/cmds/screencap/screencap.cpp b/cmds/screencap/screencap.cpp index c1d8399d91a5..a46a54cc2063 100644 --- a/cmds/screencap/screencap.cpp +++ b/cmds/screencap/screencap.cpp @@ -182,16 +182,17 @@ int main(int argc, char** argv) ProcessState::self()->setThreadPoolMaxThreadCount(0); ProcessState::self()->startThreadPool(); - ui::Dataspace outDataspace; - sp<GraphicBuffer> outBuffer; - - status_t result = ScreenshotClient::capture(*displayId, &outDataspace, &outBuffer); + ScreenCaptureResults captureResults; + status_t result = ScreenshotClient::captureDisplay(*displayId, captureResults); if (result != NO_ERROR) { close(fd); return 1; } - result = outBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN, &base); + ui::Dataspace dataspace = captureResults.capturedDataspace; + sp<GraphicBuffer> buffer = captureResults.buffer; + + result = buffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN, &base); if (base == nullptr || result != NO_ERROR) { String8 reason; @@ -207,13 +208,13 @@ int main(int argc, char** argv) if (png) { AndroidBitmapInfo info; - info.format = flinger2bitmapFormat(outBuffer->getPixelFormat()); + info.format = flinger2bitmapFormat(buffer->getPixelFormat()); info.flags = ANDROID_BITMAP_FLAGS_ALPHA_PREMUL; - info.width = outBuffer->getWidth(); - info.height = outBuffer->getHeight(); - info.stride = outBuffer->getStride() * bytesPerPixel(outBuffer->getPixelFormat()); + info.width = buffer->getWidth(); + info.height = buffer->getHeight(); + info.stride = buffer->getStride() * bytesPerPixel(buffer->getPixelFormat()); - int result = AndroidBitmap_compress(&info, static_cast<int32_t>(outDataspace), base, + int result = AndroidBitmap_compress(&info, static_cast<int32_t>(dataspace), base, ANDROID_BITMAP_COMPRESS_FORMAT_PNG, 100, &fd, [](void* fdPtr, const void* data, size_t size) -> bool { int bytesWritten = write(*static_cast<int*>(fdPtr), @@ -229,11 +230,11 @@ int main(int argc, char** argv) notifyMediaScanner(fn); } } else { - uint32_t w = outBuffer->getWidth(); - uint32_t h = outBuffer->getHeight(); - uint32_t s = outBuffer->getStride(); - uint32_t f = outBuffer->getPixelFormat(); - uint32_t c = dataSpaceToInt(outDataspace); + uint32_t w = buffer->getWidth(); + uint32_t h = buffer->getHeight(); + uint32_t s = buffer->getStride(); + uint32_t f = buffer->getPixelFormat(); + uint32_t c = dataSpaceToInt(dataspace); write(fd, &w, 4); write(fd, &h, 4); diff --git a/core/java/android/animation/AnimatorSet.java b/core/java/android/animation/AnimatorSet.java index a9239b48bb3f..bc8db029e06d 100644 --- a/core/java/android/animation/AnimatorSet.java +++ b/core/java/android/animation/AnimatorSet.java @@ -183,7 +183,7 @@ public final class AnimatorSet extends Animator implements AnimationHandler.Anim // This is to work around a bug in b/34736819. This needs to be removed once app team // fixes their side. - private AnimatorListenerAdapter mAnimationEndingListener = new AnimatorListenerAdapter() { + private AnimatorListenerAdapter mAnimationEndListener = new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { if (mNodeMap.get(animation) == null) { @@ -1186,7 +1186,7 @@ public final class AnimatorSet extends Animator implements AnimationHandler.Anim } private void startAnimation() { - addAnimationEndingListener(); + addAnimationEndListener(); // Register animation callback addAnimationCallback(0); @@ -1243,15 +1243,15 @@ public final class AnimatorSet extends Animator implements AnimationHandler.Anim // This is to work around the issue in b/34736819, as the old behavior in AnimatorSet had // masked a real bug in play movies. TODO: remove this and below once the root cause is fixed. - private void addAnimationEndingListener() { + private void addAnimationEndListener() { for (int i = 1; i < mNodes.size(); i++) { - mNodes.get(i).mAnimation.addListener(mAnimationEndingListener); + mNodes.get(i).mAnimation.addListener(mAnimationEndListener); } } - private void removeAnimationEndingListener() { + private void removeAnimationEndListener() { for (int i = 1; i < mNodes.size(); i++) { - mNodes.get(i).mAnimation.removeListener(mAnimationEndingListener); + mNodes.get(i).mAnimation.removeListener(mAnimationEndListener); } } @@ -1301,7 +1301,7 @@ public final class AnimatorSet extends Animator implements AnimationHandler.Anim tmpListeners.get(i).onAnimationEnd(this, mReversing); } } - removeAnimationEndingListener(); + removeAnimationEndListener(); mSelfPulse = true; mReversing = false; } @@ -1346,7 +1346,7 @@ public final class AnimatorSet extends Animator implements AnimationHandler.Anim anim.mNodeMap = new ArrayMap<Animator, Node>(); anim.mNodes = new ArrayList<Node>(nodeCount); anim.mEvents = new ArrayList<AnimationEvent>(); - anim.mAnimationEndingListener = new AnimatorListenerAdapter() { + anim.mAnimationEndListener = new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { if (anim.mNodeMap.get(animation) == null) { @@ -1369,7 +1369,7 @@ public final class AnimatorSet extends Animator implements AnimationHandler.Anim final Node node = mNodes.get(n); Node nodeClone = node.clone(); // Remove the old internal listener from the cloned child - nodeClone.mAnimation.removeListener(mAnimationEndingListener); + nodeClone.mAnimation.removeListener(mAnimationEndListener); clonesMap.put(node, nodeClone); anim.mNodes.add(nodeClone); anim.mNodeMap.put(nodeClone.mAnimation, nodeClone); diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java index 7fe567b5ce27..9cf0d2a3a36a 100644 --- a/core/java/android/app/ActivityManagerInternal.java +++ b/core/java/android/app/ActivityManagerInternal.java @@ -52,23 +52,14 @@ public abstract class ActivityManagerInternal { * if in the same profile group. * Otherwise, {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL} is required. */ - public static final int ALLOW_NON_FULL_IN_PROFILE_OR_FULL = 1; + public static final int ALLOW_NON_FULL_IN_PROFILE = 1; public static final int ALLOW_FULL_ONLY = 2; /** * Allows access to a caller with {@link android.Manifest.permission#INTERACT_ACROSS_PROFILES} * or {@link android.Manifest.permission#INTERACT_ACROSS_USERS} if in the same profile group. * Otherwise, {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL} is required. */ - public static final int ALLOW_ACROSS_PROFILES_IN_PROFILE_OR_FULL = 3; - /** - * Requires {@link android.Manifest.permission#INTERACT_ACROSS_PROFILES}, - * {@link android.Manifest.permission#INTERACT_ACROSS_USERS}, or - * {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL} if in same profile group, - * otherwise {@link android.Manifest.permission#INTERACT_ACROSS_USERS} or - * {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL}. (so this is an extension - * to {@link #ALLOW_NON_FULL}) - */ - public static final int ALLOW_ACROSS_PROFILES_IN_PROFILE_OR_NON_FULL = 4; + public static final int ALLOW_ALL_PROFILE_PERMISSIONS_IN_PROFILE = 3; /** * Verify that calling app has access to the given provider. diff --git a/core/java/android/companion/BluetoothDeviceFilter.java b/core/java/android/companion/BluetoothDeviceFilter.java index 2649fbee4246..cf9eeca0d739 100644 --- a/core/java/android/companion/BluetoothDeviceFilter.java +++ b/core/java/android/companion/BluetoothDeviceFilter.java @@ -142,6 +142,16 @@ public final class BluetoothDeviceFilter implements DeviceFilter<BluetoothDevice } @Override + public String toString() { + return "BluetoothDeviceFilter{" + + "mNamePattern=" + mNamePattern + + ", mAddress='" + mAddress + '\'' + + ", mServiceUuids=" + mServiceUuids + + ", mServiceUuidMasks=" + mServiceUuidMasks + + '}'; + } + + @Override public int describeContents() { return 0; } diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 7ee41b9fe418..5acc11a868bf 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -8728,16 +8728,6 @@ public final class Settings { = "bubble_important_conversations"; /** - * When enabled, notifications the notification assistant service has modified will show an - * indicator. When tapped, this indicator will describe the adjustment made and solicit - * feedback. This flag will also add a "automatic" option to the long press menu. - * - * The value 1 - enable, 0 - disable - * @hide - */ - public static final String NOTIFICATION_FEEDBACK_ENABLED = "notification_feedback_enabled"; - - /** * Whether notifications are dismissed by a right-to-left swipe (instead of a left-to-right * swipe). * @@ -14047,6 +14037,16 @@ public final class Settings { "notification_snooze_options"; /** + * When enabled, notifications the notification assistant service has modified will show an + * indicator. When tapped, this indicator will describe the adjustment made and solicit + * feedback. This flag will also add a "automatic" option to the long press menu. + * + * The value 1 - enable, 0 - disable + * @hide + */ + public static final String NOTIFICATION_FEEDBACK_ENABLED = "notification_feedback_enabled"; + + /** * Settings key for the ratio of notification dismissals to notification views - one of the * criteria for showing the notification blocking helper. * diff --git a/core/java/android/telephony/TelephonyRegistryManager.java b/core/java/android/telephony/TelephonyRegistryManager.java index 0a47032354f5..a720601d81ff 100644 --- a/core/java/android/telephony/TelephonyRegistryManager.java +++ b/core/java/android/telephony/TelephonyRegistryManager.java @@ -26,10 +26,8 @@ import android.os.Binder; import android.os.Build; import android.os.RemoteException; import android.os.ServiceManager; -import android.telephony.Annotation.ApnType; import android.telephony.Annotation.CallState; import android.telephony.Annotation.DataActivityType; -import android.telephony.Annotation.DataFailureCause; import android.telephony.Annotation.DisconnectCauses; import android.telephony.Annotation.NetworkType; import android.telephony.Annotation.PreciseCallStates; @@ -37,7 +35,6 @@ import android.telephony.Annotation.PreciseDisconnectCauses; import android.telephony.Annotation.RadioPowerState; import android.telephony.Annotation.SimActivationState; import android.telephony.Annotation.SrvccState; -import android.telephony.data.ApnSetting; import android.telephony.emergency.EmergencyNumber; import android.telephony.ims.ImsReasonInfo; import android.util.Log; @@ -402,17 +399,16 @@ public class TelephonyRegistryManager { * @param subId for which data connection state changed. * @param slotIndex for which data connections state changed. Can be derived from subId except * when subId is invalid. - * @param apnType the apn type bitmask, defined with {@code ApnSetting#TYPE_*} flags. * @param preciseState the PreciseDataConnectionState * - * @see android.telephony.PreciseDataConnection + * @see PreciseDataConnectionState * @see TelephonyManager#DATA_DISCONNECTED */ public void notifyDataConnectionForSubscriber(int slotIndex, int subId, - @ApnType int apnType, @Nullable PreciseDataConnectionState preciseState) { + @NonNull PreciseDataConnectionState preciseState) { try { sRegistry.notifyDataConnectionForSubscriber( - slotIndex, subId, apnType, preciseState); + slotIndex, subId, preciseState); } catch (RemoteException ex) { // system process is dead } @@ -612,25 +608,6 @@ public class TelephonyRegistryManager { } /** - * Notify precise data connection failed cause on certain subscription. - * - * @param subId for which data connection failed. - * @param slotIndex for which data conenction failed. Can be derived from subId except when - * subId is invalid. - * @param apnType the apn type bitmask, defined with {@code ApnSetting#TYPE_*} flags. - * @param apn the APN {@link ApnSetting#getApnName()} of this data connection. - * @param failCause data fail cause. - */ - public void notifyPreciseDataConnectionFailed(int subId, int slotIndex, @ApnType int apnType, - @Nullable String apn, @DataFailureCause int failCause) { - try { - sRegistry.notifyPreciseDataConnectionFailed(slotIndex, subId, apnType, apn, failCause); - } catch (RemoteException ex) { - // system process is dead - } - } - - /** * Notify single Radio Voice Call Continuity (SRVCC) state change for the currently active call * on certain subscription. * diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java index eaa7eafc23cc..50ed00cd0aa7 100644 --- a/core/java/android/view/SurfaceControl.java +++ b/core/java/android/view/SurfaceControl.java @@ -89,13 +89,10 @@ public final class SurfaceControl implements Parcelable { private static native void nativeWriteToParcel(long nativeObject, Parcel out); private static native void nativeRelease(long nativeObject); private static native void nativeDisconnect(long nativeObject); - - private static native ScreenshotHardwareBuffer nativeScreenshot(IBinder displayToken, - Rect sourceCrop, int width, int height, boolean useIdentityTransform, int rotation, - boolean captureSecureLayers); - private static native ScreenshotHardwareBuffer nativeCaptureLayers(IBinder displayToken, - long layerObject, Rect sourceCrop, float frameScale, long[] excludeLayerObjects, - int format); + private static native ScreenshotHardwareBuffer nativeCaptureDisplay( + DisplayCaptureArgs captureArgs); + private static native ScreenshotHardwareBuffer nativeCaptureLayers( + LayerCaptureArgs captureArgs); private static native long nativeMirrorSurface(long mirrorOfObject); private static native long nativeCreateTransaction(); private static native long nativeGetNativeTransactionFinalizer(); @@ -572,7 +569,8 @@ public final class SurfaceControl implements Parcelable { * Create ScreenshotHardwareBuffer from an existing HardwareBuffer object. * @param hardwareBuffer The existing HardwareBuffer object * @param namedColorSpace Integer value of a named color space {@link ColorSpace.Named} - * @param containsSecureLayer Indicates whether this graphic buffer contains captured contents + * @param containsSecureLayers Indicates whether this graphic buffer contains captured + * contents * of secure layers, in which case the screenshot should not be persisted. */ private static ScreenshotHardwareBuffer createFromNative(HardwareBuffer hardwareBuffer, @@ -662,14 +660,14 @@ public final class SurfaceControl implements Parcelable { /** * Each sub class should return itself to allow the builder to chain properly */ - public abstract T getThis(); + abstract T getThis(); } } /** * The arguments class used to make display capture requests. * - * @see #nativeScreenshot(IBinder, Rect, int, int, boolean, int, boolean) + * @see #nativeCaptureDisplay(DisplayCaptureArgs) * @hide */ public static class DisplayCaptureArgs extends CaptureArgs { @@ -759,7 +757,7 @@ public final class SurfaceControl implements Parcelable { } @Override - public Builder getThis() { + Builder getThis() { return this; } } @@ -768,7 +766,7 @@ public final class SurfaceControl implements Parcelable { /** * The arguments class used to make layer capture requests. * - * @see #nativeCaptureLayers(IBinder, long, Rect, float, long[], int) + * @see #nativeCaptureLayers(LayerCaptureArgs) * @hide */ public static class LayerCaptureArgs extends CaptureArgs { @@ -780,9 +778,13 @@ public final class SurfaceControl implements Parcelable { super(builder); mChildrenOnly = builder.mChildrenOnly; mNativeLayer = builder.mLayer.mNativeObject; - mNativeExcludeLayers = new long[builder.mExcludeLayers.length]; - for (int i = 0; i < builder.mExcludeLayers.length; i++) { - mNativeExcludeLayers[i] = builder.mExcludeLayers[i].mNativeObject; + if (builder.mExcludeLayers != null) { + mNativeExcludeLayers = new long[builder.mExcludeLayers.length]; + for (int i = 0; i < builder.mExcludeLayers.length; i++) { + mNativeExcludeLayers[i] = builder.mExcludeLayers[i].mNativeObject; + } + } else { + mNativeExcludeLayers = null; } } @@ -837,7 +839,7 @@ public final class SurfaceControl implements Parcelable { } @Override - public Builder getThis() { + Builder getThis() { return this; } @@ -2293,8 +2295,14 @@ public final class SurfaceControl implements Parcelable { throw new IllegalArgumentException("displayToken must not be null"); } - return nativeScreenshot(display, sourceCrop, width, height, useIdentityTransform, rotation, - false /* captureSecureLayers */); + DisplayCaptureArgs captureArgs = new DisplayCaptureArgs.Builder(display) + .setSourceCrop(sourceCrop) + .setSize(width, height) + .setUseIdentityTransform(useIdentityTransform) + .setRotation(rotation) + .build(); + + return nativeCaptureDisplay(captureArgs); } /** @@ -2314,8 +2322,15 @@ public final class SurfaceControl implements Parcelable { throw new IllegalArgumentException("displayToken must not be null"); } - return nativeScreenshot(display, sourceCrop, width, height, useIdentityTransform, rotation, - true /* captureSecureLayers */); + DisplayCaptureArgs captureArgs = new DisplayCaptureArgs.Builder(display) + .setSourceCrop(sourceCrop) + .setSize(width, height) + .setUseIdentityTransform(useIdentityTransform) + .setRotation(rotation) + .setCaptureSecureLayers(true) + .build(); + + return nativeCaptureDisplay(captureArgs); } private static void rotateCropForSF(Rect crop, int rot) { @@ -2365,24 +2380,30 @@ public final class SurfaceControl implements Parcelable { */ public static ScreenshotHardwareBuffer captureLayers(SurfaceControl layer, Rect sourceCrop, float frameScale, int format) { - final IBinder displayToken = SurfaceControl.getInternalDisplayToken(); - return nativeCaptureLayers(displayToken, layer.mNativeObject, sourceCrop, frameScale, null, - format); + LayerCaptureArgs captureArgs = new LayerCaptureArgs.Builder(layer) + .setSourceCrop(sourceCrop) + .setFrameScale(frameScale) + .setPixelFormat(format) + .build(); + + return nativeCaptureLayers(captureArgs); } /** - * Like {@link captureLayers} but with an array of layer handles to exclude. + * Like {@link #captureLayers(SurfaceControl, Rect, float, int)} but with an array of layer + * handles to exclude. * @hide */ public static ScreenshotHardwareBuffer captureLayersExcluding(SurfaceControl layer, Rect sourceCrop, float frameScale, int format, SurfaceControl[] exclude) { - final IBinder displayToken = SurfaceControl.getInternalDisplayToken(); - long[] nativeExcludeObjects = new long[exclude.length]; - for (int i = 0; i < exclude.length; i++) { - nativeExcludeObjects[i] = exclude[i].mNativeObject; - } - return nativeCaptureLayers(displayToken, layer.mNativeObject, sourceCrop, frameScale, - nativeExcludeObjects, PixelFormat.RGBA_8888); + LayerCaptureArgs captureArgs = new LayerCaptureArgs.Builder(layer) + .setSourceCrop(sourceCrop) + .setFrameScale(frameScale) + .setPixelFormat(format) + .setExcludeLayers(exclude) + .build(); + + return nativeCaptureLayers(captureArgs); } /** diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java index 708e27771ef2..2d0f05e3dc02 100644 --- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java +++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java @@ -1768,7 +1768,7 @@ public class AccessibilityNodeInfo implements Parcelable { * <strong>Note:</strong> The primary usage of this API is for UI test automation * and in order to report the fully qualified view id if an {@link AccessibilityNodeInfo} * the client has to set the {@link AccessibilityServiceInfo#FLAG_REPORT_VIEW_IDS} - * flag when configuring their {@link android.accessibilityservice.AccessibilityService}. + * flag when configuring the {@link android.accessibilityservice.AccessibilityService}. * </p> * <p> * <strong>Note:</strong> If this view hierarchy has a {@link SurfaceView} embedding another @@ -3206,7 +3206,7 @@ public class AccessibilityNodeInfo implements Parcelable { * <strong>Note:</strong> The primary usage of this API is for UI test automation * and in order to report the source view id of an {@link AccessibilityNodeInfo} the * client has to set the {@link AccessibilityServiceInfo#FLAG_REPORT_VIEW_IDS} - * flag when configuring their {@link android.accessibilityservice.AccessibilityService}. + * flag when configuring the {@link android.accessibilityservice.AccessibilityService}. * </p> * @return The id resource name. diff --git a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl index 5a04992a35b4..ea09fc8cd34a 100644 --- a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl +++ b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl @@ -65,9 +65,7 @@ interface ITelephonyRegistry { void notifyDataActivity(int state); void notifyDataActivityForSubscriber(in int subId, int state); void notifyDataConnectionForSubscriber( - int phoneId, int subId, int apnType, in PreciseDataConnectionState preciseState); - @UnsupportedAppUsage - void notifyDataConnectionFailed(String apnType); + int phoneId, int subId, in PreciseDataConnectionState preciseState); // Uses CellIdentity which is Parcelable here; will convert to CellLocation in client. void notifyCellLocation(in CellIdentity cellLocation); void notifyCellLocationForSubscriber(in int subId, in CellIdentity cellLocation); @@ -77,8 +75,6 @@ interface ITelephonyRegistry { int foregroundCallState, int backgroundCallState); void notifyDisconnectCause(int phoneId, int subId, int disconnectCause, int preciseDisconnectCause); - void notifyPreciseDataConnectionFailed(int phoneId, int subId, int apnType, String apn, - int failCause); void notifyCellInfoForSubscriber(in int subId, in List<CellInfo> cellInfo); void notifySrvccStateChanged(in int subId, in int lteState); void notifySimActivationStateChangedForPhoneId(in int phoneId, in int subId, diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp index a965ab310205..814a07e7f2df 100644 --- a/core/jni/android_view_SurfaceControl.cpp +++ b/core/jni/android_view_SurfaceControl.cpp @@ -104,6 +104,27 @@ static struct { jfieldID top; } gRectClassInfo; +static struct { + jfieldID pixelFormat; + jfieldID sourceCrop; + jfieldID frameScale; + jfieldID captureSecureLayers; +} gCaptureArgsClassInfo; + +static struct { + jfieldID displayToken; + jfieldID width; + jfieldID height; + jfieldID useIdentityTransform; + jfieldID rotation; +} gDisplayCaptureArgsClassInfo; + +static struct { + jfieldID layer; + jfieldID excludeLayers; + jfieldID childrenOnly; +} gLayerCaptureArgsClassInfo; + // Implements SkMallocPixelRef::ReleaseProc, to delete the screenshot on unref. void DeleteScreenshot(void* addr, void* context) { delete ((ScreenshotClient*) context); @@ -276,55 +297,79 @@ static Rect rectFromObj(JNIEnv* env, jobject rectObj) { return Rect(left, top, right, bottom); } -static jobject nativeScreenshot(JNIEnv* env, jclass clazz, - jobject displayTokenObj, jobject sourceCropObj, jint width, jint height, - bool useIdentityTransform, int rotation, bool captureSecureLayers) { - sp<IBinder> displayToken = ibinderForJavaObject(env, displayTokenObj); - if (displayToken == NULL) { +static void getCaptureArgs(JNIEnv* env, jobject captureArgsObject, CaptureArgs& captureArgs) { + captureArgs.pixelFormat = static_cast<ui::PixelFormat>( + env->GetIntField(captureArgsObject, gCaptureArgsClassInfo.pixelFormat)); + captureArgs.sourceCrop = + rectFromObj(env, + env->GetObjectField(captureArgsObject, gCaptureArgsClassInfo.sourceCrop)); + captureArgs.frameScale = + env->GetFloatField(captureArgsObject, gCaptureArgsClassInfo.frameScale); + captureArgs.captureSecureLayers = + env->GetBooleanField(captureArgsObject, gCaptureArgsClassInfo.captureSecureLayers); +} + +static DisplayCaptureArgs displayCaptureArgsFromObject(JNIEnv* env, + jobject displayCaptureArgsObject) { + DisplayCaptureArgs captureArgs; + getCaptureArgs(env, displayCaptureArgsObject, captureArgs); + + captureArgs.displayToken = + ibinderForJavaObject(env, + env->GetObjectField(displayCaptureArgsObject, + gDisplayCaptureArgsClassInfo.displayToken)); + captureArgs.width = + env->GetIntField(displayCaptureArgsObject, gDisplayCaptureArgsClassInfo.width); + captureArgs.height = + env->GetIntField(displayCaptureArgsObject, gDisplayCaptureArgsClassInfo.height); + captureArgs.useIdentityTransform = + env->GetBooleanField(displayCaptureArgsObject, + gDisplayCaptureArgsClassInfo.useIdentityTransform); + captureArgs.rotation = ui::toRotation( + env->GetIntField(displayCaptureArgsObject, gDisplayCaptureArgsClassInfo.rotation)); + return captureArgs; +} + +static jobject nativeCaptureDisplay(JNIEnv* env, jclass clazz, jobject displayCaptureArgsObject) { + const DisplayCaptureArgs captureArgs = + displayCaptureArgsFromObject(env, displayCaptureArgsObject); + + if (captureArgs.displayToken == NULL) { return NULL; } - const ui::ColorMode colorMode = SurfaceComposerClient::getActiveColorMode(displayToken); - const ui::Dataspace dataspace = pickDataspaceFromColorMode(colorMode); - - Rect sourceCrop = rectFromObj(env, sourceCropObj); - sp<GraphicBuffer> buffer; - bool capturedSecureLayers = false; - status_t res = ScreenshotClient::capture(displayToken, dataspace, - ui::PixelFormat::RGBA_8888, - sourceCrop, width, height, - useIdentityTransform, ui::toRotation(rotation), - captureSecureLayers, &buffer, capturedSecureLayers); + + ScreenCaptureResults captureResults; + status_t res = ScreenshotClient::captureDisplay(captureArgs, captureResults); if (res != NO_ERROR) { return NULL; } - jobject jhardwareBuffer = - android_hardware_HardwareBuffer_createFromAHardwareBuffer(env, - buffer->toAHardwareBuffer()); - const jint namedColorSpace = fromDataspaceToNamedColorSpaceValue(dataspace); + jobject jhardwareBuffer = android_hardware_HardwareBuffer_createFromAHardwareBuffer( + env, captureResults.buffer->toAHardwareBuffer()); + const jint namedColorSpace = + fromDataspaceToNamedColorSpaceValue(captureResults.capturedDataspace); return env->CallStaticObjectMethod(gScreenshotHardwareBufferClassInfo.clazz, gScreenshotHardwareBufferClassInfo.builder, jhardwareBuffer, - namedColorSpace, capturedSecureLayers); + namedColorSpace, captureResults.capturedSecureLayers); } -static jobject nativeCaptureLayers(JNIEnv* env, jclass clazz, jobject displayTokenObj, - jlong layerObject, jobject sourceCropObj, jfloat frameScale, - jlongArray excludeObjectArray, jint format) { - - auto layer = reinterpret_cast<SurfaceControl *>(layerObject); - if (layer == NULL) { - return NULL; - } - - Rect sourceCrop; - if (sourceCropObj != NULL) { - sourceCrop = rectFromObj(env, sourceCropObj); +static jobject nativeCaptureLayers(JNIEnv* env, jclass clazz, jobject layerCaptureArgsObject) { + LayerCaptureArgs captureArgs; + getCaptureArgs(env, layerCaptureArgsObject, captureArgs); + SurfaceControl* layer = reinterpret_cast<SurfaceControl*>( + env->GetLongField(layerCaptureArgsObject, gLayerCaptureArgsClassInfo.layer)); + if (layer == nullptr) { + return nullptr; } - std::unordered_set<sp<IBinder>,ISurfaceComposer::SpHash<IBinder>> excludeHandles; + captureArgs.layerHandle = layer->getHandle(); + captureArgs.childrenOnly = + env->GetBooleanField(layerCaptureArgsObject, gLayerCaptureArgsClassInfo.childrenOnly); + jlongArray excludeObjectArray = reinterpret_cast<jlongArray>( + env->GetObjectField(layerCaptureArgsObject, gLayerCaptureArgsClassInfo.excludeLayers)); if (excludeObjectArray != NULL) { const jsize len = env->GetArrayLength(excludeObjectArray); - excludeHandles.reserve(len); + captureArgs.excludeHandles.reserve(len); const jlong* objects = env->GetLongArrayElements(excludeObjectArray, nullptr); for (jsize i = 0; i < len; i++) { @@ -333,33 +378,24 @@ static jobject nativeCaptureLayers(JNIEnv* env, jclass clazz, jobject displayTok jniThrowNullPointerException(env, "Exclude layer is null"); return NULL; } - excludeHandles.emplace(excludeObject->getHandle()); + captureArgs.excludeHandles.emplace(excludeObject->getHandle()); } env->ReleaseLongArrayElements(excludeObjectArray, const_cast<jlong*>(objects), JNI_ABORT); } - sp<GraphicBuffer> buffer; - ui::Dataspace dataspace = ui::Dataspace::V0_SRGB; - sp<IBinder> displayToken = ibinderForJavaObject(env, displayTokenObj); - if (displayToken != nullptr) { - const ui::ColorMode colorMode = SurfaceComposerClient::getActiveColorMode(displayToken); - dataspace = pickDataspaceFromColorMode(colorMode); - } - status_t res = ScreenshotClient::captureChildLayers(layer->getHandle(), dataspace, - static_cast<ui::PixelFormat>(format), - sourceCrop, excludeHandles, frameScale, - &buffer); + ScreenCaptureResults captureResults; + status_t res = ScreenshotClient::captureLayers(captureArgs, captureResults); if (res != NO_ERROR) { return NULL; } - jobject jhardwareBuffer = - android_hardware_HardwareBuffer_createFromAHardwareBuffer(env, - buffer->toAHardwareBuffer()); - const jint namedColorSpace = fromDataspaceToNamedColorSpaceValue(dataspace); + jobject jhardwareBuffer = android_hardware_HardwareBuffer_createFromAHardwareBuffer( + env, captureResults.buffer->toAHardwareBuffer()); + const jint namedColorSpace = + fromDataspaceToNamedColorSpaceValue(captureResults.capturedDataspace); return env->CallStaticObjectMethod(gScreenshotHardwareBufferClassInfo.clazz, gScreenshotHardwareBufferClassInfo.builder, jhardwareBuffer, - namedColorSpace, false /* capturedSecureLayers */); + namedColorSpace, captureResults.capturedSecureLayers); } static void nativeApplyTransaction(JNIEnv* env, jclass clazz, jlong transactionObj, jboolean sync) { @@ -1614,13 +1650,12 @@ static const JNINativeMethod sSurfaceControlMethods[] = { (void*)nativeSeverChildren } , {"nativeSetOverrideScalingMode", "(JJI)V", (void*)nativeSetOverrideScalingMode }, - {"nativeScreenshot", - "(Landroid/os/IBinder;Landroid/graphics/Rect;IIZIZ)" + {"nativeCaptureDisplay", + "(Landroid/view/SurfaceControl$DisplayCaptureArgs;)" "Landroid/view/SurfaceControl$ScreenshotHardwareBuffer;", - (void*)nativeScreenshot }, + (void*)nativeCaptureDisplay }, {"nativeCaptureLayers", - "(Landroid/os/IBinder;JLandroid/graphics/Rect;" - "F[JI)" + "(Landroid/view/SurfaceControl$LayerCaptureArgs;)" "Landroid/view/SurfaceControl$ScreenshotHardwareBuffer;", (void*)nativeCaptureLayers }, {"nativeSetInputWindowInfo", "(JJLandroid/view/InputWindowHandle;)V", @@ -1795,6 +1830,36 @@ int register_android_view_SurfaceControl(JNIEnv* env) gDesiredDisplayConfigSpecsClassInfo.appRequestRefreshRateMax = GetFieldIDOrDie(env, desiredDisplayConfigSpecsClazz, "appRequestRefreshRateMax", "F"); + jclass captureArgsClazz = FindClassOrDie(env, "android/view/SurfaceControl$CaptureArgs"); + gCaptureArgsClassInfo.pixelFormat = GetFieldIDOrDie(env, captureArgsClazz, "mPixelFormat", "I"); + gCaptureArgsClassInfo.sourceCrop = + GetFieldIDOrDie(env, captureArgsClazz, "mSourceCrop", "Landroid/graphics/Rect;"); + gCaptureArgsClassInfo.frameScale = GetFieldIDOrDie(env, captureArgsClazz, "mFrameScale", "F"); + gCaptureArgsClassInfo.captureSecureLayers = + GetFieldIDOrDie(env, captureArgsClazz, "mCaptureSecureLayers", "Z"); + + jclass displayCaptureArgsClazz = + FindClassOrDie(env, "android/view/SurfaceControl$DisplayCaptureArgs"); + gDisplayCaptureArgsClassInfo.displayToken = + GetFieldIDOrDie(env, displayCaptureArgsClazz, "mDisplayToken", "Landroid/os/IBinder;"); + gDisplayCaptureArgsClassInfo.width = + GetFieldIDOrDie(env, displayCaptureArgsClazz, "mWidth", "I"); + gDisplayCaptureArgsClassInfo.height = + GetFieldIDOrDie(env, displayCaptureArgsClazz, "mHeight", "I"); + gDisplayCaptureArgsClassInfo.useIdentityTransform = + GetFieldIDOrDie(env, displayCaptureArgsClazz, "mUseIdentityTransform", "Z"); + gDisplayCaptureArgsClassInfo.rotation = + GetFieldIDOrDie(env, displayCaptureArgsClazz, "mRotation", "I"); + + jclass layerCaptureArgsClazz = + FindClassOrDie(env, "android/view/SurfaceControl$LayerCaptureArgs"); + gLayerCaptureArgsClassInfo.layer = + GetFieldIDOrDie(env, layerCaptureArgsClazz, "mNativeLayer", "J"); + gLayerCaptureArgsClassInfo.excludeLayers = + GetFieldIDOrDie(env, layerCaptureArgsClazz, "mNativeExcludeLayers", "[J"); + gLayerCaptureArgsClassInfo.childrenOnly = + GetFieldIDOrDie(env, layerCaptureArgsClazz, "mChildrenOnly", "Z"); + return err; } diff --git a/data/keyboards/Generic.kl b/data/keyboards/Generic.kl index 4cdfbb8ce27f..5711f98e3b75 100644 --- a/data/keyboards/Generic.kl +++ b/data/keyboards/Generic.kl @@ -415,6 +415,7 @@ key 583 ASSIST key usage 0x0c0067 WINDOW key usage 0x0c006F BRIGHTNESS_UP key usage 0x0c0070 BRIGHTNESS_DOWN +key usage 0x0c0173 MEDIA_AUDIO_TRACK # Joystick and game controller axes. # Axes that are not mapped will be assigned generic axis numbers by the input subsystem. diff --git a/location/java/android/location/GnssAntennaInfo.java b/location/java/android/location/GnssAntennaInfo.java index b2f9a0f41b7e..23977f18f749 100644 --- a/location/java/android/location/GnssAntennaInfo.java +++ b/location/java/android/location/GnssAntennaInfo.java @@ -53,7 +53,7 @@ public final class GnssAntennaInfo implements Parcelable { * Class containing information about the antenna phase center offset (PCO). PCO is defined with * respect to the origin of the Android sensor coordinate system, e.g., center of primary screen * for mobiles - see sensor or form factor documents for details. Uncertainties are reported - * to 1-sigma. + * to 1-sigma. */ public static final class PhaseCenterOffset implements Parcelable { private final double mOffsetXMm; @@ -95,31 +95,55 @@ public final class GnssAntennaInfo implements Parcelable { } }; + /** + * Returns the x-axis offset of the phase center from the origin of the Android sensor + * coordinate system, in millimeters. + */ @FloatRange() public double getXOffsetMm() { return mOffsetXMm; } + /** + * Returns the 1-sigma uncertainty of the x-axis offset of the phase center from the origin + * of the Android sensor coordinate system, in millimeters. + */ @FloatRange() public double getXOffsetUncertaintyMm() { return mOffsetXUncertaintyMm; } + /** + * Returns the y-axis offset of the phase center from the origin of the Android sensor + * coordinate system, in millimeters. + */ @FloatRange() public double getYOffsetMm() { return mOffsetYMm; } + /** + * Returns the 1-sigma uncertainty of the y-axis offset of the phase center from the origin + * of the Android sensor coordinate system, in millimeters. + */ @FloatRange() public double getYOffsetUncertaintyMm() { return mOffsetYUncertaintyMm; } + /** + * Returns the z-axis offset of the phase center from the origin of the Android sensor + * coordinate system, in millimeters. + */ @FloatRange() public double getZOffsetMm() { return mOffsetZMm; } + /** + * Returns the 1-sigma uncertainty of the z-axis offset of the phase center from the origin + * of the Android sensor coordinate system, in millimeters. + */ @FloatRange() public double getZOffsetUncertaintyMm() { return mOffsetZUncertaintyMm; @@ -165,7 +189,7 @@ public final class GnssAntennaInfo implements Parcelable { * at 180 degrees. They are separated by deltaPhi, the regular spacing between zenith angles, * i.e., deltaPhi = 180 / (number of columns - 1). */ - public static final class SphericalCorrections implements Parcelable{ + public static final class SphericalCorrections implements Parcelable { private final double[][] mCorrections; private final double[][] mCorrectionUncertainties; private final double mDeltaTheta; @@ -296,10 +320,10 @@ public final class GnssAntennaInfo implements Parcelable { public void writeToParcel(@NonNull Parcel dest, int flags) { dest.writeInt(mNumRows); dest.writeInt(mNumColumns); - for (double[] row: mCorrections) { + for (double[] row : mCorrections) { dest.writeDoubleArray(row); } - for (double[] row: mCorrectionUncertainties) { + for (double[] row : mCorrectionUncertainties) { dest.writeDoubleArray(row); } } @@ -340,6 +364,7 @@ public final class GnssAntennaInfo implements Parcelable { /** * Set antenna carrier frequency (MHz). + * * @param carrierFrequencyMHz antenna carrier frequency (MHz) * @return Builder builder object */ @@ -351,6 +376,7 @@ public final class GnssAntennaInfo implements Parcelable { /** * Set antenna phase center offset. + * * @param phaseCenterOffset phase center offset object * @return Builder builder object */ @@ -362,6 +388,7 @@ public final class GnssAntennaInfo implements Parcelable { /** * Set phase center variation corrections. + * * @param phaseCenterVariationCorrections phase center variation corrections object * @return Builder builder object */ @@ -374,6 +401,7 @@ public final class GnssAntennaInfo implements Parcelable { /** * Set signal gain corrections. + * * @param signalGainCorrections signal gain corrections object * @return Builder builder object */ @@ -386,6 +414,7 @@ public final class GnssAntennaInfo implements Parcelable { /** * Build GnssAntennaInfo object. + * * @return instance of GnssAntennaInfo */ @NonNull @@ -400,47 +429,65 @@ public final class GnssAntennaInfo implements Parcelable { return mCarrierFrequencyMHz; } + /** + * Returns a {@link PhaseCenterOffset} object encapsulating the phase center offset and + * corresponding uncertainties in millimeters. + * + * @return {@link PhaseCenterOffset} + */ @NonNull public PhaseCenterOffset getPhaseCenterOffset() { return mPhaseCenterOffset; } + /** + * Returns a {@link SphericalCorrections} object encapsulating the phase center variation + * corrections and corresponding uncertainties in millimeters. + * + * @return phase center variation corrections as {@link SphericalCorrections} + */ @Nullable public SphericalCorrections getPhaseCenterVariationCorrections() { return mPhaseCenterVariationCorrections; } + /** + * Returns a {@link SphericalCorrections} object encapsulating the signal gain + * corrections and corresponding uncertainties in dBi. + * + * @return signal gain corrections as {@link SphericalCorrections} + */ @Nullable public SphericalCorrections getSignalGainCorrections() { return mSignalGainCorrections; } - public static final @android.annotation.NonNull - Creator<GnssAntennaInfo> CREATOR = new Creator<GnssAntennaInfo>() { - @Override - public GnssAntennaInfo createFromParcel(Parcel in) { - double carrierFrequencyMHz = in.readDouble(); - - ClassLoader classLoader = getClass().getClassLoader(); - PhaseCenterOffset phaseCenterOffset = - in.readParcelable(classLoader); - SphericalCorrections phaseCenterVariationCorrections = - in.readParcelable(classLoader); - SphericalCorrections signalGainCorrections = - in.readParcelable(classLoader); - - return new GnssAntennaInfo( - carrierFrequencyMHz, - phaseCenterOffset, - phaseCenterVariationCorrections, - signalGainCorrections); - } - - @Override - public GnssAntennaInfo[] newArray(int size) { - return new GnssAntennaInfo[size]; - } - }; + public static final @android.annotation.NonNull Creator<GnssAntennaInfo> CREATOR = + new Creator<GnssAntennaInfo>() { + @Override + public GnssAntennaInfo createFromParcel(Parcel in) { + double carrierFrequencyMHz = in.readDouble(); + + ClassLoader classLoader = getClass().getClassLoader(); + PhaseCenterOffset phaseCenterOffset = + in.readParcelable(classLoader); + SphericalCorrections phaseCenterVariationCorrections = + in.readParcelable(classLoader); + SphericalCorrections signalGainCorrections = + in.readParcelable(classLoader); + + return new GnssAntennaInfo( + carrierFrequencyMHz, + phaseCenterOffset, + phaseCenterVariationCorrections, + signalGainCorrections); + } + + @Override + public GnssAntennaInfo[] newArray(int size) { + return new GnssAntennaInfo[size]; + } + }; @Override public int describeContents() { diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java index 4c03fd10f248..c6fb3ef8f694 100755 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -6201,6 +6201,24 @@ public class AudioManager { } } + + /** + * Retrieves the Hardware A/V synchronization ID corresponding to the given audio session ID. + * For more details on Hardware A/V synchronization please refer to + * <a href="https://source.android.com/devices/tv/multimedia-tunneling/"> + * media tunneling documentation</a>. + * @param sessionId the audio session ID for which the HW A/V sync ID is retrieved. + * @return the HW A/V sync ID for this audio session (an integer different from 0). + * @throws UnsupportedOperationException if HW A/V synchronization is not supported. + */ + public int getAudioHwSyncForSession(int sessionId) { + int hwSyncId = AudioSystem.getAudioHwSyncForSession(sessionId); + if (hwSyncId == AudioSystem.AUDIO_HW_SYNC_INVALID) { + throw new UnsupportedOperationException("HW A/V synchronization is not supported."); + } + return hwSyncId; + } + //--------------------------------------------------------- // Inner classes //-------------------- diff --git a/media/jni/audioeffect/Visualizer.cpp b/media/jni/audioeffect/Visualizer.cpp index f4d65d0a397f..a74ae5307a36 100644 --- a/media/jni/audioeffect/Visualizer.cpp +++ b/media/jni/audioeffect/Visualizer.cpp @@ -34,21 +34,9 @@ namespace android { // --------------------------------------------------------------------------- -Visualizer::Visualizer (const String16& opPackageName, - int32_t priority, - effect_callback_t cbf, - void* user, - audio_session_t sessionId) - : AudioEffect(SL_IID_VISUALIZATION, opPackageName, NULL, priority, cbf, user, sessionId), - mCaptureRate(CAPTURE_RATE_DEF), - mCaptureSize(CAPTURE_SIZE_DEF), - mSampleRate(44100000), - mScalingMode(VISUALIZER_SCALING_MODE_NORMALIZED), - mMeasurementMode(MEASUREMENT_MODE_NONE), - mCaptureCallBack(NULL), - mCaptureCbkUser(NULL) +Visualizer::Visualizer (const String16& opPackageName) + : AudioEffect(opPackageName) { - initCaptureSize(); } Visualizer::~Visualizer() @@ -58,6 +46,23 @@ Visualizer::~Visualizer() setCaptureCallBack(NULL, NULL, 0, 0); } +status_t Visualizer::set(int32_t priority, + effect_callback_t cbf, + void* user, + audio_session_t sessionId, + audio_io_handle_t io, + const AudioDeviceTypeAddr& device, + bool probe) +{ + status_t status = AudioEffect::set( + SL_IID_VISUALIZATION, nullptr, priority, cbf, user, sessionId, io, device, probe); + if (status == NO_ERROR || status == ALREADY_EXISTS) { + initCaptureSize(); + } + return status; +} + + void Visualizer::release() { ALOGV("Visualizer::release()"); diff --git a/media/jni/audioeffect/Visualizer.h b/media/jni/audioeffect/Visualizer.h index d4672a95c6d8..8b6a62f25638 100644 --- a/media/jni/audioeffect/Visualizer.h +++ b/media/jni/audioeffect/Visualizer.h @@ -65,14 +65,22 @@ public: /* Constructor. * See AudioEffect constructor for details on parameters. */ - Visualizer(const String16& opPackageName, - int32_t priority = 0, - effect_callback_t cbf = NULL, - void* user = NULL, - audio_session_t sessionId = AUDIO_SESSION_OUTPUT_MIX); + explicit Visualizer(const String16& opPackageName); ~Visualizer(); + /** + * Initialize an uninitialized Visualizer. + * See AudioEffect 'set' function for details on parameters. + */ + status_t set(int32_t priority = 0, + effect_callback_t cbf = NULL, + void* user = NULL, + audio_session_t sessionId = AUDIO_SESSION_OUTPUT_MIX, + audio_io_handle_t io = AUDIO_IO_HANDLE_NONE, + const AudioDeviceTypeAddr& device = {}, + bool probe = false); + // Declared 'final' because we call this in ~Visualizer(). status_t setEnabled(bool enabled) final; @@ -163,15 +171,15 @@ private: uint32_t initCaptureSize(); Mutex mCaptureLock; - uint32_t mCaptureRate; - uint32_t mCaptureSize; - uint32_t mSampleRate; - uint32_t mScalingMode; - uint32_t mMeasurementMode; - capture_cbk_t mCaptureCallBack; - void *mCaptureCbkUser; + uint32_t mCaptureRate = CAPTURE_RATE_DEF; + uint32_t mCaptureSize = CAPTURE_SIZE_DEF; + uint32_t mSampleRate = 44100000; + uint32_t mScalingMode = VISUALIZER_SCALING_MODE_NORMALIZED; + uint32_t mMeasurementMode = MEASUREMENT_MODE_NONE; + capture_cbk_t mCaptureCallBack = nullptr; + void *mCaptureCbkUser = nullptr; sp<CaptureThread> mCaptureThread; - uint32_t mCaptureFlags; + uint32_t mCaptureFlags = 0; }; diff --git a/media/jni/audioeffect/android_media_AudioEffect.cpp b/media/jni/audioeffect/android_media_AudioEffect.cpp index dbe7b4b619c9..96961ac21a2d 100644 --- a/media/jni/audioeffect/android_media_AudioEffect.cpp +++ b/media/jni/audioeffect/android_media_AudioEffect.cpp @@ -337,22 +337,21 @@ android_media_AudioEffect_native_setup(JNIEnv *env, jobject thiz, jobject weak_t } // create the native AudioEffect object - lpAudioEffect = new AudioEffect(typeStr, - String16(opPackageNameStr.c_str()), - uuidStr, - priority, - effectCallback, - &lpJniStorage->mCallbackData, - (audio_session_t) sessionId, - AUDIO_IO_HANDLE_NONE, - device, - probe); + lpAudioEffect = new AudioEffect(String16(opPackageNameStr.c_str())); if (lpAudioEffect == 0) { ALOGE("Error creating AudioEffect"); goto setup_failure; } - + lpAudioEffect->set(typeStr, + uuidStr, + priority, + effectCallback, + &lpJniStorage->mCallbackData, + (audio_session_t) sessionId, + AUDIO_IO_HANDLE_NONE, + device, + probe); lStatus = AudioEffectJni::translateNativeErrorToJava(lpAudioEffect->initCheck()); if (lStatus != AUDIOEFFECT_SUCCESS && lStatus != AUDIOEFFECT_ERROR_ALREADY_EXISTS) { ALOGE("AudioEffect initCheck failed %d", lStatus); diff --git a/media/jni/audioeffect/android_media_Visualizer.cpp b/media/jni/audioeffect/android_media_Visualizer.cpp index f9a77f474c50..4c5970a30a05 100644 --- a/media/jni/audioeffect/android_media_Visualizer.cpp +++ b/media/jni/audioeffect/android_media_Visualizer.cpp @@ -382,15 +382,15 @@ android_media_visualizer_native_setup(JNIEnv *env, jobject thiz, jobject weak_th } // create the native Visualizer object - lpVisualizer = new Visualizer(String16(opPackageNameStr.c_str()), - 0, - android_media_visualizer_effect_callback, - lpJniStorage, - (audio_session_t) sessionId); + lpVisualizer = new Visualizer(String16(opPackageNameStr.c_str())); if (lpVisualizer == 0) { ALOGE("Error creating Visualizer"); goto setup_failure; } + lpVisualizer->set(0, + android_media_visualizer_effect_callback, + lpJniStorage, + (audio_session_t) sessionId); lStatus = translateError(lpVisualizer->initCheck()); if (lStatus != VISUALIZER_SUCCESS && lStatus != VISUALIZER_ERROR_ALREADY_EXISTS) { diff --git a/non-updatable-api/current.txt b/non-updatable-api/current.txt index 5aaca435e71e..54618a5da3a3 100644 --- a/non-updatable-api/current.txt +++ b/non-updatable-api/current.txt @@ -24189,6 +24189,7 @@ package android.media { method @NonNull public java.util.List<android.media.AudioPlaybackConfiguration> getActivePlaybackConfigurations(); method @NonNull public java.util.List<android.media.AudioRecordingConfiguration> getActiveRecordingConfigurations(); method public int getAllowedCapturePolicy(); + method public int getAudioHwSyncForSession(int); method public android.media.AudioDeviceInfo[] getDevices(int); method public java.util.List<android.media.MicrophoneInfo> getMicrophones() throws java.io.IOException; method public int getMode(); @@ -46014,6 +46015,7 @@ package android.telephony { method @Nullable public android.net.LinkProperties getLinkProperties(); method public int getNetworkType(); method public int getState(); + method public int getTransportType(); method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.telephony.PreciseDataConnectionState> CREATOR; } diff --git a/non-updatable-api/system-current.txt b/non-updatable-api/system-current.txt index 222e563d4f96..385ae278975c 100644 --- a/non-updatable-api/system-current.txt +++ b/non-updatable-api/system-current.txt @@ -9706,6 +9706,7 @@ package android.telephony { method @Deprecated public int getDataConnectionApnTypeBitMask(); method @Deprecated public int getDataConnectionFailCause(); method @Deprecated public int getDataConnectionState(); + method public int getId(); } public final class PreciseDisconnectCause { diff --git a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java index 995a3ecde6c1..f4e704ea373e 100644 --- a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java +++ b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java @@ -38,6 +38,8 @@ import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.dock.DockManager; import com.android.systemui.dock.DockManagerImpl; import com.android.systemui.doze.DozeHost; +import com.android.systemui.pip.phone.PipMenuActivity; +import com.android.systemui.pip.phone.dagger.PipMenuActivityClass; import com.android.systemui.plugins.qs.QSFactory; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.power.EnhancedEstimates; @@ -142,6 +144,13 @@ public abstract class CarSystemUIModule { mainHandler, transactionPool).build(); } + @Singleton + @PipMenuActivityClass + @Provides + static Class<?> providePipMenuActivityClass() { + return PipMenuActivity.class; + } + @Binds abstract HeadsUpManager bindHeadsUpManagerPhone(HeadsUpManagerPhone headsUpManagerPhone); diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java index bcaee367b03c..f108e06951ef 100644 --- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java +++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java @@ -259,18 +259,19 @@ public class DeviceDiscoveryService extends Service { private void onDeviceFound(@Nullable DeviceFilterPair device) { if (device == null) return; - if (mDevicesFound.contains(device)) { - return; - } - - if (DEBUG) Log.i(LOG_TAG, "Found device " + device); - Handler.getMain().sendMessage(obtainMessage( DeviceDiscoveryService::onDeviceFoundMainThread, this, device)); } @MainThread void onDeviceFoundMainThread(@NonNull DeviceFilterPair device) { + if (mDevicesFound.contains(device)) { + Log.i(LOG_TAG, "Skipping device " + device + " - already among found devices"); + return; + } + + Log.i(LOG_TAG, "Found device " + device); + if (mDevicesFound.isEmpty()) { onReadyToShowUI(); } @@ -428,10 +429,10 @@ public class DeviceDiscoveryService extends Service { @Override public String toString() { - return "DeviceFilterPair{" + - "device=" + device + - ", filter=" + filter + - '}'; + return "DeviceFilterPair{" + + "device=" + device + " " + getDisplayName() + + ", filter=" + filter + + '}'; } } diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java index 18c2957b1adc..4eea8ad92e61 100644 --- a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java +++ b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java @@ -112,7 +112,6 @@ public class SecureSettings { Settings.Secure.FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION, Settings.Secure.VR_DISPLAY_MODE, Settings.Secure.NOTIFICATION_BADGING, - Settings.Secure.NOTIFICATION_FEEDBACK_ENABLED, Settings.Secure.NOTIFICATION_DISMISS_RTL, Settings.Secure.QS_AUTO_ADDED_TILES, Settings.Secure.SCREENSAVER_ENABLED, diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java index dd94d2eb8fe0..a02d67fd7bca 100644 --- a/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java +++ b/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java @@ -149,5 +149,6 @@ public class GlobalSettingsValidators { VALIDATORS.put(Global.CUSTOM_BUGREPORT_HANDLER_APP, ANY_STRING_VALIDATOR); VALIDATORS.put(Global.CUSTOM_BUGREPORT_HANDLER_USER, ANY_INTEGER_VALIDATOR); VALIDATORS.put(Global.DEVELOPMENT_SETTINGS_ENABLED, BOOLEAN_VALIDATOR); + VALIDATORS.put(Global.NOTIFICATION_FEEDBACK_ENABLED, BOOLEAN_VALIDATOR); } } diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java index 91f3f4af0566..c68ddbdcb5ad 100644 --- a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java +++ b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java @@ -189,7 +189,6 @@ public class SecureSettingsValidators { VALIDATORS.put(Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS, BOOLEAN_VALIDATOR); VALIDATORS.put(Secure.SHOW_NOTIFICATION_SNOOZE, BOOLEAN_VALIDATOR); VALIDATORS.put(Secure.NOTIFICATION_HISTORY_ENABLED, BOOLEAN_VALIDATOR); - VALIDATORS.put(Secure.NOTIFICATION_FEEDBACK_ENABLED, BOOLEAN_VALIDATOR); VALIDATORS.put(Secure.ZEN_DURATION, ANY_INTEGER_VALIDATOR); VALIDATORS.put(Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, BOOLEAN_VALIDATOR); VALIDATORS.put(Secure.SHOW_ZEN_SETTINGS_SUGGESTION, BOOLEAN_VALIDATOR); diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java index 24f8104570db..4bb8f45f331f 100644 --- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java +++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java @@ -389,6 +389,7 @@ public class SettingsBackupTest { Settings.Global.NITZ_UPDATE_DIFF, Settings.Global.NITZ_UPDATE_SPACING, Settings.Global.NOTIFICATION_SNOOZE_OPTIONS, + Settings.Global.NOTIFICATION_FEEDBACK_ENABLED, Settings.Global.NR_NSA_TRACKING_SCREEN_OFF_MODE, Settings.Global.NSD_ON, Settings.Global.NTP_SERVER, diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIRootComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIRootComponent.java index 900c11f0830e..9fdbb6daca51 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIRootComponent.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIRootComponent.java @@ -29,7 +29,6 @@ import com.android.systemui.dump.DumpManager; import com.android.systemui.fragments.FragmentService; import com.android.systemui.keyguard.KeyguardSliceProvider; import com.android.systemui.onehanded.dagger.OneHandedModule; -import com.android.systemui.pip.phone.PipMenuActivity; import com.android.systemui.pip.phone.dagger.PipModule; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.util.InjectionInflationController; @@ -133,9 +132,4 @@ public interface SystemUIRootComponent { * Member injection into the supplied argument. */ void inject(KeyguardSliceProvider keyguardSliceProvider); - - /** - * Member injection into the supplied argument. - */ - void inject(PipMenuActivity pipMenuActivity); } diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipAnimationController.java b/packages/SystemUI/src/com/android/systemui/pip/PipAnimationController.java index 72019315139b..4931388fe362 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/PipAnimationController.java +++ b/packages/SystemUI/src/com/android/systemui/pip/PipAnimationController.java @@ -53,16 +53,16 @@ public class PipAnimationController { public static final int TRANSITION_DIRECTION_NONE = 0; public static final int TRANSITION_DIRECTION_SAME = 1; public static final int TRANSITION_DIRECTION_TO_PIP = 2; - public static final int TRANSITION_DIRECTION_TO_FULLSCREEN = 3; - public static final int TRANSITION_DIRECTION_TO_SPLIT_SCREEN = 4; + public static final int TRANSITION_DIRECTION_LEAVE_PIP = 3; + public static final int TRANSITION_DIRECTION_LEAVE_PIP_TO_SPLIT_SCREEN = 4; public static final int TRANSITION_DIRECTION_REMOVE_STACK = 5; @IntDef(prefix = { "TRANSITION_DIRECTION_" }, value = { TRANSITION_DIRECTION_NONE, TRANSITION_DIRECTION_SAME, TRANSITION_DIRECTION_TO_PIP, - TRANSITION_DIRECTION_TO_FULLSCREEN, - TRANSITION_DIRECTION_TO_SPLIT_SCREEN, + TRANSITION_DIRECTION_LEAVE_PIP, + TRANSITION_DIRECTION_LEAVE_PIP_TO_SPLIT_SCREEN, TRANSITION_DIRECTION_REMOVE_STACK }) @Retention(RetentionPolicy.SOURCE) @@ -73,8 +73,8 @@ public class PipAnimationController { } public static boolean isOutPipDirection(@TransitionDirection int direction) { - return direction == TRANSITION_DIRECTION_TO_FULLSCREEN - || direction == TRANSITION_DIRECTION_TO_SPLIT_SCREEN; + return direction == TRANSITION_DIRECTION_LEAVE_PIP + || direction == TRANSITION_DIRECTION_LEAVE_PIP_TO_SPLIT_SCREEN; } private final PipSurfaceTransactionHelper mSurfaceTransactionHelper; diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java index 312d6d62128f..7c3743bd8bcf 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java +++ b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java @@ -23,12 +23,12 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static com.android.systemui.pip.PipAnimationController.ANIM_TYPE_ALPHA; import static com.android.systemui.pip.PipAnimationController.ANIM_TYPE_BOUNDS; +import static com.android.systemui.pip.PipAnimationController.TRANSITION_DIRECTION_LEAVE_PIP; +import static com.android.systemui.pip.PipAnimationController.TRANSITION_DIRECTION_LEAVE_PIP_TO_SPLIT_SCREEN; import static com.android.systemui.pip.PipAnimationController.TRANSITION_DIRECTION_NONE; import static com.android.systemui.pip.PipAnimationController.TRANSITION_DIRECTION_REMOVE_STACK; import static com.android.systemui.pip.PipAnimationController.TRANSITION_DIRECTION_SAME; -import static com.android.systemui.pip.PipAnimationController.TRANSITION_DIRECTION_TO_FULLSCREEN; import static com.android.systemui.pip.PipAnimationController.TRANSITION_DIRECTION_TO_PIP; -import static com.android.systemui.pip.PipAnimationController.TRANSITION_DIRECTION_TO_SPLIT_SCREEN; import static com.android.systemui.pip.PipAnimationController.isInPipDirection; import static com.android.systemui.pip.PipAnimationController.isOutPipDirection; @@ -285,8 +285,8 @@ public class PipTaskOrganizer extends TaskOrganizer implements final WindowContainerTransaction wct = new WindowContainerTransaction(); final Rect destinationBounds = initialConfig.windowConfiguration.getBounds(); final int direction = syncWithSplitScreenBounds(destinationBounds) - ? TRANSITION_DIRECTION_TO_SPLIT_SCREEN - : TRANSITION_DIRECTION_TO_FULLSCREEN; + ? TRANSITION_DIRECTION_LEAVE_PIP_TO_SPLIT_SCREEN + : TRANSITION_DIRECTION_LEAVE_PIP; if (orientationDiffers) { // Send started callback though animation is ignored. sendOnPipTransitionStarted(direction); @@ -303,7 +303,10 @@ public class PipTaskOrganizer extends TaskOrganizer implements mSurfaceTransactionHelper.scale(tx, mLeash, destinationBounds, mLastReportedBounds); tx.setWindowCrop(mLeash, destinationBounds.width(), destinationBounds.height()); - wct.setActivityWindowingMode(mToken, direction == TRANSITION_DIRECTION_TO_SPLIT_SCREEN + // We set to fullscreen here for now, but later it will be set to UNDEFINED for + // the proper windowing mode to take place. See #applyWindowingModeChangeOnExit. + wct.setActivityWindowingMode(mToken, + direction == TRANSITION_DIRECTION_LEAVE_PIP_TO_SPLIT_SCREEN ? WINDOWING_MODE_SPLIT_SCREEN_SECONDARY : WINDOWING_MODE_FULLSCREEN); wct.setBounds(mToken, destinationBounds); @@ -327,7 +330,7 @@ public class PipTaskOrganizer extends TaskOrganizer implements wct.setWindowingMode(mToken, getOutPipWindowingMode()); // Simply reset the activity mode set prior to the animation running. wct.setActivityWindowingMode(mToken, WINDOWING_MODE_UNDEFINED); - if (mSplitDivider != null && direction == TRANSITION_DIRECTION_TO_SPLIT_SCREEN) { + if (mSplitDivider != null && direction == TRANSITION_DIRECTION_LEAVE_PIP_TO_SPLIT_SCREEN) { wct.reparent(mToken, mSplitDivider.getSecondaryRoot(), true /* onTop */); } } @@ -842,7 +845,7 @@ public class PipTaskOrganizer extends TaskOrganizer implements } else if (isOutPipDirection(direction)) { // If we are animating to fullscreen, then we need to reset the override bounds // on the task to ensure that the task "matches" the parent's bounds. - taskBounds = (direction == TRANSITION_DIRECTION_TO_FULLSCREEN) + taskBounds = (direction == TRANSITION_DIRECTION_LEAVE_PIP) ? null : destinationBounds; applyWindowingModeChangeOnExit(wct, direction); } else { diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipAccessibilityInteractionConnection.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipAccessibilityInteractionConnection.java index c715398d52da..a13318990f40 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipAccessibilityInteractionConnection.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipAccessibilityInteractionConnection.java @@ -131,7 +131,7 @@ public class PipAccessibilityInteractionConnection result = true; break; case AccessibilityNodeInfo.ACTION_EXPAND: - mMotionHelper.expandPipToFullscreen(); + mMotionHelper.expandLeavePip(); result = true; break; default: diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java index 582cd046f9e0..6e75253d8604 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java @@ -47,6 +47,7 @@ import com.android.systemui.pip.BasePipManager; import com.android.systemui.pip.PipBoundsHandler; import com.android.systemui.pip.PipSnapAlgorithm; import com.android.systemui.pip.PipTaskOrganizer; +import com.android.systemui.pip.phone.dagger.PipMenuActivityClass; import com.android.systemui.shared.recents.IPinnedStackAnimationListener; import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.shared.system.InputConsumerController; @@ -181,7 +182,7 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio != WINDOWING_MODE_PINNED) { return; } - mTouchHandler.getMotionHelper().expandPipToFullscreen(clearedTask /* skipAnimation */); + mTouchHandler.getMotionHelper().expandLeavePip(clearedTask /* skipAnimation */); } }; @@ -250,6 +251,7 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio @Inject public PipManager(Context context, BroadcastDispatcher broadcastDispatcher, + @PipMenuActivityClass Class<?> pipMenuActivityClass, DisplayController displayController, FloatingContentCoordinator floatingContentCoordinator, DeviceConfigProxy deviceConfig, @@ -274,8 +276,8 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio mPipTaskOrganizer.registerPipTransitionCallback(this); mInputConsumerController = InputConsumerController.getPipInputConsumer(); mMediaController = new PipMediaController(context, mActivityManager, broadcastDispatcher); - mMenuController = new PipMenuActivityController(context, mMediaController, - mInputConsumerController); + mMenuController = new PipMenuActivityController(context, pipMenuActivityClass, + mMediaController, mInputConsumerController); mTouchHandler = new PipTouchHandler(context, mActivityManager, mMenuController, mInputConsumerController, mPipBoundsHandler, mPipTaskOrganizer, floatingContentCoordinator, deviceConfig, pipSnapAlgorithm, sysUiState); @@ -318,7 +320,7 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio */ @Override public void expandPip() { - mTouchHandler.getMotionHelper().expandPipToFullscreen(false /* skipAnimation */); + mTouchHandler.getMotionHelper().expandLeavePip(false /* skipAnimation */); } /** diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java index d6f3e163ad70..1b1b2de05883 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java @@ -76,17 +76,15 @@ import android.widget.ImageButton; import android.widget.LinearLayout; import com.android.systemui.Interpolators; -import com.android.systemui.SystemUIFactory; import com.android.wm.shell.R; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import javax.inject.Inject; - /** * Translucent activity that gets started on top of a task in PIP to allow the user to control it. + * TODO(b/150319024): PipMenuActivity will move to a Window */ public class PipMenuActivity extends Activity { @@ -126,19 +124,11 @@ public class PipMenuActivity extends Activity { private final List<RemoteAction> mActions = new ArrayList<>(); private AccessibilityManager mAccessibilityManager; - private View mViewRoot; private Drawable mBackgroundDrawable; private View mMenuContainer; private LinearLayout mActionsGroup; - private View mSettingsButton; - private View mDismissButton; - private View mResizeHandle; - private View mTopEndContainer; private int mBetweenActionPaddingLand; - @Inject - PipMenuIconsAlgorithm mPipMenuIconsAlgorithm; - private AnimatorSet mMenuContainerAnimator; private ValueAnimator.AnimatorUpdateListener mMenuBgUpdateListener = @@ -193,6 +183,9 @@ public class PipMenuActivity extends Activity { break; } case MESSAGE_MENU_EXPANDED : { + if (mMenuContainerAnimator == null) { + return; + } mMenuContainerAnimator.setStartDelay(MENU_SHOW_ON_EXPAND_START_DELAY); mMenuContainerAnimator.start(); break; @@ -202,6 +195,9 @@ public class PipMenuActivity extends Activity { break; } case MESSAGE_UPDATE_MENU_LAYOUT: { + if (mPipMenuIconsAlgorithm == null) { + return; + } final Rect bounds = (Rect) msg.obj; mPipMenuIconsAlgorithm.onBoundsChanged(bounds); break; @@ -214,6 +210,13 @@ public class PipMenuActivity extends Activity { private final Runnable mFinishRunnable = this::hideMenu; + protected View mViewRoot; + protected View mSettingsButton; + protected View mDismissButton; + protected View mResizeHandle; + protected View mTopEndContainer; + protected PipMenuIconsAlgorithm mPipMenuIconsAlgorithm; + @Override protected void onCreate(@Nullable Bundle savedInstanceState) { // Set the flags to allow us to watch for outside touches and also hide the menu and start @@ -222,8 +225,6 @@ public class PipMenuActivity extends Activity { super.onCreate(savedInstanceState); - SystemUIFactory.getInstance().getRootComponent().inject(this); - setContentView(R.layout.pip_menu_activity); mAccessibilityManager = getSystemService(AccessibilityManager.class); @@ -254,7 +255,7 @@ public class PipMenuActivity extends Activity { mActionsGroup = findViewById(R.id.actions_group); mBetweenActionPaddingLand = getResources().getDimensionPixelSize( R.dimen.pip_between_action_padding_land); - + mPipMenuIconsAlgorithm = new PipMenuIconsAlgorithm(this.getApplicationContext()); mPipMenuIconsAlgorithm.bindViews((ViewGroup) mViewRoot, (ViewGroup) mTopEndContainer, mResizeHandle, mSettingsButton, mDismissButton); updateFromIntent(getIntent()); diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java index 267c5eacd139..383f6b3bf79d 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java @@ -110,6 +110,8 @@ public class PipMenuActivityController { void onPipShowMenu(); } + /** TODO(b/150319024): PipMenuActivity will move to a Window */ + private Class<?> mPipMenuActivityClass; private Context mContext; private PipMediaController mMediaController; private InputConsumerController mInputConsumerController; @@ -185,11 +187,13 @@ public class PipMenuActivityController { } }; - public PipMenuActivityController(Context context, - PipMediaController mediaController, InputConsumerController inputConsumerController) { + public PipMenuActivityController(Context context, Class<?> pipMenuActivityClass, + PipMediaController mediaController, InputConsumerController inputConsumerController + ) { mContext = context; mMediaController = mediaController; mInputConsumerController = inputConsumerController; + mPipMenuActivityClass = pipMenuActivityClass; } public boolean isMenuActivityVisible() { @@ -454,7 +458,7 @@ public class PipMenuActivityController { WINDOWING_MODE_PINNED, ACTIVITY_TYPE_UNDEFINED); if (pinnedStackInfo != null && pinnedStackInfo.taskIds != null && pinnedStackInfo.taskIds.length > 0) { - Intent intent = new Intent(mContext, PipMenuActivity.class); + Intent intent = new Intent(mContext, mPipMenuActivityClass); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.putExtra(EXTRA_CONTROLLER_MESSENGER, mMessenger); intent.putExtra(EXTRA_ACTIONS, resolveMenuActions()); diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuIconsAlgorithm.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuIconsAlgorithm.java index 69a04d8d3e22..6cfed070198b 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuIconsAlgorithm.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuIconsAlgorithm.java @@ -24,8 +24,6 @@ import android.view.View; import android.view.ViewGroup; import android.widget.FrameLayout; -import javax.inject.Inject; - /** * Helper class to calculate and place the menu icons on the PIP Menu. */ @@ -40,8 +38,7 @@ public class PipMenuIconsAlgorithm { protected View mSettingsButton; protected View mDismissButton; - @Inject - public PipMenuIconsAlgorithm(Context context) { + protected PipMenuIconsAlgorithm(Context context) { } /** @@ -56,7 +53,6 @@ public class PipMenuIconsAlgorithm { mDismissButton = dismissButton; } - /** * Updates the position of the drag handle based on where the PIP window is on the screen. */ diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java index ca3ef2465498..ee8f295e0c30 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java @@ -54,7 +54,7 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, private static final int SHRINK_STACK_FROM_MENU_DURATION = 250; private static final int EXPAND_STACK_TO_MENU_DURATION = 250; - private static final int EXPAND_STACK_TO_FULLSCREEN_DURATION = 300; + private static final int LEAVE_PIP_DURATION = 300; private static final int SHIFT_DURATION = 300; /** Friction to use for PIP when it moves via physics fling animations. */ @@ -304,16 +304,18 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, } /** - * Resizes the pinned stack back to fullscreen. + * Resizes the pinned stack back to unknown windowing mode, which could be freeform or + * * fullscreen depending on the display area's windowing mode. */ - void expandPipToFullscreen() { - expandPipToFullscreen(false /* skipAnimation */); + void expandLeavePip() { + expandLeavePip(false /* skipAnimation */); } /** - * Resizes the pinned stack back to fullscreen. + * Resizes the pinned stack back to unknown windowing mode, which could be freeform or + * fullscreen depending on the display area's windowing mode. */ - void expandPipToFullscreen(boolean skipAnimation) { + void expandLeavePip(boolean skipAnimation) { if (DEBUG) { Log.d(TAG, "exitPip: skipAnimation=" + skipAnimation + " callers=\n" + Debug.getCallers(5, " ")); @@ -323,7 +325,7 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, mPipTaskOrganizer.getUpdateHandler().post(() -> { mPipTaskOrganizer.exitPip(skipAnimation ? 0 - : EXPAND_STACK_TO_FULLSCREEN_DURATION); + : LEAVE_PIP_DURATION); }); } diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java index 5434b62e19b8..7fc2823fc248 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java @@ -193,7 +193,7 @@ public class PipTouchHandler { @Override public void onPipExpand() { - mMotionHelper.expandPipToFullscreen(); + mMotionHelper.expandLeavePip(); } @Override @@ -991,7 +991,7 @@ public class PipTouchHandler { // Expand to fullscreen if this is a double tap // the PiP should be frozen until the transition ends setTouchEnabled(false); - mMotionHelper.expandPipToFullscreen(); + mMotionHelper.expandLeavePip(); } else if (mMenuState != MENU_STATE_FULL) { if (!mTouchState.isWaitingForDoubleTap()) { // User has stalled long enough for this not to be a drag or a double tap, just diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/dagger/PipMenuActivityClass.java b/packages/SystemUI/src/com/android/systemui/pip/phone/dagger/PipMenuActivityClass.java new file mode 100644 index 000000000000..114c30e625aa --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/dagger/PipMenuActivityClass.java @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.pip.phone.dagger; + +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; + +import javax.inject.Qualifier; + +@Qualifier +@Documented +@Retention(RUNTIME) +public @interface PipMenuActivityClass { +} diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotNotificationsController.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotNotificationsController.java index 6f5ceabcc9a5..6d1299ba98ac 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotNotificationsController.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotNotificationsController.java @@ -205,7 +205,8 @@ public class ScreenshotNotificationsController { mPublicNotificationBuilder .setContentTitle(mResources.getString(R.string.screenshot_saved_title)) .setContentText(mResources.getString(R.string.screenshot_saved_text)) - .setContentIntent(PendingIntent.getActivity(mContext, 0, launchIntent, 0)) + .setContentIntent(PendingIntent + .getActivity(mContext, 0, launchIntent, PendingIntent.FLAG_IMMUTABLE)) .setWhen(now) .setAutoCancel(true) .setColor(mContext.getColor( @@ -213,7 +214,8 @@ public class ScreenshotNotificationsController { mNotificationBuilder .setContentTitle(mResources.getString(R.string.screenshot_saved_title)) .setContentText(mResources.getString(R.string.screenshot_saved_text)) - .setContentIntent(PendingIntent.getActivity(mContext, 0, launchIntent, 0)) + .setContentIntent(PendingIntent + .getActivity(mContext, 0, launchIntent, PendingIntent.FLAG_IMMUTABLE)) .setWhen(now) .setAutoCancel(true) .setColor(mContext.getColor( diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/AssistantFeedbackController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/AssistantFeedbackController.java index ca0f62ea7538..b813b6280c12 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/AssistantFeedbackController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/AssistantFeedbackController.java @@ -20,9 +20,16 @@ import static android.service.notification.NotificationListenerService.Ranking; import android.content.ContentResolver; import android.content.Context; +import android.database.ContentObserver; +import android.net.Uri; +import android.os.Handler; +import android.os.Looper; import android.os.UserHandle; import android.provider.Settings; +import androidx.annotation.Nullable; + +import com.android.internal.annotations.VisibleForTesting; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import javax.inject.Inject; @@ -35,23 +42,42 @@ import javax.inject.Singleton; * should show an indicator. */ @Singleton -public class AssistantFeedbackController { +public class AssistantFeedbackController extends ContentObserver { + private final Uri FEEDBACK_URI + = Settings.Global.getUriFor(Settings.Global.NOTIFICATION_FEEDBACK_ENABLED); private ContentResolver mResolver; + private boolean mFeedbackEnabled; + /** Injected constructor */ @Inject public AssistantFeedbackController(Context context) { + super(new Handler(Looper.getMainLooper())); mResolver = context.getContentResolver(); + mResolver.registerContentObserver(FEEDBACK_URI, false, this, UserHandle.USER_ALL); + update(null); + } + + @Override + public void onChange(boolean selfChange, @Nullable Uri uri, int flags) { + update(uri); + } + + @VisibleForTesting + public void update(@Nullable Uri uri) { + if (uri == null || FEEDBACK_URI.equals(uri)) { + mFeedbackEnabled = Settings.Global.getInt(mResolver, + Settings.Global.NOTIFICATION_FEEDBACK_ENABLED, 0) + != 0; + } } /** * Determines whether to show any user controls related to the assistant. This is based on the - * settings flag {@link Settings.Secure.NOTIFICATION_FEEDBACK_ENABLED} + * settings flag {@link Settings.Global.NOTIFICATION_FEEDBACK_ENABLED} */ public boolean isFeedbackEnabled() { - return Settings.Secure.getIntForUser(mResolver, - Settings.Secure.NOTIFICATION_FEEDBACK_ENABLED, 0, - UserHandle.USER_CURRENT) == 1; + return mFeedbackEnabled; } /** diff --git a/packages/SystemUI/src/com/android/systemui/util/leak/LeakReporter.java b/packages/SystemUI/src/com/android/systemui/util/leak/LeakReporter.java index b25df5f9c07f..5e7280840bb9 100644 --- a/packages/SystemUI/src/com/android/systemui/util/leak/LeakReporter.java +++ b/packages/SystemUI/src/com/android/systemui/util/leak/LeakReporter.java @@ -104,9 +104,13 @@ public class LeakReporter { .setContentText(String.format( "SystemUI has detected %d leaked objects. Tap to send", garbageCount)) .setSmallIcon(com.android.internal.R.drawable.stat_sys_adb) - .setContentIntent(PendingIntent.getActivityAsUser(mContext, 0, + .setContentIntent(PendingIntent.getActivityAsUser( + mContext, + 0, getIntent(hprofFile, dumpFile), - PendingIntent.FLAG_UPDATE_CURRENT, null, UserHandle.CURRENT)); + PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE, + null, + UserHandle.CURRENT)); notiMan.notify(TAG, 0, builder.build()); } catch (IOException e) { Log.e(TAG, "Couldn't dump heap for leak", e); diff --git a/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java b/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java index 9fa03df4229a..06806d0e6ab6 100644 --- a/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java +++ b/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java @@ -338,7 +338,7 @@ public class ProximitySensor implements ThresholdSensor { @Override public void run() { unregister(); - mSensor.alertListeners(); + onProximityEvent(null); } /** diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WindowManagerShellModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/WindowManagerShellModule.java index 5b2c39db2eae..d2c61cc996dd 100644 --- a/packages/SystemUI/src/com/android/systemui/wmshell/WindowManagerShellModule.java +++ b/packages/SystemUI/src/com/android/systemui/wmshell/WindowManagerShellModule.java @@ -21,6 +21,8 @@ import android.os.Handler; import android.view.IWindowManager; import com.android.systemui.dagger.qualifiers.Main; +import com.android.systemui.pip.phone.PipMenuActivity; +import com.android.systemui.pip.phone.dagger.PipMenuActivityClass; import com.android.wm.shell.common.DisplayController; import com.android.wm.shell.common.DisplayImeController; import com.android.wm.shell.common.SystemWindows; @@ -65,4 +67,12 @@ public class WindowManagerShellModule { return new DisplayImeController.Builder(wmService, displayController, mainHandler, transactionPool).build(); } + + /** TODO(b/150319024): PipMenuActivity will move to a Window */ + @Singleton + @PipMenuActivityClass + @Provides + static Class<?> providePipMenuActivityClass() { + return PipMenuActivity.class; + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/pip/PipAnimationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/pip/PipAnimationControllerTest.java index c9c111198f4c..f0066ba4f66a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/pip/PipAnimationControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/pip/PipAnimationControllerTest.java @@ -16,7 +16,7 @@ package com.android.systemui.pip; -import static com.android.systemui.pip.PipAnimationController.TRANSITION_DIRECTION_TO_FULLSCREEN; +import static com.android.systemui.pip.PipAnimationController.TRANSITION_DIRECTION_LEAVE_PIP; import static com.android.systemui.pip.PipAnimationController.TRANSITION_DIRECTION_TO_PIP; import static org.junit.Assert.assertEquals; @@ -116,9 +116,9 @@ public class PipAnimationControllerTest extends SysuiTestCase { animator = mPipAnimationController .getAnimator(mLeash, new Rect(), 0f, 1f) - .setTransitionDirection(TRANSITION_DIRECTION_TO_FULLSCREEN); + .setTransitionDirection(TRANSITION_DIRECTION_LEAVE_PIP); assertEquals("Transition to fullscreen mode", - animator.getTransitionDirection(), TRANSITION_DIRECTION_TO_FULLSCREEN); + animator.getTransitionDirection(), TRANSITION_DIRECTION_LEAVE_PIP); } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/AssistantFeedbackControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/AssistantFeedbackControllerTest.java index 619d2444b4dd..fb8c3d9af05c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/AssistantFeedbackControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/AssistantFeedbackControllerTest.java @@ -57,8 +57,8 @@ public class AssistantFeedbackControllerTest extends SysuiTestCase { @Before public void setUp() { - switchSetting(ON); mAssistantFeedbackController = new AssistantFeedbackController(mContext); + switchSetting(ON); mSbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME, 0, null, TEST_UID, 0, new Notification(), UserHandle.CURRENT, null, 0); @@ -72,7 +72,6 @@ public class AssistantFeedbackControllerTest extends SysuiTestCase { @Test public void testUserControls_settingEnabled() { - switchSetting(ON); assertTrue(mAssistantFeedbackController.isFeedbackEnabled()); } @@ -113,7 +112,8 @@ public class AssistantFeedbackControllerTest extends SysuiTestCase { } private void switchSetting(int setting) { - Settings.Secure.putIntForUser(mContext.getContentResolver(), - Settings.Secure.NOTIFICATION_FEEDBACK_ENABLED, setting, UserHandle.USER_CURRENT); + Settings.Global.putInt(mContext.getContentResolver(), + Settings.Global.NOTIFICATION_FEEDBACK_ENABLED, setting); + mAssistantFeedbackController.update(null); } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/sensors/ProximityCheckTest.java b/packages/SystemUI/tests/src/com/android/systemui/util/sensors/ProximityCheckTest.java index 8ba11dae2b5c..c5a197eef2d4 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/util/sensors/ProximityCheckTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/util/sensors/ProximityCheckTest.java @@ -16,6 +16,7 @@ package com.android.systemui.util.sensors; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; @@ -80,6 +81,8 @@ public class ProximityCheckTest extends SysuiTestCase { mFakeExecutor.runAllReady(); assertFalse(mFakeProximitySensor.isRegistered()); + assertEquals(1, mTestableCallback.mNumCalls); + assertNull(mTestableCallback.mLastResult); } @Test @@ -110,9 +113,12 @@ public class ProximityCheckTest extends SysuiTestCase { private static class TestableCallback implements Consumer<Boolean> { Boolean mLastResult; + int mNumCalls = 0; + @Override public void accept(Boolean result) { mLastResult = result; + mNumCalls++; } } } diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java index 44c4bf4836a0..b6f2a47dd5e2 100644 --- a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java +++ b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java @@ -16,8 +16,10 @@ package com.android.server.accessibility.magnification; +import android.animation.Animator; import android.animation.ValueAnimator; import android.annotation.NonNull; +import android.annotation.Nullable; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; @@ -61,6 +63,8 @@ public class FullScreenMagnificationController { private static final boolean DEBUG = false; private static final String LOG_TAG = "FullScreenMagnificationController"; + private static final Runnable STUB_RUNNABLE = () -> { + }; public static final float MIN_SCALE = 1.0f; public static final float MAX_SCALE = 8.0f; @@ -292,7 +296,7 @@ public class FullScreenMagnificationController { // Adjust the current spec's offsets if necessary. if (updateCurrentSpecWithOffsetsLocked( mCurrentMagnificationSpec.offsetX, mCurrentMagnificationSpec.offsetY)) { - sendSpecToAnimation(mCurrentMagnificationSpec, false); + sendSpecToAnimation(mCurrentMagnificationSpec, null); } onMagnificationChangedLocked(); } @@ -300,17 +304,18 @@ public class FullScreenMagnificationController { } } - void sendSpecToAnimation(MagnificationSpec spec, boolean animate) { + void sendSpecToAnimation(MagnificationSpec spec, Runnable endCallback) { if (DEBUG) { Slog.i(LOG_TAG, - "sendSpecToAnimation(spec = " + spec + ", animate = " + animate + ")"); + "sendSpecToAnimation(spec = " + spec + ", endCallback = " + endCallback + + ")"); } if (Thread.currentThread().getId() == mMainThreadId) { - mSpecAnimationBridge.updateSentSpecMainThread(spec, animate); + mSpecAnimationBridge.updateSentSpecMainThread(spec, endCallback); } else { final Message m = PooledLambda.obtainMessage( SpecAnimationBridge::updateSentSpecMainThread, - mSpecAnimationBridge, spec, animate); + mSpecAnimationBridge, spec, endCallback); mControllerCtx.getHandler().sendMessage(m); } } @@ -410,6 +415,11 @@ public class FullScreenMagnificationController { @GuardedBy("mLock") boolean reset(boolean animate) { + return reset(transformToStubRunnable(animate)); + } + + @GuardedBy("mLock") + boolean reset(Runnable endCallback) { if (!mRegistered) { return false; } @@ -420,7 +430,7 @@ public class FullScreenMagnificationController { onMagnificationChangedLocked(); } mIdOfLastServiceToMagnify = INVALID_ID; - sendSpecToAnimation(spec, animate); + sendSpecToAnimation(spec, endCallback); return changed; } @@ -448,24 +458,24 @@ public class FullScreenMagnificationController { final float centerX = normPivotX + offsetX; final float centerY = normPivotY + offsetY; mIdOfLastServiceToMagnify = id; - return setScaleAndCenter(scale, centerX, centerY, animate, id); + return setScaleAndCenter(scale, centerX, centerY, transformToStubRunnable(animate), id); } @GuardedBy("mLock") boolean setScaleAndCenter(float scale, float centerX, float centerY, - boolean animate, int id) { + Runnable endCallback, int id) { if (!mRegistered) { return false; } if (DEBUG) { Slog.i(LOG_TAG, "setScaleAndCenterLocked(scale = " + scale + ", centerX = " + centerX - + ", centerY = " + centerY + ", animate = " + animate + + ", centerY = " + centerY + ", endCallback = " + endCallback + ", id = " + id + ")"); } final boolean changed = updateMagnificationSpecLocked(scale, centerX, centerY); - sendSpecToAnimation(mCurrentMagnificationSpec, animate); + sendSpecToAnimation(mCurrentMagnificationSpec, endCallback); if (isMagnifying() && (id != INVALID_ID)) { mIdOfLastServiceToMagnify = id; } @@ -531,7 +541,7 @@ public class FullScreenMagnificationController { if (id != INVALID_ID) { mIdOfLastServiceToMagnify = id; } - sendSpecToAnimation(mCurrentMagnificationSpec, false); + sendSpecToAnimation(mCurrentMagnificationSpec, null); } boolean updateCurrentSpecWithOffsetsLocked(float nonNormOffsetX, float nonNormOffsetY) { @@ -865,12 +875,26 @@ public class FullScreenMagnificationController { * the spec did not change */ public boolean reset(int displayId, boolean animate) { + return reset(displayId, animate ? STUB_RUNNABLE : null); + } + + /** + * Resets the magnification scale and center, optionally animating the + * transition. + * + * @param displayId The logical display id. + * @param endCallback Called when the animation is ended or the spec did not change. + * {@code null} to transition immediately + * @return {@code true} if the magnification spec changed, {@code false} if + * the spec did not change + */ + public boolean reset(int displayId, Runnable endCallback) { synchronized (mLock) { final DisplayMagnification display = mDisplays.get(displayId); if (display == null) { return false; } - return display.reset(animate); + return display.reset(endCallback); } } @@ -921,7 +945,8 @@ public class FullScreenMagnificationController { if (display == null) { return false; } - return display.setScaleAndCenter(Float.NaN, centerX, centerY, animate, id); + return display.setScaleAndCenter(Float.NaN, centerX, centerY, + animate ? STUB_RUNNABLE : null, id); } } @@ -944,12 +969,35 @@ public class FullScreenMagnificationController { */ public boolean setScaleAndCenter(int displayId, float scale, float centerX, float centerY, boolean animate, int id) { + return setScaleAndCenter(displayId, scale, centerX, centerY, + transformToStubRunnable(animate), id); + } + + /** + * Sets the scale and center of the magnified region, optionally + * animating the transition. If animation is disabled, the transition + * is immediate. + * + * @param displayId The logical display id. + * @param scale the target scale, or {@link Float#NaN} to leave unchanged + * @param centerX the screen-relative X coordinate around which to + * center and scale, or {@link Float#NaN} to leave unchanged + * @param centerY the screen-relative Y coordinate around which to + * center and scale, or {@link Float#NaN} to leave unchanged + * @param endCallback called when the transition is finished successfully or the spec did not + * change. {@code null} to transition immediately. + * @param id the ID of the service requesting the change + * @return {@code true} if the magnification spec changed, {@code false} if + * the spec did not change + */ + public boolean setScaleAndCenter(int displayId, float scale, float centerX, float centerY, + Runnable endCallback, int id) { synchronized (mLock) { final DisplayMagnification display = mDisplays.get(displayId); if (display == null) { return false; } - return display.setScaleAndCenter(scale, centerX, centerY, animate, id); + return display.setScaleAndCenter(scale, centerX, centerY, endCallback, id); } } @@ -1160,7 +1208,8 @@ public class FullScreenMagnificationController { * Class responsible for animating spec on the main thread and sending spec * updates to the window manager. */ - private static class SpecAnimationBridge implements ValueAnimator.AnimatorUpdateListener { + private static class SpecAnimationBridge implements ValueAnimator.AnimatorUpdateListener, + Animator.AnimatorListener { private final ControllerContext mControllerCtx; /** @@ -1180,6 +1229,8 @@ public class FullScreenMagnificationController { */ private final ValueAnimator mValueAnimator; + // Called when the callee wants animating and the sent spec matches the target spec. + private Runnable mEndCallback; private final Object mLock; private final int mDisplayId; @@ -1197,6 +1248,7 @@ public class FullScreenMagnificationController { mValueAnimator.setInterpolator(new DecelerateInterpolator(2.5f)); mValueAnimator.setFloatValues(0.0f, 1.0f); mValueAnimator.addUpdateListener(this); + mValueAnimator.addListener(this); } /** @@ -1216,24 +1268,36 @@ public class FullScreenMagnificationController { } } - public void updateSentSpecMainThread(MagnificationSpec spec, boolean animate) { + void updateSentSpecMainThread(MagnificationSpec spec, Runnable endCallback) { if (mValueAnimator.isRunning()) { + // Avoid AnimationEnd Callback. + mEndCallback = null; mValueAnimator.cancel(); } + mEndCallback = endCallback; // If the current and sent specs don't match, update the sent spec. synchronized (mLock) { final boolean changed = !mSentMagnificationSpec.equals(spec); if (changed) { - if (animate) { + if (mEndCallback != null) { animateMagnificationSpecLocked(spec); } else { setMagnificationSpecLocked(spec); } + } else { + sendEndCallbackMainThread(); } } } + private void sendEndCallbackMainThread() { + if (mEndCallback != null) { + mEndCallback.run(); + mEndCallback = null; + } + } + @GuardedBy("mLock") private void setMagnificationSpecLocked(MagnificationSpec spec) { if (mEnabled) { @@ -1270,6 +1334,26 @@ public class FullScreenMagnificationController { } } } + + @Override + public void onAnimationStart(Animator animation) { + + } + + @Override + public void onAnimationEnd(Animator animation) { + sendEndCallbackMainThread(); + } + + @Override + public void onAnimationCancel(Animator animation) { + + } + + @Override + public void onAnimationRepeat(Animator animation) { + + } } private static class ScreenStateObserver extends BroadcastReceiver { @@ -1395,4 +1479,9 @@ public class FullScreenMagnificationController { return mAnimationDuration; } } + + @Nullable + private static Runnable transformToStubRunnable(boolean animate) { + return animate ? STUB_RUNNABLE : null; + } } diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java index 7381da1676f5..6d71c8e68f77 100644 --- a/services/core/java/com/android/server/TelephonyRegistry.java +++ b/services/core/java/com/android/server/TelephonyRegistry.java @@ -34,7 +34,6 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager; -import android.net.LinkProperties; import android.os.Binder; import android.os.Build; import android.os.Bundle; @@ -46,8 +45,6 @@ import android.os.RemoteException; import android.os.UserHandle; import android.provider.DeviceConfig; import android.telephony.Annotation; -import android.telephony.Annotation.ApnType; -import android.telephony.Annotation.DataFailureCause; import android.telephony.Annotation.RadioPowerState; import android.telephony.Annotation.SrvccState; import android.telephony.BarringInfo; @@ -80,7 +77,9 @@ import android.telephony.TelephonyManager; import android.telephony.data.ApnSetting; import android.telephony.emergency.EmergencyNumber; import android.telephony.ims.ImsReasonInfo; +import android.util.ArrayMap; import android.util.LocalLog; +import android.util.Pair; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.app.IBatteryStats; @@ -103,6 +102,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; +import java.util.Objects; /** * Since phone process can be restarted, this class provides a centralized place @@ -302,13 +302,18 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { @RadioPowerState private int mRadioPowerState = TelephonyManager.RADIO_POWER_UNAVAILABLE; - private final LocalLog mLocalLog = new LocalLog(100); + private final LocalLog mLocalLog = new LocalLog(200); - private final LocalLog mListenLog = new LocalLog(100); + private final LocalLog mListenLog = new LocalLog(00); - // Per-phoneMap of APN Type to DataConnectionState - private List<Map<Integer, PreciseDataConnectionState>> mPreciseDataConnectionStates = - new ArrayList<Map<Integer, PreciseDataConnectionState>>(); + /** + * Per-phone map of precise data connection state. The key of the map is the pair of transport + * type and APN setting. This is the cache to prevent redundant callbacks to the listeners. + * A precise data connection with state {@link TelephonyManager#DATA_DISCONNECTED} removes + * its entry from the map. + */ + private List<Map<Pair<Integer, ApnSetting>, PreciseDataConnectionState>> + mPreciseDataConnectionStates; static final int ENFORCE_COARSE_LOCATION_PERMISSION_MASK = PhoneStateListener.LISTEN_REGISTRATION_FAILURE @@ -521,7 +526,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { mRingingCallState[i] = PreciseCallState.PRECISE_CALL_STATE_IDLE; mForegroundCallState[i] = PreciseCallState.PRECISE_CALL_STATE_IDLE; mBackgroundCallState[i] = PreciseCallState.PRECISE_CALL_STATE_IDLE; - mPreciseDataConnectionStates.add(new HashMap<Integer, PreciseDataConnectionState>()); + mPreciseDataConnectionStates.add(new ArrayMap<>()); mBarringInfo.add(i, new BarringInfo()); mTelephonyDisplayInfos[i] = null; } @@ -610,7 +615,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { mRingingCallState[i] = PreciseCallState.PRECISE_CALL_STATE_IDLE; mForegroundCallState[i] = PreciseCallState.PRECISE_CALL_STATE_IDLE; mBackgroundCallState[i] = PreciseCallState.PRECISE_CALL_STATE_IDLE; - mPreciseDataConnectionStates.add(new HashMap<Integer, PreciseDataConnectionState>()); + mPreciseDataConnectionStates.add(new ArrayMap<>()); mBarringInfo.add(i, new BarringInfo()); mTelephonyDisplayInfos[i] = null; } @@ -1687,38 +1692,25 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { * * @param phoneId the phoneId carrying the data connection * @param subId the subscriptionId for the data connection - * @param apnType the apn type bitmask, defined with {@code ApnSetting#TYPE_*} flags. * @param preciseState a PreciseDataConnectionState that has info about the data connection */ @Override - public void notifyDataConnectionForSubscriber( - int phoneId, int subId, @ApnType int apnType, PreciseDataConnectionState preciseState) { + public void notifyDataConnectionForSubscriber(int phoneId, int subId, + @NonNull PreciseDataConnectionState preciseState) { if (!checkNotifyPermission("notifyDataConnection()" )) { return; } - String apn = ""; - int state = TelephonyManager.DATA_UNKNOWN; - int networkType = TelephonyManager.NETWORK_TYPE_UNKNOWN; - LinkProperties linkProps = null; + ApnSetting apnSetting = preciseState.getApnSetting(); - if (preciseState != null) { - apn = preciseState.getDataConnectionApn(); - state = preciseState.getState(); - networkType = preciseState.getNetworkType(); - linkProps = preciseState.getLinkProperties(); - } - if (VDBG) { - log("notifyDataConnectionForSubscriber: subId=" + subId - + " state=" + state + "' apn='" + apn - + "' apnType=" + apnType + " networkType=" + networkType - + "' preciseState=" + preciseState); - } + int apnTypes = apnSetting.getApnTypeBitmask(); + int state = preciseState.getState(); + int networkType = preciseState.getNetworkType(); synchronized (mRecords) { if (validatePhoneId(phoneId)) { // We only call the callback when the change is for default APN type. - if ((ApnSetting.TYPE_DEFAULT & apnType) != 0 + if ((ApnSetting.TYPE_DEFAULT & apnTypes) != 0 && (mDataConnectionState[phoneId] != state || mDataConnectionNetworkType[phoneId] != networkType)) { String str = "onDataConnectionStateChanged(" @@ -1747,19 +1739,11 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { mDataConnectionNetworkType[phoneId] = networkType; } - boolean needsNotify = false; - // State has been cleared for this APN Type - if (preciseState == null) { - // We try clear the state and check if the state was previously not cleared - needsNotify = mPreciseDataConnectionStates.get(phoneId).remove(apnType) != null; - } else { - // We need to check to see if the state actually changed - PreciseDataConnectionState oldPreciseState = - mPreciseDataConnectionStates.get(phoneId).put(apnType, preciseState); - needsNotify = !preciseState.equals(oldPreciseState); - } - - if (needsNotify) { + Pair<Integer, ApnSetting> key = Pair.create(preciseState.getTransportType(), + preciseState.getApnSetting()); + PreciseDataConnectionState oldState = mPreciseDataConnectionStates.get(phoneId) + .remove(key); + if (!Objects.equals(oldState, preciseState)) { for (Record r : mRecords) { if (r.matchPhoneStateListenerEvent( PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE) @@ -1771,54 +1755,22 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { } } } - } - } - handleRemoveListLocked(); - } + handleRemoveListLocked(); - broadcastDataConnectionStateChanged(state, apn, apnType, subId); - } + broadcastDataConnectionStateChanged(phoneId, subId, preciseState); - /** - * Stub to satisfy the ITelephonyRegistry aidl interface; do not use this function. - * @see #notifyDataConnectionFailedForSubscriber - */ - public void notifyDataConnectionFailed(String apnType) { - loge("This function should not be invoked"); - } + String str = "notifyDataConnectionForSubscriber: phoneId=" + phoneId + " subId=" + + subId + " " + preciseState; + log(str); + mLocalLog.log(str); + } - private void notifyDataConnectionFailedForSubscriber(int phoneId, int subId, int apnType) { - if (!checkNotifyPermission("notifyDataConnectionFailed()")) { - return; - } - if (VDBG) { - log("notifyDataConnectionFailedForSubscriber: subId=" + subId - + " apnType=" + apnType); - } - synchronized (mRecords) { - if (validatePhoneId(phoneId)) { - mPreciseDataConnectionStates.get(phoneId).put( - apnType, - new PreciseDataConnectionState.Builder() - .setApnSetting(new ApnSetting.Builder() - .setApnTypeBitmask(apnType) - .build()) - .build()); - for (Record r : mRecords) { - if (r.matchPhoneStateListenerEvent( - PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE) - && idMatch(r.subId, subId, phoneId)) { - try { - r.callback.onPreciseDataConnectionStateChanged( - mPreciseDataConnectionStates.get(phoneId).get(apnType)); - } catch (RemoteException ex) { - mRemoveList.add(r.binder); - } - } + // If the state is disconnected, it would be the end of life cycle of a data + // connection, so remove it from the cache. + if (preciseState.getState() != TelephonyManager.DATA_DISCONNECTED) { + mPreciseDataConnectionStates.get(phoneId).put(key, preciseState); } } - - handleRemoveListLocked(); } } @@ -1972,43 +1924,6 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { } @Override - public void notifyPreciseDataConnectionFailed(int phoneId, int subId, @ApnType int apnType, - String apn, @DataFailureCause int failCause) { - if (!checkNotifyPermission("notifyPreciseDataConnectionFailed()")) { - return; - } - - // precise notify invokes imprecise notify - notifyDataConnectionFailedForSubscriber(phoneId, subId, apnType); - - synchronized (mRecords) { - if (validatePhoneId(phoneId)) { - mPreciseDataConnectionStates.get(phoneId).put( - apnType, - new PreciseDataConnectionState.Builder() - .setApnSetting(new ApnSetting.Builder() - .setApnTypeBitmask(apnType) - .build()) - .setFailCause(failCause) - .build()); - for (Record r : mRecords) { - if (r.matchPhoneStateListenerEvent( - PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE) - && idMatch(r.subId, subId, phoneId)) { - try { - r.callback.onPreciseDataConnectionStateChanged( - mPreciseDataConnectionStates.get(phoneId).get(apnType)); - } catch (RemoteException ex) { - mRemoveList.add(r.binder); - } - } - } - } - handleRemoveListLocked(); - } - } - - @Override public void notifySrvccStateChanged(int subId, @SrvccState int state) { if (!checkNotifyPermission("notifySrvccStateChanged()")) { return; @@ -2578,16 +2493,18 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { } } - private void broadcastDataConnectionStateChanged(int state, String apn, - int apnType, int subId) { + private void broadcastDataConnectionStateChanged(int slotIndex, int subId, + @NonNull PreciseDataConnectionState pdcs) { // Note: not reporting to the battery stats service here, because the // status bar takes care of that after taking into account all of the // required info. Intent intent = new Intent(ACTION_ANY_DATA_CONNECTION_STATE_CHANGED); - intent.putExtra(PHONE_CONSTANTS_STATE_KEY, TelephonyUtils.dataStateToString(state)); - intent.putExtra(PHONE_CONSTANTS_DATA_APN_KEY, apn); + intent.putExtra(PHONE_CONSTANTS_STATE_KEY, + TelephonyUtils.dataStateToString(pdcs.getState())); + intent.putExtra(PHONE_CONSTANTS_DATA_APN_KEY, pdcs.getApnSetting().getApnName()); intent.putExtra(PHONE_CONSTANTS_DATA_APN_TYPE_KEY, - ApnSetting.getApnTypesStringFromBitmask(apnType)); + ApnSetting.getApnTypesStringFromBitmask(pdcs.getApnSetting().getApnTypeBitmask())); + intent.putExtra(PHONE_CONSTANTS_SLOT_KEY, slotIndex); intent.putExtra(PHONE_CONSTANTS_SUBSCRIPTION_KEY, subId); mContext.sendBroadcastAsUser(intent, UserHandle.ALL, Manifest.permission.READ_PHONE_STATE); } @@ -2973,7 +2890,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { /** * Returns a string representation of the radio technology (network type) * currently in use on the device. - * @param subId for which network type is returned + * @param type for which network type is returned * @return the name of the radio technology * */ diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index 1680963e26d1..33a92e6ad0ac 100644 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -2559,12 +2559,12 @@ public final class ActiveServices { private int getAllowMode(Intent service, @Nullable String callingPackage) { if (callingPackage == null || service.getComponent() == null) { - return ActivityManagerInternal.ALLOW_NON_FULL_IN_PROFILE_OR_FULL; + return ActivityManagerInternal.ALLOW_NON_FULL_IN_PROFILE; } if (callingPackage.equals(service.getComponent().getPackageName())) { - return ActivityManagerInternal.ALLOW_ACROSS_PROFILES_IN_PROFILE_OR_FULL; + return ActivityManagerInternal.ALLOW_ALL_PROFILE_PERMISSIONS_IN_PROFILE; } else { - return ActivityManagerInternal.ALLOW_NON_FULL_IN_PROFILE_OR_FULL; + return ActivityManagerInternal.ALLOW_NON_FULL_IN_PROFILE; } } diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java index 19b671e46b71..0658e8139cc2 100644 --- a/services/core/java/com/android/server/am/UserController.java +++ b/services/core/java/com/android/server/am/UserController.java @@ -23,11 +23,10 @@ import static android.app.ActivityManager.USER_OP_ERROR_IS_SYSTEM; import static android.app.ActivityManager.USER_OP_ERROR_RELATED_USERS_CANNOT_STOP; import static android.app.ActivityManager.USER_OP_IS_CURRENT; import static android.app.ActivityManager.USER_OP_SUCCESS; -import static android.app.ActivityManagerInternal.ALLOW_ACROSS_PROFILES_IN_PROFILE_OR_NON_FULL; -import static android.app.ActivityManagerInternal.ALLOW_ACROSS_PROFILES_IN_PROFILE_OR_FULL; +import static android.app.ActivityManagerInternal.ALLOW_ALL_PROFILE_PERMISSIONS_IN_PROFILE; import static android.app.ActivityManagerInternal.ALLOW_FULL_ONLY; import static android.app.ActivityManagerInternal.ALLOW_NON_FULL; -import static android.app.ActivityManagerInternal.ALLOW_NON_FULL_IN_PROFILE_OR_FULL; +import static android.app.ActivityManagerInternal.ALLOW_NON_FULL_IN_PROFILE; import static android.os.Process.SHELL_UID; import static android.os.Process.SYSTEM_UID; @@ -1910,12 +1909,11 @@ class UserController implements Handler.Callback { callingUid, -1, true) != PackageManager.PERMISSION_GRANTED) { // If the caller does not have either permission, they are always doomed. allow = false; - } else if (allowMode == ALLOW_NON_FULL - || allowMode == ALLOW_ACROSS_PROFILES_IN_PROFILE_OR_NON_FULL) { + } else if (allowMode == ALLOW_NON_FULL) { // We are blanket allowing non-full access, you lucky caller! allow = true; - } else if (allowMode == ALLOW_NON_FULL_IN_PROFILE_OR_FULL - || allowMode == ALLOW_ACROSS_PROFILES_IN_PROFILE_OR_FULL) { + } else if (allowMode == ALLOW_NON_FULL_IN_PROFILE + || allowMode == ALLOW_ALL_PROFILE_PERMISSIONS_IN_PROFILE) { // We may or may not allow this depending on whether the two users are // in the same profile. allow = isSameProfileGroup; @@ -1942,15 +1940,12 @@ class UserController implements Handler.Callback { builder.append("; this requires "); builder.append(INTERACT_ACROSS_USERS_FULL); if (allowMode != ALLOW_FULL_ONLY) { - if (allowMode == ALLOW_NON_FULL - || allowMode == ALLOW_ACROSS_PROFILES_IN_PROFILE_OR_NON_FULL - || isSameProfileGroup) { + if (allowMode == ALLOW_NON_FULL || isSameProfileGroup) { builder.append(" or "); builder.append(INTERACT_ACROSS_USERS); } if (isSameProfileGroup - && (allowMode == ALLOW_ACROSS_PROFILES_IN_PROFILE_OR_FULL - || allowMode == ALLOW_ACROSS_PROFILES_IN_PROFILE_OR_NON_FULL)) { + && allowMode == ALLOW_ALL_PROFILE_PERMISSIONS_IN_PROFILE) { builder.append(" or "); builder.append(INTERACT_ACROSS_PROFILES); } @@ -1977,8 +1972,7 @@ class UserController implements Handler.Callback { private boolean canInteractWithAcrossProfilesPermission( int allowMode, boolean isSameProfileGroup, int callingPid, int callingUid, String callingPackage) { - if (allowMode != ALLOW_ACROSS_PROFILES_IN_PROFILE_OR_FULL - && allowMode != ALLOW_ACROSS_PROFILES_IN_PROFILE_OR_NON_FULL) { + if (allowMode != ALLOW_ALL_PROFILE_PERMISSIONS_IN_PROFILE) { return false; } if (!isSameProfileGroup) { diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java index 74f3daf50079..e6480fc6cde8 100644 --- a/services/core/java/com/android/server/appop/AppOpsService.java +++ b/services/core/java/com/android/server/appop/AppOpsService.java @@ -19,7 +19,6 @@ package com.android.server.appop; import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_CAMERA; import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION; import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_MICROPHONE; -import static android.app.ActivityManagerInternal.ALLOW_ACROSS_PROFILES_IN_PROFILE_OR_NON_FULL; import static android.app.AppOpsManager.CALL_BACK_ON_SWITCHED_OP; import static android.app.AppOpsManager.FILTER_BY_ATTRIBUTION_TAG; import static android.app.AppOpsManager.FILTER_BY_OP_NAMES; @@ -129,7 +128,6 @@ import android.provider.Settings; import android.util.ArrayMap; import android.util.ArraySet; import android.util.AtomicFile; -import android.util.EventLog; import android.util.KeyValueListParser; import android.util.LongSparseArray; import android.util.Pair; @@ -163,7 +161,6 @@ import com.android.server.LocalServices; import com.android.server.LockGuard; import com.android.server.SystemServerInitThreadPool; import com.android.server.SystemServiceManager; -import com.android.server.am.ActivityManagerService; import com.android.server.pm.PackageList; import com.android.server.pm.parsing.pkg.AndroidPackage; @@ -2200,11 +2197,8 @@ public class AppOpsService extends IAppOpsService.Stub { + " by uid " + Binder.getCallingUid()); } - int userId = UserHandle.getUserId(uid); - enforceManageAppOpsModes(Binder.getCallingPid(), Binder.getCallingUid(), uid); verifyIncomingOp(code); - verifyIncomingUser(userId); code = AppOpsManager.opToSwitch(code); if (permissionPolicyCallback == null) { @@ -2449,12 +2443,8 @@ public class AppOpsService extends IAppOpsService.Stub { private void setMode(int code, int uid, @NonNull String packageName, int mode, @Nullable IAppOpsCallback permissionPolicyCallback) { enforceManageAppOpsModes(Binder.getCallingPid(), Binder.getCallingUid(), uid); - - int userId = UserHandle.getUserId(uid); - verifyIncomingOp(code); - verifyIncomingUser(userId); - verifyIncomingPackage(packageName, userId); + verifyIncomingPackage(packageName, UserHandle.getUserId(uid)); ArraySet<ModeCallback> repCbs = null; code = AppOpsManager.opToSwitch(code); @@ -2867,11 +2857,8 @@ public class AppOpsService extends IAppOpsService.Stub { private int checkOperationImpl(int code, int uid, String packageName, boolean raw) { - int userId = UserHandle.getUserId(uid); - verifyIncomingOp(code); - verifyIncomingUser(userId); - verifyIncomingPackage(packageName, userId); + verifyIncomingPackage(packageName, UserHandle.getUserId(uid)); String resolvedPackageName = resolvePackageName(uid, packageName); if (resolvedPackageName == null) { @@ -2990,15 +2977,10 @@ public class AppOpsService extends IAppOpsService.Stub { String proxiedAttributionTag, int proxyUid, String proxyPackageName, String proxyAttributionTag, boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage) { - int proxiedUserId = UserHandle.getUserId(proxiedUid); - int proxyUserId = UserHandle.getUserId(proxyUid); - verifyIncomingUid(proxyUid); verifyIncomingOp(code); - verifyIncomingUser(proxiedUserId); - verifyIncomingUser(proxyUserId); - verifyIncomingPackage(proxiedPackageName, proxiedUserId); - verifyIncomingPackage(proxyPackageName, proxyUserId); + verifyIncomingPackage(proxiedPackageName, UserHandle.getUserId(proxiedUid)); + verifyIncomingPackage(proxyPackageName, UserHandle.getUserId(proxyUid)); String resolveProxyPackageName = resolvePackageName(proxyUid, proxyPackageName); if (resolveProxyPackageName == null) { @@ -3048,12 +3030,9 @@ public class AppOpsService extends IAppOpsService.Stub { private int noteOperationImpl(int code, int uid, @Nullable String packageName, @Nullable String attributionTag, boolean shouldCollectAsyncNotedOp, @Nullable String message, boolean shouldCollectMessage) { - int userId = UserHandle.getUserId(uid); - verifyIncomingUid(uid); verifyIncomingOp(code); - verifyIncomingUser(userId); - verifyIncomingPackage(packageName, userId); + verifyIncomingPackage(packageName, UserHandle.getUserId(uid)); String resolvedPackageName = resolvePackageName(uid, packageName); if (resolvedPackageName == null) { @@ -3430,12 +3409,9 @@ public class AppOpsService extends IAppOpsService.Stub { public int startOperation(IBinder clientId, int code, int uid, String packageName, String attributionTag, boolean startIfModeDefault, boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage) { - int userId = UserHandle.getUserId(uid); - verifyIncomingUid(uid); verifyIncomingOp(code); - verifyIncomingUser(userId); - verifyIncomingPackage(packageName, userId); + verifyIncomingPackage(packageName, UserHandle.getUserId(uid)); String resolvedPackageName = resolvePackageName(uid, packageName); if (resolvedPackageName == null) { @@ -3515,12 +3491,9 @@ public class AppOpsService extends IAppOpsService.Stub { @Override public void finishOperation(IBinder clientId, int code, int uid, String packageName, String attributionTag) { - int userId = UserHandle.getUserId(uid); - verifyIncomingUid(uid); verifyIncomingOp(code); - verifyIncomingUser(userId); - verifyIncomingPackage(packageName, userId); + verifyIncomingPackage(packageName, UserHandle.getUserId(uid)); String resolvedPackageName = resolvePackageName(uid, packageName); if (resolvedPackageName == null) { @@ -3749,33 +3722,6 @@ public class AppOpsService extends IAppOpsService.Stub { } } - private void verifyIncomingUser(@UserIdInt int userId) { - int callingUid = Binder.getCallingUid(); - int callingUserId = UserHandle.getUserId(callingUid); - int callingPid = Binder.getCallingPid(); - - if (callingUserId != userId) { - // Prevent endless loop between when checking appops inside of handleIncomingUser - if (Binder.getCallingPid() == ActivityManagerService.MY_PID) { - return; - } - long token = Binder.clearCallingIdentity(); - try { - try { - LocalServices.getService(ActivityManagerInternal.class).handleIncomingUser( - callingPid, callingUid, userId, /* allowAll */ false, - ALLOW_ACROSS_PROFILES_IN_PROFILE_OR_NON_FULL, "appop operation", null); - } catch (Exception e) { - EventLog.writeEvent(0x534e4554, "153996875", "appop", userId); - - throw e; - } - } finally { - Binder.restoreCallingIdentity(token); - } - } - } - private @Nullable UidState getUidStateLocked(int uid, boolean edit) { UidState uidState = mUidStates.get(uid); if (uidState == null) { @@ -5855,11 +5801,8 @@ public class AppOpsService extends IAppOpsService.Stub { return false; } } - int userId = UserHandle.getUserId(uid); - verifyIncomingOp(code); - verifyIncomingUser(userId); - verifyIncomingPackage(packageName, userId); + verifyIncomingPackage(packageName, UserHandle.getUserId(uid)); final String resolvedPackageName = resolvePackageName(uid, packageName); if (resolvedPackageName == null) { diff --git a/services/core/java/com/android/server/appop/TEST_MAPPING b/services/core/java/com/android/server/appop/TEST_MAPPING index a3e1b7a7e5c5..84de25c06ebf 100644 --- a/services/core/java/com/android/server/appop/TEST_MAPPING +++ b/services/core/java/com/android/server/appop/TEST_MAPPING @@ -7,9 +7,6 @@ "name": "CtsAppOps2TestCases" }, { - "name": "CtsAppOpHostTestCases" - }, - { "name": "FrameworksServicesTests", "options": [ { diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java index 6e0efb09aff3..be93b8f95b79 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java @@ -137,7 +137,6 @@ import com.android.server.LocalServices; import com.android.server.ServiceThread; import com.android.server.SystemConfig; import com.android.server.Watchdog; -import com.android.server.am.ActivityManagerService; import com.android.server.pm.ApexManager; import com.android.server.pm.PackageManagerServiceUtils; import com.android.server.pm.PackageSetting; @@ -922,16 +921,6 @@ public class PermissionManagerService extends IPermissionManager.Stub { } final int uid = UserHandle.getUid(userId, pkg.getUid()); - - try { - enforceCrossUserOrProfilePermission(Binder.getCallingUid(), UserHandle.getUserId(uid), - false, false, "checkPermissionInternal"); - } catch (Exception e) { - EventLog.writeEvent(0x534e4554, "153996875", "checkPermission", uid); - - throw e; - } - final PackageSetting ps = (PackageSetting) mPackageManagerInt.getPackageSetting( pkg.getPackageName()); if (ps == null) { @@ -4399,7 +4388,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { } final int callingUserId = UserHandle.getUserId(callingUid); if (hasCrossUserPermission( - Binder.getCallingPid(), callingUid, callingUserId, userId, requireFullPermission, + callingUid, callingUserId, userId, requireFullPermission, requirePermissionWhenSameUser)) { return; } @@ -4426,54 +4415,37 @@ public class PermissionManagerService extends IPermissionManager.Stub { private void enforceCrossUserOrProfilePermission(int callingUid, int userId, boolean requireFullPermission, boolean checkShell, String message) { - int callingPid = Binder.getCallingPid(); - final int callingUserId = UserHandle.getUserId(callingUid); - if (userId < 0) { throw new IllegalArgumentException("Invalid userId " + userId); } - - if (callingUserId == userId) { - return; + if (checkShell) { + PackageManagerServiceUtils.enforceShellRestriction(mUserManagerInt, + UserManager.DISALLOW_DEBUGGING_FEATURES, callingUid, userId); } - - // Prevent endless loop between when checking permission while checking a permission - if (callingPid == ActivityManagerService.MY_PID) { + final int callingUserId = UserHandle.getUserId(callingUid); + if (hasCrossUserPermission(callingUid, callingUserId, userId, requireFullPermission, + /*requirePermissionWhenSameUser= */ false)) { return; } - - long token = Binder.clearCallingIdentity(); - try { - if (checkShell) { - PackageManagerServiceUtils.enforceShellRestriction(mUserManagerInt, - UserManager.DISALLOW_DEBUGGING_FEATURES, callingUid, userId); - } - if (hasCrossUserPermission(callingPid, callingUid, callingUserId, userId, - requireFullPermission, /*requirePermissionWhenSameUser= */ false)) { - return; - } - final boolean isSameProfileGroup = isSameProfileGroup(callingUserId, userId); - if (isSameProfileGroup && PermissionChecker.checkPermissionForPreflight( - mContext, - android.Manifest.permission.INTERACT_ACROSS_PROFILES, - PermissionChecker.PID_UNKNOWN, - callingUid, - mPackageManagerInt.getPackage(callingUid).getPackageName()) - == PermissionChecker.PERMISSION_GRANTED) { - return; - } - - String errorMessage = buildInvalidCrossUserOrProfilePermissionMessage( - message, requireFullPermission, isSameProfileGroup); - Slog.w(TAG, errorMessage); - throw new SecurityException(errorMessage); - } finally { - Binder.restoreCallingIdentity(token); + final boolean isSameProfileGroup = isSameProfileGroup(callingUserId, userId); + if (isSameProfileGroup && PermissionChecker.checkPermissionForPreflight( + mContext, + android.Manifest.permission.INTERACT_ACROSS_PROFILES, + PermissionChecker.PID_UNKNOWN, + callingUid, + mPackageManagerInt.getPackage(callingUid).getPackageName()) + == PermissionChecker.PERMISSION_GRANTED) { + return; } + String errorMessage = buildInvalidCrossUserOrProfilePermissionMessage( + message, requireFullPermission, isSameProfileGroup); + Slog.w(TAG, errorMessage); + throw new SecurityException(errorMessage); } - private boolean hasCrossUserPermission(int callingPid, int callingUid, int callingUserId, - int userId, boolean requireFullPermission, boolean requirePermissionWhenSameUser) { + private boolean hasCrossUserPermission( + int callingUid, int callingUserId, int userId, boolean requireFullPermission, + boolean requirePermissionWhenSameUser) { if (!requirePermissionWhenSameUser && userId == callingUserId) { return true; } @@ -4481,11 +4453,15 @@ public class PermissionManagerService extends IPermissionManager.Stub { return true; } if (requireFullPermission) { - return mContext.checkPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL, - callingPid, callingUid) == PackageManager.PERMISSION_GRANTED; + return hasPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL); } - return mContext.checkPermission(android.Manifest.permission.INTERACT_ACROSS_USERS, - callingPid, callingUid) == PackageManager.PERMISSION_GRANTED; + return hasPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) + || hasPermission(Manifest.permission.INTERACT_ACROSS_USERS); + } + + private boolean hasPermission(String permission) { + return mContext.checkCallingOrSelfPermission(permission) + == PackageManager.PERMISSION_GRANTED; } private boolean isSameProfileGroup(@UserIdInt int callerUserId, @UserIdInt int userId) { diff --git a/services/core/java/com/android/server/pm/permission/TEST_MAPPING b/services/core/java/com/android/server/pm/permission/TEST_MAPPING index 65dc320eadc2..c0d71ac26853 100644 --- a/services/core/java/com/android/server/pm/permission/TEST_MAPPING +++ b/services/core/java/com/android/server/pm/permission/TEST_MAPPING @@ -18,24 +18,21 @@ ] }, { - "name": "CtsPermission2TestCases", + "name": "CtsAppSecurityHostTestCases", "options": [ { - "include-filter": "android.permission2.cts.RestrictedPermissionsTest" - }, - { - "include-filter": "android.permission.cts.PermissionMaxSdkVersionTest" + "include-filter": "android.appsecurity.cts.AppSecurityTests#rebootWithDuplicatePermission" } ] }, { - "name": "CtsPermissionHostTestCases" - }, - { - "name": "CtsAppSecurityHostTestCases", + "name": "CtsPermission2TestCases", "options": [ { - "include-filter": "android.appsecurity.cts.AppSecurityTests#rebootWithDuplicatePermission" + "include-filter": "android.permission2.cts.RestrictedPermissionsTest" + }, + { + "include-filter": "android.permission.cts.PermissionMaxSdkVersionTest" } ] }, diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java index 526ec08930ea..ac96d144c4d0 100644 --- a/services/core/java/com/android/server/wm/RootWindowContainer.java +++ b/services/core/java/com/android/server/wm/RootWindowContainer.java @@ -2155,6 +2155,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent> // non-fullscreen bounds. Then when this new PIP task exits PIP, it can restore // to its previous freeform bounds. stack.setLastNonFullscreenBounds(task.mLastNonFullscreenBounds); + stack.setBounds(task.getBounds()); // There are multiple activities in the task and moving the top activity should // reveal/leave the other activities in their original task. diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java index a9f2e4a50ded..57bfbf33d680 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java @@ -27,6 +27,7 @@ import static org.mockito.Matchers.anyObject; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -95,12 +96,15 @@ public class FullScreenMagnificationControllerTest { ValueAnimator mMockValueAnimator; ValueAnimator.AnimatorUpdateListener mTargetAnimationListener; + ValueAnimator.AnimatorListener mStateListener; FullScreenMagnificationController mFullScreenMagnificationController; + Runnable mEndCallback; @Before public void setUp() { Looper looper = InstrumentationRegistry.getContext().getMainLooper(); + mEndCallback = Mockito.mock(Runnable.class); // Pretending ID of the Thread associated with looper as main thread ID in controller when(mMockContext.getMainLooper()).thenReturn(looper); when(mMockControllerCtx.getContext()).thenReturn(mMockContext); @@ -319,6 +323,7 @@ public class FullScreenMagnificationControllerTest { for (int i = 0; i < DISPLAY_COUNT; i++) { setScaleAndCenter_animated_stateChangesAndAnimationHappens(i); resetMockWindowManager(); + Mockito.reset(mEndCallback); } } @@ -331,7 +336,7 @@ public class FullScreenMagnificationControllerTest { MagnificationSpec endSpec = getMagnificationSpec(scale, offsets); assertTrue(mFullScreenMagnificationController.setScaleAndCenter(displayId, scale, - newCenter.x, newCenter.y, true, SERVICE_ID_1)); + newCenter.x, newCenter.y, mEndCallback, SERVICE_ID_1)); mMessageCapturingHandler.sendAllMessages(); assertEquals(newCenter.x, mFullScreenMagnificationController.getCenterX(displayId), 0.5); @@ -358,7 +363,33 @@ public class FullScreenMagnificationControllerTest { Mockito.reset(mMockWindowManager); when(mMockValueAnimator.getAnimatedFraction()).thenReturn(1.0f); mTargetAnimationListener.onAnimationUpdate(mMockValueAnimator); + mStateListener.onAnimationEnd(mMockValueAnimator); verify(mMockWindowManager).setMagnificationSpec(eq(displayId), argThat(closeTo(endSpec))); + verify(mEndCallback).run(); + } + + @Test + public void testSetScaleAndCenterWithAnimation_sameSpec_noAnimationButInvokeEndCallback() { + for (int i = 0; i < DISPLAY_COUNT; i++) { + setScaleAndCenter_sameSpec_noAnimationButInvokeEndCallback(i); + Mockito.reset(mEndCallback); + } + } + + private void setScaleAndCenter_sameSpec_noAnimationButInvokeEndCallback(int displayId) { + register(displayId); + final PointF center = INITIAL_BOUNDS_LOWER_RIGHT_2X_CENTER; + final float targetScale = 2.0f; + assertTrue(mFullScreenMagnificationController.setScaleAndCenter(displayId, + targetScale, center.x, center.y, false, SERVICE_ID_1)); + mMessageCapturingHandler.sendAllMessages(); + + assertFalse(mFullScreenMagnificationController.setScaleAndCenter(displayId, + targetScale, center.x, center.y, mEndCallback, SERVICE_ID_1)); + mMessageCapturingHandler.sendAllMessages(); + + verify(mMockValueAnimator, never()).start(); + verify(mEndCallback).run(); } @Test @@ -639,6 +670,69 @@ public class FullScreenMagnificationControllerTest { } @Test + public void testReset_notMagnifying_noStateChangeButInvokeCallback() { + for (int i = 0; i < DISPLAY_COUNT; i++) { + reset_notMagnifying_noStateChangeButInvokeCallback(i); + Mockito.reset(mEndCallback); + } + } + + private void reset_notMagnifying_noStateChangeButInvokeCallback(int displayId) { + register(displayId); + + assertFalse(mFullScreenMagnificationController.reset(displayId, mEndCallback)); + mMessageCapturingHandler.sendAllMessages(); + + verify(mMockAms, never()).notifyMagnificationChanged(eq(displayId), + any(Region.class), anyFloat(), anyFloat(), anyFloat()); + verify(mEndCallback).run(); + } + + @Test + public void testReset_Magnifying_resetsMagnificationAndInvokeLastEndCallback() { + for (int i = 0; i < DISPLAY_COUNT; i++) { + reset_Magnifying_resetsMagnificationAndInvokeLastEndCallback(i); + } + } + + private void reset_Magnifying_resetsMagnificationAndInvokeLastEndCallback(int displayId) { + register(displayId); + float scale = 2.5f; + PointF firstCenter = INITIAL_BOUNDS_LOWER_RIGHT_2X_CENTER; + assertTrue(mFullScreenMagnificationController.setScaleAndCenter(displayId, + scale, firstCenter.x, firstCenter.y, mEndCallback, SERVICE_ID_1)); + mMessageCapturingHandler.sendAllMessages(); + Mockito.reset(mMockValueAnimator); + // Stubs the logic after the animation is started. + doAnswer(invocation -> { + mStateListener.onAnimationEnd(mMockValueAnimator); + return null; + }).when(mMockValueAnimator).cancel(); + when(mMockValueAnimator.isRunning()).thenReturn(true); + // Intermediate point + float fraction = 0.33f; + when(mMockValueAnimator.getAnimatedFraction()).thenReturn(fraction); + mTargetAnimationListener.onAnimationUpdate(mMockValueAnimator); + Runnable lastEndCallback = Mockito.mock(Runnable.class); + + assertTrue(mFullScreenMagnificationController.reset(displayId, lastEndCallback)); + mMessageCapturingHandler.sendAllMessages(); + + // Verify expected actions. + verify(mEndCallback, never()).run(); + verify(mMockValueAnimator).start(); + verify(mMockValueAnimator).cancel(); + + // Fast-forward the animation to the end. + when(mMockValueAnimator.getAnimatedFraction()).thenReturn(1.0f); + mTargetAnimationListener.onAnimationUpdate(mMockValueAnimator); + mStateListener.onAnimationEnd(mMockValueAnimator); + + assertFalse(mFullScreenMagnificationController.isMagnifying(DISPLAY_0)); + verify(lastEndCallback).run(); + } + + @Test public void testTurnScreenOff_resetsMagnification() { register(DISPLAY_0); register(DISPLAY_1); @@ -1043,6 +1137,10 @@ public class FullScreenMagnificationControllerTest { ArgumentCaptor.forClass(ValueAnimator.AnimatorUpdateListener.class); verify(mMockValueAnimator).addUpdateListener(listenerArgumentCaptor.capture()); mTargetAnimationListener = listenerArgumentCaptor.getValue(); + ArgumentCaptor<ValueAnimator.AnimatorListener> animatorListenerArgumentCaptor = + ArgumentCaptor.forClass(ValueAnimator.AnimatorListener.class); + verify(mMockValueAnimator).addListener(animatorListenerArgumentCaptor.capture()); + mStateListener = animatorListenerArgumentCaptor.getValue(); Mockito.reset(mMockValueAnimator); // Ignore other initialization } diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java index ee564a93e022..0ea84da54b60 100644 --- a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java +++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java @@ -1281,27 +1281,25 @@ public class SoundTriggerService extends SystemService { attributesBuilder.setInternalCapturePreset(MediaRecorder.AudioSource.HOTWORD); AudioAttributes attributes = attributesBuilder.build(); - // Use same AudioFormat processing as in RecognitionEvent.fromParcel AudioFormat originalFormat = event.getCaptureFormat(); - AudioFormat captureFormat = (new AudioFormat.Builder()) - .setChannelMask(originalFormat.getChannelMask()) - .setEncoding(originalFormat.getEncoding()) - .setSampleRate(originalFormat.getSampleRate()) - .build(); - - int bufferSize = AudioRecord.getMinBufferSize( - captureFormat.getSampleRate() == AudioFormat.SAMPLE_RATE_UNSPECIFIED - ? AudioFormat.SAMPLE_RATE_HZ_MAX - : captureFormat.getSampleRate(), - captureFormat.getChannelCount() == 2 - ? AudioFormat.CHANNEL_IN_STEREO - : AudioFormat.CHANNEL_IN_MONO, - captureFormat.getEncoding()); sEventLogger.log(new SoundTriggerLogger.StringEvent("createAudioRecordForEvent")); - return new AudioRecord(attributes, captureFormat, bufferSize, - event.getCaptureSession()); + try { + return (new AudioRecord.Builder()) + .setAudioAttributes(attributes) + .setAudioFormat((new AudioFormat.Builder()) + .setChannelMask(originalFormat.getChannelMask()) + .setEncoding(originalFormat.getEncoding()) + .setSampleRate(originalFormat.getSampleRate()) + .build()) + .setSessionId(event.getCaptureSession()) + .build(); + } catch (IllegalArgumentException | UnsupportedOperationException e) { + Slog.w(TAG, mPuuid + ": createAudioRecordForEvent(" + event + + "), failed to create AudioRecord"); + return null; + } } @Override @@ -1331,8 +1329,10 @@ public class SoundTriggerService extends SystemService { // Currently we need to start and release the audio record to reset // the DSP even if we don't want to process the event - capturedData.startRecording(); - capturedData.release(); + if (capturedData != null) { + capturedData.startRecording(); + capturedData.release(); + } } })); } diff --git a/telephony/api/system-current.txt b/telephony/api/system-current.txt index ef94c7677a17..09c16595e2c7 100644 --- a/telephony/api/system-current.txt +++ b/telephony/api/system-current.txt @@ -316,6 +316,7 @@ package android.telephony { method @Deprecated public int getDataConnectionApnTypeBitMask(); method @Deprecated public int getDataConnectionFailCause(); method @Deprecated public int getDataConnectionState(); + method public int getId(); } public final class PreciseDisconnectCause { diff --git a/telephony/java/android/telephony/PreciseDataConnectionState.java b/telephony/java/android/telephony/PreciseDataConnectionState.java index aee861768209..fd9f46011c7e 100644 --- a/telephony/java/android/telephony/PreciseDataConnectionState.java +++ b/telephony/java/android/telephony/PreciseDataConnectionState.java @@ -28,11 +28,15 @@ import android.net.LinkProperties; import android.os.Build; import android.os.Parcel; import android.os.Parcelable; +import android.telephony.AccessNetworkConstants.TransportType; import android.telephony.Annotation.ApnType; import android.telephony.Annotation.DataFailureCause; import android.telephony.Annotation.DataState; import android.telephony.Annotation.NetworkType; import android.telephony.data.ApnSetting; +import android.telephony.data.DataCallResponse; + +import com.android.internal.telephony.util.TelephonyUtils; import java.util.Objects; @@ -53,6 +57,8 @@ import java.util.Objects; * */ public final class PreciseDataConnectionState implements Parcelable { + private final @TransportType int mTransportType; + private final int mId; private final @DataState int mState; private final @NetworkType int mNetworkType; private final @DataFailureCause int mFailCause; @@ -74,16 +80,20 @@ public final class PreciseDataConnectionState implements Parcelable { @ApnType int apnTypes, @NonNull String apn, @Nullable LinkProperties linkProperties, @DataFailureCause int failCause) { - this(state, networkType, linkProperties, failCause, new ApnSetting.Builder() - .setApnTypeBitmask(apnTypes) - .setApnName(apn) - .build()); + this(AccessNetworkConstants.TRANSPORT_TYPE_INVALID, -1, state, networkType, + linkProperties, failCause, new ApnSetting.Builder() + .setApnTypeBitmask(apnTypes) + .setApnName(apn) + .setEntryName(apn) + .build()); } /** * Constructor of PreciseDataConnectionState * + * @param transportType The transport of the data connection + * @param id The id of the data connection * @param state The state of the data connection * @param networkType The access network that is/would carry this data connection * @param linkProperties If the data connection is connected, the properties of the connection @@ -92,11 +102,12 @@ public final class PreciseDataConnectionState implements Parcelable { * @param apnSetting If there is a valid APN for this Data Connection, then the APN Settings; * if there is no valid APN setting for the specific type, then this will be null */ - private PreciseDataConnectionState(@DataState int state, - @NetworkType int networkType, - @Nullable LinkProperties linkProperties, - @DataFailureCause int failCause, - @Nullable ApnSetting apnSetting) { + private PreciseDataConnectionState(@TransportType int transportType, int id, + @DataState int state, @NetworkType int networkType, + @Nullable LinkProperties linkProperties, @DataFailureCause int failCause, + @Nullable ApnSetting apnSetting) { + mTransportType = transportType; + mId = id; mState = state; mNetworkType = networkType; mLinkProperties = linkProperties; @@ -110,6 +121,8 @@ public final class PreciseDataConnectionState implements Parcelable { * @hide */ private PreciseDataConnectionState(Parcel in) { + mTransportType = in.readInt(); + mId = in.readInt(); mState = in.readInt(); mNetworkType = in.readInt(); mLinkProperties = in.readParcelable(LinkProperties.class.getClassLoader()); @@ -144,7 +157,29 @@ public final class PreciseDataConnectionState implements Parcelable { } /** - * Returns the high-level state of this data connection. + * @return The transport type of this data connection. + */ + public @TransportType int getTransportType() { + return mTransportType; + } + + /** + * @return The unique id of the data connection + * + * Note this is the id assigned in {@link DataCallResponse}. + * The id remains the same for data connection handover between + * {@link AccessNetworkConstants#TRANSPORT_TYPE_WLAN} and + * {@link AccessNetworkConstants#TRANSPORT_TYPE_WWAN} + * + * @hide + */ + @SystemApi + public int getId() { + return mId; + } + + /** + * @return The high-level state of this data connection. */ public @DataState int getState() { return mState; @@ -222,7 +257,9 @@ public final class PreciseDataConnectionState implements Parcelable { /** * Return the APN Settings for this data connection. * - * @return the ApnSetting that was used to configure this data connection. + * @return the ApnSetting that was used to configure this data connection. Note that a data + * connection cannot be established without a valid {@link ApnSetting}. The return value would + * never be {@code null} even though it has {@link Nullable} annotation. */ public @Nullable ApnSetting getApnSetting() { return mApnSetting; @@ -235,6 +272,8 @@ public final class PreciseDataConnectionState implements Parcelable { @Override public void writeToParcel(@NonNull Parcel out, int flags) { + out.writeInt(mTransportType); + out.writeInt(mId); out.writeInt(mState); out.writeInt(mNetworkType); out.writeParcelable(mLinkProperties, flags); @@ -256,7 +295,8 @@ public final class PreciseDataConnectionState implements Parcelable { @Override public int hashCode() { - return Objects.hash(mState, mNetworkType, mFailCause, mLinkProperties, mApnSetting); + return Objects.hash(mTransportType, mId, mState, mNetworkType, mFailCause, + mLinkProperties, mApnSetting); } @@ -265,7 +305,9 @@ public final class PreciseDataConnectionState implements Parcelable { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; PreciseDataConnectionState that = (PreciseDataConnectionState) o; - return mState == that.mState + return mTransportType == that.mTransportType + && mId == that.mId + && mState == that.mState && mNetworkType == that.mNetworkType && mFailCause == that.mFailCause && Objects.equals(mLinkProperties, that.mLinkProperties) @@ -277,14 +319,14 @@ public final class PreciseDataConnectionState implements Parcelable { public String toString() { StringBuilder sb = new StringBuilder(); - sb.append("Data Connection state: " + mState); - sb.append(", Network type: " + mNetworkType); - sb.append(", APN types: " + ApnSetting.getApnTypesStringFromBitmask( - getDataConnectionApnTypeBitMask())); - sb.append(", APN: " + getDataConnectionApn()); - sb.append(", Link properties: " + mLinkProperties); - sb.append(", Fail cause: " + DataFailCause.toString(mFailCause)); - sb.append(", Apn Setting: " + mApnSetting); + sb.append(" state: " + TelephonyUtils.dataStateToString(mState)); + sb.append(", transport: " + + AccessNetworkConstants.transportTypeToString(mTransportType)); + sb.append(", id: " + mId); + sb.append(", network type: " + TelephonyManager.getNetworkTypeName(mNetworkType)); + sb.append(", APN Setting: " + mApnSetting); + sb.append(", link properties: " + mLinkProperties); + sb.append(", fail cause: " + DataFailCause.toString(mFailCause)); return sb.toString(); } @@ -295,6 +337,15 @@ public final class PreciseDataConnectionState implements Parcelable { * @hide */ public static final class Builder { + /** The transport type of the data connection */ + private @TransportType int mTransportType = AccessNetworkConstants.TRANSPORT_TYPE_INVALID; + + /** + * The unique ID of the data connection. This is the id assigned in + * {@link DataCallResponse)}. + */ + private int mId = -1; + /** The state of the data connection */ private @DataState int mState = TelephonyManager.DATA_UNKNOWN; @@ -314,12 +365,34 @@ public final class PreciseDataConnectionState implements Parcelable { private @Nullable ApnSetting mApnSetting = null; /** + * Set the transport type of the data connection. + * + * @param transportType The transport type of the data connection + * @return The builder + */ + public @NonNull Builder setTransportType(@TransportType int transportType) { + mTransportType = transportType; + return this; + } + + /** + * Set the id of the data connection. + * + * @param id The id of the data connection + * @return The builder + */ + public @NonNull Builder setId(int id) { + mId = id; + return this; + } + + /** * Set the state of the data connection. * * @param state The state of the data connection * @return The builder */ - public Builder setState(@DataState int state) { + public @NonNull Builder setState(@DataState int state) { mState = state; return this; } @@ -330,7 +403,7 @@ public final class PreciseDataConnectionState implements Parcelable { * @param networkType The network type * @return The builder */ - public Builder setNetworkType(@NetworkType int networkType) { + public @NonNull Builder setNetworkType(@NetworkType int networkType) { mNetworkType = networkType; return this; } @@ -341,7 +414,7 @@ public final class PreciseDataConnectionState implements Parcelable { * @param linkProperties Link properties * @return The builder */ - public Builder setLinkProperties(@NonNull LinkProperties linkProperties) { + public @NonNull Builder setLinkProperties(LinkProperties linkProperties) { mLinkProperties = linkProperties; return this; } @@ -353,7 +426,7 @@ public final class PreciseDataConnectionState implements Parcelable { * error code indicating the cause of the failure. * @return The builder */ - public Builder setFailCause(@DataFailureCause int failCause) { + public @NonNull Builder setFailCause(@DataFailureCause int failCause) { mFailCause = failCause; return this; } @@ -364,7 +437,7 @@ public final class PreciseDataConnectionState implements Parcelable { * @param apnSetting APN setting * @return This builder */ - public Builder setApnSetting(@NonNull ApnSetting apnSetting) { + public @NonNull Builder setApnSetting(@NonNull ApnSetting apnSetting) { mApnSetting = apnSetting; return this; } @@ -375,8 +448,8 @@ public final class PreciseDataConnectionState implements Parcelable { * @return The {@link PreciseDataConnectionState} instance */ public PreciseDataConnectionState build() { - return new PreciseDataConnectionState(mState, mNetworkType, mLinkProperties, mFailCause, - mApnSetting); + return new PreciseDataConnectionState(mTransportType, mId, mState, mNetworkType, + mLinkProperties, mFailCause, mApnSetting); } } } diff --git a/telephony/java/android/telephony/data/ApnSetting.java b/telephony/java/android/telephony/data/ApnSetting.java index e60ae896f9f8..ff9329ef9742 100644 --- a/telephony/java/android/telephony/data/ApnSetting.java +++ b/telephony/java/android/telephony/data/ApnSetting.java @@ -1214,12 +1214,16 @@ public class ApnSetting implements Parcelable { return false; } - // TODO - if we have this function we should also have hashCode. - // Also should handle changes in type order and perhaps case-insensitivity. + @Override + public int hashCode() { + return Objects.hash(mApnName, mProxyAddress, mProxyPort, mMmsc, mMmsProxyAddress, + mMmsProxyPort, mUser, mPassword, mAuthType, mApnTypeBitmask, mId, mOperatorNumeric, + mProtocol, mRoamingProtocol, mMtu, mCarrierEnabled, mNetworkTypeBitmask, mProfileId, + mPersistent, mMaxConns, mWaitTime, mMaxConnsTime, mMvnoType, mMvnoMatchData, + mApnSetId, mCarrierId, mSkip464Xlat); + } - /** - * @hide - */ + @Override public boolean equals(Object o) { if (o instanceof ApnSetting == false) { return false; diff --git a/tools/stats_log_api_gen/main.cpp b/tools/stats_log_api_gen/main.cpp index d21018463868..28302493a8e1 100644 --- a/tools/stats_log_api_gen/main.cpp +++ b/tools/stats_log_api_gen/main.cpp @@ -15,8 +15,6 @@ #include "native_writer.h" #include "utils.h" -using namespace google::protobuf; - namespace android { namespace stats_log_api_gen { |