1 /* 2 * Copyright (C) 2021 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 package com.android.customization.model.themedicon; 17 18 import android.content.ContentResolver; 19 import android.content.ContentValues; 20 import android.content.Context; 21 import android.database.Cursor; 22 import android.os.Handler; 23 import android.os.Looper; 24 25 import androidx.annotation.Nullable; 26 27 import com.android.customization.module.CustomizationPreferences; 28 import com.android.themepicker.R; 29 import com.android.wallpaper.module.InjectorProvider; 30 31 import java.util.concurrent.ExecutorService; 32 import java.util.concurrent.Executors; 33 34 /** 35 * Retrieves the themed icon switch by {@link ContentResolver} from the current launcher 36 */ 37 public class ThemedIconSwitchProvider { 38 39 private static ThemedIconSwitchProvider sThemedIconSwitchProvider; 40 41 private static final String ICON_THEMED = "icon_themed"; 42 private static final String COL_ICON_THEMED_VALUE = "boolean_value"; 43 private static final int ENABLED = 1; 44 private static final int RESULT_SUCCESS = 1; 45 46 private final ExecutorService mExecutorService = Executors.newSingleThreadExecutor(); 47 private final ContentResolver mContentResolver; 48 private final ThemedIconUtils mThemedIconUtils; 49 private final CustomizationPreferences mCustomizationPreferences; 50 51 /** Callback for the themed icon enabled state fetching result. */ 52 public interface FetchThemedIconEnabledCallback { 53 /** Gets called when the result is available. */ onResult(boolean isEnabled)54 void onResult(boolean isEnabled); 55 } 56 57 /** Returns the {@link ThemedIconSwitchProvider} instance. */ getInstance(Context context)58 public static ThemedIconSwitchProvider getInstance(Context context) { 59 if (sThemedIconSwitchProvider == null) { 60 Context appContext = context.getApplicationContext(); 61 sThemedIconSwitchProvider = new ThemedIconSwitchProvider( 62 appContext.getContentResolver(), 63 new ThemedIconUtils(appContext, 64 appContext.getString(R.string.themed_icon_metadata_key)), 65 (CustomizationPreferences) InjectorProvider.getInjector() 66 .getPreferences(appContext)); 67 } 68 return sThemedIconSwitchProvider; 69 } 70 ThemedIconSwitchProvider(ContentResolver contentResolver, ThemedIconUtils themedIconUtils, CustomizationPreferences customizationPreferences)71 private ThemedIconSwitchProvider(ContentResolver contentResolver, 72 ThemedIconUtils themedIconUtils, CustomizationPreferences customizationPreferences) { 73 mContentResolver = contentResolver; 74 mThemedIconUtils = themedIconUtils; 75 mCustomizationPreferences = customizationPreferences; 76 } 77 78 /** Returns {@code true} if themed icon feature is available. */ isThemedIconAvailable()79 public boolean isThemedIconAvailable() { 80 return mThemedIconUtils.isThemedIconAvailable(); 81 } 82 83 /** Gets the themed icon feature enabled state from SharedPreferences. */ isThemedIconEnabled()84 public boolean isThemedIconEnabled() { 85 return mCustomizationPreferences.getThemedIconEnabled(); 86 } 87 88 /** 89 * Fetches the themed icon feature enabled state and stores in SharedPreferences, or returns the 90 * SharedPreferences result if the fetching failed. 91 */ fetchThemedIconEnabled(@ullable FetchThemedIconEnabledCallback callback)92 public void fetchThemedIconEnabled(@Nullable FetchThemedIconEnabledCallback callback) { 93 mExecutorService.submit(() -> { 94 try (Cursor cursor = mContentResolver.query( 95 mThemedIconUtils.getUriForPath(ICON_THEMED), /* projection= */ null, 96 /* selection= */ null, /* selectionArgs= */ null, /* sortOrder= */ null)) { 97 if (cursor != null && cursor.moveToNext()) { 98 boolean isEnabled = cursor.getInt(cursor.getColumnIndex(COL_ICON_THEMED_VALUE)) 99 == ENABLED; 100 if (mCustomizationPreferences.getThemedIconEnabled() != isEnabled) { 101 mCustomizationPreferences.setThemedIconEnabled(isEnabled); 102 } 103 if (callback != null) { 104 postMainThread(() -> callback.onResult(isEnabled)); 105 } 106 return; 107 } 108 } 109 if (callback != null) { 110 postMainThread( 111 () -> callback.onResult(mCustomizationPreferences.getThemedIconEnabled())); 112 } 113 }); 114 } 115 116 /** 117 * Enables themed icon feature or not. 118 * 119 * <p>The value would also be stored in SharedPreferences. 120 */ setThemedIconEnabled(boolean enabled)121 public void setThemedIconEnabled(boolean enabled) { 122 mExecutorService.submit(() -> { 123 ContentValues values = new ContentValues(); 124 values.put(COL_ICON_THEMED_VALUE, enabled); 125 int result = mContentResolver.update(mThemedIconUtils.getUriForPath(ICON_THEMED), 126 values, /* where= */ null, /* selectionArgs= */ null); 127 if (result == RESULT_SUCCESS) { 128 mCustomizationPreferences.setThemedIconEnabled(enabled); 129 } 130 }); 131 } 132 postMainThread(Runnable runnable)133 private void postMainThread(Runnable runnable) { 134 new Handler(Looper.getMainLooper()).post(runnable); 135 } 136 } 137