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.camera.settings; 18 19 import com.android.camera.async.Observable; 20 import com.android.camera.async.SafeCloseable; 21 22 import java.util.concurrent.Executor; 23 24 import javax.annotation.CheckReturnValue; 25 import javax.annotation.Nonnull; 26 import javax.annotation.concurrent.ThreadSafe; 27 28 /** 29 * Wraps a {@link SettingsManager} setting with thread-safe interfaces for 30 * observing changes. 31 */ 32 @ThreadSafe 33 public final class SettingObserver<T> implements Observable<T> { 34 private class Listener implements SettingsManager.OnSettingChangedListener, SafeCloseable { 35 private final Runnable mRunnable; 36 private final Executor mExecutor; 37 Listener(Runnable runnable, Executor executor)38 private Listener(Runnable runnable, Executor executor) { 39 mRunnable = runnable; 40 mExecutor = executor; 41 } 42 43 @Override onSettingChanged(SettingsManager settingsManager, String key)44 public void onSettingChanged(SettingsManager settingsManager, String key) { 45 mExecutor.execute(mRunnable); 46 } 47 48 @Override close()49 public void close() { 50 mSettingsManager.removeListener(this); 51 } 52 } 53 54 private final SettingsManager mSettingsManager; 55 private final String mScope; 56 private final String mKey; 57 private final Class<T> mTClass; 58 SettingObserver(SettingsManager manager, String scope, String key, Class<T> tClass)59 private SettingObserver(SettingsManager manager, String scope, String key, Class<T> tClass) { 60 mSettingsManager = manager; 61 mScope = scope; 62 mKey = key; 63 mTClass = tClass; 64 } 65 ofInteger(SettingsManager manager, String scope, String key)66 public static SettingObserver<Integer> ofInteger(SettingsManager manager, 67 String scope, String key) { 68 return new SettingObserver<>(manager, scope, key, 69 Integer.class); 70 } 71 ofString(SettingsManager manager, String scope, String key)72 public static SettingObserver<String> ofString(SettingsManager manager, 73 String scope, String key) { 74 return new SettingObserver<>(manager, scope, key, 75 String.class); 76 } 77 ofBoolean(SettingsManager manager, String scope, String key)78 public static SettingObserver<Boolean> ofBoolean(SettingsManager manager, 79 String scope, String key) { 80 return new SettingObserver<>(manager, scope, key, 81 Boolean.class); 82 } 83 84 @CheckReturnValue 85 @Nonnull 86 @Override addCallback(@onnull Runnable callback, @Nonnull Executor executor)87 public SafeCloseable addCallback(@Nonnull Runnable callback, @Nonnull Executor executor) { 88 Listener listener = new Listener(callback, executor); 89 mSettingsManager.addListener(listener); 90 return listener; 91 } 92 93 @Nonnull 94 @Override 95 @SuppressWarnings("unchecked") get()96 public T get() { 97 if (mTClass.equals(Integer.class)) { 98 return (T) Integer.valueOf(mSettingsManager.getInteger(mScope, mKey)); 99 } else if (mTClass.equals(String.class)) { 100 Object string = mSettingsManager.getString(mScope, mKey); 101 if (string == null) { 102 return null; 103 } else { 104 return (T) string; 105 } 106 } else if (mTClass.equals(Boolean.class)) { 107 return (T) Boolean.valueOf(mSettingsManager.getBoolean(mScope, mKey)); 108 } else { 109 // Impossible branch 110 throw new IllegalStateException("T must be one of {Integer, Boolean, String}"); 111 } 112 } 113 } 114