diff options
author | Treehugger Robot <treehugger-gerrit@google.com> | 2018-06-27 23:32:00 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2018-06-27 23:32:00 +0000 |
commit | 2e3e5ff3f2dfd4106b22835c1bf68bf551dcc032 (patch) | |
tree | 859e255dc285185cd6846e8d170e01d81456717e /java | |
parent | 92fb80560200364df45129d365bf683ff3565fb8 (diff) | |
parent | d83c23c9fe6cc4eb2923d8b8b258c5f577b7eef3 (diff) |
Merge changes Ie3a173b7,I2afbd7d9,Id6121d88
* changes:
Request high resolution photo to be downloaded by the sync adapter when a contact is added to the favorites.
UI refersh for status bar.
UI refresh for search bar.
Diffstat (limited to 'java')
9 files changed, 213 insertions, 6 deletions
diff --git a/java/com/android/dialer/contacts/ContactsComponent.java b/java/com/android/dialer/contacts/ContactsComponent.java index 5c4097ace..9c6773716 100644 --- a/java/com/android/dialer/contacts/ContactsComponent.java +++ b/java/com/android/dialer/contacts/ContactsComponent.java @@ -18,7 +18,9 @@ package com.android.dialer.contacts; import android.content.Context; import com.android.dialer.contacts.displaypreference.ContactDisplayPreferences; +import com.android.dialer.contacts.hiresphoto.HighResolutionPhotoRequester; import com.android.dialer.inject.HasRootComponent; +import com.android.dialer.inject.IncludeInDialerRoot; import dagger.Subcomponent; /** Component for contacts related utilities */ @@ -27,12 +29,15 @@ public abstract class ContactsComponent { public abstract ContactDisplayPreferences contactDisplayPreferences(); + public abstract HighResolutionPhotoRequester highResolutionPhotoLoader(); + public static ContactsComponent get(Context context) { return ((HasComponent) ((HasRootComponent) context.getApplicationContext()).component()) .contactsComponent(); } /** Used to refer to the root application component. */ + @IncludeInDialerRoot public interface HasComponent { ContactsComponent contactsComponent(); } diff --git a/java/com/android/dialer/contacts/ContactsModule.java b/java/com/android/dialer/contacts/ContactsModule.java index 979c525eb..73731e544 100644 --- a/java/com/android/dialer/contacts/ContactsModule.java +++ b/java/com/android/dialer/contacts/ContactsModule.java @@ -18,6 +18,8 @@ package com.android.dialer.contacts; import com.android.dialer.contacts.displaypreference.ContactDisplayPreferences; import com.android.dialer.contacts.displaypreference.ContactDisplayPreferencesImpl; +import com.android.dialer.contacts.hiresphoto.HighResolutionPhotoRequester; +import com.android.dialer.contacts.hiresphoto.HighResolutionPhotoRequesterImpl; import com.android.dialer.inject.DialerVariant; import com.android.dialer.inject.InstallIn; import dagger.Binds; @@ -28,5 +30,10 @@ import dagger.Module; @Module public abstract class ContactsModule { @Binds - public abstract ContactDisplayPreferences to(ContactDisplayPreferencesImpl impl); + public abstract ContactDisplayPreferences toContactDisplayPreferencesImpl( + ContactDisplayPreferencesImpl impl); + + @Binds + public abstract HighResolutionPhotoRequester toHighResolutionPhotoRequesterImpl( + HighResolutionPhotoRequesterImpl impl); } diff --git a/java/com/android/dialer/contacts/hiresphoto/HighResolutionPhotoRequester.java b/java/com/android/dialer/contacts/hiresphoto/HighResolutionPhotoRequester.java new file mode 100644 index 000000000..1075ec171 --- /dev/null +++ b/java/com/android/dialer/contacts/hiresphoto/HighResolutionPhotoRequester.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.contacts.hiresphoto; + +import android.net.Uri; +import com.google.common.util.concurrent.ListenableFuture; + +/** + * Requests the contacts sync adapter to load a high resolution photo for the contact, typically + * when we will try to show the contact in a larger view (favorites, incall UI, etc.). If a high + * resolution photo is synced, the uri will be notified. + */ +public interface HighResolutionPhotoRequester { + + ListenableFuture<Void> request(Uri contactUri); +} diff --git a/java/com/android/dialer/contacts/hiresphoto/HighResolutionPhotoRequesterImpl.java b/java/com/android/dialer/contacts/hiresphoto/HighResolutionPhotoRequesterImpl.java new file mode 100644 index 000000000..9201604be --- /dev/null +++ b/java/com/android/dialer/contacts/hiresphoto/HighResolutionPhotoRequesterImpl.java @@ -0,0 +1,137 @@ +/* + * 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.contacts.hiresphoto; + +import android.content.ComponentName; +import android.content.ContentUris; +import android.content.Context; +import android.content.Intent; +import android.database.Cursor; +import android.net.Uri; +import android.provider.ContactsContract.Contacts; +import android.provider.ContactsContract.RawContacts; +import android.support.annotation.VisibleForTesting; +import com.android.dialer.common.LogUtil; +import com.android.dialer.common.concurrent.Annotations.BackgroundExecutor; +import com.android.dialer.common.database.Selection; +import com.android.dialer.inject.ApplicationContext; +import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.ListeningExecutorService; +import java.util.ArrayList; +import java.util.List; +import javax.inject.Inject; + +/** Use the contacts sync adapter to load high resolution photos for a Google account. */ +public class HighResolutionPhotoRequesterImpl implements HighResolutionPhotoRequester { + + private static class RequestFailedException extends Exception { + RequestFailedException(String message) { + super(message); + } + + RequestFailedException(String message, Throwable cause) { + super(message, cause); + } + } + + @VisibleForTesting + static final ComponentName SYNC_HIGH_RESOLUTION_PHOTO_SERVICE = + new ComponentName( + "com.google.android.syncadapters.contacts", + "com.google.android.syncadapters.contacts.SyncHighResPhotoIntentService"); + + private final Context appContext; + private final ListeningExecutorService backgroundExecutor; + + @Inject + HighResolutionPhotoRequesterImpl( + @ApplicationContext Context appContext, + @BackgroundExecutor ListeningExecutorService backgroundExecutor) { + this.appContext = appContext; + this.backgroundExecutor = backgroundExecutor; + } + + @Override + public ListenableFuture<Void> request(Uri contactUri) { + return backgroundExecutor.submit( + () -> { + try { + requestInternal(contactUri); + } catch (RequestFailedException e) { + LogUtil.e("HighResolutionPhotoRequesterImpl.request", "request failed", e); + } + return null; + }); + } + + private void requestInternal(Uri contactUri) throws RequestFailedException { + for (Long rawContactId : getGoogleRawContactIds(getContactId(contactUri))) { + Uri rawContactUri = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId); + Intent intent = new Intent(Intent.ACTION_VIEW); + intent.setComponent(SYNC_HIGH_RESOLUTION_PHOTO_SERVICE); + intent.setDataAndType(rawContactUri, RawContacts.CONTENT_ITEM_TYPE); + intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); + try { + LogUtil.i( + "HighResolutionPhotoRequesterImpl.requestInternal", + "requesting photo for " + rawContactUri); + appContext.startService(intent); + } catch (IllegalStateException | SecurityException e) { + throw new RequestFailedException("unable to start sync adapter", e); + } + } + } + + private long getContactId(Uri contactUri) throws RequestFailedException { + try (Cursor cursor = + appContext + .getContentResolver() + .query(contactUri, new String[] {Contacts._ID}, null, null, null)) { + if (cursor == null || !cursor.moveToFirst()) { + throw new RequestFailedException("cannot get contact ID"); + } + return cursor.getLong(0); + } + } + + private List<Long> getGoogleRawContactIds(long contactId) throws RequestFailedException { + List<Long> result = new ArrayList<>(); + Selection selection = + Selection.column(RawContacts.CONTACT_ID) + .is("=", contactId) + .buildUpon() + .and(Selection.column(RawContacts.ACCOUNT_TYPE).is("=", "com.google")) + .build(); + try (Cursor cursor = + appContext + .getContentResolver() + .query( + RawContacts.CONTENT_URI, + new String[] {RawContacts._ID, RawContacts.ACCOUNT_TYPE}, + selection.getSelection(), + selection.getSelectionArgs(), + null)) { + if (cursor == null) { + throw new RequestFailedException("null cursor from raw contact IDs"); + } + for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) { + result.add(cursor.getLong(0)); + } + } + return result; + } +} diff --git a/java/com/android/dialer/main/impl/toolbar/res/drawable/search_bar_background_rounded_corners.xml b/java/com/android/dialer/main/impl/toolbar/res/drawable/search_bar_background_rounded_corners.xml index 88f5a04ca..491d5d716 100644 --- a/java/com/android/dialer/main/impl/toolbar/res/drawable/search_bar_background_rounded_corners.xml +++ b/java/com/android/dialer/main/impl/toolbar/res/drawable/search_bar_background_rounded_corners.xml @@ -17,5 +17,5 @@ <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <solid android:color="?android:attr/colorBackgroundFloating"/> - <corners android:radius="2dp"/> + <corners android:radius="8dp"/> </shape> diff --git a/java/com/android/dialer/main/impl/toolbar/res/layout/toolbar_layout.xml b/java/com/android/dialer/main/impl/toolbar/res/layout/toolbar_layout.xml index 049cf2ef5..187ece9bb 100644 --- a/java/com/android/dialer/main/impl/toolbar/res/layout/toolbar_layout.xml +++ b/java/com/android/dialer/main/impl/toolbar/res/layout/toolbar_layout.xml @@ -18,7 +18,7 @@ xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="@dimen/expanded_search_bar_height" - android:background="?android:attr/colorPrimary" + android:background="?android:attr/colorBackground" app:contentInsetEnd="0dp" app:contentInsetStart="0dp"> <FrameLayout @@ -61,8 +61,8 @@ android:layout_toEndOf="@+id/search_magnifying_glass" android:layout_toStartOf="@+id/voice_search_button" android:text="@string/dialer_hint_find_contact" - android:textSize="16dp" - style="@style/Dialer.TextAppearance.Secondary"/> + android:textColor="?android:attr/textColorHint" + style="@style/Dialer.TextAppearance.Primary"/> <ImageView android:id="@+id/voice_search_button" diff --git a/java/com/android/dialer/speeddial/loader/SpeedDialUiItemMutator.java b/java/com/android/dialer/speeddial/loader/SpeedDialUiItemMutator.java index b0b83ac32..86d5d37a9 100644 --- a/java/com/android/dialer/speeddial/loader/SpeedDialUiItemMutator.java +++ b/java/com/android/dialer/speeddial/loader/SpeedDialUiItemMutator.java @@ -34,11 +34,14 @@ import android.util.ArraySet; import com.android.dialer.common.Assert; import com.android.dialer.common.LogUtil; import com.android.dialer.common.concurrent.Annotations.BackgroundExecutor; +import com.android.dialer.common.concurrent.DefaultFutureCallback; import com.android.dialer.common.concurrent.DialerExecutor.SuccessListener; import com.android.dialer.common.concurrent.DialerFutureSerializer; import com.android.dialer.common.database.Selection; +import com.android.dialer.contacts.ContactsComponent; import com.android.dialer.contacts.displaypreference.ContactDisplayPreferences; import com.android.dialer.contacts.displaypreference.ContactDisplayPreferences.DisplayOrder; +import com.android.dialer.contacts.hiresphoto.HighResolutionPhotoRequester; import com.android.dialer.duo.DuoComponent; import com.android.dialer.inject.ApplicationContext; import com.android.dialer.speeddial.database.SpeedDialEntry; @@ -49,8 +52,10 @@ import com.android.dialer.util.CallUtil; import com.google.common.base.Optional; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; +import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListeningExecutorService; +import com.google.common.util.concurrent.MoreExecutors; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -86,15 +91,18 @@ public final class SpeedDialUiItemMutator { // Used to ensure that only one refresh flow runs at a time. private final DialerFutureSerializer dialerFutureSerializer = new DialerFutureSerializer(); private final ContactDisplayPreferences contactDisplayPreferences; + private final HighResolutionPhotoRequester highResolutionPhotoRequester; @Inject public SpeedDialUiItemMutator( @ApplicationContext Context appContext, @BackgroundExecutor ListeningExecutorService backgroundExecutor, - ContactDisplayPreferences contactDisplayPreferences) { + ContactDisplayPreferences contactDisplayPreferences, + HighResolutionPhotoRequester highResolutionPhotoRequester) { this.appContext = appContext; this.backgroundExecutor = backgroundExecutor; this.contactDisplayPreferences = contactDisplayPreferences; + this.highResolutionPhotoRequester = highResolutionPhotoRequester; } /** @@ -287,6 +295,7 @@ public final class SpeedDialUiItemMutator { Trace.endSection(); // addStarredContact Trace.beginSection("insertUpdateAndDelete"); + requestHighResolutionPhoto(entriesToInsert); ImmutableMap<SpeedDialEntry, Long> insertedEntriesToIdsMap = db.insertUpdateAndDelete( ImmutableList.copyOf(entriesToInsert), @@ -297,6 +306,20 @@ public final class SpeedDialUiItemMutator { return speedDialUiItemsWithUpdatedIds(speedDialUiItems, insertedEntriesToIdsMap); } + @WorkerThread + private void requestHighResolutionPhoto(List<SpeedDialEntry> newEntries) { + ContactsComponent.get(appContext).highResolutionPhotoLoader(); + for (SpeedDialEntry entry : newEntries) { + Uri uri; + uri = Contacts.getLookupUri(entry.contactId(), entry.lookupKey()); + + Futures.addCallback( + highResolutionPhotoRequester.request(uri), + new DefaultFutureCallback<>(), + MoreExecutors.directExecutor()); + } + } + /** * Since newly starred contacts sometimes aren't in the SpeedDialEntry database, we couldn't set * their ids when we created our initial list of {@link SpeedDialUiItem speedDialUiItems}. Now diff --git a/java/com/android/dialer/theme/base/res/values/theme_dialer_dark.xml b/java/com/android/dialer/theme/base/res/values/theme_dialer_dark.xml index 142bb897b..d03a96bc4 100644 --- a/java/com/android/dialer/theme/base/res/values/theme_dialer_dark.xml +++ b/java/com/android/dialer/theme/base/res/values/theme_dialer_dark.xml @@ -32,6 +32,8 @@ <!-- Activities and Applications should inherit from one of the themes above. --> <style name="Dialer.Dark.ThemeBase"> + <item name="android:statusBarColor">@color/google_grey_900</item> + <!-- These values should be used to color all backgrounds. --> <item name="android:colorBackground">@color/google_grey_900</item> <item name="android:colorBackgroundFloating">@color/google_grey_800</item> diff --git a/java/com/android/dialer/theme/base/res/values/theme_dialer_light.xml b/java/com/android/dialer/theme/base/res/values/theme_dialer_light.xml index e3eefe69a..8aa87dfdb 100644 --- a/java/com/android/dialer/theme/base/res/values/theme_dialer_light.xml +++ b/java/com/android/dialer/theme/base/res/values/theme_dialer_light.xml @@ -38,6 +38,9 @@ <!-- Activities and Applications should inherit from one of the themes above. --> <style name="Dialer.ThemeBase"> + <item name="android:windowLightStatusBar">true</item> + <item name="android:statusBarColor">@android:color/white</item> + <!-- These values should be used to color all backgrounds. --> <item name="android:colorBackground">@android:color/white</item> <item name="android:colorBackgroundFloating">@android:color/white</item> |