From 21b13e2975180744020b0fb8c150e4a74c45e30c Mon Sep 17 00:00:00 2001 From: linyuh Date: Thu, 8 Feb 2018 10:44:50 -0800 Subject: Show icon and label for a spam number in the new call log. Bug: 73077158 Test: CallLogEntryTextTest, GlidePhotoManagerImplTest, PhoneLookupInfoConsolidatorTest PiperOrigin-RevId: 185017362 Change-Id: I113472482da2213d17a847054272a22249edc578 --- .../glidephotomanager/GlidePhotoManager.java | 33 ++++++ .../GlidePhotoManagerComponent.java | 38 +++++++ .../glidephotomanager/GlidePhotoManagerModule.java | 30 ++++++ .../dialer/glidephotomanager/PhotoInfo.java | 110 +++++++++++++++++++ .../glidephotomanager/impl/AndroidManifest.xml | 18 ++++ .../impl/GlidePhotoManagerImpl.java | 119 +++++++++++++++++++++ .../res/drawable-xxxhdpi/ic_block_black_48dp.png | Bin 0 -> 2532 bytes .../impl/res/drawable/ic_block_grey_48dp.xml | 17 +++ .../impl/res/drawable/ic_report_red_48dp.xml | 36 +++++++ 9 files changed, 401 insertions(+) create mode 100644 java/com/android/dialer/glidephotomanager/GlidePhotoManager.java create mode 100644 java/com/android/dialer/glidephotomanager/GlidePhotoManagerComponent.java create mode 100644 java/com/android/dialer/glidephotomanager/GlidePhotoManagerModule.java create mode 100644 java/com/android/dialer/glidephotomanager/PhotoInfo.java create mode 100644 java/com/android/dialer/glidephotomanager/impl/AndroidManifest.xml create mode 100644 java/com/android/dialer/glidephotomanager/impl/GlidePhotoManagerImpl.java create mode 100644 java/com/android/dialer/glidephotomanager/impl/res/drawable-xxxhdpi/ic_block_black_48dp.png create mode 100644 java/com/android/dialer/glidephotomanager/impl/res/drawable/ic_block_grey_48dp.xml create mode 100644 java/com/android/dialer/glidephotomanager/impl/res/drawable/ic_report_red_48dp.xml (limited to 'java/com/android/dialer/glidephotomanager') diff --git a/java/com/android/dialer/glidephotomanager/GlidePhotoManager.java b/java/com/android/dialer/glidephotomanager/GlidePhotoManager.java new file mode 100644 index 000000000..519a39481 --- /dev/null +++ b/java/com/android/dialer/glidephotomanager/GlidePhotoManager.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2018 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.dialer.glidephotomanager; + +import android.support.annotation.MainThread; +import android.widget.QuickContactBadge; + +/** Class to load photo for call/contacts */ +public interface GlidePhotoManager { + + /** + * Load {@code photoInfo} into the {@code badge}. The loading is performed in the background and a + * placeholder will be used appropriately. {@code badge} must be already attached to an + * activity/fragment, and the load will be automatically canceled if the lifecycle of the activity + * ends. + */ + @MainThread + void loadQuickContactBadge(QuickContactBadge badge, PhotoInfo photoInfo); +} diff --git a/java/com/android/dialer/glidephotomanager/GlidePhotoManagerComponent.java b/java/com/android/dialer/glidephotomanager/GlidePhotoManagerComponent.java new file mode 100644 index 000000000..b4699be54 --- /dev/null +++ b/java/com/android/dialer/glidephotomanager/GlidePhotoManagerComponent.java @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2018 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.dialer.glidephotomanager; + +import android.content.Context; +import com.android.dialer.inject.HasRootComponent; +import dagger.Subcomponent; + +/** Entry point for {@link GlidePhotoManager} */ +@Subcomponent +public abstract class GlidePhotoManagerComponent { + + public abstract GlidePhotoManager glidePhotoManager(); + + public static GlidePhotoManagerComponent get(Context context) { + return ((HasComponent) ((HasRootComponent) context.getApplicationContext()).component()) + .glidePhotoManagerComponent(); + } + + /** Used to refer to the root application component. */ + public interface HasComponent { + GlidePhotoManagerComponent glidePhotoManagerComponent(); + } +} diff --git a/java/com/android/dialer/glidephotomanager/GlidePhotoManagerModule.java b/java/com/android/dialer/glidephotomanager/GlidePhotoManagerModule.java new file mode 100644 index 000000000..79629d69e --- /dev/null +++ b/java/com/android/dialer/glidephotomanager/GlidePhotoManagerModule.java @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2018 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.dialer.glidephotomanager; + +import com.android.dialer.glidephotomanager.impl.GlidePhotoManagerImpl; +import dagger.Binds; +import dagger.Module; +import javax.inject.Singleton; + +/** Module for {@link GlidePhotoManagerComponent} */ +@Module +public abstract class GlidePhotoManagerModule { + @Binds + @Singleton + public abstract GlidePhotoManager bindGlidePhotoManager(GlidePhotoManagerImpl glidePhotoManager); +} diff --git a/java/com/android/dialer/glidephotomanager/PhotoInfo.java b/java/com/android/dialer/glidephotomanager/PhotoInfo.java new file mode 100644 index 000000000..e4dd87152 --- /dev/null +++ b/java/com/android/dialer/glidephotomanager/PhotoInfo.java @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2018 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.dialer.glidephotomanager; + +import android.support.annotation.Nullable; +import com.google.auto.value.AutoValue; + +/** The number information used to create the photo.. */ +@AutoValue +public abstract class PhotoInfo { + + /** The display name of the number */ + @Nullable + public abstract String name(); + + /** The number displayed to the user. */ + @Nullable + public abstract String formattedNumber(); + + /** The URI to the photo */ + @Nullable + public abstract String photoUri(); + + /** Value of {@link android.provider.ContactsContract.CommonDataKinds.Photo#_ID} */ + public abstract long photoId(); + + /** The contacts provider lookup URI for the contact associated with the number */ + @Nullable + public abstract String lookupUri(); + + /** Should a business icon be displayed */ + public abstract boolean isBusiness(); + + /** Should a voicemail icon be displayed */ + public abstract boolean isVoicemail(); + + /** Should a blocked icon be displayed */ + public abstract boolean isBlocked(); + + /** Should a spam icon be displayed */ + public abstract boolean isSpam(); + + /** + * Should the photo be badged as video call. + * + *

Defaults to false. + */ + public abstract boolean isVideo(); + + /** + * Should the result be circularized. + * + *

Defaults to true. + */ + public abstract boolean isCircular(); + + /** Builder for {@link PhotoInfo} */ + @AutoValue.Builder + public abstract static class Builder { + + public abstract Builder setName(@Nullable String name); + + public abstract Builder setFormattedNumber(@Nullable String formattedNumber); + + public abstract Builder setPhotoUri(@Nullable String uri); + + public abstract Builder setPhotoId(long id); + + public abstract Builder setLookupUri(@Nullable String uri); + + public abstract Builder setIsBusiness(boolean isBusiness); + + public abstract Builder setIsVoicemail(boolean isVoicemail); + + public abstract Builder setIsBlocked(boolean isBlocked); + + public abstract Builder setIsSpam(boolean isSpam); + + public abstract Builder setIsVideo(boolean isVideo); + + public abstract Builder setIsCircular(boolean isCircular); + + public abstract PhotoInfo build(); + } + + public static PhotoInfo.Builder builder() { + return new AutoValue_PhotoInfo.Builder() + .setPhotoId(0) + .setIsBusiness(false) + .setIsVoicemail(false) + .setIsBlocked(false) + .setIsSpam(false) + .setIsCircular(true) + .setIsVideo(false); + } +} diff --git a/java/com/android/dialer/glidephotomanager/impl/AndroidManifest.xml b/java/com/android/dialer/glidephotomanager/impl/AndroidManifest.xml new file mode 100644 index 000000000..065c10365 --- /dev/null +++ b/java/com/android/dialer/glidephotomanager/impl/AndroidManifest.xml @@ -0,0 +1,18 @@ + + + \ No newline at end of file diff --git a/java/com/android/dialer/glidephotomanager/impl/GlidePhotoManagerImpl.java b/java/com/android/dialer/glidephotomanager/impl/GlidePhotoManagerImpl.java new file mode 100644 index 000000000..20d379c48 --- /dev/null +++ b/java/com/android/dialer/glidephotomanager/impl/GlidePhotoManagerImpl.java @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2018 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.dialer.glidephotomanager.impl; + +import android.content.ContentUris; +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.net.Uri; +import android.provider.ContactsContract.Data; +import android.support.annotation.MainThread; +import android.support.annotation.Nullable; +import android.telecom.TelecomManager; +import android.text.TextUtils; +import android.widget.QuickContactBadge; +import com.android.dialer.common.Assert; +import com.android.dialer.glide.GlideApp; +import com.android.dialer.glide.GlideRequest; +import com.android.dialer.glide.GlideRequests; +import com.android.dialer.glidephotomanager.GlidePhotoManager; +import com.android.dialer.glidephotomanager.PhotoInfo; +import com.android.dialer.inject.ApplicationContext; +import com.android.dialer.lettertile.LetterTileDrawable; +import javax.inject.Inject; + +/** Implementation of {@link GlidePhotoManager} */ +public class GlidePhotoManagerImpl implements GlidePhotoManager { + private final Context appContext; + + @Inject + public GlidePhotoManagerImpl(@ApplicationContext Context appContext) { + this.appContext = appContext; + } + + @MainThread + @Override + public void loadQuickContactBadge(QuickContactBadge badge, PhotoInfo photoInfo) { + Assert.isMainThread(); + badge.assignContactUri(parseUri(photoInfo.lookupUri())); + badge.setOverlay(null); + LetterTileDrawable defaultDrawable = getDefaultDrawable(photoInfo); + GlideRequest request = + buildRequest(GlideApp.with(badge), photoInfo) + .placeholder(defaultDrawable) // when the photo is still loading. + .fallback(defaultDrawable); // when there's nothing to load. + + if (photoInfo.isCircular()) { + request.circleCrop(); + } + + request.into(badge); + } + + private GlideRequest buildRequest(GlideRequests requestManager, PhotoInfo photoInfo) { + // The spam status takes precedence over whether the number is blocked. + if (photoInfo.isSpam()) { + return requestManager.load(R.drawable.ic_report_red_48dp); + } + if (photoInfo.isBlocked()) { + return requestManager.load(R.drawable.ic_block_grey_48dp); + } + if (!TextUtils.isEmpty(photoInfo.photoUri())) { + return requestManager.load(parseUri(photoInfo.photoUri())); + } + if (photoInfo.photoId() != 0) { + return requestManager.load(ContentUris.withAppendedId(Data.CONTENT_URI, photoInfo.photoId())); + } + // load null to indicate fallback should be used. + return requestManager.load((Object) null); + } + + /** + * Generate the default drawable when photos are not available. Used when the photo is loading or + * no photo is available. + */ + private LetterTileDrawable getDefaultDrawable(PhotoInfo photoInfo) { + LetterTileDrawable letterTileDrawable = new LetterTileDrawable(appContext.getResources()); + String displayName; + String identifier; + if (TextUtils.isEmpty(photoInfo.lookupUri())) { + // Use generic avatar instead of letter for non-contacts. + displayName = null; + identifier = + TextUtils.isEmpty(photoInfo.name()) ? photoInfo.formattedNumber() : photoInfo.name(); + } else { + displayName = photoInfo.name(); + identifier = photoInfo.lookupUri(); + } + letterTileDrawable.setCanonicalDialerLetterTileDetails( + displayName, + identifier, + LetterTileDrawable.SHAPE_CIRCLE, + LetterTileDrawable.getContactTypeFromPrimitives( + photoInfo.isVoicemail(), + false, // TODO(twyen):implement + photoInfo.isBusiness(), + TelecomManager.PRESENTATION_ALLOWED, // TODO(twyen):implement + false)); // TODO(twyen):implement + return letterTileDrawable; + } + + @Nullable + private static Uri parseUri(@Nullable String uri) { + return TextUtils.isEmpty(uri) ? null : Uri.parse(uri); + } +} diff --git a/java/com/android/dialer/glidephotomanager/impl/res/drawable-xxxhdpi/ic_block_black_48dp.png b/java/com/android/dialer/glidephotomanager/impl/res/drawable-xxxhdpi/ic_block_black_48dp.png new file mode 100644 index 000000000..1168bd8d5 Binary files /dev/null and b/java/com/android/dialer/glidephotomanager/impl/res/drawable-xxxhdpi/ic_block_black_48dp.png differ diff --git a/java/com/android/dialer/glidephotomanager/impl/res/drawable/ic_block_grey_48dp.xml b/java/com/android/dialer/glidephotomanager/impl/res/drawable/ic_block_grey_48dp.xml new file mode 100644 index 000000000..42cfa99bd --- /dev/null +++ b/java/com/android/dialer/glidephotomanager/impl/res/drawable/ic_block_grey_48dp.xml @@ -0,0 +1,17 @@ + + \ No newline at end of file diff --git a/java/com/android/dialer/glidephotomanager/impl/res/drawable/ic_report_red_48dp.xml b/java/com/android/dialer/glidephotomanager/impl/res/drawable/ic_report_red_48dp.xml new file mode 100644 index 000000000..8a1ddcd99 --- /dev/null +++ b/java/com/android/dialer/glidephotomanager/impl/res/drawable/ic_report_red_48dp.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + \ No newline at end of file -- cgit v1.2.3