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.ContentResolver; 19 import android.content.ContentValues; 20 import android.content.Context; 21 import android.content.Intent; 22 import android.content.pm.PackageManager; 23 import android.content.pm.ProviderInfo; 24 import android.content.pm.ResolveInfo; 25 import android.content.res.Resources; 26 import android.database.Cursor; 27 import android.net.Uri; 28 import android.text.TextUtils; 29 30 import androidx.annotation.Nullable; 31 import androidx.annotation.WorkerThread; 32 33 import com.android.customization.model.ResourceConstants; 34 import com.android.wallpaper.R; 35 36 import com.bumptech.glide.Glide; 37 38 import java.util.ArrayList; 39 import java.util.List; 40 41 /** 42 * Abstracts the logic to retrieve available grid options from the current Launcher. 43 */ 44 public class LauncherGridOptionsProvider { 45 46 private static final String LIST_OPTIONS = "list_options"; 47 private static final String PREVIEW = "preview"; 48 private static final String DEFAULT_GRID = "default_grid"; 49 50 private static final String COL_NAME = "name"; 51 private static final String COL_ROWS = "rows"; 52 private static final String COL_COLS = "cols"; 53 private static final String COL_PREVIEW_COUNT = "preview_count"; 54 private static final String COL_IS_DEFAULT = "is_default"; 55 56 private final Context mContext; 57 private final String mGridProviderAuthority; 58 private final ProviderInfo mProviderInfo; 59 private List<GridOption> mOptions; 60 LauncherGridOptionsProvider(Context context, String authorityMetadataKey)61 public LauncherGridOptionsProvider(Context context, String authorityMetadataKey) { 62 mContext = context; 63 Intent homeIntent = new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME); 64 65 ResolveInfo info = context.getPackageManager().resolveActivity(homeIntent, 66 PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_META_DATA); 67 if (info != null && info.activityInfo != null && info.activityInfo.metaData != null) { 68 mGridProviderAuthority = info.activityInfo.metaData.getString(authorityMetadataKey); 69 } else { 70 mGridProviderAuthority = null; 71 } 72 // TODO: check permissions if needed 73 mProviderInfo = TextUtils.isEmpty(mGridProviderAuthority) ? null 74 : mContext.getPackageManager().resolveContentProvider(mGridProviderAuthority, 0); 75 } 76 areGridsAvailable()77 boolean areGridsAvailable() { 78 return mProviderInfo != null; 79 } 80 81 /** 82 * Retrieve the available grids. 83 * @param reload whether to reload grid options if they're cached. 84 */ 85 @WorkerThread 86 @Nullable fetch(boolean reload)87 List<GridOption> fetch(boolean reload) { 88 if (!areGridsAvailable()) { 89 return null; 90 } 91 if (mOptions != null && !reload) { 92 return mOptions; 93 } 94 Uri optionsUri = new Uri.Builder() 95 .scheme(ContentResolver.SCHEME_CONTENT) 96 .authority(mProviderInfo.authority) 97 .appendPath(LIST_OPTIONS) 98 .build(); 99 ContentResolver resolver = mContext.getContentResolver(); 100 String iconPath = mContext.getResources().getString(Resources.getSystem().getIdentifier( 101 ResourceConstants.CONFIG_ICON_MASK, "string", ResourceConstants.ANDROID_PACKAGE)); 102 try (Cursor c = resolver.query(optionsUri, null, null, null, null)) { 103 mOptions = new ArrayList<>(); 104 while(c.moveToNext()) { 105 String name = c.getString(c.getColumnIndex(COL_NAME)); 106 int rows = c.getInt(c.getColumnIndex(COL_ROWS)); 107 int cols = c.getInt(c.getColumnIndex(COL_COLS)); 108 int previewCount = c.getInt(c.getColumnIndex(COL_PREVIEW_COUNT)); 109 boolean isSet = Boolean.valueOf(c.getString(c.getColumnIndex(COL_IS_DEFAULT))); 110 Uri preview = new Uri.Builder() 111 .scheme(ContentResolver.SCHEME_CONTENT) 112 .authority(mProviderInfo.authority) 113 .appendPath(PREVIEW) 114 .appendPath(name) 115 .build(); 116 String title = mContext.getString(R.string.grid_title_pattern, cols, rows); 117 mOptions.add(new GridOption(title, name, isSet, rows, cols, preview, previewCount, 118 iconPath)); 119 } 120 Glide.get(mContext).clearDiskCache(); 121 } catch (Exception e) { 122 mOptions = null; 123 } 124 return mOptions; 125 } 126 applyGrid(String name)127 int applyGrid(String name) { 128 Uri updateDefaultUri = new Uri.Builder() 129 .scheme(ContentResolver.SCHEME_CONTENT) 130 .authority(mProviderInfo.authority) 131 .appendPath(DEFAULT_GRID) 132 .build(); 133 ContentValues values = new ContentValues(); 134 values.put("name", name); 135 return mContext.getContentResolver().update(updateDefaultUri, values, null, null); 136 } 137 } 138