Dialer: Remove unused Fragments [3/x]
... and the now unused other code
Change-Id: I5b0d82e487dc20347bfe6b97f3dd5df4579cac1d
diff --git a/java/com/android/dialer/binary/aosp/AospDialerRootComponent.java b/java/com/android/dialer/binary/aosp/AospDialerRootComponent.java
index 8181e21..a0acde9 100644
--- a/java/com/android/dialer/binary/aosp/AospDialerRootComponent.java
+++ b/java/com/android/dialer/binary/aosp/AospDialerRootComponent.java
@@ -20,7 +20,6 @@
import com.android.dialer.activecalls.ActiveCallsModule;
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;
@@ -56,7 +55,6 @@
modules = {
ActiveCallsModule.class,
CallLogModule.class,
- CallLogConfigModule.class,
CommandLineModule.class,
ContactsModule.class,
ContextModule.class,
diff --git a/java/com/android/dialer/binary/basecomponent/BaseDialerRootComponent.java b/java/com/android/dialer/binary/basecomponent/BaseDialerRootComponent.java
index acf14b1..7a083f7 100644
--- a/java/com/android/dialer/binary/basecomponent/BaseDialerRootComponent.java
+++ b/java/com/android/dialer/binary/basecomponent/BaseDialerRootComponent.java
@@ -19,7 +19,6 @@
import com.android.bubble.BubbleComponent;
import com.android.dialer.activecalls.ActiveCallsComponent;
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;
@@ -58,7 +57,6 @@
BubbleComponent.HasComponent,
CallLocationComponent.HasComponent,
CallLogComponent.HasComponent,
- CallLogConfigComponent.HasComponent,
CallLogDatabaseComponent.HasComponent,
CallLogUiComponent.HasComponent,
ConfigProviderComponent.HasComponent,
diff --git a/java/com/android/dialer/binary/common/DialerApplication.java b/java/com/android/dialer/binary/common/DialerApplication.java
index 146c252..6520fc0 100644
--- a/java/com/android/dialer/binary/common/DialerApplication.java
+++ b/java/com/android/dialer/binary/common/DialerApplication.java
@@ -19,10 +19,6 @@
import android.app.Application;
import android.os.Trace;
import android.support.annotation.NonNull;
-import com.android.dialer.calllog.CallLogComponent;
-import com.android.dialer.calllog.CallLogFramework;
-import com.android.dialer.calllog.config.CallLogConfig;
-import com.android.dialer.calllog.config.CallLogConfigComponent;
import com.android.dialer.callrecord.CallRecordingAutoMigrator;
import com.android.dialer.common.LogUtil;
import com.android.dialer.common.concurrent.DialerExecutorComponent;
@@ -45,24 +41,11 @@
this.getApplicationContext(),
DialerExecutorComponent.get(this).dialerExecutorFactory())
.asyncAutoMigrate();
- initializeAnnotatedCallLog();
PersistentLogger.initialize(this);
NotificationChannelManager.initChannels(this);
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 35e7809..ee0646b 100644
--- a/java/com/android/dialer/binary/google/GoogleStubDialerRootComponent.java
+++ b/java/com/android/dialer/binary/google/GoogleStubDialerRootComponent.java
@@ -20,7 +20,6 @@
import com.android.dialer.activecalls.ActiveCallsModule;
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;
@@ -60,7 +59,6 @@
ActiveCallsModule.class,
CallLocationModule.class,
CallLogModule.class,
- CallLogConfigModule.class,
CommandLineModule.class,
ContextModule.class,
ContactsModule.class,
diff --git a/java/com/android/dialer/calllog/AndroidManifest.xml b/java/com/android/dialer/calllog/AndroidManifest.xml
index 35a798e..b8ea79f 100644
--- a/java/com/android/dialer/calllog/AndroidManifest.xml
+++ b/java/com/android/dialer/calllog/AndroidManifest.xml
@@ -20,13 +20,6 @@
android:minSdkVersion="24"
android:targetSdkVersion="30"/>
- <application>
-
- <service
- android:exported="false"
- android:name=".CallLogConfig$PollingJob"
- android:permission="android.permission.BIND_JOB_SERVICE"/>
-
- </application>
+ <application/>
</manifest>
diff --git a/java/com/android/dialer/calllog/CallLogFramework.java b/java/com/android/dialer/calllog/CallLogFramework.java
index be4db06..22c0c84 100644
--- a/java/com/android/dialer/calllog/CallLogFramework.java
+++ b/java/com/android/dialer/calllog/CallLogFramework.java
@@ -100,16 +100,7 @@
return Futures.transform(
Futures.allAsList(allFutures),
- unused -> {
- // Send a broadcast to the OldMainActivityPeer to remove the NewCallLogFragment and
- // NewVoicemailFragment if it is currently attached. If this is not done, user interaction
- // with the fragment could cause call log framework state to be unexpectedly written. For
- // example scrolling could cause the AnnotatedCallLog to be read (which would trigger
- // database creation).
- LocalBroadcastManager.getInstance(appContext)
- .sendBroadcastSync(new Intent("disableCallLogFramework"));
- return null;
- },
+ unused -> null,
uiExecutor);
}
}
diff --git a/java/com/android/dialer/calllog/config/AndroidManifest.xml b/java/com/android/dialer/calllog/config/AndroidManifest.xml
deleted file mode 100644
index 80ba1d5..0000000
--- a/java/com/android/dialer/calllog/config/AndroidManifest.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<!--
- ~ 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="30"/>
-
- <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
deleted file mode 100644
index 15fd5c1..0000000
--- a/java/com/android/dialer/calllog/config/CallLogConfig.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * 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/calllog/config/CallLogConfigComponent.java b/java/com/android/dialer/calllog/config/CallLogConfigComponent.java
deleted file mode 100644
index 7aaf638..0000000
--- a/java/com/android/dialer/calllog/config/CallLogConfigComponent.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * 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 android.content.Context;
-import com.android.dialer.inject.HasRootComponent;
-import com.android.dialer.inject.IncludeInDialerRoot;
-import dagger.Subcomponent;
-
-/** Dagger component for the call log config. */
-@Subcomponent
-public abstract class CallLogConfigComponent {
-
- public abstract CallLogConfig callLogConfig();
-
- public static CallLogConfigComponent get(Context context) {
- return ((HasComponent) ((HasRootComponent) context.getApplicationContext()).component())
- .callLogConfigComponent();
- }
-
- /** Used to refer to the root application component. */
- @IncludeInDialerRoot
- public interface HasComponent {
- CallLogConfigComponent callLogConfigComponent();
- }
-}
diff --git a/java/com/android/dialer/calllog/config/CallLogConfigImpl.java b/java/com/android/dialer/calllog/config/CallLogConfigImpl.java
deleted file mode 100644
index 9c7f472..0000000
--- a/java/com/android/dialer/calllog/config/CallLogConfigImpl.java
+++ /dev/null
@@ -1,236 +0,0 @@
-/*
- * 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 android.annotation.SuppressLint;
-import android.app.job.JobInfo;
-import android.app.job.JobParameters;
-import android.app.job.JobScheduler;
-import android.app.job.JobService;
-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.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;
-import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.ListeningExecutorService;
-import com.google.common.util.concurrent.MoreExecutors;
-import java.util.concurrent.TimeUnit;
-import javax.inject.Inject;
-
-/**
- * Determines if new call log components are enabled.
- *
- * <p>When the underlying flag values from the {@link ConfigProvider} changes, it is necessary to do
- * work such as registering/unregistering content observers, and this class is responsible for
- * coordinating that work.
- *
- * <p>New UI application components should use this class instead of reading flags directly from the
- * {@link ConfigProvider}.
- */
-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 =
- "newVoicemailFragmentEnabled";
- private static final String NEW_PEER_ENABLED_PREF_KEY = "newPeerEnabled";
- 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 ListeningExecutorService backgroundExecutor;
-
- @Inject
- public CallLogConfigImpl(
- @ApplicationContext Context appContext,
- CallLogFramework callLogFramework,
- @Unencrypted SharedPreferences sharedPreferences,
- ConfigProvider configProvider,
- @BackgroundExecutor ListeningExecutorService backgroundExecutor) {
- this.appContext = appContext;
- this.callLogFramework = callLogFramework;
- this.sharedPreferences = sharedPreferences;
- this.configProvider = configProvider;
- this.backgroundExecutor = backgroundExecutor;
- }
-
- @Override
- public ListenableFuture<Void> update() {
- boolean newCallLogFragmentEnabledInConfigProvider =
- configProvider.getBoolean("new_call_log_fragment_enabled", false);
- boolean newVoicemailFragmentEnabledInConfigProvider =
- configProvider.getBoolean("new_voicemail_fragment_enabled", false);
- boolean newPeerEnabledInConfigProvider = configProvider.getBoolean("nui_peer_enabled", false);
-
- boolean isCallLogFrameworkEnabled = isCallLogFrameworkEnabled();
- boolean callLogFrameworkShouldBeEnabled =
- newCallLogFragmentEnabledInConfigProvider
- || newVoicemailFragmentEnabledInConfigProvider
- || newPeerEnabledInConfigProvider;
-
- if (callLogFrameworkShouldBeEnabled && !isCallLogFrameworkEnabled) {
- return Futures.transform(
- callLogFramework.enable(),
- unused -> {
- // Reflect the flag changes only after the framework is enabled.
- sharedPreferences
- .edit()
- .putBoolean(
- NEW_CALL_LOG_FRAGMENT_ENABLED_PREF_KEY,
- newCallLogFragmentEnabledInConfigProvider)
- .putBoolean(
- NEW_VOICEMAIL_FRAGMENT_ENABLED_PREF_KEY,
- newVoicemailFragmentEnabledInConfigProvider)
- .putBoolean(NEW_PEER_ENABLED_PREF_KEY, newPeerEnabledInConfigProvider)
- .putBoolean(NEW_CALL_LOG_FRAMEWORK_ENABLED_PREF_KEY, true)
- .apply();
- return null;
- },
- backgroundExecutor);
- } else if (!callLogFrameworkShouldBeEnabled && isCallLogFrameworkEnabled) {
- // Reflect the flag changes before disabling the framework.
- ListenableFuture<Void> writeSharedPrefsFuture =
- backgroundExecutor.submit(
- () -> {
- sharedPreferences
- .edit()
- .putBoolean(NEW_CALL_LOG_FRAGMENT_ENABLED_PREF_KEY, false)
- .putBoolean(NEW_VOICEMAIL_FRAGMENT_ENABLED_PREF_KEY, false)
- .putBoolean(NEW_PEER_ENABLED_PREF_KEY, false)
- .putBoolean(NEW_CALL_LOG_FRAMEWORK_ENABLED_PREF_KEY, false)
- .apply();
- return null;
- });
- return Futures.transformAsync(
- 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.
- return backgroundExecutor.submit(
- () -> {
- sharedPreferences
- .edit()
- .putBoolean(
- NEW_CALL_LOG_FRAGMENT_ENABLED_PREF_KEY,
- newCallLogFragmentEnabledInConfigProvider)
- .putBoolean(
- NEW_VOICEMAIL_FRAGMENT_ENABLED_PREF_KEY,
- newVoicemailFragmentEnabledInConfigProvider)
- .putBoolean(NEW_PEER_ENABLED_PREF_KEY, newPeerEnabledInConfigProvider)
- .apply();
- return null;
- });
- }
- }
-
- @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);
- }
-
- /**
- * 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);
- }
-
- @Override
- public void schedulePollingJob() {
- if (UserManagerCompat.isUserUnlocked(appContext)) {
- JobScheduler jobScheduler = Assert.isNotNull(appContext.getSystemService(JobScheduler.class));
- @SuppressLint("MissingPermission") // Dialer has RECEIVE_BOOT permission
- JobInfo jobInfo =
- new JobInfo.Builder(
- ScheduledJobIds.CALL_LOG_CONFIG_POLLING_JOB,
- new ComponentName(appContext, PollingJob.class))
- .setPeriodic(TimeUnit.HOURS.toMillis(24))
- .setPersisted(true)
- .setRequiresCharging(true)
- .setRequiresDeviceIdle(true)
- .build();
- LogUtil.i("CallLogConfigImpl.schedulePollingJob", "scheduling");
- jobScheduler.schedule(jobInfo);
- }
- }
-
- /**
- * Job which periodically force updates the {@link CallLogConfig}. This job is necessary to
- * support {@link ConfigProvider ConfigProviders} which do not provide a reliable mechanism for
- * listening to changes and calling {@link CallLogConfig#update()} directly, such as the {@link
- * com.android.dialer.configprovider.SharedPrefConfigProvider}.
- */
- public static final class PollingJob extends JobService {
-
- @Override
- public boolean onStartJob(JobParameters params) {
- LogUtil.enterBlock("PollingJob.onStartJob");
- Futures.addCallback(
- CallLogConfigComponent.get(getApplicationContext()).callLogConfig().update(),
- new FutureCallback<Void>() {
- @Override
- public void onSuccess(Void unused) {
- jobFinished(params, false /* needsReschedule */);
- }
-
- @Override
- public void onFailure(Throwable throwable) {
- ThreadUtil.getUiThreadHandler()
- .post(
- () -> {
- throw new RuntimeException(throwable);
- });
- jobFinished(params, false /* needsReschedule */);
- }
- },
- MoreExecutors.directExecutor());
- return true;
- }
-
- @Override
- public boolean onStopJob(JobParameters params) {
- return false;
- }
- }
-}
diff --git a/java/com/android/dialer/calllog/config/CallLogConfigModule.java b/java/com/android/dialer/calllog/config/CallLogConfigModule.java
deleted file mode 100644
index d982e2b..0000000
--- a/java/com/android/dialer/calllog/config/CallLogConfigModule.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * 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 dagger.Binds;
-import dagger.Module;
-
-/** Binds {@link CallLogConfigImpl}. */
-@Module
-public abstract class CallLogConfigModule {
- @Binds
- abstract CallLogConfig to(CallLogConfigImpl impl);
-}
diff --git a/java/com/android/dialer/calllog/ui/HeaderViewHolder.java b/java/com/android/dialer/calllog/ui/HeaderViewHolder.java
deleted file mode 100644
index e4fe029..0000000
--- a/java/com/android/dialer/calllog/ui/HeaderViewHolder.java
+++ /dev/null
@@ -1,36 +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.calllog.ui;
-
-import android.support.annotation.StringRes;
-import android.support.v7.widget.RecyclerView.ViewHolder;
-import android.view.View;
-import android.widget.TextView;
-
-/** ViewHolder for {@link NewCallLogAdapter} to display "Today" or "Older" divider row. */
-final class HeaderViewHolder extends ViewHolder {
-
- private TextView headerTextView;
-
- HeaderViewHolder(View view) {
- super(view);
- headerTextView = view.findViewById(R.id.new_call_log_header_text);
- }
-
- void setHeader(@StringRes int header) {
- headerTextView.setText(header);
- }
-}
diff --git a/java/com/android/dialer/calllog/ui/NewCallLogAdapter.java b/java/com/android/dialer/calllog/ui/NewCallLogAdapter.java
deleted file mode 100644
index 185a93e..0000000
--- a/java/com/android/dialer/calllog/ui/NewCallLogAdapter.java
+++ /dev/null
@@ -1,330 +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.calllog.ui;
-
-import android.app.Activity;
-import android.content.Context;
-import android.support.annotation.IntDef;
-import android.support.annotation.Nullable;
-import android.support.v7.widget.RecyclerView;
-import android.support.v7.widget.RecyclerView.ViewHolder;
-import android.view.LayoutInflater;
-import android.view.ViewGroup;
-import com.android.dialer.calllog.model.CoalescedRow;
-import com.android.dialer.calllogutils.CallLogDates;
-import com.android.dialer.common.Assert;
-import com.android.dialer.logging.Logger;
-import com.android.dialer.promotion.Promotion;
-import com.android.dialer.time.Clock;
-import com.google.common.collect.ImmutableList;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/** {@link RecyclerView.Adapter} for the new call log fragment. */
-final class NewCallLogAdapter extends RecyclerView.Adapter<ViewHolder> {
-
- /** IntDef for the different types of rows that can be shown in the call log. */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef({
- RowType.PROMOTION_CARD,
- RowType.HEADER_TODAY,
- RowType.HEADER_YESTERDAY,
- RowType.HEADER_OLDER,
- RowType.CALL_LOG_ENTRY
- })
- @interface RowType {
- /** The promotion card. */
- int PROMOTION_CARD = 1;
-
- /** Header that displays "Today". */
- int HEADER_TODAY = 2;
-
- /** Header that displays "Yesterday". */
- int HEADER_YESTERDAY = 3;
-
- /** Header that displays "Older". */
- int HEADER_OLDER = 4;
-
- /** A row representing a call log entry (which could represent one or more calls). */
- int CALL_LOG_ENTRY = 5;
- }
-
- private final Clock clock;
- private final Activity activity;
- private final RealtimeRowProcessor realtimeRowProcessor;
- private final PopCounts popCounts = new PopCounts();
- @Nullable private final Promotion promotion;
-
- private ImmutableList<CoalescedRow> coalescedRows;
-
- /** Position of the promotion card. Null when it should not be displayed. */
- @Nullable private Integer promotionCardPosition;
-
- /** Position of the "Today" header. Null when it should not be displayed. */
- @Nullable private Integer todayHeaderPosition;
-
- /** Position of the "Yesterday" header. Null when it should not be displayed. */
- @Nullable private Integer yesterdayHeaderPosition;
-
- /** Position of the "Older" header. Null when it should not be displayed. */
- @Nullable private Integer olderHeaderPosition;
-
- NewCallLogAdapter(
- Activity activity,
- ImmutableList<CoalescedRow> coalescedRows,
- Clock clock,
- @Nullable Promotion promotion) {
- this.activity = activity;
- this.coalescedRows = coalescedRows;
- this.clock = clock;
- this.realtimeRowProcessor = CallLogUiComponent.get(activity).realtimeRowProcessor();
- this.promotion = promotion;
-
- setCardAndHeaderPositions();
- }
-
- void updateRows(ImmutableList<CoalescedRow> coalescedRows) {
- this.coalescedRows = coalescedRows;
- this.realtimeRowProcessor.clearCache();
- this.popCounts.reset();
-
- setCardAndHeaderPositions();
- notifyDataSetChanged();
- }
-
- void clearCache() {
- this.realtimeRowProcessor.clearCache();
- }
-
- void logMetrics(Context context) {
- Logger.get(context).logAnnotatedCallLogMetrics(popCounts.popped, popCounts.didNotPop);
- }
-
- private void setCardAndHeaderPositions() {
- // Set the position for the promotion card if it should be shown.
- promotionCardPosition = null;
- int numCards = 0;
- if (promotion != null && promotion.isEligibleToBeShown()) {
- promotionCardPosition = 0;
- numCards++;
- }
-
- // If there are no rows to display, set all header positions to null.
- if (coalescedRows.isEmpty()) {
- todayHeaderPosition = null;
- yesterdayHeaderPosition = null;
- olderHeaderPosition = null;
- return;
- }
-
- // Calculate positions for headers.
- long currentTimeMillis = clock.currentTimeMillis();
-
- int numItemsInToday = 0;
- int numItemsInYesterday = 0;
- int numItemsInOlder = 0;
- for (CoalescedRow coalescedRow : coalescedRows) {
- long timestamp = coalescedRow.getTimestamp();
- long dayDifference = CallLogDates.getDayDifference(currentTimeMillis, timestamp);
- if (dayDifference == 0) {
- numItemsInToday++;
- } else if (dayDifference == 1) {
- numItemsInYesterday++;
- } else {
- numItemsInOlder = coalescedRows.size() - numItemsInToday - numItemsInYesterday;
- break;
- }
- }
-
- if (numItemsInToday > 0) {
- numItemsInToday++; // including the "Today" header;
- }
- if (numItemsInYesterday > 0) {
- numItemsInYesterday++; // including the "Yesterday" header;
- }
- if (numItemsInOlder > 0) {
- numItemsInOlder++; // include the "Older" header;
- }
-
- // Set all header positions.
- // A header position will be null if there is no item to be displayed under that header.
- todayHeaderPosition = numItemsInToday > 0 ? numCards : null;
- yesterdayHeaderPosition = numItemsInYesterday > 0 ? numItemsInToday + numCards : null;
- olderHeaderPosition =
- numItemsInOlder > 0 ? numItemsInToday + numItemsInYesterday + numCards : null;
- }
-
- @Override
- public void onAttachedToRecyclerView(RecyclerView recyclerView) {
- super.onAttachedToRecyclerView(recyclerView);
-
- // Register a OnScrollListener that records when the promotion is viewed.
- if (promotion != null && promotion.isEligibleToBeShown()) {
- recyclerView.addOnScrollListener(
- new OnScrollListenerForRecordingPromotionCardFirstViewTime(promotion));
- }
- }
-
- @Override
- public ViewHolder onCreateViewHolder(ViewGroup viewGroup, @RowType int viewType) {
- switch (viewType) {
- case RowType.PROMOTION_CARD:
- return new PromotionCardViewHolder(
- LayoutInflater.from(activity)
- .inflate(
- R.layout.new_call_log_promotion_card, viewGroup, /* attachToRoot = */ false),
- promotion);
- case RowType.HEADER_TODAY:
- case RowType.HEADER_YESTERDAY:
- case RowType.HEADER_OLDER:
- return new HeaderViewHolder(
- LayoutInflater.from(activity)
- .inflate(R.layout.new_call_log_header, viewGroup, /* attachToRoot = */ false));
- case RowType.CALL_LOG_ENTRY:
- return new NewCallLogViewHolder(
- activity,
- LayoutInflater.from(activity)
- .inflate(R.layout.new_call_log_entry, viewGroup, /* attachToRoot = */ false),
- clock,
- realtimeRowProcessor,
- popCounts);
- default:
- throw Assert.createUnsupportedOperationFailException("Unsupported view type: " + viewType);
- }
- }
-
- @Override
- public void onBindViewHolder(ViewHolder viewHolder, int position) {
- @RowType int viewType = getItemViewType(position);
- switch (viewType) {
- case RowType.PROMOTION_CARD:
- ((PromotionCardViewHolder) viewHolder)
- .setDismissListener(
- () -> {
- notifyItemRemoved(promotionCardPosition);
- setCardAndHeaderPositions();
- });
- break;
- case RowType.HEADER_TODAY:
- ((HeaderViewHolder) viewHolder).setHeader(R.string.new_call_log_header_today);
- break;
- case RowType.HEADER_YESTERDAY:
- ((HeaderViewHolder) viewHolder).setHeader(R.string.new_call_log_header_yesterday);
- break;
- case RowType.HEADER_OLDER:
- ((HeaderViewHolder) viewHolder).setHeader(R.string.new_call_log_header_older);
- break;
- case RowType.CALL_LOG_ENTRY:
- NewCallLogViewHolder newCallLogViewHolder = (NewCallLogViewHolder) viewHolder;
- int previousCardAndHeaders = 0;
- if (promotionCardPosition != null && position > promotionCardPosition) {
- previousCardAndHeaders++;
- }
- if (todayHeaderPosition != null && position > todayHeaderPosition) {
- previousCardAndHeaders++;
- }
- if (yesterdayHeaderPosition != null && position > yesterdayHeaderPosition) {
- previousCardAndHeaders++;
- }
- if (olderHeaderPosition != null && position > olderHeaderPosition) {
- previousCardAndHeaders++;
- }
- newCallLogViewHolder.bind(coalescedRows.get(position - previousCardAndHeaders));
- break;
- default:
- throw Assert.createIllegalStateFailException(
- "Unexpected view type " + viewType + " at position: " + position);
- }
- }
-
- @Override
- @RowType
- public int getItemViewType(int position) {
- if (promotionCardPosition != null && position == promotionCardPosition) {
- return RowType.PROMOTION_CARD;
- }
- if (todayHeaderPosition != null && position == todayHeaderPosition) {
- return RowType.HEADER_TODAY;
- }
- if (yesterdayHeaderPosition != null && position == yesterdayHeaderPosition) {
- return RowType.HEADER_YESTERDAY;
- }
- if (olderHeaderPosition != null && position == olderHeaderPosition) {
- return RowType.HEADER_OLDER;
- }
- return RowType.CALL_LOG_ENTRY;
- }
-
- @Override
- public int getItemCount() {
- int numberOfCards = 0;
- int numberOfHeaders = 0;
-
- if (promotionCardPosition != null) {
- numberOfCards++;
- }
- if (todayHeaderPosition != null) {
- numberOfHeaders++;
- }
- if (yesterdayHeaderPosition != null) {
- numberOfHeaders++;
- }
- if (olderHeaderPosition != null) {
- numberOfHeaders++;
- }
- return coalescedRows.size() + numberOfHeaders + numberOfCards;
- }
-
- /**
- * A {@link RecyclerView.OnScrollListener} that records the timestamp at which the promotion card
- * is first viewed.
- *
- * <p>We consider the card as viewed if the user scrolls the containing RecyclerView since such
- * action is a strong proof.
- */
- private static final class OnScrollListenerForRecordingPromotionCardFirstViewTime
- extends RecyclerView.OnScrollListener {
-
- private final Promotion promotion;
-
- OnScrollListenerForRecordingPromotionCardFirstViewTime(Promotion promotion) {
- this.promotion = promotion;
- }
-
- @Override
- public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
- if (newState == RecyclerView.SCROLL_STATE_SETTLING) {
- promotion.onViewed();
-
- // Recording promotion is viewed is this listener's sole responsibility.
- // We can remove it from the containing RecyclerView after the job is done.
- recyclerView.removeOnScrollListener(this);
- }
-
- super.onScrollStateChanged(recyclerView, newState);
- }
- }
-
- static class PopCounts {
- int popped;
- int didNotPop;
-
- private void reset() {
- popped = 0;
- didNotPop = 0;
- }
- }
-}
diff --git a/java/com/android/dialer/calllog/ui/NewCallLogFragment.java b/java/com/android/dialer/calllog/ui/NewCallLogFragment.java
deleted file mode 100644
index 62f99b6..0000000
--- a/java/com/android/dialer/calllog/ui/NewCallLogFragment.java
+++ /dev/null
@@ -1,356 +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.calllog.ui;
-
-import android.app.Activity;
-import android.database.Cursor;
-import android.os.Bundle;
-import android.support.annotation.Nullable;
-import android.support.annotation.VisibleForTesting;
-import android.support.v4.app.Fragment;
-import android.support.v4.app.LoaderManager;
-import android.support.v4.app.LoaderManager.LoaderCallbacks;
-import android.support.v4.content.Loader;
-import android.support.v4.content.LocalBroadcastManager;
-import android.support.v7.widget.LinearLayoutManager;
-import android.support.v7.widget.RecyclerView;
-import android.view.LayoutInflater;
-import android.view.View;
-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;
-import com.android.dialer.common.concurrent.DefaultFutureCallback;
-import com.android.dialer.common.concurrent.DialerExecutorComponent;
-import com.android.dialer.common.concurrent.SupportUiListener;
-import com.android.dialer.common.concurrent.ThreadUtil;
-import com.android.dialer.metrics.Metrics;
-import com.android.dialer.metrics.MetricsComponent;
-import com.android.dialer.metrics.jank.RecyclerViewJankLogger;
-import com.android.dialer.promotion.Promotion.PromotionType;
-import com.android.dialer.promotion.PromotionComponent;
-import com.android.dialer.util.PermissionsUtil;
-import com.android.dialer.widget.EmptyContentView;
-import com.android.dialer.widget.EmptyContentView.OnEmptyViewActionButtonClickedListener;
-import com.google.common.collect.ImmutableList;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.MoreExecutors;
-import java.util.Arrays;
-import java.util.concurrent.TimeUnit;
-
-/** The "new" call log fragment implementation, which is built on top of the annotated call log. */
-public final class NewCallLogFragment extends Fragment implements LoaderCallbacks<Cursor> {
-
- private static final int PHONE_PERMISSIONS_REQUEST_CODE = 1;
- private static final int LOADER_ID = 0;
-
- @VisibleForTesting
- static final long MARK_ALL_CALLS_READ_WAIT_MILLIS = TimeUnit.SECONDS.toMillis(3);
-
- private RecyclerView recyclerView;
- private EmptyContentView emptyContentView;
- private RefreshAnnotatedCallLogReceiver refreshAnnotatedCallLogReceiver;
- private SupportUiListener<ImmutableList<CoalescedRow>> coalesingAnnotatedCallLogListener;
-
- private boolean shouldMarkCallsRead = false;
- private final Runnable setShouldMarkCallsReadTrue = () -> shouldMarkCallsRead = true;
-
- public NewCallLogFragment() {
- LogUtil.enterBlock("NewCallLogFragment.NewCallLogFragment");
- }
-
- @Override
- public void onActivityCreated(@Nullable Bundle savedInstanceState) {
- super.onActivityCreated(savedInstanceState);
-
- LogUtil.enterBlock("NewCallLogFragment.onActivityCreated");
-
- refreshAnnotatedCallLogReceiver = new RefreshAnnotatedCallLogReceiver(getContext());
- }
-
- @Override
- public void onStart() {
- super.onStart();
-
- LogUtil.enterBlock("NewCallLogFragment.onStart");
- }
-
- @Override
- public void onResume() {
- super.onResume();
-
- boolean isHidden = isHidden();
- LogUtil.i("NewCallLogFragment.onResume", "isHidden = %s", isHidden);
-
- // As a fragment's onResume() is tied to the containing Activity's onResume(), being resumed is
- // not equivalent to becoming visible.
- // For example, when an activity with a hidden fragment is resumed, the fragment's onResume()
- // will be called but it is not visible.
- if (!isHidden) {
- onFragmentShown();
- }
- }
-
- @Override
- public void onStop() {
- super.onStop();
-
- if (recyclerView.getAdapter() != null) {
- ((NewCallLogAdapter) recyclerView.getAdapter()).logMetrics(getContext());
- }
- }
-
- @Override
- public void onPause() {
- super.onPause();
- LogUtil.enterBlock("NewCallLogFragment.onPause");
-
- onFragmentHidden();
- }
-
- @Override
- public void onHiddenChanged(boolean hidden) {
- super.onHiddenChanged(hidden);
- LogUtil.i("NewCallLogFragment.onHiddenChanged", "hidden = %s", hidden);
-
- if (hidden) {
- onFragmentHidden();
- } else {
- onFragmentShown();
- }
- }
-
- /**
- * To be called when the fragment becomes visible.
- *
- * <p>Note that for a fragment, being resumed is not equivalent to becoming visible.
- *
- * <p>For example, when an activity with a hidden fragment is resumed, the fragment's onResume()
- * will be called but it is not visible.
- */
- private void onFragmentShown() {
- LoaderManager loaderManager = getLoaderManager();
- if (!PermissionsUtil.hasCallLogReadPermissions(getContext())) {
- recyclerView.setVisibility(View.GONE);
- emptyContentView.setVisibility(View.VISIBLE);
- loaderManager.destroyLoader(LOADER_ID);
- return;
- }
-
- recyclerView.setVisibility(View.VISIBLE);
- emptyContentView.setVisibility(View.GONE);
-
- // This can happen if permissions were not enabled when the fragment was created.
- if (loaderManager.getLoader(LOADER_ID) == null) {
- loaderManager.restartLoader(LOADER_ID, null, this);
- }
-
- registerRefreshAnnotatedCallLogReceiver();
-
- CallLogComponent.get(getContext())
- .getRefreshAnnotatedCallLogNotifier()
- .notify(/* checkDirty = */ true);
-
- // There are some types of data that we show in the call log that are not represented in the
- // AnnotatedCallLog. For example, CP2 information for invalid numbers can sometimes only be
- // fetched at display time. Because of this, we need to clear the adapter's cache and update it
- // whenever the user arrives at the call log (rather than relying on changes to the CursorLoader
- // alone).
- if (recyclerView.getAdapter() != null) {
- ((NewCallLogAdapter) recyclerView.getAdapter()).clearCache();
- recyclerView.getAdapter().notifyDataSetChanged();
- }
-
- // We shouldn't mark the calls as read immediately when the 3 second timer expires because we
- // don't want to disrupt the UI; instead we set a bit indicating to mark them read when the user
- // leaves the fragment (in onPause).
- shouldMarkCallsRead = false;
- ThreadUtil.getUiThreadHandler()
- .postDelayed(setShouldMarkCallsReadTrue, MARK_ALL_CALLS_READ_WAIT_MILLIS);
- }
-
- /**
- * To be called when the fragment becomes hidden.
- *
- * <p>This can happen in the following two cases:
- *
- * <ul>
- * <li>hide the fragment but keep the parent activity visible (e.g., calling {@link
- * android.support.v4.app.FragmentTransaction#hide(Fragment)} in an activity, or
- * <li>the parent activity is paused.
- * </ul>
- */
- private void onFragmentHidden() {
- // This is pending work that we don't actually need to follow through with.
- ThreadUtil.getUiThreadHandler().removeCallbacks(setShouldMarkCallsReadTrue);
-
- unregisterRefreshAnnotatedCallLogReceiver();
-
- if (shouldMarkCallsRead) {
- Futures.addCallback(
- CallLogComponent.get(getContext()).getClearMissedCalls().clearAll(),
- new DefaultFutureCallback<>(),
- MoreExecutors.directExecutor());
- }
- }
-
- @Override
- public View onCreateView(
- LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- LogUtil.enterBlock("NewCallLogFragment.onCreateView");
-
- View view = inflater.inflate(R.layout.new_call_log_fragment, container, false);
- recyclerView = view.findViewById(R.id.new_call_log_recycler_view);
- recyclerView.addOnScrollListener(
- new RecyclerViewJankLogger(
- MetricsComponent.get(getContext()).metrics(), Metrics.NEW_CALL_LOG_JANK_EVENT_NAME));
-
- emptyContentView = view.findViewById(R.id.new_call_log_empty_content_view);
- configureEmptyContentView();
-
- coalesingAnnotatedCallLogListener =
- DialerExecutorComponent.get(getContext())
- .createUiListener(
- getChildFragmentManager(),
- /* taskId = */ "NewCallLogFragment.coalescingAnnotatedCallLog");
-
- if (PermissionsUtil.hasCallLogReadPermissions(getContext())) {
- getLoaderManager().restartLoader(LOADER_ID, null, this);
- }
-
- return view;
- }
-
- private void configureEmptyContentView() {
- emptyContentView.setImage(R.drawable.quantum_ic_query_builder_vd_theme_24);
- emptyContentView.setDescription(R.string.new_call_log_permission_no_calllog);
- emptyContentView.setActionLabel(com.android.dialer.widget.R.string.permission_single_turn_on);
- emptyContentView.setActionClickedListener(new TurnOnPhonePermissions());
- }
-
- private class TurnOnPhonePermissions implements OnEmptyViewActionButtonClickedListener {
-
- @Override
- public void onEmptyViewActionButtonClicked() {
- if (getContext() == null) {
- LogUtil.w("TurnOnPhonePermissions.onEmptyViewActionButtonClicked", "no context");
- return;
- }
- String[] deniedPermissions =
- PermissionsUtil.getPermissionsCurrentlyDenied(
- getContext(), PermissionsUtil.allPhoneGroupPermissionsUsedInDialer);
- if (deniedPermissions.length > 0) {
- LogUtil.i(
- "TurnOnPhonePermissions.onEmptyViewActionButtonClicked",
- "requesting permissions: %s",
- Arrays.toString(deniedPermissions));
- // Don't implement onRequestPermissionsResult; instead rely on views being updated in
- // #onFragmentShown.
- requestPermissions(deniedPermissions, PHONE_PERMISSIONS_REQUEST_CODE);
- }
- }
- }
-
- private void registerRefreshAnnotatedCallLogReceiver() {
- LogUtil.enterBlock("NewCallLogFragment.registerRefreshAnnotatedCallLogReceiver");
-
- LocalBroadcastManager.getInstance(getContext())
- .registerReceiver(
- refreshAnnotatedCallLogReceiver, RefreshAnnotatedCallLogReceiver.getIntentFilter());
- }
-
- private void unregisterRefreshAnnotatedCallLogReceiver() {
- LogUtil.enterBlock("NewCallLogFragment.unregisterRefreshAnnotatedCallLogReceiver");
-
- // Cancel pending work as we don't need it any more.
- CallLogComponent.get(getContext()).getRefreshAnnotatedCallLogNotifier().cancel();
-
- LocalBroadcastManager.getInstance(getContext())
- .unregisterReceiver(refreshAnnotatedCallLogReceiver);
- }
-
- @Override
- public Loader<Cursor> onCreateLoader(int id, Bundle args) {
- LogUtil.enterBlock("NewCallLogFragment.onCreateLoader");
- return new AnnotatedCallLogCursorLoader(Assert.isNotNull(getContext()));
- }
-
- @Override
- public void onLoadFinished(Loader<Cursor> loader, Cursor newCursor) {
- LogUtil.enterBlock("NewCallLogFragment.onLoadFinished");
-
- if (newCursor == null) {
- // This might be possible when the annotated call log hasn't been created but we're trying
- // to show the call log.
- LogUtil.w("NewCallLogFragment.onLoadFinished", "null cursor");
- return;
- }
-
- // Start combining adjacent rows which should be collapsed for display purposes.
- // This is a time-consuming process so we will do it in the background.
- ListenableFuture<ImmutableList<CoalescedRow>> coalescedRowsFuture =
- CallLogDatabaseComponent.get(getContext()).coalescer().coalesce(newCursor);
-
- coalesingAnnotatedCallLogListener.listen(
- getContext(),
- coalescedRowsFuture,
- coalescedRows -> {
- LogUtil.i("NewCallLogFragment.onLoadFinished", "coalescing succeeded");
-
- // TODO(zachh): Handle empty cursor by showing empty view.
- if (recyclerView.getAdapter() == null) {
- recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
- // Note: It's not clear if this callback can be invoked when there's no associated
- // activity, but if crashes are observed here it may be possible to use getContext()
- // instead.
- Activity activity = Assert.isNotNull(getActivity());
- recyclerView.setAdapter(
- new NewCallLogAdapter(
- activity,
- coalescedRows,
- System::currentTimeMillis,
- PromotionComponent.get(getContext())
- .promotionManager()
- .getHighestPriorityPromotion(PromotionType.CARD)
- .orElse(null)));
- } else {
- ((NewCallLogAdapter) recyclerView.getAdapter()).updateRows(coalescedRows);
- }
- },
- throwable -> {
- // 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);
- }
- });
- }
-
- @Override
- public void onLoaderReset(Loader<Cursor> loader) {
- LogUtil.enterBlock("NewCallLogFragment.onLoaderReset");
- recyclerView.setAdapter(null);
- }
-}
diff --git a/java/com/android/dialer/calllog/ui/NewCallLogViewHolder.java b/java/com/android/dialer/calllog/ui/NewCallLogViewHolder.java
deleted file mode 100644
index a6e3c99..0000000
--- a/java/com/android/dialer/calllog/ui/NewCallLogViewHolder.java
+++ /dev/null
@@ -1,345 +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.calllog.ui;
-
-import android.app.Activity;
-import android.content.res.ColorStateList;
-import android.provider.CallLog.Calls;
-import android.support.annotation.ColorInt;
-import android.support.annotation.DrawableRes;
-import android.support.v7.widget.RecyclerView;
-import android.telecom.PhoneAccount;
-import android.telecom.PhoneAccountHandle;
-import android.text.TextUtils;
-import android.view.View;
-import android.view.View.AccessibilityDelegate;
-import android.view.accessibility.AccessibilityNodeInfo;
-import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
-import android.widget.ImageView;
-import android.widget.TextView;
-import com.android.dialer.calllog.model.CoalescedRow;
-import com.android.dialer.calllog.ui.NewCallLogAdapter.PopCounts;
-import com.android.dialer.calllog.ui.menu.NewCallLogMenu;
-import com.android.dialer.calllogutils.CallLogEntryDescriptions;
-import com.android.dialer.calllogutils.CallLogEntryText;
-import com.android.dialer.calllogutils.CallLogRowActions;
-import com.android.dialer.calllogutils.PhoneAccountUtils;
-import com.android.dialer.calllogutils.PhotoInfoBuilder;
-import com.android.dialer.common.concurrent.DialerExecutorComponent;
-import com.android.dialer.compat.telephony.TelephonyManagerCompat;
-import com.android.dialer.oem.MotorolaUtils;
-import com.android.dialer.phonenumberutil.PhoneNumberHelper;
-import com.android.dialer.telecom.TelecomUtil;
-import com.android.dialer.time.Clock;
-import com.android.dialer.widget.ContactPhotoView;
-import com.google.common.util.concurrent.FutureCallback;
-import com.google.common.util.concurrent.Futures;
-import java.util.Locale;
-import java.util.concurrent.ExecutorService;
-
-/** {@link RecyclerView.ViewHolder} for the new call log. */
-final class NewCallLogViewHolder extends RecyclerView.ViewHolder {
-
- private final Activity activity;
- private final ContactPhotoView contactPhotoView;
- private final TextView primaryTextView;
- private final TextView callCountTextView;
- private final TextView secondaryTextView;
- private final ImageView callTypeIcon;
- private final ImageView hdIcon;
- private final ImageView wifiIcon;
- private final ImageView assistedDialIcon;
- private final TextView phoneAccountView;
- private final ImageView callButton;
- private final View callLogEntryRootView;
-
- private final Clock clock;
- private final RealtimeRowProcessor realtimeRowProcessor;
- private final ExecutorService uiExecutorService;
- private final PopCounts popCounts;
-
- private long currentRowId;
-
- NewCallLogViewHolder(
- Activity activity,
- View view,
- Clock clock,
- RealtimeRowProcessor realtimeRowProcessor,
- PopCounts popCounts) {
- super(view);
- this.activity = activity;
- callLogEntryRootView = view;
- contactPhotoView = view.findViewById(R.id.contact_photo_view);
- primaryTextView = view.findViewById(R.id.primary_text);
- callCountTextView = view.findViewById(R.id.call_count);
- secondaryTextView = view.findViewById(R.id.secondary_text);
- callTypeIcon = view.findViewById(R.id.call_type_icon);
- hdIcon = view.findViewById(R.id.hd_icon);
- wifiIcon = view.findViewById(R.id.wifi_icon);
- assistedDialIcon = view.findViewById(R.id.assisted_dial_icon);
- phoneAccountView = view.findViewById(R.id.phone_account);
- callButton = view.findViewById(R.id.call_button);
-
- this.clock = clock;
- this.realtimeRowProcessor = realtimeRowProcessor;
- this.popCounts = popCounts;
- uiExecutorService = DialerExecutorComponent.get(activity).uiExecutor();
- }
-
- void bind(CoalescedRow coalescedRow) {
- // The row ID is used to make sure async updates are applied to the correct views.
- currentRowId = coalescedRow.getId();
-
- // Even if there is additional real time processing necessary, we still want to immediately show
- // what information we have, rather than an empty card. For example, if CP2 information needs to
- // be queried on the fly, we can still show the phone number until the contact name loads.
- displayRow(coalescedRow);
- configA11yForRow(coalescedRow);
-
- // Note: This leaks the view holder via the callback (which is an inner class), but this is OK
- // because we only create ~10 of them (and they'll be collected assuming all jobs finish).
- Futures.addCallback(
- realtimeRowProcessor.applyRealtimeProcessing(coalescedRow),
- new RealtimeRowFutureCallback(coalescedRow),
- uiExecutorService);
- }
-
- private void displayRow(CoalescedRow row) {
- // TODO(zachh): Handle RTL properly.
- primaryTextView.setText(CallLogEntryText.buildPrimaryText(activity, row));
- secondaryTextView.setText(CallLogEntryText.buildSecondaryTextForEntries(activity, clock, row));
-
- if (isUnreadMissedCall(row)) {
- primaryTextView.setTextAppearance(R.style.primary_textview_unread_call);
- callCountTextView.setTextAppearance(R.style.primary_textview_unread_call);
- secondaryTextView.setTextAppearance(R.style.secondary_textview_unread_call);
- phoneAccountView.setTextAppearance(R.style.phoneaccount_textview_unread_call);
- } else {
- primaryTextView.setTextAppearance(R.style.primary_textview);
- callCountTextView.setTextAppearance(R.style.primary_textview);
- secondaryTextView.setTextAppearance(R.style.secondary_textview);
- phoneAccountView.setTextAppearance(R.style.phoneaccount_textview);
- }
-
- setNumberCalls(row);
- setPhoto(row);
- setFeatureIcons(row);
- setCallTypeIcon(row);
- setPhoneAccounts(row);
- setCallButon(row);
-
- itemView.setOnClickListener(NewCallLogMenu.createOnClickListener(activity, row));
- }
-
- private void configA11yForRow(CoalescedRow row) {
- callLogEntryRootView.setContentDescription(
- CallLogEntryDescriptions.buildDescriptionForEntry(activity, clock, row));
-
- // Inform a11y users that double tapping an entry now makes a call.
- // This will instruct TalkBack to say "double tap to call" instead of
- // "double tap to activate".
- callLogEntryRootView.setAccessibilityDelegate(
- new AccessibilityDelegate() {
- @Override
- public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
- super.onInitializeAccessibilityNodeInfo(host, info);
- info.addAction(
- new AccessibilityAction(
- AccessibilityNodeInfo.ACTION_CLICK,
- activity
- .getResources()
- .getString(R.string.a11y_new_call_log_entry_tap_action)));
- }
- });
- }
-
- private void setNumberCalls(CoalescedRow row) {
- int numberCalls = row.getCoalescedIds().getCoalescedIdCount();
- if (numberCalls > 1) {
- callCountTextView.setText(String.format(Locale.getDefault(), "(%d)", numberCalls));
- callCountTextView.setVisibility(View.VISIBLE);
- } else {
- callCountTextView.setVisibility(View.GONE);
- }
- }
-
- private boolean isUnreadMissedCall(CoalescedRow row) {
- // Show missed call styling if the most recent call in the group was missed and it is still
- // marked as not read. The "NEW" column is presumably used for notifications and voicemails
- // only.
- return row.getCallType() == Calls.MISSED_TYPE && !row.getIsRead();
- }
-
- private void setPhoto(CoalescedRow row) {
- contactPhotoView.setPhoto(PhotoInfoBuilder.fromCoalescedRow(activity, row).build());
- }
-
- private void setFeatureIcons(CoalescedRow row) {
- ColorStateList colorStateList =
- ColorStateList.valueOf(
- activity.getColor(
- isUnreadMissedCall(row)
- ? R.color.feature_icon_unread_color
- : R.color.feature_icon_read_color));
-
- // Handle HD Icon
- if ((row.getFeatures() & Calls.FEATURES_HD_CALL) == Calls.FEATURES_HD_CALL) {
- hdIcon.setVisibility(View.VISIBLE);
- hdIcon.setImageTintList(colorStateList);
- } else {
- hdIcon.setVisibility(View.GONE);
- }
-
- // Handle Wifi Icon
- if (MotorolaUtils.shouldShowWifiIconInCallLog(activity, row.getFeatures())) {
- wifiIcon.setVisibility(View.VISIBLE);
- wifiIcon.setImageTintList(colorStateList);
- } else {
- wifiIcon.setVisibility(View.GONE);
- }
-
- // Handle Assisted Dialing Icon
- if ((row.getFeatures() & TelephonyManagerCompat.FEATURES_ASSISTED_DIALING)
- == TelephonyManagerCompat.FEATURES_ASSISTED_DIALING) {
- assistedDialIcon.setVisibility(View.VISIBLE);
- assistedDialIcon.setImageTintList(colorStateList);
- } else {
- assistedDialIcon.setVisibility(View.GONE);
- }
- }
-
- private void setCallTypeIcon(CoalescedRow row) {
- @DrawableRes int resId;
- switch (row.getCallType()) {
- case Calls.INCOMING_TYPE:
- case Calls.ANSWERED_EXTERNALLY_TYPE:
- resId = R.drawable.quantum_ic_call_received_vd_theme_24;
- break;
- case Calls.OUTGOING_TYPE:
- resId = R.drawable.quantum_ic_call_made_vd_theme_24;
- break;
- case Calls.MISSED_TYPE:
- resId = R.drawable.quantum_ic_call_missed_vd_theme_24;
- break;
- case Calls.VOICEMAIL_TYPE:
- throw new IllegalStateException("Voicemails not expected in call log");
- case Calls.BLOCKED_TYPE:
- resId = R.drawable.quantum_ic_block_vd_theme_24;
- break;
- default:
- // It is possible for users to end up with calls with unknown call types in their
- // call history, possibly due to 3rd party call log implementations (e.g. to
- // distinguish between rejected and missed calls). Instead of crashing, just
- // assume that all unknown call types are missed calls.
- resId = R.drawable.quantum_ic_call_missed_vd_theme_24;
- break;
- }
- callTypeIcon.setImageResource(resId);
-
- if (isUnreadMissedCall(row)) {
- callTypeIcon.setImageTintList(
- ColorStateList.valueOf(activity.getColor(R.color.call_type_icon_unread_color)));
- } else {
- callTypeIcon.setImageTintList(
- ColorStateList.valueOf(activity.getColor(R.color.call_type_icon_read_color)));
- }
- }
-
- private void setPhoneAccounts(CoalescedRow row) {
- PhoneAccountHandle phoneAccountHandle =
- TelecomUtil.composePhoneAccountHandle(
- row.getPhoneAccountComponentName(), row.getPhoneAccountId());
- if (phoneAccountHandle == null) {
- phoneAccountView.setVisibility(View.GONE);
- return;
- }
-
- String phoneAccountLabel = PhoneAccountUtils.getAccountLabel(activity, phoneAccountHandle);
- if (TextUtils.isEmpty(phoneAccountLabel)) {
- phoneAccountView.setVisibility(View.GONE);
- return;
- }
-
- @ColorInt
- int phoneAccountColor = PhoneAccountUtils.getAccountColor(activity, phoneAccountHandle);
- if (phoneAccountColor == PhoneAccount.NO_HIGHLIGHT_COLOR) {
- phoneAccountColor =
- activity
- .getResources()
- .getColor(R.color.dialer_secondary_text_color, activity.getTheme());
- }
-
- phoneAccountView.setText(phoneAccountLabel);
- phoneAccountView.setTextColor(phoneAccountColor);
- phoneAccountView.setVisibility(View.VISIBLE);
- }
-
- private void setCallButon(CoalescedRow row) {
- if (!PhoneNumberHelper.canPlaceCallsTo(
- row.getNumber().getNormalizedNumber(), row.getNumberPresentation())) {
- callButton.setVisibility(View.GONE);
- return;
- }
-
- callButton.setVisibility(View.VISIBLE);
- if ((row.getFeatures() & Calls.FEATURES_VIDEO) == Calls.FEATURES_VIDEO) {
- callButton.setImageResource(R.drawable.quantum_ic_videocam_vd_theme_24);
- callButton.setContentDescription(
- TextUtils.expandTemplate(
- activity.getResources().getText(R.string.a11y_new_call_log_entry_video_call),
- CallLogEntryText.buildPrimaryText(activity, row)));
- } else {
- callButton.setImageResource(R.drawable.quantum_ic_call_vd_theme_24);
- callButton.setContentDescription(
- TextUtils.expandTemplate(
- activity.getResources().getText(R.string.a11y_new_call_log_entry_voice_call),
- CallLogEntryText.buildPrimaryText(activity, row)));
- }
-
- callButton.setOnClickListener(view -> CallLogRowActions.startCallForRow(activity, row));
- }
-
- private class RealtimeRowFutureCallback implements FutureCallback<CoalescedRow> {
- private final CoalescedRow originalRow;
-
- RealtimeRowFutureCallback(CoalescedRow originalRow) {
- this.originalRow = originalRow;
- }
-
- @Override
- public void onSuccess(CoalescedRow updatedRow) {
- // If the user scrolled then this ViewHolder may not correspond to the completed task and
- // there's nothing to do.
- if (originalRow.getId() != currentRowId) {
- popCounts.didNotPop++;
- return;
- }
- // Only update the UI if the updated row differs from the original row (which has already
- // been displayed).
- if (!updatedRow.equals(originalRow)) {
- displayRow(updatedRow);
- popCounts.popped++;
- return;
- }
- popCounts.didNotPop++;
- }
-
- @Override
- public void onFailure(Throwable throwable) {
- throw new RuntimeException("realtime processing failed", throwable);
- }
- }
-}
diff --git a/java/com/android/dialer/calllog/ui/PromotionCardViewHolder.java b/java/com/android/dialer/calllog/ui/PromotionCardViewHolder.java
deleted file mode 100644
index c7d62ba..0000000
--- a/java/com/android/dialer/calllog/ui/PromotionCardViewHolder.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * 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.ui;
-
-import android.support.v7.widget.RecyclerView.ViewHolder;
-import android.text.method.LinkMovementMethod;
-import android.view.View;
-import android.widget.Button;
-import android.widget.ImageView;
-import android.widget.TextView;
-import com.android.dialer.promotion.Promotion;
-
-/** ViewHolder for {@link NewCallLogAdapter} to display the Duo disclosure card. */
-public class PromotionCardViewHolder extends ViewHolder {
-
- /** Listener to be called when promotion card is dismissed. */
- interface DismissListener {
- void onDismiss();
- }
-
- private final Button okButton;
- private final Promotion promotion;
-
- PromotionCardViewHolder(View itemView, Promotion promotion) {
- super(itemView);
- this.promotion = promotion;
-
- ImageView iconView = itemView.findViewById(R.id.new_call_log_promotion_card_icon);
- iconView.setImageResource(promotion.getIconRes());
-
- TextView cardTitleView = itemView.findViewById(R.id.new_call_log_promotion_card_title);
- cardTitleView.setText(promotion.getTitle());
-
- TextView cardDetailsView = itemView.findViewById(R.id.new_call_log_promotion_card_details);
- cardDetailsView.setText(promotion.getDetails());
- cardDetailsView.setMovementMethod(LinkMovementMethod.getInstance()); // make the link clickable
-
- // Obtain a reference to the "OK, got it" button.
- okButton = itemView.findViewById(R.id.new_call_log_promotion_card_ok);
- }
-
- void setDismissListener(DismissListener listener) {
- okButton.setOnClickListener(
- v -> {
- promotion.dismiss();
- listener.onDismiss();
- });
- }
-}
diff --git a/java/com/android/dialer/calllog/ui/res/layout/new_call_log_entry.xml b/java/com/android/dialer/calllog/ui/res/layout/new_call_log_entry.xml
deleted file mode 100644
index dba859f..0000000
--- a/java/com/android/dialer/calllog/ui/res/layout/new_call_log_entry.xml
+++ /dev/null
@@ -1,159 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ 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
- -->
-
-<RelativeLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:id="@+id/new_call_log_entry_root"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:minHeight="72dp"
- android:background="?android:attr/selectableItemBackground">
-
- <com.android.dialer.widget.ContactPhotoView
- android:id="@+id/contact_photo_view"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginStart="8dp"
- android:layout_marginEnd="8dp"
- android:layout_centerVertical="true"/>
-
- <!--
- A vertical linear layout of three rows: primary info, secondary info, and phone account info.
- It is marked as not important for a11y as we will set a more user-friendly content description
- for the entire entry view in Java code.
- -->
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_centerVertical="true"
- android:layout_toEndOf="@+id/contact_photo_view"
- android:layout_toStartOf="@+id/call_button"
- android:orientation="vertical"
- android:importantForAccessibility="noHideDescendants">
-
- <!-- 1st row: primary info -->
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:orientation="horizontal">
-
- <!--
- Important note:
-
- The following BidiTextView is the only widget that defines a weight in the containing
- LinearLayout, of which the purpose is to avoid pushing the widgets after it out of the
- boundary when the text is too long.
-
- Generally it is more efficient to assign a width/height of 0dp so that the BidiTextView
- does not have to measure its own size since it will absorb all the remaining space anyway.
-
- However, as the BidiTextView is part of an entry in the call log's RecyclerView, we must
- set layout_width to "wrap_content" so that the TextView can adjust its size when recycled
- for text of different lengths.
- -->
- <com.android.dialer.widget.BidiTextView
- android:id="@+id/primary_text"
- style="@style/Dialer.TextAppearance.Primary.Ellipsize"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:layout_marginEnd="6dp"
- android:lineSpacingMultiplier="1.5"
- tools:ignore="InefficientWeight"/>
-
- <ImageView
- android:id="@+id/hd_icon"
- android:layout_width="wrap_content"
- android:layout_height="18dp"
- android:layout_gravity="center_vertical"
- android:importantForAccessibility="no"
- android:src="@drawable/quantum_ic_hd_vd_theme_24"/>
-
- <ImageView
- android:id="@+id/wifi_icon"
- android:layout_width="wrap_content"
- android:layout_height="18dp"
- android:layout_gravity="center_vertical"
- android:importantForAccessibility="no"
- android:src="@drawable/quantum_ic_signal_wifi_4_bar_vd_theme_24"/>
-
- <ImageView
- android:id="@+id/assisted_dial_icon"
- android:layout_width="wrap_content"
- android:layout_height="18dp"
- android:layout_gravity="center_vertical"
- android:importantForAccessibility="no"
- android:src="@drawable/quantum_ic_language_vd_theme_24"/>
-
- <TextView
- android:id="@+id/call_count"
- style="@style/Dialer.TextAppearance.Primary"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginEnd="6dp"
- android:lineSpacingMultiplier="1.5"/>
-
- </LinearLayout>
-
- <!-- 2nd row: secondary info -->
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- tools:ignore="UseCompoundDrawables">
-
- <ImageView
- android:id="@+id/call_type_icon"
- android:layout_width="wrap_content"
- android:layout_height="18dp"
- android:layout_gravity="center_vertical"
- android:importantForAccessibility="no"/>
-
- <TextView
- android:id="@+id/secondary_text"
- style="@style/Dialer.TextAppearance.Secondary.Ellipsize"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:lineSpacingMultiplier="1.4"/>
-
- </LinearLayout>
-
- <!-- 3rd row: phone account info -->
- <TextView
- android:id="@+id/phone_account"
- style="@style/Dialer.TextAppearance.Secondary.Ellipsize"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"/>
-
- </LinearLayout>
-
- <!--
- The button to make a call.
- Its content description is set in Java code.
- -->
- <ImageView
- android:id="@+id/call_button"
- android:layout_width="56dp"
- android:layout_height="72dp"
- android:layout_alignParentEnd="true"
- android:layout_centerVertical="true"
- android:background="?android:attr/selectableItemBackgroundBorderless"
- android:scaleType="center"
- android:tint="?colorIcon"
- tools:ignore="ContentDescription"/>
-</RelativeLayout>
diff --git a/java/com/android/dialer/calllog/ui/res/layout/new_call_log_fragment.xml b/java/com/android/dialer/calllog/ui/res/layout/new_call_log_fragment.xml
deleted file mode 100644
index 3275cc0..0000000
--- a/java/com/android/dialer/calllog/ui/res/layout/new_call_log_fragment.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ 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
- -->
-
-<FrameLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_height="match_parent"
- android:layout_width="match_parent">
-
- <android.support.v7.widget.RecyclerView
- android:id="@+id/new_call_log_recycler_view"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:paddingBottom="@dimen/floating_action_button_list_bottom_padding"
- android:background="?android:attr/colorBackground"
- android:clipToPadding="false"/>
-
- <com.android.dialer.widget.EmptyContentView
- android:gravity="center_vertical"
- android:id="@+id/new_call_log_empty_content_view"
- android:background="?android:attr/colorBackground"
- android:layout_gravity="center"
- android:layout_height="match_parent"
- android:layout_width="match_parent"
- android:visibility="gone"/>
-
-</FrameLayout>
diff --git a/java/com/android/dialer/calllog/ui/res/layout/new_call_log_header.xml b/java/com/android/dialer/calllog/ui/res/layout/new_call_log_header.xml
deleted file mode 100644
index a6d1f61..0000000
--- a/java/com/android/dialer/calllog/ui/res/layout/new_call_log_header.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ 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
- -->
-<RelativeLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:minHeight="48dp"
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
- <TextView
- android:id="@+id/new_call_log_header_text"
- style="@style/Dialer.TextAppearance.Secondary"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginStart="16dp"
- android:layout_marginTop="8dp"
- android:layout_centerVertical="true"
- android:layout_gravity="center_vertical"/>
-</RelativeLayout>
diff --git a/java/com/android/dialer/calllog/ui/res/layout/new_call_log_promotion_card.xml b/java/com/android/dialer/calllog/ui/res/layout/new_call_log_promotion_card.xml
deleted file mode 100644
index fade6c7..0000000
--- a/java/com/android/dialer/calllog/ui/res/layout/new_call_log_promotion_card.xml
+++ /dev/null
@@ -1,80 +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
- -->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:background="?android:attr/colorBackground"
- android:orientation="vertical">
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingTop="16dp"
- android:paddingStart="16dp"
- android:paddingEnd="24dp"
- android:clipChildren="false"
- android:clipToPadding="false"
- android:orientation="horizontal">
-
- <ImageView
- android:id="@+id/new_call_log_promotion_card_icon"
- android:layout_width="40dp"
- android:layout_height="40dp"
- android:layout_marginEnd="16dp"
- android:importantForAccessibility="no"/>
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="8dp"
- android:orientation="vertical">
-
- <TextView
- android:id="@+id/new_call_log_promotion_card_title"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginBottom="12dp"
- style="@style/Dialer.TextAppearance.Header2"/>
- <TextView
- android:id="@+id/new_call_log_promotion_card_details"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginBottom="16dp"
- android:lineSpacingExtra="8dp"
- style="@style/Dialer.TextAppearance.Secondary"/>
- <Button
- android:id="@+id/new_call_log_promotion_card_ok"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="6dp"
- android:layout_marginBottom="2dp"
- android:layout_gravity="end"
- android:paddingLeft="14dp"
- android:paddingRight="14dp"
- android:text="@string/ok_got_it"
- android:textSize="14sp"/>
- </LinearLayout>
- </LinearLayout>
-
- <!-- The boundary line at the bottom -->
- <View
- android:layout_width="match_parent"
- android:layout_height="1dp"
- android:layout_marginTop="8dp"
- android:background="#DBDBDB"/>
-</LinearLayout>
diff --git a/java/com/android/dialer/constants/ScheduledJobIds.java b/java/com/android/dialer/constants/ScheduledJobIds.java
index 7ffd2da..1a852d0 100644
--- a/java/com/android/dialer/constants/ScheduledJobIds.java
+++ b/java/com/android/dialer/constants/ScheduledJobIds.java
@@ -50,8 +50,6 @@
public static final int VOIP_REGISTRATION = 300;
- public static final int CALL_LOG_CONFIG_POLLING_JOB = 400;
-
// Job Ids from 10_000 to 10_100 should be reserved for proto upload jobs.
public static final int PROTO_UPLOAD_JOB_MIN_ID = 10_000;
public static final int PROTO_UPLOAD_JOB_MAX_ID = 10_100;
diff --git a/java/com/android/dialer/main/impl/MainActivity.java b/java/com/android/dialer/main/impl/MainActivity.java
index f539bdc..c7f2ae6 100644
--- a/java/com/android/dialer/main/impl/MainActivity.java
+++ b/java/com/android/dialer/main/impl/MainActivity.java
@@ -21,7 +21,6 @@
import android.os.Bundle;
import android.support.v4.content.LocalBroadcastManager;
import com.android.dialer.blockreportspam.ShowBlockReportSpamDialogReceiver;
-import com.android.dialer.calllog.config.CallLogConfigComponent;
import com.android.dialer.common.Assert;
import com.android.dialer.common.LogUtil;
import com.android.dialer.interactions.PhoneNumberInteraction.DisambigDialogDismissedListener;
@@ -54,10 +53,6 @@
/** Returns intent that will open MainActivity to the specified tab. */
public static Intent getShowTabIntent(Context context, @TabIndex int tabIndex) {
- if (CallLogConfigComponent.get(context).callLogConfig().isNewPeerEnabled()) {
- // TODO(calderwoodra): implement this in NewMainActivityPeer
- return null;
- }
return OldMainActivityPeer.getShowTabIntent(context, tabIndex);
}
@@ -85,11 +80,7 @@
}
protected MainActivityPeer getNewPeer() {
- if (CallLogConfigComponent.get(this).callLogConfig().isNewPeerEnabled()) {
- return new NewMainActivityPeer(this);
- } else {
- return new OldMainActivityPeer(this);
- }
+ return new OldMainActivityPeer(this);
}
@Override
diff --git a/java/com/android/dialer/main/impl/NewMainActivityPeer.java b/java/com/android/dialer/main/impl/NewMainActivityPeer.java
deleted file mode 100644
index f2d6fa6..0000000
--- a/java/com/android/dialer/main/impl/NewMainActivityPeer.java
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * 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.main.impl;
-
-import android.content.Context;
-import android.content.Intent;
-import android.os.Bundle;
-import android.support.v4.app.Fragment;
-import android.support.v4.app.FragmentManager;
-import android.support.v4.app.FragmentTransaction;
-import com.android.dialer.calllog.CallLogComponent;
-import com.android.dialer.calllog.ui.NewCallLogFragment;
-import com.android.dialer.common.concurrent.DefaultFutureCallback;
-import com.android.dialer.main.MainActivityPeer;
-import com.android.dialer.main.impl.bottomnav.BottomNavBar;
-import com.android.dialer.main.impl.bottomnav.BottomNavBar.OnBottomNavTabSelectedListener;
-import com.android.dialer.main.impl.bottomnav.BottomNavBar.TabIndex;
-import com.android.dialer.voicemail.listui.NewVoicemailFragment;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.MoreExecutors;
-
-/** MainActivityPeer that implements the new fragments. */
-public class NewMainActivityPeer implements MainActivityPeer {
-
- private final MainActivity mainActivity;
-
- public NewMainActivityPeer(MainActivity mainActivity) {
- this.mainActivity = mainActivity;
- }
-
- @Override
- public void onActivityCreate(Bundle saveInstanceState) {
- mainActivity.setContentView(R.layout.main_activity);
- MainBottomNavBarBottomNavTabListener bottomNavBarBottomNavTabListener =
- new MainBottomNavBarBottomNavTabListener(
- mainActivity.getSupportFragmentManager(), mainActivity.getApplicationContext());
- BottomNavBar bottomNav = mainActivity.findViewById(R.id.bottom_nav_bar);
- bottomNav.addOnTabSelectedListener(bottomNavBarBottomNavTabListener);
- bottomNav.selectTab(TabIndex.SPEED_DIAL);
- }
-
- @Override
- public void onActivityResume() {}
-
- @Override
- public void onUserLeaveHint() {}
-
- @Override
- public void onActivityPause() {}
-
- @Override
- public void onActivityStop() {}
-
- @Override
- public void onActivityDestroyed() {}
-
- @Override
- public void onNewIntent(Intent intent) {}
-
- @Override
- public void onActivityResult(int requestCode, int resultCode, Intent data) {}
-
- @Override
- public void onSaveInstanceState(Bundle bundle) {}
-
- @Override
- public boolean onBackPressed() {
- return false;
- }
-
- /**
- * Implementation of {@link OnBottomNavTabSelectedListener} that handles logic for showing each of
- * the main tabs.
- */
- private static final class MainBottomNavBarBottomNavTabListener
- implements OnBottomNavTabSelectedListener {
-
- private static final String SPEED_DIAL_TAG = "speed_dial";
- private static final String CALL_LOG_TAG = "call_log";
- private static final String VOICEMAIL_TAG = "voicemail";
-
- private final FragmentManager supportFragmentManager;
- private final Context appContext;
-
- private MainBottomNavBarBottomNavTabListener(
- FragmentManager supportFragmentManager, Context appContext) {
- this.supportFragmentManager = supportFragmentManager;
- this.appContext = appContext;
- }
-
- @Override
- public void onSpeedDialSelected() {
- hideAllFragments();
- // TODO(calderwoodra): Since we aren't using fragment utils in this peer, let's disable
- // speed dial until we figure out a solution.
- // SpeedDialFragment fragment =
- // (SpeedDialFragment) supportFragmentManager.findFragmentByTag(SPEED_DIAL_TAG);
- // if (fragment == null) {
- // supportFragmentManager
- // .beginTransaction()
- // .add(R.id.fragment_container, SpeedDialFragment.newInstance(), SPEED_DIAL_TAG)
- // .commit();
- // } else {
- // supportFragmentManager.beginTransaction().show(fragment).commit();
- // }
- }
-
- @Override
- public void onCallLogSelected() {
- hideAllFragments();
- NewCallLogFragment fragment =
- (NewCallLogFragment) supportFragmentManager.findFragmentByTag(CALL_LOG_TAG);
- if (fragment == null) {
- supportFragmentManager
- .beginTransaction()
- .add(R.id.fragment_container, new NewCallLogFragment(), CALL_LOG_TAG)
- .commit();
- } else {
- supportFragmentManager.beginTransaction().show(fragment).commit();
- }
- }
-
- @Override
- public void onContactsSelected() {
- hideAllFragments();
- // TODO(calderwoodra): Implement ContactsFragment when FragmentUtils#getParent works
- }
-
- @Override
- public void onVoicemailSelected() {
- hideAllFragments();
- NewVoicemailFragment fragment =
- (NewVoicemailFragment) supportFragmentManager.findFragmentByTag(VOICEMAIL_TAG);
- if (fragment == null) {
- supportFragmentManager
- .beginTransaction()
- .add(R.id.fragment_container, new NewVoicemailFragment(), VOICEMAIL_TAG)
- .commit();
- } else {
- supportFragmentManager.beginTransaction().show(fragment).commit();
- }
- }
-
- // TODO(calderwoodra): fix overlapping fragments issue
- private void hideAllFragments() {
- FragmentTransaction supportTransaction = supportFragmentManager.beginTransaction();
- Fragment speedDialFragment = supportFragmentManager.findFragmentByTag(SPEED_DIAL_TAG);
- if (speedDialFragment != null) {
- supportTransaction.hide(speedDialFragment);
- }
-
- Fragment callLogFragment = supportFragmentManager.findFragmentByTag(CALL_LOG_TAG);
- if (callLogFragment != null) {
- if (callLogFragment.isVisible()) {
- // If the user taps any bottom nav button and the call log is showing, immediately cancel
- // missed calls (unbold them and clear their notifications).
- Futures.addCallback(
- // TODO(zachh): Use dagger to create Peer and MainBottomNavBarBottomNavTabListener.
- CallLogComponent.get(appContext).getClearMissedCalls().clearAll(),
- new DefaultFutureCallback<>(),
- MoreExecutors.directExecutor());
- }
- supportTransaction.hide(callLogFragment);
- }
-
- if (supportFragmentManager.findFragmentByTag(VOICEMAIL_TAG) != null) {
- supportTransaction.hide(supportFragmentManager.findFragmentByTag(VOICEMAIL_TAG));
- }
- supportTransaction.commit();
- }
- }
-}
diff --git a/java/com/android/dialer/main/impl/OldMainActivityPeer.java b/java/com/android/dialer/main/impl/OldMainActivityPeer.java
index a818ef4..2d7f7c0 100644
--- a/java/com/android/dialer/main/impl/OldMainActivityPeer.java
+++ b/java/com/android/dialer/main/impl/OldMainActivityPeer.java
@@ -21,11 +21,9 @@
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.app.KeyguardManager;
-import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
-import android.content.IntentFilter;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
@@ -40,7 +38,6 @@
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v4.content.ContextCompat;
-import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.telecom.PhoneAccount;
@@ -74,16 +71,11 @@
import com.android.dialer.calldetails.OldCallDetailsActivity;
import com.android.dialer.callintent.CallIntentBuilder;
import com.android.dialer.callintent.CallSpecificAppData;
-import com.android.dialer.calllog.CallLogComponent;
-import com.android.dialer.calllog.config.CallLogConfigComponent;
-import com.android.dialer.calllog.ui.NewCallLogFragment;
import com.android.dialer.common.FragmentUtils.FragmentUtilListener;
import com.android.dialer.common.LogUtil;
-import com.android.dialer.common.concurrent.DefaultFutureCallback;
import com.android.dialer.common.concurrent.DialerExecutorComponent;
import com.android.dialer.common.concurrent.ThreadUtil;
import com.android.dialer.common.concurrent.UiListener;
-import com.android.dialer.configprovider.ConfigProviderComponent;
import com.android.dialer.constants.ActivityRequestCodes;
import com.android.dialer.contactsfragment.ContactsFragment;
import com.android.dialer.contactsfragment.ContactsFragment.Header;
@@ -123,13 +115,10 @@
import com.android.dialer.util.DialerUtils;
import com.android.dialer.util.PermissionsUtil;
import com.android.dialer.util.TransactionSafeActivity;
-import com.android.dialer.voicemail.listui.NewVoicemailFragment;
import com.android.dialer.voicemailstatus.VisualVoicemailEnabledChecker;
import com.android.dialer.voicemailstatus.VoicemailStatusHelper;
import com.android.voicemail.VoicemailComponent;
-import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.MoreExecutors;
import java.util.Locale;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
@@ -153,24 +142,6 @@
// TODO(calderwoodra): change to AppCompatActivity once new speed dial ships
private final TransactionSafeActivity activity;
- private final BroadcastReceiver disableCallLogFrameworkReceiver =
- new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (bottomNavTabListener == null) {
- return;
- }
- /*
- * Remove the NewCallLogFragment and NewVoicemailFragment if it is currently attached. If
- * this is not done, user interaction with the fragment could cause call log framework
- * state to be unexpectedly written. For example scrolling could cause the
- * AnnotatedCallLog to be read (which would trigger database creation).
- */
- bottomNavTabListener.disableNewCallLogFragment();
- bottomNavTabListener.disableNewVoicemailFragment();
- }
- };
-
// Contacts
private MainOnContactSelectedListener onContactSelectedListener;
@@ -519,36 +490,6 @@
bottomNav.setVisibility(View.VISIBLE);
}
- /*
- * While the activity is running, listen for the call log framework being disabled. If this is
- * not done, user interaction with the fragment could cause call log framework state to be
- * unexpectedly written. For example scrolling could cause the AnnotatedCallLog to be read
- * (which would trigger database creation).
- */
- LocalBroadcastManager.getInstance(activity)
- .registerReceiver(
- disableCallLogFrameworkReceiver, new IntentFilter("disableCallLogFramework"));
-
- /*
- * Similar to above, if the new call log/new voicemail is being shown and then the activity is
- * paused, when the user returns we need to remove the NewCallLogFragment if the framework has
- * been disabled in the meantime.
- */
- bottomNavTabListener.ensureCorrectCallLogShown();
- bottomNavTabListener.ensureCorrectVoicemailShown();
-
- // Config the badge of missed calls for the new call log.
- if (bottomNavTabListener.newCallLogFragmentActive()) {
- if (PermissionsUtil.hasCallLogReadPermissions(activity)) {
- missedCallCountObserver.onChange(false); // Set the initial value for the badge
- activity
- .getContentResolver()
- .registerContentObserver(Calls.CONTENT_URI, true, missedCallCountObserver);
- } else {
- bottomNav.setNotificationCount(TabIndex.CALL_LOG, 0);
- }
- }
-
// add 1 sec delay to get memory snapshot so that dialer wont react slowly on resume.
ThreadUtil.postDelayedOnUiThread(
() ->
@@ -566,7 +507,6 @@
@Override
public void onActivityPause() {
searchController.onActivityPause();
- LocalBroadcastManager.getInstance(activity).unregisterReceiver(disableCallLogFrameworkReceiver);
activity.getContentResolver().unregisterContentObserver(missedCallCountObserver);
}
@@ -1042,15 +982,8 @@
}
private void markMissedCallsAsReadAndRemoveNotification() {
- if (bottomNavTabListener.newCallLogFragmentActive()) {
- Futures.addCallback(
- CallLogComponent.get(context).getClearMissedCalls().clearAll(),
- new DefaultFutureCallback<>(),
- MoreExecutors.directExecutor());
- } else {
- callLogQueryHandler.markMissedCallsAsRead();
- CallLogNotificationsService.cancelAllMissedCalls(context);
- }
+ callLogQueryHandler.markMissedCallsAsRead();
+ CallLogNotificationsService.cancelAllMissedCalls(context);
}
private void setCurrentTab(@TabIndex int tabIndex) {
@@ -1067,10 +1000,7 @@
registerVoicemailStatusContentObserver(context);
// TODO(a bug): Don't use callLogQueryHandler
callLogQueryHandler.fetchVoicemailStatus();
-
- if (!bottomNavTabListener.newCallLogFragmentActive()) {
- callLogQueryHandler.fetchMissedCallsUnreadCount();
- }
+ callLogQueryHandler.fetchMissedCallsUnreadCount();
// Reset the tab on resume to restart the timer
setCurrentTab(bottomNavBar.getSelectedTab());
}
@@ -1079,9 +1009,7 @@
public void onActivityStop(boolean changingConfigurations, boolean keyguardLocked) {
context.getContentResolver().unregisterContentObserver(voicemailStatusObserver);
activityIsAlive = false;
- // The new call log fragment handles this on its own.
- if (!bottomNavTabListener.newCallLogFragmentActive()
- && viewedCallLogTabPastTimeThreshold()
+ if (viewedCallLogTabPastTimeThreshold()
&& !changingConfigurations
&& !keyguardLocked) {
markMissedCallsAsReadAndRemoveNotification();
@@ -1349,15 +1277,9 @@
Logger.get(activity).logScreenView(ScreenEvent.Type.MAIN_CALL_LOG, activity);
selectedTab = TabIndex.CALL_LOG;
- if (CallLogConfigComponent.get(activity).callLogConfig().isNewCallLogFragmentEnabled()) {
- android.support.v4.app.Fragment supportFragment =
- supportFragmentManager.findFragmentByTag(CALL_LOG_TAG);
- showSupportFragment(
- supportFragment == null ? new NewCallLogFragment() : supportFragment, CALL_LOG_TAG);
- } else {
- Fragment fragment = fragmentManager.findFragmentByTag(CALL_LOG_TAG);
- showFragment(fragment == null ? new CallLogFragment() : fragment, CALL_LOG_TAG);
- }
+ Fragment fragment = fragmentManager.findFragmentByTag(CALL_LOG_TAG);
+ showFragment(fragment == null ? new CallLogFragment() : fragment, CALL_LOG_TAG);
+
fab.show();
showPromotionBottomSheet(activity, bottomSheet);
}
@@ -1392,79 +1314,6 @@
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
}
- void disableNewCallLogFragment() {
- LogUtil.i("MainBottomNavBarBottomNavTabListener.disableNewCallLogFragment", "disabled");
- android.support.v4.app.Fragment supportFragment =
- supportFragmentManager.findFragmentByTag(CALL_LOG_TAG);
- if (supportFragment != null) {
- supportFragmentManager.beginTransaction().remove(supportFragment).commitAllowingStateLoss();
- // If the NewCallLogFragment was showing, immediately show the old call log fragment
- // instead.
- if (selectedTab == TabIndex.CALL_LOG) {
- LogUtil.i(
- "MainBottomNavBarBottomNavTabListener.disableNewCallLogFragment", "showing old");
- Fragment fragment = fragmentManager.findFragmentByTag(CALL_LOG_TAG);
- showFragment(fragment == null ? new CallLogFragment() : fragment, CALL_LOG_TAG);
- }
- }
- }
-
- void disableNewVoicemailFragment() {
- LogUtil.i("MainBottomNavBarBottomNavTabListener.disableNewVoicemailFragment", "disabled");
- android.support.v4.app.Fragment supportFragment =
- supportFragmentManager.findFragmentByTag(VOICEMAIL_TAG);
- if (supportFragment != null) {
- supportFragmentManager.beginTransaction().remove(supportFragment).commitAllowingStateLoss();
- // If the NewVoicemailFragment was showing, immediately show the old voicemail fragment
- // instead.
- if (selectedTab == TabIndex.VOICEMAIL) {
- LogUtil.i(
- "MainBottomNavBarBottomNavTabListener.disableNewVoicemailFragment", "showing old");
- Fragment fragment = fragmentManager.findFragmentByTag(VOICEMAIL_TAG);
- showFragment(
- fragment == null ? new VisualVoicemailCallLogFragment() : fragment, VOICEMAIL_TAG);
- }
- }
- }
-
- void ensureCorrectCallLogShown() {
- android.support.v4.app.Fragment supportFragment =
- supportFragmentManager.findFragmentByTag(CALL_LOG_TAG);
- if (supportFragment != null
- && !CallLogConfigComponent.get(activity).callLogConfig().isNewCallLogFragmentEnabled()) {
- LogUtil.i("MainBottomNavBarBottomNavTabListener.ensureCorrectCallLogShown", "disabling");
- disableNewCallLogFragment();
- }
- }
-
- void ensureCorrectVoicemailShown() {
- android.support.v4.app.Fragment supportFragment =
- supportFragmentManager.findFragmentByTag(VOICEMAIL_TAG);
- if (supportFragment != null
- && !CallLogConfigComponent.get(activity)
- .callLogConfig()
- .isNewVoicemailFragmentEnabled()) {
- LogUtil.i("MainBottomNavBarBottomNavTabListener.ensureCorrectVoicemailShown", "disabling");
- disableNewVoicemailFragment();
- }
- }
-
- boolean newCallLogFragmentActive() {
- return supportFragmentManager.findFragmentByTag(CALL_LOG_TAG) != null
- || (fragmentManager.findFragmentByTag(CALL_LOG_TAG) == null
- && CallLogConfigComponent.get(activity)
- .callLogConfig()
- .isNewCallLogFragmentEnabled());
- }
-
- boolean newVoicemailFragmentActive() {
- return supportFragmentManager.findFragmentByTag(VOICEMAIL_TAG) != null
- || (fragmentManager.findFragmentByTag(VOICEMAIL_TAG) == null
- && CallLogConfigComponent.get(activity)
- .callLogConfig()
- .isNewVoicemailFragmentEnabled());
- }
-
@Override
public void onContactsSelected() {
LogUtil.enterBlock("MainBottomNavBarBottomNavTabListener.onContactsSelected");
@@ -1489,21 +1338,14 @@
Logger.get(activity).logScreenView(ScreenEvent.Type.MAIN_VOICEMAIL, activity);
selectedTab = TabIndex.VOICEMAIL;
- if (CallLogConfigComponent.get(activity).callLogConfig().isNewVoicemailFragmentEnabled()) {
- android.support.v4.app.Fragment supportFragment =
- supportFragmentManager.findFragmentByTag(VOICEMAIL_TAG);
- showSupportFragment(
- supportFragment == null ? new NewVoicemailFragment() : supportFragment, VOICEMAIL_TAG);
- } else {
- VisualVoicemailCallLogFragment fragment =
- (VisualVoicemailCallLogFragment) fragmentManager.findFragmentByTag(VOICEMAIL_TAG);
- if (fragment == null) {
- fragment = new VisualVoicemailCallLogFragment();
- }
- showFragment(fragment, VOICEMAIL_TAG);
- fragment.setUserVisibleHint(true);
- fragment.onVisible();
+ VisualVoicemailCallLogFragment fragment =
+ (VisualVoicemailCallLogFragment) fragmentManager.findFragmentByTag(VOICEMAIL_TAG);
+ if (fragment == null) {
+ fragment = new VisualVoicemailCallLogFragment();
}
+ showFragment(fragment, VOICEMAIL_TAG);
+ fragment.setUserVisibleHint(true);
+ fragment.onVisible();
}
private void showFragment(@NonNull Fragment fragment, String tag) {
diff --git a/java/com/android/dialer/voicemail/listui/NewVoicemailAdapter.java b/java/com/android/dialer/voicemail/listui/NewVoicemailAdapter.java
deleted file mode 100644
index 5b2f061..0000000
--- a/java/com/android/dialer/voicemail/listui/NewVoicemailAdapter.java
+++ /dev/null
@@ -1,1115 +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.voicemail.listui;
-
-import android.app.FragmentManager;
-import android.content.ContentValues;
-import android.content.Context;
-import android.content.Intent;
-import android.database.Cursor;
-import android.media.MediaPlayer;
-import android.media.MediaPlayer.OnCompletionListener;
-import android.media.MediaPlayer.OnErrorListener;
-import android.media.MediaPlayer.OnPreparedListener;
-import android.net.Uri;
-import android.provider.VoicemailContract.Voicemails;
-import android.support.annotation.IntDef;
-import android.support.annotation.Nullable;
-import android.support.annotation.WorkerThread;
-import android.support.design.widget.Snackbar;
-import android.support.v7.widget.RecyclerView;
-import android.support.v7.widget.RecyclerView.ViewHolder;
-import android.util.ArrayMap;
-import android.util.ArraySet;
-import android.util.Pair;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.view.ViewGroup;
-import com.android.dialer.calllogutils.CallLogDates;
-import com.android.dialer.common.Assert;
-import com.android.dialer.common.LogUtil;
-import com.android.dialer.common.concurrent.DialerExecutorComponent;
-import com.android.dialer.common.concurrent.ThreadUtil;
-import com.android.dialer.time.Clock;
-import com.android.dialer.voicemail.listui.NewVoicemailViewHolder.NewVoicemailViewHolderListener;
-import com.android.dialer.voicemail.listui.error.VoicemailErrorMessage;
-import com.android.dialer.voicemail.listui.error.VoicemailErrorMessageCreator;
-import com.android.dialer.voicemail.listui.error.VoicemailStatus;
-import com.android.dialer.voicemail.model.VoicemailEntry;
-import com.android.voicemail.VoicemailClient;
-import com.google.common.collect.ImmutableList;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.Locale;
-import java.util.Objects;
-import java.util.Set;
-
-/** {@link RecyclerView.Adapter} for the new voicemail call log fragment. */
-final class NewVoicemailAdapter extends RecyclerView.Adapter<ViewHolder>
- implements NewVoicemailViewHolderListener {
-
- private static final int VOICEMAIL_DELETE_DELAY_MS = 3000;
-
- /** IntDef for the different types of rows that can be shown in the call log. */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef({RowType.HEADER, RowType.VOICEMAIL_ENTRY, RowType.VOICEMAIL_ALERT})
- @interface RowType {
- /** A row representing a voicemail alert. */
- int VOICEMAIL_ALERT = 1;
- /** Header that displays "Today", "Yesterday" or "Older". */
- int HEADER = 2;
- /** A row representing a voicemail entry. */
- int VOICEMAIL_ENTRY = 3;
- }
-
- private Cursor cursor;
- private final Clock clock;
-
- /** {@link Integer#MAX_VALUE} when the "Today" header should not be displayed. */
- private int todayHeaderPosition = Integer.MAX_VALUE;
- /** {@link Integer#MAX_VALUE} when the "Yesterday" header should not be displayed. */
- private int yesterdayHeaderPosition = Integer.MAX_VALUE;
- /** {@link Integer#MAX_VALUE} when the "Older" header should not be displayed. */
- private int olderHeaderPosition = Integer.MAX_VALUE;
- /** {@link Integer#MAX_VALUE} when the voicemail alert message should not be displayed. */
- private int voicemailAlertPosition = Integer.MAX_VALUE;
-
- private final FragmentManager fragmentManager;
- /** A valid id for {@link VoicemailEntry} is greater than 0 */
- private long currentlyExpandedViewHolderId = -1;
-
- private VoicemailErrorMessage voicemailErrorMessage;
-
- /**
- * It takes time to delete voicemails from the server, so we "remove" them and remember the
- * positions we removed until a new cursor is ready.
- */
- Set<Integer> deletedVoicemailPosition = new ArraySet<>();
-
- /**
- * A set of (re-usable) view holders being used by the recycler view to display voicemails. This
- * set may include multiple view holder with the same ID and shouldn't be used to lookup a
- * specific viewholder based on this value, instead use newVoicemailViewHolderArrayMap for that
- * purpose.
- */
- private final Set<NewVoicemailViewHolder> newVoicemailViewHolderSet = new ArraySet<>();
- /**
- * This allows us to retrieve the view holder corresponding to a particular view holder id, and
- * will always ensure there is only (up-to-date) view holder corresponding to a view holder id,
- * unlike the newVoicemailViewHolderSet.
- */
- private final ArrayMap<Long, NewVoicemailViewHolder> newVoicemailViewHolderArrayMap =
- new ArrayMap<>();
-
- // A single instance of a media player re-used across the expanded view holders.
- private final NewVoicemailMediaPlayer mediaPlayer =
- new NewVoicemailMediaPlayer(new MediaPlayer());
-
- /** @param cursor whose projection is {@link VoicemailCursorLoader#VOICEMAIL_COLUMNS} */
- NewVoicemailAdapter(Cursor cursor, Clock clock, FragmentManager fragmentManager) {
- LogUtil.enterBlock("NewVoicemailAdapter");
- this.cursor = cursor;
- this.clock = clock;
- this.fragmentManager = fragmentManager;
- initializeMediaPlayerListeners();
- updateHeaderPositions();
- }
-
- private void updateHeaderPositions() {
- LogUtil.i(
- "NewVoicemailAdapter.updateHeaderPositions",
- "before updating todayPos:%d, yestPos:%d, olderPos:%d, alertPos:%d",
- todayHeaderPosition,
- yesterdayHeaderPosition,
- olderHeaderPosition,
- voicemailAlertPosition);
-
- // If there are no rows to display, set all header positions to MAX_VALUE.
- if (!cursor.moveToFirst()) {
- todayHeaderPosition = Integer.MAX_VALUE;
- yesterdayHeaderPosition = Integer.MAX_VALUE;
- olderHeaderPosition = Integer.MAX_VALUE;
- return;
- }
-
- long currentTimeMillis = clock.currentTimeMillis();
-
- int numItemsInToday = 0;
- int numItemsInYesterday = 0;
-
- do {
- long timestamp = VoicemailCursorLoader.getTimestamp(cursor);
- long dayDifference = CallLogDates.getDayDifference(currentTimeMillis, timestamp);
- if (dayDifference == 0) {
- numItemsInToday++;
- } else if (dayDifference == 1) {
- numItemsInYesterday++;
- } else {
- break;
- }
- } while (cursor.moveToNext());
-
- if (numItemsInToday > 0) {
- numItemsInToday++; // including the "Today" header;
- }
- if (numItemsInYesterday > 0) {
- numItemsInYesterday++; // including the "Yesterday" header;
- }
-
- int alertOffSet = 0;
- if (voicemailAlertPosition != Integer.MAX_VALUE) {
- Assert.checkArgument(
- voicemailAlertPosition == 0, "voicemail alert can only be 0, when showing");
- alertOffSet = 1;
- }
-
- // Set all header positions.
- // A header position will be MAX_VALUE if there is no item to be displayed under that header.
- todayHeaderPosition = numItemsInToday > 0 ? alertOffSet : Integer.MAX_VALUE;
- yesterdayHeaderPosition =
- numItemsInYesterday > 0 ? numItemsInToday + alertOffSet : Integer.MAX_VALUE;
- olderHeaderPosition =
- !cursor.isAfterLast()
- ? numItemsInToday + numItemsInYesterday + alertOffSet
- : Integer.MAX_VALUE;
-
- LogUtil.i(
- "NewVoicemailAdapter.updateHeaderPositions",
- "after updating todayPos:%d, yestPos:%d, olderPos:%d, alertOffSet:%d, alertPos:%d",
- todayHeaderPosition,
- yesterdayHeaderPosition,
- olderHeaderPosition,
- alertOffSet,
- voicemailAlertPosition);
- }
-
- private void initializeMediaPlayerListeners() {
- mediaPlayer.setOnCompletionListener(onCompletionListener);
- mediaPlayer.setOnPreparedListener(onPreparedListener);
- mediaPlayer.setOnErrorListener(onErrorListener);
- }
-
- public void updateCursor(Cursor updatedCursor) {
- LogUtil.enterBlock("NewVoicemailAdapter.updateCursor");
- deletedVoicemailPosition.clear();
- this.cursor = updatedCursor;
- updateHeaderPositions();
- notifyDataSetChanged();
- }
-
- @Override
- public ViewHolder onCreateViewHolder(ViewGroup viewGroup, @RowType int viewType) {
- LogUtil.enterBlock("NewVoicemailAdapter.onCreateViewHolder");
- LayoutInflater inflater = LayoutInflater.from(viewGroup.getContext());
- View view;
- switch (viewType) {
- case RowType.VOICEMAIL_ALERT:
- view = inflater.inflate(R.layout.new_voicemail_entry_alert, viewGroup, false);
- return new NewVoicemailAlertViewHolder(view);
- case RowType.HEADER:
- view = inflater.inflate(R.layout.new_voicemail_entry_header, viewGroup, false);
- return new NewVoicemailHeaderViewHolder(view);
- case NewVoicemailAdapter.RowType.VOICEMAIL_ENTRY:
- view = inflater.inflate(R.layout.new_voicemail_entry, viewGroup, false);
- NewVoicemailViewHolder newVoicemailViewHolder =
- new NewVoicemailViewHolder(view, clock, this);
- newVoicemailViewHolderSet.add(newVoicemailViewHolder);
- return newVoicemailViewHolder;
- default:
- throw Assert.createUnsupportedOperationFailException("Unsupported view type: " + viewType);
- }
- }
-
- // TODO(uabdullah): a bug - Clean up logging in this function, here for debugging during
- // development.
- @Override
- public void onBindViewHolder(ViewHolder viewHolder, int position) {
- LogUtil.enterBlock("NewVoicemailAdapter.onBindViewHolder, pos:" + position);
- // Re-request a bind when a viewholder is deleted to ensure correct position
- if (deletedVoicemailPosition.contains(position)) {
- LogUtil.i(
- "NewVoicemailAdapter.onBindViewHolder",
- "pos:%d contains deleted voicemail, re-bind. #of deleted voicemail positions: %d",
- position,
- deletedVoicemailPosition.size());
- // TODO(uabdullah): This should be removed when we support multi-select delete
- Assert.checkArgument(
- deletedVoicemailPosition.size() == 1, "multi-deletes not currently supported");
- onBindViewHolder(viewHolder, ++position);
- return;
- }
-
- // TODO(uabdullah): a bug Remove logging, temporarily here for debugging.
- printHashSet();
- // TODO(uabdullah): a bug Remove logging, temporarily here for debugging.
- printArrayMap();
-
- if (viewHolder instanceof NewVoicemailHeaderViewHolder) {
- LogUtil.i(
- "NewVoicemailAdapter.onBindViewHolder", "view holder at pos:%d is a header", position);
- onBindHeaderViewHolder(viewHolder, position);
- return;
- }
-
- if (viewHolder instanceof NewVoicemailAlertViewHolder) {
- LogUtil.i(
- "NewVoicemailAdapter.onBindViewHolder", "view holder at pos:%d is a alert", position);
- onBindAlertViewHolder(viewHolder, position);
- return;
- }
-
- LogUtil.i(
- "NewVoicemailAdapter.onBindViewHolder",
- "view holder at pos:%d is a not a header or an alert",
- position);
-
- NewVoicemailViewHolder newVoicemailViewHolder = (NewVoicemailViewHolder) viewHolder;
- int nonVoicemailEntryHeaders = getHeaderCountAtPosition(position);
-
- LogUtil.i(
- "NewVoicemailAdapter.onBindViewHolder",
- "view holder at pos:%d, nonVoicemailEntryHeaders:%d",
- position,
- nonVoicemailEntryHeaders);
-
- // Remove if the viewholder is being recycled.
- if (newVoicemailViewHolderArrayMap.containsKey(newVoicemailViewHolder.getViewHolderId())) {
- // TODO(uabdullah): a bug Remove logging, temporarily here for debugging.
- LogUtil.i(
- "NewVoicemailAdapter.onBindViewHolder",
- "Removing from hashset:%d, hashsetSize:%d, currExpanded:%d",
- newVoicemailViewHolder.getViewHolderId(),
- newVoicemailViewHolderArrayMap.size(),
- currentlyExpandedViewHolderId);
-
- newVoicemailViewHolderArrayMap.remove(newVoicemailViewHolder.getViewHolderId());
- printHashSet();
- printArrayMap();
- }
-
- newVoicemailViewHolder.reset();
- cursor.moveToPosition(position - nonVoicemailEntryHeaders);
- newVoicemailViewHolder.bindViewHolderValuesFromAdapter(
- cursor, fragmentManager, mediaPlayer, position, currentlyExpandedViewHolderId);
-
- // TODO(uabdullah): a bug Remove logging, temporarily here for debugging.
- LogUtil.i(
- "NewVoicemailAdapter.onBindViewHolder",
- "Adding to hashset:%d, hashsetSize:%d, pos:%d, currExpanded:%d",
- newVoicemailViewHolder.getViewHolderId(),
- newVoicemailViewHolderArrayMap.size(),
- position,
- currentlyExpandedViewHolderId);
-
- // Need this to ensure correct getCurrentlyExpandedViewHolder() value
- newVoicemailViewHolderArrayMap.put(
- newVoicemailViewHolder.getViewHolderId(), newVoicemailViewHolder);
-
- // TODO(uabdullah): a bug Remove logging, temporarily here for debugging.
- printHashSet();
- // TODO(uabdullah): a bug Remove logging, temporarily here for debugging.
- printArrayMap();
-
- // If the viewholder is playing the voicemail, keep updating its media player view (seekbar,
- // duration etc.)
- if (newVoicemailViewHolder.isViewHolderExpanded() && mediaPlayer.isPlaying()) {
- LogUtil.i(
- "NewVoicemailAdapter.onBindViewHolder",
- "Adding to hashset:%d, hashsetSize:%d, pos:%d, currExpanded:%d",
- newVoicemailViewHolderSet.size(),
- newVoicemailViewHolderArrayMap.size(),
- position,
- currentlyExpandedViewHolderId);
-
- Assert.checkArgument(
- newVoicemailViewHolder
- .getViewHolderVoicemailUri()
- .equals(mediaPlayer.getLastPlayedOrPlayingVoicemailUri()),
- "only the expanded view holder can be playing.");
- Assert.isNotNull(getCurrentlyExpandedViewHolder());
- Assert.checkArgument(
- getCurrentlyExpandedViewHolder()
- .getViewHolderVoicemailUri()
- .equals(mediaPlayer.getLastPlayedOrPlayingVoicemailUri()));
-
- recursivelyUpdateMediaPlayerViewOfExpandedViewHolder(newVoicemailViewHolder);
- }
- // Updates the hashmap with the most up-to-date state of the viewholder.
- newVoicemailViewHolderArrayMap.put(
- newVoicemailViewHolder.getViewHolderId(), newVoicemailViewHolder);
-
- // TODO(uabdullah): a bug Remove logging, temporarily here for debugging.
- printHashSet();
- // TODO(uabdullah): a bug Remove logging, temporarily here for debugging.
- printArrayMap();
- }
-
- private int getHeaderCountAtPosition(int position) {
- int previousHeaders = 0;
- if (voicemailAlertPosition != Integer.MAX_VALUE && position > voicemailAlertPosition) {
- previousHeaders++;
- }
- if (todayHeaderPosition != Integer.MAX_VALUE && position > todayHeaderPosition) {
- previousHeaders++;
- }
- if (yesterdayHeaderPosition != Integer.MAX_VALUE && position > yesterdayHeaderPosition) {
- previousHeaders++;
- }
- if (olderHeaderPosition != Integer.MAX_VALUE && position > olderHeaderPosition) {
- previousHeaders++;
- }
- return previousHeaders;
- }
-
- private void onBindAlertViewHolder(ViewHolder viewHolder, int position) {
- LogUtil.i(
- "NewVoicemailAdapter.onBindAlertViewHolder",
- "pos:%d, voicemailAlertPosition:%d",
- position,
- voicemailAlertPosition);
-
- NewVoicemailAlertViewHolder alertViewHolder = (NewVoicemailAlertViewHolder) viewHolder;
- @RowType int viewType = getItemViewType(position);
-
- Assert.checkArgument(position == 0, "position is not 0");
- Assert.checkArgument(
- position == voicemailAlertPosition,
- String.format(
- Locale.US,
- "position:%d and voicemailAlertPosition:%d are different",
- position,
- voicemailAlertPosition));
- Assert.checkArgument(viewType == RowType.VOICEMAIL_ALERT, "Invalid row type: " + viewType);
- Assert.checkArgument(
- voicemailErrorMessage.getActions().size() <= 2,
- "Too many actions: " + voicemailErrorMessage.getActions().size());
-
- alertViewHolder.setTitle(voicemailErrorMessage.getTitle());
- alertViewHolder.setDescription(voicemailErrorMessage.getDescription());
-
- if (!voicemailErrorMessage.getActions().isEmpty()) {
- alertViewHolder.setPrimaryButton(voicemailErrorMessage.getActions().get(0));
- }
- if (voicemailErrorMessage.getActions().size() > 1) {
- alertViewHolder.setSecondaryButton(voicemailErrorMessage.getActions().get(1));
- }
- }
-
- private void onBindHeaderViewHolder(ViewHolder viewHolder, int position) {
- NewVoicemailHeaderViewHolder headerViewHolder = (NewVoicemailHeaderViewHolder) viewHolder;
- @RowType int viewType = getItemViewType(position);
- if (position == todayHeaderPosition) {
- headerViewHolder.setHeader(R.string.new_voicemail_header_today);
- } else if (position == yesterdayHeaderPosition) {
- headerViewHolder.setHeader(R.string.new_voicemail_header_yesterday);
- } else if (position == olderHeaderPosition) {
- headerViewHolder.setHeader(R.string.new_voicemail_header_older);
- } else {
- throw Assert.createIllegalStateFailException(
- "Unexpected view type " + viewType + " at position: " + position);
- }
- }
-
- private void printArrayMap() {
- LogUtil.i(
- "NewVoicemailAdapter.printArrayMap",
- "hashMapSize: %d, currentlyExpandedViewHolderId:%d",
- newVoicemailViewHolderArrayMap.size(),
- currentlyExpandedViewHolderId);
-
- if (!newVoicemailViewHolderArrayMap.isEmpty()) {
- String ids = "";
- for (long id : newVoicemailViewHolderArrayMap.keySet()) {
- ids = ids + id + " ";
- }
- LogUtil.i("NewVoicemailAdapter.printArrayMap", "ids are " + ids);
- }
- }
-
- private void printHashSet() {
- LogUtil.i(
- "NewVoicemailAdapter.printHashSet",
- "hashSetSize: %d, currentlyExpandedViewHolderId:%d",
- newVoicemailViewHolderSet.size(),
- currentlyExpandedViewHolderId);
-
- if (!newVoicemailViewHolderSet.isEmpty()) {
- String viewHolderID = "";
- for (NewVoicemailViewHolder vh : newVoicemailViewHolderSet) {
- viewHolderID = viewHolderID + vh.getViewHolderId() + " ";
- }
- LogUtil.i("NewVoicemailAdapter.printHashSet", "ids are " + viewHolderID);
- }
- }
-
- /**
- * The {@link NewVoicemailAdapter} needs to keep track of {@link NewVoicemailViewHolder} that has
- * been expanded. This is so that the adapter can ensure the correct {@link
- * NewVoicemailMediaPlayerView} and {@link NewVoicemailViewHolder} states are maintained
- * (playing/paused/reset) for the expanded viewholder, especially when views are recycled in
- * {@link RecyclerView}. Since we can only have one expanded voicemail view holder, this method
- * ensures that except for the currently expanded view holder, all the other view holders visible
- * on the screen are collapsed.
- *
- * <p>The {@link NewVoicemailMediaPlayer} is also reset, if there is an existing playing
- * voicemail.
- *
- * <p>This is the function that is responsible of keeping track of the expanded viewholder in the
- * {@link NewVoicemailAdapter}
- *
- * <p>This is the first function called in the adapter when a viewholder has been expanded.
- *
- * <p>This is the function that is responsible of keeping track of the expanded viewholder in the
- * {@link NewVoicemailAdapter}
- *
- * @param viewHolderRequestedToExpand is the view holder that is currently expanded.
- * @param voicemailEntryOfViewHolder
- */
- @Override
- public void expandViewHolderFirstTimeAndCollapseAllOtherVisibleViewHolders(
- NewVoicemailViewHolder viewHolderRequestedToExpand,
- VoicemailEntry voicemailEntryOfViewHolder,
- NewVoicemailViewHolderListener listener) {
-
- LogUtil.i(
- "NewVoicemailAdapter.expandViewHolderFirstTimeAndCollapseAllOtherVisibleViewHolders",
- "viewholder id:%d being request to expand, isExpanded:%b, size of our view holder "
- + "dataset:%d, hashmap size:%d",
- viewHolderRequestedToExpand.getViewHolderId(),
- viewHolderRequestedToExpand.isViewHolderExpanded(),
- newVoicemailViewHolderSet.size(),
- newVoicemailViewHolderArrayMap.size());
-
- currentlyExpandedViewHolderId = viewHolderRequestedToExpand.getViewHolderId();
-
- for (NewVoicemailViewHolder viewHolder : newVoicemailViewHolderSet) {
- if (viewHolder.getViewHolderId() != viewHolderRequestedToExpand.getViewHolderId()) {
- viewHolder.collapseViewHolder();
- }
- }
-
- // If the media player is playing and we expand something other than the currently playing one
- // we should stop playing the media player
- if (mediaPlayer.isPlaying()
- && !Objects.equals(
- mediaPlayer.getLastPlayedOrPlayingVoicemailUri(),
- viewHolderRequestedToExpand.getViewHolderVoicemailUri())) {
- LogUtil.i(
- "NewVoicemailAdapter.expandViewHolderFirstTimeAndCollapseAllOtherVisibleViewHolders",
- "Reset the media player since we expanded something other that the playing "
- + "voicemail, MP was playing:%s, viewholderExpanded:%d, MP.isPlaying():%b",
- String.valueOf(mediaPlayer.getLastPlayedOrPlayingVoicemailUri()),
- viewHolderRequestedToExpand.getViewHolderId(),
- mediaPlayer.isPlaying());
- mediaPlayer.reset();
- }
-
- // If the media player is paused and we expand something other than the currently paused one
- // we should stop playing the media player
- if (mediaPlayer.isPaused()
- && !Objects.equals(
- mediaPlayer.getLastPausedVoicemailUri(),
- viewHolderRequestedToExpand.getViewHolderVoicemailUri())) {
- LogUtil.i(
- "NewVoicemailAdapter.expandViewHolderFirstTimeAndCollapseAllOtherVisibleViewHolders",
- "There was an existing paused viewholder, the media player should reset since we "
- + "expanded something other that the paused voicemail, MP.paused:%s",
- String.valueOf(mediaPlayer.getLastPausedVoicemailUri()));
- mediaPlayer.reset();
- }
-
- Assert.checkArgument(
- !viewHolderRequestedToExpand.isViewHolderExpanded(),
- "cannot expand a voicemail that is not collapsed");
-
- viewHolderRequestedToExpand.expandAndBindViewHolderAndMediaPlayerViewWithAdapterValues(
- voicemailEntryOfViewHolder, fragmentManager, mediaPlayer, listener);
-
- // There should be nothing playing when we expand a viewholder for the first time
- Assert.checkArgument(!mediaPlayer.isPlaying());
- }
-
- /**
- * Ensures that when we collapse the expanded view, we don't expand it again when we are recycling
- * the viewholders. If we collapse an existing playing voicemail viewholder, we should stop
- * playing it.
- *
- * @param collapseViewHolder is the view holder that is currently collapsed.
- */
- @Override
- public void collapseExpandedViewHolder(NewVoicemailViewHolder collapseViewHolder) {
- Assert.checkArgument(collapseViewHolder.getViewHolderId() == currentlyExpandedViewHolderId);
- collapseViewHolder.collapseViewHolder();
- currentlyExpandedViewHolderId = -1;
-
- // If the view holder is currently playing, then we should stop playing it.
- if (mediaPlayer.isPlaying()) {
- Assert.checkArgument(
- Objects.equals(
- mediaPlayer.getLastPlayedOrPlayingVoicemailUri(),
- collapseViewHolder.getViewHolderVoicemailUri()),
- "the voicemail being played should have been of the recently collapsed view holder.");
- mediaPlayer.reset();
- }
- }
-
- @Override
- public void pauseViewHolder(NewVoicemailViewHolder expandedViewHolder) {
- Assert.isNotNull(
- getCurrentlyExpandedViewHolder(),
- "cannot have pressed pause if the viewholder wasn't expanded");
- Assert.checkArgument(
- getCurrentlyExpandedViewHolder()
- .getViewHolderVoicemailUri()
- .equals(expandedViewHolder.getViewHolderVoicemailUri()),
- "view holder whose pause button was pressed has to have been the expanded "
- + "viewholder being tracked by the adapter.");
- mediaPlayer.pauseMediaPlayer(expandedViewHolder.getViewHolderVoicemailUri());
- expandedViewHolder.setPausedStateOfMediaPlayerView(
- expandedViewHolder.getViewHolderVoicemailUri(), mediaPlayer);
- }
-
- @Override
- public void resumePausedViewHolder(NewVoicemailViewHolder expandedViewHolder) {
- Assert.isNotNull(
- getCurrentlyExpandedViewHolder(),
- "cannot have pressed pause if the viewholder wasn't expanded");
- Assert.checkArgument(
- getCurrentlyExpandedViewHolder()
- .getViewHolderVoicemailUri()
- .equals(expandedViewHolder.getViewHolderVoicemailUri()),
- "view holder whose play button was pressed has to have been the expanded "
- + "viewholder being tracked by the adapter.");
- Assert.isNotNull(
- mediaPlayer.getLastPausedVoicemailUri(), "there should be be an pausedUri to resume");
- Assert.checkArgument(
- mediaPlayer
- .getLastPlayedOrPlayingVoicemailUri()
- .equals(expandedViewHolder.getViewHolderVoicemailUri()),
- "only the last playing uri can be resumed");
- Assert.checkArgument(
- mediaPlayer
- .getLastPreparedOrPreparingToPlayVoicemailUri()
- .equals(expandedViewHolder.getViewHolderVoicemailUri()),
- "only the last prepared uri can be resumed");
- Assert.checkArgument(
- mediaPlayer
- .getLastPreparedOrPreparingToPlayVoicemailUri()
- .equals(mediaPlayer.getLastPlayedOrPlayingVoicemailUri()),
- "the last prepared and playing voicemails have to be the same when resuming");
-
- onPreparedListener.onPrepared(mediaPlayer.getMediaPlayer());
- }
-
- @Override
- public void deleteViewHolder(
- Context context,
- FragmentManager fragmentManager,
- NewVoicemailViewHolder expandedViewHolder,
- Uri voicemailUri) {
- LogUtil.i(
- "NewVoicemailAdapter.deleteViewHolder",
- "deleting adapter position %d, id:%d, uri:%s ",
- expandedViewHolder.getAdapterPosition(),
- expandedViewHolder.getViewHolderId(),
- String.valueOf(voicemailUri));
-
- deletedVoicemailPosition.add(expandedViewHolder.getAdapterPosition());
-
- Assert.checkArgument(expandedViewHolder.getViewHolderVoicemailUri().equals(voicemailUri));
-
- Assert.checkArgument(currentlyExpandedViewHolderId == expandedViewHolder.getViewHolderId());
-
- collapseExpandedViewHolder(expandedViewHolder);
-
- showUndoSnackbar(
- context,
- expandedViewHolder.getMediaPlayerView(),
- expandedViewHolder.getAdapterPosition(),
- voicemailUri);
- }
-
- private void showUndoSnackbar(
- Context context, View newVoicemailMediaPlayerView, int position, Uri voicemailUri) {
- LogUtil.i(
- "NewVoicemailAdapter.showUndoSnackbar",
- "position:%d and uri:%s",
- position,
- String.valueOf(voicemailUri));
- Snackbar undoSnackbar =
- Snackbar.make(
- newVoicemailMediaPlayerView,
- R.string.snackbar_voicemail_deleted,
- VOICEMAIL_DELETE_DELAY_MS);
- undoSnackbar.addCallback(
- new Snackbar.Callback() {
- @Override
- public void onShown(Snackbar sb) {
- notifyItemRemoved(position);
- LogUtil.i(
- "NewVoicemailAdapter.showUndoSnackbar",
- "onShown for position:%d and uri:%s",
- position,
- voicemailUri);
- super.onShown(sb);
- }
-
- @Override
- public void onDismissed(Snackbar transientBottomBar, int event) {
- LogUtil.i(
- "NewVoicemailAdapter.showUndoSnackbar",
- "onDismissed for event:%d, position:%d and uri:%s",
- event,
- position,
- String.valueOf(voicemailUri));
-
- switch (event) {
- case DISMISS_EVENT_SWIPE:
- case DISMISS_EVENT_ACTION:
- case DISMISS_EVENT_MANUAL:
- LogUtil.i(
- "NewVoicemailAdapter.showUndoSnackbar",
- "Not proceeding with deleting the voicemail");
- deletedVoicemailPosition.remove(position);
- notifyItemChanged(position);
- break;
- case DISMISS_EVENT_TIMEOUT:
- case DISMISS_EVENT_CONSECUTIVE:
- LogUtil.i(
- "NewVoicemailAdapter.showUndoSnackbar", "Proceeding with deleting voicemail");
-
- DialerExecutorComponent.get(context)
- .dialerExecutorFactory()
- .createNonUiTaskBuilder(this::deleteVoicemail)
- .build()
- .executeSerial(new Pair<>(context, voicemailUri));
- break;
- default:
- Assert.checkArgument(event <= 4 && event >= 0, "unknown event");
- }
- }
-
- @WorkerThread
- private Void deleteVoicemail(Pair<Context, Uri> contextUriPair) {
- Assert.isWorkerThread();
- Context context = contextUriPair.first;
- Uri uri = contextUriPair.second;
- LogUtil.i(
- "NewVoicemailAdapter.deleteVoicemail", "deleting uri:%s", String.valueOf(uri));
- ContentValues values = new ContentValues();
- values.put(Voicemails.DELETED, "1");
-
- int numRowsUpdated = context.getContentResolver().update(uri, values, null, null);
-
- LogUtil.i("NewVoicemailAdapter.deleteVoicemail", "return value:%d", numRowsUpdated);
- Assert.checkArgument(numRowsUpdated == 1, "voicemail delete was not successful");
-
- Intent intent = new Intent(VoicemailClient.ACTION_UPLOAD);
- intent.setPackage(context.getPackageName());
- context.sendBroadcast(intent);
- return null;
- }
- });
-
- undoSnackbar
- .setAction(
- R.string.snackbar_undo,
- new OnClickListener() {
- @Override
- public void onClick(View v) {
- // does nothing, but needed for the undo button to show
- }
- })
- .setActionTextColor(
- context.getResources().getColor(R.color.dialer_snackbar_action_text_color))
- .show();
- }
-
- /**
- * This function is called recursively to update the seekbar, duration, play/pause buttons of the
- * expanded view holder if its playing.
- *
- * <p>Since this function is called at 30 frames/second, its possible (and eventually will happen)
- * that between each update the playing voicemail state could have changed, in which case this
- * method should stop calling itself. These conditions are:
- *
- * <ul>
- * <li>The user scrolled the playing voicemail out of view.
- * <li>Another view holder was expanded.
- * <li>The playing voicemail was paused.
- * <li>The media player returned {@link MediaPlayer#isPlaying()} to be true but had its {@link
- * MediaPlayer#getCurrentPosition()} > {@link MediaPlayer#getDuration()}.
- * <li>The {@link MediaPlayer} stopped playing.
- * </ul>
- *
- * <p>Note: Since the update happens at 30 frames/second, it's also possible that the viewholder
- * was recycled when scrolling the playing voicemail out of view.
- *
- * @param expandedViewHolderPossiblyPlaying the view holder that was expanded and could or could
- * not be playing. This viewholder can be recycled.
- */
- private void recursivelyUpdateMediaPlayerViewOfExpandedViewHolder(
- NewVoicemailViewHolder expandedViewHolderPossiblyPlaying) {
- // TODO(uabdullah): a bug Remove logging, temporarily here for debugging.
- LogUtil.i(
- "NewVoicemailAdapter.recursivelyUpdateMediaPlayerViewOfExpandedViewHolder",
- "currentlyExpanded:%d",
- currentlyExpandedViewHolderId);
-
- // It's possible that by the time this is run, the expanded view holder has been
- // scrolled out of view (and possibly recycled)
- if (getCurrentlyExpandedViewHolder() == null) {
- LogUtil.i(
- "NewVoicemailAdapter.recursivelyUpdateMediaPlayerViewOfExpandedViewHolder",
- "viewholder:%d media player view, no longer on screen, no need to update",
- expandedViewHolderPossiblyPlaying.getViewHolderId());
- return;
- }
-
- // Another viewholder was expanded, no need to update
- if (!getCurrentlyExpandedViewHolder().equals(expandedViewHolderPossiblyPlaying)) {
- LogUtil.i(
- "NewVoicemailAdapter.recursivelyUpdateMediaPlayerViewOfExpandedViewHolder",
- "currentlyExpandedViewHolderId:%d and the one we are attempting to update:%d "
- + "aren't the same.",
- currentlyExpandedViewHolderId,
- expandedViewHolderPossiblyPlaying.getViewHolderId());
- return;
- }
-
- Assert.checkArgument(expandedViewHolderPossiblyPlaying.isViewHolderExpanded());
- Assert.checkArgument(
- expandedViewHolderPossiblyPlaying.getViewHolderId()
- == getCurrentlyExpandedViewHolder().getViewHolderId());
-
- // If the viewholder was paused, there is no need to update the media player view
- if (mediaPlayer.isPaused()) {
- Assert.checkArgument(
- expandedViewHolderPossiblyPlaying
- .getViewHolderVoicemailUri()
- .equals(mediaPlayer.getLastPausedVoicemailUri()),
- "only the expanded viewholder can be paused.");
-
- LogUtil.i(
- "NewVoicemailAdapter.recursivelyUpdateMediaPlayerViewOfExpandedViewHolder",
- "set the media player to a paused state");
- expandedViewHolderPossiblyPlaying.setPausedStateOfMediaPlayerView(
- expandedViewHolderPossiblyPlaying.getViewHolderVoicemailUri(), mediaPlayer);
- return;
- }
-
- // In some weird corner cases a media player could return isPlaying() as true but would
- // have getCurrentPosition > getDuration(). We consider that as the voicemail has finished
- // playing.
- if (mediaPlayer.isPlaying() && mediaPlayer.getCurrentPosition() < mediaPlayer.getDuration()) {
-
- Assert.checkArgument(
- mediaPlayer
- .getLastPlayedOrPlayingVoicemailUri()
- .equals(getCurrentlyExpandedViewHolder().getViewHolderVoicemailUri()));
- // TODO(uabdullah): a bug Remove logging, temporarily here for debugging.
- LogUtil.i(
- "NewVoicemailAdapter.recursivelyUpdateMediaPlayerViewOfExpandedViewHolder",
- "recursely update the player, currentlyExpanded:%d",
- expandedViewHolderPossiblyPlaying.getViewHolderId());
-
- Assert.checkArgument(
- expandedViewHolderPossiblyPlaying
- .getViewHolderVoicemailUri()
- .equals(getCurrentlyExpandedViewHolder().getViewHolderVoicemailUri()));
-
- expandedViewHolderPossiblyPlaying.updateMediaPlayerViewWithPlayingState(
- expandedViewHolderPossiblyPlaying, mediaPlayer);
-
- ThreadUtil.postDelayedOnUiThread(
- new Runnable() {
- @Override
- public void run() {
- recursivelyUpdateMediaPlayerViewOfExpandedViewHolder(
- expandedViewHolderPossiblyPlaying);
- }
- },
- 1000 / 30 /*30 FPS*/);
- return;
- }
-
- if (!mediaPlayer.isPlaying()
- || (mediaPlayer.isPlaying()
- && mediaPlayer.getCurrentPosition() > mediaPlayer.getDuration())) {
- LogUtil.i(
- "NewVoicemailAdapter.recursivelyUpdateMediaPlayerViewOfExpandedViewHolder",
- "resetting the player, currentlyExpanded:%d, MPPlaying:%b",
- getCurrentlyExpandedViewHolder().getViewHolderId(),
- mediaPlayer.isPlaying());
- mediaPlayer.reset();
- Assert.checkArgument(
- expandedViewHolderPossiblyPlaying
- .getViewHolderVoicemailUri()
- .equals(getCurrentlyExpandedViewHolder().getViewHolderVoicemailUri()));
- expandedViewHolderPossiblyPlaying.setMediaPlayerViewToResetState(
- expandedViewHolderPossiblyPlaying, mediaPlayer);
- return;
- }
-
- String error =
- String.format(
- "expandedViewHolderPossiblyPlaying:%d, expanded:%b, CurrentExpanded:%d, uri:%s, "
- + "MPPlaying:%b, MPPaused:%b, MPPreparedUri:%s, MPPausedUri:%s",
- expandedViewHolderPossiblyPlaying.getViewHolderId(),
- expandedViewHolderPossiblyPlaying.isViewHolderExpanded(),
- currentlyExpandedViewHolderId,
- String.valueOf(expandedViewHolderPossiblyPlaying.getViewHolderVoicemailUri()),
- mediaPlayer.isPlaying(),
- mediaPlayer.isPaused(),
- String.valueOf(mediaPlayer.getLastPreparedOrPreparingToPlayVoicemailUri()),
- String.valueOf(mediaPlayer.getLastPreparedOrPreparingToPlayVoicemailUri()));
-
- throw Assert.createAssertionFailException(
- "All cases should have been handled before. Error " + error);
- }
-
- // When a voicemail has finished playing.
- OnCompletionListener onCompletionListener =
- new OnCompletionListener() {
-
- @Override
- public void onCompletion(MediaPlayer mp) {
- Assert.checkArgument(
- mediaPlayer
- .getLastPlayedOrPlayingVoicemailUri()
- .equals(mediaPlayer.getLastPreparedOrPreparingToPlayVoicemailUri()));
- Assert.checkArgument(!mediaPlayer.isPlaying());
-
- LogUtil.i(
- "NewVoicemailAdapter.onCompletionListener",
- "completed playing voicemailUri: %s, expanded viewholder is %d, visibility :%b",
- mediaPlayer.getLastPlayedOrPlayingVoicemailUri().toString(),
- currentlyExpandedViewHolderId,
- isCurrentlyExpandedViewHolderInViewHolderSet());
-
- Assert.checkArgument(
- currentlyExpandedViewHolderId != -1,
- "a voicemail that was never expanded, should never be playing.");
- mediaPlayer.reset();
- }
- };
-
- // When a voicemail has been prepared and can be played
- private final OnPreparedListener onPreparedListener =
- new OnPreparedListener() {
-
- /**
- * When a user pressed the play button, this listener should be called immediately. The
- * asserts ensures that is the case. This function starts playing the voicemail and updates
- * the UI.
- */
- @Override
- public void onPrepared(MediaPlayer mp) {
- LogUtil.i(
- "NewVoicemailAdapter.onPrepared",
- "MPPreparedUri: %s, currentlyExpandedViewHolderId:%d, and its visibility on "
- + "the screen is:%b",
- String.valueOf(mediaPlayer.getLastPreparedOrPreparingToPlayVoicemailUri()),
- currentlyExpandedViewHolderId,
- isCurrentlyExpandedViewHolderInViewHolderSet());
-
- NewVoicemailViewHolder currentlyExpandedViewHolder = getCurrentlyExpandedViewHolder();
- Assert.checkArgument(currentlyExpandedViewHolder != null);
- Assert.checkArgument(
- currentlyExpandedViewHolder
- .getViewHolderVoicemailUri()
- .equals(mediaPlayer.getLastPreparedOrPreparingToPlayVoicemailUri()),
- "should only have prepared the last expanded view holder.");
-
- mediaPlayer.start(mediaPlayer.getLastPreparedOrPreparingToPlayVoicemailUri());
-
- recursivelyUpdateMediaPlayerViewOfExpandedViewHolder(currentlyExpandedViewHolder);
-
- Assert.checkArgument(mediaPlayer.isPlaying());
- LogUtil.i("NewVoicemailAdapter.onPrepared", "voicemail should be playing");
- }
- };
-
- // TODO(uabdullah): when playing the voicemail results in an error
- // we must update the viewholder and mention there was an error playing the voicemail, and reset
- // the media player and the media player view
- private final OnErrorListener onErrorListener =
- new OnErrorListener() {
- @Override
- public boolean onError(MediaPlayer mp, int what, int extra) {
- LogUtil.e("NewVoicemailAdapter.onError", "onError, what:%d, extra:%d", what, extra);
- Assert.checkArgument(
- mediaPlayer.getMediaPlayer().equals(mp),
- "there should always only be one instance of the media player");
- Assert.checkArgument(
- mediaPlayer
- .getLastPlayedOrPlayingVoicemailUri()
- .equals(mediaPlayer.getLastPreparedOrPreparingToPlayVoicemailUri()));
- LogUtil.i(
- "NewVoicemailAdapter.onErrorListener",
- "error playing voicemailUri: %s",
- mediaPlayer.getLastPlayedOrPlayingVoicemailUri().toString());
- return false;
- }
- };
-
- private boolean isCurrentlyExpandedViewHolderInViewHolderSet() {
- for (NewVoicemailViewHolder viewHolder : newVoicemailViewHolderSet) {
- if (viewHolder.getViewHolderId() == currentlyExpandedViewHolderId) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * The expanded view holder may or may not be visible on the screen. Since the {@link
- * NewVoicemailViewHolder} may be recycled, it's possible that the expanded view holder is
- * recycled for a non-expanded view holder when the expanded view holder is scrolled out of view.
- *
- * @return the expanded view holder if it is amongst the recycled views on the screen, otherwise
- * null.
- */
- @Nullable
- private NewVoicemailViewHolder getCurrentlyExpandedViewHolder() {
- if (newVoicemailViewHolderArrayMap.containsKey(currentlyExpandedViewHolderId)) {
- Assert.checkArgument(
- newVoicemailViewHolderArrayMap.get(currentlyExpandedViewHolderId).getViewHolderId()
- == currentlyExpandedViewHolderId);
- return newVoicemailViewHolderArrayMap.get(currentlyExpandedViewHolderId);
- } else {
- // returned when currentlyExpandedViewHolderId = -1 (viewholder was collapsed)
- LogUtil.i(
- "NewVoicemailAdapter.getCurrentlyExpandedViewHolder",
- "no view holder found in hashmap size:%d for %d",
- newVoicemailViewHolderArrayMap.size(),
- currentlyExpandedViewHolderId);
- // TODO(uabdullah): a bug Remove logging, temporarily here for debugging.
- printHashSet();
- printArrayMap();
- return null;
- }
- }
-
- @Override
- public int getItemCount() {
- // TODO(uabdullah): a bug Remove logging, temporarily here for debugging.
- LogUtil.enterBlock("NewVoicemailAdapter.getItemCount");
- int numberOfHeaders = 0;
- if (voicemailAlertPosition != Integer.MAX_VALUE) {
- numberOfHeaders++;
- }
- if (todayHeaderPosition != Integer.MAX_VALUE) {
- numberOfHeaders++;
- }
- if (yesterdayHeaderPosition != Integer.MAX_VALUE) {
- numberOfHeaders++;
- }
- if (olderHeaderPosition != Integer.MAX_VALUE) {
- numberOfHeaders++;
- }
- // TODO(uabdullah): a bug Remove logging, temporarily here for debugging.
- LogUtil.i(
- "NewVoicemailAdapter.getItemCount",
- "cursor cnt:%d, num of headers:%d, delete size:%d",
- cursor.getCount(),
- numberOfHeaders,
- deletedVoicemailPosition.size());
- return cursor.getCount() + numberOfHeaders - deletedVoicemailPosition.size();
- }
-
- @RowType
- @Override
- public int getItemViewType(int position) {
- LogUtil.enterBlock("NewVoicemailAdapter.getItemViewType");
- if (voicemailAlertPosition != Integer.MAX_VALUE && position == voicemailAlertPosition) {
- return RowType.VOICEMAIL_ALERT;
- }
- if (todayHeaderPosition != Integer.MAX_VALUE && position == todayHeaderPosition) {
- return RowType.HEADER;
- }
- if (yesterdayHeaderPosition != Integer.MAX_VALUE && position == yesterdayHeaderPosition) {
- return RowType.HEADER;
- }
- if (olderHeaderPosition != Integer.MAX_VALUE && position == olderHeaderPosition) {
- return RowType.HEADER;
- }
- return RowType.VOICEMAIL_ENTRY;
- }
-
- /**
- * This will be called once the voicemail that was attempted to be played (and was not locally
- * available) was downloaded from the server. However it is possible that by the time the download
- * was completed, the view holder was collapsed. In that case we shouldn't play the voicemail.
- */
- public void checkAndPlayVoicemail() {
- LogUtil.i(
- "NewVoicemailAdapter.checkAndPlayVoicemail",
- "expandedViewHolder:%d, inViewHolderSet:%b, MPRequestToDownload:%s",
- currentlyExpandedViewHolderId,
- isCurrentlyExpandedViewHolderInViewHolderSet(),
- String.valueOf(mediaPlayer.getVoicemailRequestedToDownload()));
-
- NewVoicemailViewHolder currentlyExpandedViewHolder = getCurrentlyExpandedViewHolder();
- if (currentlyExpandedViewHolderId != -1
- && isCurrentlyExpandedViewHolderInViewHolderSet()
- && currentlyExpandedViewHolder != null
- // Used to differentiate underlying table changes from voicemail downloads and other changes
- // (e.g delete)
- && mediaPlayer.getVoicemailRequestedToDownload() != null
- && (mediaPlayer
- .getVoicemailRequestedToDownload()
- .equals(currentlyExpandedViewHolder.getViewHolderVoicemailUri()))) {
- currentlyExpandedViewHolder.clickPlayButtonOfViewHoldersMediaPlayerView(
- currentlyExpandedViewHolder);
- } else {
- LogUtil.i("NewVoicemailAdapter.checkAndPlayVoicemail", "not playing downloaded voicemail");
- }
- }
-
- /**
- * Updates the voicemail alert message to reflect the state of the {@link VoicemailStatus} table.
- * TODO(uabdullah): Handle ToS properly (a bug)
- */
- public void updateVoicemailAlertWithMostRecentStatus(
- Context context, ImmutableList<VoicemailStatus> voicemailStatuses) {
-
- if (voicemailStatuses.isEmpty()) {
- LogUtil.i(
- "NewVoicemailAdapter.updateVoicemailAlertWithMostRecentStatus",
- "voicemailStatuses was empty");
- return;
- }
-
- voicemailErrorMessage = null;
- VoicemailErrorMessageCreator messageCreator = new VoicemailErrorMessageCreator();
-
- for (VoicemailStatus status : voicemailStatuses) {
- voicemailErrorMessage = messageCreator.create(context, status, null);
- if (voicemailErrorMessage != null) {
- break;
- }
- }
-
- if (voicemailErrorMessage != null) {
- LogUtil.i("NewVoicemailAdapter.updateVoicemailAlertWithMostRecentStatus", "showing alert");
- voicemailAlertPosition = 0;
- updateHeaderPositions();
- notifyItemChanged(0);
- }
- }
-}
diff --git a/java/com/android/dialer/voicemail/listui/NewVoicemailAlertViewHolder.java b/java/com/android/dialer/voicemail/listui/NewVoicemailAlertViewHolder.java
deleted file mode 100644
index ac989a8..0000000
--- a/java/com/android/dialer/voicemail/listui/NewVoicemailAlertViewHolder.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * 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.voicemail.listui;
-
-import android.support.v7.widget.RecyclerView.ViewHolder;
-import android.view.View;
-import android.widget.Button;
-import android.widget.TextView;
-import com.android.dialer.voicemail.listui.error.VoicemailErrorMessage.Action;
-
-/** ViewHolder for {@link NewVoicemailAdapter} to display voicemail error states. */
-final class NewVoicemailAlertViewHolder extends ViewHolder {
-
- private final TextView voicemailErrorTitleTextView;
- private final TextView voicemailErrorDetailsTextView;
- private final Button primaryButton;
- private final Button secondaryButton;
-
- NewVoicemailAlertViewHolder(View view) {
- super(view);
- voicemailErrorTitleTextView = view.findViewById(R.id.voicemail_alert_header);
- voicemailErrorDetailsTextView = view.findViewById(R.id.voicemail_alert_details);
- primaryButton = view.findViewById(R.id.voicemail_alert_primary_button);
- secondaryButton = view.findViewById(R.id.voicemail_alert_primary_button);
- }
-
- void setTitle(CharSequence error) {
- voicemailErrorTitleTextView.setText(error);
- }
-
- void setDescription(CharSequence error) {
- voicemailErrorDetailsTextView.setText(error);
- }
-
- void setPrimaryButton(Action action) {
- primaryButton.setVisibility(View.VISIBLE);
- primaryButton.setText(action.getText());
- primaryButton.setOnClickListener(action.getListener());
- }
-
- void setSecondaryButton(Action action) {
- secondaryButton.setVisibility(View.VISIBLE);
- secondaryButton.setText(action.getText());
- secondaryButton.setOnClickListener(action.getListener());
- }
-}
diff --git a/java/com/android/dialer/voicemail/listui/NewVoicemailFragment.java b/java/com/android/dialer/voicemail/listui/NewVoicemailFragment.java
deleted file mode 100644
index 87b0a63..0000000
--- a/java/com/android/dialer/voicemail/listui/NewVoicemailFragment.java
+++ /dev/null
@@ -1,308 +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.voicemail.listui;
-
-import android.content.Context;
-import android.database.Cursor;
-import android.os.Bundle;
-import android.provider.VoicemailContract.Status;
-import android.support.annotation.Nullable;
-import android.support.v4.app.Fragment;
-import android.support.v4.app.LoaderManager.LoaderCallbacks;
-import android.support.v4.content.Loader;
-import android.support.v4.content.LocalBroadcastManager;
-import android.support.v7.widget.LinearLayoutManager;
-import android.support.v7.widget.RecyclerView;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.FrameLayout;
-import com.android.dialer.calllog.CallLogComponent;
-import com.android.dialer.calllog.RefreshAnnotatedCallLogReceiver;
-import com.android.dialer.common.LogUtil;
-import com.android.dialer.common.concurrent.DialerExecutorComponent;
-import com.android.dialer.common.concurrent.UiListener;
-import com.android.dialer.voicemail.listui.error.VoicemailStatus;
-import com.android.dialer.voicemailstatus.VoicemailStatusQuery;
-import com.android.dialer.widget.EmptyContentView;
-import com.android.voicemail.VoicemailComponent;
-import com.google.common.collect.ImmutableList;
-import com.google.common.util.concurrent.ListenableFuture;
-import java.util.ArrayList;
-import java.util.List;
-
-// TODO(uabdullah): Register content observer for VoicemailContract.Status.CONTENT_URI in onStart
-/** Fragment for Dialer Voicemail Tab. */
-public final class NewVoicemailFragment extends Fragment implements LoaderCallbacks<Cursor> {
-
- private RecyclerView recyclerView;
- private RefreshAnnotatedCallLogReceiver refreshAnnotatedCallLogReceiver;
- private UiListener<ImmutableList<VoicemailStatus>> queryVoicemailStatusTableListener;
-
- // View required to show/hide recycler and empty views
- FrameLayout fragmentRootFrameLayout;
-
- private EmptyContentView emptyContentView;
-
- public NewVoicemailFragment() {
- LogUtil.enterBlock("NewVoicemailFragment.NewVoicemailFragment");
- }
-
- @Override
- public void onActivityCreated(@Nullable Bundle savedInstanceState) {
- super.onActivityCreated(savedInstanceState);
-
- LogUtil.enterBlock("NewVoicemailFragment.onActivityCreated");
-
- refreshAnnotatedCallLogReceiver = new RefreshAnnotatedCallLogReceiver(getContext());
- queryVoicemailStatusTableListener =
- DialerExecutorComponent.get(getContext())
- .createUiListener(
- getActivity().getFragmentManager(),
- "NewVoicemailFragment.queryVoicemailStatusTable");
- }
-
- @Override
- public void onStart() {
- super.onStart();
- LogUtil.enterBlock("NewVoicemailFragment.onStart");
- }
-
- @Override
- public void onResume() {
- super.onResume();
-
- boolean isHidden = isHidden();
- LogUtil.i("NewVoicemailFragment.onResume", "isHidden = %s", isHidden);
-
- // As a fragment's onResume() is tied to the containing Activity's onResume(), being resumed is
- // not equivalent to becoming visible.
- // For example, when an activity with a hidden fragment is resumed, the fragment's onResume()
- // will be called but it is not visible.
- if (!isHidden) {
- onFragmentShown();
- }
- }
-
- @Override
- public void onPause() {
- super.onPause();
- LogUtil.enterBlock("NewVoicemailFragment.onPause");
-
- onFragmentHidden();
- }
-
- @Override
- public void onHiddenChanged(boolean hidden) {
- super.onHiddenChanged(hidden);
- LogUtil.i("NewVoicemailFragment.onHiddenChanged", "hidden = %s", hidden);
-
- if (hidden) {
- onFragmentHidden();
- } else {
- onFragmentShown();
- }
- }
-
- /**
- * To be called when the fragment becomes visible.
- *
- * <p>Note that for a fragment, being resumed is not equivalent to becoming visible.
- *
- * <p>For example, when an activity with a hidden fragment is resumed, the fragment's onResume()
- * will be called but it is not visible.
- */
- private void onFragmentShown() {
- registerRefreshAnnotatedCallLogReceiver();
-
- CallLogComponent.get(getContext())
- .getRefreshAnnotatedCallLogNotifier()
- .notify(/* checkDirty = */ true);
- }
-
- /**
- * To be called when the fragment becomes hidden.
- *
- * <p>This can happen in the following two cases:
- *
- * <ul>
- * <li>hide the fragment but keep the parent activity visible (e.g., calling {@link
- * android.support.v4.app.FragmentTransaction#hide(Fragment)} in an activity, or
- * <li>the parent activity is paused.
- * </ul>
- */
- private void onFragmentHidden() {
- unregisterRefreshAnnotatedCallLogReceiver();
- }
-
- @Override
- public View onCreateView(
- LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
- LogUtil.enterBlock("NewVoicemailFragment.onCreateView");
-
- fragmentRootFrameLayout =
- (FrameLayout) inflater.inflate(R.layout.new_voicemail_call_log_fragment, container, false);
- recyclerView = fragmentRootFrameLayout.findViewById(R.id.new_voicemail_call_log_recycler_view);
-
- emptyContentView = fragmentRootFrameLayout.findViewById(R.id.empty_content_view);
- getLoaderManager().restartLoader(0, null, this);
- return fragmentRootFrameLayout;
- }
-
- @Override
- public Loader<Cursor> onCreateLoader(int id, Bundle args) {
- LogUtil.enterBlock("NewVoicemailFragment.onCreateLoader");
- return new VoicemailCursorLoader(getContext());
- }
-
- @Override
- public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
- LogUtil.i("NewVoicemailFragment.onLoadFinished", "cursor size is %d", data.getCount());
- if (data.getCount() == 0) {
- showEmptyVoicemailFragmentView();
- return;
- }
- showView(recyclerView);
-
- if (recyclerView.getAdapter() == null) {
- recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
- // TODO(uabdullah): Replace getActivity().getFragmentManager() with getChildFragment()
- recyclerView.setAdapter(
- new NewVoicemailAdapter(
- data, System::currentTimeMillis, getActivity().getFragmentManager()));
- } else {
- // This would only be called in cases such as when voicemail has been fetched from the server
- // or a changed occurred in the annotated table changed (e.g deletes). To check if the change
- // was due to a voicemail download,
- // NewVoicemailAdapter.mediaPlayer.getVoicemailRequestedToDownload() is called.
- LogUtil.i(
- "NewVoicemailFragment.onLoadFinished",
- "adapter: %s was not null, checking and playing the voicemail if conditions met",
- recyclerView.getAdapter());
- ((NewVoicemailAdapter) recyclerView.getAdapter()).updateCursor(data);
- ((NewVoicemailAdapter) recyclerView.getAdapter()).checkAndPlayVoicemail();
- queryAndUpdateVoicemailStatusAlert();
- }
- }
-
- /** Shows the view when there are no voicemails to be displayed * */
- private void showEmptyVoicemailFragmentView() {
- LogUtil.enterBlock("NewVoicemailFragment.showEmptyVoicemailFragmentView");
-
- showView(emptyContentView);
-
- emptyContentView.setDescription((R.string.empty_voicemail_tab_text));
- emptyContentView.setImage(R.drawable.quantum_ic_voicemail_vd_theme_24);
- }
-
- private void showView(View view) {
- LogUtil.i("NewVoicemailFragment.showView", "Showing view: " + view);
- emptyContentView.setVisibility(view == emptyContentView ? View.VISIBLE : View.GONE);
- recyclerView.setVisibility(view == recyclerView ? View.VISIBLE : View.GONE);
- }
-
- private void registerRefreshAnnotatedCallLogReceiver() {
- LogUtil.enterBlock("NewVoicemailFragment.registerRefreshAnnotatedCallLogReceiver");
-
- LocalBroadcastManager.getInstance(getContext())
- .registerReceiver(
- refreshAnnotatedCallLogReceiver, RefreshAnnotatedCallLogReceiver.getIntentFilter());
- }
-
- private void unregisterRefreshAnnotatedCallLogReceiver() {
- LogUtil.enterBlock("NewVoicemailFragment.unregisterRefreshAnnotatedCallLogReceiver");
-
- // Cancel pending work as we don't need it any more.
- CallLogComponent.get(getContext()).getRefreshAnnotatedCallLogNotifier().cancel();
-
- LocalBroadcastManager.getInstance(getContext())
- .unregisterReceiver(refreshAnnotatedCallLogReceiver);
- }
-
- private void queryAndUpdateVoicemailStatusAlert() {
- queryVoicemailStatusTableListener.listen(
- getContext(),
- queryVoicemailStatus(getContext()),
- this::updateVoicemailStatusAlert,
- throwable -> {
- throw new RuntimeException(throwable);
- });
- }
-
- private ListenableFuture<ImmutableList<VoicemailStatus>> queryVoicemailStatus(Context context) {
- return DialerExecutorComponent.get(context)
- .backgroundExecutor()
- .submit(
- () -> {
- StringBuilder where = new StringBuilder();
- List<String> selectionArgs = new ArrayList<>();
-
- VoicemailComponent.get(context)
- .getVoicemailClient()
- .appendOmtpVoicemailStatusSelectionClause(context, where, selectionArgs);
-
- ImmutableList.Builder<VoicemailStatus> statuses = ImmutableList.builder();
-
- try (Cursor cursor =
- context
- .getContentResolver()
- .query(
- Status.CONTENT_URI,
- VoicemailStatusQuery.getProjection(),
- where.toString(),
- selectionArgs.toArray(new String[selectionArgs.size()]),
- null)) {
- if (cursor == null) {
- LogUtil.e(
- "NewVoicemailFragment.queryVoicemailStatus", "query failed. Null cursor.");
- return statuses.build();
- }
-
- LogUtil.i(
- "NewVoicemailFragment.queryVoicemailStatus",
- "cursor size:%d ",
- cursor.getCount());
-
- while (cursor.moveToNext()) {
- VoicemailStatus status = new VoicemailStatus(context, cursor);
- if (status.isActive(context)) {
- LogUtil.i(
- "NewVoicemailFragment.queryVoicemailStatus", "inactive source ignored");
- statuses.add(status);
- // TODO(a bug): Handle Service State Listeners
- }
- }
- }
- LogUtil.i(
- "NewVoicemailFragment.queryVoicemailStatus",
- "query returned %d results",
- statuses.build().size());
- return statuses.build();
- });
- }
-
- private void updateVoicemailStatusAlert(ImmutableList<VoicemailStatus> voicemailStatuses) {
- ((NewVoicemailAdapter) recyclerView.getAdapter())
- .updateVoicemailAlertWithMostRecentStatus(getContext(), voicemailStatuses);
- }
-
- @Override
- public void onLoaderReset(Loader<Cursor> loader) {
- LogUtil.enterBlock("NewVoicemailFragment.onLoaderReset");
- recyclerView.setAdapter(null);
- }
-}
diff --git a/java/com/android/dialer/voicemail/listui/NewVoicemailHeaderViewHolder.java b/java/com/android/dialer/voicemail/listui/NewVoicemailHeaderViewHolder.java
deleted file mode 100644
index 6bd8e86..0000000
--- a/java/com/android/dialer/voicemail/listui/NewVoicemailHeaderViewHolder.java
+++ /dev/null
@@ -1,43 +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.voicemail.listui;
-
-import android.support.annotation.StringRes;
-import android.support.annotation.VisibleForTesting;
-import android.support.v7.widget.RecyclerView.ViewHolder;
-import android.view.View;
-import android.widget.TextView;
-
-/** ViewHolder for {@link NewVoicemailAdapter} to display "Today" or "Older" divider row. */
-final class NewVoicemailHeaderViewHolder extends ViewHolder {
-
- private final TextView headerTextView;
-
- NewVoicemailHeaderViewHolder(View view) {
- super(view);
- headerTextView = view.findViewById(R.id.new_voicemail_header_text);
- }
-
- void setHeader(@StringRes int header) {
- headerTextView.setText(header);
- }
-
- @VisibleForTesting(otherwise = VisibleForTesting.NONE)
- String getHeaderText() {
- return headerTextView.getText().toString();
- }
-}
diff --git a/java/com/android/dialer/voicemail/listui/NewVoicemailMediaPlayer.java b/java/com/android/dialer/voicemail/listui/NewVoicemailMediaPlayer.java
deleted file mode 100644
index efa1060..0000000
--- a/java/com/android/dialer/voicemail/listui/NewVoicemailMediaPlayer.java
+++ /dev/null
@@ -1,233 +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.voicemail.listui;
-
-import android.content.Context;
-import android.media.AudioManager;
-import android.media.MediaPlayer;
-import android.media.MediaPlayer.OnCompletionListener;
-import android.media.MediaPlayer.OnErrorListener;
-import android.media.MediaPlayer.OnPreparedListener;
-import android.net.Uri;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import com.android.dialer.common.Assert;
-import com.android.dialer.common.LogUtil;
-import com.android.dialer.strictmode.StrictModeUtils;
-import java.io.IOException;
-
-/** A wrapper around {@link MediaPlayer} */
-public class NewVoicemailMediaPlayer {
-
- private final MediaPlayer mediaPlayer;
- private Uri voicemailLastPlayedOrPlayingUri;
- private Uri voicemailUriLastPreparedOrPreparingToPlay;
-
- private OnErrorListener newVoicemailMediaPlayerOnErrorListener;
- private OnPreparedListener newVoicemailMediaPlayerOnPreparedListener;
- private OnCompletionListener newVoicemailMediaPlayerOnCompletionListener;
- private Uri pausedUri;
- @Nullable private Uri voicemailRequestedToDownload;
-
- public NewVoicemailMediaPlayer(@NonNull MediaPlayer player) {
- mediaPlayer = Assert.isNotNull(player);
- }
-
- // TODO(uabdullah): Consider removing the StrictModeUtils.bypass (a bug)
- public void prepareMediaPlayerAndPlayVoicemailWhenReady(Context context, Uri uri)
- throws IOException {
- Assert.checkArgument(uri != null, "Media player cannot play a null uri");
- LogUtil.i(
- "NewVoicemailMediaPlayer",
- "trying to prepare playing voicemail uri: %s",
- String.valueOf(uri));
- try {
- reset();
- voicemailUriLastPreparedOrPreparingToPlay = uri;
- verifyListenersNotNull();
- LogUtil.i("NewVoicemailMediaPlayer", "setData source");
- StrictModeUtils.bypass(
- () -> {
- try {
- mediaPlayer.setDataSource(context, uri);
- setAudioManagerToNonSpeakerMode(context);
- } catch (IOException e) {
- LogUtil.i(
- "NewVoicemailMediaPlayer",
- "threw an Exception when setting datasource "
- + e
- + " for uri: "
- + uri
- + "for context : "
- + context);
- }
- });
- LogUtil.i("NewVoicemailMediaPlayer", "prepare async");
- StrictModeUtils.bypass(() -> mediaPlayer.prepareAsync());
- } catch (IllegalStateException e) {
- LogUtil.i(
- "NewVoicemailMediaPlayer", "caught an IllegalStateException state exception : \n" + e);
- } catch (Exception e) {
- LogUtil.i(
- "NewVoicemailMediaPlayer",
- "threw an Exception " + e + " for uri: " + uri + "for context : " + context);
- }
- }
-
- /** We should never start playing voicemails from the speaker mode */
- private void setAudioManagerToNonSpeakerMode(Context context) {
- AudioManager audioManager = context.getSystemService(AudioManager.class);
- audioManager.setMode(AudioManager.STREAM_MUSIC);
- audioManager.setSpeakerphoneOn(false);
- }
-
- private void verifyListenersNotNull() {
- Assert.isNotNull(
- newVoicemailMediaPlayerOnErrorListener,
- "newVoicemailMediaPlayerOnErrorListener must be set before preparing to "
- + "play voicemails");
- Assert.isNotNull(
- newVoicemailMediaPlayerOnCompletionListener,
- "newVoicemailMediaPlayerOnCompletionListener must be set before preparing"
- + " to play voicemails");
- Assert.isNotNull(
- newVoicemailMediaPlayerOnPreparedListener,
- "newVoicemailMediaPlayerOnPreparedListener must be set before preparing to"
- + " play voicemails");
- }
-
- // Must be called from onPrepared
- public void start(Uri startPlayingVoicemailUri) {
- Assert.checkArgument(
- startPlayingVoicemailUri.equals(voicemailUriLastPreparedOrPreparingToPlay),
- "uri:%s was not prepared before calling start. Uri that is currently prepared: %s",
- startPlayingVoicemailUri,
- getLastPreparedOrPreparingToPlayVoicemailUri());
-
- mediaPlayer.start();
- voicemailLastPlayedOrPlayingUri = startPlayingVoicemailUri;
- pausedUri = null;
- voicemailRequestedToDownload = null;
- }
-
- public void reset() {
- LogUtil.enterBlock("NewVoicemailMediaPlayer.reset");
- mediaPlayer.reset();
- voicemailLastPlayedOrPlayingUri = null;
- voicemailUriLastPreparedOrPreparingToPlay = null;
- pausedUri = null;
- voicemailRequestedToDownload = null;
- }
-
- public void pauseMediaPlayer(Uri voicemailUri) {
- pausedUri = voicemailUri;
- Assert.checkArgument(
- voicemailUriLastPreparedOrPreparingToPlay.equals(voicemailLastPlayedOrPlayingUri),
- "last prepared and last playing should be the same");
- Assert.checkArgument(
- pausedUri.equals(voicemailLastPlayedOrPlayingUri),
- "only the last played uri can be paused");
- mediaPlayer.pause();
- }
-
- public void seekTo(int progress) {
- mediaPlayer.seekTo(progress);
- }
-
- public void setOnErrorListener(OnErrorListener onErrorListener) {
- mediaPlayer.setOnErrorListener(onErrorListener);
- newVoicemailMediaPlayerOnErrorListener = onErrorListener;
- }
-
- public void setOnPreparedListener(OnPreparedListener onPreparedListener) {
- mediaPlayer.setOnPreparedListener(onPreparedListener);
- newVoicemailMediaPlayerOnPreparedListener = onPreparedListener;
- }
-
- public void setOnCompletionListener(OnCompletionListener onCompletionListener) {
- mediaPlayer.setOnCompletionListener(onCompletionListener);
- newVoicemailMediaPlayerOnCompletionListener = onCompletionListener;
- }
-
- public void setVoicemailRequestedToDownload(@NonNull Uri uri) {
- Assert.isNotNull(uri, "cannot download a null voicemail");
- voicemailRequestedToDownload = uri;
- }
-
- /**
- * Note: In some cases it's possible mediaPlayer.isPlaying() can return true, but
- * mediaPlayer.getCurrentPosition() can be greater than mediaPlayer.getDuration(), after which
- * mediaPlayer.isPlaying() will be false. This is a weird corner case and adding the
- * mediaPlayer.getCurrentPosition() < mediaPlayer.getDuration() check here messes with the
- * mediaPlayer.start() (doesn't return mediaPlayer.isPlaying() to be true immediately).
- *
- * @return if the media plaer;
- */
- public boolean isPlaying() {
- return mediaPlayer.isPlaying();
- }
-
- public int getCurrentPosition() {
- return mediaPlayer.getCurrentPosition();
- }
-
- public Uri getLastPlayedOrPlayingVoicemailUri() {
- if (mediaPlayer.isPlaying()) {
- Assert.isNotNull(voicemailLastPlayedOrPlayingUri);
- }
-
- return voicemailLastPlayedOrPlayingUri == null ? Uri.EMPTY : voicemailLastPlayedOrPlayingUri;
- }
-
- /**
- * All the places that call this function, we expect the voicemail to have been prepared, but we
- * could get rid of the assert check in the future if needed.
- */
- public Uri getLastPreparedOrPreparingToPlayVoicemailUri() {
- return Assert.isNotNull(
- voicemailUriLastPreparedOrPreparingToPlay,
- "we expect whoever called this to have prepared a voicemail before calling this function");
- }
-
- public Uri getLastPausedVoicemailUri() {
- return pausedUri;
- }
-
- public MediaPlayer getMediaPlayer() {
- return mediaPlayer;
- }
-
- public int getDuration() {
- Assert.checkArgument(mediaPlayer != null);
- return mediaPlayer.getDuration();
- }
-
- /**
- * A null v/s non-value is important for the {@link NewVoicemailAdapter} to differentiate between
- * a underlying table change due to a voicemail being downloaded or something else (e.g delete).
- *
- * @return if there was a Uri that was requested to be downloaded from the server, null otherwise.
- */
- @Nullable
- public Uri getVoicemailRequestedToDownload() {
- return voicemailRequestedToDownload;
- }
-
- public boolean isPaused() {
- return pausedUri != null;
- }
-}
diff --git a/java/com/android/dialer/voicemail/listui/NewVoicemailMediaPlayerView.java b/java/com/android/dialer/voicemail/listui/NewVoicemailMediaPlayerView.java
deleted file mode 100644
index f821f4f..0000000
--- a/java/com/android/dialer/voicemail/listui/NewVoicemailMediaPlayerView.java
+++ /dev/null
@@ -1,677 +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.voicemail.listui;
-
-import android.app.FragmentManager;
-import android.content.Context;
-import android.content.Intent;
-import android.database.Cursor;
-import android.graphics.drawable.Drawable;
-import android.media.AudioManager;
-import android.net.Uri;
-import android.provider.VoicemailContract;
-import android.provider.VoicemailContract.Voicemails;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.v4.util.Pair;
-import android.text.TextUtils;
-import android.util.AttributeSet;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.ImageButton;
-import android.widget.LinearLayout;
-import android.widget.SeekBar;
-import android.widget.SeekBar.OnSeekBarChangeListener;
-import android.widget.TextView;
-import com.android.dialer.callintent.CallInitiationType.Type;
-import com.android.dialer.callintent.CallIntentBuilder;
-import com.android.dialer.calllog.database.contract.AnnotatedCallLogContract.AnnotatedCallLog;
-import com.android.dialer.common.Assert;
-import com.android.dialer.common.LogUtil;
-import com.android.dialer.common.concurrent.DialerExecutor.SuccessListener;
-import com.android.dialer.common.concurrent.DialerExecutor.Worker;
-import com.android.dialer.common.concurrent.DialerExecutorComponent;
-import com.android.dialer.precall.PreCall;
-import com.android.dialer.telecom.TelecomUtil;
-import com.android.dialer.voicemail.listui.NewVoicemailViewHolder.NewVoicemailViewHolderListener;
-import com.android.dialer.voicemail.model.VoicemailEntry;
-import java.util.Locale;
-
-/**
- * The view of the media player that is visible when a {@link NewVoicemailViewHolder} is expanded.
- */
-public final class NewVoicemailMediaPlayerView extends LinearLayout {
-
- private ImageButton playButton;
- private ImageButton pauseButton;
- private ImageButton speakerButton;
- private ImageButton phoneButton;
- private ImageButton deleteButton;
- private TextView currentSeekBarPosition;
- private SeekBar seekBarView;
- private Drawable voicemailSeekHandleDisabled;
-
- private TextView totalDurationView;
- private TextView voicemailLoadingStatusView;
- private Uri voicemailUri;
- private String numberVoicemailFrom;
- private String phoneAccountId;
- private String phoneAccountComponentName;
- private FragmentManager fragmentManager;
- private NewVoicemailViewHolder newVoicemailViewHolder;
- private NewVoicemailMediaPlayer mediaPlayer;
- private NewVoicemailViewHolderListener newVoicemailViewHolderListener;
-
- public NewVoicemailMediaPlayerView(Context context, AttributeSet attrs) {
- super(context, attrs);
- LogUtil.enterBlock("NewVoicemailMediaPlayer");
- LayoutInflater inflater =
- (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- inflater.inflate(R.layout.new_voicemail_media_player_layout, this);
- }
-
- @Override
- protected void onFinishInflate() {
- super.onFinishInflate();
- LogUtil.enterBlock("NewVoicemailMediaPlayer.onFinishInflate");
- initializeMediaPlayerButtonsAndViews();
- setupListenersForMediaPlayerButtons();
- }
-
- private void initializeMediaPlayerButtonsAndViews() {
- playButton = findViewById(R.id.playButton);
- pauseButton = findViewById(R.id.pauseButton);
- currentSeekBarPosition = findViewById(R.id.playback_position_text);
- seekBarView = findViewById(R.id.playback_seek);
- speakerButton = findViewById(R.id.speakerButton);
- phoneButton = findViewById(R.id.phoneButton);
- deleteButton = findViewById(R.id.deleteButton);
- totalDurationView = findViewById(R.id.playback_seek_total_duration);
- voicemailLoadingStatusView = findViewById(R.id.playback_state_text);
-
- voicemailSeekHandleDisabled =
- getContext()
- .getResources()
- .getDrawable(R.drawable.ic_voicemail_seek_handle_disabled, getContext().getTheme());
- }
-
- private void setupListenersForMediaPlayerButtons() {
- playButton.setOnClickListener(playButtonListener);
- pauseButton.setOnClickListener(pauseButtonListener);
- seekBarView.setOnSeekBarChangeListener(seekbarChangeListener);
- speakerButton.setOnClickListener(speakerButtonListener);
- phoneButton.setOnClickListener(phoneButtonListener);
- deleteButton.setOnClickListener(deleteButtonListener);
- }
-
- public void reset() {
- LogUtil.i(
- "NewVoicemailMediaPlayer.reset",
- "the uri for this is " + voicemailUri + " and number is " + numberVoicemailFrom);
- voicemailUri = null;
- voicemailLoadingStatusView.setVisibility(GONE);
- numberVoicemailFrom = null;
- phoneAccountId = null;
- phoneAccountComponentName = null;
- }
-
- /**
- * Can be called either when binding happens on the {@link NewVoicemailViewHolder} from {@link
- * NewVoicemailAdapter} or when a user expands a {@link NewVoicemailViewHolder}. During the
- * binding, since {@link NewVoicemailMediaPlayerView} is part of {@link NewVoicemailViewHolder},
- * we have to ensure that during the binding the values from the {@link NewVoicemailAdapter} are
- * also propogated down to the {@link NewVoicemailMediaPlayerView} via {@link
- * NewVoicemailViewHolder}. In the case of when the {@link NewVoicemailViewHolder} is expanded,
- * the most recent value and states from the {@link NewVoicemailAdapter} are set for the expanded
- * {@link NewVoicemailMediaPlayerView}.
- *
- * @param viewHolder
- * @param voicemailEntryFromAdapter are the voicemail related values from the {@link
- * AnnotatedCallLog} converted into {@link VoicemailEntry} format.
- * @param fragmentManager
- * @param mp the media player passed down from the adapter
- * @param listener
- */
- void bindValuesFromAdapterOfExpandedViewHolderMediaPlayerView(
- NewVoicemailViewHolder viewHolder,
- @NonNull VoicemailEntry voicemailEntryFromAdapter,
- @NonNull FragmentManager fragmentManager,
- NewVoicemailMediaPlayer mp,
- NewVoicemailViewHolderListener listener) {
-
- Assert.isNotNull(voicemailEntryFromAdapter);
- Uri uri = Uri.parse(voicemailEntryFromAdapter.getVoicemailUri());
-
- numberVoicemailFrom = voicemailEntryFromAdapter.getNumber().getNormalizedNumber();
- phoneAccountId = voicemailEntryFromAdapter.getPhoneAccountId();
- phoneAccountComponentName = voicemailEntryFromAdapter.getPhoneAccountComponentName();
-
- Assert.isNotNull(viewHolder);
- Assert.isNotNull(uri);
- Assert.isNotNull(listener);
- Assert.isNotNull(totalDurationView);
- Assert.checkArgument(uri.equals(viewHolder.getViewHolderVoicemailUri()));
-
- LogUtil.i(
- "NewVoicemailMediaPlayerView.bindValuesFromAdapterOfExpandedViewHolderMediaPlayerView",
- "Updating the viewholder:%d mediaPlayerView with uri value:%s",
- viewHolder.getViewHolderId(),
- uri.toString());
-
- this.fragmentManager = fragmentManager;
-
- newVoicemailViewHolder = viewHolder;
- newVoicemailViewHolderListener = listener;
- mediaPlayer = mp;
- voicemailUri = uri;
- totalDurationView.setText(
- VoicemailEntryText.getVoicemailDuration(getContext(), voicemailEntryFromAdapter));
- // Not sure if these are needed, but it'll ensure that onInflate() has atleast happened.
- initializeMediaPlayerButtonsAndViews();
- setupListenersForMediaPlayerButtons();
-
- // TODO(uabdullah): Handle seekbar seeking properly (a bug)
- seekBarView.setEnabled(false);
- seekBarView.setThumb(voicemailSeekHandleDisabled);
-
- updatePhoneIcon(numberVoicemailFrom);
-
- // During the binding we only send a request to the adapter to tell us what the
- // state of the media player should be and call that function.
- // This could be the paused state, or the playing state of the resume state.
- // Our job here is only to send the request upto the adapter and have it decide what we should
- // do.
- LogUtil.i(
- "NewVoicemailMediaPlayerView.bindValuesFromAdapterOfExpandedViewHolderMediaPlayerView",
- "Updating media player values for id:" + viewHolder.getViewHolderId());
-
- // During the binding make sure that the first time we just set the mediaplayer view
- // This does not take care of the constant update
- if (mp.isPlaying() && mp.getLastPlayedOrPlayingVoicemailUri().equals(voicemailUri)) {
- Assert.checkArgument(
- mp.getLastPlayedOrPlayingVoicemailUri()
- .equals(mp.getLastPreparedOrPreparingToPlayVoicemailUri()));
- LogUtil.i(
- "NewVoicemailMediaPlayerView.bindValuesFromAdapterOfExpandedViewHolderMediaPlayerView",
- "show playing state");
- playButton.setVisibility(GONE);
- pauseButton.setVisibility(VISIBLE);
- currentSeekBarPosition.setText(formatAsMinutesAndSeconds(mp.getCurrentPosition()));
-
- if (seekBarView.getMax() != mp.getDuration()) {
- seekBarView.setMax(mp.getDuration());
- }
- seekBarView.setProgress(mp.getCurrentPosition());
-
- } else if (mediaPlayer.isPaused() && mp.getLastPausedVoicemailUri().equals(voicemailUri)) {
- LogUtil.i(
- "NewVoicemailMediaPlayerView.bindValuesFromAdapterOfExpandedViewHolderMediaPlayerView",
- "show paused state");
- Assert.checkArgument(viewHolder.getViewHolderVoicemailUri().equals(voicemailUri));
- playButton.setVisibility(VISIBLE);
- pauseButton.setVisibility(GONE);
- currentSeekBarPosition.setText(formatAsMinutesAndSeconds(mp.getCurrentPosition()));
- if (seekBarView.getMax() != mp.getDuration()) {
- seekBarView.setMax(mp.getDuration());
- }
- seekBarView.setProgress(mp.getCurrentPosition());
-
- } else {
- LogUtil.i(
- "NewVoicemailMediaPlayerView.bindValuesFromAdapterOfExpandedViewHolderMediaPlayerView",
- "show reset state");
- playButton.setVisibility(VISIBLE);
- pauseButton.setVisibility(GONE);
- seekBarView.setProgress(0);
- seekBarView.setMax(100);
- currentSeekBarPosition.setText(formatAsMinutesAndSeconds(0));
- }
- }
-
- /**
- * Updates the phone icon depending if we can dial it or not.
- *
- * <p>Note: This must be called after the onClickListeners have been set, otherwise isClickable()
- * state is not maintained.
- */
- private void updatePhoneIcon(@Nullable String numberVoicemailFrom) {
- // TODO(uabdullah): Handle restricted/blocked numbers (a bug)
- if (TextUtils.isEmpty(numberVoicemailFrom)) {
- phoneButton.setEnabled(false);
- phoneButton.setClickable(false);
- } else {
- phoneButton.setEnabled(true);
- phoneButton.setClickable(true);
- }
- }
-
- private final OnSeekBarChangeListener seekbarChangeListener =
- new OnSeekBarChangeListener() {
- @Override
- public void onProgressChanged(SeekBar seekBarfromProgress, int progress, boolean fromUser) {
- // TODO(uabdullah): Only for debugging purposes, to be removed.
- if (progress < 100) {
- LogUtil.i(
- "NewVoicemailMediaPlayer.seekbarChangeListener",
- "onProgressChanged, progress:%d, seekbarMax: %d, fromUser:%b",
- progress,
- seekBarfromProgress.getMax(),
- fromUser);
- }
-
- if (fromUser) {
- mediaPlayer.seekTo(progress);
- currentSeekBarPosition.setText(formatAsMinutesAndSeconds(progress));
- }
- }
-
- @Override
- // TODO(uabdullah): Handle this case
- public void onStartTrackingTouch(SeekBar seekBar) {
- LogUtil.i("NewVoicemailMediaPlayer.onStartTrackingTouch", "does nothing for now");
- }
-
- @Override
- // TODO(uabdullah): Handle this case
- public void onStopTrackingTouch(SeekBar seekBar) {
- LogUtil.i("NewVoicemailMediaPlayer.onStopTrackingTouch", "does nothing for now");
- }
- };
-
- private final View.OnClickListener pauseButtonListener =
- new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- LogUtil.i(
- "NewVoicemailMediaPlayer.pauseButtonListener",
- "pauseMediaPlayerAndSetPausedStateOfViewHolder button for voicemailUri: %s",
- voicemailUri.toString());
-
- Assert.checkArgument(playButton.getVisibility() == GONE);
- Assert.checkArgument(mediaPlayer != null);
- Assert.checkArgument(
- mediaPlayer.getLastPlayedOrPlayingVoicemailUri().equals((voicemailUri)),
- "the voicemail being played is the only voicemail that should"
- + " be paused. last played voicemail:%s, uri:%s",
- mediaPlayer.getLastPlayedOrPlayingVoicemailUri().toString(),
- voicemailUri.toString());
- Assert.checkArgument(
- newVoicemailViewHolder.getViewHolderVoicemailUri().equals(voicemailUri),
- "viewholder uri and mediaplayer view should be the same.");
- newVoicemailViewHolderListener.pauseViewHolder(newVoicemailViewHolder);
- }
- };
-
- /**
- * Attempts to imitate clicking the play button. This is useful for when we the user attempted to
- * play a voicemail, but the media player didn't start playing till the voicemail was downloaded
- * from the server. However once we have the voicemail downloaded, we want to start playing, so as
- * to make it seem like that this is a continuation of the users initial play button click.
- */
- public final void clickPlayButton() {
- playButtonListener.onClick(null);
- }
-
- private final View.OnClickListener playButtonListener =
- new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- LogUtil.i(
- "NewVoicemailMediaPlayer.playButtonListener",
- "play button for voicemailUri: %s",
- String.valueOf(voicemailUri));
-
- if (mediaPlayer.getLastPausedVoicemailUri() != null
- && mediaPlayer
- .getLastPausedVoicemailUri()
- .toString()
- .contentEquals(voicemailUri.toString())) {
- LogUtil.i(
- "NewVoicemailMediaPlayer.playButtonListener",
- "resume playing voicemailUri: %s",
- voicemailUri.toString());
-
- newVoicemailViewHolderListener.resumePausedViewHolder(newVoicemailViewHolder);
-
- } else {
- playVoicemailWhenAvailableLocally();
- }
- }
- };
-
- /**
- * Plays the voicemail when we are able to play the voicemail locally from the device. This
- * involves checking if the voicemail is available to play locally, if it is, then we setup the
- * Media Player to play the voicemail. If the voicemail is not available, then we need download
- * the voicemail from the voicemail server to the device, and then have the Media player play it.
- */
- private void playVoicemailWhenAvailableLocally() {
- LogUtil.enterBlock("playVoicemailWhenAvailableLocally");
- Worker<Pair<Context, Uri>, Pair<Boolean, Uri>> checkVoicemailHasContent =
- this::queryVoicemailHasContent;
- SuccessListener<Pair<Boolean, Uri>> checkVoicemailHasContentCallBack = this::prepareMediaPlayer;
-
- DialerExecutorComponent.get(getContext())
- .dialerExecutorFactory()
- .createUiTaskBuilder(fragmentManager, "lookup_voicemail_content", checkVoicemailHasContent)
- .onSuccess(checkVoicemailHasContentCallBack)
- .build()
- .executeSerial(new Pair<>(getContext(), voicemailUri));
- }
-
- private Pair<Boolean, Uri> queryVoicemailHasContent(Pair<Context, Uri> contextUriPair) {
- Context context = contextUriPair.first;
- Uri uri = contextUriPair.second;
-
- try (Cursor cursor = context.getContentResolver().query(uri, null, null, null, null)) {
- if (cursor != null && cursor.moveToFirst()) {
- return new Pair<>(
- cursor.getInt(cursor.getColumnIndex(VoicemailContract.Voicemails.HAS_CONTENT)) == 1,
- uri);
- }
- return new Pair<>(false, uri);
- }
- }
-
- /**
- * If the voicemail is available to play locally, setup the media player to play it. Otherwise
- * send a request to download the voicemail and then play it.
- */
- private void prepareMediaPlayer(Pair<Boolean, Uri> booleanUriPair) {
- boolean voicemailAvailableLocally = booleanUriPair.first;
- Uri uri = booleanUriPair.second;
- LogUtil.i(
- "NewVoicemailMediaPlayer.prepareMediaPlayer",
- "voicemail available locally: %b for voicemailUri: %s",
- voicemailAvailableLocally,
- uri.toString());
-
- if (voicemailAvailableLocally) {
- try {
- Assert.checkArgument(mediaPlayer != null, "media player should not have been null");
- mediaPlayer.prepareMediaPlayerAndPlayVoicemailWhenReady(getContext(), uri);
- } catch (Exception e) {
- LogUtil.e(
- "NewVoicemailMediaPlayer.prepareMediaPlayer",
- "Exception when mediaPlayer.prepareMediaPlayerAndPlayVoicemailWhenReady"
- + "(getContext(), uri)\n"
- + e
- + "\n uri:"
- + uri
- + "context should not be null, its value is :"
- + getContext());
- }
- } else {
- LogUtil.i(
- "NewVoicemailMediaPlayer.prepareVoicemailForMediaPlayer", "need to download content");
- // Important to set since it allows the adapter to differentiate when to start playing the
- // voicemail, after it's downloaded.
- mediaPlayer.setVoicemailRequestedToDownload(uri);
- voicemailLoadingStatusView.setVisibility(VISIBLE);
- sendIntentToDownloadVoicemail(uri);
- }
- }
-
- private void sendIntentToDownloadVoicemail(Uri uri) {
- LogUtil.i("NewVoicemailMediaPlayer.sendIntentToDownloadVoicemail", "uri:%s", uri.toString());
-
- Worker<Pair<Context, Uri>, Pair<String, Uri>> getVoicemailSourcePackage =
- this::queryVoicemailSourcePackage;
- SuccessListener<Pair<String, Uri>> checkVoicemailHasSourcePackageCallBack = this::sendIntent;
-
- DialerExecutorComponent.get(getContext())
- .dialerExecutorFactory()
- .createUiTaskBuilder(fragmentManager, "lookup_voicemail_pkg", getVoicemailSourcePackage)
- .onSuccess(checkVoicemailHasSourcePackageCallBack)
- .build()
- .executeSerial(new Pair<>(getContext(), voicemailUri));
- }
-
- private void sendIntent(Pair<String, Uri> booleanUriPair) {
- String sourcePackage = booleanUriPair.first;
- Uri uri = booleanUriPair.second;
- LogUtil.i(
- "NewVoicemailMediaPlayer.sendIntent",
- "srcPkg:%s, uri:%s",
- sourcePackage,
- String.valueOf(uri));
- Intent intent = new Intent(VoicemailContract.ACTION_FETCH_VOICEMAIL, uri);
- intent.setPackage(sourcePackage);
- voicemailLoadingStatusView.setVisibility(VISIBLE);
- getContext().sendBroadcast(intent);
- }
-
- @Nullable
- private Pair<String, Uri> queryVoicemailSourcePackage(Pair<Context, Uri> contextUriPair) {
- LogUtil.enterBlock("NewVoicemailMediaPlayer.queryVoicemailSourcePackage");
- Context context = contextUriPair.first;
- Uri uri = contextUriPair.second;
- String sourcePackage;
- try (Cursor cursor =
- context
- .getContentResolver()
- .query(uri, new String[] {Voicemails.SOURCE_PACKAGE}, null, null, null)) {
-
- if (!hasContent(cursor)) {
- LogUtil.e(
- "NewVoicemailMediaPlayer.queryVoicemailSourcePackage",
- "uri: %s does not return a SOURCE_PACKAGE",
- uri.toString());
- sourcePackage = null;
- } else {
- sourcePackage = cursor.getString(0);
- LogUtil.i(
- "NewVoicemailMediaPlayer.queryVoicemailSourcePackage",
- "uri: %s has a SOURCE_PACKAGE: %s",
- uri.toString(),
- sourcePackage);
- }
- LogUtil.i(
- "NewVoicemailMediaPlayer.queryVoicemailSourcePackage",
- "uri: %s has a SOURCE_PACKAGE: %s",
- uri.toString(),
- sourcePackage);
- }
- return new Pair<>(sourcePackage, uri);
- }
-
- private boolean hasContent(Cursor cursor) {
- return cursor != null && cursor.moveToFirst();
- }
-
- private final View.OnClickListener speakerButtonListener =
- new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- LogUtil.i(
- "NewVoicemailMediaPlayer.speakerButtonListener",
- "speaker request for voicemailUri: %s",
- voicemailUri.toString());
- AudioManager audioManager =
- (AudioManager) getContext().getSystemService(AudioManager.class);
- audioManager.setMode(AudioManager.STREAM_MUSIC);
- if (audioManager.isSpeakerphoneOn()) {
- LogUtil.i(
- "NewVoicemailMediaPlayer.speakerButtonListener", "speaker was on, turning it off");
- audioManager.setSpeakerphoneOn(false);
- } else {
- LogUtil.i(
- "NewVoicemailMediaPlayer.speakerButtonListener", "speaker was off, turning it on");
- audioManager.setSpeakerphoneOn(true);
- }
- // TODO(uabdullah): Handle colors of speaker icon when speaker is on and off.
- }
- };
-
- private final View.OnClickListener phoneButtonListener =
- new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- LogUtil.i(
- "NewVoicemailMediaPlayer.phoneButtonListener",
- "phone request for voicemailUri: %s with number:%s",
- voicemailUri.toString(),
- numberVoicemailFrom);
-
- Assert.checkArgument(
- !TextUtils.isEmpty(numberVoicemailFrom),
- "number cannot be empty:" + numberVoicemailFrom);
- PreCall.start(
- getContext(),
- new CallIntentBuilder(numberVoicemailFrom, Type.VOICEMAIL_LOG)
- .setPhoneAccountHandle(
- TelecomUtil.composePhoneAccountHandle(
- phoneAccountComponentName, phoneAccountId)));
- }
- };
-
- private final View.OnClickListener deleteButtonListener =
- new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- LogUtil.i(
- "NewVoicemailMediaPlayer.deleteButtonListener",
- "delete voicemailUri %s",
- String.valueOf(voicemailUri));
- newVoicemailViewHolderListener.deleteViewHolder(
- getContext(), fragmentManager, newVoicemailViewHolder, voicemailUri);
- }
- };
-
- /**
- * This is only called to update the media player view of the seekbar, and the duration and the
- * play button. For constant updates the adapter should seek track. This is the state when a
- * voicemail is playing.
- */
- public void updateSeekBarDurationAndShowPlayButton(NewVoicemailMediaPlayer mp) {
- if (!mp.isPlaying()) {
- return;
- }
-
- playButton.setVisibility(GONE);
- pauseButton.setVisibility(VISIBLE);
- voicemailLoadingStatusView.setVisibility(GONE);
-
- Assert.checkArgument(
- mp.equals(mediaPlayer), "there should only be one instance of a media player");
- Assert.checkArgument(
- mediaPlayer.getLastPreparedOrPreparingToPlayVoicemailUri().equals(voicemailUri));
- Assert.checkArgument(mediaPlayer.getLastPlayedOrPlayingVoicemailUri().equals(voicemailUri));
- Assert.isNotNull(mediaPlayer, "media player should have been set on bind");
- Assert.checkArgument(mediaPlayer.isPlaying());
- Assert.checkArgument(mediaPlayer.getCurrentPosition() >= 0);
- Assert.checkArgument(mediaPlayer.getDuration() >= 0);
- Assert.checkArgument(playButton.getVisibility() == GONE);
- Assert.checkArgument(pauseButton.getVisibility() == VISIBLE);
- Assert.checkArgument(seekBarView.getVisibility() == VISIBLE);
- Assert.checkArgument(currentSeekBarPosition.getVisibility() == VISIBLE);
-
- currentSeekBarPosition.setText(formatAsMinutesAndSeconds(mediaPlayer.getCurrentPosition()));
- if (seekBarView.getMax() != mediaPlayer.getDuration()) {
- seekBarView.setMax(mediaPlayer.getDuration());
- }
- seekBarView.setProgress(mediaPlayer.getCurrentPosition());
- }
-
- /**
- * What the default state of an expanded media player view should look like.
- *
- * @param currentlyExpandedViewHolderOnScreen
- * @param mediaPlayer
- */
- public void setToResetState(
- NewVoicemailViewHolder currentlyExpandedViewHolderOnScreen,
- NewVoicemailMediaPlayer mediaPlayer) {
- LogUtil.i(
- "NewVoicemailMediaPlayer.setToResetState",
- "update the seekbar for viewholder id:%d, mediaplayer view uri:%s, play button "
- + "visible:%b, pause button visible:%b",
- currentlyExpandedViewHolderOnScreen.getViewHolderId(),
- String.valueOf(voicemailUri),
- playButton.getVisibility() == VISIBLE,
- pauseButton.getVisibility() == VISIBLE);
-
- if (playButton.getVisibility() == GONE) {
- playButton.setVisibility(VISIBLE);
- pauseButton.setVisibility(GONE);
- }
-
- Assert.checkArgument(playButton.getVisibility() == VISIBLE);
- Assert.checkArgument(pauseButton.getVisibility() == GONE);
-
- Assert.checkArgument(
- !mediaPlayer.isPlaying(),
- "when resetting an expanded " + "state, there should be no voicemail playing");
-
- Assert.checkArgument(
- mediaPlayer.getLastPlayedOrPlayingVoicemailUri().equals(Uri.EMPTY),
- "reset should have been called before updating its media player view");
- currentSeekBarPosition.setText(formatAsMinutesAndSeconds(0));
- seekBarView.setProgress(0);
- seekBarView.setMax(100);
- }
-
- public void setToPausedState(Uri toPausedState, NewVoicemailMediaPlayer mp) {
- LogUtil.i(
- "NewVoicemailMediaPlayer.setToPausedState",
- "toPausedState uri:%s, play button visible:%b, pause button visible:%b",
- toPausedState == null ? "null" : voicemailUri.toString(),
- playButton.getVisibility() == VISIBLE,
- pauseButton.getVisibility() == VISIBLE);
-
- playButton.setVisibility(VISIBLE);
- pauseButton.setVisibility(GONE);
-
- currentSeekBarPosition.setText(formatAsMinutesAndSeconds(mediaPlayer.getCurrentPosition()));
- if (seekBarView.getMax() != mediaPlayer.getDuration()) {
- seekBarView.setMax(mediaPlayer.getDuration());
- }
- seekBarView.setProgress(mediaPlayer.getCurrentPosition());
-
- Assert.checkArgument(voicemailUri.equals(toPausedState));
- Assert.checkArgument(!mp.isPlaying());
- Assert.checkArgument(
- mp.equals(mediaPlayer), "there should only be one instance of a media player");
- Assert.checkArgument(
- this.mediaPlayer.getLastPreparedOrPreparingToPlayVoicemailUri().equals(voicemailUri));
- Assert.checkArgument(
- this.mediaPlayer.getLastPlayedOrPlayingVoicemailUri().equals(voicemailUri));
- Assert.checkArgument(this.mediaPlayer.getLastPausedVoicemailUri().equals(voicemailUri));
- Assert.isNotNull(this.mediaPlayer, "media player should have been set on bind");
- Assert.checkArgument(this.mediaPlayer.getCurrentPosition() >= 0);
- Assert.checkArgument(this.mediaPlayer.getDuration() >= 0);
- Assert.checkArgument(playButton.getVisibility() == VISIBLE);
- Assert.checkArgument(pauseButton.getVisibility() == GONE);
- Assert.checkArgument(seekBarView.getVisibility() == VISIBLE);
- Assert.checkArgument(currentSeekBarPosition.getVisibility() == VISIBLE);
- }
-
- @NonNull
- public Uri getVoicemailUri() {
- return voicemailUri;
- }
-
- private String formatAsMinutesAndSeconds(int millis) {
- int seconds = millis / 1000;
- int minutes = seconds / 60;
- seconds -= minutes * 60;
- if (minutes > 99) {
- minutes = 99;
- }
- return String.format(Locale.US, "%02d:%02d", minutes, seconds);
- }
-}
diff --git a/java/com/android/dialer/voicemail/listui/NewVoicemailViewHolder.java b/java/com/android/dialer/voicemail/listui/NewVoicemailViewHolder.java
deleted file mode 100644
index ba851eb..0000000
--- a/java/com/android/dialer/voicemail/listui/NewVoicemailViewHolder.java
+++ /dev/null
@@ -1,481 +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.voicemail.listui;
-
-import static android.view.View.GONE;
-import static android.view.View.VISIBLE;
-
-import android.app.FragmentManager;
-import android.content.ContentValues;
-import android.content.Context;
-import android.content.Intent;
-import android.database.Cursor;
-import android.graphics.Typeface;
-import android.net.Uri;
-import android.provider.VoicemailContract.Voicemails;
-import android.support.annotation.NonNull;
-import android.support.annotation.WorkerThread;
-import android.support.v7.widget.RecyclerView;
-import android.text.TextUtils;
-import android.util.Pair;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.widget.ImageView;
-import android.widget.TextView;
-import com.android.dialer.calllog.database.contract.AnnotatedCallLogContract.AnnotatedCallLog;
-import com.android.dialer.calllogutils.PhotoInfoBuilder;
-import com.android.dialer.common.Assert;
-import com.android.dialer.common.LogUtil;
-import com.android.dialer.common.concurrent.DialerExecutor.SuccessListener;
-import com.android.dialer.common.concurrent.DialerExecutor.Worker;
-import com.android.dialer.common.concurrent.DialerExecutorComponent;
-import com.android.dialer.compat.android.provider.VoicemailCompat;
-import com.android.dialer.time.Clock;
-import com.android.dialer.voicemail.listui.menu.NewVoicemailMenu;
-import com.android.dialer.voicemail.model.VoicemailEntry;
-import com.android.dialer.widget.ContactPhotoView;
-import com.android.voicemail.VoicemailClient;
-
-/** {@link RecyclerView.ViewHolder} for the new voicemail tab. */
-final class NewVoicemailViewHolder extends RecyclerView.ViewHolder implements OnClickListener {
-
- private final Context context;
- private final TextView primaryTextView;
- private final TextView secondaryTextView;
- private final TextView transcriptionTextView;
- private final TextView transcriptionBrandingTextView;
- private final ContactPhotoView contactPhotoView;
- private final NewVoicemailMediaPlayerView mediaPlayerView;
- private final ImageView menuButton;
- private final Clock clock;
- private boolean isViewHolderExpanded;
- private long viewHolderId;
- private VoicemailEntry voicemailEntryOfViewHolder;
- @NonNull private Uri viewHolderVoicemailUri;
- private final NewVoicemailViewHolderListener voicemailViewHolderListener;
-
- NewVoicemailViewHolder(
- View view, Clock clock, NewVoicemailViewHolderListener newVoicemailViewHolderListener) {
- super(view);
- LogUtil.enterBlock("NewVoicemailViewHolder");
- this.context = view.getContext();
- primaryTextView = view.findViewById(R.id.primary_text);
- secondaryTextView = view.findViewById(R.id.secondary_text);
- transcriptionTextView = view.findViewById(R.id.transcription_text);
- transcriptionBrandingTextView = view.findViewById(R.id.transcription_branding);
- contactPhotoView = view.findViewById(R.id.contact_photo_view);
- mediaPlayerView = view.findViewById(R.id.new_voicemail_media_player);
- menuButton = view.findViewById(R.id.menu_button);
- this.clock = clock;
- voicemailViewHolderListener = newVoicemailViewHolderListener;
-
- viewHolderId = -1;
- isViewHolderExpanded = false;
- viewHolderVoicemailUri = null;
- }
-
- public NewVoicemailMediaPlayerView getMediaPlayerView() {
- return Assert.isNotNull(mediaPlayerView);
- }
-
- /**
- * When the {@link RecyclerView} displays voicemail entries, it might recycle the views upon
- * scrolling. In that case we need to ensure that the member variables of this {@link
- * NewVoicemailViewHolder} and its views are correctly set, especially when this {@link
- * NewVoicemailViewHolder} is recycled.
- *
- * @param cursor the voicemail data from {@link AnnotatedCallLog} generated by the {@link
- * VoicemailCursorLoader} related
- * @param fragmentManager FragmentManager retrieved from {@link
- * NewVoicemailFragment#getActivity()}
- * @param mediaPlayer
- * @param position the position of the item within the adapter's data set.
- * @param currentlyExpandedViewHolderId the value the adapter keeps track of which viewholder if
- */
- void bindViewHolderValuesFromAdapter(
- Cursor cursor,
- FragmentManager fragmentManager,
- NewVoicemailMediaPlayer mediaPlayer,
- int position,
- long currentlyExpandedViewHolderId) {
-
- LogUtil.i(
- "NewVoicemailViewHolder.bindViewHolderValuesFromAdapter",
- "view holder at pos:%d, adapterPos:%d, cursorPos:%d, cursorSize:%d",
- position,
- getAdapterPosition(),
- cursor.getPosition(),
- cursor.getCount());
-
- voicemailEntryOfViewHolder = VoicemailCursorLoader.toVoicemailEntry(cursor);
- viewHolderId = voicemailEntryOfViewHolder.getId();
- LogUtil.i(
- "NewVoicemailViewHolder.bindViewHolderValuesFromAdapter", "viewholderId:%d", viewHolderId);
- viewHolderVoicemailUri = Uri.parse(voicemailEntryOfViewHolder.getVoicemailUri());
- primaryTextView.setText(
- VoicemailEntryText.buildPrimaryVoicemailText(context, voicemailEntryOfViewHolder));
- secondaryTextView.setText(
- VoicemailEntryText.buildSecondaryVoicemailText(context, clock, voicemailEntryOfViewHolder));
-
- String voicemailTranscription = voicemailEntryOfViewHolder.getTranscription();
-
- if (TextUtils.isEmpty(voicemailTranscription)) {
- transcriptionTextView.setVisibility(GONE);
- transcriptionTextView.setText(null);
- } else {
- transcriptionTextView.setVisibility(View.VISIBLE);
- transcriptionTextView.setText(voicemailTranscription);
- }
-
- // Bold if voicemail is unread
- boldViewHolderIfUnread();
-
- itemView.setOnClickListener(this);
- menuButton.setOnClickListener(
- NewVoicemailMenu.createOnClickListener(context, voicemailEntryOfViewHolder));
-
- contactPhotoView.setPhoto(
- PhotoInfoBuilder.fromVoicemailEntry(voicemailEntryOfViewHolder).build());
-
- // Update the expanded/collapsed state of this view holder
- // Only update the binding of the mediaPlayerView of the expanded view holder
- if (viewHolderId == currentlyExpandedViewHolderId) {
- LogUtil.i(
- "NewVoicemailViewHolder.bindViewHolderValuesFromAdapter",
- "viewHolderId:%d is expanded, update its mediaplayer view",
- viewHolderId);
- expandAndBindViewHolderAndMediaPlayerViewWithAdapterValues(
- voicemailEntryOfViewHolder, fragmentManager, mediaPlayer, voicemailViewHolderListener);
- LogUtil.i(
- "NewVoicemailViewHolder.bindViewHolderValuesFromAdapter",
- "After 2nd updating the MPPlayerView: viewHolderId:%d, uri:%s, MediaplayerView(after "
- + "updated):%s, adapter position passed down:%d, getAdapterPos:%d",
- viewHolderId,
- String.valueOf(viewHolderVoicemailUri),
- String.valueOf(mediaPlayerView.getVoicemailUri()),
- position,
- getAdapterPosition());
- Assert.checkArgument(
- mediaPlayerView.getVisibility() == VISIBLE,
- "a expanded viewholder should have its media player view visible");
- } else {
- LogUtil.i(
- "NewVoicemailViewHolder.bindViewHolderValuesFromAdapter",
- "viewHolderId:%d is not the expanded one, collapse it and don't update the MpView",
- viewHolderId);
- collapseViewHolder();
- Assert.checkArgument(
- mediaPlayerView.getVisibility() == GONE,
- "a collapsed viewholder should not have its media player view visible");
- }
- LogUtil.i(
- "NewVoicemailViewHolder.bindViewHolderValuesFromAdapter",
- "Final value after updating: viewHolderId:%d, uri:%s, MediaplayerView(not updated):%s,"
- + " adapter position passed down:%d, getAdapterPos:%d, MPPlayerVisibility:%b",
- viewHolderId,
- String.valueOf(viewHolderVoicemailUri),
- String.valueOf(mediaPlayerView.getVoicemailUri()),
- position,
- getAdapterPosition(),
- mediaPlayerView.getVisibility() == VISIBLE);
- }
-
- private void boldViewHolderIfUnread() {
- LogUtil.v(
- "NewVoicemailViewHolder.boldViewHolderIfUnread",
- "id:%d, isRead:%d",
- voicemailEntryOfViewHolder.getId(),
- voicemailEntryOfViewHolder.getIsRead());
-
- if (voicemailEntryOfViewHolder.getIsRead() == 0) {
- primaryTextView.setTypeface(Typeface.DEFAULT, Typeface.BOLD);
- secondaryTextView.setTypeface(Typeface.DEFAULT, Typeface.BOLD);
- transcriptionTextView.setTypeface(Typeface.DEFAULT, Typeface.BOLD);
- }
- }
-
- void collapseViewHolder() {
- LogUtil.i(
- "NewVoicemailViewHolder.collapseViewHolder",
- "viewHolderId:%d is being collapsed, its MPViewUri:%s, its Uri is :%s",
- viewHolderId,
- String.valueOf(mediaPlayerView.getVoicemailUri()),
- String.valueOf(viewHolderVoicemailUri));
- transcriptionTextView.setMaxLines(1);
- transcriptionBrandingTextView.setVisibility(GONE);
- isViewHolderExpanded = false;
-
- mediaPlayerView.reset();
- mediaPlayerView.setVisibility(GONE);
- }
-
- // When we are recycling the views ensure that we reset the viewHolder, as if its brand new
- public void reset() {
- LogUtil.i(
- "NewVoicemailViewHolder.reset()",
- "Reset the viewholder, currently viewHolderId:%d, uri:%s, isViewHolderExpanded:%b, "
- + "its MediaPlayerViewUri:%s",
- viewHolderId,
- String.valueOf(viewHolderVoicemailUri),
- isViewHolderExpanded,
- String.valueOf(mediaPlayerView.getVoicemailUri()));
-
- viewHolderId = -1;
- isViewHolderExpanded = false;
- viewHolderVoicemailUri = null;
-
- primaryTextView.setTypeface(null, Typeface.NORMAL);
- secondaryTextView.setTypeface(null, Typeface.NORMAL);
- transcriptionTextView.setTypeface(null, Typeface.NORMAL);
-
- transcriptionBrandingTextView.setVisibility(GONE);
-
- mediaPlayerView.reset();
-
- LogUtil.i(
- "NewVoicemailViewHolder.reset()",
- "Reset the viewholder, after resetting viewHolderId:%d, uri:%s, isViewHolderExpanded:%b",
- viewHolderId,
- String.valueOf(viewHolderVoicemailUri),
- isViewHolderExpanded);
- }
-
- /**
- * Is only called when a user either clicks a {@link NewVoicemailViewHolder} to expand it or if
- * the user had already expanded, then scrolled the {@link NewVoicemailViewHolder} out of view and
- * then scrolled it back into view, and during the binding (as the views are recyled in {@link
- * RecyclerView}) we restore the expanded state of the {@link NewVoicemailViewHolder}.
- *
- * <p>This function also tracks if the state of this viewholder is expanded.
- *
- * @param voicemailEntry are the voicemail related values from the {@link AnnotatedCallLog}
- * @param fragmentManager FragmentManager retrieved from {@link
- * NewVoicemailFragment#getActivity()}
- * @param mediaPlayer there should only be one instance of this passed down from the {@link
- * NewVoicemailAdapter}
- * @param voicemailViewHolderListener
- */
- void expandAndBindViewHolderAndMediaPlayerViewWithAdapterValues(
- VoicemailEntry voicemailEntry,
- FragmentManager fragmentManager,
- NewVoicemailMediaPlayer mediaPlayer,
- NewVoicemailViewHolderListener voicemailViewHolderListener) {
-
- Assert.isNotNull(voicemailViewHolderListener);
- Assert.checkArgument(
- voicemailEntry.getId() == viewHolderId, "ensure that the adapter binding has taken place");
- Assert.checkArgument(
- Uri.parse(voicemailEntry.getVoicemailUri()).equals(viewHolderVoicemailUri),
- "ensure that the adapter binding has taken place");
- LogUtil.i(
- "NewVoicemailViewHolder.expandAndBindViewHolderAndMediaPlayerViewWithAdapterValues",
- "voicemail id: %d, value of isViewHolderExpanded:%b, before setting it to be true, and"
- + " value of ViewholderUri:%s, MPView:%s, VoicemailRead:%d, before updating it",
- viewHolderId,
- isViewHolderExpanded,
- String.valueOf(viewHolderVoicemailUri),
- String.valueOf(mediaPlayerView.getVoicemailUri()),
- voicemailEntry.getIsRead());
-
- if (voicemailEntry.getIsRead() == 0) {
- // update as read.
- primaryTextView.setTypeface(Typeface.DEFAULT, Typeface.NORMAL);
- secondaryTextView.setTypeface(Typeface.DEFAULT, Typeface.NORMAL);
- transcriptionTextView.setTypeface(Typeface.DEFAULT, Typeface.NORMAL);
-
- Uri uri = Uri.parse(voicemailEntry.getVoicemailUri());
-
- Worker<Pair<Context, Uri>, Integer> markVoicemailRead = this::markVoicemailAsRead;
- SuccessListener<Integer> markedAsReadVoicemailCallBack = this::onVoicemailMarkedAsRead;
-
- DialerExecutorComponent.get(context)
- .dialerExecutorFactory()
- .createUiTaskBuilder(fragmentManager, "mark_voicemail_read", markVoicemailRead)
- .onSuccess(markedAsReadVoicemailCallBack)
- .build()
- .executeSerial(new Pair<>(context, uri));
- }
-
- transcriptionTextView.setMaxLines(999);
- isViewHolderExpanded = true;
- updateBrandingText(voicemailEntry);
- // Once the media player is visible update its state
- mediaPlayerView.setVisibility(View.VISIBLE);
- mediaPlayerView.bindValuesFromAdapterOfExpandedViewHolderMediaPlayerView(
- this, voicemailEntry, fragmentManager, mediaPlayer, voicemailViewHolderListener);
- LogUtil.i(
- "NewVoicemailViewHolder.expandAndBindViewHolderAndMediaPlayerViewWithAdapterValues",
- "voicemail id: %d, value of isViewHolderExpanded:%b, after setting it to be true, and"
- + " value of ViewholderUri:%s, MPView:%s, after updating it",
- viewHolderId,
- isViewHolderExpanded,
- String.valueOf(viewHolderVoicemailUri),
- String.valueOf(mediaPlayerView.getVoicemailUri()));
- }
-
- private void updateBrandingText(VoicemailEntry voicemailEntry) {
- if (voicemailEntry.getTranscriptionState() == VoicemailCompat.TRANSCRIPTION_AVAILABLE
- && !TextUtils.isEmpty(voicemailEntry.getTranscription())) {
- transcriptionBrandingTextView.setVisibility(VISIBLE);
- } else {
- transcriptionBrandingTextView.setVisibility(GONE);
- }
- }
-
- @WorkerThread
- private Integer markVoicemailAsRead(Pair<Context, Uri> contextUriPair) {
- Assert.isWorkerThread();
- LogUtil.enterBlock("NewVoicemailAdapter.markVoicemailAsRead");
- Context context = contextUriPair.first;
- Uri uri = contextUriPair.second;
-
- ContentValues values = new ContentValues();
- values.put(Voicemails.IS_READ, true);
- values.put(Voicemails.DIRTY, 1);
-
- LogUtil.i(
- "NewVoicemailAdapter.markVoicemailAsRead", "marking as read uri:%s", String.valueOf(uri));
- return context.getContentResolver().update(uri, values, null, null);
- }
-
- private void onVoicemailMarkedAsRead(Integer integer) {
- LogUtil.i("NewVoicemailAdapter.markVoicemailAsRead", "return value:%d", integer);
- Assert.checkArgument(integer > 0, "marking voicemail read was not successful");
-
- Intent intent = new Intent(VoicemailClient.ACTION_UPLOAD);
- intent.setPackage(context.getPackageName());
- context.sendBroadcast(intent);
- }
-
- /**
- * Called when we want to update the voicemail that is currently playing Updates the Seekbar,
- * duration timer and the play/pause button visibility when the expanded voicemail is being
- * played.
- */
- public void updateMediaPlayerViewWithPlayingState(
- NewVoicemailViewHolder newVoicemailViewHolder, NewVoicemailMediaPlayer mp) {
-
- LogUtil.i(
- "NewVoicemailViewHolder.updateMediaPlayerViewWithPlayingState",
- "viewholderUri:%s, mediaPlayerViewUri:%s, MPPosition:%d, MpDuration:%d, MpIsPlaying:%b",
- newVoicemailViewHolder.getViewHolderVoicemailUri().toString(),
- mediaPlayerView.getVoicemailUri().toString(),
- mp.getCurrentPosition(),
- mp.getDuration(),
- mp.isPlaying());
-
- Assert.checkArgument(
- mp.isPlaying(),
- "this method is only called when we are certain that the media player is playing");
-
- LogUtil.i(
- "NewVoicemailViewHolder.updateMediaPlayerViewWithPlayingState",
- "viewholderUri:%s, mediaPlayerViewUri:%s",
- newVoicemailViewHolder.getViewHolderVoicemailUri().toString(),
- mediaPlayerView.getVoicemailUri().toString());
- Assert.checkArgument(
- newVoicemailViewHolder
- .getViewHolderVoicemailUri()
- .equals(mediaPlayerView.getVoicemailUri()),
- "the mediaplayer view must be that of the viewholder we are updating");
- Assert.checkArgument(
- mp.getLastPlayedOrPlayingVoicemailUri()
- .equals(mp.getLastPreparedOrPreparingToPlayVoicemailUri()),
- "the media player view we are attempting to update should be of the "
- + "currently prepared and playing voicemail");
-
- mediaPlayerView.updateSeekBarDurationAndShowPlayButton(mp);
- }
-
- public void setMediaPlayerViewToResetState(
- NewVoicemailViewHolder currentlyExpandedViewHolderOnScreen,
- NewVoicemailMediaPlayer mediaPlayer) {
- Assert.isNotNull(currentlyExpandedViewHolderOnScreen);
- mediaPlayerView.setToResetState(currentlyExpandedViewHolderOnScreen, mediaPlayer);
- }
-
- public void setPausedStateOfMediaPlayerView(Uri uri, NewVoicemailMediaPlayer mediaPlayer) {
- Assert.checkArgument(viewHolderVoicemailUri.equals(uri));
- Assert.checkArgument(mediaPlayerView.getVoicemailUri().equals(uri));
- Assert.checkArgument(mediaPlayerView.getVoicemailUri().equals(viewHolderVoicemailUri));
- mediaPlayerView.setToPausedState(uri, mediaPlayer);
- }
-
- boolean isViewHolderExpanded() {
- return isViewHolderExpanded;
- }
-
- public long getViewHolderId() {
- return viewHolderId;
- }
-
- public Uri getViewHolderVoicemailUri() {
- return viewHolderVoicemailUri;
- }
-
- public void clickPlayButtonOfViewHoldersMediaPlayerView(
- NewVoicemailViewHolder expandedViewHolder) {
- LogUtil.i(
- "NewVoicemailViewHolder.clickPlayButtonOfViewHoldersMediaPlayerView",
- "expandedViewHolderID:%d",
- expandedViewHolder.getViewHolderId());
-
- Assert.checkArgument(
- mediaPlayerView.getVoicemailUri().equals(expandedViewHolder.getViewHolderVoicemailUri()));
- Assert.checkArgument(
- expandedViewHolder.getViewHolderVoicemailUri().equals(getViewHolderVoicemailUri()));
- Assert.checkArgument(
- mediaPlayerView.getVisibility() == View.VISIBLE,
- "the media player must be visible for viewholder id:%d, before we attempt to play");
- mediaPlayerView.clickPlayButton();
- }
-
- interface NewVoicemailViewHolderListener {
- void expandViewHolderFirstTimeAndCollapseAllOtherVisibleViewHolders(
- NewVoicemailViewHolder expandedViewHolder,
- VoicemailEntry voicemailEntryOfViewHolder,
- NewVoicemailViewHolderListener listener);
-
- void collapseExpandedViewHolder(NewVoicemailViewHolder expandedViewHolder);
-
- void pauseViewHolder(NewVoicemailViewHolder expandedViewHolder);
-
- void resumePausedViewHolder(NewVoicemailViewHolder expandedViewHolder);
-
- void deleteViewHolder(
- Context context,
- FragmentManager fragmentManager,
- NewVoicemailViewHolder expandedViewHolder,
- Uri uri);
- }
-
- @Override
- public void onClick(View v) {
- LogUtil.i(
- "NewVoicemailViewHolder.onClick",
- "voicemail id: %d, isViewHolderCurrentlyExpanded:%b",
- viewHolderId,
- isViewHolderExpanded);
- if (isViewHolderExpanded) {
- voicemailViewHolderListener.collapseExpandedViewHolder(this);
- } else {
- voicemailViewHolderListener.expandViewHolderFirstTimeAndCollapseAllOtherVisibleViewHolders(
- this,
- Assert.isNotNull(voicemailEntryOfViewHolder),
- Assert.isNotNull(voicemailViewHolderListener));
- }
- }
-}
diff --git a/java/com/android/dialer/voicemail/listui/VoicemailCursorLoader.java b/java/com/android/dialer/voicemail/listui/VoicemailCursorLoader.java
deleted file mode 100644
index f242484..0000000
--- a/java/com/android/dialer/voicemail/listui/VoicemailCursorLoader.java
+++ /dev/null
@@ -1,150 +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.voicemail.listui;
-
-import android.content.Context;
-import android.database.Cursor;
-import android.provider.CallLog.Calls;
-import android.support.v4.content.CursorLoader;
-import android.text.TextUtils;
-import com.android.dialer.DialerPhoneNumber;
-import com.android.dialer.NumberAttributes;
-import com.android.dialer.calllog.database.contract.AnnotatedCallLogContract.AnnotatedCallLog;
-import com.android.dialer.common.Assert;
-import com.android.dialer.common.LogUtil;
-import com.android.dialer.voicemail.model.VoicemailEntry;
-import com.google.protobuf.InvalidProtocolBufferException;
-
-/** CursorLoader for the annotated call log (voicemails only). */
-final class VoicemailCursorLoader extends CursorLoader {
-
- // When adding columns be sure to update {@link #VoicemailCursorLoader.toVoicemailEntry}.
- public static final String[] VOICEMAIL_COLUMNS =
- new String[] {
- AnnotatedCallLog._ID,
- AnnotatedCallLog.TIMESTAMP,
- AnnotatedCallLog.NUMBER,
- AnnotatedCallLog.FORMATTED_NUMBER,
- AnnotatedCallLog.DURATION,
- AnnotatedCallLog.GEOCODED_LOCATION,
- AnnotatedCallLog.CALL_TYPE,
- AnnotatedCallLog.TRANSCRIPTION,
- AnnotatedCallLog.VOICEMAIL_URI,
- AnnotatedCallLog.IS_READ,
- AnnotatedCallLog.NUMBER_ATTRIBUTES,
- AnnotatedCallLog.TRANSCRIPTION_STATE,
- AnnotatedCallLog.PHONE_ACCOUNT_COMPONENT_NAME,
- AnnotatedCallLog.PHONE_ACCOUNT_ID,
- };
-
- // Indexes for VOICEMAIL_COLUMNS
- private static final int ID = 0;
- private static final int TIMESTAMP = 1;
- private static final int NUMBER = 2;
- private static final int FORMATTED_NUMBER = 3;
- private static final int DURATION = 4;
- private static final int GEOCODED_LOCATION = 5;
- private static final int CALL_TYPE = 6;
- private static final int TRANSCRIPTION = 7;
- private static final int VOICEMAIL_URI = 8;
- private static final int IS_READ = 9;
- private static final int NUMBER_ATTRIBUTES = 10;
- private static final int TRANSCRIPTION_STATE = 11;
- private static final int PHONE_ACCOUNT_COMPONENT_NAME = 12;
- private static final int PHONE_ACCOUNT_ID = 13;
-
- // TODO(zachh): Optimize indexes
- VoicemailCursorLoader(Context context) {
- super(
- context,
- AnnotatedCallLog.CONTENT_URI,
- VOICEMAIL_COLUMNS,
- AnnotatedCallLog.CALL_TYPE + " = ?",
- new String[] {Integer.toString(Calls.VOICEMAIL_TYPE)},
- AnnotatedCallLog.TIMESTAMP + " DESC");
- }
-
- /** Creates a new {@link VoicemailEntry} from the provided cursor using the current position. */
- static VoicemailEntry toVoicemailEntry(Cursor cursor) {
- DialerPhoneNumber number;
- try {
- number = DialerPhoneNumber.parseFrom(cursor.getBlob(NUMBER));
- } catch (InvalidProtocolBufferException e) {
- throw new IllegalStateException("Couldn't parse DialerPhoneNumber bytes");
- }
- NumberAttributes numberAttributes;
- try {
- numberAttributes = NumberAttributes.parseFrom(cursor.getBlob(NUMBER_ATTRIBUTES));
- } catch (InvalidProtocolBufferException e) {
- throw new IllegalStateException("Couldn't parse NumberAttributes bytes");
- }
-
- // Voicemail numbers should always be valid so the CP2 information should never be incomplete,
- // and there should be no need to query PhoneLookup at render time.
- Assert.checkArgument(
- !numberAttributes.getIsCp2InfoIncomplete(),
- "CP2 info incomplete for number: %s",
- LogUtil.sanitizePii(number.getNormalizedNumber()));
-
- VoicemailEntry.Builder voicemailEntryBuilder =
- VoicemailEntry.newBuilder()
- .setId(cursor.getInt(ID))
- .setTimestamp(cursor.getLong(TIMESTAMP))
- .setNumber(number)
- .setDuration(cursor.getLong(DURATION))
- .setCallType(cursor.getInt(CALL_TYPE))
- .setIsRead(cursor.getInt(IS_READ))
- .setNumberAttributes(numberAttributes)
- .setTranscriptionState(cursor.getInt(TRANSCRIPTION_STATE));
-
- String formattedNumber = cursor.getString(FORMATTED_NUMBER);
- if (!TextUtils.isEmpty(formattedNumber)) {
- voicemailEntryBuilder.setFormattedNumber(formattedNumber);
- }
-
- String geocodedLocation = cursor.getString(GEOCODED_LOCATION);
- if (!TextUtils.isEmpty(geocodedLocation)) {
- voicemailEntryBuilder.setGeocodedLocation(geocodedLocation);
- }
-
- String transcription = cursor.getString(TRANSCRIPTION);
- if (!TextUtils.isEmpty(transcription)) {
- voicemailEntryBuilder.setTranscription(transcription);
- }
-
- String voicemailUri = cursor.getString(VOICEMAIL_URI);
- if (!TextUtils.isEmpty(voicemailUri)) {
- voicemailEntryBuilder.setVoicemailUri(voicemailUri);
- }
-
- String phoneAccountComponentName = cursor.getString(PHONE_ACCOUNT_COMPONENT_NAME);
- if (!TextUtils.isEmpty(phoneAccountComponentName)) {
- voicemailEntryBuilder.setPhoneAccountComponentName(phoneAccountComponentName);
- }
-
- String phoneAccountId = cursor.getString(PHONE_ACCOUNT_ID);
- if (!TextUtils.isEmpty(phoneAccountId)) {
- voicemailEntryBuilder.setPhoneAccountId(phoneAccountId);
- }
-
- return voicemailEntryBuilder.build();
- }
-
- static long getTimestamp(Cursor cursor) {
- return cursor.getLong(TIMESTAMP);
- }
-}
diff --git a/java/com/android/dialer/voicemail/listui/VoicemailEntryText.java b/java/com/android/dialer/voicemail/listui/VoicemailEntryText.java
deleted file mode 100644
index dd53dff..0000000
--- a/java/com/android/dialer/voicemail/listui/VoicemailEntryText.java
+++ /dev/null
@@ -1,113 +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.voicemail.listui;
-
-import android.content.Context;
-import android.text.TextUtils;
-import com.android.dialer.calllogutils.CallLogDates;
-import com.android.dialer.common.LogUtil;
-import com.android.dialer.time.Clock;
-import com.android.dialer.voicemail.model.VoicemailEntry;
-import java.util.concurrent.TimeUnit;
-
-/**
- * Computes the primary text for voicemail entries.
- *
- * <p>These text values are shown in the voicemail tab.
- */
-public class VoicemailEntryText {
-
- public static String buildPrimaryVoicemailText(Context context, VoicemailEntry data) {
- StringBuilder primaryText = new StringBuilder();
- if (!TextUtils.isEmpty(data.getNumberAttributes().getName())) {
- primaryText.append(data.getNumberAttributes().getName());
- } else if (!TextUtils.isEmpty(data.getFormattedNumber())) {
- primaryText.append(data.getFormattedNumber());
- } else {
- // TODO(uabdullah): Handle CallLog.Calls.PRESENTATION_*, including Verizon restricted numbers.
- primaryText.append(context.getText(R.string.voicemail_entry_unknown));
- }
- return primaryText.toString();
- }
-
- /**
- * Uses the new date and location formatting rules to format the location and date in the new
- * voicemail tab.
- *
- * <p>Rules: $Location • Date
- *
- * <p>Examples:
- *
- * <p>Jun 20 San Francisco • Now
- *
- * <p>Markham, ON • Jul 27
- *
- * <p>Toledo, OH • 12:15 PM
- *
- * <p>Date rules: if < 1 minute ago: "Now"; else if today: HH:MM(am|pm); else if < 3 days: day;
- * else: MON D *
- *
- * @return $Location • Date
- */
- public static String buildSecondaryVoicemailText(
- Context context, Clock clock, VoicemailEntry voicemailEntry) {
- return secondaryTextPrefix(context, clock, voicemailEntry);
- }
-
- private static String secondaryTextPrefix(
- Context context, Clock clock, VoicemailEntry voicemailEntry) {
- StringBuilder secondaryText = new StringBuilder();
- String location = voicemailEntry.getGeocodedLocation();
- if (!TextUtils.isEmpty(location)) {
- secondaryText.append(location);
- }
- if (secondaryText.length() > 0) {
- secondaryText.append(" • ");
- }
- secondaryText.append(
- CallLogDates.newCallLogTimestampLabel(
- context,
- clock.currentTimeMillis(),
- voicemailEntry.getTimestamp(),
- /* abbreviateDateTime = */ true));
-
- long duration = voicemailEntry.getDuration();
- if (duration >= 0) {
- secondaryText.append(" • ");
- String formattedDuration = getVoicemailDuration(context, voicemailEntry);
- secondaryText.append(formattedDuration);
- }
- return secondaryText.toString();
- }
-
- static String getVoicemailDuration(Context context, VoicemailEntry voicemailEntry) {
- long minutes = TimeUnit.SECONDS.toMinutes(voicemailEntry.getDuration());
- long seconds = voicemailEntry.getDuration() - TimeUnit.MINUTES.toSeconds(minutes);
-
- // The format for duration is "MM:SS" and we never expect the duration to be > 5 minutes
- // However an incorrect duration could be set by the framework/someone to be >99, and in that
- // case cap it at 99, for the UI to still be able to display it in "MM:SS" format.
- if (minutes > 99) {
- LogUtil.w(
- "VoicemailEntryText.getVoicemailDuration",
- "Duration was %d",
- voicemailEntry.getDuration());
- minutes = 99;
- }
- return context.getString(R.string.voicemailDurationFormat, minutes, seconds);
- }
-}
diff --git a/java/com/android/dialer/voicemail/listui/menu/AndroidManifest.xml b/java/com/android/dialer/voicemail/listui/menu/AndroidManifest.xml
deleted file mode 100644
index 07d4d22..0000000
--- a/java/com/android/dialer/voicemail/listui/menu/AndroidManifest.xml
+++ /dev/null
@@ -1,16 +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
- -->
-<manifest package="com.android.dialer.voicemail.listui.menu"/>
\ No newline at end of file
diff --git a/java/com/android/dialer/voicemail/listui/menu/BottomSheetHeader.java b/java/com/android/dialer/voicemail/listui/menu/BottomSheetHeader.java
deleted file mode 100644
index deca7bd..0000000
--- a/java/com/android/dialer/voicemail/listui/menu/BottomSheetHeader.java
+++ /dev/null
@@ -1,54 +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.voicemail.listui.menu;
-
-import android.text.TextUtils;
-import com.android.dialer.calllogutils.PhotoInfoBuilder;
-import com.android.dialer.historyitemactions.HistoryItemBottomSheetHeaderInfo;
-import com.android.dialer.voicemail.model.VoicemailEntry;
-
-/** Configures the top row in the bottom sheet for the Voicemail Tab */
-final class BottomSheetHeader {
-
- static HistoryItemBottomSheetHeaderInfo fromVoicemailEntry(VoicemailEntry voicemailEntry) {
- return HistoryItemBottomSheetHeaderInfo.newBuilder()
- .setNumber(voicemailEntry.getNumber())
- .setPhotoInfo(PhotoInfoBuilder.fromVoicemailEntry(voicemailEntry))
- .setPrimaryText(buildPrimaryVoicemailText(voicemailEntry))
- .setSecondaryText(buildSecondaryVoicemailText(voicemailEntry))
- .build();
- }
-
- private static String buildSecondaryVoicemailText(VoicemailEntry voicemailEntry) {
- return voicemailEntry.getGeocodedLocation();
- }
-
- private static String buildPrimaryVoicemailText(VoicemailEntry data) {
- StringBuilder primaryText = new StringBuilder();
- if (!TextUtils.isEmpty(data.getNumberAttributes().getName())) {
- primaryText.append(data.getNumberAttributes().getName());
- } else if (!TextUtils.isEmpty(data.getFormattedNumber())) {
- primaryText.append(data.getFormattedNumber());
- } else {
- // TODO(uabdullah): Handle CallLog.Calls.PRESENTATION_*, including Verizon restricted numbers.
- // primaryText.append(context.getText(R.string.voicemail_unknown));
- // TODO(uabdullah): Figure out why http://gpaste/5980163120562176 error when using string
- primaryText.append("Unknown");
- }
- return primaryText.toString();
- }
-}
diff --git a/java/com/android/dialer/voicemail/listui/menu/Modules.java b/java/com/android/dialer/voicemail/listui/menu/Modules.java
deleted file mode 100644
index 5a9a711..0000000
--- a/java/com/android/dialer/voicemail/listui/menu/Modules.java
+++ /dev/null
@@ -1,70 +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.voicemail.listui.menu;
-
-import android.content.Context;
-import android.text.TextUtils;
-import com.android.dialer.historyitemactions.HistoryItemActionModule;
-import com.android.dialer.historyitemactions.HistoryItemActionModuleInfo;
-import com.android.dialer.historyitemactions.HistoryItemActionModulesBuilder;
-import com.android.dialer.voicemail.model.VoicemailEntry;
-import java.util.List;
-
-/**
- * Configures the modules for the voicemail bottom sheet; these are the rows below the top row
- * (contact info) in the bottom sheet.
- */
-final class Modules {
-
- static List<HistoryItemActionModule> fromVoicemailEntry(
- Context context, VoicemailEntry voicemailEntry) {
- return new HistoryItemActionModulesBuilder(context, buildModuleInfo(voicemailEntry))
- // TODO(uabdullah): add module for calls.
- .addModuleForAddingToContacts()
- .addModuleForSendingTextMessage()
- .addModuleForDivider()
- .addModuleForBlockedOrSpamNumber()
- .addModuleForCopyingNumber()
- // TODO(zachh): Module for CallComposer.
- .build();
- }
-
- private static HistoryItemActionModuleInfo buildModuleInfo(VoicemailEntry voicemailEntry) {
- return HistoryItemActionModuleInfo.newBuilder()
- .setNormalizedNumber(voicemailEntry.getNumber().getNormalizedNumber())
- .setCountryIso(voicemailEntry.getNumber().getCountryIso())
- .setName(voicemailEntry.getNumberAttributes().getName())
- .setCallType(voicemailEntry.getCallType())
- .setLookupUri(voicemailEntry.getNumberAttributes().getLookupUri())
- .setPhoneAccountComponentName(voicemailEntry.getPhoneAccountComponentName())
- .setCanReportAsInvalidNumber(
- voicemailEntry.getNumberAttributes().getCanReportAsInvalidNumber())
- .setCanSupportAssistedDialing(
- !TextUtils.isEmpty(voicemailEntry.getNumberAttributes().getLookupUri()))
- .setCanSupportCarrierVideoCall(
- voicemailEntry.getNumberAttributes().getCanSupportCarrierVideoCall())
- .setIsBlocked(voicemailEntry.getNumberAttributes().getIsBlocked())
- .setIsEmergencyNumber(voicemailEntry.getNumberAttributes().getIsEmergencyNumber())
- .setIsSpam(voicemailEntry.getNumberAttributes().getIsSpam())
- // A voicemail call is an outgoing call to the voicemail box.
- // Voicemail entries are not voicemail calls.
- .setIsVoicemailCall(false)
- .setContactSource(voicemailEntry.getNumberAttributes().getContactSource())
- .setHost(HistoryItemActionModuleInfo.Host.VOICEMAIL)
- .build();
- }
-}
diff --git a/java/com/android/dialer/voicemail/listui/menu/NewVoicemailMenu.java b/java/com/android/dialer/voicemail/listui/menu/NewVoicemailMenu.java
deleted file mode 100644
index 6008059..0000000
--- a/java/com/android/dialer/voicemail/listui/menu/NewVoicemailMenu.java
+++ /dev/null
@@ -1,36 +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.voicemail.listui.menu;
-
-import android.content.Context;
-import android.view.View;
-import com.android.dialer.historyitemactions.HistoryItemActionBottomSheet;
-import com.android.dialer.voicemail.model.VoicemailEntry;
-
-/** Handles configuration of the bottom sheet menus for voicemail entries. */
-public final class NewVoicemailMenu {
-
- /** Creates and returns the OnClickListener which opens the menu for the provided row. */
- public static View.OnClickListener createOnClickListener(
- Context context, VoicemailEntry voicemailEntry) {
- return (view) ->
- HistoryItemActionBottomSheet.show(
- context,
- BottomSheetHeader.fromVoicemailEntry(voicemailEntry),
- Modules.fromVoicemailEntry(context, voicemailEntry));
- }
-}
diff --git a/java/com/android/dialer/voicemail/listui/res/layout/new_voicemail_call_log_fragment.xml b/java/com/android/dialer/voicemail/listui/res/layout/new_voicemail_call_log_fragment.xml
deleted file mode 100644
index a001bd6..0000000
--- a/java/com/android/dialer/voicemail/listui/res/layout/new_voicemail_call_log_fragment.xml
+++ /dev/null
@@ -1,46 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ 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
- -->
-
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/new_voicemail_frame_layout"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:background="?android:attr/colorBackground"
- android:orientation="vertical">
-
- <android.support.v7.widget.RecyclerView
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/new_voicemail_call_log_recycler_view"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:paddingBottom="88dp"
- android:clipToPadding="false"/>
-
-
- <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- <com.android.dialer.widget.EmptyContentView
- android:id="@+id/empty_content_view"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:visibility="gone"/>
- </FrameLayout>
-
-</FrameLayout>
diff --git a/java/com/android/dialer/voicemail/listui/res/layout/new_voicemail_entry.xml b/java/com/android/dialer/voicemail/listui/res/layout/new_voicemail_entry.xml
deleted file mode 100644
index 95711e0..0000000
--- a/java/com/android/dialer/voicemail/listui/res/layout/new_voicemail_entry.xml
+++ /dev/null
@@ -1,110 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ 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
- -->
-
-<RelativeLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:minHeight="72dp">
-
- <com.android.dialer.widget.ContactPhotoView
- android:id="@+id/contact_photo_view"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="12dp"
- android:layout_marginStart="8dp"
- android:layout_marginEnd="8dp"/>
-
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_toEndOf="@+id/contact_photo_view"
- android:layout_toStartOf="@+id/menu_button"
- android:orientation="vertical">
-
- <TextView
- android:id="@+id/primary_text"
- style="@style/Dialer.TextAppearance.Primary.Ellipsize"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="14dp"
- android:layout_marginEnd="6dp"
- android:lineSpacingMultiplier="1.5"/>
-
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- tools:ignore="UseCompoundDrawables">
-
- <ImageView
- android:layout_width="wrap_content"
- android:layout_height="18dp"
- android:layout_gravity="center_vertical"
- android:importantForAccessibility="no"
- android:src="@drawable/quantum_ic_voicemail_vd_theme_24"
- android:tint="?android:attr/colorPrimary"
- android:tintMode="multiply"
- tools:ignore="ContentDescription"/>
-
- <TextView
- android:id="@+id/secondary_text"
- style="@style/Dialer.TextAppearance.Secondary.Ellipsize"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:lineSpacingMultiplier="1.4"/>
- </LinearLayout>
-
- <!-- TODO(a bug): Make text selectable -->
- <TextView
- android:id="@+id/transcription_text"
- style="@style/Dialer.TextAppearance.Primary"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="6dp"
- android:layout_gravity="center_vertical"
- android:textSize="@dimen/voicemail_transcription_text_size"
- android:visibility="gone"/>
-
- <TextView
- android:id="@+id/transcription_branding"
- style="@style/Dialer.TextAppearance.Secondary"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center_vertical"
- android:text="@string/voicemail_transcription_branding_text"
- android:visibility="gone"/>
-
- <com.android.dialer.voicemail.listui.NewVoicemailMediaPlayerView
- android:id="@+id/new_voicemail_media_player"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:visibility="gone"/>
- </LinearLayout>
-
- <ImageView
- android:id="@+id/menu_button"
- android:layout_width="56dp"
- android:layout_height="72dp"
- android:layout_alignParentEnd="true"
- android:background="?android:attr/selectableItemBackgroundBorderless"
- android:contentDescription="@string/a11y_voicemail_entry_expand_menu"
- android:scaleType="center"
- android:src="@drawable/quantum_ic_more_vert_vd_theme_24"
- android:tint="?colorIcon"/>
-</RelativeLayout>
diff --git a/java/com/android/dialer/voicemail/listui/res/layout/new_voicemail_entry_alert.xml b/java/com/android/dialer/voicemail/listui/res/layout/new_voicemail_entry_alert.xml
deleted file mode 100644
index 1df8b2c..0000000
--- a/java/com/android/dialer/voicemail/listui/res/layout/new_voicemail_entry_alert.xml
+++ /dev/null
@@ -1,104 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ 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
- -->
-
-<!-- TODO(uabdullah): Use a relative layout instead of nested linear layouts.-->
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/voicemail_alert_content"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical">
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingTop="@dimen/alert_main_padding"
- android:paddingBottom="@dimen/alert_main_padding"
- android:paddingStart="@dimen/alert_main_padding"
- android:paddingEnd="@dimen/alert_main_padding"
- android:gravity="top"
- android:orientation="horizontal">
-
- <ImageView
- android:id="@+id/voicemail_alert_icon"
- android:layout_width="@dimen/voicemail_promo_card_icon_size"
- android:layout_height="@dimen/voicemail_promo_card_icon_size"
- android:layout_gravity="top"
- android:importantForAccessibility="no"
- android:src="@drawable/ic_voicemail_error_24px"/>
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginStart="@dimen/voicemail_promo_card_main_padding"
- android:gravity="center_vertical"
- android:orientation="vertical">
-
- <TextView
- android:id="@+id/voicemail_alert_header"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginBottom="@dimen/voicemail_promo_card_title_padding"
- android:layout_gravity="center_vertical"
- android:text="Voicemail Alert"
- style="@style/Dialer.TextAppearance.Header2"/>
-
- <TextView
- android:id="@+id/voicemail_alert_details"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:lineSpacingExtra="@dimen/voicemail_promo_card_line_spacing"
- android:text="This is a voicemail alert message."
- style="@style/Dialer.TextAppearance.Secondary"/>
- </LinearLayout>
- </LinearLayout>
-
- <LinearLayout
- android:id="@+id/voicemail_alert_button"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_gravity="end"
- android:paddingTop="10dp"
- android:paddingBottom="10dp"
- android:paddingStart="16dp"
- android:paddingEnd="16dp"
- android:gravity="end"
- android:minHeight="56dp"
- android:orientation="horizontal">
- <Button
- android:id="@+id/voicemail_alert_secondary_button"
- style="@style/TosButtonStyle"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textColor="?android:attr/colorPrimary"/>
-
- <Button
- android:id="@+id/voicemail_alert_primary_button"
- style="@style/TosButtonStyle"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textColor="?android:attr/colorPrimary"/>
- </LinearLayout>
-
- <View
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="1dp"
- android:layout_marginTop="8dp"
- android:layout_marginBottom="8dp"
- android:background="#12000000"/>
-</LinearLayout>
diff --git a/java/com/android/dialer/voicemail/listui/res/layout/new_voicemail_entry_header.xml b/java/com/android/dialer/voicemail/listui/res/layout/new_voicemail_entry_header.xml
deleted file mode 100644
index 70ca2ac..0000000
--- a/java/com/android/dialer/voicemail/listui/res/layout/new_voicemail_entry_header.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ 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
- -->
-<RelativeLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:minHeight="48dp"
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
- <TextView
- android:id="@+id/new_voicemail_header_text"
- style="@style/Dialer.TextAppearance.Secondary.Ellipsize"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginStart="16dp"
- android:layout_marginTop="8dp"
- android:layout_centerVertical="true"
- android:layout_gravity="center_vertical"/>
-</RelativeLayout>
diff --git a/java/com/android/dialer/voicemail/listui/res/layout/new_voicemail_media_player_layout.xml b/java/com/android/dialer/voicemail/listui/res/layout/new_voicemail_media_player_layout.xml
deleted file mode 100644
index 2796142..0000000
--- a/java/com/android/dialer/voicemail/listui/res/layout/new_voicemail_media_player_layout.xml
+++ /dev/null
@@ -1,111 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ 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
- -->
-
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingTop="@dimen/voicemail_media_player_padding_top"
- android:orientation="vertical">
-
- <TextView
- android:id="@+id/playback_state_text"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:gravity="center"
- android:text="@string/voicemail_media_player_state"
- android:textSize="@dimen/voicemail_playback_state_text_size"
- android:visibility="gone"/>
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:gravity="center_vertical"
- android:orientation="horizontal">
-
- <TextView
- android:id="@+id/playback_position_text"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:importantForAccessibility="no"
- android:text="@string/voicemail_media_player_inital_start_position"
- android:textSize="@dimen/voicemail_duration_size"/>
-
- <!-- TODO(uabdullah): Add listener to seekbar -->
- <SeekBar
- android:id="@+id/playback_seek"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:max="0"
- android:progress="0"/>
-
- <TextView
- android:id="@+id/playback_seek_total_duration"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:importantForAccessibility="no"
- android:textSize="@dimen/voicemail_duration_size"/>
- </LinearLayout>
-
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:paddingTop="10dp"
- android:gravity="center"
- android:orientation="horizontal"
- android:weightSum="4">
-
- <ImageButton
- android:id="@+id/pauseButton"
- style="@style/voicemail_media_player_buttons"
- android:layout_weight="1"
- android:contentDescription="@string/a11y_voicemail_entry_pause"
- android:src="@drawable/quantum_ic_pause_vd_theme_24"
- android:visibility="gone"/>
-
- <ImageButton
- android:id="@+id/playButton"
- style="@style/voicemail_media_player_buttons"
- android:layout_weight="1"
- android:contentDescription="@string/a11y_voicemail_entry_play"
- android:src="@drawable/quantum_ic_play_arrow_vd_theme_24"/>
-
-
- <ImageButton
- android:id="@+id/speakerButton"
- style="@style/voicemail_media_player_buttons"
- android:layout_weight="1"
- android:contentDescription="@string/a11y_voicemail_entry_speaker"
- android:src="@drawable/quantum_ic_volume_up_vd_theme_24"/>
-
-
- <ImageButton
- android:id="@+id/phoneButton"
- style="@style/voicemail_media_player_buttons"
- android:layout_weight="1"
- android:contentDescription="@string/a11y_voicemail_entry_call"
- android:src="@drawable/quantum_ic_phone_vd_theme_24"/>
-
- <ImageButton
- android:id="@+id/deleteButton"
- style="@style/voicemail_media_player_buttons"
- android:layout_weight="1"
- android:contentDescription="@string/a11y_voicemail_entry_delete"
- android:src="@drawable/quantum_ic_delete_vd_theme_24"/>
- </LinearLayout>
-</LinearLayout>
\ No newline at end of file
diff --git a/java/com/android/incallui/InCallPresenter.java b/java/com/android/incallui/InCallPresenter.java
index 67bc2a5..92c4518 100644
--- a/java/com/android/incallui/InCallPresenter.java
+++ b/java/com/android/incallui/InCallPresenter.java
@@ -628,8 +628,6 @@
// Since a call has been added we are no longer waiting for Telecom to send us a call.
setBoundAndWaitingForOutgoingCall(false, null);
call.registerCallback(callCallback);
- // TODO(maxwelb): Return the future in recordPhoneLookupInfo and propagate.
- PhoneLookupHistoryRecorder.recordPhoneLookupInfo(context.getApplicationContext(), call);
Trace.endSection();
}
diff --git a/java/com/android/incallui/PhoneLookupHistoryRecorder.java b/java/com/android/incallui/PhoneLookupHistoryRecorder.java
deleted file mode 100644
index 4c5cf8a..0000000
--- a/java/com/android/incallui/PhoneLookupHistoryRecorder.java
+++ /dev/null
@@ -1,86 +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.incallui;
-
-import android.content.ContentValues;
-import android.content.Context;
-import android.support.annotation.Nullable;
-import android.telecom.Call;
-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.phonelookup.PhoneLookupComponent;
-import com.android.dialer.phonelookup.PhoneLookupInfo;
-import com.android.dialer.phonelookup.database.contract.PhoneLookupHistoryContract.PhoneLookupHistory;
-import com.android.dialer.telecom.TelecomCallUtil;
-import com.google.common.base.Optional;
-import com.google.common.util.concurrent.FutureCallback;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
-
-/**
- * Fetches the current {@link PhoneLookupInfo} for the provided call and writes it to the
- * PhoneLookupHistory.
- */
-final class PhoneLookupHistoryRecorder {
-
- /**
- * 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 (!CallLogConfigComponent.get(appContext).callLogConfig().isCallLogFrameworkEnabled()) {
- return;
- }
-
- ListenableFuture<PhoneLookupInfo> infoFuture =
- PhoneLookupComponent.get(appContext).compositePhoneLookup().lookup(call);
-
- Futures.addCallback(
- infoFuture,
- new FutureCallback<PhoneLookupInfo>() {
- @Override
- public void onSuccess(@Nullable PhoneLookupInfo result) {
- Assert.checkArgument(result != null);
- Optional<String> normalizedNumber =
- TelecomCallUtil.getNormalizedNumber(appContext, call);
- if (!normalizedNumber.isPresent()) {
- LogUtil.w("PhoneLookupHistoryRecorder.onSuccess", "couldn't get a number");
- return;
- }
- ContentValues contentValues = new ContentValues();
- contentValues.put(PhoneLookupHistory.PHONE_LOOKUP_INFO, result.toByteArray());
- contentValues.put(PhoneLookupHistory.LAST_MODIFIED, System.currentTimeMillis());
- appContext
- .getContentResolver()
- .update(
- PhoneLookupHistory.contentUriForNumber(normalizedNumber.get()),
- contentValues,
- null,
- null);
- }
-
- @Override
- public void onFailure(Throwable t) {
- // TODO(zachh): Consider how to best handle this; take measures to repair call log?
- LogUtil.w(
- "PhoneLookupHistoryRecorder.onFailure", "could not write PhoneLookupHistory", t);
- }
- },
- DialerExecutorComponent.get(appContext).backgroundExecutor());
- }
-}