Initialize projection maps in a class synchronized method for thread safety. am: fc137b105f
am: 0f7d31578c

Change-Id: I2a025c6d880f9db1544328caaaadbb504173212f
diff --git a/src/com/android/providers/tv/TvProvider.java b/src/com/android/providers/tv/TvProvider.java
index ff2452e..6968196 100644
--- a/src/com/android/providers/tv/TvProvider.java
+++ b/src/com/android/providers/tv/TvProvider.java
@@ -970,38 +970,9 @@
 
         @Override
         public void onOpen(SQLiteDatabase db) {
-            // 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) {
-            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,
-                Map<String, String> projectionMap) {
-            try(Cursor cursor = db.rawQuery("SELECT * FROM " + tableName + " LIMIT 0", null)) {
-                for (String columnName : cursor.getColumnNames()) {
-                    if (!projectionMap.containsKey(columnName)) {
-                        projectionMap.put(columnName, tableName + '.' + columnName);
-                    }
-                }
-            }
+            // Call a static method on the TvProvider because changes to sInitialized must
+            // be guarded by a lock on the class.
+            initOnOpenIfNeeded(mContext, db);
         }
 
         private static void migrateIntegerColumnToTextColumn(SQLiteDatabase db, String table,
@@ -1596,6 +1567,36 @@
         }
     }
 
+    private static synchronized void initOnOpenIfNeeded(Context context, SQLiteDatabase db) {
+        if (!sInitialized) {
+            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);
+            sBlockedPackagesSharedPreference = PreferenceManager.getDefaultSharedPreferences(
+                    context);
+            sBlockedPackages = new ConcurrentHashMap<>();
+            for (String packageName : sBlockedPackagesSharedPreference.getStringSet(
+                    SHARED_PREF_BLOCKED_PACKAGES_KEY, new HashSet<>())) {
+                sBlockedPackages.put(packageName, true);
+            }
+            sInitialized = true;
+        }
+    }
+
+    private static void updateProjectionMap(SQLiteDatabase db, String tableName,
+            Map<String, String> projectionMap) {
+        try(Cursor cursor = db.rawQuery("SELECT * FROM " + tableName + " LIMIT 0", null)) {
+            for (String columnName : cursor.getColumnNames()) {
+                if (!projectionMap.containsKey(columnName)) {
+                    projectionMap.put(columnName, tableName + '.' + columnName);
+                }
+            }
+        }
+    }
+
     private Map<String, String> createProjectionMapForQuery(String[] projection,
             Map<String, String> projectionMap) {
         if (projection == null) {