Merge "Use ContentProvider for clockfaces" into ub-launcher3-master
diff --git a/res/values/override.xml b/res/values/override.xml
index de6e908..54bb551 100644
--- a/res/values/override.xml
+++ b/res/values/override.xml
@@ -18,6 +18,8 @@
<resources>
<string name="themes_stub_package" translatable="false"/>
<string name="clocks_stub_package" translatable="false"/>
+ <!-- Authority of a provider in System UI that will provide preview info for available clockfaces. -->
+ <string name="clocks_provider_authority" translatable="false">com.android.keyguard.clock</string>
<!--Name of metadata in the main launcher Activity which values contains the authority
corresponding to a ContentProvider in launcher to provide available grids and
diff --git a/src/com/android/customization/model/clock/Clockface.java b/src/com/android/customization/model/clock/Clockface.java
index b72ef23..9eba02d 100644
--- a/src/com/android/customization/model/clock/Clockface.java
+++ b/src/com/android/customization/model/clock/Clockface.java
@@ -15,7 +15,8 @@
*/
package com.android.customization.model.clock;
-import android.graphics.drawable.Drawable;
+import android.content.Context;
+import android.provider.Settings.Secure;
import android.text.TextUtils;
import android.view.View;
import android.widget.ImageView;
@@ -23,15 +24,16 @@
import com.android.customization.model.CustomizationManager;
import com.android.customization.model.CustomizationOption;
import com.android.wallpaper.R;
+import com.android.wallpaper.asset.Asset;
public class Clockface implements CustomizationOption<Clockface> {
private final String mTitle;
private final String mId;
- private final Drawable mPreview;
- private final Drawable mThumbnail;
+ private final Asset mPreview;
+ private final Asset mThumbnail;
- private Clockface(String title, String id, Drawable preview, Drawable thumbnail) {
+ private Clockface(String title, String id, Asset preview, Asset thumbnail) {
mTitle = title;
mId = id;
mPreview = preview;
@@ -45,7 +47,9 @@
@Override
public void bindThumbnailTile(View view) {
- ((ImageView) view.findViewById(R.id.clock_option_thumbnail)).setImageDrawable(mThumbnail);
+ ImageView thumbView = view.findViewById(R.id.clock_option_thumbnail);
+ mThumbnail.loadDrawableWithTransition(thumbView.getContext(), thumbView, 50, null,
+ thumbView.getResources().getColor(android.R.color.transparent, null));
}
@Override
@@ -61,7 +65,7 @@
return R.layout.clock_option;
}
- public Drawable getPreviewDrawable() {
+ public Asset getPreviewAsset() {
return mPreview;
}
@@ -72,8 +76,8 @@
public static class Builder {
private String mTitle;
private String mId;
- private Drawable mPreview;
- private Drawable mThumbnail;
+ private Asset mPreview;
+ private Asset mThumbnail;
public Clockface build() {
return new Clockface(mTitle, mId, mPreview, mThumbnail);
@@ -89,12 +93,12 @@
return this;
}
- public Builder setPreview(Drawable preview) {
+ public Builder setPreview(Asset preview) {
mPreview = preview;
return this;
}
- public Builder setThumbnail(Drawable thumbnail) {
+ public Builder setThumbnail(Asset thumbnail) {
mThumbnail = thumbnail;
return this;
}
diff --git a/src/com/android/customization/model/clock/ContentProviderClockProvider.java b/src/com/android/customization/model/clock/ContentProviderClockProvider.java
new file mode 100644
index 0000000..375f3c1
--- /dev/null
+++ b/src/com/android/customization/model/clock/ContentProviderClockProvider.java
@@ -0,0 +1,130 @@
+package com.android.customization.model.clock;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.pm.ProviderInfo;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.text.TextUtils;
+
+import com.android.customization.model.CustomizationManager.OptionsFetchedListener;
+import com.android.customization.model.clock.Clockface.Builder;
+import com.android.wallpaper.R;
+import com.android.wallpaper.asset.ContentUriAsset;
+
+import com.bumptech.glide.Glide;
+import com.bumptech.glide.request.RequestOptions;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ContentProviderClockProvider implements ClockProvider {
+
+ private final Context mContext;
+ private final ProviderInfo mProviderInfo;
+ private List<Clockface> mClocks;
+
+ public ContentProviderClockProvider(Context context) {
+ mContext = context;
+ String providerAuthority = mContext.getString(R.string.clocks_provider_authority);
+ // TODO: check permissions if needed
+ mProviderInfo = TextUtils.isEmpty(providerAuthority) ? null
+ : mContext.getPackageManager().resolveContentProvider(providerAuthority,
+ PackageManager.MATCH_SYSTEM_ONLY);
+ }
+
+ @Override
+ public boolean isAvailable() {
+ return mProviderInfo != null;
+ }
+
+ @Override
+ public void fetch(OptionsFetchedListener<Clockface> callback, boolean reload) {
+ if (!isAvailable()) {
+ if (callback != null) {
+ callback.onOptionsLoaded(null);
+ }
+ return;
+ }
+ if (mClocks != null && !reload) {
+ if (callback != null) {
+ callback.onOptionsLoaded(mClocks);
+ }
+ return;
+ }
+ new ClocksFetchTask(mContext, mProviderInfo, options -> {
+ mClocks = options;
+ if (callback != null) {
+ callback.onOptionsLoaded(mClocks);
+ }
+ }).execute();
+ }
+
+ private static class ClocksFetchTask extends AsyncTask<Void, Void, List<Clockface>> {
+
+ private static final String LIST_OPTIONS = "list_options";
+
+ private static final String COL_NAME = "name";
+ private static final String COL_TITLE = "title";
+ private static final String COL_ID = "id";
+ private static final String COL_THUMBNAIL = "thumbnail";
+ private static final String COL_PREVIEW = "preview";
+
+ private final OptionsFetchedListener<Clockface> mCallback;
+ private Context mContext;
+ private final ProviderInfo mProviderInfo;
+
+ public ClocksFetchTask(Context context, ProviderInfo providerInfo,
+ OptionsFetchedListener<Clockface> callback) {
+ super();
+ mContext = context;
+ mProviderInfo = providerInfo;
+ mCallback = callback;
+ }
+
+ @Override
+ protected List<Clockface> doInBackground(Void... voids) {
+ Uri optionsUri = new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(mProviderInfo.authority)
+ .appendPath(LIST_OPTIONS)
+ .build();
+
+ ContentResolver resolver = mContext.getContentResolver();
+
+ List<Clockface> clockfaces = new ArrayList<>();
+ try (Cursor c = resolver.query(optionsUri, null, null, null, null)) {
+ while(c.moveToNext()) {
+ String id = c.getString(c.getColumnIndex(COL_ID));
+ String title = c.getString(c.getColumnIndex(COL_TITLE));
+ String thumbnailUri = c.getString(c.getColumnIndex(COL_THUMBNAIL));
+ String previewUri = c.getString(c.getColumnIndex(COL_PREVIEW));
+ Uri thumbnail = Uri.parse(thumbnailUri);
+ Uri preview = Uri.parse(previewUri);
+
+ Clockface.Builder builder = new Builder();
+ builder.setId(id).setTitle(title)
+ .setThumbnail(new ContentUriAsset(mContext, thumbnail,
+ RequestOptions.fitCenterTransform()))
+ .setPreview(new ContentUriAsset(mContext, preview,
+ RequestOptions.fitCenterTransform()));
+ clockfaces.add(builder.build());
+ }
+ Glide.get(mContext).clearDiskCache();
+ } catch (Exception e) {
+ clockfaces = null;
+ } finally {
+ mContext = null;
+ }
+ return clockfaces;
+ }
+
+ @Override
+ protected void onPostExecute(List<Clockface> clockfaces) {
+ super.onPostExecute(clockfaces);
+ mCallback.onOptionsLoaded(clockfaces);
+ }
+ }
+}
diff --git a/src/com/android/customization/model/clock/ResourcesApkClockProvider.java b/src/com/android/customization/model/clock/ResourcesApkClockProvider.java
deleted file mode 100644
index 1533db9..0000000
--- a/src/com/android/customization/model/clock/ResourcesApkClockProvider.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.customization.model.clock;
-
-import android.content.Context;
-import android.content.res.Resources.NotFoundException;
-import android.util.Log;
-
-import com.android.customization.model.CustomizationManager.OptionsFetchedListener;
-import com.android.customization.model.ResourcesApkProvider;
-import com.android.customization.model.clock.Clockface.Builder;
-import com.android.wallpaper.R;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class ResourcesApkClockProvider extends ResourcesApkProvider implements ClockProvider {
-
- private static final String TAG = "ResourcesApkClockProvider";
-
- private static final String CLOCKS_ARRAY = "clocks";
- private static final String TITLE_PREFIX = "clock_title_";
- private static final String ID_PREFIX = "clock_id_";
- private static final String PREVIEW_PREFIX = "clock_preview_";
- private static final String THUMBNAIL_PREFIX = "clock_thumbnail_";
-
- private List<Clockface> mClocks;
-
- public ResourcesApkClockProvider(Context context){
- super(context, context.getString(R.string.clocks_stub_package));
- }
-
- @Override
- public void fetch(OptionsFetchedListener<Clockface> callback, boolean reload) {
- if (mClocks == null || reload) {
- mClocks = new ArrayList<>();
- loadAll();
- }
-
- if(callback != null) {
- callback.onOptionsLoaded(mClocks);
- }
- }
-
- private void loadAll() {
- String[] clockNames = getItemsFromStub(CLOCKS_ARRAY);
-
- for (String clockName : clockNames) {
- try {
- Builder builder = new Builder();
-
- builder.setTitle(getItemStringFromStub(TITLE_PREFIX, clockName))
- .setId(getItemStringFromStub(ID_PREFIX, clockName))
- .setPreview(getItemDrawableFromStub(PREVIEW_PREFIX, clockName))
- .setThumbnail(getItemDrawableFromStub(THUMBNAIL_PREFIX, clockName));
-
- mClocks.add(builder.build());
- } catch (NotFoundException e) {
- Log.i(TAG, "Resource not found, skipping clock", e);
- }
- }
- }
-}
diff --git a/src/com/android/customization/picker/CustomizationPickerActivity.java b/src/com/android/customization/picker/CustomizationPickerActivity.java
index 2b65862..ec4963f 100644
--- a/src/com/android/customization/picker/CustomizationPickerActivity.java
+++ b/src/com/android/customization/picker/CustomizationPickerActivity.java
@@ -34,7 +34,7 @@
import com.android.customization.model.CustomizationOption;
import com.android.customization.model.clock.ClockManager;
import com.android.customization.model.clock.Clockface;
-import com.android.customization.model.clock.ResourcesApkClockProvider;
+import com.android.customization.model.clock.ContentProviderClockProvider;
import com.android.customization.model.grid.GridOption;
import com.android.customization.model.grid.GridOptionsManager;
import com.android.customization.model.grid.LauncherGridOptionsProvider;
@@ -134,7 +134,8 @@
mSections.put(R.id.nav_theme, new ThemeSection(R.id.nav_theme, themeManager));
}
//Clock
- ClockManager clockManager = new ClockManager(this, new ResourcesApkClockProvider(this));
+ //ClockManager clockManager = new ClockManager(this, new ResourcesApkClockProvider(this));
+ ClockManager clockManager = new ClockManager(this, new ContentProviderClockProvider(this));
if (clockManager.isAvailable()) {
mSections.put(R.id.nav_clock, new ClockSection(R.id.nav_clock, clockManager));
}
diff --git a/src/com/android/customization/picker/clock/ClockFragment.java b/src/com/android/customization/picker/clock/ClockFragment.java
index 2401686..ab38987 100644
--- a/src/com/android/customization/picker/clock/ClockFragment.java
+++ b/src/com/android/customization/picker/clock/ClockFragment.java
@@ -16,7 +16,7 @@
package com.android.customization.picker.clock;
import android.content.Context;
-import android.graphics.drawable.Drawable;
+import android.content.res.Resources;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
@@ -34,6 +34,7 @@
import com.android.customization.widget.OptionSelectorController;
import com.android.customization.widget.PreviewPager;
import com.android.wallpaper.R;
+import com.android.wallpaper.asset.Asset;
import com.android.wallpaper.picker.ToolbarFragment;
/**
@@ -111,17 +112,22 @@
private static class ClockfacePreviewPage extends PreviewPage {
- private final Drawable mPreview;
+ private final Asset mPreviewAsset;
- public ClockfacePreviewPage(String title, Drawable previewDrawable) {
+ public ClockfacePreviewPage(String title, Asset previewAsset) {
super(title);
- mPreview = previewDrawable;
+ mPreviewAsset = previewAsset;
}
@Override
public void bindPreviewContent() {
- ((ImageView) card.findViewById(R.id.clock_preview_image))
- .setImageDrawable(mPreview);
+ ImageView previewImage = card.findViewById(R.id.clock_preview_image);
+ Context context = previewImage.getContext();
+ Resources res = previewImage.getResources();
+ mPreviewAsset.loadDrawableWithTransition(context, previewImage,
+ 100 /* transitionDurationMillis */,
+ null /* drawableLoadedListener */,
+ res.getColor(android.R.color.transparent, null) /* placeholderColor */);
}
}
@@ -133,7 +139,7 @@
private static class ClockPreviewAdapter extends BasePreviewAdapter<ClockfacePreviewPage> {
ClockPreviewAdapter(Context context, Clockface clockface) {
super(context, R.layout.clock_preview_card);
- addPage(new ClockfacePreviewPage(clockface.getTitle(), clockface.getPreviewDrawable()));
+ addPage(new ClockfacePreviewPage(clockface.getTitle(), clockface.getPreviewAsset()));
}
}
}