Merge changes I962a8884,If095b33c into main
* changes:
[Media Quality] Add Temp Id Map to Sound Profile and refactor
[Media Quality] Implement Remove Picture Profile API & temp map functionality
diff --git a/services/core/Android.bp b/services/core/Android.bp
index 0820615..ffa259b 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -221,6 +221,7 @@
"securebox",
"apache-commons-math",
"battery_saver_flag_lib",
+ "guava",
"notification_flags_lib",
"power_hint_flags_lib",
"biometrics_flags_lib",
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 65d0ab3..14eeb3dc 100644
--- a/services/core/java/com/android/server/media/quality/MediaQualityService.java
+++ b/services/core/java/com/android/server/media/quality/MediaQualityService.java
@@ -35,6 +35,9 @@
import com.android.server.SystemService;
+import com.google.common.collect.BiMap;
+import com.google.common.collect.HashBiMap;
+
import org.json.JSONException;
import org.json.JSONObject;
@@ -43,6 +46,7 @@
import java.util.List;
import java.util.Locale;
import java.util.stream.Collectors;
+import java.util.UUID;
/**
* This service manage picture profile and sound profile for TV setting. Also communicates with the
@@ -54,10 +58,14 @@
private static final String TAG = "MediaQualityService";
private final Context mContext;
private final MediaQualityDbHelper mMediaQualityDbHelper;
+ private final BiMap<Long, String> mPictureProfileTempIdMap;
+ private final BiMap<Long, String> mSoundProfileTempIdMap;
public MediaQualityService(Context context) {
super(context);
mContext = context;
+ mPictureProfileTempIdMap = HashBiMap.create();
+ mSoundProfileTempIdMap = HashBiMap.create();
mMediaQualityDbHelper = new MediaQualityDbHelper(mContext);
mMediaQualityDbHelper.setWriteAheadLoggingEnabled(true);
mMediaQualityDbHelper.setIdleConnectionTimeout(30);
@@ -80,11 +88,14 @@
values.put(BaseParameters.PARAMETER_NAME, pp.getName());
values.put(BaseParameters.PARAMETER_PACKAGE, pp.getPackageName());
values.put(BaseParameters.PARAMETER_INPUT_ID, pp.getInputId());
- values.put(mMediaQualityDbHelper.SETTINGS, bundleToJson(pp.getParameters()));
+ values.put(mMediaQualityDbHelper.SETTINGS, persistableBundleToJson(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();
+ Long id = db.insert(mMediaQualityDbHelper.PICTURE_QUALITY_TABLE_NAME,
+ null, values);
+ populateTempIdMap(mPictureProfileTempIdMap, id);
+ pp.setProfileId(mPictureProfileTempIdMap.get(id));
+ return pp;
}
@Override
@@ -94,26 +105,27 @@
@Override
public void removePictureProfile(String id, int userId) {
- // TODO: implement
+ Long intId = mPictureProfileTempIdMap.inverse().get(id);
+ if (intId != null) {
+ SQLiteDatabase db = mMediaQualityDbHelper.getWritableDatabase();
+ String selection = BaseParameters.PARAMETER_ID + " = ?";
+ String[] selectionArgs = {Long.toString(intId)};
+ db.delete(mMediaQualityDbHelper.PICTURE_QUALITY_TABLE_NAME, selection,
+ selectionArgs);
+ mPictureProfileTempIdMap.remove(intId);
+ }
}
@Override
public PictureProfile getPictureProfile(int type, String name, int userId) {
- SQLiteDatabase db = mMediaQualityDbHelper.getReadableDatabase();
-
String selection = BaseParameters.PARAMETER_TYPE + " = ? AND "
+ BaseParameters.PARAMETER_NAME + " = ?";
String[] selectionArguments = {Integer.toString(type), name};
try (
- Cursor cursor = db.query(
+ Cursor cursor = getCursorAfterQuerying(
mMediaQualityDbHelper.PICTURE_QUALITY_TABLE_NAME,
- getAllPictureProfileColumns(),
- selection,
- selectionArguments,
- /*groupBy=*/ null,
- /*having=*/ null,
- /*orderBy=*/ null)
+ getAllMediaProfileColumns(), selection, selectionArguments)
) {
int count = cursor.getCount();
if (count == 0) {
@@ -122,93 +134,19 @@
if (count > 1) {
Log.wtf(TAG, String.format(Locale.US, "%d entries found for type=%d and name=%s"
+ " in %s. Should only ever be 0 or 1.", count, type, name,
- mMediaQualityDbHelper.PICTURE_QUALITY_TABLE_NAME));
+ mMediaQualityDbHelper.PICTURE_QUALITY_TABLE_NAME));
return null;
}
cursor.moveToFirst();
- return getPictureProfileFromCursor(cursor);
+ return getPictureProfileWithTempIdFromCursor(cursor);
}
}
- private String bundleToJson(PersistableBundle 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 PersistableBundle jsonToBundle(String jsonString) {
- JSONObject jsonObject = null;
- PersistableBundle bundle = new PersistableBundle();
-
- 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;
- }
-
- private String[] getAllPictureProfileColumns() {
- return new String[]{
- BaseParameters.PARAMETER_ID,
- BaseParameters.PARAMETER_TYPE,
- BaseParameters.PARAMETER_NAME,
- BaseParameters.PARAMETER_INPUT_ID,
- BaseParameters.PARAMETER_PACKAGE,
- mMediaQualityDbHelper.SETTINGS
- };
- }
-
- private PictureProfile getPictureProfileFromCursor(Cursor cursor) {
- String returnId = cursor.getString(cursor.getColumnIndexOrThrow(
- BaseParameters.PARAMETER_ID));
- int type = cursor.getInt(cursor.getColumnIndexOrThrow(
- BaseParameters.PARAMETER_TYPE));
- String name = cursor.getString(cursor.getColumnIndexOrThrow(
- BaseParameters.PARAMETER_NAME));
- String inputId = cursor.getString(cursor.getColumnIndexOrThrow(
- BaseParameters.PARAMETER_INPUT_ID));
- String packageName = cursor.getString(cursor.getColumnIndexOrThrow(
- BaseParameters.PARAMETER_PACKAGE));
- String settings = cursor.getString(
- cursor.getColumnIndexOrThrow(mMediaQualityDbHelper.SETTINGS));
- return new PictureProfile(returnId, type, name, inputId,
- packageName, jsonToBundle(settings));
- }
-
@Override
public List<PictureProfile> getPictureProfilesByPackage(String packageName, int userId) {
String selection = BaseParameters.PARAMETER_PACKAGE + " = ?";
String[] selectionArguments = {packageName};
- return getPictureProfilesBasedOnConditions(getAllPictureProfileColumns(), selection,
+ return getPictureProfilesBasedOnConditions(getAllMediaProfileColumns(), selection,
selectionArguments);
}
@@ -219,36 +157,15 @@
@Override
public List<String> getPictureProfilePackageNames(int userId) {
- String [] column = {BaseParameters.PARAMETER_NAME};
+ String [] column = {BaseParameters.PARAMETER_PACKAGE};
List<PictureProfile> pictureProfiles = getPictureProfilesBasedOnConditions(column,
null, null);
return pictureProfiles.stream()
- .map(PictureProfile::getName)
+ .map(PictureProfile::getPackageName)
+ .distinct()
.collect(Collectors.toList());
}
- private List<PictureProfile> getPictureProfilesBasedOnConditions(String[] columns,
- String selection, String[] selectionArguments) {
- SQLiteDatabase db = mMediaQualityDbHelper.getReadableDatabase();
-
- try (
- Cursor cursor = db.query(
- mMediaQualityDbHelper.PICTURE_QUALITY_TABLE_NAME,
- columns,
- selection,
- selectionArguments,
- /*groupBy=*/ null,
- /*having=*/ null,
- /*orderBy=*/ null)
- ) {
- List<PictureProfile> pictureProfiles = new ArrayList<>();
- while (cursor.moveToNext()) {
- pictureProfiles.add(getPictureProfileFromCursor(cursor));
- }
- return pictureProfiles;
- }
- }
-
@Override
public PictureProfileHandle getPictureProfileHandle(String id, int userId) {
return null;
@@ -259,13 +176,18 @@
SQLiteDatabase db = mMediaQualityDbHelper.getWritableDatabase();
ContentValues values = new ContentValues();
+ values.put(BaseParameters.PARAMETER_TYPE, sp.getProfileType());
values.put(BaseParameters.PARAMETER_NAME, sp.getName());
values.put(BaseParameters.PARAMETER_PACKAGE, sp.getPackageName());
values.put(BaseParameters.PARAMETER_INPUT_ID, sp.getInputId());
- values.put(mMediaQualityDbHelper.SETTINGS, bundleToJson(sp.getParameters()));
+ values.put(mMediaQualityDbHelper.SETTINGS, persistableBundleToJson(sp.getParameters()));
- long id = db.insert(mMediaQualityDbHelper.SOUND_QUALITY_TABLE_NAME, null, values);
- return new SoundProfile.Builder(sp).setProfileId(Long.toString(id)).build();
+ // id is auto-generated by SQLite upon successful insertion of row
+ Long id = db.insert(mMediaQualityDbHelper.SOUND_QUALITY_TABLE_NAME,
+ null, values);
+ populateTempIdMap(mSoundProfileTempIdMap, id);
+ sp.setProfileId(mSoundProfileTempIdMap.get(id));
+ return sp;
}
@Override
@@ -275,28 +197,27 @@
@Override
public void removeSoundProfile(String id, int userId) {
- SQLiteDatabase db = mMediaQualityDbHelper.getWritableDatabase();
- String selection = BaseParameters.PARAMETER_ID + " = ?";
- String[] selectionArgs = {id};
- db.delete(mMediaQualityDbHelper.SOUND_QUALITY_TABLE_NAME, selection, selectionArgs);
+ Long intId = mSoundProfileTempIdMap.inverse().get(id);
+ if (intId != null) {
+ SQLiteDatabase db = mMediaQualityDbHelper.getWritableDatabase();
+ String selection = BaseParameters.PARAMETER_ID + " = ?";
+ String[] selectionArgs = {Long.toString(intId)};
+ db.delete(mMediaQualityDbHelper.SOUND_QUALITY_TABLE_NAME, selection,
+ selectionArgs);
+ mSoundProfileTempIdMap.remove(intId);
+ }
}
@Override
public SoundProfile getSoundProfile(int type, String id, int userId) {
- SQLiteDatabase db = mMediaQualityDbHelper.getReadableDatabase();
-
- String selection = BaseParameters.PARAMETER_ID + " = ?";
- String[] selectionArguments = {id};
+ String selection = BaseParameters.PARAMETER_TYPE + " = ? AND "
+ + BaseParameters.PARAMETER_NAME + " = ?";
+ String[] selectionArguments = {String.valueOf(type), id};
try (
- Cursor cursor = db.query(
+ Cursor cursor = getCursorAfterQuerying(
mMediaQualityDbHelper.SOUND_QUALITY_TABLE_NAME,
- getAllSoundProfileColumns(),
- selection,
- selectionArguments,
- /*groupBy=*/ null,
- /*having=*/ null,
- /*orderBy=*/ null)
+ getAllMediaProfileColumns(), selection, selectionArguments)
) {
int count = cursor.getCount();
if (count == 0) {
@@ -309,7 +230,7 @@
return null;
}
cursor.moveToFirst();
- return getSoundProfileFromCursor(cursor);
+ return getSoundProfileWithTempIdFromCursor(cursor);
}
}
@@ -317,7 +238,7 @@
public List<SoundProfile> getSoundProfilesByPackage(String packageName, int userId) {
String selection = BaseParameters.PARAMETER_PACKAGE + " = ?";
String[] selectionArguments = {packageName};
- return getSoundProfilesBasedOnConditions(getAllSoundProfileColumns(), selection,
+ return getSoundProfilesBasedOnConditions(getAllMediaProfileColumns(), selection,
selectionArguments);
}
@@ -332,13 +253,79 @@
List<SoundProfile> soundProfiles = getSoundProfilesBasedOnConditions(column,
null, null);
return soundProfiles.stream()
- .map(SoundProfile::getName)
+ .map(SoundProfile::getPackageName)
+ .distinct()
.collect(Collectors.toList());
}
- private String[] getAllSoundProfileColumns() {
+ private void populateTempIdMap(BiMap<Long, String> map, Long id) {
+ if (id != null && map.get(id) == null) {
+ String uuid = UUID.randomUUID().toString();
+ while (map.inverse().containsKey(uuid)) {
+ uuid = UUID.randomUUID().toString();
+ }
+ map.put(id, uuid);
+ }
+ }
+
+ private String persistableBundleToJson(PersistableBundle bundle) {
+ JSONObject json = new JSONObject();
+ for (String key : bundle.keySet()) {
+ Object value = bundle.get(key);
+ try {
+ if (value instanceof String) {
+ json.put(key, bundle.getString(key));
+ } else if (value instanceof Integer) {
+ json.put(key, bundle.getInt(key));
+ } else if (value instanceof Long) {
+ json.put(key, bundle.getLong(key));
+ } else if (value instanceof Boolean) {
+ json.put(key, bundle.getBoolean(key));
+ } else if (value instanceof Double) {
+ json.put(key, bundle.getDouble(key));
+ }
+ } catch (JSONException e) {
+ Log.e(TAG, "Unable to serialize ", e);
+ }
+ }
+ return json.toString();
+ }
+
+ private PersistableBundle jsonToBundle(String jsonString) {
+ PersistableBundle bundle = new PersistableBundle();
+ if (jsonString != null) {
+ JSONObject jsonObject = null;
+ 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;
+ }
+
+ private String[] getAllMediaProfileColumns() {
return new String[]{
BaseParameters.PARAMETER_ID,
+ BaseParameters.PARAMETER_TYPE,
BaseParameters.PARAMETER_NAME,
BaseParameters.PARAMETER_INPUT_ID,
BaseParameters.PARAMETER_PACKAGE,
@@ -346,40 +333,92 @@
};
}
- private SoundProfile getSoundProfileFromCursor(Cursor cursor) {
- String returnId = cursor.getString(
- cursor.getColumnIndexOrThrow(BaseParameters.PARAMETER_ID));
- int type = cursor.getInt(
- cursor.getColumnIndexOrThrow(BaseParameters.PARAMETER_TYPE));
- String name = cursor.getString(
- cursor.getColumnIndexOrThrow(BaseParameters.PARAMETER_NAME));
- String inputId = cursor.getString(
- cursor.getColumnIndexOrThrow(BaseParameters.PARAMETER_INPUT_ID));
- String packageName = cursor.getString(
- cursor.getColumnIndexOrThrow(BaseParameters.PARAMETER_PACKAGE));
- String settings = cursor.getString(
- cursor.getColumnIndexOrThrow(mMediaQualityDbHelper.SETTINGS));
- return new SoundProfile(returnId, type, name, inputId, packageName,
- jsonToBundle(settings));
+ private PictureProfile getPictureProfileWithTempIdFromCursor(Cursor cursor) {
+ return new PictureProfile(
+ getTempId(mPictureProfileTempIdMap, cursor),
+ getType(cursor),
+ getName(cursor),
+ getInputId(cursor),
+ getPackageName(cursor),
+ jsonToBundle(getSettingsString(cursor))
+ );
+ }
+
+ private SoundProfile getSoundProfileWithTempIdFromCursor(Cursor cursor) {
+ return new SoundProfile(
+ getTempId(mSoundProfileTempIdMap, cursor),
+ getType(cursor),
+ getName(cursor),
+ getInputId(cursor),
+ getPackageName(cursor),
+ jsonToBundle(getSettingsString(cursor))
+ );
+ }
+
+ private String getTempId(BiMap<Long, String> map, Cursor cursor) {
+ int colIndex = cursor.getColumnIndex(BaseParameters.PARAMETER_ID);
+ Long dbId = colIndex != -1 ? cursor.getLong(colIndex) : null;
+ populateTempIdMap(map, dbId);
+ return map.get(dbId);
+ }
+
+ private int getType(Cursor cursor) {
+ int colIndex = cursor.getColumnIndex(BaseParameters.PARAMETER_TYPE);
+ return colIndex != -1 ? cursor.getInt(colIndex) : 0;
+ }
+
+ private String getName(Cursor cursor) {
+ int colIndex = cursor.getColumnIndex(BaseParameters.PARAMETER_NAME);
+ return colIndex != -1 ? cursor.getString(colIndex) : null;
+ }
+
+ private String getInputId(Cursor cursor) {
+ int colIndex = cursor.getColumnIndex(BaseParameters.PARAMETER_INPUT_ID);
+ return colIndex != -1 ? cursor.getString(colIndex) : null;
+ }
+
+ private String getPackageName(Cursor cursor) {
+ int colIndex = cursor.getColumnIndex(BaseParameters.PARAMETER_PACKAGE);
+ return colIndex != -1 ? cursor.getString(colIndex) : null;
+ }
+
+ private String getSettingsString(Cursor cursor) {
+ int colIndex = cursor.getColumnIndex(mMediaQualityDbHelper.SETTINGS);
+ return colIndex != -1 ? cursor.getString(colIndex) : null;
+ }
+
+ private Cursor getCursorAfterQuerying(String table, String[] columns, String selection,
+ String[] selectionArgs) {
+ SQLiteDatabase db = mMediaQualityDbHelper.getReadableDatabase();
+ return db.query(table, columns, selection, selectionArgs,
+ /*groupBy=*/ null, /*having=*/ null, /*orderBy=*/ null);
+ }
+
+ private List<PictureProfile> getPictureProfilesBasedOnConditions(String[] columns,
+ String selection, String[] selectionArguments) {
+ try (
+ Cursor cursor = getCursorAfterQuerying(
+ mMediaQualityDbHelper.PICTURE_QUALITY_TABLE_NAME, columns, selection,
+ selectionArguments)
+ ) {
+ List<PictureProfile> pictureProfiles = new ArrayList<>();
+ while (cursor.moveToNext()) {
+ pictureProfiles.add(getPictureProfileWithTempIdFromCursor(cursor));
+ }
+ return pictureProfiles;
+ }
}
private List<SoundProfile> getSoundProfilesBasedOnConditions(String[] columns,
String selection, String[] selectionArguments) {
- SQLiteDatabase db = mMediaQualityDbHelper.getReadableDatabase();
-
try (
- Cursor cursor = db.query(
- mMediaQualityDbHelper.SOUND_QUALITY_TABLE_NAME,
- columns,
- selection,
- selectionArguments,
- /*groupBy=*/ null,
- /*having=*/ null,
- /*orderBy=*/ null)
+ Cursor cursor = getCursorAfterQuerying(
+ mMediaQualityDbHelper.SOUND_QUALITY_TABLE_NAME, columns, selection,
+ selectionArguments)
) {
List<SoundProfile> soundProfiles = new ArrayList<>();
while (cursor.moveToNext()) {
- soundProfiles.add(getSoundProfileFromCursor(cursor));
+ soundProfiles.add(getSoundProfileWithTempIdFromCursor(cursor));
}
return soundProfiles;
}