1ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian/* 2ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * Copyright (C) 2016 The Android Open Source Project 3ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * 4ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * Licensed under the Apache License, Version 2.0 (the "License"); 5ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * you may not use this file except in compliance with the License. 6ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * You may obtain a copy of the License at 7ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * 8ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * http://www.apache.org/licenses/LICENSE-2.0 9ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * 10ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * Unless required by applicable law or agreed to in writing, software 11ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * distributed under the License is distributed on an "AS IS" BASIS, 12ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * See the License for the specific language governing permissions and 14ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * limitations under the License. 15ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian */ 16ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 17ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianpackage com.android.dialer.shortcuts; 18ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 19ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.content.Context; 20ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.os.Build; 21ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.support.annotation.MainThread; 22ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.support.annotation.NonNull; 23ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.support.annotation.WorkerThread; 24ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.contacts.common.list.ContactEntry; 25ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.dialer.common.Assert; 26ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport com.android.dialer.common.LogUtil; 279779f967ebb9512e5b19090b071572c9c4f0f2a6Eric Erfanianimport com.android.dialer.common.concurrent.AsyncTaskExecutor; 289779f967ebb9512e5b19090b071572c9c4f0f2a6Eric Erfanianimport com.android.dialer.common.concurrent.AsyncTaskExecutors; 299779f967ebb9512e5b19090b071572c9c4f0f2a6Eric Erfanianimport com.android.dialer.common.concurrent.FallibleAsyncTask; 30ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport java.util.ArrayList; 31ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport java.util.List; 32ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 33ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian/** Refreshes launcher shortcuts from UI components using provided list of contacts. */ 34ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianpublic final class ShortcutRefresher { 35ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 36ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private static final AsyncTaskExecutor EXECUTOR = AsyncTaskExecutors.createThreadPoolExecutor(); 37ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 38ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian /** Asynchronously updates launcher shortcuts using the provided list of contacts. */ 39ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian @MainThread 40ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public static void refresh(@NonNull Context context, List<ContactEntry> contacts) { 41ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian Assert.isMainThread(); 42ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian Assert.isNotNull(context); 43ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 44ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N_MR1) { 45ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian return; 46ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 47ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 48ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (!Shortcuts.areDynamicShortcutsEnabled(context)) { 49ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian return; 50ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 51ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 52ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian //noinspection unchecked 53ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian EXECUTOR.submit(Task.ID, new Task(context), new ArrayList<>(contacts)); 54ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 55ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 56ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private static final class Task extends FallibleAsyncTask<List<ContactEntry>, Void, Void> { 57ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private static final String ID = "ShortcutRefresher.Task"; 58ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 59ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private final Context context; 60ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 61ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian Task(Context context) { 62ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian this.context = context; 63ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 64ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 65ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian /** 66ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * @param params array containing exactly one element, the list of contacts from favorites 67ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * tiles, ordered in tile order. 68ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian */ 69ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian @SafeVarargs 70ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian @Override 71ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian @NonNull 72ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian @WorkerThread 73ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian protected final Void doInBackgroundFallible(List<ContactEntry>... params) { 74ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian Assert.isWorkerThread(); 75ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian LogUtil.enterBlock("ShortcutRefresher.Task.doInBackground"); 76ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 77ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // Only dynamic shortcuts are maintained from UI components. Pinned shortcuts are maintained 78ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // by the job scheduler. This is because a pinned contact may not necessarily still be in the 79ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // favorites tiles, so refreshing it would require an additional database query. We don't want 80ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // to incur the cost of that extra database query every time the favorites tiles change. 81ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian new DynamicShortcuts(context, new IconFactory(context)).refresh(params[0]); // Blocking 82ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 83ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian return null; 84ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 85ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 86ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian} 87