aboutsummaryrefslogtreecommitdiff
path: root/common/src/com/android/tv/common/CommonPreferences.java
diff options
context:
space:
mode:
Diffstat (limited to 'common/src/com/android/tv/common/CommonPreferences.java')
-rw-r--r--common/src/com/android/tv/common/CommonPreferences.java332
1 files changed, 332 insertions, 0 deletions
diff --git a/common/src/com/android/tv/common/CommonPreferences.java b/common/src/com/android/tv/common/CommonPreferences.java
new file mode 100644
index 00000000..5a94eecb
--- /dev/null
+++ b/common/src/com/android/tv/common/CommonPreferences.java
@@ -0,0 +1,332 @@
+/*
+ * Copyright (C) 2017 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.tv.common;
+
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.database.ContentObserver;
+import android.database.Cursor;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.os.Handler;
+import android.support.annotation.GuardedBy;
+import android.support.annotation.IntDef;
+import android.support.annotation.MainThread;
+import android.util.Log;
+import com.android.tv.common.CommonPreferenceProvider.Preferences;
+import com.android.tv.common.util.CommonUtils;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.HashMap;
+import java.util.Map;
+
+/** A helper class for setting/getting common preferences across applications. */
+public class CommonPreferences {
+ private static final String TAG = "CommonPreferences";
+
+ private static final String PREFS_KEY_LAUNCH_SETUP = "launch_setup";
+ private static final String PREFS_KEY_STORE_TS_STREAM = "store_ts_stream";
+ private static final String PREFS_KEY_TRICKPLAY_SETTING = "trickplay_setting";
+ private static final String PREFS_KEY_LAST_POSTAL_CODE = "last_postal_code";
+
+ private static final Map<String, Class> sPref2TypeMapping = new HashMap<>();
+
+ static {
+ sPref2TypeMapping.put(PREFS_KEY_TRICKPLAY_SETTING, int.class);
+ sPref2TypeMapping.put(PREFS_KEY_STORE_TS_STREAM, boolean.class);
+ sPref2TypeMapping.put(PREFS_KEY_LAUNCH_SETUP, boolean.class);
+ sPref2TypeMapping.put(PREFS_KEY_LAST_POSTAL_CODE, String.class);
+ }
+
+ private static final String SHARED_PREFS_NAME =
+ CommonConstants.BASE_PACKAGE + ".common.preferences";
+
+ @IntDef({TRICKPLAY_SETTING_NOT_SET, TRICKPLAY_SETTING_DISABLED, TRICKPLAY_SETTING_ENABLED})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface TrickplaySetting {}
+
+ /** Trickplay setting is not changed by a user. Trickplay will be enabled in this case. */
+ public static final int TRICKPLAY_SETTING_NOT_SET = -1;
+
+ /** Trickplay setting is disabled. */
+ public static final int TRICKPLAY_SETTING_DISABLED = 0;
+
+ /** Trickplay setting is enabled. */
+ public static final int TRICKPLAY_SETTING_ENABLED = 1;
+
+ @GuardedBy("CommonPreferences.class")
+ private static final Bundle sPreferenceValues = new Bundle();
+
+ private static LoadPreferencesTask sLoadPreferencesTask;
+ private static ContentObserver sContentObserver;
+ private static CommonPreferencesChangedListener sPreferencesChangedListener = null;
+
+ protected static boolean sInitialized;
+
+ /** Listeners for CommonPreferences change. */
+ public interface CommonPreferencesChangedListener {
+ void onCommonPreferencesChanged();
+ }
+
+ /** Initializes the common preferences. */
+ @MainThread
+ public static void initialize(final Context context) {
+ if (sInitialized) {
+ return;
+ }
+ sInitialized = true;
+ if (useContentProvider(context)) {
+ loadPreferences(context);
+ sContentObserver =
+ new ContentObserver(new Handler()) {
+ @Override
+ public void onChange(boolean selfChange) {
+ loadPreferences(context);
+ }
+ };
+ context.getContentResolver()
+ .registerContentObserver(Preferences.CONTENT_URI, true, sContentObserver);
+ } else {
+ new AsyncTask<Void, Void, Void>() {
+ @Override
+ protected Void doInBackground(Void... params) {
+ getSharedPreferences(context);
+ return null;
+ }
+ }.execute();
+ }
+ }
+
+ /** Releases the resources. */
+ public static synchronized void release(Context context) {
+ if (useContentProvider(context) && sContentObserver != null) {
+ context.getContentResolver().unregisterContentObserver(sContentObserver);
+ }
+ setCommonPreferencesChangedListener(null);
+ }
+
+ /** Sets the listener for CommonPreferences change. */
+ public static void setCommonPreferencesChangedListener(
+ CommonPreferencesChangedListener listener) {
+ sPreferencesChangedListener = listener;
+ }
+
+ /**
+ * Loads the preferences from database.
+ *
+ * <p>This preferences is used across processes, so the preferences should be loaded again when
+ * the databases changes.
+ */
+ @MainThread
+ public static void loadPreferences(Context context) {
+ if (sLoadPreferencesTask != null
+ && sLoadPreferencesTask.getStatus() != AsyncTask.Status.FINISHED) {
+ sLoadPreferencesTask.cancel(true);
+ }
+ sLoadPreferencesTask = new LoadPreferencesTask(context);
+ sLoadPreferencesTask.execute();
+ }
+
+ private static boolean useContentProvider(Context context) {
+ // If TIS is a part of LC, it should use ContentProvider to resolve multiple process access.
+ return CommonUtils.isPackagedWithLiveChannels(context);
+ }
+
+ public static synchronized boolean shouldShowSetupActivity(Context context) {
+ SoftPreconditions.checkState(sInitialized);
+ if (useContentProvider(context)) {
+ return sPreferenceValues.getBoolean(PREFS_KEY_LAUNCH_SETUP);
+ } else {
+ return getSharedPreferences(context).getBoolean(PREFS_KEY_LAUNCH_SETUP, false);
+ }
+ }
+
+ public static synchronized void setShouldShowSetupActivity(Context context, boolean need) {
+ if (useContentProvider(context)) {
+ setPreference(context, PREFS_KEY_LAUNCH_SETUP, need);
+ } else {
+ getSharedPreferences(context).edit().putBoolean(PREFS_KEY_LAUNCH_SETUP, need).apply();
+ }
+ }
+
+ public static synchronized @TrickplaySetting int getTrickplaySetting(Context context) {
+ SoftPreconditions.checkState(sInitialized);
+ if (useContentProvider(context)) {
+ return sPreferenceValues.getInt(PREFS_KEY_TRICKPLAY_SETTING, TRICKPLAY_SETTING_NOT_SET);
+ } else {
+ return getSharedPreferences(context)
+ .getInt(PREFS_KEY_TRICKPLAY_SETTING, TRICKPLAY_SETTING_NOT_SET);
+ }
+ }
+
+ public static synchronized void setTrickplaySetting(
+ Context context, @TrickplaySetting int trickplaySetting) {
+ SoftPreconditions.checkState(sInitialized);
+ SoftPreconditions.checkArgument(trickplaySetting != TRICKPLAY_SETTING_NOT_SET);
+ if (useContentProvider(context)) {
+ setPreference(context, PREFS_KEY_TRICKPLAY_SETTING, trickplaySetting);
+ } else {
+ getSharedPreferences(context)
+ .edit()
+ .putInt(PREFS_KEY_TRICKPLAY_SETTING, trickplaySetting)
+ .apply();
+ }
+ }
+
+ public static synchronized boolean getStoreTsStream(Context context) {
+ SoftPreconditions.checkState(sInitialized);
+ if (useContentProvider(context)) {
+ return sPreferenceValues.getBoolean(PREFS_KEY_STORE_TS_STREAM, false);
+ } else {
+ return getSharedPreferences(context).getBoolean(PREFS_KEY_STORE_TS_STREAM, false);
+ }
+ }
+
+ public static synchronized void setStoreTsStream(Context context, boolean shouldStore) {
+ if (useContentProvider(context)) {
+ setPreference(context, PREFS_KEY_STORE_TS_STREAM, shouldStore);
+ } else {
+ getSharedPreferences(context)
+ .edit()
+ .putBoolean(PREFS_KEY_STORE_TS_STREAM, shouldStore)
+ .apply();
+ }
+ }
+
+ public static synchronized String getLastPostalCode(Context context) {
+ SoftPreconditions.checkState(sInitialized);
+ if (useContentProvider(context)) {
+ return sPreferenceValues.getString(PREFS_KEY_LAST_POSTAL_CODE);
+ } else {
+ return getSharedPreferences(context).getString(PREFS_KEY_LAST_POSTAL_CODE, null);
+ }
+ }
+
+ public static synchronized void setLastPostalCode(Context context, String postalCode) {
+ if (useContentProvider(context)) {
+ setPreference(context, PREFS_KEY_LAST_POSTAL_CODE, postalCode);
+ } else {
+ getSharedPreferences(context)
+ .edit()
+ .putString(PREFS_KEY_LAST_POSTAL_CODE, postalCode)
+ .apply();
+ }
+ }
+
+ protected static SharedPreferences getSharedPreferences(Context context) {
+ return context.getSharedPreferences(SHARED_PREFS_NAME, Context.MODE_PRIVATE);
+ }
+
+ private static synchronized void setPreference(Context context, String key, String value) {
+ sPreferenceValues.putString(key, value);
+ savePreference(context, key, value);
+ }
+
+ private static synchronized void setPreference(Context context, String key, int value) {
+ sPreferenceValues.putInt(key, value);
+ savePreference(context, key, Integer.toString(value));
+ }
+
+ private static synchronized void setPreference(Context context, String key, long value) {
+ sPreferenceValues.putLong(key, value);
+ savePreference(context, key, Long.toString(value));
+ }
+
+ private static synchronized void setPreference(Context context, String key, boolean value) {
+ sPreferenceValues.putBoolean(key, value);
+ savePreference(context, key, Boolean.toString(value));
+ }
+
+ private static void savePreference(
+ final Context context, final String key, final String value) {
+ new AsyncTask<Void, Void, Void>() {
+ @Override
+ protected Void doInBackground(Void... params) {
+ ContentResolver resolver = context.getContentResolver();
+ ContentValues values = new ContentValues();
+ values.put(Preferences.COLUMN_KEY, key);
+ values.put(Preferences.COLUMN_VALUE, value);
+ try {
+ resolver.insert(Preferences.CONTENT_URI, values);
+ } catch (Exception e) {
+ SoftPreconditions.warn(
+ TAG, "setPreference", e, "Error writing preference values");
+ }
+ return null;
+ }
+ }.execute();
+ }
+
+ private static class LoadPreferencesTask extends AsyncTask<Void, Void, Bundle> {
+ private final Context mContext;
+
+ private LoadPreferencesTask(Context context) {
+ mContext = context;
+ }
+
+ @Override
+ protected Bundle doInBackground(Void... params) {
+ Bundle bundle = new Bundle();
+ ContentResolver resolver = mContext.getContentResolver();
+ String[] projection = new String[] {Preferences.COLUMN_KEY, Preferences.COLUMN_VALUE};
+ try (Cursor cursor =
+ resolver.query(Preferences.CONTENT_URI, projection, null, null, null)) {
+ if (cursor != null) {
+ while (!isCancelled() && cursor.moveToNext()) {
+ String key = cursor.getString(0);
+ String value = cursor.getString(1);
+ Class prefClass = sPref2TypeMapping.get(key);
+ if (prefClass == int.class) {
+ try {
+ bundle.putInt(key, Integer.parseInt(value));
+ } catch (NumberFormatException e) {
+ Log.w(TAG, "Invalid format, key=" + key + ", value=" + value);
+ }
+ } else if (prefClass == long.class) {
+ try {
+ bundle.putLong(key, Long.parseLong(value));
+ } catch (NumberFormatException e) {
+ Log.w(TAG, "Invalid format, key=" + key + ", value=" + value);
+ }
+ } else if (prefClass == boolean.class) {
+ bundle.putBoolean(key, Boolean.parseBoolean(value));
+ } else {
+ bundle.putString(key, value);
+ }
+ }
+ }
+ } catch (Exception e) {
+ SoftPreconditions.warn(TAG, "getPreference", e, "Error querying preference values");
+ return null;
+ }
+ return bundle;
+ }
+
+ @Override
+ protected void onPostExecute(Bundle bundle) {
+ synchronized (CommonPreferences.class) {
+ if (bundle != null) {
+ sPreferenceValues.putAll(bundle);
+ }
+ }
+ if (sPreferencesChangedListener != null) {
+ sPreferencesChangedListener.onCommonPreferencesChanged();
+ }
+ }
+ }
+}