summaryrefslogtreecommitdiff
path: root/java/com/android/dialer/main
diff options
context:
space:
mode:
authorzachh <zachh@google.com>2018-03-27 18:13:49 -0700
committerCopybara-Service <copybara-piper@google.com>2018-03-27 18:16:10 -0700
commit68ea8cf4e1d5a19bf8ef44e9686305ded95852de (patch)
treec14d8aea364c511d69db8e8ab3b097ec1547b494 /java/com/android/dialer/main
parentbb4c1be2923ea7bfc9152e3cef9d0c12cb6664bd (diff)
Support new call log fragment in old peer.
This makes the old peer read the CallLogConfig#isNewCallLogFragmentEnabled and show the old or new fragment accordingly. If the user is viewing the NewCallLog and the CallLogConfig needs to disable the framework, the new fragment is immediately replaced with the old one. This is necessary because if the user were to scroll the fragment, the AnnotatedCallLog and PhoneLookupHistory databases would be read, which would trigger creation. I don't expect this to be a common case because 1) we hopefully never have to disable the framework and 2) Framework is only updated on Phenotype broadcasts and JobScheduler jobs, which hopefully don't typically happen when user is viewing the call log. However, I still want to make sure that if it happens we don't irreversibly break users when we turn the framework back on. I tested this by flipping flags and observing underlying data being removed: > dialer-cmd configprovider set new_voicemail_fragment_enabled false > adb shell ls /data/data/com.google.android.dialer/databases/ && echo && adb shell cat /data/user_de/0/com.google.android.dialer/shared_prefs/com.google.android.dialer_preferences.xml I test flipping flags back and forth on the call log tab, speed dial tab, and while the activity was paused (pressing Home after viewing call log). Note that this CL doesn't address showing missed calls and badge counts correctly with the new fragment; that will come in a later CL. Bug: 74821995 Test: unit and manual PiperOrigin-RevId: 190706481 Change-Id: I618d9c1649169abd65733502cfebc662a835e787
Diffstat (limited to 'java/com/android/dialer/main')
-rw-r--r--java/com/android/dialer/main/impl/OldMainActivityPeer.java152
1 files changed, 141 insertions, 11 deletions
diff --git a/java/com/android/dialer/main/impl/OldMainActivityPeer.java b/java/com/android/dialer/main/impl/OldMainActivityPeer.java
index 9e8bd1ad6..6d78a5171 100644
--- a/java/com/android/dialer/main/impl/OldMainActivityPeer.java
+++ b/java/com/android/dialer/main/impl/OldMainActivityPeer.java
@@ -21,9 +21,11 @@ import android.app.Fragment;
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;
@@ -37,6 +39,7 @@ import android.support.annotation.Nullable;
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;
@@ -65,6 +68,8 @@ import com.android.dialer.callcomposer.CallComposerActivity;
import com.android.dialer.calldetails.OldCallDetailsActivity;
import com.android.dialer.callintent.CallIntentBuilder;
import com.android.dialer.callintent.CallSpecificAppData;
+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.DialerExecutorComponent;
@@ -110,7 +115,6 @@ import com.android.dialer.voicemailstatus.VoicemailStatusHelper;
import com.android.voicemail.VoicemailComponent;
import com.google.common.util.concurrent.ListenableFuture;
import java.util.Locale;
-import java.util.Objects;
import java.util.concurrent.TimeUnit;
/**
@@ -132,6 +136,23 @@ public class OldMainActivityPeer implements MainActivityPeer, FragmentUtilListen
// TODO(calderwoodra): change to AppCompatActivity once new speed dial ships
private final TransactionSafeActivity activity;
+ private final BroadcastReceiver disableNewCallLogReceiver =
+ new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (bottomNavTabListener == null) {
+ return;
+ }
+ /*
+ * Remove the NewCallLogFragment 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();
+ }
+ };
+
// Contacts
private MainOnContactSelectedListener onContactSelectedListener;
@@ -161,6 +182,7 @@ public class OldMainActivityPeer implements MainActivityPeer, FragmentUtilListen
private LastTabController lastTabController;
private BottomNavBar bottomNav;
+ private MainBottomNavBarBottomNavTabListener bottomNavTabListener;
private View snackbarContainer;
private UiListener<String> getLastOutgoingCallListener;
@@ -217,8 +239,9 @@ public class OldMainActivityPeer implements MainActivityPeer, FragmentUtilListen
activity.setSupportActionBar(activity.findViewById(R.id.toolbar));
bottomNav = activity.findViewById(R.id.bottom_nav_bar);
- MainBottomNavBarBottomNavTabListener bottomNavTabListener =
- new MainBottomNavBarBottomNavTabListener(activity, activity.getFragmentManager(), fab);
+ bottomNavTabListener =
+ new MainBottomNavBarBottomNavTabListener(
+ activity, activity.getFragmentManager(), activity.getSupportFragmentManager(), fab);
bottomNav.addOnTabSelectedListener(bottomNavTabListener);
// TODO(uabdullah): Handle case of when a sim is inserted/removed while the activity is open.
boolean showVoicemailTab = canVoicemailTabBeShown(activity);
@@ -432,6 +455,22 @@ public class OldMainActivityPeer implements MainActivityPeer, FragmentUtilListen
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(disableNewCallLogReceiver, new IntentFilter("disableNewCallLogFragment"));
+
+ /*
+ * Similar to above, if the new call log 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();
+
// add 1 sec delay to get memory snapshot so that dialer wont react slowly on resume.
ThreadUtil.postDelayedOnUiThread(
() ->
@@ -449,6 +488,7 @@ public class OldMainActivityPeer implements MainActivityPeer, FragmentUtilListen
@Override
public void onActivityPause() {
searchController.onActivityPause();
+ LocalBroadcastManager.getInstance(activity).unregisterReceiver(disableNewCallLogReceiver);
}
@Override
@@ -1122,14 +1162,19 @@ public class OldMainActivityPeer implements MainActivityPeer, FragmentUtilListen
private final AppCompatActivity activity;
private final FragmentManager fragmentManager;
+ private final android.support.v4.app.FragmentManager supportFragmentManager;
private final FloatingActionButton fab;
@TabIndex private int selectedTab = -1;
private MainBottomNavBarBottomNavTabListener(
- AppCompatActivity activity, FragmentManager fragmentManager, FloatingActionButton fab) {
+ AppCompatActivity activity,
+ FragmentManager fragmentManager,
+ android.support.v4.app.FragmentManager supportFragmentManager,
+ FloatingActionButton fab) {
this.activity = activity;
this.fragmentManager = fragmentManager;
+ this.supportFragmentManager = supportFragmentManager;
this.fab = fab;
}
@@ -1154,11 +1199,46 @@ public class OldMainActivityPeer implements MainActivityPeer, FragmentUtilListen
}
Logger.get(activity).logScreenView(ScreenEvent.Type.MAIN_CALL_LOG, activity);
selectedTab = TabIndex.CALL_LOG;
- Fragment fragment = fragmentManager.findFragmentByTag(CALL_LOG_TAG);
- showFragment(fragment == null ? new CallLogFragment() : fragment, CALL_LOG_TAG);
+
+ 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);
+ }
fab.show();
}
+ 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).commit();
+ // 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 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();
+ }
+ }
+
@Override
public void onContactsSelected() {
LogUtil.enterBlock("MainBottomNavBarBottomNavTabListener.onContactsSelected");
@@ -1193,34 +1273,65 @@ public class OldMainActivityPeer implements MainActivityPeer, FragmentUtilListen
fragment.onVisible();
}
+ private void showFragment(@NonNull Fragment fragment, String tag) {
+ showFragment(fragment, null, tag);
+ }
+
/**
* Shows the passed in fragment and hides all of the others in one transaction.
*
+ * <p>Exactly one of fragment or supportFragment should be provided.
+ *
* <p>Executes all fragment shows/hides in one transaction with no conflicting transactions
* (like showing and hiding the same fragment in the same transaction). See a bug.
*
* <p>Special care should be taken to avoid calling this method several times in a short window
* as it can lead to fragments overlapping.
*/
- private void showFragment(@NonNull Fragment fragment, String tag) {
+ private void showFragment(
+ @Nullable Fragment fragment,
+ @Nullable android.support.v4.app.Fragment supportFragment,
+ String tag) {
LogUtil.enterBlock("MainBottomNavBarBottomNavTabListener.showFragment");
Fragment speedDial = fragmentManager.findFragmentByTag(SPEED_DIAL_TAG);
- Fragment callLog = fragmentManager.findFragmentByTag(CALL_LOG_TAG);
+ Fragment oldCallLog = fragmentManager.findFragmentByTag(CALL_LOG_TAG);
Fragment contacts = fragmentManager.findFragmentByTag(CONTACTS_TAG);
Fragment voicemail = fragmentManager.findFragmentByTag(VOICEMAIL_TAG);
FragmentTransaction transaction = fragmentManager.beginTransaction();
boolean fragmentShown = showIfEqualElseHide(transaction, fragment, speedDial);
- fragmentShown |= showIfEqualElseHide(transaction, fragment, callLog);
+ fragmentShown |= showIfEqualElseHide(transaction, fragment, oldCallLog);
fragmentShown |= showIfEqualElseHide(transaction, fragment, contacts);
fragmentShown |= showIfEqualElseHide(transaction, fragment, voicemail);
- if (!fragmentShown) {
+ if (!fragmentShown && fragment != null) {
LogUtil.i(
"MainBottomNavBarBottomNavTabListener.showFragment", "Not added yet: " + fragment);
transaction.add(R.id.fragment_container, fragment, tag);
}
transaction.commit();
+
+ // Handle support fragments.
+ // TODO(calderwoodra): Handle other new fragments.
+ android.support.v4.app.Fragment newCallLog =
+ supportFragmentManager.findFragmentByTag(CALL_LOG_TAG);
+
+ android.support.v4.app.FragmentTransaction supportTransaction =
+ supportFragmentManager.beginTransaction();
+ boolean supportFragmentShown =
+ showIfEqualElseHideSupport(supportTransaction, supportFragment, newCallLog);
+ if (!supportFragmentShown && supportFragment != null) {
+ LogUtil.i(
+ "MainBottomNavBarBottomNavTabListener.showFragment",
+ "Not added yet: " + supportFragment);
+ supportTransaction.add(R.id.fragment_container, supportFragment, tag);
+ }
+ supportTransaction.commit();
+ }
+
+ private void showSupportFragment(
+ @NonNull android.support.v4.app.Fragment supportFragment, String tag) {
+ showFragment(null, supportFragment, tag);
}
/**
@@ -1231,7 +1342,7 @@ public class OldMainActivityPeer implements MainActivityPeer, FragmentUtilListen
private boolean showIfEqualElseHide(
FragmentTransaction transaction, Fragment fragment1, Fragment fragment2) {
boolean shown = false;
- if (Objects.equals(fragment1, fragment2)) {
+ if (fragment1 != null && fragment1.equals(fragment2)) {
transaction.show(fragment1);
shown = true;
} else if (fragment2 != null) {
@@ -1243,6 +1354,25 @@ public class OldMainActivityPeer implements MainActivityPeer, FragmentUtilListen
}
return shown;
}
+
+ /**
+ * @param supportFragment1 will be shown if equal to {@code fragment2}
+ * @param supportFragment2 will be hidden if unequal to {@code fragment1}
+ * @return {@code true} if {@code fragment1} was shown
+ */
+ private boolean showIfEqualElseHideSupport(
+ android.support.v4.app.FragmentTransaction supportTransaction,
+ android.support.v4.app.Fragment supportFragment1,
+ android.support.v4.app.Fragment supportFragment2) {
+ boolean shown = false;
+ if (supportFragment1 != null && supportFragment1.equals(supportFragment2)) {
+ supportTransaction.show(supportFragment1);
+ shown = true;
+ } else if (supportFragment2 != null) {
+ supportTransaction.hide(supportFragment2);
+ }
+ return shown;
+ }
}
private static final class LastTabController {