diff options
author | twyen <twyen@google.com> | 2018-03-27 06:53:36 +0000 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2018-03-27 06:53:36 +0000 |
commit | 50df6ca7cde9d7a79b24987f4f680e71de006e51 (patch) | |
tree | 892c40f887b8ada65dbaacca86b9648e97206fe8 | |
parent | fe8e034a13d4f338c8c2e5d7a6cbf76137cc6342 (diff) | |
parent | 111b79c9e4206ed2a7bedd3e31d4e1146d30c1cd (diff) |
Merge changes I9949de54,I6f01935f,I3673a6b2,I73c8e83a,Ia6b838ac, ...
am: 111b79c9e4
Change-Id: I7a3d51287c63f3806df7ae4e5c1b4dc9c1751221
44 files changed, 642 insertions, 434 deletions
diff --git a/java/com/android/dialer/app/DialtactsActivity.java b/java/com/android/dialer/app/DialtactsActivity.java index a9a11e008..3d61f7371 100644 --- a/java/com/android/dialer/app/DialtactsActivity.java +++ b/java/com/android/dialer/app/DialtactsActivity.java @@ -725,9 +725,6 @@ public class DialtactsActivity extends TransactionSafeActivity handleMenuSettings(); Logger.get(this).logScreenView(ScreenEvent.Type.SETTINGS, this); return true; - } else if (resId == R.id.menu_new_ui_launcher_shortcut) { - MainComponent.createNewUiLauncherShortcut(this); - return true; } return false; } @@ -1599,10 +1596,6 @@ public class DialtactsActivity extends TransactionSafeActivity } else { simulatorMenuItem.setVisible(false); } - - menu.findItem(R.id.menu_new_ui_launcher_shortcut) - .setVisible(MainComponent.isNewUiEnabled(context)); - super.show(); } } diff --git a/java/com/android/dialer/app/MainComponent.java b/java/com/android/dialer/app/MainComponent.java index f8d457c5f..c223723c6 100644 --- a/java/com/android/dialer/app/MainComponent.java +++ b/java/com/android/dialer/app/MainComponent.java @@ -19,44 +19,14 @@ package com.android.dialer.app; import android.content.ComponentName; import android.content.Context; import android.content.Intent; -import android.content.pm.PackageManager; -import com.android.dialer.configprovider.ConfigProviderBindings; -/** This class is a copy of dialer.main.impl.MainImpl to get around a dependency issue. */ +/** + * Main activity intents. + * + * <p>TODO(calderwoodra): Move this elsewhere. + */ public class MainComponent { - public static boolean isNewUiEnabled(Context context) { - return ConfigProviderBindings.get(context).getBoolean("is_nui_shortcut_enabled", false); - } - - public static void createNewUiLauncherShortcut(Context context) { - enableComponent(context); - } - - public static boolean isNuiComponentEnabled(Context context) { - if (!isNewUiEnabled(context)) { - return false; - } - return context - .getPackageManager() - .getComponentEnabledSetting(new ComponentName(context, getComponentName())) - == PackageManager.COMPONENT_ENABLED_STATE_ENABLED; - } - - /** - * Enables the NUI activity component. By default the component is disabled and can't be accessed. - * Once the component has been enabled the user will get an option to use the new UI to handle - * DIAL (and other) intents. - */ - private static void enableComponent(Context context) { - context - .getPackageManager() - .setComponentEnabledSetting( - new ComponentName(context, getComponentName()), - PackageManager.COMPONENT_ENABLED_STATE_ENABLED, - PackageManager.DONT_KILL_APP); - } - /** * @param context Context of the application package implementing MainActivity class. * @return intent for MainActivity.class diff --git a/java/com/android/dialer/app/calllog/CallLogGroupBuilder.java b/java/com/android/dialer/app/calllog/CallLogGroupBuilder.java index 4a0d78d57..e4bae5e5f 100644 --- a/java/com/android/dialer/app/calllog/CallLogGroupBuilder.java +++ b/java/com/android/dialer/app/calllog/CallLogGroupBuilder.java @@ -17,8 +17,6 @@ package com.android.dialer.app.calllog; import android.database.Cursor; -import android.os.Build.VERSION; -import android.os.Build.VERSION_CODES; import android.support.annotation.Nullable; import android.support.annotation.VisibleForTesting; import android.telephony.PhoneNumberUtils; @@ -104,10 +102,8 @@ public class CallLogGroupBuilder { // Instantiate other group values to those of the first call in the cursor. String groupAccountId = cursor.getString(CallLogQuery.ACCOUNT_ID); - String groupPostDialDigits = - (VERSION.SDK_INT >= VERSION_CODES.N) ? cursor.getString(CallLogQuery.POST_DIAL_DIGITS) : ""; - String groupViaNumbers = - (VERSION.SDK_INT >= VERSION_CODES.N) ? cursor.getString(CallLogQuery.VIA_NUMBER) : ""; + String groupPostDialDigits = cursor.getString(CallLogQuery.POST_DIAL_DIGITS); + String groupViaNumbers = cursor.getString(CallLogQuery.VIA_NUMBER); int groupCallType = cursor.getInt(CallLogQuery.CALL_TYPE); int groupSize = 1; @@ -123,12 +119,8 @@ public class CallLogGroupBuilder { while (cursor.moveToNext()) { // Obtain the values for the current call to group. number = cursor.getString(CallLogQuery.NUMBER); - numberPostDialDigits = - (VERSION.SDK_INT >= VERSION_CODES.N) - ? cursor.getString(CallLogQuery.POST_DIAL_DIGITS) - : ""; - numberViaNumbers = - (VERSION.SDK_INT >= VERSION_CODES.N) ? cursor.getString(CallLogQuery.VIA_NUMBER) : ""; + numberPostDialDigits = cursor.getString(CallLogQuery.POST_DIAL_DIGITS); + numberViaNumbers = cursor.getString(CallLogQuery.VIA_NUMBER); callType = cursor.getInt(CallLogQuery.CALL_TYPE); callFeatures = cursor.getInt(CallLogQuery.FEATURES); accountComponentName = cursor.getString(CallLogQuery.ACCOUNT_COMPONENT_NAME); diff --git a/java/com/android/dialer/app/calllog/MissedCallNotifier.java b/java/com/android/dialer/app/calllog/MissedCallNotifier.java index 158ae2b03..772feed53 100644 --- a/java/com/android/dialer/app/calllog/MissedCallNotifier.java +++ b/java/com/android/dialer/app/calllog/MissedCallNotifier.java @@ -42,12 +42,10 @@ import android.text.TextDirectionHeuristics; import android.text.TextUtils; import android.util.ArraySet; import com.android.contacts.common.ContactsUtils; -import com.android.dialer.app.DialtactsActivity; import com.android.dialer.app.MainComponent; import com.android.dialer.app.R; import com.android.dialer.app.calllog.CallLogNotificationsQueryHelper.NewCall; import com.android.dialer.app.contactinfo.ContactPhotoLoader; -import com.android.dialer.app.list.DialtactsPagerAdapter; import com.android.dialer.callintent.CallInitiationType; import com.android.dialer.callintent.CallIntentBuilder; import com.android.dialer.common.Assert; @@ -454,13 +452,8 @@ public class MissedCallNotifier implements Worker<Pair<Integer, String>, Void> { * @param callUri Uri of the call to jump to. May be null */ private PendingIntent createCallLogPendingIntent(@Nullable Uri callUri) { - Intent contentIntent; - if (MainComponent.isNuiComponentEnabled(context)) { - contentIntent = MainComponent.getShowCallLogIntent(context); - } else { - contentIntent = - DialtactsActivity.getShowTabIntent(context, DialtactsPagerAdapter.TAB_INDEX_HISTORY); - } + Intent contentIntent = MainComponent.getShowCallLogIntent(context); + // TODO (a bug): scroll to call contentIntent.setData(callUri); return PendingIntent.getActivity(context, 0, contentIntent, PendingIntent.FLAG_UPDATE_CURRENT); diff --git a/java/com/android/dialer/app/calllog/VisualVoicemailNotifier.java b/java/com/android/dialer/app/calllog/VisualVoicemailNotifier.java index cba389cc3..793d9627c 100644 --- a/java/com/android/dialer/app/calllog/VisualVoicemailNotifier.java +++ b/java/com/android/dialer/app/calllog/VisualVoicemailNotifier.java @@ -38,7 +38,6 @@ import com.android.dialer.app.MainComponent; import com.android.dialer.app.R; import com.android.dialer.app.calllog.CallLogNotificationsQueryHelper.NewCall; import com.android.dialer.app.contactinfo.ContactPhotoLoader; -import com.android.dialer.app.list.DialtactsPagerAdapter; import com.android.dialer.common.LogUtil; import com.android.dialer.compat.android.provider.VoicemailCompat; import com.android.dialer.logging.DialerImpression; @@ -267,13 +266,8 @@ final class VisualVoicemailNotifier { private static PendingIntent newVoicemailIntent( @NonNull Context context, @Nullable NewCall voicemail) { - Intent intent; - if (MainComponent.isNuiComponentEnabled(context)) { - intent = MainComponent.getShowVoicemailIntent(context); - } else { - intent = - DialtactsActivity.getShowTabIntent(context, DialtactsPagerAdapter.TAB_INDEX_VOICEMAIL); - } + Intent intent = MainComponent.getShowVoicemailIntent(context); + // TODO (a bug): scroll to this voicemail if (voicemail != null) { intent.setData(voicemail.voicemailUri); diff --git a/java/com/android/dialer/app/manifests/activities/AndroidManifest.xml b/java/com/android/dialer/app/manifests/activities/AndroidManifest.xml index b9e5f6201..31960c979 100644 --- a/java/com/android/dialer/app/manifests/activities/AndroidManifest.xml +++ b/java/com/android/dialer/app/manifests/activities/AndroidManifest.xml @@ -37,16 +37,11 @@ <!-- The entrance point for Phone UI. stateAlwaysHidden is set to suppress keyboard show up on dialpad screen. --> - <activity - android:enabled="false" - android:clearTaskOnLaunch="true" - android:directBootAware="true" - android:label="@string/launcherActivityLabel" - android:launchMode="singleTask" - android:name="com.android.dialer.app.DialtactsActivity" - android:resizeableActivity="true" - android:theme="@style/DialtactsActivityTheme" - android:windowSoftInputMode="stateAlwaysHidden|adjustNothing"> + <activity-alias + android:exported="true" + android:name="com.android.dialer.app.DialtactsActivity" + android:targetActivity="com.android.dialer.main.impl.MainActivity"> + <intent-filter> <action android:name="android.intent.action.DIAL"/> @@ -106,23 +101,17 @@ <category android:name="android.intent.category.DEFAULT"/> <category android:name="android.intent.category.TAB"/> </intent-filter> - <intent-filter android:label="@string/callHistoryIconLabel"> + <intent-filter android:label="@string/main_call_history_tab_description"> <action android:name="com.android.phone.action.RECENT_CALLS"/> <category android:name="android.intent.category.DEFAULT"/> <category android:name="android.intent.category.TAB"/> </intent-filter> - - <meta-data - android:name="com.android.keyguard.layout" - android:resource="@layout/keyguard_preview"/> - </activity> + </activity-alias> <activity-alias android:exported="true" android:name="com.android.dialer.DialtactsActivity" android:targetActivity="com.android.dialer.main.impl.MainActivity"/> - </application> - </manifest> diff --git a/java/com/android/dialer/app/res/menu/dialtacts_options.xml b/java/com/android/dialer/app/res/menu/dialtacts_options.xml index b50e6ad5f..fcd520a1e 100644 --- a/java/com/android/dialer/app/res/menu/dialtacts_options.xml +++ b/java/com/android/dialer/app/res/menu/dialtacts_options.xml @@ -28,8 +28,4 @@ <item android:id="@+id/menu_simulator_submenu" android:title="@string/simulator_submenu_label"/> - <item - android:id="@+id/menu_new_ui_launcher_shortcut" - android:title="@string/new_ui_launcher_shortcut_label"/> - </menu> diff --git a/java/com/android/dialer/binary/aosp/AospDialerRootComponent.java b/java/com/android/dialer/binary/aosp/AospDialerRootComponent.java index 969172b7f..21a282ded 100644 --- a/java/com/android/dialer/binary/aosp/AospDialerRootComponent.java +++ b/java/com/android/dialer/binary/aosp/AospDialerRootComponent.java @@ -19,6 +19,7 @@ package com.android.dialer.binary.aosp; import com.android.bubble.stub.StubBubbleModule; import com.android.dialer.binary.basecomponent.BaseDialerRootComponent; import com.android.dialer.calllog.CallLogModule; +import com.android.dialer.calllog.config.CallLogConfigModule; import com.android.dialer.commandline.CommandLineModule; import com.android.dialer.common.concurrent.DialerExecutorModule; import com.android.dialer.configprovider.SharedPrefConfigProviderModule; @@ -49,6 +50,7 @@ import javax.inject.Singleton; @Component( modules = { CallLogModule.class, + CallLogConfigModule.class, CommandLineModule.class, ContextModule.class, DialerExecutorModule.class, diff --git a/java/com/android/dialer/binary/basecomponent/BaseDialerRootComponent.java b/java/com/android/dialer/binary/basecomponent/BaseDialerRootComponent.java index 2cafb260f..b668d9114 100644 --- a/java/com/android/dialer/binary/basecomponent/BaseDialerRootComponent.java +++ b/java/com/android/dialer/binary/basecomponent/BaseDialerRootComponent.java @@ -18,6 +18,7 @@ package com.android.dialer.binary.basecomponent; import com.android.bubble.BubbleComponent; import com.android.dialer.calllog.CallLogComponent; +import com.android.dialer.calllog.config.CallLogConfigComponent; import com.android.dialer.calllog.database.CallLogDatabaseComponent; import com.android.dialer.calllog.ui.CallLogUiComponent; import com.android.dialer.commandline.CommandLineComponent; @@ -27,7 +28,6 @@ import com.android.dialer.duo.DuoComponent; import com.android.dialer.enrichedcall.EnrichedCallComponent; import com.android.dialer.feedback.FeedbackComponent; import com.android.dialer.glidephotomanager.GlidePhotoManagerComponent; -import com.android.dialer.main.MainComponent; import com.android.dialer.metrics.MetricsComponent; import com.android.dialer.phonelookup.PhoneLookupComponent; import com.android.dialer.phonelookup.database.PhoneLookupDatabaseComponent; @@ -51,6 +51,7 @@ public interface BaseDialerRootComponent extends BubbleComponent.HasComponent, CallLocationComponent.HasComponent, CallLogComponent.HasComponent, + CallLogConfigComponent.HasComponent, CallLogDatabaseComponent.HasComponent, CallLogUiComponent.HasComponent, ConfigProviderComponent.HasComponent, @@ -60,7 +61,6 @@ public interface BaseDialerRootComponent EnrichedCallComponent.HasComponent, FeedbackComponent.HasComponent, GlidePhotoManagerComponent.HasComponent, - MainComponent.HasComponent, MapsComponent.HasComponent, MetricsComponent.HasComponent, PhoneLookupComponent.HasComponent, diff --git a/java/com/android/dialer/binary/common/DialerApplication.java b/java/com/android/dialer/binary/common/DialerApplication.java index 9e9b03b5f..3247c7053 100644 --- a/java/com/android/dialer/binary/common/DialerApplication.java +++ b/java/com/android/dialer/binary/common/DialerApplication.java @@ -23,14 +23,15 @@ import android.support.v4.os.BuildCompat; import com.android.dialer.blocking.BlockedNumbersAutoMigrator; import com.android.dialer.blocking.FilteredNumberAsyncQueryHandler; import com.android.dialer.calllog.CallLogComponent; -import com.android.dialer.common.concurrent.DefaultFutureCallback; +import com.android.dialer.calllog.CallLogFramework; +import com.android.dialer.calllog.config.CallLogConfig; +import com.android.dialer.calllog.config.CallLogConfigComponent; +import com.android.dialer.common.LogUtil; import com.android.dialer.common.concurrent.DialerExecutorComponent; import com.android.dialer.inject.HasRootComponent; import com.android.dialer.notification.NotificationChannelManager; import com.android.dialer.persistentlog.PersistentLogger; import com.android.dialer.strictmode.StrictModeComponent; -import com.google.common.util.concurrent.Futures; -import com.google.common.util.concurrent.MoreExecutors; /** A common application subclass for all Dialer build variants. */ public abstract class DialerApplication extends Application implements HasRootComponent { @@ -48,11 +49,7 @@ public abstract class DialerApplication extends Application implements HasRootCo new FilteredNumberAsyncQueryHandler(this), DialerExecutorComponent.get(this).dialerExecutorFactory()) .asyncAutoMigrate(); - CallLogComponent.get(this).callLogFramework().onApplicationCreate(); - Futures.addCallback( - CallLogComponent.get(this).getAnnotatedCallLogMigrator().migrate(), - new DefaultFutureCallback<>(), - MoreExecutors.directExecutor()); + initializeAnnotatedCallLog(); PersistentLogger.initialize(this); if (BuildCompat.isAtLeastO()) { @@ -61,6 +58,18 @@ public abstract class DialerApplication extends Application implements HasRootCo Trace.endSection(); } + private void initializeAnnotatedCallLog() { + CallLogConfig callLogConfig = CallLogConfigComponent.get(this).callLogConfig(); + callLogConfig.schedulePollingJob(); + + if (callLogConfig.isCallLogFrameworkEnabled()) { + CallLogFramework callLogFramework = CallLogComponent.get(this).callLogFramework(); + callLogFramework.registerContentObservers(); + } else { + LogUtil.i("DialerApplication.initializeAnnotatedCallLog", "framework not enabled"); + } + } + /** * Returns a new instance of the root component for the application. Sub classes should define a * root component that extends all the sub components "HasComponent" intefaces. The component diff --git a/java/com/android/dialer/binary/google/GoogleStubDialerRootComponent.java b/java/com/android/dialer/binary/google/GoogleStubDialerRootComponent.java index f9f561a0e..0da2f9577 100644 --- a/java/com/android/dialer/binary/google/GoogleStubDialerRootComponent.java +++ b/java/com/android/dialer/binary/google/GoogleStubDialerRootComponent.java @@ -19,6 +19,7 @@ package com.android.dialer.binary.google; import com.android.bubble.stub.StubBubbleModule; import com.android.dialer.binary.basecomponent.BaseDialerRootComponent; import com.android.dialer.calllog.CallLogModule; +import com.android.dialer.calllog.config.CallLogConfigModule; import com.android.dialer.commandline.CommandLineModule; import com.android.dialer.common.concurrent.DialerExecutorModule; import com.android.dialer.configprovider.SharedPrefConfigProviderModule; @@ -53,6 +54,7 @@ import javax.inject.Singleton; modules = { CallLocationModule.class, CallLogModule.class, + CallLogConfigModule.class, CommandLineModule.class, ContextModule.class, DialerExecutorModule.class, diff --git a/java/com/android/dialer/callintent/CallIntentBuilder.java b/java/com/android/dialer/callintent/CallIntentBuilder.java index ff490c296..9d9fcf4da 100644 --- a/java/com/android/dialer/callintent/CallIntentBuilder.java +++ b/java/com/android/dialer/callintent/CallIntentBuilder.java @@ -25,6 +25,7 @@ import android.os.SystemClock; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.annotation.VisibleForTesting; +import android.telecom.Call.Details; import android.telecom.PhoneAccount; import android.telecom.PhoneAccountHandle; import android.telecom.TelecomManager; @@ -168,6 +169,7 @@ public class CallIntentBuilder implements Parcelable { return callSubject; } + /** Additional data the in call UI can read with {@link Details#getIntentExtras()} */ public Bundle getOutgoingCallExtras() { return outgoingCallExtras; } diff --git a/java/com/android/dialer/calllog/AnnotatedCallLogMigrator.java b/java/com/android/dialer/calllog/AnnotatedCallLogMigrator.java index a12a98f0e..71bfb753c 100644 --- a/java/com/android/dialer/calllog/AnnotatedCallLogMigrator.java +++ b/java/com/android/dialer/calllog/AnnotatedCallLogMigrator.java @@ -16,12 +16,9 @@ package com.android.dialer.calllog; -import android.content.Context; import android.content.SharedPreferences; import com.android.dialer.common.LogUtil; import com.android.dialer.common.concurrent.Annotations.BackgroundExecutor; -import com.android.dialer.configprovider.ConfigProviderBindings; -import com.android.dialer.inject.ApplicationContext; import com.android.dialer.storage.Unencrypted; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; @@ -37,18 +34,15 @@ public final class AnnotatedCallLogMigrator { private static final String PREF_MIGRATED = "annotatedCallLogMigratorMigrated"; - private final Context appContext; private final SharedPreferences sharedPreferences; private final RefreshAnnotatedCallLogWorker refreshAnnotatedCallLogWorker; private final ListeningExecutorService backgroundExecutor; @Inject AnnotatedCallLogMigrator( - @ApplicationContext Context appContext, @Unencrypted SharedPreferences sharedPreferences, @BackgroundExecutor ListeningExecutorService backgroundExecutor, RefreshAnnotatedCallLogWorker refreshAnnotatedCallLogWorker) { - this.appContext = appContext; this.sharedPreferences = sharedPreferences; this.backgroundExecutor = backgroundExecutor; this.refreshAnnotatedCallLogWorker = refreshAnnotatedCallLogWorker; @@ -78,17 +72,7 @@ public final class AnnotatedCallLogMigrator { } private ListenableFuture<Boolean> shouldMigrate() { - return backgroundExecutor.submit( - () -> { - if (!(ConfigProviderBindings.get(appContext) - .getBoolean("is_nui_shortcut_enabled", false))) { - return false; - } - if (sharedPreferences.getBoolean(PREF_MIGRATED, false)) { - return false; - } - return true; - }); + return backgroundExecutor.submit(() -> !sharedPreferences.getBoolean(PREF_MIGRATED, false)); } /** diff --git a/java/com/android/dialer/calllog/CallLogComponent.java b/java/com/android/dialer/calllog/CallLogComponent.java index c7b44a818..4f147f1a6 100644 --- a/java/com/android/dialer/calllog/CallLogComponent.java +++ b/java/com/android/dialer/calllog/CallLogComponent.java @@ -30,12 +30,8 @@ public abstract class CallLogComponent { public abstract RefreshAnnotatedCallLogWorker getRefreshAnnotatedCallLogWorker(); - public abstract AnnotatedCallLogMigrator getAnnotatedCallLogMigrator(); - public abstract ClearMissedCalls getClearMissedCalls(); - public abstract CallLogConfig callLogConfig(); - public static CallLogComponent get(Context context) { return ((HasComponent) ((HasRootComponent) context.getApplicationContext()).component()) .callLogComponent(); diff --git a/java/com/android/dialer/calllog/CallLogFramework.java b/java/com/android/dialer/calllog/CallLogFramework.java index 936f2bbf6..53ff43057 100644 --- a/java/com/android/dialer/calllog/CallLogFramework.java +++ b/java/com/android/dialer/calllog/CallLogFramework.java @@ -16,12 +16,9 @@ package com.android.dialer.calllog; -import android.content.Context; import com.android.dialer.calllog.datasources.CallLogDataSource; import com.android.dialer.calllog.datasources.DataSources; import com.android.dialer.common.LogUtil; -import com.android.dialer.configprovider.ConfigProviderBindings; -import com.android.dialer.inject.ApplicationContext; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.MoreExecutors; @@ -38,46 +35,39 @@ import javax.inject.Singleton; @Singleton public final class CallLogFramework { - private final Context appContext; private final DataSources dataSources; + private final AnnotatedCallLogMigrator annotatedCallLogMigrator; @Inject - CallLogFramework(@ApplicationContext Context appContext, DataSources dataSources) { - this.appContext = appContext; + CallLogFramework(DataSources dataSources, AnnotatedCallLogMigrator annotatedCallLogMigrator) { this.dataSources = dataSources; - } - - /** Performs necessary setup work when the application is created. */ - public void onApplicationCreate() { - registerContentObservers(); - CallLogConfig.schedulePollingJob(appContext); + this.annotatedCallLogMigrator = annotatedCallLogMigrator; } /** Registers the content observers for all data sources. */ public void registerContentObservers() { LogUtil.enterBlock("CallLogFramework.registerContentObservers"); - - // This is the same condition used in MainImpl#isNewUiEnabled. It means that bugfood/debug - // users will have "new call log" content observers firing. These observers usually do simple - // things like writing shared preferences. - // TODO(zachh): Find a way to access Main#isNewUiEnabled without creating a circular dependency. - if (ConfigProviderBindings.get(appContext).getBoolean("is_nui_shortcut_enabled", false)) { - for (CallLogDataSource dataSource : dataSources.getDataSourcesIncludingSystemCallLog()) { - dataSource.registerContentObservers(); - } - } else { - LogUtil.i("CallLogFramework.registerContentObservers", "not registering content observers"); + for (CallLogDataSource dataSource : dataSources.getDataSourcesIncludingSystemCallLog()) { + dataSource.registerContentObservers(); } } + /** Enables the framework. */ + public ListenableFuture<Void> enable() { + registerContentObservers(); + return annotatedCallLogMigrator.migrate(); + } + /** Disables the framework. */ public ListenableFuture<Void> disable() { - LogUtil.enterBlock("CallLogFramework.disable"); + return Futures.transform( + Futures.allAsList(disableDataSources(), annotatedCallLogMigrator.clearData()), + unused -> null, + MoreExecutors.directExecutor()); + } - if (!ConfigProviderBindings.get(appContext).getBoolean("is_nui_shortcut_enabled", false)) { - LogUtil.i("CallLogFramework.disable", "not disabling"); - return Futures.immediateFuture(null); - } + private ListenableFuture<Void> disableDataSources() { + LogUtil.enterBlock("CallLogFramework.disableDataSources"); for (CallLogDataSource dataSource : dataSources.getDataSourcesIncludingSystemCallLog()) { dataSource.unregisterContentObservers(); diff --git a/java/com/android/dialer/calllog/config/AndroidManifest.xml b/java/com/android/dialer/calllog/config/AndroidManifest.xml new file mode 100644 index 000000000..7f65fac5d --- /dev/null +++ b/java/com/android/dialer/calllog/config/AndroidManifest.xml @@ -0,0 +1,32 @@ +<!-- + ~ 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 + --> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.dialer.calllog.config"> + + <uses-sdk + android:minSdkVersion="24" + android:targetSdkVersion="27"/> + + <application> + + <service + android:exported="false" + android:name=".CallLogConfigImpl$PollingJob" + android:permission="android.permission.BIND_JOB_SERVICE"/> + + </application> + +</manifest> diff --git a/java/com/android/dialer/calllog/config/CallLogConfig.java b/java/com/android/dialer/calllog/config/CallLogConfig.java new file mode 100644 index 000000000..15fd5c1c2 --- /dev/null +++ b/java/com/android/dialer/calllog/config/CallLogConfig.java @@ -0,0 +1,40 @@ +/* + * 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.calllog.config; + +import com.google.common.util.concurrent.ListenableFuture; + +/** Determines if new call log components are enabled. */ +public interface CallLogConfig { + + /** + * Updates the config values. This may kick off a lot of work so should be done infrequently, for + * example by a scheduled job or broadcast receiver which rarely fires. + */ + ListenableFuture<Void> update(); + + boolean isNewCallLogFragmentEnabled(); + + boolean isNewVoicemailFragmentEnabled(); + + boolean isNewPeerEnabled(); + + boolean isCallLogFrameworkEnabled(); + + /** Schedules a job to periodically update the config. */ + void schedulePollingJob(); +} diff --git a/java/com/android/dialer/main/MainComponent.java b/java/com/android/dialer/calllog/config/CallLogConfigComponent.java index e735457f4..c325025f3 100644 --- a/java/com/android/dialer/main/MainComponent.java +++ b/java/com/android/dialer/calllog/config/CallLogConfigComponent.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017 The Android Open Source Project + * 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. @@ -13,27 +13,25 @@ * See the License for the specific language governing permissions and * limitations under the License */ - -package com.android.dialer.main; +package com.android.dialer.calllog.config; import android.content.Context; import com.android.dialer.inject.HasRootComponent; -import com.android.dialer.main.impl.MainModule; import dagger.Subcomponent; -/** Subcomponent that can be used to access the main implementation. */ -@Subcomponent(modules = MainModule.class) -public abstract class MainComponent { +/** Dagger component for the call log config. */ +@Subcomponent +public abstract class CallLogConfigComponent { - public abstract Main getMain(); + public abstract CallLogConfig callLogConfig(); - public static MainComponent get(Context context) { + public static CallLogConfigComponent get(Context context) { return ((HasComponent) ((HasRootComponent) context.getApplicationContext()).component()) - .mainComponent(); + .callLogConfigComponent(); } /** Used to refer to the root application component. */ public interface HasComponent { - MainComponent mainComponent(); + CallLogConfigComponent callLogConfigComponent(); } } diff --git a/java/com/android/dialer/calllog/CallLogConfig.java b/java/com/android/dialer/calllog/config/CallLogConfigImpl.java index 12056c758..9c7f472d5 100644 --- a/java/com/android/dialer/calllog/CallLogConfig.java +++ b/java/com/android/dialer/calllog/config/CallLogConfigImpl.java @@ -14,7 +14,7 @@ * limitations under the License */ -package com.android.dialer.calllog; +package com.android.dialer.calllog.config; import android.annotation.SuppressLint; import android.app.job.JobInfo; @@ -25,13 +25,14 @@ import android.content.ComponentName; import android.content.Context; import android.content.SharedPreferences; import android.support.v4.os.UserManagerCompat; +import com.android.dialer.calllog.CallLogFramework; 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.Annotations.LightweightExecutor; import com.android.dialer.common.concurrent.ThreadUtil; import com.android.dialer.configprovider.ConfigProvider; import com.android.dialer.constants.ScheduledJobIds; +import com.android.dialer.inject.ApplicationContext; import com.android.dialer.storage.Unencrypted; import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; @@ -51,7 +52,7 @@ import javax.inject.Inject; * <p>New UI application components should use this class instead of reading flags directly from the * {@link ConfigProvider}. */ -public final class CallLogConfig { +public final class CallLogConfigImpl implements CallLogConfig { private static final String NEW_CALL_LOG_FRAGMENT_ENABLED_PREF_KEY = "newCallLogFragmentEnabled"; private static final String NEW_VOICEMAIL_FRAGMENT_ENABLED_PREF_KEY = @@ -60,33 +61,27 @@ public final class CallLogConfig { private static final String NEW_CALL_LOG_FRAMEWORK_ENABLED_PREF_KEY = "newCallLogFrameworkEnabled"; + private final Context appContext; private final CallLogFramework callLogFramework; private final SharedPreferences sharedPreferences; private final ConfigProvider configProvider; - private final AnnotatedCallLogMigrator annotatedCallLogMigrator; private final ListeningExecutorService backgroundExecutor; - private final ListeningExecutorService lightweightExecutor; @Inject - public CallLogConfig( + public CallLogConfigImpl( + @ApplicationContext Context appContext, CallLogFramework callLogFramework, @Unencrypted SharedPreferences sharedPreferences, ConfigProvider configProvider, - AnnotatedCallLogMigrator annotatedCallLogMigrator, - @BackgroundExecutor ListeningExecutorService backgroundExecutor, - @LightweightExecutor ListeningExecutorService lightweightExecutor) { + @BackgroundExecutor ListeningExecutorService backgroundExecutor) { + this.appContext = appContext; this.callLogFramework = callLogFramework; this.sharedPreferences = sharedPreferences; this.configProvider = configProvider; - this.annotatedCallLogMigrator = annotatedCallLogMigrator; this.backgroundExecutor = backgroundExecutor; - this.lightweightExecutor = lightweightExecutor; } - /** - * Updates the config values. This may kick off a lot of work so should be done infrequently, for - * example by a scheduled job or broadcast receiver which rarely fires. - */ + @Override public ListenableFuture<Void> update() { boolean newCallLogFragmentEnabledInConfigProvider = configProvider.getBoolean("new_call_log_fragment_enabled", false); @@ -102,7 +97,7 @@ public final class CallLogConfig { if (callLogFrameworkShouldBeEnabled && !isCallLogFrameworkEnabled) { return Futures.transform( - enableFramework(), + callLogFramework.enable(), unused -> { // Reflect the flag changes only after the framework is enabled. sharedPreferences @@ -134,7 +129,9 @@ public final class CallLogConfig { return null; }); return Futures.transformAsync( - writeSharedPrefsFuture, unused -> disableFramework(), MoreExecutors.directExecutor()); + writeSharedPrefsFuture, + unused -> callLogFramework.disable(), + MoreExecutors.directExecutor()); } else { // We didn't need to enable/disable the framework, but we still need to update the // individual flags. @@ -155,35 +152,17 @@ public final class CallLogConfig { } } - private ListenableFuture<Void> enableFramework() { - ListenableFuture<Void> registerObserversFuture = - lightweightExecutor.submit( - () -> { - callLogFramework.registerContentObservers(); - return null; - }); - ListenableFuture<Void> migratorFuture = annotatedCallLogMigrator.migrate(); - return Futures.transform( - Futures.allAsList(registerObserversFuture, migratorFuture), - unused -> null, - MoreExecutors.directExecutor()); - } - - private ListenableFuture<Void> disableFramework() { - return Futures.transform( - Futures.allAsList(callLogFramework.disable(), annotatedCallLogMigrator.clearData()), - unused -> null, - MoreExecutors.directExecutor()); - } - + @Override public boolean isNewCallLogFragmentEnabled() { return sharedPreferences.getBoolean(NEW_CALL_LOG_FRAGMENT_ENABLED_PREF_KEY, false); } + @Override public boolean isNewVoicemailFragmentEnabled() { return sharedPreferences.getBoolean(NEW_VOICEMAIL_FRAGMENT_ENABLED_PREF_KEY, false); } + @Override public boolean isNewPeerEnabled() { return sharedPreferences.getBoolean(NEW_PEER_ENABLED_PREF_KEY, false); } @@ -192,11 +171,13 @@ public final class CallLogConfig { * Returns true if the new call log framework is enabled, meaning that content observers are * firing and PhoneLookupHistory is being populated, etc. */ + @Override public boolean isCallLogFrameworkEnabled() { return sharedPreferences.getBoolean(NEW_CALL_LOG_FRAMEWORK_ENABLED_PREF_KEY, false); } - static void schedulePollingJob(Context appContext) { + @Override + public void schedulePollingJob() { if (UserManagerCompat.isUserUnlocked(appContext)) { JobScheduler jobScheduler = Assert.isNotNull(appContext.getSystemService(JobScheduler.class)); @SuppressLint("MissingPermission") // Dialer has RECEIVE_BOOT permission @@ -209,7 +190,7 @@ public final class CallLogConfig { .setRequiresCharging(true) .setRequiresDeviceIdle(true) .build(); - LogUtil.i("CallLogConfig.schedulePollingJob", "scheduling"); + LogUtil.i("CallLogConfigImpl.schedulePollingJob", "scheduling"); jobScheduler.schedule(jobInfo); } } @@ -226,7 +207,7 @@ public final class CallLogConfig { public boolean onStartJob(JobParameters params) { LogUtil.enterBlock("PollingJob.onStartJob"); Futures.addCallback( - CallLogComponent.get(getApplicationContext()).callLogConfig().update(), + CallLogConfigComponent.get(getApplicationContext()).callLogConfig().update(), new FutureCallback<Void>() { @Override public void onSuccess(Void unused) { diff --git a/java/com/android/dialer/main/impl/MainModule.java b/java/com/android/dialer/calllog/config/CallLogConfigModule.java index 90342cf59..d982e2bd8 100644 --- a/java/com/android/dialer/main/impl/MainModule.java +++ b/java/com/android/dialer/calllog/config/CallLogConfigModule.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017 The Android Open Source Project + * 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. @@ -14,17 +14,14 @@ * limitations under the License */ -package com.android.dialer.main.impl; +package com.android.dialer.calllog.config; -import com.android.dialer.main.Main; +import dagger.Binds; import dagger.Module; -import dagger.Provides; -/** This module provides an instance of {@link Main}. */ +/** Binds {@link CallLogConfigImpl}. */ @Module -public final class MainModule { - @Provides - public static Main provideMain() { - return new MainImpl(); - } +public abstract class CallLogConfigModule { + @Binds + abstract CallLogConfig to(CallLogConfigImpl impl); } diff --git a/java/com/android/dialer/commandline/impl/CallCommand.java b/java/com/android/dialer/commandline/impl/CallCommand.java index a6d78f4de..b3ea8601f 100644 --- a/java/com/android/dialer/commandline/impl/CallCommand.java +++ b/java/com/android/dialer/commandline/impl/CallCommand.java @@ -53,7 +53,10 @@ public class CallCommand implements Command { @NonNull @Override public String getUsage() { - return "call number\n\nuse 'voicemail' to call voicemail"; + return "call [flags --] number\n" + + "\nuse 'voicemail' to call voicemail" + + "\n\nflags:" + + "\n--direct send intent to telecom instead of pre call"; } @Override @@ -73,11 +76,16 @@ public class CallCommand implements Command { } else { callIntentBuilder = new CallIntentBuilder(number, CallInitiationType.Type.DIALPAD); } - - Intent intent = PreCall.getIntent(appContext, callIntentBuilder); - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - appContext.startActivity(intent); - + if (args.getBoolean("direct", false)) { + Intent intent = callIntentBuilder.build(); + appContext + .getSystemService(TelecomManager.class) + .placeCall(intent.getData(), intent.getExtras()); + } else { + Intent intent = PreCall.getIntent(appContext, callIntentBuilder); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + appContext.startActivity(intent); + } return Futures.immediateFuture("Calling " + number); } } diff --git a/java/com/android/dialer/dialpadview/DialpadFragment.java b/java/com/android/dialer/dialpadview/DialpadFragment.java index 833b91f59..6f8d677e8 100644 --- a/java/com/android/dialer/dialpadview/DialpadFragment.java +++ b/java/com/android/dialer/dialpadview/DialpadFragment.java @@ -16,6 +16,7 @@ package com.android.dialer.dialpadview; +import android.annotation.TargetApi; import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; @@ -34,6 +35,8 @@ import android.graphics.BitmapFactory; import android.media.AudioManager; import android.media.ToneGenerator; import android.net.Uri; +import android.os.Build.VERSION; +import android.os.Build.VERSION_CODES; import android.os.Bundle; import android.os.Trace; import android.provider.Contacts.People; @@ -48,6 +51,7 @@ import android.telecom.PhoneAccount; import android.telecom.PhoneAccountHandle; import android.telephony.PhoneNumberFormattingTextWatcher; import android.telephony.PhoneNumberUtils; +import android.telephony.ServiceState; import android.telephony.TelephonyManager; import android.text.Editable; import android.text.Selection; @@ -75,6 +79,7 @@ import android.widget.TextView; import com.android.contacts.common.dialog.CallSubjectDialog; import com.android.contacts.common.util.StopWatch; import com.android.dialer.animation.AnimUtils; +import com.android.dialer.animation.AnimUtils.AnimationCallback; import com.android.dialer.callintent.CallInitiationType; import com.android.dialer.callintent.CallIntentBuilder; import com.android.dialer.common.Assert; @@ -141,7 +146,18 @@ public class DialpadFragment extends Fragment private static final String PREF_DIGITS_FILLED_BY_INTENT = "pref_digits_filled_by_intent"; private static final String PREF_IS_DIALPAD_SLIDE_OUT = "pref_is_dialpad_slide_out"; + /** + * Hidden key in carrier config to determine if no emergency call over wifi warning is required. + * + * <p>"Time delay (in ms) after which we show the notification for emergency calls, while the + * device is registered over WFC. Default value is -1, which indicates that this notification is + * not pertinent for a particular carrier. We've added a delay to prevent false positives." + */ + @VisibleForTesting + static final String KEY_EMERGENCY_NOTIFICATION_DELAY_INT = "emergency_notification_delay_int"; + private static Optional<String> currentCountryIsoForTesting = Optional.absent(); + private static Boolean showEmergencyCallWarningForTest = null; private final Object toneGeneratorLock = new Object(); /** Set of dialpad keys that are currently being pressed */ @@ -303,6 +319,7 @@ public class DialpadFragment extends Fragment activity.invalidateOptionsMenu(); updateMenuOverflowButton(wasEmptyBeforeTextChange); } + updateDialpadHint(); } // DTMF Tones do not need to be played here any longer - @@ -439,6 +456,73 @@ public class DialpadFragment extends Fragment return fragmentView; } + /** + * The dialpad hint is a TextView overlaid above the digit EditText. {@link EditText#setHint(int)} + * is not used because the digits has auto resize and makes setting the size of the hint + * difficult. + */ + private void updateDialpadHint() { + TextView hint = dialpadView.getDigitsHint(); + if (!TextUtils.isEmpty(digits.getText())) { + hint.setVisibility(View.GONE); + return; + } + + if (shouldShowEmergencyCallWarning(getContext())) { + hint.setText(getContext().getString(R.string.dialpad_hint_emergency_calling_not_available)); + hint.setVisibility(View.VISIBLE); + return; + } + hint.setVisibility(View.GONE); + } + + /** + * Only show the "emergency call not available" warning when on wifi call and carrier requires it. + * + * <p>internal method tested because the conditions cannot be setup in espresso, and the layout + * cannot be inflated in robolectric. + */ + @SuppressWarnings("missingPermission") + @TargetApi(VERSION_CODES.O) + @VisibleForTesting + static boolean shouldShowEmergencyCallWarning(Context context) { + if (showEmergencyCallWarningForTest != null) { + return showEmergencyCallWarningForTest; + } + if (VERSION.SDK_INT < VERSION_CODES.O) { + return false; + } + if (!PermissionsUtil.hasReadPhoneStatePermissions(context)) { + return false; + } + TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class); + // A delay of -1 means wifi emergency call is available/the warning is not required. + if (telephonyManager.getCarrierConfig().getInt(KEY_EMERGENCY_NOTIFICATION_DELAY_INT, -1) + == -1) { + return false; + } + + // TelephonyManager.getVoiceNetworkType() Doesn't always return NETWORK_TYPE_IWLAN when on wifi. + // other wifi calling checks are hidden API. Emergency calling is not available without service + // regardless of the wifi state so this check is omitted. + + switch (telephonyManager.getServiceState().getState()) { + case ServiceState.STATE_OUT_OF_SERVICE: + case ServiceState.STATE_POWER_OFF: + return true; + case ServiceState.STATE_EMERGENCY_ONLY: + case ServiceState.STATE_IN_SERVICE: + return false; + default: + throw new AssertionError("unknown state " + telephonyManager.getServiceState().getState()); + } + } + + @VisibleForTesting + static void setShowEmergencyCallWarningForTest(Boolean value) { + showEmergencyCallWarningForTest = value; + } + @Override public void onAttach(Context context) { super.onAttach(context); @@ -732,6 +816,8 @@ public class DialpadFragment extends Fragment overflowMenuButton.setOnClickListener(this); overflowMenuButton.setVisibility(isDigitsEmpty() ? View.INVISIBLE : View.VISIBLE); + updateDialpadHint(); + if (firstLaunch) { // The onHiddenChanged callback does not get called the first time the fragment is // attached, so call it ourselves here. @@ -1392,7 +1478,16 @@ public class DialpadFragment extends Fragment if (transitionIn) { AnimUtils.fadeIn(overflowMenuButton, AnimUtils.DEFAULT_DURATION); } else { - AnimUtils.fadeOut(overflowMenuButton, AnimUtils.DEFAULT_DURATION); + AnimUtils.fadeOut( + overflowMenuButton, + AnimUtils.DEFAULT_DURATION, + new AnimationCallback() { + @Override + public void onAnimationEnd() { + // AnimUtils will set the visibility to GONE and cause the layout to move around. + overflowMenuButton.setVisibility(View.INVISIBLE); + } + }); } } diff --git a/java/com/android/dialer/dialpadview/DialpadView.java b/java/com/android/dialer/dialpadview/DialpadView.java index 58ba233bd..1bd8bad4f 100644 --- a/java/com/android/dialer/dialpadview/DialpadView.java +++ b/java/com/android/dialer/dialpadview/DialpadView.java @@ -82,6 +82,7 @@ public class DialpadView extends LinearLayout { private final int translateDistance; private EditText digits; + private TextView digitsHint; private ImageButton delete; private View overflowMenuButton; private ViewGroup rateContainer; @@ -134,6 +135,7 @@ public class DialpadView extends LinearLayout { setupKeypad(); digits = (EditText) findViewById(R.id.digits); + digitsHint = findViewById(R.id.digits_hint); delete = (ImageButton) findViewById(R.id.deleteButton); overflowMenuButton = findViewById(R.id.dialpad_overflow); rateContainer = (ViewGroup) findViewById(R.id.rate_container); @@ -311,6 +313,10 @@ public class DialpadView extends LinearLayout { return digits; } + public TextView getDigitsHint() { + return digitsHint; + } + public ImageButton getDeleteButton() { return delete; } diff --git a/java/com/android/dialer/dialpadview/res/layout/dialpad_view_unthemed.xml b/java/com/android/dialer/dialpadview/res/layout/dialpad_view_unthemed.xml index 13c11f1ce..69d23a9b6 100644 --- a/java/com/android/dialer/dialpadview/res/layout/dialpad_view_unthemed.xml +++ b/java/com/android/dialer/dialpadview/res/layout/dialpad_view_unthemed.xml @@ -13,9 +13,8 @@ See the License for the specific language governing permissions and limitations under the License. --> -<view xmlns:android="http://schemas.android.com/apk/res/android" +<com.android.dialer.dialpadview.DialpadView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/dialpad_view" - class="com.android.dialer.dialpadview.DialpadView" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="bottom" @@ -100,29 +99,39 @@ android:tint="?attr/dialpad_icon_tint" android:tintMode="src_in" android:visibility="gone"/> - - <view xmlns:ex="http://schemas.android.com/apk/res-auto" - android:id="@+id/digits" - class="com.android.dialer.dialpadview.DigitsEditText" - android:textStyle="normal" - android:layout_width="0dp" - android:layout_height="match_parent" - android:layout_weight="1" - android:background="@android:color/transparent" - android:cursorVisible="false" - android:focusableInTouchMode="true" - android:fontFamily="sans-serif" - android:freezesText="true" - android:gravity="center" - android:importantForAutofill="no" - android:maxLines="1" - android:scrollHorizontally="true" - android:singleLine="true" - android:textColor="?attr/dialpad_text_color" - android:textCursorDrawable="@null" - android:textSize="?attr/dialpad_digits_adjustable_text_size" - ex:resizing_text_min_size="@dimen/dialpad_digits_text_min_size"/> - + <FrameLayout android:layout_width="0dp" + android:layout_height="match_parent" + android:layout_weight="1"> + <TextView android:layout_width="match_parent" + android:layout_height="match_parent" + android:id="@+id/digits_hint" + android:focusable="false" + android:gravity="center" + android:textSize="14sp" + android:textColor="@color/secondary_text_color" + android:visibility="gone" + /> + <com.android.dialer.dialpadview.DigitsEditText + xmlns:ex="http://schemas.android.com/apk/res-auto" + android:id="@+id/digits" + android:textStyle="normal" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:background="@android:color/transparent" + android:cursorVisible="false" + android:focusableInTouchMode="true" + android:fontFamily="sans-serif" + android:freezesText="true" + android:gravity="center" + android:importantForAutofill="no" + android:maxLines="1" + android:scrollHorizontally="true" + android:singleLine="true" + android:textColor="?attr/dialpad_text_color" + android:textCursorDrawable="@null" + android:textSize="?attr/dialpad_digits_adjustable_text_size" + ex:resizing_text_min_size="@dimen/dialpad_digits_text_min_size"/> + </FrameLayout> <ImageButton android:id="@+id/deleteButton" android:layout_width="wrap_content" @@ -152,4 +161,4 @@ android:layout_width="match_parent" android:layout_height="@dimen/dialpad_space_below_keys"/> -</view> +</com.android.dialer.dialpadview.DialpadView> diff --git a/java/com/android/dialer/dialpadview/res/values/strings.xml b/java/com/android/dialer/dialpadview/res/values/strings.xml index 51367b644..5d8d8e6a5 100644 --- a/java/com/android/dialer/dialpadview/res/values/strings.xml +++ b/java/com/android/dialer/dialpadview/res/values/strings.xml @@ -97,7 +97,11 @@ Ignored if empty. --> <string name="config_prohibited_phone_number_regexp" translatable="false"></string> + <!-- Warning hint shown in the dialpad input field when emergency call (911, etc.) cannot be made. + [CHAR_LIMIT=60] --> + <string name="dialpad_hint_emergency_calling_not_available">Emergency calling not available</string> + <!-- Dialog message which is shown when the user tries to make a phone call to prohibited phone numbers [CHAR LIMIT=NONE] --> - <string msgid="4313552620858880999" name="dialog_phone_call_prohibited_message">Can\'t call this number</string> + <string name="dialog_phone_call_prohibited_message" msgid="4313552620858880999">Can\'t call this number</string> </resources> diff --git a/java/com/android/dialer/main/Main.java b/java/com/android/dialer/main/Main.java deleted file mode 100644 index e7295f199..000000000 --- a/java/com/android/dialer/main/Main.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2017 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.main; - -import android.content.Context; - -/** Used to display the main activity for Dialer. This hosts favorites, dial pad, search, etc... */ -public interface Main { - - boolean isNewUiEnabled(Context context); - - // TODO(38502365): Remove this when we're ready to launch the new UI. */ - void createNewUiLauncherShortcut(Context context); - - void disableComponentForTesting(Context context); -} diff --git a/java/com/android/dialer/main/impl/AndroidManifest.xml b/java/com/android/dialer/main/impl/AndroidManifest.xml index b3d916bee..4608e4299 100644 --- a/java/com/android/dialer/main/impl/AndroidManifest.xml +++ b/java/com/android/dialer/main/impl/AndroidManifest.xml @@ -22,8 +22,6 @@ <activity android:clearTaskOnLaunch="true" android:directBootAware="true" - android:exported="true" - android:icon="@drawable/nui_launcher_icon" android:label="@string/main_activity_label" android:launchMode="singleTask" android:name="com.android.dialer.main.impl.MainActivity" @@ -31,79 +29,9 @@ android:theme="@style/NuiActivityTheme" android:windowSoftInputMode="stateAlwaysHidden|adjustNothing"> - - <intent-filter> - <action android:name="android.intent.action.DIAL"/> - - <category android:name="android.intent.category.DEFAULT"/> - <category android:name="android.intent.category.BROWSABLE"/> - - <data android:mimeType="vnd.android.cursor.item/phone"/> - <data android:mimeType="vnd.android.cursor.item/person"/> - </intent-filter> - <intent-filter> - <action android:name="android.intent.action.DIAL"/> - - <category android:name="android.intent.category.DEFAULT"/> - <category android:name="android.intent.category.BROWSABLE"/> - - <data android:scheme="voicemail"/> - </intent-filter> - <intent-filter> - <action android:name="android.intent.action.DIAL"/> - <category android:name="android.intent.category.DEFAULT"/> - </intent-filter> - <intent-filter> - <action android:name="android.intent.action.MAIN"/> - - <category android:name="android.intent.category.DEFAULT"/> - <category android:name="android.intent.category.LAUNCHER"/> - <category android:name="android.intent.category.BROWSABLE"/> - </intent-filter> - <intent-filter> - <action android:name="android.intent.action.VIEW"/> - <action android:name="android.intent.action.DIAL"/> - - <category android:name="android.intent.category.DEFAULT"/> - <category android:name="android.intent.category.BROWSABLE"/> - - <data android:scheme="tel"/> - </intent-filter> - <intent-filter> - <action android:name="android.intent.action.VIEW"/> - - <category android:name="android.intent.category.DEFAULT"/> - <category android:name="android.intent.category.BROWSABLE"/> - - <data android:mimeType="vnd.android.cursor.dir/calls"/> - </intent-filter> - <intent-filter> - <action android:name="android.intent.action.CALL_BUTTON"/> - - <category android:name="android.intent.category.DEFAULT"/> - <category android:name="android.intent.category.BROWSABLE"/> - </intent-filter> - <!-- This was never intended to be public, but is here for backward - compatibility. Use Intent.ACTION_DIAL instead. --> - <intent-filter> - <action android:name="com.android.phone.action.TOUCH_DIALER"/> - - <category android:name="android.intent.category.DEFAULT"/> - <category android:name="android.intent.category.TAB"/> - </intent-filter> - <intent-filter android:label="@string/main_call_history_tab_description"> - <action android:name="com.android.phone.action.RECENT_CALLS"/> - - <category android:name="android.intent.category.DEFAULT"/> - <category android:name="android.intent.category.TAB"/> - </intent-filter> - - <meta-data android:name="com.android.keyguard.layout" android:resource="@layout/keyguard_preview"/> </activity> - </application> - </manifest> diff --git a/java/com/android/dialer/main/impl/MainImpl.java b/java/com/android/dialer/main/impl/MainImpl.java deleted file mode 100644 index 717350e5f..000000000 --- a/java/com/android/dialer/main/impl/MainImpl.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2017 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.main.impl; - -import android.content.ComponentName; -import android.content.Context; -import android.content.pm.PackageManager; -import com.android.dialer.configprovider.ConfigProviderBindings; -import com.android.dialer.main.Main; -import javax.inject.Inject; - -/** The entry point for the main feature. */ -final class MainImpl implements Main { - - @Inject - MainImpl() {} - - @Override - public boolean isNewUiEnabled(Context context) { - return ConfigProviderBindings.get(context).getBoolean("is_nui_shortcut_enabled", false); - } - - @Override - public void createNewUiLauncherShortcut(Context context) { - enableComponent(context); - } - - /** - * Enables the NUI activity component. By default the component is disabled and can't be accessed. - * Once the component has been enabled the user will get an option to use the new UI to handle - * DIAL (and other) intents. - */ - private static void enableComponent(Context context) { - context - .getPackageManager() - .setComponentEnabledSetting( - new ComponentName(context, MainActivity.class), - PackageManager.COMPONENT_ENABLED_STATE_ENABLED, - PackageManager.DONT_KILL_APP); - } - - @Override - public void disableComponentForTesting(Context context) { - context - .getPackageManager() - .setComponentEnabledSetting( - new ComponentName(context, MainActivity.class), - PackageManager.COMPONENT_ENABLED_STATE_DISABLED, - PackageManager.DONT_KILL_APP); - } -} diff --git a/java/com/android/dialer/precall/impl/CallingAccountSelector.java b/java/com/android/dialer/precall/impl/CallingAccountSelector.java index b7f071d58..a5dc6a097 100644 --- a/java/com/android/dialer/precall/impl/CallingAccountSelector.java +++ b/java/com/android/dialer/precall/impl/CallingAccountSelector.java @@ -159,6 +159,11 @@ public class CallingAccountSelector implements PreCallAction { LogUtil.i( "CallingAccountSelector.processPreferredAccount", "Auto selected suggestion"); builder.setPhoneAccountHandle(result.getSuggestion().get().phoneAccountHandle); + builder + .getOutgoingCallExtras() + .putString( + SuggestionProvider.EXTRA_SIM_SUGGESTION_REASON, + result.getSuggestion().get().reason.name()); pendingAction.finish(); return; } diff --git a/java/com/android/dialer/precall/impl/MalformedNumberRectifier.java b/java/com/android/dialer/precall/impl/MalformedNumberRectifier.java new file mode 100644 index 000000000..2e414632b --- /dev/null +++ b/java/com/android/dialer/precall/impl/MalformedNumberRectifier.java @@ -0,0 +1,77 @@ +/* + * 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.precall.impl; + +import android.content.Context; +import android.net.Uri; +import android.support.annotation.MainThread; +import android.telecom.PhoneAccount; +import com.android.dialer.callintent.CallIntentBuilder; +import com.android.dialer.precall.PreCallAction; +import com.android.dialer.precall.PreCallCoordinator; +import com.google.common.base.Optional; +import com.google.common.collect.ImmutableList; + +/** + * Fix common malformed number before it is dialed. Rewrite the number to the first handler that can + * handle it + */ +public class MalformedNumberRectifier implements PreCallAction { + + /** Handler for individual rules. */ + public interface MalformedNumberHandler { + + /** @return the number to be corrected to. */ + @MainThread + Optional<String> handle(Context context, String number); + } + + private final ImmutableList<MalformedNumberHandler> handlers; + + MalformedNumberRectifier(ImmutableList<MalformedNumberHandler> handlers) { + this.handlers = handlers; + } + + @Override + public boolean requiresUi(Context context, CallIntentBuilder builder) { + return false; + } + + @Override + public void runWithoutUi(Context context, CallIntentBuilder builder) { + if (!PhoneAccount.SCHEME_TEL.equals(builder.getUri().getScheme())) { + return; + } + String number = builder.getUri().getSchemeSpecificPart(); + + for (MalformedNumberHandler handler : handlers) { + Optional<String> result = handler.handle(context, number); + if (result.isPresent()) { + builder.setUri(Uri.fromParts(PhoneAccount.SCHEME_TEL, result.get(), null)); + return; + } + } + } + + @Override + public void runWithUi(PreCallCoordinator coordinator) { + runWithoutUi(coordinator.getActivity(), coordinator.getBuilder()); + } + + @Override + public void onDiscard() {} +} diff --git a/java/com/android/dialer/precall/impl/PreCallImpl.java b/java/com/android/dialer/precall/impl/PreCallImpl.java index f75c8d9ec..bd23f9ece 100644 --- a/java/com/android/dialer/precall/impl/PreCallImpl.java +++ b/java/com/android/dialer/precall/impl/PreCallImpl.java @@ -39,7 +39,11 @@ public class PreCallImpl implements PreCall { @Override public ImmutableList<PreCallAction> getActions() { return ImmutableList.of( - new PermissionCheckAction(), new CallingAccountSelector(), new AssistedDialAction()); + new PermissionCheckAction(), + new MalformedNumberRectifier( + ImmutableList.of(new UkRegionPrefixInInternationalFormatHandler())), + new CallingAccountSelector(), + new AssistedDialAction()); } @NonNull diff --git a/java/com/android/dialer/precall/impl/UkRegionPrefixInInternationalFormatHandler.java b/java/com/android/dialer/precall/impl/UkRegionPrefixInInternationalFormatHandler.java new file mode 100644 index 000000000..b8f54d873 --- /dev/null +++ b/java/com/android/dialer/precall/impl/UkRegionPrefixInInternationalFormatHandler.java @@ -0,0 +1,69 @@ +/* + * 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.precall.impl; + +import android.content.Context; +import android.telephony.PhoneNumberUtils; +import com.android.dialer.common.LogUtil; +import com.android.dialer.configprovider.ConfigProviderBindings; +import com.android.dialer.precall.impl.MalformedNumberRectifier.MalformedNumberHandler; +import com.google.common.base.Optional; + +/** + * It is customary in UK to present numbers as "+44 (0) xx xxxx xxxx". This is actually a amalgam of + * international (+44 xx xxxx xxxx) and regional (0xx xxxx xxxx) format, and is in fact invalid. It + * might be rejected depending on the carrier. + * + * <p>This class removes the "0" region code prefix if the first dialable digits are "+440". UK + * short codes and region codes in international format will never start with a 0. + */ +class UkRegionPrefixInInternationalFormatHandler implements MalformedNumberHandler { + + private static final String MALFORMED_PREFIX = "+440"; + + @Override + public Optional<String> handle(Context context, String number) { + if (!ConfigProviderBindings.get(context) + .getBoolean("uk_region_prefix_in_international_format_fix_enabled", true)) { + return Optional.absent(); + } + if (!PhoneNumberUtils.normalizeNumber(number).startsWith(MALFORMED_PREFIX)) { + return Optional.absent(); + } + LogUtil.i("UkRegionPrefixInInternationalFormatHandler.handle", "removing (0) in UK numbers"); + + // libPhoneNumber is not used because we want to keep post dial digits, and this is on the main + // thread. + String convertedNumber = PhoneNumberUtils.convertKeypadLettersToDigits(number); + StringBuilder result = new StringBuilder(); + int prefixPosition = 0; + for (int i = 0; i < convertedNumber.length(); i++) { + char c = convertedNumber.charAt(i); + if (c != MALFORMED_PREFIX.charAt(prefixPosition)) { + result.append(c); + continue; + } + prefixPosition++; + if (prefixPosition == MALFORMED_PREFIX.length()) { + result.append(convertedNumber.substring(i + 1)); + break; + } + result.append(c); + } + return Optional.of(result.toString()); + } +} diff --git a/java/com/android/dialer/preferredsim/PreferredAccountWorker.java b/java/com/android/dialer/preferredsim/PreferredAccountWorker.java index aa617889e..df743c342 100644 --- a/java/com/android/dialer/preferredsim/PreferredAccountWorker.java +++ b/java/com/android/dialer/preferredsim/PreferredAccountWorker.java @@ -34,6 +34,7 @@ import android.support.annotation.Nullable; import android.support.annotation.VisibleForTesting; import android.support.annotation.WorkerThread; import android.telecom.PhoneAccountHandle; +import android.text.TextUtils; import com.android.dialer.common.Assert; import com.android.dialer.common.LogUtil; import com.android.dialer.common.concurrent.DialerExecutor.Worker; @@ -128,6 +129,9 @@ public class PreferredAccountWorker implements Worker<Context, Result> { private static Optional<String> getDataId( @NonNull Context context, @Nullable String phoneNumber) { Assert.isWorkerThread(); + if (TextUtils.isEmpty(phoneNumber)) { + return Optional.absent(); + } try (Cursor cursor = context .getContentResolver() diff --git a/java/com/android/dialer/preferredsim/suggestion/SuggestionProvider.java b/java/com/android/dialer/preferredsim/suggestion/SuggestionProvider.java index cfa37c883..f710f734c 100644 --- a/java/com/android/dialer/preferredsim/suggestion/SuggestionProvider.java +++ b/java/com/android/dialer/preferredsim/suggestion/SuggestionProvider.java @@ -30,6 +30,8 @@ import java.util.List; /** Provides hints to the user when selecting a SIM to make a call. */ public interface SuggestionProvider { + String EXTRA_SIM_SUGGESTION_REASON = "sim_suggestion_reason"; + /** The reason the suggestion is made. */ enum Reason { UNKNOWN, diff --git a/java/com/android/incallui/CallCardPresenter.java b/java/com/android/incallui/CallCardPresenter.java index 8eb07c579..49f819bab 100644 --- a/java/com/android/incallui/CallCardPresenter.java +++ b/java/com/android/incallui/CallCardPresenter.java @@ -54,6 +54,7 @@ import com.android.dialer.multimedia.MultimediaData; import com.android.dialer.oem.MotorolaUtils; import com.android.dialer.phonenumberutil.PhoneNumberHelper; import com.android.dialer.postcall.PostCall; +import com.android.dialer.preferredsim.suggestion.SuggestionProvider; import com.android.incallui.ContactInfoCache.ContactCacheEntry; import com.android.incallui.ContactInfoCache.ContactInfoCacheCallback; import com.android.incallui.InCallPresenter.InCallDetailsListener; @@ -478,6 +479,7 @@ public class CallCardPresenter .setSessionModificationState(primary.getVideoTech().getSessionModificationState()) .setDisconnectCause(primary.getDisconnectCause()) .setConnectionLabel(getConnectionLabel()) + .setSimSuggestionReason(getSimSuggestionReason()) .setConnectionIcon(getCallStateIcon()) .setGatewayNumber(getGatewayNumber()) .setCallSubject(shouldShowCallSubject(primary) ? primary.getCallSubject() : null) @@ -988,6 +990,21 @@ public class CallCardPresenter return primary.getCallProviderLabel(); } + @Nullable + private SuggestionProvider.Reason getSimSuggestionReason() { + String value = + primary.getIntentExtras().getString(SuggestionProvider.EXTRA_SIM_SUGGESTION_REASON); + if (value == null) { + return null; + } + try { + return SuggestionProvider.Reason.valueOf(value); + } catch (IllegalArgumentException e) { + LogUtil.e("CallCardPresenter.getConnectionLabel", "unknown reason " + value); + return null; + } + } + private Drawable getCallStateIcon() { // Return connection icon if one exists. StatusHints statusHints = primary.getStatusHints(); diff --git a/java/com/android/incallui/PhoneLookupHistoryRecorder.java b/java/com/android/incallui/PhoneLookupHistoryRecorder.java index 16d73ced9..2b8075878 100644 --- a/java/com/android/incallui/PhoneLookupHistoryRecorder.java +++ b/java/com/android/incallui/PhoneLookupHistoryRecorder.java @@ -20,10 +20,10 @@ import android.content.Context; import android.support.annotation.Nullable; import android.telecom.Call; import com.android.dialer.DialerPhoneNumber; +import com.android.dialer.calllog.config.CallLogConfigComponent; import com.android.dialer.common.Assert; import com.android.dialer.common.LogUtil; import com.android.dialer.common.concurrent.DialerExecutorComponent; -import com.android.dialer.configprovider.ConfigProviderBindings; import com.android.dialer.location.GeoUtil; import com.android.dialer.phonelookup.PhoneLookupComponent; import com.android.dialer.phonelookup.PhoneLookupInfo; @@ -45,11 +45,11 @@ import com.google.i18n.phonenumbers.PhoneNumberUtil; final class PhoneLookupHistoryRecorder { /** - * If the new UI is enabled, fetches the current {@link PhoneLookupInfo} for the provided call and - * writes it to the PhoneLookupHistory. Otherwise does nothing. + * If the call log framework is enabled, fetches the current {@link PhoneLookupInfo} for the + * provided call and writes it to the PhoneLookupHistory. Otherwise does nothing. */ static void recordPhoneLookupInfo(Context appContext, Call call) { - if (!(ConfigProviderBindings.get(appContext).getBoolean("is_nui_shortcut_enabled", false))) { + if (!CallLogConfigComponent.get(appContext).callLogConfig().isCallLogFrameworkEnabled()) { return; } diff --git a/java/com/android/incallui/contactgrid/ContactGridManager.java b/java/com/android/incallui/contactgrid/ContactGridManager.java index 327eaf2b8..d8b1f5004 100644 --- a/java/com/android/incallui/contactgrid/ContactGridManager.java +++ b/java/com/android/incallui/contactgrid/ContactGridManager.java @@ -244,6 +244,10 @@ public class ContactGridManager { statusTextView.setText(info.label); statusTextView.setVisibility(View.VISIBLE); statusTextView.setSingleLine(info.labelIsSingleLine); + // Required to start the marquee + // This will send a AccessibilityEvent.TYPE_VIEW_SELECTED, but has no observable effect on + // talkback. + statusTextView.setSelected(true); } if (info.icon == null) { diff --git a/java/com/android/incallui/contactgrid/TopRow.java b/java/com/android/incallui/contactgrid/TopRow.java index f551092d4..89300caa8 100644 --- a/java/com/android/incallui/contactgrid/TopRow.java +++ b/java/com/android/incallui/contactgrid/TopRow.java @@ -166,7 +166,22 @@ public class TopRow { private static CharSequence getLabelForDialing(Context context, PrimaryCallState state) { if (!TextUtils.isEmpty(state.connectionLabel()) && !state.isWifi()) { - return context.getString(R.string.incall_calling_via_template, state.connectionLabel()); + CharSequence label = getCallingViaLabel(context, state); + + if (state.isAssistedDialed() && state.assistedDialingExtras() != null) { + LogUtil.i("TopRow.getLabelForDialing", "using assisted dialing with via label."); + String countryCode = + String.valueOf(state.assistedDialingExtras().transformedNumberCountryCallingCode()); + label = + TextUtils.concat( + label, + " • ", + context.getString( + R.string.incall_connecting_assited_dialed_component, + countryCode, + state.assistedDialingExtras().userHomeCountryCode())); + } + return label; } else { if (state.isVideoCall()) { if (state.isWifi()) { @@ -189,6 +204,22 @@ public class TopRow { } } + private static CharSequence getCallingViaLabel(Context context, PrimaryCallState state) { + if (state.simSuggestionReason() != null) { + switch (state.simSuggestionReason()) { + case FREQUENT: + return context.getString( + R.string.incall_calling_on_recent_choice_template, state.connectionLabel()); + case INTRA_CARRIER: + return context.getString( + R.string.incall_calling_on_same_carrier_template, state.connectionLabel()); + default: + break; + } + } + return context.getString(R.string.incall_calling_via_template, state.connectionLabel()); + } + private static CharSequence getConnectionLabel(PrimaryCallState state) { if (!TextUtils.isEmpty(state.connectionLabel()) && (isAccount(state) || state.isWifi() || state.isConference())) { diff --git a/java/com/android/incallui/contactgrid/res/layout/incall_contactgrid_top_row.xml b/java/com/android/incallui/contactgrid/res/layout/incall_contactgrid_top_row.xml index 42066f286..2f9ca3ea8 100644 --- a/java/com/android/incallui/contactgrid/res/layout/incall_contactgrid_top_row.xml +++ b/java/com/android/incallui/contactgrid/res/layout/incall_contactgrid_top_row.xml @@ -40,6 +40,8 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:singleLine="true" + android:ellipsize="marquee" + android:scrollHorizontally="true" android:textAppearance="@style/Dialer.Incall.TextAppearance" tools:text="Captain Holt"/> </LinearLayout> diff --git a/java/com/android/incallui/contactgrid/res/values/strings.xml b/java/com/android/incallui/contactgrid/res/values/strings.xml index c6bdb11ba..7c0f5a679 100644 --- a/java/com/android/incallui/contactgrid/res/values/strings.xml +++ b/java/com/android/incallui/contactgrid/res/values/strings.xml @@ -20,6 +20,14 @@ [CHAR LIMIT=40] --> <string name="incall_calling_via_template">Calling via <xliff:g id="provider_name">%s</xliff:g></string> + <!-- Title displayed in the overlay for outgoing calls when the provider is automatically chosen + because it is the same provider the callee is using. [CHAR LIMIT=60] --> + <string name="incall_calling_on_same_carrier_template">Calling on same carrier <xliff:g id="provider_name">%s</xliff:g></string> + + <!-- Title displayed in the overlay for outgoing calls when the provider is automatically chosen + because the user has selected it multiple times. [CHAR LIMIT=60] --> + <string name="incall_calling_on_recent_choice_template">Calling on recent choice <xliff:g id="provider_name">%s</xliff:g></string> + <!-- Displayed above the contact name during an outgoing phone call. Indicates that the call is in the connecting stage. --> <string name="incall_connecting">Calling…</string> @@ -27,6 +35,9 @@ <!-- Display information related to assisted dialing, for example Calling using +1 (US)… --> <string name="incall_connecting_assited_dialed">Calling using +<xliff:g example="1" id="ad_country_code">%1$s</xliff:g> (<xliff:g example="1" id="ad_user_home_locale">%2$s</xliff:g>)\u2026</string> + <!-- String appended to the outgoing call title for additional information related to assisted dialing, for example "Calling via <CARRIER> • Using +1 (US)… "--> + <string name="incall_connecting_assited_dialed_component">Using +<xliff:g example="1" id="ad_country_code">%1$s</xliff:g> (<xliff:g example="1" id="ad_user_home_locale">%2$s</xliff:g>)\u2026</string> + <!-- Displayed above the contact name when an external call is being pulled to the local device. --> <string name="incall_transferring">Transferring…</string> diff --git a/java/com/android/incallui/incall/protocol/PrimaryCallState.java b/java/com/android/incallui/incall/protocol/PrimaryCallState.java index 1d536e9b9..1d23036fc 100644 --- a/java/com/android/incallui/incall/protocol/PrimaryCallState.java +++ b/java/com/android/incallui/incall/protocol/PrimaryCallState.java @@ -23,6 +23,7 @@ import android.telecom.DisconnectCause; import android.text.TextUtils; import com.android.dialer.assisteddialing.TransformationInfo; import com.android.dialer.common.Assert; +import com.android.dialer.preferredsim.suggestion.SuggestionProvider; import com.android.incallui.call.DialerCall; import com.android.incallui.call.DialerCall.State; import com.android.incallui.videotech.utils.SessionModificationState; @@ -60,6 +61,9 @@ public abstract class PrimaryCallState { public abstract String connectionLabel(); @Nullable + public abstract SuggestionProvider.Reason simSuggestionReason(); + + @Nullable public abstract Drawable connectionIcon(); @Nullable @@ -141,6 +145,8 @@ public abstract class PrimaryCallState { public abstract Builder setConnectionLabel(String connectionLabel); + public abstract Builder setSimSuggestionReason(SuggestionProvider.Reason reason); + public abstract Builder setConnectionIcon(Drawable connectionIcon); public abstract Builder setGatewayNumber(String gatewayNumber); diff --git a/java/com/android/voicemail/impl/settings/VisualVoicemailSettingsUtil.java b/java/com/android/voicemail/impl/settings/VisualVoicemailSettingsUtil.java index 3e006988e..e7248c40f 100644 --- a/java/com/android/voicemail/impl/settings/VisualVoicemailSettingsUtil.java +++ b/java/com/android/voicemail/impl/settings/VisualVoicemailSettingsUtil.java @@ -15,18 +15,22 @@ */ package com.android.voicemail.impl.settings; +import android.content.ContentValues; import android.content.Context; +import android.provider.CallLog; +import android.provider.CallLog.Calls; +import android.provider.VoicemailContract.Voicemails; import android.support.annotation.VisibleForTesting; import android.telecom.PhoneAccountHandle; import com.android.dialer.common.Assert; import com.android.dialer.common.concurrent.DialerExecutor.Worker; import com.android.dialer.common.concurrent.DialerExecutorComponent; +import com.android.dialer.common.database.Selection; import com.android.voicemail.VoicemailComponent; import com.android.voicemail.impl.OmtpVvmCarrierConfigHelper; import com.android.voicemail.impl.VisualVoicemailPreferences; import com.android.voicemail.impl.VvmLog; import com.android.voicemail.impl.sync.VvmAccountManager; -import com.android.voicemail.impl.utils.VoicemailDatabaseUtil; /** Save whether or not a particular account is enabled in shared to be retrieved later. */ public class VisualVoicemailSettingsUtil { @@ -88,6 +92,28 @@ public class VisualVoicemailSettingsUtil { .edit() .putBoolean(TRANSCRIBE_VOICEMAILS_KEY, isEnabled) .apply(); + + if (!isEnabled) { + VvmLog.i( + "VisualVoicemailSettingsUtil.setVoicemailTranscriptionEnabled", + "clear all Google transcribed voicemail."); + DialerExecutorComponent.get(context) + .dialerExecutorFactory() + .createNonUiTaskBuilder(new ClearGoogleTranscribedVoicemailTranscriptionWorker(context)) + .onSuccess( + (result) -> + VvmLog.i( + "VisualVoicemailSettingsUtil.setVoicemailTranscriptionEnabled", + "voicemail transciptions cleared successfully")) + .onFailure( + (throwable) -> + VvmLog.e( + "VisualVoicemailSettingsUtil.setVoicemailTranscriptionEnabled", + "unable to clear Google transcribed voicemails", + throwable)) + .build() + .executeParallel(null); + } } public static void setVoicemailDonationEnabled( @@ -153,6 +179,7 @@ public class VisualVoicemailSettingsUtil { return prefs.contains(IS_ENABLED_KEY); } + /** Delete all the voicemails whose source_package field matches this package */ private static class VoicemailDeleteWorker implements Worker<Void, Void> { private final Context context; @@ -162,9 +189,53 @@ public class VisualVoicemailSettingsUtil { @Override public Void doInBackground(Void unused) { - int deleted = VoicemailDatabaseUtil.deleteAll(context); + int deleted = + context + .getContentResolver() + .delete(Voicemails.buildSourceUri(context.getPackageName()), null, null); + VvmLog.i("VisualVoicemailSettingsUtil.doInBackground", "deleted " + deleted + " voicemails"); return null; } } + + /** + * Clears all the voicemail transcripts in the call log whose source_package field matches this + * package + */ + private static class ClearGoogleTranscribedVoicemailTranscriptionWorker + implements Worker<Void, Void> { + private final Context context; + + ClearGoogleTranscribedVoicemailTranscriptionWorker(Context context) { + this.context = context; + } + + @Override + public Void doInBackground(Void unused) { + + ContentValues contentValues = new ContentValues(); + contentValues.put(Voicemails.TRANSCRIPTION, ""); + + Selection selection = + Selection.builder() + .and(Selection.column(CallLog.Calls.TYPE).is("=", Calls.VOICEMAIL_TYPE)) + .and(Selection.column(Voicemails.SOURCE_PACKAGE).is("=", context.getPackageName())) + .build(); + + int cleared = + context + .getContentResolver() + .update( + Calls.CONTENT_URI_WITH_VOICEMAIL, + contentValues, + selection.getSelection(), + selection.getSelectionArgs()); + + VvmLog.i( + "VisualVoicemailSettingsUtil.doInBackground", + "cleared " + cleared + " voicemail transcription"); + return null; + } + } } diff --git a/java/com/android/voicemail/impl/utils/VoicemailDatabaseUtil.java b/java/com/android/voicemail/impl/utils/VoicemailDatabaseUtil.java index ef5447d32..711d6a8a4 100644 --- a/java/com/android/voicemail/impl/utils/VoicemailDatabaseUtil.java +++ b/java/com/android/voicemail/impl/utils/VoicemailDatabaseUtil.java @@ -57,16 +57,6 @@ public class VoicemailDatabaseUtil { return voicemails.size(); } - /** - * Delete all the voicemails whose source_package field matches this package - * - * @return the number of voicemails deleted - */ - public static int deleteAll(Context context) { - ContentResolver contentResolver = context.getContentResolver(); - return contentResolver.delete(Voicemails.buildSourceUri(context.getPackageName()), null, null); - } - /** Maps structured {@link Voicemail} to {@link ContentValues} in content provider. */ private static ContentValues getContentValues(Voicemail voicemail) { ContentValues contentValues = new ContentValues(); diff --git a/packages.mk b/packages.mk index 4ae490c38..f10c33213 100644 --- a/packages.mk +++ b/packages.mk @@ -19,7 +19,7 @@ LOCAL_AAPT_FLAGS := \ com.android.dialer.callcomposer.camera.camerafocus \ com.android.dialer.callcomposer.cameraui \ com.android.dialer.calldetails \ - com.android.dialer.calllog \ + com.android.dialer.calllog.config \ com.android.dialer.calllog.database \ com.android.dialer.calllog.ui \ com.android.dialer.calllog.ui.menu \ |