diff options
author | Conrad Chen <conradchen@google.com> | 2017-05-08 14:13:40 -0700 |
---|---|---|
committer | Conrad Chen <conradchen@google.com> | 2017-05-11 14:28:07 -0700 |
commit | 3106a2deefc84c565eef6d6df50e7c359c3e4fe4 (patch) | |
tree | 5106e659c17188034fd31cd3d96a3e755cb85d44 | |
parent | fd09753145ae5af960e177e21857b224ea331048 (diff) | |
download | TvProvider-3106a2deefc84c565eef6d6df50e7c359c3e4fe4.tar.gz |
Fix bugs in TvProvider
Project maps and blocked packages are updated/loaded when DB is opened.
It may cause inconsistency or NPE if we check projection maps or blocked
packages before any actual DB operations are done.
Test: gts-tradefed run gts -m GtsTvTestCases
Bug: 37944095
Change-Id: I2444ea80d2123cebddeb05a56a91ced4b7a54290
-rw-r--r-- | src/com/android/providers/tv/TvProvider.java | 51 |
1 files changed, 29 insertions, 22 deletions
diff --git a/src/com/android/providers/tv/TvProvider.java b/src/com/android/providers/tv/TvProvider.java index ceb864c..0a4577f 100644 --- a/src/com/android/providers/tv/TvProvider.java +++ b/src/com/android/providers/tv/TvProvider.java @@ -147,7 +147,7 @@ public class TvProvider extends ContentProvider { private static final Map<String, String> sRecordedProgramProjectionMap; private static final Map<String, String> sPreviewProgramProjectionMap; private static final Map<String, String> sWatchNextProgramProjectionMap; - private static boolean sProjectionMapsUpdated; + private static boolean sInitialized; static { sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH); @@ -970,26 +970,27 @@ public class TvProvider extends ContentProvider { @Override public void onOpen(SQLiteDatabase db) { - buildProjectionMap(db); - sBlockedPackagesSharedPreference = PreferenceManager.getDefaultSharedPreferences( - mContext); - sBlockedPackages = new ConcurrentHashMap<>(); - for (String packageName : sBlockedPackagesSharedPreference.getStringSet( - SHARED_PREF_BLOCKED_PACKAGES_KEY, new HashSet<>())) { - sBlockedPackages.put(packageName, true); + // This method is thread-safe. It's guaranteed by the implementation of SQLiteOpenHelper + if (!sInitialized) { + buildProjectionMap(db); + sBlockedPackagesSharedPreference = PreferenceManager.getDefaultSharedPreferences( + mContext); + sBlockedPackages = new ConcurrentHashMap<>(); + for (String packageName : sBlockedPackagesSharedPreference.getStringSet( + SHARED_PREF_BLOCKED_PACKAGES_KEY, new HashSet<>())) { + sBlockedPackages.put(packageName, true); + } + sInitialized = true; } } private void buildProjectionMap(SQLiteDatabase db) { - if (!sProjectionMapsUpdated) { - updateProjectionMap(db, CHANNELS_TABLE, sChannelProjectionMap); - updateProjectionMap(db, PROGRAMS_TABLE, sProgramProjectionMap); - updateProjectionMap(db, WATCHED_PROGRAMS_TABLE, sWatchedProgramProjectionMap); - updateProjectionMap(db, RECORDED_PROGRAMS_TABLE, sRecordedProgramProjectionMap); - updateProjectionMap(db, PREVIEW_PROGRAMS_TABLE, sPreviewProgramProjectionMap); - updateProjectionMap(db, WATCH_NEXT_PROGRAMS_TABLE, sWatchNextProgramProjectionMap); - sProjectionMapsUpdated = true; - } + updateProjectionMap(db, CHANNELS_TABLE, sChannelProjectionMap); + updateProjectionMap(db, PROGRAMS_TABLE, sProgramProjectionMap); + updateProjectionMap(db, WATCHED_PROGRAMS_TABLE, sWatchedProgramProjectionMap); + updateProjectionMap(db, RECORDED_PROGRAMS_TABLE, sRecordedProgramProjectionMap); + updateProjectionMap(db, PREVIEW_PROGRAMS_TABLE, sPreviewProgramProjectionMap); + updateProjectionMap(db, WATCH_NEXT_PROGRAMS_TABLE, sWatchNextProgramProjectionMap); } private void updateProjectionMap(SQLiteDatabase db, String tableName, @@ -1129,11 +1130,7 @@ public class TvProvider extends ContentProvider { if (!callerHasAccessAllEpgDataPermission()) { return null; } - if (!sProjectionMapsUpdated) { - // Database is not accessed before and the projection maps are not updated yet. - // Gets database here to make it initialized. - mOpenHelper.getReadableDatabase().close(); - } + ensureInitialized(); Map<String, String> projectionMap; switch (method) { case TvContract.METHOD_GET_COLUMNS: @@ -1273,6 +1270,7 @@ public class TvProvider extends ContentProvider { @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { + ensureInitialized(); mTransientRowHelper.ensureOldTransientRowsDeleted(); boolean needsToValidateSortOrder = !callerHasAccessAllEpgDataPermission(); SqlParams params = createSqlParams(OP_QUERY, uri, selection, selectionArgs); @@ -1326,6 +1324,7 @@ public class TvProvider extends ContentProvider { @Override public Uri insert(Uri uri, ContentValues values) { + ensureInitialized(); mTransientRowHelper.ensureOldTransientRowsDeleted(); switch (sUriMatcher.match(uri)) { case MATCH_CHANNEL: @@ -1585,6 +1584,14 @@ public class TvProvider extends ContentProvider { return count; } + private synchronized void ensureInitialized() { + if (!sInitialized) { + // Database is not accessed before and the projection maps and the blocked package list + // are not updated yet. Gets database here to make it initialized. + mOpenHelper.getReadableDatabase().close(); + } + } + private Map<String, String> createProjectionMapForQuery(String[] projection, Map<String, String> projectionMap) { if (projection == null) { |