Merge "CameraITS: Force stop the app before loading scene." into tm-dev
diff --git a/apps/CameraITS/build/scripts/gpylint_rcfile b/apps/CameraITS/build/scripts/gpylint_rcfile
index fe9f3d1..38c1693 100644
--- a/apps/CameraITS/build/scripts/gpylint_rcfile
+++ b/apps/CameraITS/build/scripts/gpylint_rcfile
@@ -61,9 +61,6 @@
 # Inject some known modules.
 inject-known-modules=no
 
-# The import path resolver
-resolver=blaze
-
 
 [REPORTS]
 
diff --git a/apps/CameraITS/tests/scene1_1/test_ae_af.py b/apps/CameraITS/tests/scene1_1/test_ae_af.py
index 09a1470..852c786 100644
--- a/apps/CameraITS/tests/scene1_1/test_ae_af.py
+++ b/apps/CameraITS/tests/scene1_1/test_ae_af.py
@@ -67,8 +67,8 @@
                                                      do_awb=three_a_req[2],
                                                      mono_camera=mono_camera)
 
-        except error_util.CameraItsError:
-          raise AssertionError(f'{k} did not converge.')
+        except error_util.CameraItsError as e_util:
+          raise AssertionError(f'{k} did not converge.') from e_util
 
         logging.debug('AWB gains: %s, xform: %s', str(awb_gains),
                       str(awb_xform))
diff --git a/apps/CameraITS/tests/scene1_1/test_capture_result.py b/apps/CameraITS/tests/scene1_1/test_capture_result.py
index 304a737..f3a9e9d 100644
--- a/apps/CameraITS/tests/scene1_1/test_capture_result.py
+++ b/apps/CameraITS/tests/scene1_1/test_capture_result.py
@@ -213,7 +213,7 @@
             metadata['android.tonemap.curve']['green'],
             metadata['android.tonemap.curve']['blue']]
   logging.debug('Tonemap: %s', str(curves[0][1::16]))
-  for j, c in enumerate(curves):
+  for _, c in enumerate(curves):
     if not c:
       raise AssertionError('c in curves is empty.')
     if not all([np.isclose(c[i], c[i+1], atol=ISCLOSE_ATOL)
diff --git a/apps/CameraITS/tests/scene1_2/test_raw_sensitivity.py b/apps/CameraITS/tests/scene1_2/test_raw_sensitivity.py
index 8c542ab..62a017b 100644
--- a/apps/CameraITS/tests/scene1_2/test_raw_sensitivity.py
+++ b/apps/CameraITS/tests/scene1_2/test_raw_sensitivity.py
@@ -63,7 +63,6 @@
           camera_properties_utils.per_frame_control(props) and
           not camera_properties_utils.mono_camera(props))
       name_with_log_path = os.path.join(self.log_path, NAME)
-      camera_fov = float(cam.calc_camera_fov(props))
 
       # Load chart for scene (chart_distance=0 for no chart scaling)
       its_session_utils.load_scene(
diff --git a/apps/CameraITS/tests/scene2_a/test_format_combos.py b/apps/CameraITS/tests/scene2_a/test_format_combos.py
index 7568da7..c05301b 100644
--- a/apps/CameraITS/tests/scene2_a/test_format_combos.py
+++ b/apps/CameraITS/tests/scene2_a/test_format_combos.py
@@ -147,7 +147,7 @@
               if STOP_AT_FIRST_FAILURE:
                 raise AssertionError(
                     f'Capture fail at combo req: {req_str}, fmt: {fmt_combo}, '
-                    f'burst: {burst_len}')
+                    f'burst: {burst_len}') from e
             n += 1
 
       num_fail = len(failures)
diff --git a/apps/CameraITS/tests/scene4/test_preview_stabilization_fov.py b/apps/CameraITS/tests/scene4/test_preview_stabilization_fov.py
index e77a702..3959b42 100644
--- a/apps/CameraITS/tests/scene4/test_preview_stabilization_fov.py
+++ b/apps/CameraITS/tests/scene4/test_preview_stabilization_fov.py
@@ -148,7 +148,7 @@
       camera_properties_utils.skip_unless(
           first_api_level >= its_session_utils.ANDROID13_API_LEVEL,
           'First API level should be {} or higher. Found {}.'.format(
-            its_session_utils.ANDROID13_API_LEVEL, first_api_level))
+              its_session_utils.ANDROID13_API_LEVEL, first_api_level))
 
       supported_stabilization_modes = props[
           'android.control.availableVideoStabilizationModes'
diff --git a/apps/CameraITS/tests/scene4/test_video_aspect_ratio_and_crop.py b/apps/CameraITS/tests/scene4/test_video_aspect_ratio_and_crop.py
index eca64ef..06f3f12 100644
--- a/apps/CameraITS/tests/scene4/test_video_aspect_ratio_and_crop.py
+++ b/apps/CameraITS/tests/scene4/test_video_aspect_ratio_and_crop.py
@@ -182,7 +182,8 @@
 
           for hlg10_param in hlg10_params:
             video_recording_obj = cam.do_basic_recording(
-                profile_id, quality, _VIDEO_RECORDING_DURATION_SECONDS, 0, hlg10_param)
+                profile_id, quality, _VIDEO_RECORDING_DURATION_SECONDS, 0,
+                hlg10_param)
             logging.debug('video_recording_obj: %s', video_recording_obj)
             # TODO(ruchamk): Modify video recording object to send videoFrame
             # width and height instead of videoSize to avoid string operation
@@ -196,7 +197,8 @@
                                self.log_path])
             logging.debug('Recorded video is available at: %s',
                           self.log_path)
-            video_file_name = video_recording_obj['recordedOutputPath'].split('/')[-1]
+            video_file_name = video_recording_obj[
+                'recordedOutputPath'].split('/')[-1]
             logging.debug('video_file_name: %s', video_file_name)
 
             key_frame_files = []
@@ -208,7 +210,8 @@
             last_key_frame_file = video_processing_utils.get_key_frame_to_process(
                 key_frame_files)
             logging.debug('last_key_frame: %s', last_key_frame_file)
-            last_key_frame_path = os.path.join(self.log_path, last_key_frame_file)
+            last_key_frame_path = os.path.join(
+                self.log_path, last_key_frame_file)
 
             # Convert lastKeyFrame to numpy array
             np_image = image_processing_utils.convert_image_to_numpy_array(
@@ -222,7 +225,7 @@
 
             max_img_value = _MAX_8BIT_IMGS
             if hlg10_param:
-                max_img_value = _MAX_10BIT_IMGS
+              max_img_value = _MAX_10BIT_IMGS
 
             # Check pass/fail for fov coverage for all fmts in AR_CHECKED
             fov_chk_msg = image_fov_utils.check_fov(
@@ -232,7 +235,8 @@
                   os.path.join(self.log_path, _NAME), quality, width, height)
               fov_chk_quality_msg = f'Quality: {quality} {fov_chk_msg}'
               failed_fov.append(fov_chk_quality_msg)
-              image_processing_utils.write_image(np_image/max_img_value, img_name, True)
+              image_processing_utils.write_image(
+                  np_image/max_img_value, img_name, True)
 
             # Check pass/fail for aspect ratio.
             ar_chk_msg = image_fov_utils.check_ar(
@@ -242,14 +246,16 @@
               img_name = '%s_%s_w%d_h%d_ar.png' % (
                   os.path.join(self.log_path, _NAME), quality, width, height)
               failed_ar.append(ar_chk_msg)
-              image_processing_utils.write_image(np_image/max_img_value, img_name, True)
+              image_processing_utils.write_image(
+                  np_image/max_img_value, img_name, True)
 
             # Check pass/fail for crop.
             if run_crop_test:
               # Normalize the circle size to 1/4 of the image size, so that
               # circle size won't affect the crop test result
               crop_thresh_factor = ((min(ref_fov['w'], ref_fov['h']) / 4.0) /
-                                    max(ref_fov['circle_w'], ref_fov['circle_h']))
+                                    max(ref_fov['circle_w'],
+                                        ref_fov['circle_h']))
               crop_chk_msg = image_fov_utils.check_crop(
                   circle, cc_ct_gt, width, height,
                   f'{quality}', crop_thresh_factor)
diff --git a/apps/CameraITS/tests/scene6/test_zoom.py b/apps/CameraITS/tests/scene6/test_zoom.py
index c828ad5..d4fa21c 100644
--- a/apps/CameraITS/tests/scene6/test_zoom.py
+++ b/apps/CameraITS/tests/scene6/test_zoom.py
@@ -273,13 +273,13 @@
           if circle_cropped(circle, size):
             logging.debug('zoom %.2f is too large! Skip further captures', z)
             break
-        except AssertionError:
+        except AssertionError as e:
           if z/z_list[0] >= ZOOM_MAX_THRESH:
             break
           else:
             raise AssertionError(
                 f'No circle was detected for zoom ratio <= {ZOOM_MAX_THRESH}. '
-                'Please take pictures according to instructions carefully!')
+                'Take pictures according to instructions carefully!') from e
         test_data[i] = {'z': z, 'circle': circle, 'r_tol': radius_tol,
                         'o_tol': offset_tol, 'fl': cap_fl}
 
diff --git a/apps/CameraITS/tests/sensor_fusion/test_preview_stabilization.py b/apps/CameraITS/tests/sensor_fusion/test_preview_stabilization.py
index 713d577..8f199ce 100644
--- a/apps/CameraITS/tests/sensor_fusion/test_preview_stabilization.py
+++ b/apps/CameraITS/tests/sensor_fusion/test_preview_stabilization.py
@@ -137,6 +137,8 @@
       # Initialize rotation rig
       rot_rig['cntl'] = self.rotator_cntl
       rot_rig['ch'] = self.rotator_ch
+      if rot_rig['cntl'].lower() != 'arduino':
+        raise AssertionError(f'You must use the arduino controller for {_NAME}.')
 
       # List of video resolutions to test
       supported_preview_sizes = cam.get_supported_preview_sizes(self.camera_id)
diff --git a/apps/CameraITS/tests/sensor_fusion/test_sensor_fusion.py b/apps/CameraITS/tests/sensor_fusion/test_sensor_fusion.py
index e6eec9f..1939935 100644
--- a/apps/CameraITS/tests/sensor_fusion/test_sensor_fusion.py
+++ b/apps/CameraITS/tests/sensor_fusion/test_sensor_fusion.py
@@ -337,7 +337,7 @@
           " smaller values of 'w', 'h', 'fps', or 'test_length'.")
 
     if replay:
