gt:         mContactHasUpdates = !data.getStreamItems().isEmpty();
context: /*
   * Copyright (C) 2011 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.contacts.detail;
  
  import android.animation.Animator;
  import android.animation.Animator.AnimatorListener;
  import android.animation.ObjectAnimator;
  import android.app.Activity;
  import android.app.FragmentManager;
  import android.app.FragmentTransaction;
  import android.content.Context;
  import android.net.Uri;
  import android.os.Bundle;
  import android.support.v4.view.ViewPager;
  import android.support.v4.view.ViewPager.OnPageChangeListener;
  import android.util.DisplayMetrics;
  import android.util.Log;
  import android.view.LayoutInflater;
  import android.view.View;
  import android.view.ViewPropertyAnimator;
  import android.view.animation.AnimationUtils;
  import android.widget.AbsListView;
  import android.widget.AbsListView.OnScrollListener;
  
  import com.android.contacts.NfcHandler;
  import com.android.contacts.R;
  import com.android.contacts.activities.ContactDetailActivity.FragmentKeyListener;
  /** M: New Feature @{ */
  import com.android.contacts.detail.ContactDetailFragment.OnUpdateClickListener;
  /** @} */
  import com.android.contacts.model.Contact;
  import com.android.contacts.util.PhoneCapabilityTester;
  import com.android.contacts.util.UriUtils;
  import com.android.contacts.widget.FrameLayoutWithOverlay;
  import com.android.contacts.widget.TransitionAnimationView;
  
  import com.mediatek.contacts.ExtensionManager;
  
  /**
   * Determines the layout of the contact card.
   */
  public class ContactDetailLayoutController implements OnUpdateClickListener {
  
      private static final String KEY_CONTACT_URI = "contactUri";
      private static final String KEY_CONTACT_HAS_UPDATES = "contactHasUpdates";
      private static final String KEY_CURRENT_PAGE_INDEX = "currentPageIndex";
  
      private static final int TAB_INDEX_DETAIL = 0;
      private static final int TAB_INDEX_UPDATES = 1;
  
      private final int SINGLE_PANE_FADE_IN_DURATION = 275;
  
      /**
       * There are 4 possible layouts for the contact detail screen: TWO_COLUMN,
       * VIEW_PAGER_AND_TAB_CAROUSEL, FRAGMENT_CAROUSEL, and TWO_COLUMN_FRAGMENT_CAROUSEL.
       */
      private interface LayoutMode {
          /**
           * Tall and wide screen with details and updates shown side-by-side.
           */
          static final int TWO_COLUMN = 0;
          /**
           * Tall and narrow screen to allow swipe between the details and updates.
           */
          static final int VIEW_PAGER_AND_TAB_CAROUSEL = 1;
          /**
           * Short and wide screen to allow part of the other page to show.
           */
          static final int FRAGMENT_CAROUSEL = 2;
          /**
           * Same as FRAGMENT_CAROUSEL (allowing part of the other page to show) except the details
           * layout is similar to the details layout in TWO_COLUMN mode.
           */
          static final int TWO_COLUMN_FRAGMENT_CAROUSEL = 3;
      }
  
      private final Activity mActivity;
      private final LayoutInflater mLayoutInflater;
      private final FragmentManager mFragmentManager;
  
      private final View mViewContainer;
      private final TransitionAnimationView mTransitionAnimationView;
      private ContactDetailFragment mDetailFragment;
      private ContactDetailUpdatesFragment mUpdatesFragment;
  
      private View mDetailFragmentView;
      private View mUpdatesFragmentView;
  
      private final ViewPager mViewPager;
      private ContactDetailViewPagerAdapter mViewPagerAdapter;
      private int mViewPagerState;
  
      private final ContactDetailTabCarousel mTabCarousel;
      private final ContactDetailFragmentCarousel mFragmentCarousel;
  
      private final ContactDetailFragment.Listener mContactDetailFragmentListener;
  
      private Contact mContactData;
      private Uri mContactUri;
  
      private boolean mTabCarouselIsAnimating;
  
      private boolean mContactHasUpdates;
  
      private int mLayoutMode;
  
      public ContactDetailLayoutController(Activity activity, Bundle savedState,
              FragmentManager fragmentManager, TransitionAnimationView animationView,
              View viewContainer, ContactDetailFragment.Listener contactDetailFragmentListener) {
  
          if (fragmentManager == null) {
              throw new IllegalStateException("Cannot initialize a ContactDetailLayoutController "
                      + "without a non-null FragmentManager");
          }
  
          mActivity = activity;
          mLayoutInflater = (LayoutInflater) activity.getSystemService(
                  Context.LAYOUT_INFLATER_SERVICE);
          mFragmentManager = fragmentManager;
          mContactDetailFragmentListener = contactDetailFragmentListener;
  
          mTransitionAnimationView = animationView;
  
          // Retrieve views in case this is view pager and carousel mode
          mViewContainer = viewContainer;
  
          mViewPager = (ViewPager) viewContainer.findViewById(R.id.pager);
          mTabCarousel = (ContactDetailTabCarousel) viewContainer.findViewById(R.id.tab_carousel);
  
          // Retrieve view in case this is in fragment carousel mode
          mFragmentCarousel = (ContactDetailFragmentCarousel) viewContainer.findViewById(
                  R.id.fragment_carousel);
  
          // Retrieve container views in case they are already in the XML layout
          mDetailFragmentView = viewContainer.findViewById(R.id.about_fragment_container);
          mUpdatesFragmentView = viewContainer.findViewById(R.id.updates_fragment_container);
  
          // Determine the layout mode based on the presence of certain views in the layout XML.
          if (mViewPager != null) {
              mLayoutMode = LayoutMode.VIEW_PAGER_AND_TAB_CAROUSEL;
          } else if (mFragmentCarousel != null) {
              if (PhoneCapabilityTester.isUsingTwoPanes(mActivity)) {
                  mLayoutMode = LayoutMode.TWO_COLUMN_FRAGMENT_CAROUSEL;
              } else {
                  mLayoutMode = LayoutMode.FRAGMENT_CAROUSEL;
              }
          } else {
              mLayoutMode = LayoutMode.TWO_COLUMN;
          }
  
          initialize(savedState);
      }
  
      private void initialize(Bundle savedState) {
          boolean fragmentsAddedToFragmentManager = true;
          mDetailFragment = (ContactDetailFragment) mFragmentManager.findFragmentByTag(
                  ContactDetailViewPagerAdapter.ABOUT_FRAGMENT_TAG);
          mUpdatesFragment = (ContactDetailUpdatesFragment) mFragmentManager.findFragmentByTag(
                  ContactDetailViewPagerAdapter.UPDATES_FRAGMENT_TAG);
  
          // If the detail fragment was found in the {@link FragmentManager} then we don't need to add
          // it again. Otherwise, create the fragments dynamically and remember to add them to the
          // {@link FragmentManager}.
          if (mDetailFragment == null) {
              mDetailFragment = new ContactDetailFragment();
              mUpdatesFragment = new ContactDetailUpdatesFragment();
              fragmentsAddedToFragmentManager = false;
          }
  
          mDetailFragment.setListener(mContactDetailFragmentListener);
          NfcHandler.register(mActivity, mDetailFragment);
  
          // Read from savedState if possible
          int currentPageIndex = 0;
          if (savedState != null) {
              mContactUri = savedState.getParcelable(KEY_CONTACT_URI);
              mContactHasUpdates = savedState.getBoolean(KEY_CONTACT_HAS_UPDATES);
              currentPageIndex = savedState.getInt(KEY_CURRENT_PAGE_INDEX, 0);
          }
  
          switch (mLayoutMode) {
              case LayoutMode.VIEW_PAGER_AND_TAB_CAROUSEL: {
                  // Inflate 2 view containers to pass in as children to the {@link ViewPager},
                  // which will in turn be the parents to the mDetailFragment and mUpdatesFragment
                  // since the fragments must have the same parent view IDs in both landscape and
                  // portrait layouts.
                  mDetailFragmentView = mLayoutInflater.inflate(
                          R.layout.contact_detail_about_fragment_container, mViewPager, false);
                  mUpdatesFragmentView = mLayoutInflater.inflate(
                          R.layout.contact_detail_updates_fragment_container, mViewPager, false);
  
                  mViewPagerAdapter = new ContactDetailViewPagerAdapter();
                  mViewPagerAdapter.setAboutFragmentView(mDetailFragmentView);
                  mViewPagerAdapter.setUpdatesFragmentView(mUpdatesFragmentView);
  
                  mViewPager.addView(mDetailFragmentView);
                  mViewPager.addView(mUpdatesFragmentView);
                  mViewPager.setAdapter(mViewPagerAdapter);
                  mViewPager.setOnPageChangeListener(mOnPageChangeListener);
  
                  if (!fragmentsAddedToFragmentManager) {
                      FragmentTransaction transaction = mFragmentManager.beginTransaction();
                      transaction.add(R.id.about_fragment_container, mDetailFragment,
                              ContactDetailViewPagerAdapter.ABOUT_FRAGMENT_TAG);
                      transaction.add(R.id.updates_fragment_container, mUpdatesFragment,
                              ContactDetailViewPagerAdapter.UPDATES_FRAGMENT_TAG);
                      transaction.commitAllowingStateLoss();
                      mFragmentManager.executePendingTransactions();
                  }
  
                  mTabCarousel.setListener(mTabCarouselListener);
                  mTabCarousel.restoreCurrentTab(currentPageIndex);
                  mDetailFragment.setVerticalScrollListener(
                          new VerticalScrollListener(TAB_INDEX_DETAIL));
                  mUpdatesFragment.setVerticalScrollListener(
                          new VerticalScrollListener(TAB_INDEX_UPDATES));
                  mViewPager.setCurrentItem(currentPageIndex);
                  /// M: for SNS plugin @{
                  if (ExtensionManager.getInstance().getContactDetailExtension()
                          .checkPluginSupport(ExtensionManager.COMMD_FOR_SNS)) {
                      mDetailFragment.setUpdateClickListener(this);
                  }
                  /// @}
                  break;
              }
              case LayoutMode.TWO_COLUMN: {
                  if (!fragmentsAddedToFragmentManager) {
                      FragmentTransaction transaction = mFragmentManager.beginTransaction();
                      transaction.add(R.id.about_fragment_container, mDetailFragment,
                              ContactDetailViewPagerAdapter.ABOUT_FRAGMENT_TAG);
                      transaction.add(R.id.updates_fragment_container, mUpdatesFragment,
                              ContactDetailViewPagerAdapter.UPDATES_FRAGMENT_TAG);
                      transaction.commitAllowingStateLoss();
                      mFragmentManager.executePendingTransactions();
                  }
                  break;
              }
              case LayoutMode.FRAGMENT_CAROUSEL:
              case LayoutMode.TWO_COLUMN_FRAGMENT_CAROUSEL: {
                  // Add the fragments to the fragment containers in the carousel using a
                  // {@link FragmentTransaction} if they haven't already been added to the
                  // {@link FragmentManager}.
                  if (!fragmentsAddedToFragmentManager) {
                      FragmentTransaction transaction = mFragmentManager.beginTransaction();
                      transaction.add(R.id.about_fragment_container, mDetailFragment,
                              ContactDetailViewPagerAdapter.ABOUT_FRAGMENT_TAG);
                      transaction.add(R.id.updates_fragment_container, mUpdatesFragment,
                              ContactDetailViewPagerAdapter.UPDATES_FRAGMENT_TAG);
                      transaction.commitAllowingStateLoss();
                      mFragmentManager.executePendingTransactions();
                  }
  
                  mFragmentCarousel.setFragmentViews(
                          (FrameLayoutWithOverlay) mDetailFragmentView,
                          (FrameLayoutWithOverlay) mUpdatesFragmentView);
                  mFragmentCarousel.setCurrentPage(currentPageIndex);
  
                  /// M: for SNS plugin @{
                  if (ExtensionManager.getInstance().getContactDetailExtension()
                          .checkPluginSupport(ExtensionManager.COMMD_FOR_SNS)) {
                      mDetailFragment.setUpdateClickListener(this);
                  }
                  /// @}
  
                  break;
              }
          }
  
          // Setup the layout if we already have a saved state
          if (savedState != null) {
              if (mContactHasUpdates) {
                  showContactWithUpdates(false);
              } else {
                  showContactWithoutUpdates();
              }
          }
      }
  
      public void setContactData(Contact data) {
          final boolean contactWasLoaded;
          final boolean contactHadUpdates;
          final boolean isDifferentContact;
          if (mContactData == null) {
              contactHadUpdates = false;
              contactWasLoaded = false;
              isDifferentContact = true;
          } else {
              contactHadUpdates = mContactHasUpdates;
              contactWasLoaded = true;
              isDifferentContact =
                      !UriUtils.areEqual(mContactData.getLookupUri(), data.getLookupUri());
          }
          mContactData = data;
  