Adding API for createPictureProfile and getPictureProfileById

Test: add logs and through CTS
Flag: android.media.tv.flags.media_quality_fw

Change-Id: I83597620af0b738fffbc77b813bad7b572abd3cc
diff --git a/media/java/android/media/quality/MediaQualityContract.java b/media/java/android/media/quality/MediaQualityContract.java
index 472d798..f07ef87 100644
--- a/media/java/android/media/quality/MediaQualityContract.java
+++ b/media/java/android/media/quality/MediaQualityContract.java
@@ -33,6 +33,7 @@
      */
     public interface BaseParameters {
         String PARAMETER_ID = "_id";
+        String PARAMETER_TYPE = "_type";
         String PARAMETER_NAME = "_name";
         String PARAMETER_PACKAGE = "_package";
         String PARAMETER_INPUT_ID = "_input_id";
@@ -43,7 +44,7 @@
      * Parameters picture quality.
      * @hide
      */
-    public static final class PictureQuality {
+    public static final class PictureQuality implements BaseParameters {
         /**
          * The brightness.
          *
diff --git a/services/core/java/com/android/server/media/quality/MediaQualityDbHelper.java b/services/core/java/com/android/server/media/quality/MediaQualityDbHelper.java
new file mode 100644
index 0000000..04f6216
--- /dev/null
+++ b/services/core/java/com/android/server/media/quality/MediaQualityDbHelper.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.media.quality;
+
+import android.content.Context;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+import android.media.quality.MediaQualityContract.BaseParameters;
+
+public class MediaQualityDbHelper extends SQLiteOpenHelper {
+
+    private static final String TAG = "MediaQualityDbHelper";
+
+    static final int DATABASE_VERSION_1 = 1;
+    private static final String DATABASE_NAME = "media_quality.db";
+    public static final String PICTURE_QUALITY_TABLE_NAME = "picture_quality";
+    public static final String SOUND_QUALITY_TABLE_NAME = "sound_quality";
+    public static final String SETTINGS = "settings";
+
+    MediaQualityDbHelper(Context context) {
+        super(context, DATABASE_NAME, null, getDbVersion());
+    }
+
+    private static int getDbVersion() {
+        return DATABASE_VERSION_1;
+    }
+
+    @Override
+    public void onCreate(SQLiteDatabase db) {
+        db.execSQL(getTableCreateStatement(PICTURE_QUALITY_TABLE_NAME));
+        db.execSQL(getTableCreateStatement(SOUND_QUALITY_TABLE_NAME));
+    }
+
+    private String getTableCreateStatement(String tableName) {
+        return
+                "CREATE TABLE " + tableName + "("
+                        + BaseParameters.PARAMETER_ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"
+                        + BaseParameters.PARAMETER_TYPE + " INTEGER,"
+                        + BaseParameters.PARAMETER_NAME + " STRING,"
+                        + BaseParameters.PARAMETER_PACKAGE + " STRING,"
+                        + BaseParameters.PARAMETER_INPUT_ID + " STRING,"
+                        + SETTINGS + " TEXT)";
+    }
+
+    @Override
+    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+        // to do
+    }
+
+}
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 21ae182..84413d5 100644
--- a/services/core/java/com/android/server/media/quality/MediaQualityService.java
+++ b/services/core/java/com/android/server/media/quality/MediaQualityService.java
@@ -16,20 +16,31 @@
 
 package com.android.server.media.quality;
 
+import android.content.ContentValues;
 import android.content.Context;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
 import android.media.quality.AmbientBacklightSettings;
 import android.media.quality.IAmbientBacklightCallback;
 import android.media.quality.IMediaQualityManager;
 import android.media.quality.IPictureProfileCallback;
 import android.media.quality.ISoundProfileCallback;
+import android.media.quality.MediaQualityContract.PictureQuality;
 import android.media.quality.ParamCapability;
 import android.media.quality.PictureProfile;
 import android.media.quality.SoundProfile;
+import android.os.Bundle;
+import android.util.Log;
 
 import com.android.server.SystemService;
 
+import org.json.JSONException;
+import org.json.JSONObject;
+
 import java.util.ArrayList;
+import java.util.Iterator;
 import java.util.List;
+import java.util.Locale;
 
 /**
  * This service manage picture profile and sound profile for TV setting. Also communicates with the
@@ -40,10 +51,14 @@
     private static final boolean DEBUG = false;
     private static final String TAG = "MediaQualityService";
     private final Context mContext;
+    private final MediaQualityDbHelper mMediaQualityDbHelper;
 
     public MediaQualityService(Context context) {
         super(context);
         mContext = context;
+        mMediaQualityDbHelper = new MediaQualityDbHelper(mContext);
+        mMediaQualityDbHelper.setWriteAheadLoggingEnabled(true);
+        mMediaQualityDbHelper.setIdleConnectionTimeout(30);
     }
 
     @Override
@@ -53,11 +68,23 @@
 
     // TODO: Add additional APIs. b/373951081
     private final class BinderService extends IMediaQualityManager.Stub {
+
         @Override
         public PictureProfile createPictureProfile(PictureProfile pp) {
-            // TODO: implement
-            return pp;
+            SQLiteDatabase db = mMediaQualityDbHelper.getWritableDatabase();
+
+            ContentValues values = new ContentValues();
+            values.put(PictureQuality.PARAMETER_TYPE, pp.getProfileType());
+            values.put(PictureQuality.PARAMETER_NAME, pp.getName());
+            values.put(PictureQuality.PARAMETER_PACKAGE, pp.getPackageName());
+            values.put(PictureQuality.PARAMETER_INPUT_ID, pp.getInputId());
+            values.put(mMediaQualityDbHelper.SETTINGS, bundleToJson(pp.getParameters()));
+
+            // id is auto-generated by SQLite upon successful insertion of row
+            long id = db.insert(mMediaQualityDbHelper.PICTURE_QUALITY_TABLE_NAME, null, values);
+            return new PictureProfile.Builder(pp).setProfileId(Long.toString(id)).build();
         }
+
         @Override
         public void updatePictureProfile(String id, PictureProfile pp) {
             // TODO: implement
@@ -66,10 +93,58 @@
         public void removePictureProfile(String id) {
             // TODO: implement
         }
+
         @Override
         public PictureProfile getPictureProfile(int type, String name) {
             return null;
         }
+
+        private String bundleToJson(Bundle bundle) {
+            JSONObject jsonObject = new JSONObject();
+            if (bundle == null) {
+                return jsonObject.toString();
+            }
+            for (String key : bundle.keySet()) {
+                try {
+                    jsonObject.put(key, bundle.getString(key));
+                } catch (JSONException e) {
+                    Log.e(TAG, "Unable to serialize ", e);
+                }
+            }
+            return jsonObject.toString();
+        }
+
+        private Bundle jsonToBundle(String jsonString) {
+            JSONObject jsonObject = null;
+            Bundle bundle = new Bundle();
+
+            try {
+                jsonObject = new JSONObject(jsonString);
+
+                Iterator<String> keys = jsonObject.keys();
+                while (keys.hasNext()) {
+                    String key = keys.next();
+                    Object value = jsonObject.get(key);
+
+                    if (value instanceof String) {
+                        bundle.putString(key, (String) value);
+                    } else if (value instanceof Integer) {
+                        bundle.putInt(key, (Integer) value);
+                    } else if (value instanceof Boolean) {
+                        bundle.putBoolean(key, (Boolean) value);
+                    } else if (value instanceof Double) {
+                        bundle.putDouble(key, (Double) value);
+                    } else if (value instanceof Long) {
+                        bundle.putLong(key, (Long) value);
+                    }
+                }
+            } catch (JSONException e) {
+                throw new RuntimeException(e);
+            }
+
+            return bundle;
+        }
+
         @Override
         public List<PictureProfile> getPictureProfilesByPackage(String packageName) {
             return new ArrayList<>();