From 9075f39fca1e800d786ce4974214424bf74588cd Mon Sep 17 00:00:00 2001 From: Yixiao Luo Date: Sat, 15 Mar 2025 12:36:42 -0700 Subject: [Media Quality] Picture profile application Support the following use cases: - Applying app-selected picture profile using KEY_PICTURE_PROFILE_INSTANCE or KEY_PICTURE_PROFILE_ID on MediaCodec.configure() - Applying app-selected picture profile using KEY_PICTURE_PROFILE_INSTANCE or KEY_PICTURE_PROFILE_ID on MediaCodec.setParameters() - Applying app-default picture profile from MediaQualityService on MediaCodec.configure() Bug: 391947448, 394391342 Test: m Flag: android.media.tv.flags.apply_picture_profiles Change-Id: Iaaa8a7f3ee6e3a3dbe8d208da7a63bbbb0ab9197 --- media/java/android/media/MediaCodec.java | 72 ++++++++++++++++++++-- .../media/quality/IMediaQualityManager.aidl | 3 + .../server/media/quality/MediaQualityService.java | 33 ++++++++++ 3 files changed, 104 insertions(+), 4 deletions(-) diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java index 15c832392a22..d0676e693b95 100644 --- a/media/java/android/media/MediaCodec.java +++ b/media/java/android/media/MediaCodec.java @@ -50,6 +50,7 @@ import android.os.Message; import android.os.PersistableBundle; import android.os.Trace; import android.view.Surface; +import android.util.Log; import java.io.IOException; import java.lang.annotation.Retention; @@ -1656,6 +1657,7 @@ import java.util.function.Supplier; */ final public class MediaCodec { + private static final String TAG = "MediaCodec"; /** * Per buffer metadata includes an offset and size specifying @@ -2496,6 +2498,49 @@ final public class MediaCodec { } keys[i] = "audio-hw-sync"; values[i] = AudioSystem.getAudioHwSyncForSession(sessionId); + } else if (applyPictureProfiles() && mediaQualityFw() + && entry.getKey().equals(MediaFormat.KEY_PICTURE_PROFILE_INSTANCE)) { + PictureProfile pictureProfile = null; + try { + pictureProfile = (PictureProfile) entry.getValue(); + } catch (ClassCastException e) { + throw new IllegalArgumentException( + "Cannot cast the instance parameter to PictureProfile!"); + } catch (Exception e) { + Log.e(TAG, Log.getStackTraceString(e)); + throw new IllegalArgumentException("Unexpected exception when casting the " + + "instance parameter to PictureProfile!"); + } + if (pictureProfile == null) { + throw new IllegalArgumentException( + "Picture profile instance parameter is null!"); + } + PictureProfileHandle handle = pictureProfile.getHandle(); + if (handle != PictureProfileHandle.NONE) { + keys[i] = PARAMETER_KEY_PICTURE_PROFILE_HANDLE; + values[i] = Long.valueOf(handle.getId()); + } + } else if (applyPictureProfiles() && mediaQualityFw() + && entry.getKey().equals(MediaFormat.KEY_PICTURE_PROFILE_ID)) { + String pictureProfileId = null; + try { + pictureProfileId = (String) entry.getValue(); + } catch (ClassCastException e) { + throw new IllegalArgumentException( + "Cannot cast the KEY_PICTURE_PROFILE_ID parameter to String!"); + } catch (Exception e) { + Log.e(TAG, Log.getStackTraceString(e)); + throw new IllegalArgumentException("Unexpected exception when casting the " + + "KEY_PICTURE_PROFILE_ID parameter!"); + } + if (pictureProfileId == null) { + throw new IllegalArgumentException( + "KEY_PICTURE_PROFILE_ID parameter is null!"); + } + if (!pictureProfileId.isEmpty()) { + keys[i] = MediaFormat.KEY_PICTURE_PROFILE_ID; + values[i] = pictureProfileId; + } } else { keys[i] = entry.getKey(); values[i] = entry.getValue(); @@ -5424,7 +5469,7 @@ final public class MediaCodec { throw new IllegalArgumentException( "Cannot cast the instance parameter to PictureProfile!"); } catch (Exception e) { - android.util.Log.getStackTraceString(e); + Log.e(TAG, Log.getStackTraceString(e)); throw new IllegalArgumentException("Unexpected exception when casting the " + "instance parameter to PictureProfile!"); } @@ -5437,6 +5482,26 @@ final public class MediaCodec { keys[i] = PARAMETER_KEY_PICTURE_PROFILE_HANDLE; values[i] = Long.valueOf(handle.getId()); } + } else if (applyPictureProfiles() && mediaQualityFw() + && key.equals(MediaFormat.KEY_PICTURE_PROFILE_ID)) { + String pictureProfileId = null; + try { + pictureProfileId = (String) params.get(key); + } catch (ClassCastException e) { + throw new IllegalArgumentException( + "Cannot cast the KEY_PICTURE_PROFILE_ID parameter to String!"); + } catch (Exception e) { + Log.e(TAG, Log.getStackTraceString(e)); + throw new IllegalArgumentException("Unexpected exception when casting the " + + "KEY_PICTURE_PROFILE_ID parameter!"); + } + if (pictureProfileId == null) { + throw new IllegalArgumentException("KEY_PICTURE_PROFILE_ID parameter is null!"); + } + if (!pictureProfileId.isEmpty()) { + keys[i] = MediaFormat.KEY_PICTURE_PROFILE_ID; + values[i] = pictureProfileId; + } } else { keys[i] = key; Object value = params.get(key); @@ -5455,10 +5520,9 @@ final public class MediaCodec { } private void logAndRun(String message, Runnable r) { - final String TAG = "MediaCodec"; - android.util.Log.d(TAG, "enter: " + message); + Log.d(TAG, "enter: " + message); r.run(); - android.util.Log.d(TAG, "exit : " + message); + Log.d(TAG, "exit : " + message); } /** diff --git a/media/java/android/media/quality/aidl/android/media/quality/IMediaQualityManager.aidl b/media/java/android/media/quality/aidl/android/media/quality/IMediaQualityManager.aidl index 6ac1656b77aa..4f24d8c5cc48 100644 --- a/media/java/android/media/quality/aidl/android/media/quality/IMediaQualityManager.aidl +++ b/media/java/android/media/quality/aidl/android/media/quality/IMediaQualityManager.aidl @@ -46,6 +46,9 @@ interface IMediaQualityManager { List getPictureProfileAllowList(int userId); void setPictureProfileAllowList(in List packages, int userId); List getPictureProfileHandle(in String[] id, int userId); + long getPictureProfileHandleValue(in String id, int userId); + long getDefaultPictureProfileHandleValue(int userId); + void notifyPictureProfileHandleSelection(in long handle, int userId); void createSoundProfile(in SoundProfile pp, int userId); void updateSoundProfile(in String id, in SoundProfile pp, int userId); diff --git a/services/core/java/com/android/server/media/quality/MediaQualityService.java b/services/core/java/com/android/server/media/quality/MediaQualityService.java index 4c61e226a574..d1dcd9d9fa75 100644 --- a/services/core/java/com/android/server/media/quality/MediaQualityService.java +++ b/services/core/java/com/android/server/media/quality/MediaQualityService.java @@ -105,6 +105,7 @@ public class MediaQualityService extends SystemService { private final MediaQualityDbHelper mMediaQualityDbHelper; private final BiMap mPictureProfileTempIdMap; private final BiMap mSoundProfileTempIdMap; + private final Map mPackageDefaultPictureProfileHandleMap = new HashMap<>(); private IMediaQuality mMediaQuality; private PictureProfileAdjustmentListenerImpl mPictureProfileAdjListener; private SoundProfileAdjustmentListenerImpl mSoundProfileAdjListener; @@ -184,6 +185,8 @@ public class MediaQualityService extends SystemService { mMediaQuality.setPictureProfileAdjustmentListener(mPictureProfileAdjListener); mMediaQuality.setSoundProfileAdjustmentListener(mSoundProfileAdjListener); + // TODO: populate mPackageDefaultPictureProfileHandleMap + } catch (RemoteException e) { Slog.e(TAG, "Failed to set ambient backlight detector callback", e); } @@ -443,6 +446,36 @@ public class MediaQualityService extends SystemService { return toReturn; } + @GuardedBy("mPictureProfileLock") + @Override + public long getPictureProfileHandleValue(String id, int userId) { + synchronized (mPictureProfileLock) { + Long value = mPictureProfileTempIdMap.getKey(id); + return value != null ? value : -1; + } + } + + @GuardedBy("mPictureProfileLock") + @Override + public long getDefaultPictureProfileHandleValue(int userId) { + synchronized (mPictureProfileLock) { + String packageName = getPackageOfCallingUid(); + Long value = null; + if (packageName != null) { + value = mPackageDefaultPictureProfileHandleMap.get(packageName); + } + return value != null ? value : -1; + } + } + + @GuardedBy("mPictureProfileLock") + @Override + public void notifyPictureProfileHandleSelection(long handle, int userId) { + PictureProfile profile = mMqDatabaseUtils.getPictureProfile(handle); + if (profile != null) { + mHalNotifier.notifyHalOnPictureProfileChange(handle, profile.getParameters()); + } + } @GuardedBy("mSoundProfileLock") @Override -- cgit v1.2.3-59-g8ed1b