-      events, frames, _, h = load_data()
+      events, frames, _, _ = load_data()
     else:
       with its_session_utils.ItsSession(
           device_id=self.dut.serial,
diff --git a/apps/CameraITS/tests/sensor_fusion/test_video_stabilization.py b/apps/CameraITS/tests/sensor_fusion/test_video_stabilization.py
index 9417d18..c834ba3 100644
--- a/apps/CameraITS/tests/sensor_fusion/test_video_stabilization.py
+++ b/apps/CameraITS/tests/sensor_fusion/test_video_stabilization.py
@@ -156,6 +156,8 @@
       # Initialize rotation rig
       rot_rig['cntl'] = self.rotator_cntl
       rot_rig['ch'] = self.rotator_ch
+      if rot_rig['cntl'].lower() != 'arduino':
+        raise AssertionError(f'You must use the arduino controller for {_NAME}.')
 
       # Create list of video qualities to test
       supported_video_qualities = cam.get_supported_video_qualities(
diff --git a/apps/CameraITS/utils/image_processing_utils.py b/apps/CameraITS/utils/image_processing_utils.py
index d0bf08e..19d76c3 100644
--- a/apps/CameraITS/utils/image_processing_utils.py
+++ b/apps/CameraITS/utils/image_processing_utils.py
@@ -137,7 +137,7 @@
   # Cut out the 4x2b LSBs and put each in bits [1:0] of their own 8b words.
   lsbs = img[::, 4::5].reshape(h, w // 4)
   lsbs = numpy.right_shift(
-      numpy.packbits(numpy.unpackbits(lsbs).reshape(h, w // 4, 4, 2), 3), 6)
+      numpy.packbits(numpy.unpackbits(lsbs).reshape((h, w // 4, 4, 2)), 3), 6)
   # Pair the LSB bits group to 0th pixel instead of 3rd pixel
   lsbs = lsbs.reshape(h, w // 4, 4)[:, :, ::-1]
   lsbs = lsbs.reshape(h, w)
@@ -190,7 +190,7 @@
   # Cut out the 2x4b LSBs and put each in bits [3:0] of their own 8b words.
   lsbs = img[::, 2::3].reshape(h, w // 2)
   lsbs = numpy.right_shift(
-      numpy.packbits(numpy.unpackbits(lsbs).reshape(h, w // 2, 2, 4), 3), 4)
+      numpy.packbits(numpy.unpackbits(lsbs).reshape((h, w // 2, 2, 4)), 3), 4)
   # Pair the LSB bits group to pixel 0 instead of pixel 1
   lsbs = lsbs.reshape(h, w // 2, 2)[:, :, ::-1]
   lsbs = lsbs.reshape(h, w)
@@ -243,7 +243,7 @@
   img = Image.open(io.BytesIO(jpeg_buffer))
   w = img.size[0]
   h = img.size[1]
-  return numpy.array(img).reshape(h, w, 3) / 255.0
+  return numpy.array(img).reshape((h, w, 3)) / 255.0
 
 
 def convert_image_to_numpy_array(image_path):
@@ -453,7 +453,7 @@
   img = (((img.reshape(h, w, 3) - black_levels) * scale) * gains).clip(0.0, 1.0)
   if apply_ccm_raw_to_rgb:
     img = numpy.dot(
-        img.reshape(w * h, 3), ccm.T).reshape(h, w, 3).clip(0.0, 1.0)
+        img.reshape(w * h, 3), ccm.T).reshape((h, w, 3)).clip(0.0, 1.0)
   return img
 
 
@@ -938,7 +938,7 @@
     ref_image = [0.1, 0.2, 0.3]
     lut_max = 65536
     lut = numpy.array([i*2 for i in range(lut_max)])
-    x = numpy.array(ref_image).reshape(1, 1, 3)
+    x = numpy.array(ref_image).reshape((1, 1, 3))
     y = apply_lut_to_image(x, lut).reshape(3).tolist()
     y_ref = [i*2 for i in ref_image]
     self.assertTrue(numpy.allclose(y, y_ref, atol=1/lut_max))
diff --git a/apps/CameraITS/utils/its_session_utils.py b/apps/CameraITS/utils/its_session_utils.py
index 722f586..4a6cbf9 100644
--- a/apps/CameraITS/utils/its_session_utils.py
+++ b/apps/CameraITS/utils/its_session_utils.py
@@ -134,10 +134,10 @@
       try:
         socket_lock.bind((ItsSession.IPADDR, ItsSession.LOCK_PORT))
         break
-      except (socket.error, socket.timeout):
+      except (socket.error, socket.timeout) as socket_issue:
         if i == num_retries - 1:
-          raise error_util.CameraItsError(self._device_id,
-                                          'socket lock returns error')
+          raise error_util.CameraItsError(
+              self._device_id, 'socket lock returns error') from socket_issue
         else:
           time.sleep(retry_wait_time_sec)
 
@@ -545,8 +545,9 @@
       VideoRecordingObject: {
         'tag': 'recordingResponse',
         'objValue': {
-          'recordedOutputPath': '/storage/emulated/0/Android/data/com.android.cts.verifier'
-                                '/files/VideoITS/VID_20220324_080414_0_CIF_352x288.mp4',
+          'recordedOutputPath': '/storage/emulated/0/Android/data/'
+                                'com.android.cts.verifier/files/VideoITS/'
+                                'VID_20220324_080414_0_CIF_352x288.mp4',
           'quality': 'preview',
           'videoSize': '352x288'
         }
@@ -1478,8 +1479,8 @@
   try:
     build_sdk_version = int(subprocess.check_output(cmd.split()).rstrip())
     logging.debug('Build SDK version: %d', build_sdk_version)
-  except (subprocess.CalledProcessError, ValueError):
-    raise AssertionError('No build_sdk_version.')
+  except (subprocess.CalledProcessError, ValueError) as exp_errors:
+    raise AssertionError('No build_sdk_version.') from exp_errors
   return build_sdk_version
 
 
diff --git a/apps/CameraITS/utils/sensor_fusion_utils.py b/apps/CameraITS/utils/sensor_fusion_utils.py
index 0f83af9..327b233 100644
--- a/apps/CameraITS/utils/sensor_fusion_utils.py
+++ b/apps/CameraITS/utils/sensor_fusion_utils.py
@@ -146,8 +146,9 @@
     time.sleep(CANAKIT_CMD_TIME)  # This is critical for relay.
     canakit_serial_port.write(cmd_str.encode())
 
-  except IOError:
-    raise IOError(f'Port {CANAKIT_VID}:{CANAKIT_PID} is not open!')
+  except IOError as io_error:
+    raise IOError(
+        f'Port {CANAKIT_VID}:{CANAKIT_PID} is not open!') from io_error
 
 
 def canakit_set_relay_channel_state(canakit_port, ch, state):
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index 0b3e811..35afa20 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -105,7 +105,9 @@
     <uses-permission android:name="android.permission.USE_EXACT_ALARM" />
 
     <!-- Needed for Wi-Fi Direct tests from T -->
-    <uses-permission android:name="android.permission.NEARBY_WIFI_DEVICES" />
+    <uses-permission
+        android:name="android.permission.NEARBY_WIFI_DEVICES"
+        android:usesPermissionFlags="neverForLocation" />
 
     <!-- READ_LOGS User Consent Test from T -->
     <uses-permission android:name="android.permission.READ_LOGS" />
diff --git a/apps/CtsVerifier/res/layout/audio_dev_notify.xml b/apps/CtsVerifier/res/layout/audio_dev_notify.xml
index e8f49ce..6fa178d 100644
--- a/apps/CtsVerifier/res/layout/audio_dev_notify.xml
+++ b/apps/CtsVerifier/res/layout/audio_dev_notify.xml
@@ -38,6 +38,12 @@
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:orientation="vertical">
+      <Button
+          android:layout_width="match_parent"
+          android:layout_height="wrap_content"
+          android:id="@+id/audio_dev_notification_connect_clearmsgs_btn"
+          android:text="@string/audio_dev_notification_clearmsgs"/>
+
       <TextView
           android:layout_width="match_parent"
           android:layout_height="wrap_content"
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioInputDeviceNotificationsActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioInputDeviceNotificationsActivity.java
index a6709e7..9a5f314 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioInputDeviceNotificationsActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioInputDeviceNotificationsActivity.java
@@ -81,6 +81,17 @@
         mInfoView.setText(mContext.getResources().getString(
                 R.string.audio_devices_notification_instructions));
 
+        findViewById(R.id.audio_dev_notification_connect_clearmsgs_btn)
+                .setOnClickListener(new View.OnClickListener() {
+                    public void onClick(View v) {
+                        mConnectView.setText("");
+                        mConnectReceived = false;
+                        mDisconnectView.setText("");
+                        mDisconnectReceived = false;
+                        calculatePass();
+                    }
+                });
+
         AudioManager audioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
         audioManager.registerAudioDeviceCallback(new TestAudioDeviceCallback(), null);
 
@@ -90,6 +101,8 @@
         setInfoResources(R.string.audio_in_devices_notifications_test,
                 R.string.audio_in_devices_infotext, -1);
         setPassFailButtonClickListeners();
+
+        calculatePass();
     }
 
     @Override
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioInputRoutingNotificationsActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioInputRoutingNotificationsActivity.java
index 7399f33..38d99b4 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioInputRoutingNotificationsActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioInputRoutingNotificationsActivity.java
@@ -129,6 +129,7 @@
             AudioDeviceInfo routedDevice = audioRecord.getRoutedDevice();
             CharSequence deviceName = routedDevice != null ? routedDevice.getProductName() : "none";
             mConnectedPeripheralName = deviceName.toString();
+
             int deviceType = routedDevice != null ? routedDevice.getType() : -1;
             textView.setText(msg + " - " +
                              deviceName + " [0x" + Integer.toHexString(deviceType) + "]" +
@@ -156,8 +157,6 @@
                     R.id.audio_routingnotification_testresult)).setText(
                             "Test PASSES - No peripheral support");
         }
-
-        stopRecording();
     }
 
     protected void storeTestResults() {
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioOutputDeviceNotificationsActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioOutputDeviceNotificationsActivity.java
index c0f98d1..5fb51c4 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioOutputDeviceNotificationsActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioOutputDeviceNotificationsActivity.java
@@ -81,6 +81,17 @@
         mInfoView.setText(mContext.getResources().getString(
                 R.string.audio_devices_notification_instructions));
 
+        findViewById(R.id.audio_dev_notification_connect_clearmsgs_btn)
+                .setOnClickListener(new View.OnClickListener() {
+                    public void onClick(View v) {
+                        mConnectView.setText("");
+                        mConnectReceived = false;
+                        mDisconnectView.setText("");
+                        mDisconnectReceived = false;
+                        calculatePass();
+                    }
+                });
+
         AudioManager audioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
         audioManager.registerAudioDeviceCallback(new TestAudioDeviceCallback(), null);
 
@@ -90,6 +101,8 @@
         setInfoResources(R.string.audio_out_devices_notifications_test,
                 R.string.audio_out_devices_infotext, -1);
         setPassFailButtonClickListeners();
+
+        calculatePass();
     }
 
     @Override
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioOutputRoutingNotificationsActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioOutputRoutingNotificationsActivity.java
index e23ee17..591fe9b 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioOutputRoutingNotificationsActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioOutputRoutingNotificationsActivity.java
@@ -160,8 +160,6 @@
                     R.id.audio_routingnotification_testresult)).setText(
                     "Test PASSES - No peripheral support");
         }
-
-        stopPlayback();
     }
 
     protected void storeTestResults() {
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioWiredDeviceBaseActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioWiredDeviceBaseActivity.java
index 8348393..97813af 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioWiredDeviceBaseActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioWiredDeviceBaseActivity.java
@@ -35,7 +35,7 @@
     private Button mSupportsBtn;
     private Button mDoesntSupportBtn;
 
-    protected boolean mSupportsWiredPeripheral;
+    protected boolean mSupportsWiredPeripheral = true;
     protected String mConnectedPeripheralName;
 
     protected abstract void enableTestButtons(boolean enabled);
diff --git a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/InputDeviceInfo.kt b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/InputDeviceInfo.kt
index 2d109ba..a3e391d 100644
--- a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/InputDeviceInfo.kt
+++ b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/InputDeviceInfo.kt
@@ -16,9 +16,7 @@
 package com.android.compatibility.common.deviceinfo
 
 import android.content.Context
-
 import androidx.test.core.app.ApplicationProvider
-
 import com.android.compatibility.common.util.DeviceConfigStateManager
 import com.android.compatibility.common.util.DeviceInfoStore
 
@@ -35,10 +33,11 @@
         collectInputInfo(store, "input")
     }
 
-    private fun readDeviceConfig(namespace: String, name: String): String {
+    private fun readDeviceConfig(namespace: String, name: String, default: String): String {
         val context: Context = ApplicationProvider.getApplicationContext()
         val stateManager = DeviceConfigStateManager(context, namespace, name)
-        return stateManager.get()!!
+        val value = stateManager.get()
+        return if (value != null) value else default
     }
 
     /**
@@ -47,10 +46,15 @@
     private fun collectInputInfo(store: DeviceInfoStore, groupName: String) {
         store.startGroup(groupName)
 
-        val palmRejectionValue = readDeviceConfig("input_native_boot", "palm_rejection_enabled")
+        val palmRejectionValue = readDeviceConfig("input_native_boot", "palm_rejection_enabled", "")
         val palmRejectionEnabled = palmRejectionValue == "1" || palmRejectionValue == "true"
         store.addResult("palm_rejection_enabled", palmRejectionEnabled)
 
+        val velocityTrackerStrategyValue = readDeviceConfig(
+            "input_native_boot", "velocitytracker_strategy", "default"
+        )
+        store.addResult("velocitytracker_strategy", velocityTrackerStrategyValue)
+
         store.endGroup()
     }
 }
diff --git a/hostsidetests/compilation/src/android/compilation/cts/BackgroundDexOptimizationTest.java b/hostsidetests/compilation/src/android/compilation/cts/BackgroundDexOptimizationTest.java
index e7d954f..9affccb 100644
--- a/hostsidetests/compilation/src/android/compilation/cts/BackgroundDexOptimizationTest.java
+++ b/hostsidetests/compilation/src/android/compilation/cts/BackgroundDexOptimizationTest.java
@@ -82,6 +82,8 @@
     // Uses internal consts defined in BackgroundDexOptService only for testing purpose.
     private static final int STATUS_OK = 0;
     private static final int STATUS_CANCELLED = 1;
+    // We allow package level failure in dexopt, which will lead into this error state.
+    private static final int STATUS_DEX_OPT_FAILED = 5;
 
     private ITestDevice mDevice;
 
@@ -124,7 +126,7 @@
                 () -> getLastExecutionTime().duration >= 0);
 
         int status = getLastDexOptStatus();
-        assertThat(status).isAnyOf(STATUS_OK, STATUS_CANCELLED);
+        assertThat(status).isAnyOf(STATUS_OK, STATUS_DEX_OPT_FAILED, STATUS_CANCELLED);
         if (status == STATUS_CANCELLED) {
             assertThat(checkFinishedPostBootUpdate()).isFalse();
             // If cancelled, we can complete it by running it again.
@@ -177,7 +179,7 @@
                 () -> getLastExecutionTime().duration >= 0);
 
         int status = getLastDexOptStatus();
-        assertThat(status).isAnyOf(STATUS_OK, STATUS_CANCELLED);
+        assertThat(status).isAnyOf(STATUS_OK, STATUS_DEX_OPT_FAILED, STATUS_CANCELLED);
         if (status == STATUS_CANCELLED) {
             // If cancelled, we can complete it by running it again.
             completeIdleOptimization();
@@ -204,7 +206,7 @@
         assertThat(timeAfter.startTime).isAtLeast(timeBefore.deviceCurrentTime);
         assertThat(timeAfter.duration).isAtLeast(0);
         int status = getLastDexOptStatus();
-        assertThat(status).isEqualTo(STATUS_OK);
+        assertThat(status).isAnyOf(STATUS_OK, STATUS_DEX_OPT_FAILED);
     }
 
     private void completeIdleOptimization() throws Exception {
@@ -220,7 +222,7 @@
                 });
 
         int status = getLastDexOptStatus();
-        assertThat(status).isEqualTo(STATUS_OK);
+        assertThat(status).isAnyOf(STATUS_OK, STATUS_DEX_OPT_FAILED);
     }
 
     @After
diff --git a/hostsidetests/statsdatom/src/android/cts/statsdatom/appops/AppOpsTests.java b/hostsidetests/statsdatom/src/android/cts/statsdatom/appops/AppOpsTests.java
index c7feda6..f07f9d3 100644
--- a/hostsidetests/statsdatom/src/android/cts/statsdatom/appops/AppOpsTests.java
+++ b/hostsidetests/statsdatom/src/android/cts/statsdatom/appops/AppOpsTests.java
@@ -61,12 +61,13 @@
     protected void setUp() throws Exception {
         super.setUp();
 
-        mTransformedFromOp.clear();
-        // The hotword op is allowed to all UIDs on TV and Auto devices.
-        if (!(DeviceUtils.hasFeature(getDevice(), FEATURE_AUTOMOTIVE)
-                || DeviceUtils.hasFeature(getDevice(), FEATURE_LEANBACK_ONLY))) {
-            mTransformedFromOp.put(APP_OP_RECORD_AUDIO, APP_OP_RECORD_AUDIO_HOTWORD);
-        }
+        // Temporarily commented out until the Trusted Hotword requirement is enforced again.
+        // mTransformedFromOp.clear();
+        // // The hotword op is allowed to all UIDs on TV and Auto devices.
+        // if (!(DeviceUtils.hasFeature(getDevice(), FEATURE_AUTOMOTIVE)
+        //         || DeviceUtils.hasFeature(getDevice(), FEATURE_LEANBACK_ONLY))) {
+        //     mTransformedFromOp.put(APP_OP_RECORD_AUDIO, APP_OP_RECORD_AUDIO_HOTWORD);
+        // }
 
         assertThat(mCtsBuild).isNotNull();
         ConfigUtils.removeConfig(getDevice());
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/ActivityTransitionTests.java b/tests/framework/base/windowmanager/src/android/server/wm/ActivityTransitionTests.java
index 31bb8bf..879d397 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/ActivityTransitionTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/ActivityTransitionTests.java
@@ -304,7 +304,7 @@
                 EdgeExtensionActivity.class, extras);
         final Rect appBounds = getTopAppBounds();
         assertColorChangeXIndex(screenshots,
-                (appBounds.left + appBounds.right) / 4 * 3, testBounds);
+                appBounds.left + (appBounds.right - appBounds.left) * 3 / 4, testBounds);
     }
 
     /**
@@ -355,7 +355,7 @@
                 EdgeExtensionActivity.class, extras);
         final Rect appBounds = getTopAppBounds();
         assertColorChangeXIndex(screenshots,
-                (appBounds.left + appBounds.right) / 4, testBounds);
+            appBounds.left + (appBounds.right - appBounds.left) / 4, testBounds);
     }
 
     /**
@@ -422,9 +422,7 @@
         boolean isTransitioning;
         do {
             getWmState().computeState();
-            isTransitioning =
-                    getWmState().getDefaultDisplayLastTransition().equals("TRANSIT_ACTIVITY_OPEN")
-                    && getWmState().getDefaultDisplayAppTransitionState()
+            isTransitioning = getWmState().getDefaultDisplayAppTransitionState()
                             .equals("APP_STATE_RUNNING");
             SystemClock.sleep(10);
         } while (!isTransitioning);
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/WindowInputTests.java b/tests/framework/base/windowmanager/src/android/server/wm/WindowInputTests.java
index 669594d..e73ae81 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/WindowInputTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/WindowInputTests.java
@@ -756,8 +756,16 @@
 
         final ExecutorService executor = Executors.newSingleThreadExecutor();
         boolean[] securityExceptionCaught = new boolean[1];
+        Exception[] illegalArgumentException = new Exception[1];
         executor.execute(() -> {
-            mInstrumentation.sendPointerSync(eventDown);
+            try {
+                mInstrumentation.sendPointerSync(eventDown);
+            } catch (IllegalArgumentException e) {
+                // InputManagerService throws IllegalArgumentException when input target mismatch.
+                // Store the exception, and raise test failure later to avoid cts thread crash.
+                illegalArgumentException[0] = e;
+                return;
+            }
             for (int i = 0; i < 20; i++) {
                 final long eventTime = SystemClock.uptimeMillis();
                 final MotionEvent eventMove = MotionEvent.obtain(
@@ -766,8 +774,13 @@
                     mInstrumentation.sendPointerSync(eventMove);
                 } catch (SecurityException e) {
                     securityExceptionCaught[0] = true;
+                    return;
+                } catch (IllegalArgumentException e) {
+                    illegalArgumentException[0] = e;
+                    return;
                 }
             }
+
         });
 
         // Launch another activity, should not crash the process.
@@ -783,6 +796,11 @@
             // so the failure is thrown in the test thread.
             fail("Should be allowed to inject event.");
         }
+
+        if (illegalArgumentException[0] != null) {
+            fail("Failed to inject event due to input target mismatch: "
+                    + illegalArgumentException[0].getMessage());
+        }
     }
 
     private void waitForWindow(String name) {
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/StylusHandwritingTest.java b/tests/inputmethod/src/android/view/inputmethod/cts/StylusHandwritingTest.java
index 6395679..8cc0b8e 100644
--- a/tests/inputmethod/src/android/view/inputmethod/cts/StylusHandwritingTest.java
+++ b/tests/inputmethod/src/android/view/inputmethod/cts/StylusHandwritingTest.java
@@ -582,8 +582,8 @@
                     NOT_EXPECT_TIMEOUT);
 
             final int touchSlop = getTouchSlop();
-            final int startX = 50;
-            final int startY = 50;
+            final int startX = editText.getWidth() / 2;
+            final int startY = editText.getHeight() / 2;
             final int endX = startX + 2 * touchSlop;
             final int endY = startY + 2 * touchSlop;
             final int number = 5;
diff --git a/tests/net/src/android/net/cts/LocalSocketTest.java b/tests/net/src/android/net/cts/LocalSocketTest.java
index 39b5dbc..c302f81 100644
--- a/tests/net/src/android/net/cts/LocalSocketTest.java
+++ b/tests/net/src/android/net/cts/LocalSocketTest.java
@@ -30,12 +30,9 @@
 import android.net.LocalServerSocket;
 import android.net.LocalSocket;
 import android.net.LocalSocketAddress;
-import android.os.ParcelFileDescriptor;
-import android.os.SystemClock;
 import android.system.Os;
 import android.system.OsConstants;
 import android.system.StructTimeval;
-import android.system.UnixSocketAddress;
 
 import androidx.test.runner.AndroidJUnit4;
 
@@ -196,7 +193,7 @@
     }
 
     // http://b/31205169
-    @Test
+    @Test @IgnoreUpTo(SC_V2)  // Crashes on pre-T due to a JNI bug. See http://r.android.com/2096720
     public void testSetSoTimeout_readTimeout() throws Exception {
         String address = ADDRESS_PREFIX + "_testSetSoTimeout_readTimeout";
 
diff --git a/tests/tests/content/src/android/content/pm/cts/PackageManagerShellCommandMultiUserTest.kt b/tests/tests/content/src/android/content/pm/cts/PackageManagerShellCommandMultiUserTest.kt
index cf9dde0..155cf74 100644
--- a/tests/tests/content/src/android/content/pm/cts/PackageManagerShellCommandMultiUserTest.kt
+++ b/tests/tests/content/src/android/content/pm/cts/PackageManagerShellCommandMultiUserTest.kt
@@ -237,18 +237,18 @@
         val intentFilter = IntentFilter()
         intentFilter.addAction(Intent.ACTION_PACKAGE_FULLY_REMOVED)
         intentFilter.addDataScheme("package")
-        context.registerReceiver(
-            broadcastReceiverForPrimaryUser,
-            intentFilter,
-            null,
-            backgroundHandler,
-            RECEIVER_EXPORTED
-        )
         uiAutomation.adoptShellPermissionIdentity(
             Manifest.permission.INTERACT_ACROSS_USERS,
             Manifest.permission.INTERACT_ACROSS_USERS_FULL
         )
         try {
+            context.createContextAsUser(primaryUser.userHandle(), 0).registerReceiver(
+                broadcastReceiverForPrimaryUser,
+                intentFilter,
+                null,
+                backgroundHandler,
+                RECEIVER_EXPORTED
+            )
             context.createContextAsUser(secondaryUser.userHandle(), 0).registerReceiver(
                 broadcastReceiverForSecondaryUser,
                 intentFilter,
diff --git a/tests/tests/graphics/AndroidManifest.xml b/tests/tests/graphics/AndroidManifest.xml
index 6406133..9a1c591 100644
--- a/tests/tests/graphics/AndroidManifest.xml
+++ b/tests/tests/graphics/AndroidManifest.xml
@@ -55,6 +55,23 @@
         <activity android:name="android.graphics.drawable.cts.DrawableStubActivity"
              android:theme="@style/WhiteBackgroundNoWindowAnimation"
              android:screenOrientation="locked"/>
+
+        <activity android:name="android.graphics.cts.EmptyActivity"
+                  android:label="Empty Activity"
+                  android:exported="true">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
+            </intent-filter>
+        </activity>
+        <activity android:name="android.graphics.cts.EmptyActivity2"
+                  android:label="Empty Activity 2"
+                  android:exported="true">
+            <intent-filter>
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST"/>
+            </intent-filter>
+        </activity>
         <activity android:name="android.graphics.drawable.cts.AnimatedImageActivity"
              android:theme="@style/WhiteBackgroundNoWindowAnimation"
              android:screenOrientation="locked">
diff --git a/tests/tests/graphics/res/xml/valid_themes.xml b/tests/tests/graphics/res/xml/valid_themes.xml
index a7619d4..a7e2304 100644
--- a/tests/tests/graphics/res/xml/valid_themes.xml
+++ b/tests/tests/graphics/res/xml/valid_themes.xml
@@ -19,7 +19,7 @@
     <theme color="ffb9577a">
         <spritz>ffffff,fffbff,ffecf0,f9dbe2,dcbfc6,c0a4ab,a48a90,887076,6f595e,564147,3e2b31,27171c,000000,ffffff,fffbff,ffecf0,f2dde1,d5c2c6,b9a7aa,9e8c90,827276,6a5b5e,514347,3a2d30,24191c,000000,ffffff,fffbff,ffecf0,ffd9e2,e3bdc6,c6a2ab,aa8891,8d6e76,74565f,5b3f47,422931,2b151c,000000,ffffff,fffbff,f7efef,e8e1e1,ccc5c5,b0aaaa,958f90,7a7575,625d5e,4a4646,332f30,1e1b1b,000000,ffffff,fffbff,f7efef,e8e1e1,ccc5c5,b0aaaa,958f90,7a7575,625d5e,4a4646,332f30,1e1b1b,000000</spritz>
         <tonal_spot>ffffff,fffbff,ffecf0,ffd9e2,ffb1c8,e494ad,c67b92,a76178,8c4a60,703348,541d32,3a071d,000000,ffffff,fffbff,ffecf0,ffd9e2,e3bdc6,c6a2ab,aa8891,8d6e76,74565f,5b3f47,422931,2b151c,000000,ffffff,fffbff,ffeee2,ffdcc1,efbd94,d1a27b,b48862,976d4a,7c5635,613f20,48290b,2e1500,000000,ffffff,fffbff,faeeef,ebe0e1,cfc4c5,b3a9aa,988e90,7d7475,645c5e,4c4546,352f30,201a1b,000000,ffffff,fffbff,ffecf0,f2dde1,d5c2c6,b9a7aa,9e8c90,827276,6a5b5e,514347,3a2d30,24191c,000000</tonal_spot>
-        <vibrant>ffffff,fffbff,ffecf0,ffd9e2,ffb1c8,ff84ae,ff4896,e5007b,b90063,8e004a,650033,3e001d,000000,ffffff,fffbff,ffedec,ffdad9,f5b7b7,d79c9c,ba8382,9c6968,815252,663b3b,4c2526,331112,000000,ffffff,fffbff,ffede8,ffdbd1,ffb59f,e49982,c67f6a,a76551,8b4e3c,6e3726,532212,370d02,000000,ffffff,fffbff,ffecf0,f2dde1,d5c2c6,b9a7aa,9e8c90,827276,6a5b5e,514347,3a2d30,24191c,000000,ffffff,fffbff,ffecf0,f9dbe2,dcbfc6,c0a4ab,a48a90,887076,6f595e,564147,3e2b31,27171c,000000</vibrant>
+        <vibrant>ffffff,fffbff,ffecf0,ffd9e2,ffb1c8,ff84ae,ff4896,e5007b,b90063,8e004a,650033,3e001d,000000,ffffff,fffbff,ffedec,ffdad9,f5b7b7,d79c9c,ba8382,9c6968,815252,663b3b,4c2526,331112,000000,ffffff,fffbff,ffede8,ffdbd1,ffb59f,e49982,c67f6a,a76551,8b4e3c,6e3726,532212,370d02,000000,ffffff,fffbff,ffecf0,f6dce2,d9c0c6,bca5ab,a18b90,857176,6c5a5e,534247,3c2c30,25181c,000000,ffffff,fffbff,ffecf0,f9dbe2,dcbfc6,c0a4ab,a48a90,887076,6f595e,564147,3e2b31,27171c,000000</vibrant>
         <expressive>ffffff,fbfcff,e5f2ff,c8e6ff,8bcefd,6fb2e0,5298c4,337da8,0c648e,004c6d,00344d,001e2e,000000,ffffff,fffbff,ffede6,ffdbcb,f4ba9e,d69f85,b9856c,9b6b53,80543e,653d28,4b2714,311303,000000,ffffff,fcffdd,ebf8ad,dde9a0,c1cd86,a6b16e,8b9656,717b3e,596329,424b13,2c3400,181e00,000000,ffffff,fffbff,ffedec,f4dddd,d7c1c2,bba6a7,9f8c8c,847272,6b5a5b,524343,3b2d2d,241819,000000,ffffff,fffbff,ffedec,fcdbdb,debfc0,c2a4a5,a68a8b,8a7070,715859,584142,3f2b2c,281718,000000</expressive>
         <rainbow>ffffff,fffbff,ffecf0,ffd9e2,ffb1c8,f48bae,d57193,b55779,984061,7b2949,5e1132,3e001d,000000,ffffff,fffbff,ffecf0,ffd9e2,e3bdc6,c6a2ab,aa8891,8d6e76,74565f,5b3f47,422931,2b151c,000000,ffffff,fffbff,ffeee2,ffdcc1,efbd94,d1a27b,b48862,976d4a,7c5635,613f20,48290b,2e1500,000000,ffffff,fcfcfc,f1f1f1,e2e2e2,c6c6c6,ababab,919191,767676,5e5e5e,474747,303030,1b1b1b,000000,ffffff,fcfcfc,f1f1f1,e2e2e2,c6c6c6,ababab,919191,767676,5e5e5e,474747,303030,1b1b1b,000000</rainbow>
         <fruit_salad>ffffff,fffbff,f9ecff,f0dbff,dcb8ff,c598f1,a97ed4,8d64b7,744c9d,5b3383,431a6b,2c0051,000000,ffffff,fffbff,f9ecff,f0dbff,dab9f9,be9edc,a384c0,876aa4,6e528a,553b71,3e2459,280d42,000000,ffffff,fffbff,ffecf0,ffd9e2,ffb1c8,e494ad,c67b92,a76178,8c4a60,703348,541d32,3a071d,000000,ffffff,fffbff,ffecf0,f6dce2,d9c0c6,bca5ab,a18b90,857176,6c5a5e,534247,3c2c30,25181c,000000,ffffff,fffbff,ffecf0,ffd9e2,e3bdc6,c6a2ab,aa8891,8d6e76,74565f,5b3f47,422931,2b151c,000000</fruit_salad>
@@ -27,7 +27,7 @@
     <theme color="ffb16407">
         <spritz>ffffff,fffbff,ffeee2,f9ddc9,dcc2ae,c0a793,a48c7a,887261,6f5a4a,564334,3d2d1f,27190c,000000,ffffff,fffbff,ffeee2,f2dfd1,d6c3b6,b9a89b,9e8e82,827368,6a5c51,51443a,3a2e25,231a11,000000,ffffff,fffbff,ffeee2,ffdcc1,e2c0a5,c6a58b,a98b72,8d7159,735943,5a422d,412c19,2a1706,000000,ffffff,fffbff,f7efec,e8e1dd,ccc5c2,b0aaa7,95908d,7a7572,625d5b,4a4644,33302e,1e1b19,000000,ffffff,fffbff,f7efec,e8e1dd,ccc5c2,b0aaa7,95908d,7a7572,625d5b,4a4644,33302e,1e1b19,000000</spritz>
         <tonal_spot>ffffff,fffbff,ffeee2,ffdcc1,ffb778,e09d60,c28349,a36931,87521c,6b3b04,4c2700,2e1500,000000,ffffff,fffbff,ffeee2,ffdcc1,e2c0a5,c6a58b,a98b72,8d7159,735943,5a422d,412c19,2a1706,000000,ffffff,fcffde,edf6bf,dfe7b2,c3cb98,a8b07e,8d9566,727a4d,5b6238,434a22,2d330e,181e00,000000,ffffff,fffbff,faefe8,ece0da,cfc4be,b3a9a3,988f89,7d746f,655d58,4c4541,352f2b,201b17,000000,ffffff,fffbff,ffeee2,f2dfd1,d6c3b6,b9a89b,9e8e82,827368,6a5c51,51443a,3a2e25,231a11,000000</tonal_spot>
-        <vibrant>ffffff,fffbff,ffeee2,ffdcc1,ffb778,fd9000,d77900,b06200,8e4e00,6c3a00,4c2700,2e1500,000000,ffffff,fffbff,ffeedc,ffddb2,e6c08d,c9a574,ad8b5c,907144,76592f,5c421a,432c06,291800,000000,ffffff,fffbff,ffefcf,ffe090,e1c477,c4a85f,a88e48,8c7330,725c1a,584401,3d2e00,241a00,000000,ffffff,fffbff,ffeee2,f2dfd1,d6c3b6,b9a89b,9e8e82,827368,6a5c51,51443a,3a2e25,231a11,000000,ffffff,fffbff,ffeee2,f9ddc9,dcc2ae,c0a793,a48c7a,887261,6f5a4a,564334,3d2d1f,27190c,000000</vibrant>
+        <vibrant>ffffff,fffbff,ffeee2,ffdcc1,ffb778,fd9000,d77900,b06200,8e4e00,6c3a00,4c2700,2e1500,000000,ffffff,fffbff,ffeedc,ffddb2,e6c08d,c9a574,ad8b5c,907144,76592f,5c421a,432c06,291800,000000,ffffff,fffbff,ffefcf,ffe090,e1c477,c4a85f,a88e48,8c7330,725c1a,584401,3d2e00,241a00,000000,ffffff,fffbff,ffeee2,f6decd,d9c2b2,bda797,a18d7e,857364,6c5b4e,534437,3c2e22,25190f,000000,ffffff,fffbff,ffeee2,f9ddc9,dcc2ae,c0a793,a48c7a,887261,6f5a4a,564334,3d2d1f,27190c,000000</vibrant>
         <expressive>ffffff,fffbff,f6edff,eaddff,d1bcff,b6a0e8,9b85cb,7f6baf,675395,4f3b7b,382463,220b4d,000000,ffffff,fffbff,fbf2b7,ece4aa,cfc890,b3ad77,98925f,7d7747,656031,4c481c,353107,1f1c00,000000,ffffff,fffbff,ffeed9,ffdeaa,ebc078,cda55f,b08b48,937030,79591b,5e4102,422c00,271900,000000,ffffff,fffbff,feeedd,efe0cf,d3c4b4,b7a99a,9b8f80,807466,675d50,4f4539,382f24,221a10,000000,ffffff,fffbff,ffeedc,f5dfc6,d8c3ab,bba891,a08e77,84735e,6b5c48,524432,3b2e1d,241a0a,000000</expressive>
         <rainbow>ffffff,fffbff,ffeee2,ffdcc1,ffb778,ee9743,ce7d2b,ae640f,8e4e00,6c3a00,4c2700,2e1500,000000,ffffff,fffbff,ffeee2,ffdcc1,e2c0a5,c6a58b,a98b72,8d7159,735943,5a422d,412c19,2a1706,000000,ffffff,fcffde,edf6bf,dfe7b2,c3cb98,a8b07e,8d9566,727a4d,5b6238,434a22,2d330e,181e00,000000,ffffff,fcfcfc,f1f1f1,e2e2e2,c6c6c6,ababab,919191,767676,5e5e5e,474747,303030,1b1b1b,000000,ffffff,fcfcfc,f1f1f1,e2e2e2,c6c6c6,ababab,919191,767676,5e5e5e,474747,303030,1b1b1b,000000</rainbow>
         <fruit_salad>ffffff,fffbff,ffeced,ffd9dd,ffb2bb,f98a9b,d97181,b95767,9b4051,7d293a,5f1125,400012,000000,ffffff,fffbff,ffeced,ffd9dd,ffb2bb,e8949f,c97a85,aa606b,8e4954,72333d,561d28,3b0714,000000,ffffff,fffbff,ffeee2,ffdcc1,ffb778,e09d60,c28349,a36931,87521c,6b3b04,4c2700,2e1500,000000,ffffff,fffbff,ffeee2,f6decd,d9c2b2,bda797,a18d7e,857364,6c5b4e,534437,3c2e22,25190f,000000,ffffff,fffbff,ffeee2,ffdcc1,e2c0a5,c6a58b,a98b72,8d7159,735943,5a422d,412c19,2a1706,000000</fruit_salad>
@@ -35,7 +35,7 @@
     <theme color="ff6e7f10">
         <spritz>ffffff,fdfee4,f1f3d8,e3e4cb,c6c8b0,abad95,90937c,757862,5d604c,464835,2f3220,1a1d0d,000000,ffffff,fefdec,f2f2e1,e4e3d3,c7c7b7,acac9d,919283,767769,5e5f52,46483b,303126,1b1c12,000000,ffffff,fcffdd,f0f4d0,e2e5c2,c5c9a8,aaae8e,8f9375,74795b,5d6145,45492f,2e321b,1a1d08,000000,ffffff,fcffdd,f4f0ec,e5e2de,c9c6c2,adaba7,92908d,777672,5f5e5b,474744,31302e,1c1c19,000000,ffffff,fcffdd,f4f0ec,e5e2de,c9c6c2,adaba7,92908d,777672,5f5e5b,474744,31302e,1c1c19,000000</spritz>
         <tonal_spot>ffffff,fcffdd,eaf8a4,dcea97,c0ce7e,a5b265,8a974e,707c36,586420,414b08,2c3400,181e00,000000,ffffff,fcffdd,f0f4d0,e2e5c2,c5c9a8,aaae8e,8f9375,74795b,5d6145,45492f,2e321b,1a1d08,000000,ffffff,f3fffa,cbfbed,bdecdf,a2d0c3,87b4a8,6d998e,527e74,3a665c,224e45,05372f,00201a,000000,ffffff,fffcf4,f3f1e8,e5e2da,c8c7bf,adaba4,92918a,77766f,5f5f58,474741,31312b,1b1c17,000000,ffffff,fefdec,f2f2e1,e4e3d3,c7c7b7,acac9d,919283,767769,5e5f52,46483b,303126,1b1c12,000000</tonal_spot>
-        <vibrant>ffffff,fcffdd,e9f99b,d0f100,b7d300,9db600,859a00,6c7e00,566500,404c00,2c3400,181e00,000000,ffffff,f9ffe9,e4f8c7,d6e9ba,bacd9f,9fb286,85976d,6a7c54,53643e,3c4c28,263514,111f03,000000,ffffff,f6ffef,d0fdc6,c2eeb9,a7d29e,8cb685,729b6c,588053,41673d,2a4f28,133813,002203,000000,ffffff,fefdec,f2f2e1,e4e3d3,c7c7b7,acac9d,919283,767769,5e5f52,46483b,303126,1b1c12,000000,ffffff,fdfee4,f1f3d8,e3e4cb,c6c8b0,abad95,90937c,757862,5d604c,464835,2f3220,1a1d0d,000000</vibrant>
+        <vibrant>ffffff,fcffdd,e9f99b,d0f100,b7d300,9db600,859a00,6c7e00,566500,404c00,2c3400,181e00,000000,ffffff,f9ffe9,e4f8c7,d6e9ba,bacd9f,9fb286,85976d,6a7c54,53643e,3c4c28,263514,111f03,000000,ffffff,f6ffef,d0fdc6,c2eeb9,a7d29e,8cb685,729b6c,588053,41673d,2a4f28,133813,002203,000000,ffffff,fdfee8,f2f2dd,e3e4cf,c7c8b3,abad99,91927f,767766,5e604f,464838,2f3223,1b1d10,000000,ffffff,fdfee4,f1f3d8,e3e4cb,c6c8b0,abad95,90937c,757862,5d604c,464835,2f3220,1a1d0d,000000</vibrant>
         <expressive>ffffff,fffbff,ffecf0,ffd9e2,ffb1c8,e991ad,cb7893,ac5e78,904760,733049,581932,3c031d,000000,ffffff,f4fff6,d0fbe1,c2ecd4,a6d0b8,8bb49e,719984,577e6a,406653,284e3c,0f3726,002114,000000,ffffff,f7ffed,d5fcc1,c7eeb3,acd199,91b580,779a67,5d7f4f,466739,2f4e23,19370f,042100,000000,ffffff,fafeef,eff2e4,e0e4d6,c4c8ba,a9ada0,8e9286,73786c,5b6055,44483e,2d3228,191d14,000000,ffffff,f8ffeb,ebf4dd,dde6d0,c1cab4,a6ae9a,8b9480,717966,596150,414939,2b3324,171e10,000000</expressive>
         <rainbow>ffffff,fcffdd,e9f99b,d9ec7b,bdd062,a2b44a,879932,6d7d17,566500,404c00,2c3400,181e00,000000,ffffff,fcffdd,f0f4d0,e2e5c2,c5c9a8,aaae8e,8f9375,74795b,5d6145,45492f,2e321b,1a1d08,000000,ffffff,f3fffa,cbfbed,bdecdf,a2d0c3,87b4a8,6d998e,527e74,3a665c,224e45,05372f,00201a,000000,ffffff,fcfcfc,f1f1f1,e2e2e2,c6c6c6,ababab,919191,767676,5e5e5e,474747,303030,1b1b1b,000000,ffffff,fcfcfc,f1f1f1,e2e2e2,c6c6c6,ababab,919191,767676,5e5e5e,474747,303030,1b1b1b,000000</rainbow>
         <fruit_salad>ffffff,fffbff,ffeede,ffddb8,ffb960,e59c37,c7821d,a66800,865300,653e00,472a00,2b1700,000000,ffffff,fffbff,ffeede,ffddb8,f8bb71,daa059,bc8642,9e6c2a,825513,653e00,472a00,2b1700,000000,ffffff,fcffdd,eaf8a4,dcea97,c0ce7e,a5b265,8a974e,707c36,586420,414b08,2c3400,181e00,000000,ffffff,fdfee8,f2f2dd,e3e4cf,c7c8b3,abad99,91927f,767766,5e604f,464838,2f3223,1b1d10,000000,ffffff,fcffdd,f0f4d0,e2e5c2,c5c9a8,aaae8e,8f9375,74795b,5d6145,45492f,2e321b,1a1d08,000000</fruit_salad>
@@ -43,7 +43,7 @@
     <theme color="ff008673">
         <spritz>ffffff,f3fffa,e2f5ee,d4e7e0,b8cbc4,9dafa9,83958f,687a74,51625d,3a4a46,23342f,0e1e1b,000000,ffffff,f4fffa,e9f3ef,dbe5e0,bec9c5,a3ada9,89938f,6e7875,57605d,3f4946,293230,141d1b,000000,ffffff,f3fffa,dbf7ee,cde8e0,b1ccc4,96b1a9,7c968f,627b74,4a635d,334b45,1d352f,06201b,000000,ffffff,fdfcfa,f2f0ef,e3e2e1,c7c6c5,ababaa,91918f,767675,5e5e5d,464746,2f3130,1b1c1b,000000,ffffff,fdfcfa,f2f0ef,e3e2e1,c7c6c5,ababaa,91918f,767675,5e5e5d,464746,2f3130,1b1c1b,000000</spritz>
         <tonal_spot>ffffff,f3fffa,b6ffed,a0f2de,84d6c2,69baa7,4d9f8d,2e8373,056b5b,005144,00382f,00201a,000000,ffffff,f3fffa,dbf7ee,cde8e0,b1ccc4,96b1a9,7c968f,627b74,4a635d,334b45,1d352f,06201b,000000,ffffff,fcfcff,e5f2ff,c8e6ff,abcae4,90afc8,7594ac,5b7a91,436278,2b4a5f,113348,001e2f,000000,ffffff,fafdfa,eff1ef,e0e3e1,c4c7c5,a9acaa,8e918f,737775,5c5f5d,444746,2e3130,191c1b,000000,ffffff,f4fffa,e9f3ef,dbe5e0,bec9c5,a3ada9,89938f,6e7875,57605d,3f4946,293230,141d1b,000000</tonal_spot>
-        <vibrant>ffffff,f3fffa,b6ffed,00fedc,00dfc1,00c1a6,00a38c,008572,006b5b,005144,00382f,00201a,000000,ffffff,f1fffe,c9faf8,bbecea,a0cfce,85b4b2,6b9998,507e7d,386665,1e4e4d,003736,00201f,000000,ffffff,f6feff,d1f8ff,a9eefa,8dd1dd,72b6c1,579ba6,3a808b,1b6772,004f58,00363d,001f24,000000,ffffff,f4fffa,e9f3ef,dbe5e0,bec9c5,a3ada9,89938f,6e7875,57605d,3f4946,293230,141d1b,000000,ffffff,f3fffa,e2f5ee,d4e7e0,b8cbc4,9dafa9,83958f,687a74,51625d,3a4a46,23342f,0e1e1b,000000</vibrant>
+        <vibrant>ffffff,f3fffa,b6ffed,00fedc,00dfc1,00c1a6,00a38c,008572,006b5b,005144,00382f,00201a,000000,ffffff,f1fffe,c9faf8,bbecea,a0cfce,85b4b2,6b9998,507e7d,386665,1e4e4d,003736,00201f,000000,ffffff,f6feff,d1f8ff,a9eefa,8dd1dd,72b6c1,579ba6,3a808b,1b6772,004f58,00363d,001f24,000000,ffffff,f3fffa,e6f4ee,d7e6e0,bbcac4,a0aea9,86948f,6b7975,54615d,3c4946,26332f,111e1b,000000,ffffff,f3fffa,e2f5ee,d4e7e0,b8cbc4,9dafa9,83958f,687a74,51625d,3a4a46,23342f,0e1e1b,000000</vibrant>
         <expressive>ffffff,fffbff,ffeee2,ffdcc1,ffb779,e59b57,c68140,a76728,8b5011,6c3a00,4c2700,2e1500,000000,ffffff,fafdff,def4ff,c0e9fb,a5cdde,8ab1c2,7096a7,557b8b,3d6473,244c5a,063543,001f29,000000,ffffff,f1ffff,bbfcff,a8eff2,8cd2d5,70b7ba,559c9f,388183,19686b,004f52,003739,002021,000000,ffffff,f4fefd,e8f3f2,dae5e3,bec9c8,a3adac,889392,6e7877,566060,3f4948,293232,141d1d,000000,ffffff,f1fffe,e2f5f3,d3e6e5,b8cac9,9dafae,829493,687979,506261,394a49,233333,0e1e1e,000000</expressive>
         <rainbow>ffffff,f3fffa,b6ffed,78f8dd,59dbc1,35bfa6,00a38c,008572,006b5b,005144,00382f,00201a,000000,ffffff,f3fffa,dbf7ee,cde8e0,b1ccc4,96b1a9,7c968f,627b74,4a635d,334b45,1d352f,06201b,000000,ffffff,fcfcff,e5f2ff,c8e6ff,abcae4,90afc8,7594ac,5b7a91,436278,2b4a5f,113348,001e2f,000000,ffffff,fcfcfc,f1f1f1,e2e2e2,c6c6c6,ababab,919191,767676,5e5e5e,474747,303030,1b1b1b,000000,ffffff,fcfcfc,f1f1f1,e2e2e2,c6c6c6,ababab,919191,767676,5e5e5e,474747,303030,1b1b1b,000000</rainbow>
         <fruit_salad>ffffff,f9ffe7,dafca7,c6f08a,abd471,90b759,779c41,5d8128,466810,324f00,213600,111f00,000000,ffffff,f9ffe7,ddfbaf,cfeda2,b3d088,98b56f,7e9a57,647e3f,4d662a,364e14,213600,111f00,000000,ffffff,f3fffa,b6ffed,a0f2de,84d6c2,69baa7,4d9f8d,2e8373,056b5b,005144,00382f,00201a,000000,ffffff,f3fffa,e6f4ee,d7e6e0,bbcac4,a0aea9,86948f,6b7975,54615d,3c4946,26332f,111e1b,000000,ffffff,f3fffa,dbf7ee,cde8e0,b1ccc4,96b1a9,7c968f,627b74,4a635d,334b45,1d352f,06201b,000000</fruit_salad>
@@ -51,7 +51,7 @@
     <theme color="ff007fb4">
         <spritz>ffffff,fbfcff,e6f2fe,d8e4ef,bcc8d3,a1adb7,86929d,6c7781,546069,3d4851,26323a,121d25,000000,ffffff,fbfcff,ebf1f8,dde3ea,c1c7ce,a6acb2,8b9198,70777d,595f65,41484d,2b3136,161c21,000000,ffffff,fbfcff,e5f2ff,d2e5f5,b7c9d8,9cadbd,8193a2,677886,4f606e,384956,21323f,0b1d29,000000,ffffff,fefcfc,f2f0f1,e4e2e3,c7c6c7,acabac,919091,767677,5e5e5f,464748,303031,1b1c1c,000000,ffffff,fefcfc,f2f0f1,e4e2e3,c7c6c7,acabac,919091,767677,5e5e5f,464748,303031,1b1c1c,000000</spritz>
         <tonal_spot>ffffff,fbfcff,e5f2ff,c8e6ff,94cdf6,78b2da,5d97be,407ca1,246488,004c6d,00344d,001e2e,000000,ffffff,fbfcff,e5f2ff,d2e5f5,b7c9d8,9cadbd,8193a2,677886,4f606e,384956,21323f,0b1d29,000000,ffffff,fffbff,f6edff,e9ddff,cdc0e8,b2a5cc,978bb1,7c7095,63597c,4b4163,342b4b,1f1635,000000,ffffff,fcfcff,f0f0f3,e2e2e5,c5c6c9,aaabae,8f9193,747679,5d5e61,454749,2e3133,191c1e,000000,ffffff,fbfcff,ebf1f8,dde3ea,c1c7ce,a6acb2,8b9198,70777d,595f65,41484d,2b3136,161c21,000000</tonal_spot>
-        <vibrant>ffffff,fbfcff,e5f2ff,c8e6ff,87ceff,0eb6ff,009ad9,007eb2,006590,004c6d,00344d,001e2e,000000,ffffff,fdfcff,ebf1ff,d4e3ff,b3c8e9,98accc,7e92b1,637795,4c5f7c,344863,1d314b,051c35,000000,ffffff,fefbff,efefff,dce1ff,b8c4fa,9da9dd,838ec1,6874a4,505c8b,384472,212e5a,0a1844,000000,ffffff,fbfcff,ebf1f8,dde3ea,c1c7ce,a6acb2,8b9198,70777d,595f65,41484d,2b3136,161c21,000000,ffffff,fbfcff,e6f2fe,d8e4ef,bcc8d3,a1adb7,86929d,6c7781,546069,3d4851,26323a,121d25,000000</vibrant>
+        <vibrant>ffffff,fbfcff,e5f2ff,c8e6ff,87ceff,0eb6ff,009ad9,007eb2,006590,004c6d,00344d,001e2e,000000,ffffff,fdfcff,ebf1ff,d4e3ff,b3c8e9,98accc,7e92b1,637795,4c5f7c,344863,1d314b,051c35,000000,ffffff,fefbff,efefff,dce1ff,b8c4fa,9da9dd,838ec1,6874a4,505c8b,384472,212e5a,0a1844,000000,ffffff,fbfcff,e9f2fb,dbe4ed,bfc8d0,a3acb5,89929a,6e777f,575f67,3f484f,293138,141d23,000000,ffffff,fbfcff,e6f2fe,d8e4ef,bcc8d3,a1adb7,86929d,6c7781,546069,3d4851,26323a,121d25,000000</vibrant>
         <expressive>ffffff,fcffdd,e9f99a,dbeb8e,bfce75,a4b35c,8a9845,6f7c2d,586416,414c00,2c3400,191e00,000000,ffffff,fffbff,ffebfa,fed7f9,e0bbdd,c4a0c1,a886a6,8c6c8a,735572,593d59,412742,2a122c,000000,ffffff,fdfcff,eaf1ff,d2e4ff,a7c9f6,8caed9,7293bd,5778a1,3f6088,25496f,073257,001c37,000000,ffffff,fdfcff,edf1fa,dfe2eb,c3c6cf,a7abb4,8d9199,72767e,5a5f66,43474e,2c3137,171c22,000000,ffffff,fdfcff,eaf1ff,dbe3f1,bfc7d5,a4acb9,89919e,6f7783,575f6b,3f4753,29313c,141c26,000000</expressive>
         <rainbow>ffffff,fbfcff,e5f2ff,c8e6ff,87ceff,55b4ed,3399d1,007eb2,006590,004c6d,00344d,001e2e,000000,ffffff,fbfcff,e5f2ff,d2e5f5,b7c9d8,9cadbd,8193a2,677886,4f606e,384956,21323f,0b1d29,000000,ffffff,fffbff,f6edff,e9ddff,cdc0e8,b2a5cc,978bb1,7c7095,63597c,4b4163,342b4b,1f1635,000000,ffffff,fcfcfc,f1f1f1,e2e2e2,c6c6c6,ababab,919191,767676,5e5e5e,474747,303030,1b1b1b,000000,ffffff,fcfcfc,f1f1f1,e2e2e2,c6c6c6,ababab,919191,767676,5e5e5e,474747,303030,1b1b1b,000000</rainbow>
         <fruit_salad>ffffff,f2fffc,b1fff7,71f7ec,50dbd0,25beb5,00a299,00847d,006a64,00504b,003734,00201e,000000,ffffff,f2fffc,b1fff7,9df2e9,81d5cd,65b9b2,489e97,28837c,006a64,00504b,003734,00201e,000000,ffffff,fbfcff,e5f2ff,c8e6ff,94cdf6,78b2da,5d97be,407ca1,246488,004c6d,00344d,001e2e,000000,ffffff,fbfcff,e9f2fb,dbe4ed,bfc8d0,a3acb5,89929a,6e777f,575f67,3f484f,293138,141d23,000000,ffffff,fbfcff,e5f2ff,d2e5f5,b7c9d8,9cadbd,8193a2,677886,4f606e,384956,21323f,0b1d29,000000</fruit_salad>
@@ -59,7 +59,7 @@
     <theme color="ff8267c2">
         <spritz>ffffff,fffbff,f6edff,e8dff2,cbc3d5,afa8b9,958e9e,797383,615c6b,494453,332e3c,1d1a26,000000,ffffff,fffbff,f5eefa,e7e0eb,cac4cf,afa9b4,948f99,79747e,615d66,49454e,322f37,1d1a22,000000,ffffff,fffbff,f6edff,e8def8,ccc2db,b0a7bf,958da4,7a7289,625b70,4a4458,332d41,1e192b,000000,ffffff,fffbff,f4eff1,e6e1e3,c9c5c7,aeaaac,939092,787577,605e5f,484648,313031,1c1b1d,000000,ffffff,fffbff,f4eff1,e6e1e3,c9c5c7,aeaaac,939092,787577,605e5f,484648,313031,1c1b1d,000000</spritz>
         <tonal_spot>ffffff,fffbff,f6edff,e9ddff,d0bcfe,b5a1e1,9987c4,7e6ca8,66558e,4e3d75,37265d,210f47,000000,ffffff,fffbff,f6edff,e8def8,ccc2db,b0a7bf,958da4,7a7289,625b70,4a4458,332d41,1e192b,000000,ffffff,fffbff,ffecef,ffd9e2,f0b8c7,d29dac,b58391,986977,7e525f,633b47,4a2531,31101c,000000,ffffff,fffbff,f5eff4,e6e1e6,cac5ca,aeaaae,938f94,787579,605d61,48464a,323033,1c1b1e,000000,ffffff,fffbff,f5eefa,e7e0eb,cac4cf,afa9b4,948f99,79747e,615d66,49454e,322f37,1d1a22,000000</tonal_spot>
-        <vibrant>ffffff,fffbff,f6edff,e9ddff,d1bcff,b89bff,a078ff,884fff,7212ff,5700c9,3c0090,23005b,000000,ffffff,fffbff,fbecff,f4daff,d7bde4,bba2c8,a088ac,846e90,6c5778,533f5f,3b2947,251431,000000,ffffff,fffbff,ffebfa,ffd6fa,e9b6e6,cc9cc9,b082ae,936792,7a5079,603960,472348,2f0d32,000000,ffffff,fffbff,f5eefa,e7e0eb,cac4cf,afa9b4,948f99,79747e,615d66,49454e,322f37,1d1a22,000000,ffffff,fffbff,f6edff,e8dff2,cbc3d5,afa8b9,958e9e,797383,615c6b,494453,332e3c,1d1a26,000000</vibrant>
+        <vibrant>ffffff,fffbff,f6edff,e9ddff,d1bcff,b89bff,a078ff,884fff,7212ff,5700c9,3c0090,23005b,000000,ffffff,fffbff,fbecff,f4daff,d7bde4,bba2c8,a088ac,846e90,6c5778,533f5f,3b2947,251431,000000,ffffff,fffbff,ffebfa,ffd6fa,e9b6e6,cc9cc9,b082ae,936792,7a5079,603960,472348,2f0d32,000000,ffffff,fffbff,f6eefd,e7e0ee,cbc4d2,afa9b7,948e9c,797481,615c69,494551,322f3a,1d1a24,000000,ffffff,fffbff,f6edff,e8dff2,cbc3d5,afa8b9,958e9e,797383,615c6b,494453,332e3c,1d1a26,000000</vibrant>
         <expressive>ffffff,f3fffa,b7ffed,94f4de,78d7c2,5bbba7,3da08d,168572,006b5b,005144,00382f,00201a,000000,ffffff,fffbff,ffecf4,ffd8ec,e9b9d3,cc9eb7,b0849c,936a81,795369,5f3c51,46263a,2f1124,000000,ffffff,fffbff,feebff,f8d8ff,e1b9ed,c49ed0,a984b5,8c6998,73527f,5a3b66,42244e,2b0e38,000000,ffffff,fffbff,f8edf8,eadfea,cdc3ce,b2a8b2,978e98,7b737d,635c65,4b454d,342e36,1f1a21,000000,ffffff,fffbff,fbecfe,ecdeef,d0c2d3,b4a7b7,998d9d,7d7281,655b69,4d4351,362d3a,201925,000000</expressive>
         <rainbow>ffffff,fffbff,f6edff,e9ddff,d1bcff,b79cf7,9c82da,8167bd,684fa3,50378a,391e72,23005b,000000,ffffff,fffbff,f6edff,e8def8,ccc2db,b0a7bf,958da4,7a7289,625b70,4a4458,332d41,1e192b,000000,ffffff,fffbff,ffecef,ffd9e2,f0b8c7,d29dac,b58391,986977,7e525f,633b47,4a2531,31101c,000000,ffffff,fcfcfc,f1f1f1,e2e2e2,c6c6c6,ababab,919191,767676,5e5e5e,474747,303030,1b1b1b,000000,ffffff,fcfcfc,f1f1f1,e2e2e2,c6c6c6,ababab,919191,767676,5e5e5e,474747,303030,1b1b1b,000000</rainbow>
         <fruit_salad>ffffff,fcfcff,e8f1ff,cfe5ff,99cbff,68b1f4,4a96d8,277bbb,00629e,004a78,003355,001d34,000000,ffffff,fcfcff,e8f1ff,cfe5ff,9dcbfb,82afdf,6794c2,4b7aa6,31628d,124a73,003355,001d34,000000,ffffff,fffbff,f6edff,e9ddff,d0bcfe,b5a1e1,9987c4,7e6ca8,66558e,4e3d75,37265d,210f47,000000,ffffff,fffbff,f6eefd,e7e0ee,cbc4d2,afa9b7,948e9c,797481,615c69,494551,322f3a,1d1a24,000000,ffffff,fffbff,f6edff,e8def8,ccc2db,b0a7bf,958da4,7a7289,625b70,4a4458,332d41,1e192b,000000</fruit_salad>
diff --git a/tests/tests/graphics/src/android/graphics/cts/AnimatorLeakTest.java b/tests/tests/graphics/src/android/graphics/cts/AnimatorLeakTest.java
new file mode 100644
index 0000000..b21edd5
--- /dev/null
+++ b/tests/tests/graphics/src/android/graphics/cts/AnimatorLeakTest.java
@@ -0,0 +1,255 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics.cts;
+
+import static androidx.test.InstrumentationRegistry.getInstrumentation;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ValueAnimator;
+import android.support.test.uiautomator.UiDevice;
+
+import androidx.test.filters.MediumTest;
+import androidx.test.rule.ActivityTestRule;
+import androidx.test.runner.AndroidJUnit4;
+
+import junit.framework.Assert;
+
+import org.junit.After;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+@MediumTest
+@RunWith(AndroidJUnit4.class)
+public class AnimatorLeakTest {
+
+    @Rule
+    public  ActivityTestRule<EmptyActivity> mActivityRule =
+            new ActivityTestRule<>(EmptyActivity.class, false, true);
+    public  ActivityTestRule<EmptyActivity2> mActivityRule2 =
+            new ActivityTestRule<>(EmptyActivity2.class, false, false);
+
+    boolean mPaused = false;
+    boolean mPausedSet = false;
+    boolean mFinitePaused = false;
+    boolean mFinitePausedSet = false;
+    boolean mResumed = false;
+
+    @After
+    public void cleanup() {
+        Animator.setAnimatorPausingEnabled(true);
+    }
+
+    /**
+     * The approach of this test is to start animators in the main activity for the test.
+     * That activity is forced into the background and the test checks whether the animators
+     * are paused appropriately. The activity is then forced back into the foreground again
+     * and the test checks whether the animators previously paused are resumed. There are also
+     * checks to make sure that animators which should not have been paused are handled
+     * correctly.
+     */
+    @Test
+    public void testPauseResume() {
+        // Latches used to wait for each of the appropriate lifecycle events
+        final CountDownLatch animatorStartedLatch = new CountDownLatch(1);
+        // There are 2 animators which should be paused and resumed, thus a countdown of 2
+        final CountDownLatch animatorPausedLatch = new CountDownLatch(2);
+        final CountDownLatch animatorResumedLatch = new CountDownLatch(2);
+
+        // The first of these (infinite) should get paused, the second (finite) should not
+        ValueAnimator infiniteAnimator = ValueAnimator.ofFloat(0f, 1f).setDuration(1000);
+        infiniteAnimator.setRepeatCount(ValueAnimator.INFINITE);
+        ValueAnimator finiteAnimator = ValueAnimator.ofFloat(0f, 1f).setDuration(5000);
+
+        // Now create infinite and finite AnimatorSets
+        // As above, the infinite set should get paused, the finite one should not
+        ValueAnimator infiniteAnimator1 = ValueAnimator.ofFloat(0f, 1f).setDuration(1000);
+        infiniteAnimator1.setRepeatCount(ValueAnimator.INFINITE);
+        AnimatorSet infiniteSet = new AnimatorSet();
+        infiniteSet.play(infiniteAnimator1);
+        ValueAnimator finiteAnimator1 = ValueAnimator.ofFloat(0f, 1f).setDuration(5000);
+        AnimatorSet finiteSet = new AnimatorSet();
+        finiteSet.play(finiteAnimator1);
+
+        // This listener tracks which animators get paused and resumed
+        AnimatorListenerAdapter listener = new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationStart(Animator animation) {
+                // Wait until animators start to trigger the lifecycle changes
+                animatorStartedLatch.countDown();
+            }
+
+            @Override
+            public void onAnimationPause(Animator animation) {
+                if (animation == infiniteAnimator) {
+                    mPaused = true;
+                } else if (animation == infiniteSet) {
+                    mPausedSet = true;
+                } else if (animation == finiteAnimator) {
+                    mFinitePaused = true;
+                    // end it to avoid having it interfere with future resume latch
+                    animation.end();
+                    return;
+                } else if (animation == finiteSet) {
+                    mFinitePausedSet = true;
+                    // end it to avoid having it interfere with future resume latch
+                    animation.end();
+                    return;
+                }
+                animatorPausedLatch.countDown();
+            }
+
+            @Override
+            public void onAnimationResume(Animator animation) {
+                mResumed = true;
+                animatorResumedLatch.countDown();
+            }
+        };
+        infiniteAnimator.addListener(listener);
+        infiniteAnimator.addPauseListener(listener);
+        finiteAnimator.addPauseListener(listener);
+        infiniteSet.addPauseListener(listener);
+        finiteSet.addPauseListener(listener);
+
+        getInstrumentation().runOnMainSync(new Runnable() {
+            public void run() {
+                Animator.setBackgroundPauseDelay(500);
+                try {
+                    infiniteAnimator.start();
+                    finiteAnimator.start();
+                    infiniteSet.start();
+                    finiteSet.start();
+                } catch (Throwable throwable) {
+                }
+            }
+        });
+        try {
+            // Wait until the animators are running to start changing the activity lifecycle
+            animatorStartedLatch.await(5, TimeUnit.SECONDS);
+
+            // First, test that animators are *not* paused when an activity goes to the background
+            // if there is another activity in the same process which is now in the foreground.
+            mActivityRule2.launchActivity(null);
+            animatorPausedLatch.await(1, TimeUnit.SECONDS);
+            Assert.assertFalse("Animator was paused", mPaused);
+            mActivityRule2.finishActivity();
+
+            // Send the activity to the background. This should cause the animators to be paused
+            // after Animator.getBackgroundPauseDelay()
+            UiDevice uiDevice = UiDevice.getInstance(getInstrumentation());
+            uiDevice.pressHome();
+
+            animatorPausedLatch.await(5, TimeUnit.SECONDS);
+
+            // It is not possible (or obvious) how to bring the activity back into the foreground.
+            // However, AnimationHandler pauses/resumes all animators for the process based on
+            // *any* visible activities in that process. So it is sufficient to launch a second
+            // activity, which should resume the animators paused when the first activity went
+            // into the background.
+            mActivityRule2.launchActivity(null);
+            animatorResumedLatch.await(5, TimeUnit.SECONDS);
+        } catch (Exception e) { }
+        Assert.assertTrue("Animator was not paused", mPaused);
+        Assert.assertTrue("AnimatorSet was not paused", mPausedSet);
+        Assert.assertFalse("Non-infinite Animator was paused", mFinitePaused);
+        Assert.assertFalse("Non-infinite AnimatorSet was paused", mFinitePausedSet);
+        Assert.assertTrue("Animator was not resumed", mResumed);
+        Assert.assertTrue("AnimatorSet was not resumed", mResumed);
+    }
+
+    /**
+     * The approach of this test is to start animators in the main activity for the test.
+     * That activity is forced into the background and the test checks whether the animators
+     * are paused appropriately. The activity is then forced back into the foreground again
+     * and the test checks whether the animators previously paused are resumed. There are also
+     * checks to make sure that animators which should not have been paused are handled
+     * correctly.
+     */
+    @Test
+    public void testPauseDisablement() {
+        // Latches used to wait for each of the appropriate lifecycle events
+        final CountDownLatch animatorStartedLatch = new CountDownLatch(1);
+        // There are 2 animators which should be paused and resumed, thus a countdown of 2
+        final CountDownLatch animatorPausedLatch = new CountDownLatch(1);
+        final CountDownLatch animatorResumedLatch = new CountDownLatch(1);
+
+        // The first of these (infinite) should get paused, the second (finite) should not
+        ValueAnimator infiniteAnimator = ValueAnimator.ofFloat(0f, 1f).setDuration(1000);
+        infiniteAnimator.setRepeatCount(ValueAnimator.INFINITE);
+
+        // This listener tracks which animators get paused and resumed
+        AnimatorListenerAdapter listener = new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationStart(Animator animation) {
+                // Wait until animators start to trigger the lifecycle changes
+                animatorStartedLatch.countDown();
+            }
+
+            @Override
+            public void onAnimationPause(Animator animation) {
+                mPaused = true;
+                animatorPausedLatch.countDown();
+            }
+
+            @Override
+            public void onAnimationResume(Animator animation) {
+                mResumed = true;
+                animatorResumedLatch.countDown();
+            }
+        };
+        infiniteAnimator.addListener(listener);
+        infiniteAnimator.addPauseListener(listener);
+
+        getInstrumentation().runOnMainSync(new Runnable() {
+            public void run() {
+                Animator.setBackgroundPauseDelay(500);
+                Animator.setAnimatorPausingEnabled(false);
+                try {
+                    infiniteAnimator.start();
+                } catch (Throwable throwable) {
+                }
+            }
+        });
+        try {
+            // Wait until the animators are running to start changing the activity lifecycle
+            animatorStartedLatch.await(5, TimeUnit.SECONDS);
+
+            // Send the activity to the background. This should cause the animators to be paused
+            // after Animator.getBackgroundPauseDelay()
+            UiDevice uiDevice = UiDevice.getInstance(getInstrumentation());
+            uiDevice.pressHome();
+
+            animatorPausedLatch.await(2, TimeUnit.SECONDS);
+
+            // It is not possible (or obvious) how to bring the activity back into the foreground.
+            // However, AnimationHandler pauses/resumes all animators for the process based on
+            // *any* visible activities in that process. So it is sufficient to launch a second
+            // activity, which should resume the animators paused when the first activity went
+            // into the background.
+            mActivityRule2.launchActivity(null);
+            animatorResumedLatch.await(2, TimeUnit.SECONDS);
+        } catch (Exception e) { }
+        Assert.assertFalse("Animator paused when pausing disabled", mPaused);
+        Assert.assertFalse("Animator resumed when pausing disabled", mResumed);
+    }
+
+}
diff --git a/tests/tests/graphics/src/android/graphics/cts/EmptyActivity.java b/tests/tests/graphics/src/android/graphics/cts/EmptyActivity.java
new file mode 100644
index 0000000..5ae6cd3
--- /dev/null
+++ b/tests/tests/graphics/src/android/graphics/cts/EmptyActivity.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics.cts;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.ViewGroup;
+import android.widget.Button;
+
+/**
+ * Empty activity
+ */
+public final class EmptyActivity extends Activity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        Button b = new Button(this);
+        b.setLayoutParams(new ViewGroup.LayoutParams(100, 100));
+        b.setText("My Button 1111");
+        setContentView(b);
+    }
+}
diff --git a/tests/tests/graphics/src/android/graphics/cts/EmptyActivity2.java b/tests/tests/graphics/src/android/graphics/cts/EmptyActivity2.java
new file mode 100644
index 0000000..da0b8a6
--- /dev/null
+++ b/tests/tests/graphics/src/android/graphics/cts/EmptyActivity2.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics.cts;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.ViewGroup;
+import android.widget.Button;
+
+/**
+ * Empty activity - this one exists in addition to EmptyActivity when an app
+ * needs two launch 2 separate activities.
+ */
+public final class EmptyActivity2 extends Activity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        Button b = new Button(this);
+        b.setLayoutParams(new ViewGroup.LayoutParams(100, 100));
+        b.setText("My Button 22222");
+        setContentView(b);
+    }
+}
diff --git a/tests/tests/media/decoder/src/android/media/decoder/cts/DecoderTest.java b/tests/tests/media/decoder/src/android/media/decoder/cts/DecoderTest.java
index 68d80e3..73ba7c3 100644
--- a/tests/tests/media/decoder/src/android/media/decoder/cts/DecoderTest.java
+++ b/tests/tests/media/decoder/src/android/media/decoder/cts/DecoderTest.java
@@ -41,7 +41,6 @@
 import android.media.AudioFormat;
 import android.media.AudioManager;
 import android.media.AudioTimestamp;
-import android.media.AudioTrack;
 import android.media.Image;
 import android.media.MediaCodec;
 import android.media.MediaCodec.BufferInfo;
@@ -4611,7 +4610,7 @@
         assertTrue("MediaCodecPlayer.start() failed!", mMediaCodecPlayer.start());
         assertTrue("MediaCodecPlayer.prepare() failed!", mMediaCodecPlayer.prepare());
 
-        // starts video playback
+        // Starts video playback
         mMediaCodecPlayer.startThread();
         sleepUntil(() ->
                 mMediaCodecPlayer.getCurrentPosition() > CodecState.UNINITIALIZED_TIMESTAMP
@@ -4626,82 +4625,97 @@
 
         // Keep buffering video content but stop buffering audio content -> audio underrun
         mMediaCodecPlayer.simulateAudioUnderrun(true);
-        // Loop to wait for audio underrun
-        // TODO(b/200280965): Find a more appropriate delay based on partner feedback
+
+        // Wait for audio underrun
         final int audioUnderrunTimeoutMs = 1000; // Arbitrary upper time limit on loop time duration
         long startTimeMs = System.currentTimeMillis();
-        AudioTimestamp previousTimestamp;
-        while ((previousTimestamp = mMediaCodecPlayer.getTimestamp()) == null) {
-            assertTrue(String.format("No audio timestamp after %d milliseconds",
+        AudioTimestamp currentAudioTimestamp = mMediaCodecPlayer.getTimestamp();
+        AudioTimestamp underrunAudioTimestamp;
+        do {
+            assertTrue(String.format("No audio underrun after %d milliseconds",
                             System.currentTimeMillis() - startTimeMs),
                     System.currentTimeMillis() - startTimeMs < audioUnderrunTimeoutMs);
+            underrunAudioTimestamp = currentAudioTimestamp;
             Thread.sleep(50);
-        }
-        AudioTimestamp underrunAudioTimestamp;
-        while ((underrunAudioTimestamp = mMediaCodecPlayer.getTimestamp()) != previousTimestamp) {
-            assertTrue(String.format("No audio underrun after %d milliseconds",
-                            audioUnderrunTimeoutMs),
-                    System.currentTimeMillis() - startTimeMs < audioUnderrunTimeoutMs);
-            previousTimestamp = underrunAudioTimestamp;
-            Thread.sleep(50);
-        }
-        // Loop to wait until video playback stalls
-        long previousVideoTimeUs = mMediaCodecPlayer.getVideoTimeUs();
-        long underrunVideoTimeUs;
-        startTimeMs = System.currentTimeMillis();
-        // TODO(b/200280965): Find a more appropriate delay based on partner feedback
+            currentAudioTimestamp = mMediaCodecPlayer.getTimestamp();
+        } while (currentAudioTimestamp.framePosition != underrunAudioTimestamp.framePosition);
+
+
+        // Wait until video playback stalls
         final int videoUnderrunTimeoutMs = 1000;
-        while ((underrunVideoTimeUs = mMediaCodecPlayer.getVideoTimeUs()) != previousVideoTimeUs) {
+        startTimeMs = System.currentTimeMillis();
+        long currentVideoTimeUs = mMediaCodecPlayer.getVideoTimeUs();
+        long underrunVideoTimeUs = -1;
+        do {
             assertTrue(String.format("No video underrun after %d milliseconds",
                             videoUnderrunTimeoutMs),
                     System.currentTimeMillis() - startTimeMs < videoUnderrunTimeoutMs);
-            previousVideoTimeUs = underrunVideoTimeUs;
+            underrunVideoTimeUs = currentVideoTimeUs;
             Thread.sleep(50);
-        }
+            currentVideoTimeUs = mMediaCodecPlayer.getVideoTimeUs();
+        } while (currentVideoTimeUs != underrunVideoTimeUs);
 
-        final int underrunVideoRenderedTimestampIndex =
+        // Retrieve index for the video rendered frame at the time of underrun
+        int underrunVideoRenderedTimestampIndex =
                 mMediaCodecPlayer.getRenderedVideoFrameTimestampList().size() - 1;
+
         // Resume audio buffering with a negative offset, in order to simulate a desynchronisation.
         // TODO(b/202710709): Use timestamp relative to last played video frame before pause
         mMediaCodecPlayer.setAudioTrackOffsetMs(-100);
         mMediaCodecPlayer.simulateAudioUnderrun(false);
 
-        // Loop to wait until audio playback resumes
+        // Wait until audio playback resumes
+        final int audioResumeTimeoutMs = 1000;
         startTimeMs = System.currentTimeMillis();
-        AudioTimestamp postResumeTimestamp;
-        while ((postResumeTimestamp = mMediaCodecPlayer.getTimestamp()) == underrunAudioTimestamp) {
+        currentAudioTimestamp = mMediaCodecPlayer.getTimestamp();
+        AudioTimestamp postResumeAudioTimestamp;
+        do {
             assertTrue(String.format("Audio has not resumed after %d milliseconds",
-                            audioUnderrunTimeoutMs),
-                    System.currentTimeMillis() - startTimeMs < audioUnderrunTimeoutMs);
+                            audioResumeTimeoutMs),
+                    System.currentTimeMillis() - startTimeMs < audioResumeTimeoutMs);
+            postResumeAudioTimestamp = currentAudioTimestamp;
             Thread.sleep(50);
-        }
+            currentAudioTimestamp = mMediaCodecPlayer.getTimestamp();
+        } while(currentAudioTimestamp.framePosition == postResumeAudioTimestamp.framePosition);
 
-        long resumeAudioSystemTime = interpolateSystemTimeAt(
-                underrunAudioTimestamp.framePosition + 1, postResumeTimestamp,
-                mMediaCodecPlayer.getAudioTrack());
-
-        // Now that audio playback has resumed, loop to wait until video playback resumes
+        // Now that audio playback has resumed, wait until video playback resumes
         // We care about the timestamp of the first output frame, rather than the exact time the
         // video resumed, which is why we only start polling after we are sure audio playback has
         // resumed.
-        long resumeVideoTimeUs = 0;
+        final int videoResumeTimeoutMs = 1000;
         startTimeMs = System.currentTimeMillis();
-        while ((resumeVideoTimeUs = mMediaCodecPlayer.getVideoTimeUs()) == underrunVideoTimeUs) {
+        currentVideoTimeUs = mMediaCodecPlayer.getVideoTimeUs();
+        long resumeVideoTimeUs = -1;
+        do {
             assertTrue(String.format("Video has not resumed after %d milliseconds",
-                            videoUnderrunTimeoutMs),
-                    System.currentTimeMillis() - startTimeMs < videoUnderrunTimeoutMs);
+                            videoResumeTimeoutMs),
+                    System.currentTimeMillis() - startTimeMs < videoResumeTimeoutMs);
+            resumeVideoTimeUs = currentVideoTimeUs;
             Thread.sleep(50);
-        }
+            currentVideoTimeUs = mMediaCodecPlayer.getVideoTimeUs();
+        } while (currentVideoTimeUs == resumeVideoTimeUs);
 
-        final ImmutableList<Long> renderedSystemTimeList =
-                mMediaCodecPlayer.getRenderedVideoFrameSystemTimeList();
-        final long resumeVideoFrameSystemTime = mMediaCodecPlayer
-                .getRenderedVideoFrameSystemTimeList().get(underrunVideoRenderedTimestampIndex + 1);
-        final long vsync = (long) (1000 / frameRate);
-        final long avSyncOffset = resumeAudioSystemTime + 100 - resumeVideoFrameSystemTime;
-        assertTrue(String.format("Audio and video tracks are more than %d milliseconds out of sync",
-                        vsync),
-                Math.abs(avSyncOffset) <= vsync);
+        // The system time when rendering the first audio frame after the resume
+        long playbackRateFps = mMediaCodecPlayer.getAudioTrack().getPlaybackRate();
+        long playedFrames = postResumeAudioTimestamp.framePosition
+                - underrunAudioTimestamp.framePosition + 1;
+        double elapsedTimeNs = playedFrames * (1000.0 * 1000.0 * 1000.0 / playbackRateFps);
+        long resumeAudioSystemTimeNs = postResumeAudioTimestamp.nanoTime - (long) elapsedTimeNs;
+        long resumeAudioSystemTimeMs = resumeAudioSystemTimeNs / 1000 / 1000;
+
+        // The system time when rendering the first video frame after the resume
+        long resumeVideoSystemTimeMs = mMediaCodecPlayer.getRenderedVideoFrameSystemTimeList()
+                .get(underrunVideoRenderedTimestampIndex + 1) / 1000 / 1000;
+
+        // Verify that audio and video are in-sync after resume time
+        // Note: Because a -100ms PTS gap is introduced, the video should resume 100ms later
+        resumeAudioSystemTimeMs += 100;
+        long vsyncMs = 1000 / frameRate;
+        long avSyncOffsetMs = resumeAudioSystemTimeMs - resumeVideoSystemTimeMs;
+        assertTrue(String.format(
+                        "Audio is %d milliseconds out of sync of video (audio:%d video:%d)",
+                        avSyncOffsetMs, resumeAudioSystemTimeMs, resumeVideoSystemTimeMs),
+                Math.abs(avSyncOffsetMs) <= vsyncMs);
     }
 
     /**
@@ -4745,18 +4759,6 @@
     }
 
     /**
-     * Returns the system time of the frame {@code framePosition} from {@code timestamp}, for a
-     * specific {@code AudioTrack}.
-     */
-    private static long interpolateSystemTimeAt(long framePosition, AudioTimestamp timestamp,
-            AudioTrack audioTrack) {
-        final long playbackRateFps = audioTrack.getPlaybackRate();  // Frames per second
-        final long playedFrames = timestamp.framePosition - framePosition;
-        final double elapsedTimeNs = playedFrames * (1000000000.0 / playbackRateFps);
-        return timestamp.nanoTime - (long) elapsedTimeNs;
-    }
-
-    /**
      * Returns list of CodecCapabilities advertising support for the given MIME type.
      */
     private static List<CodecCapabilities> getCodecCapabilitiesForMimeType(String mimeType) {
diff --git a/tests/tests/permission3/src/android/permission3/cts/PermissionAttributionTest.kt b/tests/tests/permission3/src/android/permission3/cts/PermissionAttributionTest.kt
index 57efe74..31e5449 100644
--- a/tests/tests/permission3/src/android/permission3/cts/PermissionAttributionTest.kt
+++ b/tests/tests/permission3/src/android/permission3/cts/PermissionAttributionTest.kt
@@ -29,11 +29,9 @@
 import com.android.compatibility.common.util.CtsDownstreamingTest
 import com.android.compatibility.common.util.SystemUtil.callWithShellPermissionIdentity
 import com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity
-import com.android.modules.utils.build.SdkLevel
 import org.junit.After
 import org.junit.Assert.assertEquals
 import org.junit.Assert.assertTrue
-import org.junit.Assume.assumeFalse
 import org.junit.Before
 import org.junit.Test
 import java.util.concurrent.TimeUnit
@@ -41,19 +39,16 @@
 /**
  * Tests permission attribution for location providers.
  */
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
+// Tests converted to GTS since these are GMS requirements not CDD.
+// These will be moved to GTS in U.
+@CtsDownstreamingTest
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU)
 class PermissionAttributionTest : BasePermissionHubTest() {
     private val micLabel = packageManager.getPermissionGroupInfo(
         android.Manifest.permission_group.MICROPHONE, 0).loadLabel(packageManager).toString()
     val locationManager = context.getSystemService(LocationManager::class.java)!!
     private var wasEnabled = false
 
-    // Permission history is not available on Auto devices running S or below.
-    @Before
-    fun assumeNotAutoBelowT() {
-        assumeFalse(isAutomotive && !SdkLevel.isAtLeastT())
-    }
-
     @Before
     fun installAppLocationProviderAndAllowMockLocation() {
         installPackage(APP_APK_PATH, grantRuntimePermissions = true)
@@ -79,7 +74,6 @@
         }
     }
 
-    @CtsDownstreamingTest
     @Test
     fun testLocationProviderAttributionForMicrophone() {
         enableAppAsLocationProvider()
diff --git a/tests/tests/permission4/src/android/permission4/cts/CameraMicIndicatorsPermissionTest.kt b/tests/tests/permission4/src/android/permission4/cts/CameraMicIndicatorsPermissionTest.kt
index f23faae..fe9037a 100644
--- a/tests/tests/permission4/src/android/permission4/cts/CameraMicIndicatorsPermissionTest.kt
+++ b/tests/tests/permission4/src/android/permission4/cts/CameraMicIndicatorsPermissionTest.kt
@@ -295,7 +295,7 @@
                 // indicator
                 uiDevice.openQuickSettings()
                 assertPrivacyChipAndIndicatorsPresent(
-                    useMic || useHotword,
+                    useMic,
                     useCamera,
                     chainUsage,
                     safetyCenterEnabled
@@ -390,11 +390,13 @@
         chainUsage: Boolean,
         safetyCenterEnabled: Boolean = false
     ) {
-        // Ensure the privacy chip is present
-        eventually {
-            val privacyChip = uiDevice.findObject(UiSelector().resourceId(PRIVACY_CHIP_ID))
-            assertTrue("view with id $PRIVACY_CHIP_ID not found", privacyChip.exists())
-            privacyChip.click()
+        // Ensure the privacy chip is present (or not)
+        val chipFound = isChipPresent()
+        if (useMic || useCamera) {
+            assertTrue("Did not find chip", chipFound)
+        } else { // hotword
+            assertFalse("Found chip, but did not expect to", chipFound)
+            return
         }
 
         eventually {
@@ -455,6 +457,21 @@
         assertEquals("Expected only one shell view", 1, shellView.size)
     }
 
+    private fun isChipPresent(): Boolean {
+        var chipFound = false
+        try {
+            eventually {
+                val privacyChip = uiDevice.findObject(By.res(PRIVACY_CHIP_ID))
+                assertNotNull("view with id $PRIVACY_CHIP_ID not found", privacyChip)
+                privacyChip.click()
+                chipFound = true
+            }
+        } catch (e: Exception) {
+            // Handle more gracefully after
+        }
+        return chipFound
+    }
+
     private fun pressBack() {
         uiDevice.pressBack()
         waitForIdle()