Add ClockOptionsProvider for more realistic previews.
This change enables the picker app to move to the new ContentProvider but it doesn't change any of the assets. A follow-up change will dynamically generate a realistic preview image from the clock. Bug: 123704608 Test: atest on new tests ClockInfoTest and ClockOptionsProviderTest Change-Id: I744c8dd063f6aa112e290fcf54cdc0e0b1377a0e
@@ -631,6 +631,14 @@
|
||||
android:exported="true">
|
||||
</provider>
|
||||
|
||||
<!-- Provides list and realistic previews of clock faces for the picker app. -->
|
||||
<provider
|
||||
android:name="com.android.keyguard.clock.ClockOptionsProvider"
|
||||
android:authorities="com.android.keyguard.clock"
|
||||
android:exported="true"
|
||||
android:grantUriPermissions="true">
|
||||
</provider>
|
||||
|
||||
<receiver
|
||||
android:name=".statusbar.KeyboardShortcutsReceiver">
|
||||
<intent-filter>
|
||||
|
||||
|
After Width: | Height: | Size: 7.5 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 3.4 KiB |
|
After Width: | Height: | Size: 6.6 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
BIN
packages/SystemUI/res-keyguard/drawable-xxxhdpi/type_preview.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 6.2 KiB |
@@ -485,4 +485,17 @@ number">%d</xliff:g> remaining attempts before SIM becomes permanently unusable.
|
||||
<item>Fifty\nNine</item>
|
||||
</string-array>
|
||||
|
||||
<!-- Title for default clock face that will appear in the picker app next to a preview image of
|
||||
the clock face. [CHAR LIMIT=8] -->
|
||||
<string name="clock_title_default" translatable="false">Default</string>
|
||||
<!-- Title for Bubble clock face that will appear in the picker app next to a preview image of
|
||||
the clock face. [CHAR LIMIT=8] -->
|
||||
<string name="clock_title_bubble" translatable="false">Bubble</string>
|
||||
<!-- Title for Stretch clock face that will appear in the picker app next to a preview image of
|
||||
the clock face. [CHAR LIMIT=8] -->
|
||||
<string name="clock_title_stretch" translatable="false">Stretch</string>
|
||||
<!-- Title for Typographic clock face that will appear in the picker app next to a preview image of
|
||||
the clock face. [CHAR LIMIT=8] -->
|
||||
<string name="clock_title_type" translatable="false">Type</string>
|
||||
|
||||
</resources>
|
||||
|
||||
117
packages/SystemUI/src/com/android/keyguard/clock/ClockInfo.java
Normal file
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* 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.keyguard.clock;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* Metadata about an available clock face.
|
||||
*/
|
||||
final class ClockInfo {
|
||||
|
||||
private final String mName;
|
||||
private final String mTitle;
|
||||
private final String mId;
|
||||
private final Supplier<Bitmap> mThumbnail;
|
||||
private final Supplier<Bitmap> mPreview;
|
||||
|
||||
private ClockInfo(String name, String title, String id,
|
||||
Supplier<Bitmap> thumbnail, Supplier<Bitmap> preview) {
|
||||
mName = name;
|
||||
mTitle = title;
|
||||
mId = id;
|
||||
mThumbnail = thumbnail;
|
||||
mPreview = preview;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the non-internationalized name for the clock face.
|
||||
*/
|
||||
String getName() {
|
||||
return mName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name (title) of the clock face to be shown in the picker app.
|
||||
*/
|
||||
String getTitle() {
|
||||
return mTitle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the ID of the clock face, used by the picker to set the current selection.
|
||||
*/
|
||||
String getId() {
|
||||
return mId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a thumbnail image of the clock.
|
||||
*/
|
||||
Bitmap getThumbnail() {
|
||||
return mThumbnail.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a potentially realistic preview image of the clock face.
|
||||
*/
|
||||
Bitmap getPreview() {
|
||||
return mPreview.get();
|
||||
}
|
||||
|
||||
static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
static class Builder {
|
||||
private String mName;
|
||||
private String mTitle;
|
||||
private String mId;
|
||||
private Supplier<Bitmap> mThumbnail;
|
||||
private Supplier<Bitmap> mPreview;
|
||||
|
||||
public ClockInfo build() {
|
||||
return new ClockInfo(mName, mTitle, mId, mThumbnail, mPreview);
|
||||
}
|
||||
|
||||
public Builder setName(String name) {
|
||||
mName = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setTitle(String title) {
|
||||
mTitle = title;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setId(String id) {
|
||||
mId = id;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setThumbnail(Supplier<Bitmap> thumbnail) {
|
||||
mThumbnail = thumbnail;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setPreview(Supplier<Bitmap> preview) {
|
||||
mPreview = preview;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,12 +17,15 @@ package com.android.keyguard.clock;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.database.ContentObserver;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.provider.Settings;
|
||||
import android.view.LayoutInflater;
|
||||
|
||||
import com.android.keyguard.R;
|
||||
import com.android.systemui.plugins.ClockPlugin;
|
||||
import com.android.systemui.statusbar.policy.ExtensionController;
|
||||
import com.android.systemui.statusbar.policy.ExtensionController.Extension;
|
||||
@@ -45,6 +48,7 @@ public final class ClockManager {
|
||||
private final LayoutInflater mLayoutInflater;
|
||||
private final ContentResolver mContentResolver;
|
||||
|
||||
private final List<ClockInfo> mClockInfos = new ArrayList<>();
|
||||
/**
|
||||
* Observe settings changes to know when to switch the clock face.
|
||||
*/
|
||||
@@ -76,6 +80,36 @@ public final class ClockManager {
|
||||
mExtensionController = extensionController;
|
||||
mLayoutInflater = LayoutInflater.from(context);
|
||||
mContentResolver = context.getContentResolver();
|
||||
|
||||
Resources res = context.getResources();
|
||||
mClockInfos.add(ClockInfo.builder()
|
||||
.setName("default")
|
||||
.setTitle(res.getString(R.string.clock_title_default))
|
||||
.setId("default")
|
||||
.setThumbnail(() -> BitmapFactory.decodeResource(res, R.drawable.default_thumbnail))
|
||||
.setPreview(() -> BitmapFactory.decodeResource(res, R.drawable.default_preview))
|
||||
.build());
|
||||
mClockInfos.add(ClockInfo.builder()
|
||||
.setName("bubble")
|
||||
.setTitle(res.getString(R.string.clock_title_bubble))
|
||||
.setId(BubbleClockController.class.getName())
|
||||
.setThumbnail(() -> BitmapFactory.decodeResource(res, R.drawable.bubble_thumbnail))
|
||||
.setPreview(() -> BitmapFactory.decodeResource(res, R.drawable.bubble_preview))
|
||||
.build());
|
||||
mClockInfos.add(ClockInfo.builder()
|
||||
.setName("stretch")
|
||||
.setTitle(res.getString(R.string.clock_title_stretch))
|
||||
.setId(StretchAnalogClockController.class.getName())
|
||||
.setThumbnail(() -> BitmapFactory.decodeResource(res, R.drawable.stretch_thumbnail))
|
||||
.setPreview(() -> BitmapFactory.decodeResource(res, R.drawable.stretch_preview))
|
||||
.build());
|
||||
mClockInfos.add(ClockInfo.builder()
|
||||
.setName("type")
|
||||
.setTitle(res.getString(R.string.clock_title_type))
|
||||
.setId(TypeClockController.class.getName())
|
||||
.setThumbnail(() -> BitmapFactory.decodeResource(res, R.drawable.type_thumbnail))
|
||||
.setPreview(() -> BitmapFactory.decodeResource(res, R.drawable.type_preview))
|
||||
.build());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -101,6 +135,13 @@ public final class ClockManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get information about available clock faces.
|
||||
*/
|
||||
List<ClockInfo> getClockInfos() {
|
||||
return mClockInfos;
|
||||
}
|
||||
|
||||
private void setClockPlugin(ClockPlugin plugin) {
|
||||
for (int i = 0; i < mListeners.size(); i++) {
|
||||
// It probably doesn't make sense to supply the same plugin instances to multiple
|
||||
|
||||
@@ -0,0 +1,185 @@
|
||||
/*
|
||||
* 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.keyguard.clock;
|
||||
|
||||
import android.content.ContentProvider;
|
||||
import android.content.ContentValues;
|
||||
import android.database.Cursor;
|
||||
import android.database.MatrixCursor;
|
||||
import android.graphics.Bitmap;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.os.ParcelFileDescriptor.AutoCloseOutputStream;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.systemui.Dependency;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* Exposes custom clock face options and provides realistic preview images.
|
||||
*
|
||||
* APIs:
|
||||
*
|
||||
* /list_options: List the available clock faces, which has the following columns
|
||||
* name: name of the clock face
|
||||
* title: title of the clock face
|
||||
* id: value used to set the clock face
|
||||
* thumbnail: uri of the thumbnail image, should be /thumbnail/{name}
|
||||
* preview: uri of the preview image, should be /preview/{name}
|
||||
*
|
||||
* /thumbnail/{id}: Opens a file stream for the thumbnail image for clock face {id}.
|
||||
*
|
||||
* /preview/{id}: Opens a file stream for the preview image for clock face {id}.
|
||||
*/
|
||||
public final class ClockOptionsProvider extends ContentProvider {
|
||||
|
||||
private static final String TAG = "ClockOptionsProvider";
|
||||
private static final String KEY_LIST_OPTIONS = "/list_options";
|
||||
private static final String KEY_PREVIEW = "preview";
|
||||
private static final String KEY_THUMBNAIL = "thumbnail";
|
||||
private static final String COLUMN_NAME = "name";
|
||||
private static final String COLUMN_TITLE = "title";
|
||||
private static final String COLUMN_ID = "id";
|
||||
private static final String COLUMN_THUMBNAIL = "thumbnail";
|
||||
private static final String COLUMN_PREVIEW = "preview";
|
||||
private static final String MIME_TYPE_PNG = "image/png";
|
||||
private static final String CONTENT_SCHEME = "content";
|
||||
private static final String AUTHORITY = "com.android.keyguard.clock";
|
||||
|
||||
private final Supplier<List<ClockInfo>> mClocksSupplier;
|
||||
|
||||
public ClockOptionsProvider() {
|
||||
this(() -> Dependency.get(ClockManager.class).getClockInfos());
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
ClockOptionsProvider(Supplier<List<ClockInfo>> clocksSupplier) {
|
||||
mClocksSupplier = clocksSupplier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreate() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType(Uri uri) {
|
||||
List<String> segments = uri.getPathSegments();
|
||||
if (segments.size() > 0 && (KEY_PREVIEW.equals(segments.get(0))
|
||||
|| KEY_THUMBNAIL.equals(segments.get(0)))) {
|
||||
return MIME_TYPE_PNG;
|
||||
}
|
||||
return "vnd.android.cursor.dir/clock_faces";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cursor query(Uri uri, String[] projection, String selection,
|
||||
String[] selectionArgs, String sortOrder) {
|
||||
if (!KEY_LIST_OPTIONS.equals(uri.getPath())) {
|
||||
return null;
|
||||
}
|
||||
MatrixCursor cursor = new MatrixCursor(new String[] {
|
||||
COLUMN_NAME, COLUMN_TITLE, COLUMN_ID, COLUMN_THUMBNAIL, COLUMN_PREVIEW});
|
||||
List<ClockInfo> clocks = mClocksSupplier.get();
|
||||
for (int i = 0; i < clocks.size(); i++) {
|
||||
ClockInfo clock = clocks.get(i);
|
||||
cursor.newRow()
|
||||
.add(COLUMN_NAME, clock.getName())
|
||||
.add(COLUMN_TITLE, clock.getTitle())
|
||||
.add(COLUMN_ID, clock.getId())
|
||||
.add(COLUMN_THUMBNAIL, createThumbnailUri(clock))
|
||||
.add(COLUMN_PREVIEW, createPreviewUri(clock));
|
||||
}
|
||||
return cursor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Uri insert(Uri uri, ContentValues initialValues) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int delete(Uri uri, String selection, String[] selectionArgs) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
|
||||
List<String> segments = uri.getPathSegments();
|
||||
if (segments.size() != 2 || !(KEY_PREVIEW.equals(segments.get(0))
|
||||
|| KEY_THUMBNAIL.equals(segments.get(0)))) {
|
||||
throw new FileNotFoundException("Invalid preview url");
|
||||
}
|
||||
String id = segments.get(1);
|
||||
if (TextUtils.isEmpty(id)) {
|
||||
throw new FileNotFoundException("Invalid preview url, missing id");
|
||||
}
|
||||
ClockInfo clock = null;
|
||||
List<ClockInfo> clocks = mClocksSupplier.get();
|
||||
for (int i = 0; i < clocks.size(); i++) {
|
||||
if (id.equals(clocks.get(i).getId())) {
|
||||
clock = clocks.get(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (clock == null) {
|
||||
throw new FileNotFoundException("Invalid preview url, id not found");
|
||||
}
|
||||
return openPipeHelper(uri, MIME_TYPE_PNG, null, KEY_PREVIEW.equals(segments.get(0))
|
||||
? clock.getPreview() : clock.getThumbnail(), new MyWriter());
|
||||
}
|
||||
|
||||
private Uri createThumbnailUri(ClockInfo clock) {
|
||||
return new Uri.Builder()
|
||||
.scheme(CONTENT_SCHEME)
|
||||
.authority(AUTHORITY)
|
||||
.appendPath(KEY_THUMBNAIL)
|
||||
.appendPath(clock.getId())
|
||||
.build();
|
||||
}
|
||||
|
||||
private Uri createPreviewUri(ClockInfo clock) {
|
||||
return new Uri.Builder()
|
||||
.scheme(CONTENT_SCHEME)
|
||||
.authority(AUTHORITY)
|
||||
.appendPath(KEY_PREVIEW)
|
||||
.appendPath(clock.getId())
|
||||
.build();
|
||||
}
|
||||
|
||||
private static class MyWriter implements ContentProvider.PipeDataWriter<Bitmap> {
|
||||
@Override
|
||||
public void writeDataToPipe(ParcelFileDescriptor output, Uri uri, String mimeType,
|
||||
Bundle opts, Bitmap bitmap) {
|
||||
try (AutoCloseOutputStream os = new AutoCloseOutputStream(output)) {
|
||||
bitmap.compress(Bitmap.CompressFormat.PNG, 100, os);
|
||||
} catch (Exception e) {
|
||||
Log.w(TAG, "fail to write to pipe", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* 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.keyguard.clock;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.test.suitebuilder.annotation.SmallTest;
|
||||
import android.testing.AndroidTestingRunner;
|
||||
import android.testing.TestableLooper.RunWithLooper;
|
||||
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidTestingRunner.class)
|
||||
@RunWithLooper
|
||||
public final class ClockInfoTest extends SysuiTestCase {
|
||||
|
||||
@Mock
|
||||
private Supplier<Bitmap> mMockSupplier;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetName() {
|
||||
final String name = "name";
|
||||
ClockInfo info = ClockInfo.builder().setName(name).build();
|
||||
assertThat(info.getName()).isEqualTo(name);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetTitle() {
|
||||
final String title = "title";
|
||||
ClockInfo info = ClockInfo.builder().setTitle(title).build();
|
||||
assertThat(info.getTitle()).isEqualTo(title);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetId() {
|
||||
final String id = "id";
|
||||
ClockInfo info = ClockInfo.builder().setId(id).build();
|
||||
assertThat(info.getId()).isEqualTo(id);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetThumbnail() {
|
||||
ClockInfo info = ClockInfo.builder().setThumbnail(mMockSupplier).build();
|
||||
info.getThumbnail();
|
||||
verify(mMockSupplier).get();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetPreview() {
|
||||
ClockInfo info = ClockInfo.builder().setPreview(mMockSupplier).build();
|
||||
info.getPreview();
|
||||
verify(mMockSupplier).get();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,189 @@
|
||||
/*
|
||||
* 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.keyguard.clock;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import android.database.Cursor;
|
||||
import android.graphics.Bitmap;
|
||||
import android.net.Uri;
|
||||
import android.test.suitebuilder.annotation.SmallTest;
|
||||
import android.testing.AndroidTestingRunner;
|
||||
import android.testing.TestableLooper.RunWithLooper;
|
||||
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidTestingRunner.class)
|
||||
@RunWithLooper
|
||||
public final class ClockOptionsProviderTest extends SysuiTestCase {
|
||||
|
||||
private static final String CONTENT_SCHEME = "content";
|
||||
private static final String AUTHORITY = "com.android.keyguard.clock";
|
||||
private static final String LIST_OPTIONS = "list_options";
|
||||
private static final String PREVIEW = "preview";
|
||||
private static final String THUMBNAIL = "thumbnail";
|
||||
private static final String MIME_TYPE_LIST_OPTIONS = "vnd.android.cursor.dir/clock_faces";
|
||||
private static final String MIME_TYPE_PNG = "image/png";
|
||||
private static final String NAME_COLUMN = "name";
|
||||
private static final String TITLE_COLUMN = "title";
|
||||
private static final String ID_COLUMN = "id";
|
||||
private static final String PREVIEW_COLUMN = "preview";
|
||||
private static final String THUMBNAIL_COLUMN = "thumbnail";
|
||||
|
||||
private ClockOptionsProvider mProvider;
|
||||
private Supplier<List<ClockInfo>> mMockSupplier;
|
||||
private List<ClockInfo> mClocks;
|
||||
private Uri mListOptionsUri;
|
||||
@Mock
|
||||
private Supplier<Bitmap> mMockBitmapSupplier;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mClocks = new ArrayList<>();
|
||||
mProvider = new ClockOptionsProvider(() -> mClocks);
|
||||
mListOptionsUri = new Uri.Builder()
|
||||
.scheme(CONTENT_SCHEME)
|
||||
.authority(AUTHORITY)
|
||||
.appendPath(LIST_OPTIONS)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetType_listOptions() {
|
||||
Uri uri = new Uri.Builder()
|
||||
.scheme(CONTENT_SCHEME)
|
||||
.authority(AUTHORITY)
|
||||
.appendPath(LIST_OPTIONS)
|
||||
.build();
|
||||
assertThat(mProvider.getType(uri)).isEqualTo(MIME_TYPE_LIST_OPTIONS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetType_preview() {
|
||||
Uri uri = new Uri.Builder()
|
||||
.scheme(CONTENT_SCHEME)
|
||||
.authority(AUTHORITY)
|
||||
.appendPath(PREVIEW)
|
||||
.appendPath("id")
|
||||
.build();
|
||||
assertThat(mProvider.getType(uri)).isEqualTo(MIME_TYPE_PNG);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetType_thumbnail() {
|
||||
Uri uri = new Uri.Builder()
|
||||
.scheme(CONTENT_SCHEME)
|
||||
.authority(AUTHORITY)
|
||||
.appendPath(THUMBNAIL)
|
||||
.appendPath("id")
|
||||
.build();
|
||||
assertThat(mProvider.getType(uri)).isEqualTo(MIME_TYPE_PNG);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testQuery_noClocks() {
|
||||
Cursor cursor = mProvider.query(mListOptionsUri, null, null, null);
|
||||
assertThat(cursor.getCount()).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testQuery_listOptions() {
|
||||
mClocks.add(ClockInfo.builder()
|
||||
.setName("name_a")
|
||||
.setTitle("title_a")
|
||||
.setId("id_a")
|
||||
.build());
|
||||
mClocks.add(ClockInfo.builder()
|
||||
.setName("name_b")
|
||||
.setTitle("title_b")
|
||||
.setId("id_b")
|
||||
.build());
|
||||
Cursor cursor = mProvider.query(mListOptionsUri, null, null, null);
|
||||
assertThat(cursor.getCount()).isEqualTo(2);
|
||||
cursor.moveToFirst();
|
||||
assertThat(cursor.getString(
|
||||
cursor.getColumnIndex(NAME_COLUMN))).isEqualTo("name_a");
|
||||
assertThat(cursor.getString(
|
||||
cursor.getColumnIndex(TITLE_COLUMN))).isEqualTo("title_a");
|
||||
assertThat(cursor.getString(
|
||||
cursor.getColumnIndex(ID_COLUMN))).isEqualTo("id_a");
|
||||
assertThat(cursor.getString(
|
||||
cursor.getColumnIndex(PREVIEW_COLUMN)))
|
||||
.isEqualTo("content://com.android.keyguard.clock/preview/id_a");
|
||||
assertThat(cursor.getString(
|
||||
cursor.getColumnIndex(THUMBNAIL_COLUMN)))
|
||||
.isEqualTo("content://com.android.keyguard.clock/thumbnail/id_a");
|
||||
cursor.moveToNext();
|
||||
assertThat(cursor.getString(
|
||||
cursor.getColumnIndex(NAME_COLUMN))).isEqualTo("name_b");
|
||||
assertThat(cursor.getString(
|
||||
cursor.getColumnIndex(TITLE_COLUMN))).isEqualTo("title_b");
|
||||
assertThat(cursor.getString(
|
||||
cursor.getColumnIndex(ID_COLUMN))).isEqualTo("id_b");
|
||||
assertThat(cursor.getString(
|
||||
cursor.getColumnIndex(PREVIEW_COLUMN)))
|
||||
.isEqualTo("content://com.android.keyguard.clock/preview/id_b");
|
||||
assertThat(cursor.getString(
|
||||
cursor.getColumnIndex(THUMBNAIL_COLUMN)))
|
||||
.isEqualTo("content://com.android.keyguard.clock/thumbnail/id_b");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOpenFile_preview() throws Exception {
|
||||
mClocks.add(ClockInfo.builder()
|
||||
.setId("id")
|
||||
.setPreview(mMockBitmapSupplier)
|
||||
.build());
|
||||
Uri uri = new Uri.Builder()
|
||||
.scheme(CONTENT_SCHEME)
|
||||
.authority(AUTHORITY)
|
||||
.appendPath(PREVIEW)
|
||||
.appendPath("id")
|
||||
.build();
|
||||
mProvider.openFile(uri, "r").close();
|
||||
verify(mMockBitmapSupplier).get();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOpenFile_thumbnail() throws Exception {
|
||||
mClocks.add(ClockInfo.builder()
|
||||
.setId("id")
|
||||
.setThumbnail(mMockBitmapSupplier)
|
||||
.build());
|
||||
Uri uri = new Uri.Builder()
|
||||
.scheme(CONTENT_SCHEME)
|
||||
.authority(AUTHORITY)
|
||||
.appendPath(THUMBNAIL)
|
||||
.appendPath("id")
|
||||
.build();
|
||||
mProvider.openFile(uri, "r").close();
|
||||
verify(mMockBitmapSupplier).get();
|
||||
}
|
||||
}
|
||||