• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 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.grid;
17 
18 import android.content.Context;
19 import android.os.Bundle;
20 import android.os.Handler;
21 import android.os.Looper;
22 import android.util.Log;
23 
24 import androidx.annotation.Nullable;
25 import androidx.annotation.VisibleForTesting;
26 import androidx.lifecycle.LiveData;
27 
28 import com.android.customization.model.CustomizationManager;
29 import com.android.customization.module.CustomizationInjector;
30 import com.android.customization.module.ThemesUserEventLogger;
31 import com.android.wallpaper.R;
32 import com.android.wallpaper.module.InjectorProvider;
33 import com.android.wallpaper.util.PreviewUtils;
34 
35 import java.util.List;
36 import java.util.concurrent.ExecutionException;
37 import java.util.concurrent.ExecutorService;
38 import java.util.concurrent.Executors;
39 
40 /**
41  * {@link CustomizationManager} for interfacing with the launcher to handle {@link GridOption}s.
42  */
43 public class GridOptionsManager implements CustomizationManager<GridOption> {
44 
45     private static final ExecutorService sExecutorService = Executors.newSingleThreadExecutor();
46     private static final String TAG = "GridOptionsManager";
47 
48     private static GridOptionsManager sGridOptionsManager;
49 
50     private final LauncherGridOptionsProvider mProvider;
51     private final ThemesUserEventLogger mEventLogger;
52     private int mGridOptionSize = -1;
53 
54     /** Returns the {@link GridOptionsManager} instance. */
getInstance(Context context)55     public static GridOptionsManager getInstance(Context context) {
56         if (sGridOptionsManager == null) {
57             Context appContext = context.getApplicationContext();
58             CustomizationInjector injector = (CustomizationInjector) InjectorProvider.getInjector();
59             ThemesUserEventLogger eventLogger = (ThemesUserEventLogger) injector.getUserEventLogger(
60                     appContext);
61             sGridOptionsManager = new GridOptionsManager(
62                     new LauncherGridOptionsProvider(appContext,
63                             appContext.getString(R.string.grid_control_metadata_name)),
64                     eventLogger);
65         }
66         return sGridOptionsManager;
67     }
68 
69     @VisibleForTesting
GridOptionsManager(LauncherGridOptionsProvider provider, ThemesUserEventLogger logger)70     GridOptionsManager(LauncherGridOptionsProvider provider, ThemesUserEventLogger logger) {
71         mProvider = provider;
72         mEventLogger = logger;
73     }
74 
75     @Override
isAvailable()76     public boolean isAvailable() {
77         if (mGridOptionSize < 0) {
78             try {
79                 mGridOptionSize = sExecutorService.submit(() -> {
80                     List<GridOption> gridOptions = mProvider.fetch(/* reload= */true);
81                     return gridOptions == null ? 0 : gridOptions.size();
82                 }).get();
83             } catch (InterruptedException | ExecutionException e) {
84                 Log.w(TAG, "could not get gridOptionSize", e);
85             }
86         }
87         return mGridOptionSize > 1 && mProvider.areGridsAvailable();
88     }
89 
90     @Override
apply(GridOption option, Callback callback)91     public void apply(GridOption option, Callback callback) {
92         int updated = mProvider.applyGrid(option.name);
93         if (updated == 1) {
94             mEventLogger.logGridApplied(option);
95             callback.onSuccess();
96         } else {
97             callback.onError(null);
98         }
99     }
100 
101     @Override
preview(GridOption option)102     public void preview(GridOption option) {
103         mProvider.updateView();
104     }
105 
106     @Override
fetchOptions(OptionsFetchedListener<GridOption> callback, boolean reload)107     public void fetchOptions(OptionsFetchedListener<GridOption> callback, boolean reload) {
108         sExecutorService.submit(() -> {
109             List<GridOption> gridOptions = mProvider.fetch(reload);
110             new Handler(Looper.getMainLooper()).post(() -> {
111                 if (callback != null) {
112                     if (gridOptions != null && !gridOptions.isEmpty()) {
113                         callback.onOptionsLoaded(gridOptions);
114                     } else {
115                         callback.onError(null);
116                     }
117                 }
118             });
119         });
120     }
121 
122     /**
123      * Returns an observable that receives a new value each time that the grid options are changed.
124      */
getOptionChangeObservable(@ullable Handler handler)125     public LiveData<Object> getOptionChangeObservable(@Nullable Handler handler) {
126         return mProvider.getOptionChangeObservable(handler);
127     }
128 
129     /** Call through content provider API to render preview */
renderPreview(Bundle bundle, String gridName, PreviewUtils.WorkspacePreviewCallback callback)130     public void renderPreview(Bundle bundle, String gridName,
131             PreviewUtils.WorkspacePreviewCallback callback) {
132         mProvider.renderPreview(gridName, bundle, callback);
133     }
134 }
135