diff options
31 files changed, 472 insertions, 155 deletions
diff --git a/java/com/android/dialer/app/calllog/CallLogAdapter.java b/java/com/android/dialer/app/calllog/CallLogAdapter.java index f5474eec6..485683b09 100644 --- a/java/com/android/dialer/app/calllog/CallLogAdapter.java +++ b/java/com/android/dialer/app/calllog/CallLogAdapter.java @@ -100,6 +100,8 @@ import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber; import java.util.ArrayList; import java.util.Map; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; /** Adapter class to fill in data for the Call Log. */ public class CallLogAdapter extends GroupingListAdapter @@ -158,9 +160,12 @@ public class CallLogAdapter extends GroupingListAdapter /** * Maps a raw input number to match info. We only log one MatchInfo per raw input number to reduce * the amount of data logged. + * + * <p>Note that this has to be a {@link ConcurrentMap} as the match info for each row in the UI is + * loaded in a background thread spawned when the ViewHolder is bound. */ - private final Map<String, ContactsProviderMatchInfo> contactsProviderMatchInfos = - new ArrayMap<>(); + private final ConcurrentMap<String, ContactsProviderMatchInfo> contactsProviderMatchInfos = + new ConcurrentHashMap<>(); private final ActionMode.Callback actionModeCallback = new ActionMode.Callback() { @@ -1464,6 +1469,7 @@ public class CallLogAdapter extends GroupingListAdapter notifyDataSetChanged(); } + @WorkerThread private void logCp2Metrics(PhoneCallDetails details, ContactInfo contactInfo) { if (details == null) { return; diff --git a/java/com/android/dialer/calllog/CallLogCacheUpdater.java b/java/com/android/dialer/calllog/CallLogCacheUpdater.java index a7b2b3d0d..b3130e964 100644 --- a/java/com/android/dialer/calllog/CallLogCacheUpdater.java +++ b/java/com/android/dialer/calllog/CallLogCacheUpdater.java @@ -25,6 +25,7 @@ import android.os.RemoteException; import android.provider.CallLog; import android.provider.CallLog.Calls; import android.provider.ContactsContract.CommonDataKinds.Phone; +import android.support.annotation.VisibleForTesting; import com.android.dialer.DialerPhoneNumber; import com.android.dialer.NumberAttributes; import com.android.dialer.calllog.database.contract.AnnotatedCallLogContract.AnnotatedCallLog; @@ -33,6 +34,7 @@ import com.android.dialer.common.LogUtil; import com.android.dialer.common.concurrent.Annotations.BackgroundExecutor; import com.android.dialer.inject.ApplicationContext; import com.android.dialer.protos.ProtoParsers; +import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListeningExecutorService; import java.util.ArrayList; @@ -49,13 +51,23 @@ public final class CallLogCacheUpdater { private final Context appContext; private final ListeningExecutorService backgroundExecutor; + private final CallLogState callLogState; + + /** + * Maximum numbers of operations the updater can do. Each transaction to the system call log will + * trigger a call log refresh, so the updater can only do a single batch. If there are more + * operations it will be truncated. Under normal circumstances there will only be 1 operation + */ + @VisibleForTesting static final int CACHE_UPDATE_LIMIT = 100; @Inject CallLogCacheUpdater( @ApplicationContext Context appContext, - @BackgroundExecutor ListeningExecutorService backgroundExecutor) { + @BackgroundExecutor ListeningExecutorService backgroundExecutor, + CallLogState callLogState) { this.appContext = appContext; this.backgroundExecutor = backgroundExecutor; + this.callLogState = callLogState; } /** @@ -66,17 +78,27 @@ public final class CallLogCacheUpdater { * has changed */ public ListenableFuture<Void> updateCache(CallLogMutations mutations) { - return backgroundExecutor.submit( - () -> { + return Futures.transform( + callLogState.isBuilt(), + isBuilt -> { + if (!isBuilt) { + // Initial build might need to update 1000 caches, which may overflow the batch + // operation limit. The initial data was already built with the cache, there's no need + // to update it. + LogUtil.i("CallLogCacheUpdater.updateCache", "not updating cache for initial build"); + return null; + } updateCacheInternal(mutations); return null; - }); + }, + backgroundExecutor); } private void updateCacheInternal(CallLogMutations mutations) { ArrayList<ContentProviderOperation> operations = new ArrayList<>(); Stream.concat( mutations.getInserts().entrySet().stream(), mutations.getUpdates().entrySet().stream()) + .limit(CACHE_UPDATE_LIMIT) .forEach( entry -> { ContentValues values = entry.getValue(); diff --git a/java/com/android/dialer/calllog/database/Coalescer.java b/java/com/android/dialer/calllog/database/Coalescer.java index 2ad9f9a97..fd751e767 100644 --- a/java/com/android/dialer/calllog/database/Coalescer.java +++ b/java/com/android/dialer/calllog/database/Coalescer.java @@ -16,6 +16,7 @@ package com.android.dialer.calllog.database; import android.database.Cursor; +import android.database.StaleDataException; import android.provider.CallLog.Calls; import android.support.annotation.NonNull; import android.support.annotation.WorkerThread; @@ -85,34 +86,72 @@ public class Coalescer { @WorkerThread @NonNull private ImmutableList<CoalescedRow> coalesceInternal( - Cursor allAnnotatedCallLogRowsSortedByTimestampDesc) { + Cursor allAnnotatedCallLogRowsSortedByTimestampDesc) throws ExpectedCoalescerException { Assert.isWorkerThread(); - if (!allAnnotatedCallLogRowsSortedByTimestampDesc.moveToFirst()) { - return ImmutableList.of(); - } - ImmutableList.Builder<CoalescedRow> coalescedRowListBuilder = new ImmutableList.Builder<>(); - RowCombiner rowCombiner = new RowCombiner(allAnnotatedCallLogRowsSortedByTimestampDesc); - rowCombiner.startNewGroup(); + try { + if (!allAnnotatedCallLogRowsSortedByTimestampDesc.moveToFirst()) { + return ImmutableList.of(); + } - long coalescedRowId = 0; - do { - boolean isRowMerged = rowCombiner.mergeRow(allAnnotatedCallLogRowsSortedByTimestampDesc); + RowCombiner rowCombiner = new RowCombiner(allAnnotatedCallLogRowsSortedByTimestampDesc); + rowCombiner.startNewGroup(); - if (isRowMerged) { - allAnnotatedCallLogRowsSortedByTimestampDesc.moveToNext(); - } + long coalescedRowId = 0; + do { + boolean isRowMerged = rowCombiner.mergeRow(allAnnotatedCallLogRowsSortedByTimestampDesc); + + if (isRowMerged) { + allAnnotatedCallLogRowsSortedByTimestampDesc.moveToNext(); + } + + if (!isRowMerged || allAnnotatedCallLogRowsSortedByTimestampDesc.isAfterLast()) { + coalescedRowListBuilder.add( + rowCombiner.combine().toBuilder().setId(coalescedRowId++).build()); + rowCombiner.startNewGroup(); + } + } while (!allAnnotatedCallLogRowsSortedByTimestampDesc.isAfterLast()); + + return coalescedRowListBuilder.build(); - if (!isRowMerged || allAnnotatedCallLogRowsSortedByTimestampDesc.isAfterLast()) { - coalescedRowListBuilder.add( - rowCombiner.combine().toBuilder().setId(coalescedRowId++).build()); - rowCombiner.startNewGroup(); + } catch (Exception exception) { + // Coalescing can fail if cursor "allAnnotatedCallLogRowsSortedByTimestampDesc" is closed by + // its loader while the work is still in progress. + // + // This can happen when the loader restarts and finishes loading data before the coalescing + // work is completed. + // + // This kind of failure doesn't have to crash the app as coalescing will be restarted on the + // latest data obtained by the loader. Therefore, we inspect the exception here and throw an + // ExpectedCoalescerException if it is the case described above. + // + // The type of expected exception depends on whether AbstractWindowedCursor#checkPosition() is + // called when the cursor is closed. + // (1) If it is called before the cursor is closed, we will get IllegalStateException thrown + // by SQLiteClosable when it attempts to acquire a reference to the database. + // (2) Otherwise, we will get StaleDataException thrown by AbstractWindowedCursor's + // checkPosition() method. + // + // Note that it would be more accurate to inspect the stack trace to locate the origin of the + // exception. However, according to the documentation on Throwable#getStackTrace, "some + // virtual machines may, under some circumstances, omit one or more stack frames from the + // stack trace". "In the extreme case, a virtual machine that has no stack trace information + // concerning this throwable is permitted to return a zero-length array from this method." + // Therefore, the best we can do is to inspect the message in the exception. + // TODO(linyuh): try to avoid the expected failure. + String message = exception.getMessage(); + if (message != null + && ((exception instanceof StaleDataException + && message.startsWith("Attempting to access a closed CursorWindow")) + || (exception instanceof IllegalStateException + && message.startsWith("attempt to re-open an already-closed object")))) { + throw new ExpectedCoalescerException(exception); } - } while (!allAnnotatedCallLogRowsSortedByTimestampDesc.isAfterLast()); - return coalescedRowListBuilder.build(); + throw exception; + } } /** Combines rows from {@link AnnotatedCallLog} into a {@link CoalescedRow}. */ @@ -337,4 +376,11 @@ public class Coalescer { return dialerPhoneNumberUtil.isMatch(groupPhoneNumber, rowPhoneNumber); } } + + /** A checked exception thrown when expected failure happens when coalescing is in progress. */ + public static final class ExpectedCoalescerException extends Exception { + ExpectedCoalescerException(Throwable throwable) { + super("Expected coalescing exception", throwable); + } + } } diff --git a/java/com/android/dialer/calllog/ui/NewCallLogFragment.java b/java/com/android/dialer/calllog/ui/NewCallLogFragment.java index 4141fe723..5e72a1af3 100644 --- a/java/com/android/dialer/calllog/ui/NewCallLogFragment.java +++ b/java/com/android/dialer/calllog/ui/NewCallLogFragment.java @@ -17,7 +17,6 @@ package com.android.dialer.calllog.ui; import android.app.Activity; import android.database.Cursor; -import android.database.StaleDataException; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.annotation.VisibleForTesting; @@ -34,6 +33,7 @@ import android.view.ViewGroup; import com.android.dialer.calllog.CallLogComponent; import com.android.dialer.calllog.RefreshAnnotatedCallLogReceiver; import com.android.dialer.calllog.database.CallLogDatabaseComponent; +import com.android.dialer.calllog.database.Coalescer; import com.android.dialer.calllog.model.CoalescedRow; import com.android.dialer.common.Assert; import com.android.dialer.common.LogUtil; @@ -337,16 +337,13 @@ public final class NewCallLogFragment extends Fragment implements LoaderCallback } }, throwable -> { - if (throwable instanceof StaleDataException) { - // Coalescing can fail if the cursor passed to Coalescer is closed by the loader while - // the work is still in progress. - // This can happen when the loader restarts and finishes loading data before the - // coalescing work is completed. - // This failure doesn't need to be thrown as coalescing will be restarted on the latest - // data obtained by the loader. - // TODO(linyuh): Also throw an exception if the failure above can be avoided. - LogUtil.e("NewCallLogFragment.onLoadFinished", "coalescing failed", throwable); - } else { + // Coalescing can fail if the cursor passed to Coalescer is closed by the loader while + // the work is still in progress. + // This can happen when the loader restarts and finishes loading data before the + // coalescing work is completed. + // This failure is identified by ExpectedCoalescerException and doesn't need to be + // thrown as coalescing will be restarted on the latest data obtained by the loader. + if (!(throwable instanceof Coalescer.ExpectedCoalescerException)) { throw new AssertionError(throwable); } }); diff --git a/java/com/android/dialer/main/impl/OldMainActivityPeer.java b/java/com/android/dialer/main/impl/OldMainActivityPeer.java index d790c6814..73bb4f81a 100644 --- a/java/com/android/dialer/main/impl/OldMainActivityPeer.java +++ b/java/com/android/dialer/main/impl/OldMainActivityPeer.java @@ -51,6 +51,7 @@ import android.text.method.LinkMovementMethod; import android.view.ActionMode; import android.view.DragEvent; import android.view.View; +import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; import com.android.contacts.common.list.OnPhoneNumberPickerActionListener; @@ -334,7 +335,12 @@ public class OldMainActivityPeer implements MainActivityPeer, FragmentUtilListen activity.findViewById(R.id.remove_view), activity.findViewById(R.id.search_view_container), toolbar); - speedDialFragmentHost = new MainSpeedDialFragmentHost(toolbar); + speedDialFragmentHost = + new MainSpeedDialFragmentHost( + toolbar, + activity.findViewById(R.id.root_layout), + activity.findViewById(R.id.coordinator_layout), + activity.findViewById(R.id.fragment_container)); lastTabController = new LastTabController(activity, bottomNav, showVoicemailTab); @@ -1255,15 +1261,32 @@ public class OldMainActivityPeer implements MainActivityPeer, FragmentUtilListen private static final class MainSpeedDialFragmentHost implements SpeedDialFragment.HostInterface { private final MainToolbar toolbar; - - MainSpeedDialFragmentHost(MainToolbar toolbar) { + private final ViewGroup rootLayout; + private final ViewGroup coordinatorLayout; + private final ViewGroup fragmentContainer; + + MainSpeedDialFragmentHost( + MainToolbar toolbar, + ViewGroup rootLayout, + ViewGroup coordinatorLayout, + ViewGroup fragmentContainer) { this.toolbar = toolbar; + this.rootLayout = rootLayout; + this.coordinatorLayout = coordinatorLayout; + this.fragmentContainer = fragmentContainer; } @Override public void setHasFrequents(boolean hasFrequents) { toolbar.showClearFrequents(hasFrequents); } + + @Override + public void dragFavorite(boolean start) { + rootLayout.setClipChildren(!start); + coordinatorLayout.setClipChildren(!start); + fragmentContainer.setClipChildren(!start); + } } /** diff --git a/java/com/android/dialer/main/impl/bottomnav/BottomNavItem.java b/java/com/android/dialer/main/impl/bottomnav/BottomNavItem.java index 4794b8823..48cfc8160 100644 --- a/java/com/android/dialer/main/impl/bottomnav/BottomNavItem.java +++ b/java/com/android/dialer/main/impl/bottomnav/BottomNavItem.java @@ -20,20 +20,18 @@ import android.content.Context; import android.content.res.ColorStateList; import android.support.annotation.DrawableRes; import android.support.annotation.Nullable; -import android.support.annotation.Px; import android.support.annotation.StringRes; import android.util.AttributeSet; import android.view.View; -import android.widget.FrameLayout; import android.widget.ImageView; -import android.widget.LinearLayout; +import android.widget.RelativeLayout; import android.widget.TextView; import com.android.dialer.common.Assert; import com.android.dialer.configprovider.ConfigProviderComponent; import com.android.dialer.theme.base.ThemeComponent; /** Navigation item in a bottom nav. */ -final class BottomNavItem extends LinearLayout { +final class BottomNavItem extends RelativeLayout { private ImageView image; private TextView text; @@ -57,7 +55,7 @@ final class BottomNavItem extends LinearLayout { int colorId = selected ? ThemeComponent.get(getContext()).theme().getColorPrimary() - : ThemeComponent.get(getContext()).theme().getTextColorSecondary(); + : ThemeComponent.get(getContext()).theme().getColorIcon(); image.setImageTintList(ColorStateList.valueOf(colorId)); text.setTextColor(colorId); } @@ -87,20 +85,6 @@ final class BottomNavItem extends LinearLayout { } notificationBadge.setVisibility(View.VISIBLE); notificationBadge.setText(countString); - - @Px int margin; - if (countString.length() == 1) { - margin = getContext().getResources().getDimensionPixelSize(R.dimen.badge_margin_length_1); - } else if (countString.length() == 2) { - margin = getContext().getResources().getDimensionPixelSize(R.dimen.badge_margin_length_2); - } else { - margin = getContext().getResources().getDimensionPixelSize(R.dimen.badge_margin_length_3); - } - - FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) image.getLayoutParams(); - params.setMarginStart(margin); - params.setMarginEnd(margin); - image.setLayoutParams(params); } } } diff --git a/java/com/android/dialer/main/impl/bottomnav/res/drawable/notification_badge.xml b/java/com/android/dialer/main/impl/bottomnav/res/drawable/notification_badge.xml index 65bc8f9b4..e02d7c441 100644 --- a/java/com/android/dialer/main/impl/bottomnav/res/drawable/notification_badge.xml +++ b/java/com/android/dialer/main/impl/bottomnav/res/drawable/notification_badge.xml @@ -16,8 +16,6 @@ --> <shape xmlns:android="http://schemas.android.com/apk/res/android" - android:shape="rectangle"> - <solid android:color="?android:attr/colorPrimary"/> - <corners android:radius="20dp"/> - <stroke android:color="?android:attr/colorBackgroundFloating" android:width="2dp"/> + android:shape="oval"> + <solid android:color="@color/dialer_red"/> </shape>
\ No newline at end of file diff --git a/java/com/android/dialer/main/impl/bottomnav/res/layout/bottom_nav_item.xml b/java/com/android/dialer/main/impl/bottomnav/res/layout/bottom_nav_item.xml index 02874a9d8..8c0705fe0 100644 --- a/java/com/android/dialer/main/impl/bottomnav/res/layout/bottom_nav_item.xml +++ b/java/com/android/dialer/main/impl/bottomnav/res/layout/bottom_nav_item.xml @@ -16,49 +16,41 @@ --> <com.android.dialer.main.impl.bottomnav.BottomNavItem xmlns:android="http://schemas.android.com/apk/res/android" - android:orientation="vertical" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:minWidth="80dp" + android:background="?android:attr/selectableItemBackgroundBorderless" android:minHeight="56dp" - android:gravity="center" - android:background="?android:attr/selectableItemBackgroundBorderless"> + android:minWidth="80dp"> - <FrameLayout - android:layout_width="wrap_content" - android:layout_height="wrap_content"> - - <ImageView - android:id="@+id/bottom_nav_item_image" - android:layout_width="24dp" - android:layout_height="24dp" - android:layout_marginTop="8dp"/> - - <TextView - android:id="@+id/notification_badge" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="top|end" - android:layout_marginTop="2dp" - android:paddingStart="6dp" - android:paddingEnd="6dp" - android:paddingBottom="1dp" - android:minHeight="20dp" - android:minWidth="20dp" - android:gravity="center" - android:textSize="12sp" - android:textColor="?android:attr/textColorPrimaryInverse" - android:background="@drawable/notification_badge" - android:fontFamily="sans-serif-medium" - android:visibility="invisible"/> - </FrameLayout> + <ImageView + android:id="@+id/bottom_nav_item_image" + android:layout_width="24dp" + android:layout_height="24dp" + android:layout_marginTop="8dp" + android:layout_alignParentTop="true" + android:layout_centerHorizontal="true"/> <TextView + android:id="@+id/notification_badge" + style="@style/Dialer.TextAppearance.OVERLINE" + android:layout_width="16dp" + android:layout_height="16dp" + android:layout_marginTop="2dp" + android:layout_marginStart="-8dp" + android:layout_alignParentTop="true" + android:layout_toEndOf="@id/bottom_nav_item_image" + android:background="@drawable/notification_badge" + android:gravity="center" + android:textColor="?android:attr/colorBackgroundFloating" + android:textSize="11dp" + android:visibility="invisible"/> + <TextView android:id="@+id/bottom_nav_item_text" + style="@style/Dialer.TextAppearance.SubHeader2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="8dp" - android:gravity="center_horizontal" - android:textSize="12sp" - style="@style/Dialer.TextAppearance.Secondary"/> + android:layout_below="@id/bottom_nav_item_image" + android:layout_centerHorizontal="true" + android:gravity="center_horizontal"/> </com.android.dialer.main.impl.bottomnav.BottomNavItem>
\ No newline at end of file diff --git a/java/com/android/dialer/main/impl/bottomnav/res/values/dimens.xml b/java/com/android/dialer/main/impl/bottomnav/res/values/dimens.xml deleted file mode 100644 index 8fd376bda..000000000 --- a/java/com/android/dialer/main/impl/bottomnav/res/values/dimens.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - ~ 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 - --> -<resources> - <dimen name="badge_margin_length_1">10dp</dimen> - <dimen name="badge_margin_length_2">14dp</dimen> - <dimen name="badge_margin_length_3">22dp</dimen> -</resources>
\ No newline at end of file diff --git a/java/com/android/dialer/main/impl/res/layout/main_activity.xml b/java/com/android/dialer/main/impl/res/layout/main_activity.xml index 5cb457ec9..5fd9bed7b 100644 --- a/java/com/android/dialer/main/impl/res/layout/main_activity.xml +++ b/java/com/android/dialer/main/impl/res/layout/main_activity.xml @@ -19,9 +19,7 @@ xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/root_layout" android:layout_width="match_parent" - android:layout_height="match_parent" - android:clipChildren="false" - android:clipToPadding="false"> + android:layout_height="match_parent"> <!-- MainToolbar --> <include @@ -35,17 +33,13 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:layout_below="@+id/toolbar" - android:layout_above="@+id/bottom_nav_bar" - android:clipChildren="false" - android:clipToPadding="false"> + android:layout_above="@+id/bottom_nav_bar"> <!-- Holds SpeedDial, Call Log, Contacts, Voicemail and Search fragments --> <FrameLayout android:id="@+id/fragment_container" android:layout_width="match_parent" - android:layout_height="match_parent" - android:clipChildren="false" - android:clipToPadding="false"/> + android:layout_height="match_parent"/> <FrameLayout android:id="@+id/search_fragment_container" @@ -64,7 +58,7 @@ android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_margin="16dp" + android:layout_margin="24dp" android:layout_gravity="end|bottom" android:src="@drawable/quantum_ic_dialpad_white_24" android:contentDescription="@string/dialpad_button_content_description" @@ -102,4 +96,4 @@ android:importantForAccessibility="no" android:visibility="gone"/> </FrameLayout> -</RelativeLayout>
\ No newline at end of file +</RelativeLayout> diff --git a/java/com/android/dialer/main/impl/toolbar/res/layout/expanded_search_bar.xml b/java/com/android/dialer/main/impl/toolbar/res/layout/expanded_search_bar.xml index e5b72f233..9ae884d8b 100644 --- a/java/com/android/dialer/main/impl/toolbar/res/layout/expanded_search_bar.xml +++ b/java/com/android/dialer/main/impl/toolbar/res/layout/expanded_search_bar.xml @@ -29,7 +29,7 @@ android:background="?attr/selectableItemBackgroundBorderless" android:contentDescription="@string/action_menu_back_from_search" android:src="@drawable/quantum_ic_arrow_back_vd_theme_24" - android:tint="?android:attr/colorPrimary"/> + android:tint="?colorIcon"/> <EditText android:id="@+id/search_view" @@ -45,10 +45,9 @@ android:inputType="textFilter" android:maxLines="1" android:hint="@string/dialer_hint_find_contact" - android:textColor="?android:attr/textColorSecondary" android:textColorHint="?android:attr/textColorHint" android:textCursorDrawable="@drawable/custom_cursor" - android:textSize="16sp"/> + style="@style/Dialer.TextAppearance.Primary"/> <ImageView android:id="@+id/search_clear_button" diff --git a/java/com/android/dialer/searchfragment/common/res/layout/search_contact_row.xml b/java/com/android/dialer/searchfragment/common/res/layout/search_contact_row.xml index 4f8e305fe..08d2baade 100644 --- a/java/com/android/dialer/searchfragment/common/res/layout/search_contact_row.xml +++ b/java/com/android/dialer/searchfragment/common/res/layout/search_contact_row.xml @@ -19,8 +19,8 @@ android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="@dimen/search_row_height" - android:paddingStart="8dp" - android:paddingEnd="8dp" + android:paddingStart="16dp" + android:paddingEnd="16dp" android:background="?android:attr/selectableItemBackground"> <QuickContactBadge @@ -44,7 +44,6 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center_vertical|start" - android:fontFamily="sans-serif" style="@style/Dialer.TextAppearance.Primary"/> <com.android.dialer.widget.BidiTextView @@ -52,7 +51,6 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center_vertical|start" - android:fontFamily="sans-serif" style="@style/Dialer.TextAppearance.Secondary"/> </LinearLayout> diff --git a/java/com/android/dialer/searchfragment/list/NewSearchFragment.java b/java/com/android/dialer/searchfragment/list/NewSearchFragment.java index 65ce87340..809f91775 100644 --- a/java/com/android/dialer/searchfragment/list/NewSearchFragment.java +++ b/java/com/android/dialer/searchfragment/list/NewSearchFragment.java @@ -121,11 +121,23 @@ public final class NewSearchFragment extends Fragment // the contacts in them). private final List<Directory> directories = new ArrayList<>(); private final Runnable loaderCp2ContactsRunnable = - () -> getLoaderManager().restartLoader(CONTACTS_LOADER_ID, null, this); + () -> { + if (getHost() != null) { + getLoaderManager().restartLoader(CONTACTS_LOADER_ID, null, this); + } + }; private final Runnable loadNearbyPlacesRunnable = - () -> getLoaderManager().restartLoader(NEARBY_PLACES_LOADER_ID, null, this); + () -> { + if (getHost() != null) { + getLoaderManager().restartLoader(NEARBY_PLACES_LOADER_ID, null, this); + } + }; private final Runnable loadDirectoryContactsRunnable = - () -> getLoaderManager().restartLoader(DIRECTORY_CONTACTS_LOADER_ID, null, this); + () -> { + if (getHost() != null) { + getLoaderManager().restartLoader(DIRECTORY_CONTACTS_LOADER_ID, null, this); + } + }; private final Runnable capabilitiesUpdatedRunnable = () -> adapter.notifyDataSetChanged(); private Runnable updatePositionRunnable; diff --git a/java/com/android/dialer/searchfragment/list/res/layout/header_layout.xml b/java/com/android/dialer/searchfragment/list/res/layout/header_layout.xml index ff59206ad..16f3701c6 100644 --- a/java/com/android/dialer/searchfragment/list/res/layout/header_layout.xml +++ b/java/com/android/dialer/searchfragment/list/res/layout/header_layout.xml @@ -27,5 +27,5 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" - style="@style/Dialer.TextAppearance.Secondary.Ellipsize"/> + style="@style/Dialer.TextAppearance.OVERLINE.Ellipsize"/> </FrameLayout> diff --git a/java/com/android/dialer/speeddial/SpeedDialAdapter.java b/java/com/android/dialer/speeddial/SpeedDialAdapter.java index ff52a0745..4a48b6504 100644 --- a/java/com/android/dialer/speeddial/SpeedDialAdapter.java +++ b/java/com/android/dialer/speeddial/SpeedDialAdapter.java @@ -34,6 +34,7 @@ import android.widget.FrameLayout; import com.android.dialer.common.Assert; import com.android.dialer.speeddial.FavoritesViewHolder.FavoriteContactsListener; import com.android.dialer.speeddial.HeaderViewHolder.SpeedDialHeaderListener; +import com.android.dialer.speeddial.SpeedDialFragment.HostInterface; import com.android.dialer.speeddial.SuggestionViewHolder.SuggestedContactsListener; import com.android.dialer.speeddial.draghelper.SpeedDialItemTouchHelperCallback.ItemTouchHelperAdapter; import com.android.dialer.speeddial.loader.SpeedDialUiItem; @@ -81,6 +82,7 @@ public final class SpeedDialAdapter extends RecyclerView.Adapter<RecyclerView.Vi private final FavoriteContactsListener favoritesListener; private final SuggestedContactsListener suggestedListener; private final SpeedDialHeaderListener headerListener; + private final HostInterface hostInterface; private final Map<Integer, Integer> positionToRowTypeMap = new ArrayMap<>(); private List<SpeedDialUiItem> speedDialUiItems; @@ -95,11 +97,13 @@ public final class SpeedDialAdapter extends RecyclerView.Adapter<RecyclerView.Vi Context context, FavoriteContactsListener favoritesListener, SuggestedContactsListener suggestedListener, - SpeedDialHeaderListener headerListener) { + SpeedDialHeaderListener headerListener, + HostInterface hostInterface) { this.context = context; this.favoritesListener = favoritesListener; this.suggestedListener = suggestedListener; this.headerListener = headerListener; + this.hostInterface = hostInterface; } @Override @@ -255,6 +259,7 @@ public final class SpeedDialAdapter extends RecyclerView.Adapter<RecyclerView.Vi if (viewHolder != null) { draggingFavoritesViewHolder = (FavoritesViewHolder) viewHolder; draggingFavoritesViewHolder.onSelectedChanged(true); + hostInterface.dragFavorite(true); removeViewHolder.show(); } break; @@ -263,6 +268,7 @@ public final class SpeedDialAdapter extends RecyclerView.Adapter<RecyclerView.Vi if (draggingFavoritesViewHolder != null) { draggingFavoritesViewHolder.onSelectedChanged(false); draggingFavoritesViewHolder = null; + hostInterface.dragFavorite(false); removeViewHolder.hide(); } break; diff --git a/java/com/android/dialer/speeddial/SpeedDialFragment.java b/java/com/android/dialer/speeddial/SpeedDialFragment.java index a958d443a..d4e7a76fa 100644 --- a/java/com/android/dialer/speeddial/SpeedDialFragment.java +++ b/java/com/android/dialer/speeddial/SpeedDialFragment.java @@ -156,7 +156,12 @@ public class SpeedDialFragment extends Fragment { new UpdateSpeedDialAdapterListener(), speedDialLoaderListener); adapter = - new SpeedDialAdapter(getContext(), favoritesListener, suggestedListener, headerListener); + new SpeedDialAdapter( + getContext(), + favoritesListener, + suggestedListener, + headerListener, + FragmentUtils.getParentUnsafe(this, HostInterface.class)); layoutManager.setSpanSizeLookup(adapter.getSpanSizeLookup()); RecyclerView recyclerView = rootLayout.findViewById(R.id.speed_dial_recycler_view); recyclerView.setLayoutManager(layoutManager); @@ -653,5 +658,7 @@ public class SpeedDialFragment extends Fragment { public interface HostInterface { void setHasFrequents(boolean hasFrequents); + + void dragFavorite(boolean start); } } diff --git a/java/com/android/dialer/speeddial/res/layout/fragment_speed_dial.xml b/java/com/android/dialer/speeddial/res/layout/fragment_speed_dial.xml index 472f9e951..e79bc6b2f 100644 --- a/java/com/android/dialer/speeddial/res/layout/fragment_speed_dial.xml +++ b/java/com/android/dialer/speeddial/res/layout/fragment_speed_dial.xml @@ -17,9 +17,7 @@ <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/speed_dial_root" android:layout_width="match_parent" - android:layout_height="match_parent" - android:clipChildren="false" - android:clipToPadding="false"> + android:layout_height="match_parent"> <android.support.v7.widget.RecyclerView android:id="@+id/speed_dial_recycler_view" 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 d03a96bc4..d2cc0fc9c 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 @@ -51,8 +51,8 @@ <item name="colorPrimary">@color/dialer_dark_theme_color</item> <item name="android:colorPrimaryDark">@color/dialer_dark_theme_color_dark</item> <item name="colorPrimaryDark">@color/dialer_dark_theme_color_dark</item> - <item name="android:colorAccent">@color/dialer_dark_secondary_color</item> - <item name="colorAccent">@color/dialer_dark_secondary_color</item> + <item name="android:colorAccent">@color/dialer_dark_theme_color</item> + <item name="colorAccent">@color/dialer_dark_theme_color</item> <!-- Used to automatically style check/selected checkbox, switches and radio buttons --> <item name="colorControlActivated">?android:attr/colorPrimary</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 8aa87dfdb..69ecba41e 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 @@ -57,8 +57,8 @@ <item name="colorPrimary">@color/dialer_theme_color</item> <item name="android:colorPrimaryDark">@color/dialer_theme_color_dark</item> <item name="colorPrimaryDark">@color/dialer_theme_color_dark</item> - <item name="android:colorAccent">@color/dialer_secondary_color</item> - <item name="colorAccent">@color/dialer_secondary_color</item> + <item name="android:colorAccent">@color/dialer_theme_color</item> + <item name="colorAccent">@color/dialer_theme_color</item> <!-- Used to automatically style check/selected checkbox, switches and radio buttons --> <item name="colorControlActivated">?android:attr/colorPrimary</item> diff --git a/java/com/android/dialer/theme/common/res/values/colors.xml b/java/com/android/dialer/theme/common/res/values/colors.xml index 207d29c80..0af550fce 100644 --- a/java/com/android/dialer/theme/common/res/values/colors.xml +++ b/java/com/android/dialer/theme/common/res/values/colors.xml @@ -27,7 +27,7 @@ <color name="notification_action_dismiss">#A52714</color> <color name="notification_action_answer_video">#097138</color> - <color name="dialer_red">#C53929</color> + <color name="dialer_red">#EA4335</color> <!-- Legacy --> <color name="blue_grey_100">#CFD8DC</color> diff --git a/java/com/android/dialer/theme/common/res/values/text_styles.xml b/java/com/android/dialer/theme/common/res/values/text_styles.xml index df5dafa31..1f2d6c728 100644 --- a/java/com/android/dialer/theme/common/res/values/text_styles.xml +++ b/java/com/android/dialer/theme/common/res/values/text_styles.xml @@ -37,6 +37,12 @@ <item name="android:fontFamily">sans-serif-medium</item> </style> + <style name="Dialer.TextAppearance.SubHeader2" parent="TextAppearance.AppCompat"> + <item name="android:textColor">?android:attr/textColorSecondary</item> + <item name="android:textSize">14sp</item> + <item name="android:fontFamily">sans-serif-medium</item> + </style> + <style name="Dialer.TextAppearance.Primary" parent="TextAppearance.AppCompat"> <item name="android:textColor">?android:attr/textColorPrimary</item> <item name="android:textSize">16sp</item> diff --git a/java/com/android/dialer/theme/hidden/res/values/colors_dialer_dark.xml b/java/com/android/dialer/theme/hidden/res/values/colors_dialer_dark.xml index e48474e9f..41c5fd1c5 100644 --- a/java/com/android/dialer/theme/hidden/res/values/colors_dialer_dark.xml +++ b/java/com/android/dialer/theme/hidden/res/values/colors_dialer_dark.xml @@ -18,5 +18,4 @@ <color name="dialer_dark_theme_color">#5195EA</color> <color name="dialer_dark_theme_color_20pct">#335195EA</color> <color name="dialer_dark_theme_color_dark">#2374CE</color> - <color name="dialer_dark_secondary_color">#5195EA</color> </resources> diff --git a/java/com/android/dialer/theme/hidden/res/values/colors_dialer_light.xml b/java/com/android/dialer/theme/hidden/res/values/colors_dialer_light.xml index 4621be115..ec2f2629e 100644 --- a/java/com/android/dialer/theme/hidden/res/values/colors_dialer_light.xml +++ b/java/com/android/dialer/theme/hidden/res/values/colors_dialer_light.xml @@ -18,5 +18,4 @@ <color name="dialer_theme_color">@color/google_blue_600</color> <color name="dialer_theme_color_20pct">#332A56C6</color> <color name="dialer_theme_color_dark">#1C3AA9</color> - <color name="dialer_secondary_color">#F50057</color> </resources> diff --git a/java/com/android/dialer/voicemail/settings/AndroidManifest.xml b/java/com/android/dialer/voicemail/settings/AndroidManifest.xml index 71a70da7e..8506ddd41 100644 --- a/java/com/android/dialer/voicemail/settings/AndroidManifest.xml +++ b/java/com/android/dialer/voicemail/settings/AndroidManifest.xml @@ -13,12 +13,10 @@ See the License for the specific language governing permissions and limitations under the License. --> - <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.dialer.voicemail.settings"> <application> - <!-- Causes the "Voicemail" item under "Calls" setting to be hidden. The voicemail module will be handling the settings. Has no effect before OC where dialer cannot provide voicemail settings --> @@ -43,7 +41,13 @@ android:parentActivityName="com.android.dialer.app.settings.DialerSettingsActivity" android:theme="@style/SettingsStyle"> </activity> - <activity android:name=".CurrentVoicemailGreetingActivity"> + <activity + android:name=".CurrentVoicemailGreetingActivity" + android:label="@string/voicemail_change_greeting_preference_title" + android:parentActivityName="com.android.dialer.app.settings.DialerSettingsActivity" + android:exported="true"> + <!-- TODO(a bug): delete android:exported="true" closer to submitting --> </activity> </application> + </manifest> diff --git a/java/com/android/dialer/voicemail/settings/CurrentVoicemailGreetingActivity.java b/java/com/android/dialer/voicemail/settings/CurrentVoicemailGreetingActivity.java index 2b6f27bc3..ff7ae97cc 100644 --- a/java/com/android/dialer/voicemail/settings/CurrentVoicemailGreetingActivity.java +++ b/java/com/android/dialer/voicemail/settings/CurrentVoicemailGreetingActivity.java @@ -16,15 +16,154 @@ package com.android.dialer.voicemail.settings; +import android.Manifest; import android.app.Activity; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.media.MediaPlayer; import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.v4.app.ActivityCompat; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.ImageButton; +import android.widget.TextView; +import com.android.dialer.common.LogUtil; +import com.android.dialer.widget.DialerToolbar; +import java.io.IOException; +import java.util.Locale; /** Activity to display current voicemail greeting and allow user to navigate to record a new one */ public class CurrentVoicemailGreetingActivity extends Activity { + public static final String VOICEMAIL_GREETING_FILEPATH_KEY = "canonVoicemailGreetingFilePathKey"; + + private static final int REQUEST_RECORD_AUDIO_PERMISSION = 200; + + private boolean permissionToRecordAccepted = false; + + private ImageButton changeGreetingButton; + private ImageButton playButton; + + private DialerToolbar currentVoicemailGreetingDialerToolbar; + + private int greetingDuration = -1; + + private MediaPlayer mediaPlayer; + + private TextView playbackProgressLabel; + private View playbackDisplay; + + private String voicemailGreetingFilePath = ""; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_current_voicemail_greeting); + + playbackDisplay = findViewById(R.id.current_voicemail_greeting_recording_display); + playbackProgressLabel = (TextView) findViewById(R.id.playback_progress_text_view); + currentVoicemailGreetingDialerToolbar = (DialerToolbar) findViewById(R.id.toolbar); + + currentVoicemailGreetingDialerToolbar.setTitle( + R.string.voicemail_change_greeting_preference_title); + + changeGreetingButton = (ImageButton) findViewById(R.id.change_greeting_button); + changeGreetingButton.setOnClickListener( + new OnClickListener() { + @Override + public void onClick(View v) { + // TODO(sabowitz): Implement this in CL child beta01. + } + }); + + playButton = (ImageButton) findViewById(R.id.play_button); + playButton.setOnClickListener( + new OnClickListener() { + @Override + public void onClick(View v) { + // TODO(sabowitz): Finish implementing this in CL child beta02. + } + }); + + displayCurrentVoicemailGreetingStatus(); + } + + @Override + public void onStart() { + ActivityCompat.requestPermissions( + this, new String[] {Manifest.permission.RECORD_AUDIO}, REQUEST_RECORD_AUDIO_PERMISSION); + + if (isGreetingRecorded()) { + mediaPlayer = new MediaPlayer(); + try { + mediaPlayer.setDataSource(voicemailGreetingFilePath); + mediaPlayer.prepare(); + } catch (IOException e) { + LogUtil.e("CurrentVoicemailGreetingActivity.onStart", "mediaPlayer setup failed."); + } + } + super.onStart(); + } + + @Override + public void onPause() { + if (isGreetingRecorded()) { + if (mediaPlayer.isPlaying()) { + mediaPlayer.release(); + mediaPlayer = null; + } + } + super.onPause(); + } + + @Override + public void onRequestPermissionsResult( + int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + + if (requestCode == REQUEST_RECORD_AUDIO_PERMISSION) { + permissionToRecordAccepted = grantResults[0] == PackageManager.PERMISSION_GRANTED; + } + if (!permissionToRecordAccepted) { + LogUtil.w( + "CurrentVoicemailGreetingActivity.onRequestPermissionsResult", + "permissionToRecordAccepted = false."); + // TODO(sabowitz): Implement error dialog logic in a child CL. + } + } + + private boolean isGreetingRecorded() { + Intent intent = getIntent(); + if (intent.hasExtra(VOICEMAIL_GREETING_FILEPATH_KEY)) { + String filePathProxy = intent.getStringExtra(VOICEMAIL_GREETING_FILEPATH_KEY); + if (filePathProxy == null || filePathProxy.length() == 0) { + return false; + } + if (mediaPlayer == null) { + mediaPlayer = new MediaPlayer(); + } + try { + mediaPlayer.setDataSource(filePathProxy); + int durationProxy = mediaPlayer.getDuration(); + greetingDuration = durationProxy; + voicemailGreetingFilePath = filePathProxy; + mediaPlayer = null; + return true; + } catch (IOException e) { + LogUtil.e("CurrentVoicemailGreetingActivity.isGreetingRecorded", "bad filepath."); + mediaPlayer = null; + return false; + } + } + return false; + } + + private void displayCurrentVoicemailGreetingStatus() { + if (isGreetingRecorded()) { + String durationLabel = String.format(Locale.US, "00:%d", greetingDuration); + playbackProgressLabel.setText(durationLabel); + } else { + playbackDisplay.setVisibility(View.GONE); + } } } diff --git a/java/com/android/dialer/voicemail/settings/res/drawable-xhdpi/ic_arrow_back_grey600_48dp.png b/java/com/android/dialer/voicemail/settings/res/drawable-xhdpi/ic_arrow_back_grey600_48dp.png Binary files differnew file mode 100644 index 000000000..0a379b484 --- /dev/null +++ b/java/com/android/dialer/voicemail/settings/res/drawable-xhdpi/ic_arrow_back_grey600_48dp.png diff --git a/java/com/android/dialer/voicemail/settings/res/drawable-xhdpi/ic_circles_add_googblue_48dp.png b/java/com/android/dialer/voicemail/settings/res/drawable-xhdpi/ic_circles_add_googblue_48dp.png Binary files differnew file mode 100644 index 000000000..5ae52308d --- /dev/null +++ b/java/com/android/dialer/voicemail/settings/res/drawable-xhdpi/ic_circles_add_googblue_48dp.png diff --git a/java/com/android/dialer/voicemail/settings/res/drawable-xhdpi/ic_play_circle_filled_googblue_48dp.png b/java/com/android/dialer/voicemail/settings/res/drawable-xhdpi/ic_play_circle_filled_googblue_48dp.png Binary files differnew file mode 100644 index 000000000..065775861 --- /dev/null +++ b/java/com/android/dialer/voicemail/settings/res/drawable-xhdpi/ic_play_circle_filled_googblue_48dp.png diff --git a/java/com/android/dialer/voicemail/settings/res/drawable-xhdpi/ic_stop_circle_filled_blue_24dp.png b/java/com/android/dialer/voicemail/settings/res/drawable-xhdpi/ic_stop_circle_filled_blue_24dp.png Binary files differnew file mode 100644 index 000000000..520f860fa --- /dev/null +++ b/java/com/android/dialer/voicemail/settings/res/drawable-xhdpi/ic_stop_circle_filled_blue_24dp.png diff --git a/java/com/android/dialer/voicemail/settings/res/layout/activity_current_voicemail_greeting.xml b/java/com/android/dialer/voicemail/settings/res/layout/activity_current_voicemail_greeting.xml index 81d175a4f..3e90cf749 100644 --- a/java/com/android/dialer/voicemail/settings/res/layout/activity_current_voicemail_greeting.xml +++ b/java/com/android/dialer/voicemail/settings/res/layout/activity_current_voicemail_greeting.xml @@ -21,4 +21,107 @@ android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.android.dialer.voicemail.settings.CurrentVoicemailGreetingActivity"> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_alignParentTop="true" + android:layout_centerHorizontal="true" + android:orientation="vertical"> + <com.android.dialer.widget.DialerToolbar + android:id="@+id/toolbar" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:title="@string/voicemail_change_greeting_preference_title"> + </com.android.dialer.widget.DialerToolbar> + + <View + android:layout_width="match_parent" + android:layout_height="1dp" + android:background="@color/dialer_divider_line_color" + /> + + <!-- Change Greeting Panel --> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="72dp" + android:layout_marginTop="8dp" + android:layout_marginBottom="7dp" + android:orientation="horizontal" + android:visibility="visible"> + + <!-- Change Greeting Button --> + <ImageButton + android:id="@+id/change_greeting_button" + style="@android:style/Widget.Material.Light.ImageButton" + android:layout_width="40dp" + android:layout_height="40dp" + android:layout_marginStart="16dp" + android:layout_gravity="center_vertical" + android:background="?android:attr/colorBackground" + android:foregroundGravity="center_vertical" + android:scaleType="centerCrop" + android:src="@drawable/ic_circles_add_googblue_48dp"/> + + <TextView + android:id="@+id/textView" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:layout_marginStart="17dp" + android:layout_gravity="center_vertical" + android:text="@string/current_voicemail_greeting_record_instruction" + style="@style/Dialer.TextAppearance.Primary"/> + + </LinearLayout> + <View + android:layout_width="match_parent" + android:layout_height="1dp" + android:background="@color/dialer_divider_line_color" + /> + <LinearLayout + android:id="@+id/current_voicemail_greeting_recording_display" + android:layout_width="match_parent" + android:layout_height="72dp" + android:background="?android:attr/colorBackground" + android:orientation="horizontal"> + <!-- Play Button --> + <ImageButton + android:id="@+id/play_button" + style="@android:style/Widget.Material.Light.ImageButton" + android:layout_width="40dp" + android:layout_height="40dp" + android:layout_marginStart="16dp" + android:layout_gravity="center_vertical" + android:adjustViewBounds="false" + android:background="?android:attr/colorBackground" + android:cropToPadding="false" + android:scaleType="centerCrop" + android:src="@drawable/ic_play_circle_filled_googblue_48dp"/> + + <LinearLayout + android:layout_width="232dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:layout_marginStart="16dp" + android:layout_gravity="center_vertical" + android:orientation="vertical"> + <TextView + android:id="@+id/current_voicemail_greeting_recording_title_textview" + style="@style/Dialer.TextAppearance.Primary" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/current_voicemail_greeting_recording_title"/> + <TextView + android:id="@+id/playback_progress_text_view" + style="@style/Dialer.TextAppearance.Secondary" + android:layout_width="match_parent" + android:layout_height="wrap_content"/> + </LinearLayout> + </LinearLayout> + <View + android:layout_width="match_parent" + android:layout_height="1dp" + android:background="@color/dialer_divider_line_color" + /> + </LinearLayout> </RelativeLayout> diff --git a/java/com/android/dialer/voicemail/settings/res/values/strings.xml b/java/com/android/dialer/voicemail/settings/res/values/strings.xml index 14793fd33..971f37a2e 100644 --- a/java/com/android/dialer/voicemail/settings/res/values/strings.xml +++ b/java/com/android/dialer/voicemail/settings/res/values/strings.xml @@ -36,6 +36,12 @@ <!-- Title for changing voicemail greeting activity [CHAR LIMIT=40] --> <string name="voicemail_change_greeting_preference_title">Voicemail greeting</string> + <!-- Text instruction shown on the current voicemail greeting display screen [CHAR LIMIT=20] --> + <string name="current_voicemail_greeting_record_instruction">Record a greeting</string> + + <!-- Title for voicemail greeting, if one is already recorded. --> + <string name="current_voicemail_greeting_recording_title">My voicemail greeting</string> + <!-- Text shown on the record voicemail activity [CHAR LIMIT=20] --> <string name="change_greeting_text">Tap to Record</string> |