Loading core/api/test-current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -800,6 +800,7 @@ package android.content.pm { method public boolean hasRequestForegroundServiceExemption(); method public boolean isPrivilegedApp(); method public boolean isSystemApp(); method public void setEnableOnBackInvokedCallback(boolean); field public static final int PRIVATE_FLAG_PRIVILEGED = 8; // 0x8 field public int privateFlags; } Loading core/java/android/app/AppOpsManager.java +14 −9 Original line number Diff line number Diff line Loading @@ -2537,8 +2537,8 @@ public class AppOpsManager { * restriction} for a certain app-op. */ private static RestrictionBypass[] sOpAllowSystemRestrictionBypass = new RestrictionBypass[] { null, //COARSE_LOCATION null, //FINE_LOCATION new RestrictionBypass(true, false, false), //COARSE_LOCATION new RestrictionBypass(true, false, false), //FINE_LOCATION null, //GPS null, //VIBRATE null, //READ_CONTACTS Loading @@ -2547,7 +2547,7 @@ public class AppOpsManager { null, //WRITE_CALL_LOG null, //READ_CALENDAR null, //WRITE_CALENDAR new RestrictionBypass(true, false), //WIFI_SCAN new RestrictionBypass(false, true, false), //WIFI_SCAN null, //POST_NOTIFICATION null, //NEIGHBORING_CELLS null, //CALL_PHONE Loading @@ -2561,10 +2561,10 @@ public class AppOpsManager { null, //READ_ICC_SMS null, //WRITE_ICC_SMS null, //WRITE_SETTINGS new RestrictionBypass(true, false), //SYSTEM_ALERT_WINDOW new RestrictionBypass(false, true, false), //SYSTEM_ALERT_WINDOW null, //ACCESS_NOTIFICATIONS null, //CAMERA new RestrictionBypass(false, true), //RECORD_AUDIO new RestrictionBypass(false, false, true), //RECORD_AUDIO null, //PLAY_AUDIO null, //READ_CLIPBOARD null, //WRITE_CLIPBOARD Loading @@ -2582,7 +2582,7 @@ public class AppOpsManager { null, //MONITOR_HIGH_POWER_LOCATION null, //GET_USAGE_STATS null, //MUTE_MICROPHONE new RestrictionBypass(true, false), //TOAST_WINDOW new RestrictionBypass(false, true, false), //TOAST_WINDOW null, //PROJECT_MEDIA null, //ACTIVATE_VPN null, //WALLPAPER Loading Loading @@ -2614,7 +2614,7 @@ public class AppOpsManager { null, // ACCEPT_HANDOVER null, // MANAGE_IPSEC_HANDOVERS null, // START_FOREGROUND new RestrictionBypass(true, false), // BLUETOOTH_SCAN new RestrictionBypass(false, true, false), // BLUETOOTH_SCAN null, // USE_BIOMETRIC null, // ACTIVITY_RECOGNITION null, // SMS_FINANCIAL_TRANSACTIONS Loading Loading @@ -3331,6 +3331,9 @@ public class AppOpsManager { * @hide */ public static class RestrictionBypass { /** Does the app need to be system uid to bypass the restriction */ public boolean isSystemUid; /** Does the app need to be privileged to bypass the restriction */ public boolean isPrivileged; Loading @@ -3340,12 +3343,14 @@ public class AppOpsManager { */ public boolean isRecordAudioRestrictionExcept; public RestrictionBypass(boolean isPrivileged, boolean isRecordAudioRestrictionExcept) { public RestrictionBypass(boolean isSystemUid, boolean isPrivileged, boolean isRecordAudioRestrictionExcept) { this.isSystemUid = isSystemUid; this.isPrivileged = isPrivileged; this.isRecordAudioRestrictionExcept = isRecordAudioRestrictionExcept; } public static RestrictionBypass UNRESTRICTED = new RestrictionBypass(true, true); public static RestrictionBypass UNRESTRICTED = new RestrictionBypass(false, true, true); } /** Loading core/java/android/app/admin/DevicePolicyManager.java +7 −6 Original line number Diff line number Diff line Loading @@ -1811,10 +1811,6 @@ public class DevicePolicyManager { * #EXTRA_PROVISIONING_ALLOWED_PROVISIONING_MODES} array extra contain {@link * #PROVISIONING_MODE_MANAGED_PROFILE} and {@link #PROVISIONING_MODE_FULLY_MANAGED_DEVICE}. * * <p>Also, if this flag is set, the admin app's {@link #ACTION_GET_PROVISIONING_MODE} activity * will not receive the {@link #EXTRA_PROVISIONING_IMEI} and {@link * #EXTRA_PROVISIONING_SERIAL_NUMBER} extras. * * <p>This flag can be combined with {@link #FLAG_SUPPORTED_MODES_PERSONALLY_OWNED}. In * that case, the admin app's {@link #ACTION_GET_PROVISIONING_MODE} activity will have * the {@link #EXTRA_PROVISIONING_ALLOWED_PROVISIONING_MODES} array extra contain {@link Loading @@ -1834,6 +1830,10 @@ public class DevicePolicyManager { * activity to have the {@link #EXTRA_PROVISIONING_ALLOWED_PROVISIONING_MODES} array extra * contain only {@link #PROVISIONING_MODE_MANAGED_PROFILE}. * * <p>Also, if this flag is set, the admin app's {@link #ACTION_GET_PROVISIONING_MODE} activity * will not receive the {@link #EXTRA_PROVISIONING_IMEI} and {@link * #EXTRA_PROVISIONING_SERIAL_NUMBER} extras. * * <p>This flag can be combined with {@link #FLAG_SUPPORTED_MODES_ORGANIZATION_OWNED}. In * that case, the admin app's {@link #ACTION_GET_PROVISIONING_MODE} activity will have the * {@link #EXTRA_PROVISIONING_ALLOWED_PROVISIONING_MODES} array extra contain {@link Loading Loading @@ -13249,8 +13249,9 @@ public class DevicePolicyManager { * Called by a device owner, profile owner of a managed profile or delegated app with * {@link #DELEGATION_NETWORK_LOGGING} to control the network logging feature. * * <p> When network logging is enabled by a profile owner, the network logs will only include * work profile network activity, not activity on the personal profile. * <p> Supported for a device owner from Android 8. Supported for a profile owner of a managed * profile from Android 12. When network logging is enabled by a profile owner, the network logs * will only include work profile network activity, not activity on the personal profile. * * <p> Network logs contain DNS lookup and connect() library call events. The following library * functions are recorded while network logging is active: core/java/android/content/pm/ApplicationInfo.java +17 −0 Original line number Diff line number Diff line Loading @@ -2752,4 +2752,21 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { mKnownActivityEmbeddingCerts.add(knownCert.toUpperCase(Locale.US)); } } /** * Sets whether the application will use the {@link android.window.OnBackInvokedCallback} * navigation system instead of the {@link android.view.KeyEvent#KEYCODE_BACK} and related * callbacks. Intended to be used from tests only. * * @see #isOnBackInvokedCallbackEnabled() * @hide */ @TestApi public void setEnableOnBackInvokedCallback(boolean isEnable) { if (isEnable) { privateFlagsExt |= PRIVATE_FLAG_EXT_ENABLE_ON_BACK_INVOKED_CALLBACK; } else { privateFlagsExt &= ~PRIVATE_FLAG_EXT_ENABLE_ON_BACK_INVOKED_CALLBACK; } } } core/java/android/hardware/camera2/impl/CameraExtensionSessionImpl.java +96 −33 Original line number Diff line number Diff line Loading @@ -72,7 +72,7 @@ import java.util.Set; import java.util.concurrent.Executor; public final class CameraExtensionSessionImpl extends CameraExtensionSession { private static final int PREVIEW_QUEUE_SIZE = 3; private static final int PREVIEW_QUEUE_SIZE = 10; private static final String TAG = "CameraExtensionSessionImpl"; private final Executor mExecutor; Loading Loading @@ -1057,15 +1057,8 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession { mClientRequest)); if (mCaptureResultHandler != null) { CameraMetadataNative captureResults = new CameraMetadataNative(); for (CaptureResult.Key key : mSupportedResultKeys) { Object value = result.get(key); if (value != null) { captureResults.set(key, value); } } mCaptureResultHandler.onCaptureCompleted(timestamp, captureResults); initializeFilteredResults(result)); } } finally { Binder.restoreCallingIdentity(ident); Loading Loading @@ -1126,6 +1119,11 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession { } private class ImageCallback implements OnImageAvailableListener { @Override public void onImageDropped(long timestamp) { notifyCaptureFailed(); } @Override public void onImageAvailable(ImageReader reader, Image img) { if (mCaptureFailed) { Loading Loading @@ -1159,6 +1157,9 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession { } private class ImageLoopbackCallback implements OnImageAvailableListener { @Override public void onImageDropped(long timestamp) { } @Override public void onImageAvailable(ImageReader reader, Image img) { img.close(); Loading Loading @@ -1221,7 +1222,8 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession { } private interface OnImageAvailableListener { public void onImageAvailable (ImageReader reader, Image img); void onImageDropped(long timestamp); void onImageAvailable (ImageReader reader, Image img); } private class CameraOutputImageCallback implements ImageReader.OnImageAvailableListener, Loading Loading @@ -1263,6 +1265,29 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession { } else { mImageListenerMap.put(img.getTimestamp(), new Pair<>(img, null)); } notifyDroppedImages(timestamp); } private void notifyDroppedImages(long timestamp) { Set<Long> timestamps = mImageListenerMap.keySet(); ArrayList<Long> removedTs = new ArrayList<>(); for (long ts : timestamps) { if (ts < timestamp) { Log.e(TAG, "Dropped image with ts: " + ts); Pair<Image, OnImageAvailableListener> entry = mImageListenerMap.get(ts); if (entry.second != null) { entry.second.onImageDropped(ts); } if (entry.first != null) { entry.first.close(); } removedTs.add(ts); } } for (long ts : removedTs) { mImageListenerMap.remove(ts); } } public void registerListener(Long timestamp, OnImageAvailableListener listener) { Loading Loading @@ -1291,6 +1316,12 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession { entry.first.close(); } } for (long timestamp : mImageListenerMap.keySet()) { Pair<Image, OnImageAvailableListener> entry = mImageListenerMap.get(timestamp); if (entry.second != null) { entry.second.onImageDropped(timestamp); } } mImageListenerMap.clear(); } } Loading Loading @@ -1447,7 +1478,6 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession { } else { notifyConfigurationFailure(); } } @Override Loading Loading @@ -1536,7 +1566,16 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession { } else if (mPreviewProcessorType == IPreviewExtenderImpl.PROCESSOR_TYPE_IMAGE_PROCESSOR) { int idx = mPendingResultMap.indexOfKey(timestamp); if (idx >= 0) { if ((idx >= 0) && (mPendingResultMap.get(timestamp).first == null)) { // Image was dropped before we can receive the capture results if ((mCaptureResultHandler != null)) { mCaptureResultHandler.onCaptureCompleted(timestamp, initializeFilteredResults(result)); } discardPendingRepeatingResults(idx, mPendingResultMap, false); } else if (idx >= 0) { // Image came before the capture results ParcelImage parcelImage = initializeParcelImage( mPendingResultMap.get(timestamp).first); try { Loading @@ -1563,6 +1602,7 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession { } discardPendingRepeatingResults(idx, mPendingResultMap, false); } else { // Image not yet available notifyClient = false; mPendingResultMap.put(timestamp, new Pair<>(null, Loading @@ -1581,16 +1621,8 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession { mClientRequest)); if ((mCaptureResultHandler != null) && (mPreviewProcessorType != IPreviewExtenderImpl.PROCESSOR_TYPE_IMAGE_PROCESSOR)) { CameraMetadataNative captureResults = new CameraMetadataNative(); for (CaptureResult.Key key : mSupportedResultKeys) { Object value = result.get(key); if (value != null) { captureResults.set(key, value); } } mCaptureResultHandler.onCaptureCompleted(timestamp, captureResults); initializeFilteredResults(result)); } } else { mExecutor.execute( Loading Loading @@ -1657,8 +1689,13 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession { for (int i = idx; i >= 0; i--) { if (previewMap.valueAt(i).first != null) { previewMap.valueAt(i).first.close(); } else { if (mClientNotificationsEnabled && ((i != idx) || notifyCurrentIndex)) { } else if (mClientNotificationsEnabled && (previewMap.valueAt(i).second != null) && ((i != idx) || notifyCurrentIndex)) { TotalCaptureResult result = previewMap.valueAt(i).second; Long timestamp = result.get(CaptureResult.SENSOR_TIMESTAMP); mCaptureResultHandler.onCaptureCompleted(timestamp, initializeFilteredResults(result)); Log.w(TAG, "Preview frame drop with timestamp: " + previewMap.keyAt(i)); final long ident = Binder.clearCallingIdentity(); try { Loading @@ -1669,7 +1706,7 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession { } finally { Binder.restoreCallingIdentity(ident); } } } previewMap.removeAt(i); } Loading @@ -1682,6 +1719,12 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession { mOutputWriter = imageWriter; } @Override public void onImageDropped(long timestamp) { discardPendingRepeatingResults(mPendingResultMap.indexOfKey(timestamp), mPendingResultMap, true); } @Override public void onImageAvailable(ImageReader reader, Image img) { if (img == null) { Loading @@ -1702,6 +1745,15 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession { private class ImageProcessCallback implements OnImageAvailableListener { @Override public void onImageDropped(long timestamp) { discardPendingRepeatingResults(mPendingResultMap.indexOfKey(timestamp), mPendingResultMap, true); // Add an empty frame&results entry to flag that we dropped a frame // and valid capture results can immediately return to client. mPendingResultMap.put(timestamp, new Pair<>(null, null)); } @Override public void onImageAvailable(ImageReader reader, Image img) { if (mPendingResultMap.size() + 1 >= PREVIEW_QUEUE_SIZE) { Loading Loading @@ -1768,6 +1820,17 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession { } } private CameraMetadataNative initializeFilteredResults(TotalCaptureResult result) { CameraMetadataNative captureResults = new CameraMetadataNative(); for (CaptureResult.Key key : mSupportedResultKeys) { Object value = result.get(key); if (value != null) { captureResults.set(key, value); } } return captureResults; } private static Size findSmallestAspectMatchedSize(@NonNull List<Size> sizes, @NonNull Size arSize) { final float TOLL = .01f; Loading Loading
core/api/test-current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -800,6 +800,7 @@ package android.content.pm { method public boolean hasRequestForegroundServiceExemption(); method public boolean isPrivilegedApp(); method public boolean isSystemApp(); method public void setEnableOnBackInvokedCallback(boolean); field public static final int PRIVATE_FLAG_PRIVILEGED = 8; // 0x8 field public int privateFlags; } Loading
core/java/android/app/AppOpsManager.java +14 −9 Original line number Diff line number Diff line Loading @@ -2537,8 +2537,8 @@ public class AppOpsManager { * restriction} for a certain app-op. */ private static RestrictionBypass[] sOpAllowSystemRestrictionBypass = new RestrictionBypass[] { null, //COARSE_LOCATION null, //FINE_LOCATION new RestrictionBypass(true, false, false), //COARSE_LOCATION new RestrictionBypass(true, false, false), //FINE_LOCATION null, //GPS null, //VIBRATE null, //READ_CONTACTS Loading @@ -2547,7 +2547,7 @@ public class AppOpsManager { null, //WRITE_CALL_LOG null, //READ_CALENDAR null, //WRITE_CALENDAR new RestrictionBypass(true, false), //WIFI_SCAN new RestrictionBypass(false, true, false), //WIFI_SCAN null, //POST_NOTIFICATION null, //NEIGHBORING_CELLS null, //CALL_PHONE Loading @@ -2561,10 +2561,10 @@ public class AppOpsManager { null, //READ_ICC_SMS null, //WRITE_ICC_SMS null, //WRITE_SETTINGS new RestrictionBypass(true, false), //SYSTEM_ALERT_WINDOW new RestrictionBypass(false, true, false), //SYSTEM_ALERT_WINDOW null, //ACCESS_NOTIFICATIONS null, //CAMERA new RestrictionBypass(false, true), //RECORD_AUDIO new RestrictionBypass(false, false, true), //RECORD_AUDIO null, //PLAY_AUDIO null, //READ_CLIPBOARD null, //WRITE_CLIPBOARD Loading @@ -2582,7 +2582,7 @@ public class AppOpsManager { null, //MONITOR_HIGH_POWER_LOCATION null, //GET_USAGE_STATS null, //MUTE_MICROPHONE new RestrictionBypass(true, false), //TOAST_WINDOW new RestrictionBypass(false, true, false), //TOAST_WINDOW null, //PROJECT_MEDIA null, //ACTIVATE_VPN null, //WALLPAPER Loading Loading @@ -2614,7 +2614,7 @@ public class AppOpsManager { null, // ACCEPT_HANDOVER null, // MANAGE_IPSEC_HANDOVERS null, // START_FOREGROUND new RestrictionBypass(true, false), // BLUETOOTH_SCAN new RestrictionBypass(false, true, false), // BLUETOOTH_SCAN null, // USE_BIOMETRIC null, // ACTIVITY_RECOGNITION null, // SMS_FINANCIAL_TRANSACTIONS Loading Loading @@ -3331,6 +3331,9 @@ public class AppOpsManager { * @hide */ public static class RestrictionBypass { /** Does the app need to be system uid to bypass the restriction */ public boolean isSystemUid; /** Does the app need to be privileged to bypass the restriction */ public boolean isPrivileged; Loading @@ -3340,12 +3343,14 @@ public class AppOpsManager { */ public boolean isRecordAudioRestrictionExcept; public RestrictionBypass(boolean isPrivileged, boolean isRecordAudioRestrictionExcept) { public RestrictionBypass(boolean isSystemUid, boolean isPrivileged, boolean isRecordAudioRestrictionExcept) { this.isSystemUid = isSystemUid; this.isPrivileged = isPrivileged; this.isRecordAudioRestrictionExcept = isRecordAudioRestrictionExcept; } public static RestrictionBypass UNRESTRICTED = new RestrictionBypass(true, true); public static RestrictionBypass UNRESTRICTED = new RestrictionBypass(false, true, true); } /** Loading
core/java/android/app/admin/DevicePolicyManager.java +7 −6 Original line number Diff line number Diff line Loading @@ -1811,10 +1811,6 @@ public class DevicePolicyManager { * #EXTRA_PROVISIONING_ALLOWED_PROVISIONING_MODES} array extra contain {@link * #PROVISIONING_MODE_MANAGED_PROFILE} and {@link #PROVISIONING_MODE_FULLY_MANAGED_DEVICE}. * * <p>Also, if this flag is set, the admin app's {@link #ACTION_GET_PROVISIONING_MODE} activity * will not receive the {@link #EXTRA_PROVISIONING_IMEI} and {@link * #EXTRA_PROVISIONING_SERIAL_NUMBER} extras. * * <p>This flag can be combined with {@link #FLAG_SUPPORTED_MODES_PERSONALLY_OWNED}. In * that case, the admin app's {@link #ACTION_GET_PROVISIONING_MODE} activity will have * the {@link #EXTRA_PROVISIONING_ALLOWED_PROVISIONING_MODES} array extra contain {@link Loading @@ -1834,6 +1830,10 @@ public class DevicePolicyManager { * activity to have the {@link #EXTRA_PROVISIONING_ALLOWED_PROVISIONING_MODES} array extra * contain only {@link #PROVISIONING_MODE_MANAGED_PROFILE}. * * <p>Also, if this flag is set, the admin app's {@link #ACTION_GET_PROVISIONING_MODE} activity * will not receive the {@link #EXTRA_PROVISIONING_IMEI} and {@link * #EXTRA_PROVISIONING_SERIAL_NUMBER} extras. * * <p>This flag can be combined with {@link #FLAG_SUPPORTED_MODES_ORGANIZATION_OWNED}. In * that case, the admin app's {@link #ACTION_GET_PROVISIONING_MODE} activity will have the * {@link #EXTRA_PROVISIONING_ALLOWED_PROVISIONING_MODES} array extra contain {@link Loading Loading @@ -13249,8 +13249,9 @@ public class DevicePolicyManager { * Called by a device owner, profile owner of a managed profile or delegated app with * {@link #DELEGATION_NETWORK_LOGGING} to control the network logging feature. * * <p> When network logging is enabled by a profile owner, the network logs will only include * work profile network activity, not activity on the personal profile. * <p> Supported for a device owner from Android 8. Supported for a profile owner of a managed * profile from Android 12. When network logging is enabled by a profile owner, the network logs * will only include work profile network activity, not activity on the personal profile. * * <p> Network logs contain DNS lookup and connect() library call events. The following library * functions are recorded while network logging is active:
core/java/android/content/pm/ApplicationInfo.java +17 −0 Original line number Diff line number Diff line Loading @@ -2752,4 +2752,21 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { mKnownActivityEmbeddingCerts.add(knownCert.toUpperCase(Locale.US)); } } /** * Sets whether the application will use the {@link android.window.OnBackInvokedCallback} * navigation system instead of the {@link android.view.KeyEvent#KEYCODE_BACK} and related * callbacks. Intended to be used from tests only. * * @see #isOnBackInvokedCallbackEnabled() * @hide */ @TestApi public void setEnableOnBackInvokedCallback(boolean isEnable) { if (isEnable) { privateFlagsExt |= PRIVATE_FLAG_EXT_ENABLE_ON_BACK_INVOKED_CALLBACK; } else { privateFlagsExt &= ~PRIVATE_FLAG_EXT_ENABLE_ON_BACK_INVOKED_CALLBACK; } } }
core/java/android/hardware/camera2/impl/CameraExtensionSessionImpl.java +96 −33 Original line number Diff line number Diff line Loading @@ -72,7 +72,7 @@ import java.util.Set; import java.util.concurrent.Executor; public final class CameraExtensionSessionImpl extends CameraExtensionSession { private static final int PREVIEW_QUEUE_SIZE = 3; private static final int PREVIEW_QUEUE_SIZE = 10; private static final String TAG = "CameraExtensionSessionImpl"; private final Executor mExecutor; Loading Loading @@ -1057,15 +1057,8 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession { mClientRequest)); if (mCaptureResultHandler != null) { CameraMetadataNative captureResults = new CameraMetadataNative(); for (CaptureResult.Key key : mSupportedResultKeys) { Object value = result.get(key); if (value != null) { captureResults.set(key, value); } } mCaptureResultHandler.onCaptureCompleted(timestamp, captureResults); initializeFilteredResults(result)); } } finally { Binder.restoreCallingIdentity(ident); Loading Loading @@ -1126,6 +1119,11 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession { } private class ImageCallback implements OnImageAvailableListener { @Override public void onImageDropped(long timestamp) { notifyCaptureFailed(); } @Override public void onImageAvailable(ImageReader reader, Image img) { if (mCaptureFailed) { Loading Loading @@ -1159,6 +1157,9 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession { } private class ImageLoopbackCallback implements OnImageAvailableListener { @Override public void onImageDropped(long timestamp) { } @Override public void onImageAvailable(ImageReader reader, Image img) { img.close(); Loading Loading @@ -1221,7 +1222,8 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession { } private interface OnImageAvailableListener { public void onImageAvailable (ImageReader reader, Image img); void onImageDropped(long timestamp); void onImageAvailable (ImageReader reader, Image img); } private class CameraOutputImageCallback implements ImageReader.OnImageAvailableListener, Loading Loading @@ -1263,6 +1265,29 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession { } else { mImageListenerMap.put(img.getTimestamp(), new Pair<>(img, null)); } notifyDroppedImages(timestamp); } private void notifyDroppedImages(long timestamp) { Set<Long> timestamps = mImageListenerMap.keySet(); ArrayList<Long> removedTs = new ArrayList<>(); for (long ts : timestamps) { if (ts < timestamp) { Log.e(TAG, "Dropped image with ts: " + ts); Pair<Image, OnImageAvailableListener> entry = mImageListenerMap.get(ts); if (entry.second != null) { entry.second.onImageDropped(ts); } if (entry.first != null) { entry.first.close(); } removedTs.add(ts); } } for (long ts : removedTs) { mImageListenerMap.remove(ts); } } public void registerListener(Long timestamp, OnImageAvailableListener listener) { Loading Loading @@ -1291,6 +1316,12 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession { entry.first.close(); } } for (long timestamp : mImageListenerMap.keySet()) { Pair<Image, OnImageAvailableListener> entry = mImageListenerMap.get(timestamp); if (entry.second != null) { entry.second.onImageDropped(timestamp); } } mImageListenerMap.clear(); } } Loading Loading @@ -1447,7 +1478,6 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession { } else { notifyConfigurationFailure(); } } @Override Loading Loading @@ -1536,7 +1566,16 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession { } else if (mPreviewProcessorType == IPreviewExtenderImpl.PROCESSOR_TYPE_IMAGE_PROCESSOR) { int idx = mPendingResultMap.indexOfKey(timestamp); if (idx >= 0) { if ((idx >= 0) && (mPendingResultMap.get(timestamp).first == null)) { // Image was dropped before we can receive the capture results if ((mCaptureResultHandler != null)) { mCaptureResultHandler.onCaptureCompleted(timestamp, initializeFilteredResults(result)); } discardPendingRepeatingResults(idx, mPendingResultMap, false); } else if (idx >= 0) { // Image came before the capture results ParcelImage parcelImage = initializeParcelImage( mPendingResultMap.get(timestamp).first); try { Loading @@ -1563,6 +1602,7 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession { } discardPendingRepeatingResults(idx, mPendingResultMap, false); } else { // Image not yet available notifyClient = false; mPendingResultMap.put(timestamp, new Pair<>(null, Loading @@ -1581,16 +1621,8 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession { mClientRequest)); if ((mCaptureResultHandler != null) && (mPreviewProcessorType != IPreviewExtenderImpl.PROCESSOR_TYPE_IMAGE_PROCESSOR)) { CameraMetadataNative captureResults = new CameraMetadataNative(); for (CaptureResult.Key key : mSupportedResultKeys) { Object value = result.get(key); if (value != null) { captureResults.set(key, value); } } mCaptureResultHandler.onCaptureCompleted(timestamp, captureResults); initializeFilteredResults(result)); } } else { mExecutor.execute( Loading Loading @@ -1657,8 +1689,13 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession { for (int i = idx; i >= 0; i--) { if (previewMap.valueAt(i).first != null) { previewMap.valueAt(i).first.close(); } else { if (mClientNotificationsEnabled && ((i != idx) || notifyCurrentIndex)) { } else if (mClientNotificationsEnabled && (previewMap.valueAt(i).second != null) && ((i != idx) || notifyCurrentIndex)) { TotalCaptureResult result = previewMap.valueAt(i).second; Long timestamp = result.get(CaptureResult.SENSOR_TIMESTAMP); mCaptureResultHandler.onCaptureCompleted(timestamp, initializeFilteredResults(result)); Log.w(TAG, "Preview frame drop with timestamp: " + previewMap.keyAt(i)); final long ident = Binder.clearCallingIdentity(); try { Loading @@ -1669,7 +1706,7 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession { } finally { Binder.restoreCallingIdentity(ident); } } } previewMap.removeAt(i); } Loading @@ -1682,6 +1719,12 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession { mOutputWriter = imageWriter; } @Override public void onImageDropped(long timestamp) { discardPendingRepeatingResults(mPendingResultMap.indexOfKey(timestamp), mPendingResultMap, true); } @Override public void onImageAvailable(ImageReader reader, Image img) { if (img == null) { Loading @@ -1702,6 +1745,15 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession { private class ImageProcessCallback implements OnImageAvailableListener { @Override public void onImageDropped(long timestamp) { discardPendingRepeatingResults(mPendingResultMap.indexOfKey(timestamp), mPendingResultMap, true); // Add an empty frame&results entry to flag that we dropped a frame // and valid capture results can immediately return to client. mPendingResultMap.put(timestamp, new Pair<>(null, null)); } @Override public void onImageAvailable(ImageReader reader, Image img) { if (mPendingResultMap.size() + 1 >= PREVIEW_QUEUE_SIZE) { Loading Loading @@ -1768,6 +1820,17 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession { } } private CameraMetadataNative initializeFilteredResults(TotalCaptureResult result) { CameraMetadataNative captureResults = new CameraMetadataNative(); for (CaptureResult.Key key : mSupportedResultKeys) { Object value = result.get(key); if (value != null) { captureResults.set(key, value); } } return captureResults; } private static Size findSmallestAspectMatchedSize(@NonNull List<Size> sizes, @NonNull Size arSize) { final float TOLL = .01f; Loading