Home | History | Annotate | Download | only in tuner
      1 /*
      2  * Copyright (C) 2015 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.tv.tuner;
     18 
     19 import android.content.ContentResolver;
     20 import android.content.ContentValues;
     21 import android.content.Context;
     22 import android.content.SharedPreferences;
     23 import android.database.ContentObserver;
     24 import android.database.Cursor;
     25 import android.os.AsyncTask;
     26 import android.os.Bundle;
     27 import android.os.Handler;
     28 import android.support.annotation.MainThread;
     29 
     30 import com.android.tv.common.SoftPreconditions;
     31 import com.android.tv.tuner.TunerPreferenceProvider.Preferences;
     32 import com.android.tv.tuner.util.TisConfiguration;
     33 
     34 /**
     35  * A helper class for the USB tuner preferences.
     36  */
     37 public class TunerPreferences {
     38     private static final String TAG = "TunerPreferences";
     39 
     40     private static final String PREFS_KEY_CHANNEL_DATA_VERSION = "channel_data_version";
     41     private static final String PREFS_KEY_SCANNED_CHANNEL_COUNT = "scanned_channel_count";
     42     private static final String PREFS_KEY_SCAN_DONE = "scan_done";
     43     private static final String PREFS_KEY_LAUNCH_SETUP = "launch_setup";
     44     private static final String PREFS_KEY_STORE_TS_STREAM = "store_ts_stream";
     45 
     46     private static final String SHARED_PREFS_NAME = "com.android.tv.tuner.preferences";
     47 
     48     public static final int CHANNEL_DATA_VERSION_NOT_SET = -1;
     49 
     50     private static final Bundle sPreferenceValues = new Bundle();
     51     private static LoadPreferencesTask sLoadPreferencesTask;
     52     private static ContentObserver sContentObserver;
     53 
     54     private static boolean sInitialized;
     55 
     56     /**
     57      * Initializes the USB tuner preferences.
     58      */
     59     @MainThread
     60     public static void initialize(final Context context) {
     61         if (sInitialized) {
     62             return;
     63         }
     64         sInitialized = true;
     65         if (useContentProvider(context)) {
     66             loadPreferences(context);
     67             sContentObserver = new ContentObserver(new Handler()) {
     68                 @Override
     69                 public void onChange(boolean selfChange) {
     70                     loadPreferences(context);
     71                 }
     72             };
     73             context.getContentResolver().registerContentObserver(
     74                     TunerPreferenceProvider.Preferences.CONTENT_URI, true, sContentObserver);
     75         } else {
     76             new AsyncTask<Void, Void, Void>() {
     77                 @Override
     78                 protected Void doInBackground(Void... params) {
     79                     getSharedPreferences(context);
     80                     return null;
     81                 }
     82             }.execute();
     83         }
     84     }
     85 
     86     /**
     87      * Releases the resources.
     88      */
     89     @MainThread
     90     public static void release(Context context) {
     91         if (useContentProvider(context) && sContentObserver != null) {
     92             context.getContentResolver().unregisterContentObserver(sContentObserver);
     93         }
     94     }
     95 
     96     /**
     97      * Loads the preferences from database.
     98      * <p>
     99      * This preferences is used across processes, so the preferences should be loaded again when the
    100      * databases changes.
    101      */
    102     public static synchronized void loadPreferences(Context context) {
    103         if (sLoadPreferencesTask != null
    104                 && sLoadPreferencesTask.getStatus() != AsyncTask.Status.FINISHED) {
    105             sLoadPreferencesTask.cancel(true);
    106         }
    107         sLoadPreferencesTask = new LoadPreferencesTask(context);
    108         sLoadPreferencesTask.execute();
    109     }
    110 
    111     private static boolean useContentProvider(Context context) {
    112         // If TIS is a part of LC, it should use ContentProvider to resolve multiple process access.
    113         return TisConfiguration.isPackagedWithLiveChannels(context);
    114     }
    115 
    116     @MainThread
    117     public static int getChannelDataVersion(Context context) {
    118         SoftPreconditions.checkState(sInitialized);
    119         if (useContentProvider(context)) {
    120             return sPreferenceValues.getInt(PREFS_KEY_CHANNEL_DATA_VERSION,
    121                     CHANNEL_DATA_VERSION_NOT_SET);
    122         } else {
    123             return getSharedPreferences(context)
    124                     .getInt(TunerPreferences.PREFS_KEY_CHANNEL_DATA_VERSION,
    125                             CHANNEL_DATA_VERSION_NOT_SET);
    126         }
    127     }
    128 
    129     @MainThread
    130     public static void setChannelDataVersion(Context context, int version) {
    131         if (useContentProvider(context)) {
    132             setPreference(context, PREFS_KEY_CHANNEL_DATA_VERSION, version);
    133         } else {
    134             getSharedPreferences(context).edit()
    135                     .putInt(TunerPreferences.PREFS_KEY_CHANNEL_DATA_VERSION, version)
    136                     .apply();
    137         }
    138     }
    139 
    140     @MainThread
    141     public static int getScannedChannelCount(Context context) {
    142         SoftPreconditions.checkState(sInitialized);
    143         if (useContentProvider(context)) {
    144             return sPreferenceValues.getInt(PREFS_KEY_SCANNED_CHANNEL_COUNT);
    145         } else {
    146             return getSharedPreferences(context)
    147                     .getInt(TunerPreferences.PREFS_KEY_SCANNED_CHANNEL_COUNT, 0);
    148         }
    149     }
    150 
    151     @MainThread
    152     public static void setScannedChannelCount(Context context, int channelCount) {
    153         if (useContentProvider(context)) {
    154             setPreference(context, PREFS_KEY_SCANNED_CHANNEL_COUNT, channelCount);
    155         } else {
    156             getSharedPreferences(context).edit()
    157                     .putInt(TunerPreferences.PREFS_KEY_SCANNED_CHANNEL_COUNT, channelCount)
    158                     .apply();
    159         }
    160     }
    161 
    162     @MainThread
    163     public static boolean isScanDone(Context context) {
    164         SoftPreconditions.checkState(sInitialized);
    165         if (useContentProvider(context)) {
    166             return sPreferenceValues.getBoolean(PREFS_KEY_SCAN_DONE);
    167         } else {
    168             return getSharedPreferences(context)
    169                     .getBoolean(TunerPreferences.PREFS_KEY_SCAN_DONE, false);
    170         }
    171     }
    172 
    173     @MainThread
    174     public static void setScanDone(Context context) {
    175         if (useContentProvider(context)) {
    176             setPreference(context, PREFS_KEY_SCAN_DONE, true);
    177         } else {
    178             getSharedPreferences(context).edit()
    179                     .putBoolean(TunerPreferences.PREFS_KEY_SCAN_DONE, true)
    180                     .apply();
    181         }
    182     }
    183 
    184     @MainThread
    185     public static boolean shouldShowSetupActivity(Context context) {
    186         SoftPreconditions.checkState(sInitialized);
    187         if (useContentProvider(context)) {
    188             return sPreferenceValues.getBoolean(PREFS_KEY_LAUNCH_SETUP);
    189         } else {
    190             return getSharedPreferences(context)
    191                     .getBoolean(TunerPreferences.PREFS_KEY_LAUNCH_SETUP, false);
    192         }
    193     }
    194 
    195     @MainThread
    196     public static void setShouldShowSetupActivity(Context context, boolean need) {
    197         if (useContentProvider(context)) {
    198             setPreference(context, PREFS_KEY_LAUNCH_SETUP, need);
    199         } else {
    200             getSharedPreferences(context).edit()
    201                     .putBoolean(TunerPreferences.PREFS_KEY_LAUNCH_SETUP, need)
    202                     .apply();
    203         }
    204     }
    205 
    206     @MainThread
    207     public static boolean getStoreTsStream(Context context) {
    208         SoftPreconditions.checkState(sInitialized);
    209         if (useContentProvider(context)) {
    210             return sPreferenceValues.getBoolean(PREFS_KEY_STORE_TS_STREAM, false);
    211         } else {
    212             return getSharedPreferences(context)
    213                     .getBoolean(TunerPreferences.PREFS_KEY_STORE_TS_STREAM, false);
    214         }
    215     }
    216 
    217     @MainThread
    218     public static void setStoreTsStream(Context context, boolean shouldStore) {
    219         if (useContentProvider(context)) {
    220             setPreference(context, PREFS_KEY_STORE_TS_STREAM, shouldStore);
    221         } else {
    222             getSharedPreferences(context).edit()
    223                     .putBoolean(TunerPreferences.PREFS_KEY_STORE_TS_STREAM, shouldStore)
    224                     .apply();
    225         }
    226     }
    227 
    228     private static SharedPreferences getSharedPreferences(Context context) {
    229         return context.getSharedPreferences(SHARED_PREFS_NAME, Context.MODE_PRIVATE);
    230     }
    231 
    232     @MainThread
    233     private static void setPreference(final Context context, final String key, final String value) {
    234         new AsyncTask<Void, Void, Void>() {
    235             @Override
    236             protected Void doInBackground(Void... params) {
    237                 ContentResolver resolver = context.getContentResolver();
    238                 ContentValues values = new ContentValues();
    239                 values.put(Preferences.COLUMN_KEY, key);
    240                 values.put(Preferences.COLUMN_VALUE, value);
    241                 try {
    242                     resolver.insert(Preferences.CONTENT_URI, values);
    243                 } catch (Exception e) {
    244                     SoftPreconditions.warn(TAG, "setPreference", "Error writing preference values",
    245                             e);
    246                 }
    247                 return null;
    248             }
    249         }.execute();
    250     }
    251 
    252     @MainThread
    253     private static void setPreference(Context context, String key, int value) {
    254         sPreferenceValues.putInt(key, value);
    255         setPreference(context, key, Integer.toString(value));
    256     }
    257 
    258     @MainThread
    259     private static void setPreference(Context context, String key, boolean value) {
    260         sPreferenceValues.putBoolean(key, value);
    261         setPreference(context, key, Boolean.toString(value));
    262     }
    263 
    264     private static class LoadPreferencesTask extends AsyncTask<Void, Void, Bundle> {
    265         private final Context mContext;
    266         private LoadPreferencesTask(Context context) {
    267             mContext = context;
    268         }
    269 
    270         @Override
    271         protected Bundle doInBackground(Void... params) {
    272             Bundle bundle = new Bundle();
    273             ContentResolver resolver = mContext.getContentResolver();
    274             String[] projection = new String[] { Preferences.COLUMN_KEY, Preferences.COLUMN_VALUE };
    275             try (Cursor cursor = resolver.query(Preferences.CONTENT_URI, projection, null, null,
    276                     null)) {
    277                 if (cursor != null) {
    278                     while (!isCancelled() && cursor.moveToNext()) {
    279                         String key = cursor.getString(0);
    280                         String value = cursor.getString(1);
    281                         switch (key) {
    282                             case PREFS_KEY_CHANNEL_DATA_VERSION:
    283                             case PREFS_KEY_SCANNED_CHANNEL_COUNT:
    284                                 try {
    285                                     bundle.putInt(key, Integer.parseInt(value));
    286                                 } catch (NumberFormatException e) {
    287                                     // Does nothing.
    288                                 }
    289                                 break;
    290                             case PREFS_KEY_SCAN_DONE:
    291                             case PREFS_KEY_LAUNCH_SETUP:
    292                             case PREFS_KEY_STORE_TS_STREAM:
    293                                 bundle.putBoolean(key, Boolean.parseBoolean(value));
    294                                 break;
    295                         }
    296                     }
    297                 }
    298             } catch (Exception e) {
    299                 SoftPreconditions.warn(TAG, "getPreference", "Error querying preference values", e);
    300                 return null;
    301             }
    302             return bundle;
    303         }
    304 
    305         @Override
    306         protected void onPostExecute(Bundle bundle) {
    307             sPreferenceValues.putAll(bundle);
    308         }
    309     }
    310 }
    311