content: package com.actionbarsherlock.internal;
  
  import android.app.Activity;
  import android.content.Context;
  import android.content.pm.ActivityInfo;
  import android.content.res.AssetManager;
  import android.content.res.Configuration;
  import android.content.res.Resources;
  import android.content.res.TypedArray;
  import android.content.res.XmlResourceParser;
  import android.os.Bundle;
  import android.util.AndroidRuntimeException;
  import android.util.Log;
  import android.util.TypedValue;
  import android.view.ContextThemeWrapper;
  import android.view.KeyCharacterMap;
  import android.view.KeyEvent;
  import android.view.View;
  import android.view.ViewGroup;
  import android.view.ViewStub;
  import android.view.Window;
  import android.view.accessibility.AccessibilityEvent;
  import android.view.animation.Animation;
  import android.view.animation.AnimationUtils;
  import com.actionbarsherlock.ActionBarSherlock;
  import com.actionbarsherlock.BuildConfig;
  import com.actionbarsherlock.R;
  import com.actionbarsherlock.app.ActionBar;
  import com.actionbarsherlock.internal.app.ActionBarImpl;
  import com.actionbarsherlock.internal.view.StandaloneActionMode;
  import com.actionbarsherlock.internal.view.menu.ActionMenuPresenter;
  import com.actionbarsherlock.internal.view.menu.MenuBuilder;
  import com.actionbarsherlock.internal.view.menu.MenuItemImpl;
  import com.actionbarsherlock.internal.view.menu.MenuPresenter;
  import com.actionbarsherlock.internal.widget.ActionBarContainer;
  import com.actionbarsherlock.internal.widget.ActionBarContextView;
  import com.actionbarsherlock.internal.widget.ActionBarView;
  import com.actionbarsherlock.internal.widget.IcsProgressBar;
  import com.actionbarsherlock.view.ActionMode;
  import com.actionbarsherlock.view.Menu;
  import com.actionbarsherlock.view.MenuItem;
  import java.util.ArrayList;
  import java.util.HashMap;
  import java.util.List;
  import org.xmlpull.v1.XmlPullParser;
  
  import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
  import static com.actionbarsherlock.internal.ResourcesCompat.getResources_getBoolean;
  
  @ActionBarSherlock.Implementation(api = 7)
  public class ActionBarSherlockCompat extends ActionBarSherlock implements MenuBuilder.Callback, com.actionbarsherlock.view.Window.Callback, MenuPresenter.Callback, android.view.MenuItem.OnMenuItemClickListener {
      /** Window features which are enabled by default. */
      protected static final int DEFAULT_FEATURES = 0;
  
      static private final String PANELS_TAG = "sherlock:Panels";
  
      public ActionBarSherlockCompat(Activity activity, int flags) {
          super(activity, flags);
      }
  
  
      ///////////////////////////////////////////////////////////////////////////
      // Properties
      ///////////////////////////////////////////////////////////////////////////
  
      /** Whether or not the device has a dedicated menu key button. */
      private boolean mReserveOverflow;
      /** Lazy-load indicator for {@link #mReserveOverflow}. */
      private boolean mReserveOverflowSet = false;
  
      /** Current menu instance for managing action items. */
      private MenuBuilder mMenu;
      /** Map between native options items and sherlock items. */
      protected HashMap<android.view.MenuItem, MenuItemImpl> mNativeItemMap;
  
      /** Parent view of the window decoration (action bar, mode, etc.). */
      private ViewGroup mDecor;
      /** Parent view of the activity content. */
      private ViewGroup mContentParent;
  
      /** Whether or not the title is stable and can be displayed. */
      private boolean mIsTitleReady = false;
      /** Whether or not the parent activity has been destroyed. */
      private boolean mIsDestroyed = false;
  
      /* Emulate PanelFeatureState */
      private boolean mClosingActionMenu;
      private boolean mMenuIsPrepared;
      private boolean mMenuRefreshContent;
      private Bundle mMenuFrozenActionViewState;
  
      /** Implementation which backs the action bar interface API. */
      private ActionBarImpl aActionBar;
      /** Main action bar view which displays the core content. */
      private ActionBarView wActionBar;
      /** Relevant window and action bar features flags. */
      private int mFeatures = DEFAULT_FEATURES;
      /** Relevant user interface option flags. */
      private int mUiOptions = 0;
  
      /** Decor indeterminate progress indicator. */
      private IcsProgressBar mCircularProgressBar;
      /** Decor progress indicator. */
      private IcsProgressBar mHorizontalProgressBar;
  
      /** Current displayed context action bar, if any. */
      private ActionMode mActionMode;
      /** Parent view in which the context action bar is displayed. */
      private ActionBarContextView mActionModeView;
  
  
  
      ///////////////////////////////////////////////////////////////////////////
      // Instance methods
      ///////////////////////////////////////////////////////////////////////////
  
      @Override
      public ActionBar getActionBar() {
          if (BuildConfig.DEBUG) Log.d(TAG, "[getActionBar]");
  
          initActionBar();
          return aActionBar;
      }
  
      private void initActionBar() {
          if (BuildConfig.DEBUG) Log.d(TAG, "[initActionBar]");
  
          // Initializing the window decor can change window feature flags.
          // Make sure that we have the correct set before performing the test below.
          if (mDecor == null) {
              installDecor();
          }
  
          if ((aActionBar != null) || !hasFeature(Window.FEATURE_ACTION_BAR) || hasFeature(Window.FEATURE_NO_TITLE) || mActivity.isChild()) {
              return;
          }
  
          aActionBar = new ActionBarImpl(mActivity, mFeatures);
  
          if (!mIsDelegate) {
              //We may never get another chance to set the title
              wActionBar.setWindowTitle(mActivity.getTitle());
          }
      }
  
      @Override
      protected Context getThemedContext() {
          return aActionBar.getThemedContext();
      }
  
      @Override
      public void setTitle(CharSequence title) {
          if (BuildConfig.DEBUG) Log.d(TAG, "[setTitle] title: " + title);
  
          dispatchTitleChanged(title, 0);
      }
  
      @Override
      public ActionMode startActionMode(ActionMode.Callback callback) {
          if (BuildConfig.DEBUG) Log.d(TAG, "[startActionMode] callback: " + callback);
  
          if (mActionMode != null) {
              mActionMode.finish();
          }
  
          final ActionMode.Callback wrappedCallback = new ActionModeCallbackWrapper(callback);
          ActionMode mode = null;
  
          //Emulate Activity's onWindowStartingActionMode:
          initActionBar();
          if (aActionBar != null) {
              mode = aActionBar.startActionMode(wrappedCallback);
          }
  
          if (mode != null) {
              mActionMode = mode;
          } else {
              if (mActionModeView == null) {
                  ViewStub stub = (ViewStub)mDecor.findViewById(R.id.abs__action_mode_bar_stub);
                  if (stub != null) {
                      mActionModeView = (ActionBarContextView)stub.inflate();
                  }
              }
              if (mActionModeView != null) {
                  mActionModeView.killMode();
                  mode = new StandaloneActionMode(mActivity, mActionModeView, wrappedCallback, true);
                  if (callback.onCreateActionMode(mode, mode.getMenu())) {
                      mode.invalidate();
                      mActionModeView.initForMode(mode);
                      mActionModeView.setVisibility(View.VISIBLE);
                      mActionMode = mode;
                      mActionModeView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
                  } else {
                      mActionMode = null;
                  }
              }
          }
          if (mActionMode != null && mActivity instanceof OnActionModeStartedListener) {
              ((OnActionModeStartedListener)mActivity).onActionModeStarted(mActionMode);
          }
          return mActionMode;
      }
  
  
      ///////////////////////////////////////////////////////////////////////////
      // Lifecycle and interaction callbacks for delegation
      ///////////////////////////////////////////////////////////////////////////
  
      @Override
      public void dispatchConfigurationChanged(Configuration newConfig) {
          if (BuildConfig.DEBUG) Log.d(TAG, "[dispatchConfigurationChanged] newConfig: " + newConfig);
  
          if (aActionBar != null) {
              aActionBar.onConfigurationChanged(newConfig);
          }
      }
  
      @Override
      public void dispatchPostResume() {
          if (BuildConfig.DEBUG) Log.d(TAG, "[dispatchPostResume]");
  
          if (aActionBar != null) {
              aActionBar.setShowHideAnimationEnabled(true);
          }
      }
  
      @Override
      public void dispatchPause() {
          if (BuildConfig.DEBUG) Log.d(TAG, "[dispatchPause]");
  
          if (wActionBar != null && wActionBar.isOverflowMenuShowing()) {
              wActionBar.hideOverflowMenu();
          }
      }
  
      @Override
      public void dispatchStop() {
          if (BuildConfig.DEBUG) Log.d(TAG, "[dispatchStop]");
  
          if (aActionBar != null) {
              aActionBar.setShowHideAnimationEnabled(false);
          }
      }
  
      @Override
      public void dispatchInvalidateOptionsMenu() {
          if (BuildConfig.DEBUG) Log.d(TAG, "[dispatchInvalidateOptionsMenu]");
  
          Bundle savedActionViewStates = null;
          if (mMenu != null) {
              savedActionViewStates = new Bundle();
              mMenu.saveActionViewStates(savedActionViewStates);
              if (savedActionViewStates.size() > 0) {
                  mMenuFrozenActionViewState = savedActionViewStates;
              }
              // This will be started again when the panel is prepared.
              mMenu.stopDispatchingItemsChanged();
              mMenu.clear();
          }
          mMenuRefreshContent = true;
  
          // Prepare the options panel if we have an action bar
          if (wActionBar != null) {
              mMenuIsPrepared = false;
              preparePanel();
          }
      }
  
      @Override
      public boolean dispatchOpenOptionsMenu() {
          if (BuildConfig.DEBUG) Log.d(TAG, "[dispatchOpenOptionsMenu]");
  
          if (!isReservingOverflow()) {
              return false;
          }
  
          return wActionBar.showOverflowMenu();
      }
  
      @Override
      public boolean dispatchCloseOptionsMenu() {
          if (BuildConfig.DEBUG) Log.d(TAG, "[dispatchCloseOptionsMenu]");
  
          if (!isReservingOverflow()) {
              return false;
          }
  
          if (wActionBar != null) {
              return wActionBar.hideOverflowMenu();
          }
          return false;
      }
  
      @Override
      public void dispatchPostCreate(Bundle savedInstanceState) {
          if (BuildConfig.DEBUG) Log.d(TAG, "[dispatchOnPostCreate]");
  
          if (mIsDelegate) {
              mIsTitleReady = true;
          }
  
          if (mDecor == null) {
              initActionBar();
          }
      }
  
      @Override
      public boolean dispatchCreateOptionsMenu(android.view.Menu menu) {
          if (BuildConfig.DEBUG) {
              Log.d(TAG, "[dispatchCreateOptionsMenu] android.view.Menu: " + menu);
              Log.d(TAG, "[dispatchCreateOptionsMenu] returning true");
          }
          return true;
      }
  
      @Override
      public boolean dispatchPrepareOptionsMenu(android.view.Menu menu) {
          if (BuildConfig.DEBUG) Log.d(TAG, "[dispatchPrepareOptionsMenu] android.view.Menu: " + menu);
  
          if (mActionMode != null) {
              return false;
          }
  
          mMenuIsPrepared = false;
          if (!preparePanel()) {
              return false;
          }
  
          if (isReservingOverflow()) {
              return false;
          }
  
          if (mNativeItemMap == null) {
              mNativeItemMap = new HashMap<android.view.MenuItem, MenuItemImpl>();
          } else {
              mNativeItemMap.clear();
          }
  
          if (mMenu == null) {
              return false;
          }
  
          boolean result = mMenu.bindNativeOverflow(menu, this, mNativeItemMap);
          if (BuildConfig.DEBUG) Log.d(TAG, "[dispatchPrepareOptionsMenu] returning " + result);
          return result;
      }
  
      @Override
      public boolean dispatchOptionsItemSelected(android.view.MenuItem item) {
          throw new IllegalStateException("Native callback invoked. Create a test case and report!");
      }
  
      @Override
      public boolean dispatchMenuOpened(int featureId, android.view.Menu menu) {
          if (BuildConfig.DEBUG) Log.d(TAG, "[dispatchMenuOpened] featureId: " + featureId + ", menu: " + menu);
  
          if (featureId == Window.FEATURE_ACTION_BAR || featureId == Window.FEATURE_OPTIONS_PANEL) {
              if (aActionBar != null) {
                  aActionBar.dispatchMenuVisibilityChanged(true);
              }
              return true;
          }
  
          return false;
      }
  
      @Override
      public void dispatchPanelClosed(int featureId, android.view.Menu menu){
          if (BuildConfig.DEBUG) Log.d(TAG, "[dispatchPanelClosed] featureId: " + featureId + ", menu: " + menu);
  
          if (featureId == Window.FEATURE_ACTION_BAR || featureId == Window.FEATURE_OPTIONS_PANEL) {
              if (aActionBar != null) {
                  aActionBar.dispatchMenuVisibilityChanged(false);
              }
          }
      }
  
      @Override
      public void dispatchTitleChanged(CharSequence title, int color) {
          if (BuildConfig.DEBUG) Log.d(TAG, "[dispatchTitleChanged] title: " + title + ", color: " + color);
  
          if ((!mIsDelegate || mIsTitleReady) && (wActionBar != null)) {
              wActionBar.setWindowTitle(title);
          }
      }
  
      @Override
      public boolean dispatchKeyEvent(KeyEvent event) {
          if (BuildConfig.DEBUG) Log.d(TAG, "[dispatchKeyEvent] event: " + event);
  
          final int keyCode = event.getKeyCode();
  
          // Not handled by the view hierarchy, does the action bar want it
          // to cancel out of something special?
          if (keyCode == KeyEvent.KEYCODE_BACK) {
              final int action = event.getAction();
              // Back cancels action modes first.
              if (mActionMode != null) {
                  if (action == KeyEvent.ACTION_UP) {
                      mActionMode.finish();
                  }
                  if (BuildConfig.DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true");
                  return true;
              }
  
              // Next collapse any expanded action views.
              if (wActionBar != null && wActionBar.hasExpandedActionView()) {
                  if (action == KeyEvent.ACTION_UP) {
                      wActionBar.collapseActionView();
                  }
                  if (BuildConfig.DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true");
                  return true;
              }
          }
  
          if (BuildConfig.DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning false");
          return false;
      }
  
      @Override
      public void dispatchDestroy() {
          mIsDestroyed = true;
      }
  
      @Override
      public void dispatchSaveInstanceState(Bundle outState) {
          if (mMenu != null) {
              mMenuFrozenActionViewState = new Bundle();
              mMenu.saveActionViewStates(mMenuFrozenActionViewState);
          }
          outState.putParcelable(PANELS_TAG, mMenuFrozenActionViewState);
      }
  
      @Override
      public void dispatchRestoreInstanceState(Bundle savedInstanceState) {
          mMenuFrozenActionViewState = savedInstanceState.getParcelable(PANELS_TAG);
      }
  
      ///////////////////////////////////////////////////////////////////////////
      // Menu callback lifecycle and creation
      ///////////////////////////////////////////////////////////////////////////
  
      private boolean preparePanel() {
          // Already prepared (isPrepared will be reset to false later)
          if (mMenuIsPrepared) {
              return true;
          }
  
          // Init the panel state's menu--return false if init failed
          if (mMenu == null || mMenuRefreshContent) {
              if (mMenu == null) {
                  if (!initializePanelMenu() || (mMenu == null)) {
                      return false;
                  }
              }
  
              if (wActionBar != null) {
                  wActionBar.setMenu(mMenu, this);
              }
  
              // Call callback, and return if it doesn't want to display menu.
  
              // Creating the panel menu will involve a lot of manipulation;
              // don't dispatch change events to presenters until we're done.
              mMenu.stopDispatchingItemsChanged();
              if (!callbackCreateOptionsMenu(mMenu)) {
                  // Ditch the menu created above
                  mMenu = null;
  
                  if (wActionBar != null) {
                      // Don't show it in the action bar either
                      wActionBar.setMenu(null, this);
                  }
  
                  return false;
              }
  
              mMenuRefreshContent = false;
          }
  
          // Callback and return if the callback does not want to show the menu
  
          // Preparing the panel menu can involve a lot of manipulation;
          // don't dispatch change events to presenters until we're done.
          mMenu.stopDispatchingItemsChanged();
  
          // Restore action view state before we prepare. This gives apps
          // an opportunity to override frozen/restored state in onPrepare.
          if (mMenuFrozenActionViewState != null) {
              mMenu.restoreActionViewStates(mMenuFrozenActionViewState);
              mMenuFrozenActionViewState = null;
          }
  
          if (!callbackPrepareOptionsMenu(mMenu)) {
              if (wActionBar != null) {
                  // The app didn't want to show the menu for now but it still exists.
                  // Clear it out of the action bar.
                  wActionBar.setMenu(null, this);
              }
              mMenu.startDispatchingItemsChanged();
              return false;
          }
  
          // Set the proper keymap
          KeyCharacterMap kmap = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD);
          mMenu.setQwertyMode(kmap.getKeyboardType() != KeyCharacterMap.NUMERIC);
          mMenu.startDispatchingItemsChanged();
  
          // Set other state
          mMenuIsPrepared = true;
  
          return true;
      }
  
      public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) {
          return callbackOptionsItemSelected(item);
      }
  
      public void onMenuModeChange(MenuBuilder menu) {
          reopenMenu(true);
      }
  
      private void reopenMenu(boolean toggleMenuMode) {
          if (wActionBar != null && wActionBar.isOverflowReserved()) {
              if (!wActionBar.isOverflowMenuShowing() || !toggleMenuMode) {
                  if (wActionBar.getVisibility() == View.VISIBLE) {
                      if (callbackPrepareOptionsMenu(mMenu)) {
                          wActionBar.showOverflowMenu();
                      }
                  }
              } else {
                  wActionBar.hideOverflowMenu();
              }
              return;
          }
      }
  
      private boolean initializePanelMenu() {
          Context context = mActivity;//getContext();
  
          // If we have an action bar, initialize the menu with a context themed for it.
          if (wActionBar != null) {
              TypedValue outValue = new TypedValue();
              Resources.Theme currentTheme = context.getTheme();
              currentTheme.resolveAttribute(R.attr.actionBarWidgetTheme,
                      outValue, true);
              final int targetThemeRes = outValue.resourceId;
  
              if (targetThemeRes != 0 /*&& context.getThemeResId() != targetThemeRes*/) {
                  context = new ContextThemeWrapper(context, targetThemeRes);
              }
          }
  
          mMenu = new MenuBuilder(context);
          mMenu.setCallback(this);
  
          return true;
      }
  
      void checkCloseActionMenu(Menu menu) {
          if (mClosingActionMenu) {
              return;
          }
  
          mClosingActionMenu = true;
          wActionBar.dismissPopupMenus();
          //Callback cb = getCallback();
          //if (cb != null && !isDestroyed()) {
          //    cb.onPanelClosed(FEATURE_ACTION_BAR, menu);
          //}
          mClosingActionMenu = false;
      }
  
      @Override
      public boolean onOpenSubMenu(MenuBuilder subMenu) {
          return true;
      }
  
      @Override
      public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) {
          checkCloseActionMenu(menu);
      }
  
      @Override
      public boolean onMenuItemClick(android.view.MenuItem item) {
          if (BuildConfig.DEBUG) Log.d(TAG, "[mNativeItemListener.onMenuItemClick] item: " + item);
  
          final MenuItemImpl sherlockItem = mNativeItemMap.get(item);
          if (sherlockItem != null) {
              sherlockItem.invoke();
          } else {
              Log.e(TAG, "Options item \"" + item + "\" not found in mapping");
          }
  
          return true; //Do not allow continuation of native handling
      }
  
      @Override
      public boolean onMenuItemSelected(int featureId, MenuItem item) {
          return callbackOptionsItemSelected(item);
      }
  
  
      ///////////////////////////////////////////////////////////////////////////
      // Progress bar interaction and internal handling
      ///////////////////////////////////////////////////////////////////////////
  
      @Override
      public void setProgressBarVisibility(boolean visible) {
          if (BuildConfig.DEBUG) Log.d(TAG, "[setProgressBarVisibility] visible: " + visible);
  
          setFeatureInt(Window.FEATURE_PROGRESS, visible ? Window.PROGRESS_VISIBILITY_ON :
              Window.PROGRESS_VISIBILITY_OFF);
      }
  
      @Override
      public void setProgressBarIndeterminateVisibility(boolean visible) {
          if (BuildConfig.DEBUG) Log.d(TAG, "[setProgressBarIndeterminateVisibility] visible: " + visible);
  
          setFeatureInt(Window.FEATURE_INDETERMINATE_PROGRESS,
                  visible ? Window.PROGRESS_VISIBILITY_ON : Window.PROGRESS_VISIBILITY_OFF);
      }
  
      @Override
      public void setProgressBarIndeterminate(boolean indeterminate) {
          if (BuildConfig.DEBUG) Log.d(TAG, "[setProgressBarIndeterminate] indeterminate: " + indeterminate);
  
          setFeatureInt(Window.FEATURE_PROGRESS,
                  indeterminate ? Window.PROGRESS_INDETERMINATE_ON : Window.PROGRESS_INDETERMINATE_OFF);
      }
  
      @Override
      public void setProgress(int progress) {
          if (BuildConfig.DEBUG) Log.d(TAG, "[setProgress] progress: " + progress);
  
          setFeatureInt(Window.FEATURE_PROGRESS, progress + Window.PROGRESS_START);
      }
  
      @Override
      public void setSecondaryProgress(int secondaryProgress) {
          if (BuildConfig.DEBUG) Log.d(TAG, "[setSecondaryProgress] secondaryProgress: " + secondaryProgress);
  
          setFeatureInt(Window.FEATURE_PROGRESS,
                  secondaryProgress + Window.PROGRESS_SECONDARY_START);
      }
  
      private void setFeatureInt(int featureId, int value) {
          updateInt(featureId, value, false);
      }
  
      private void updateInt(int featureId, int value, boolean fromResume) {
          // Do nothing if the decor is not yet installed... an update will
          // need to be forced when we eventually become active.
          if (mContentParent == null) {
              return;
          }
  
          final int featureMask = 1 << featureId;
  
          if ((getFeatures() & featureMask) == 0 && !fromResume) {
              return;
          }
  
          onIntChanged(featureId, value);
      }
  
      private void onIntChanged(int featureId, int value) {
          if (featureId == Window.FEATURE_PROGRESS || featureId == Window.FEATURE_INDETERMINATE_PROGRESS) {
              updateProgressBars(value);
          }
      }
  
      private void updateProgressBars(int value) {
          IcsProgressBar circularProgressBar = getCircularProgressBar(true);
          IcsProgressBar horizontalProgressBar = getHorizontalProgressBar(true);
  
          final int features = mFeatures;//getLocalFeatures();
          if (value == Window.PROGRESS_VISIBILITY_ON) {
              if ((features & (1 << Window.FEATURE_PROGRESS)) != 0) {
                  int level = horizontalProgressBar.getProgress();
                  int visibility = (horizontalProgressBar.isIndeterminate() || level < 10000) ?
                          View.VISIBLE : View.INVISIBLE;
                  horizontalProgressBar.setVisibility(visibility);
              }
              if ((features & (1 << Window.FEATURE_INDETERMINATE_PROGRESS)) != 0) {
                  circularProgressBar.setVisibility(View.VISIBLE);
              }
          } else if (value == Window.PROGRESS_VISIBILITY_OFF) {
              if ((features & (1 << Window.FEATURE_PROGRESS)) != 0) {
                  horizontalProgressBar.setVisibility(View.GONE);
              }
              if ((features & (1 << Window.FEATURE_INDETERMINATE_PROGRESS)) != 0) {
                  circularProgressBar.setVisibility(View.GONE);
              }
          } else if (value == Window.PROGRESS_INDETERMINATE_ON) {
              horizontalProgressBar.setIndeterminate(true);
          } else if (value == Window.PROGRESS_INDETERMINATE_OFF) {
              horizontalProgressBar.setIndeterminate(false);
          } else if (Window.PROGRESS_START <= value && value <= Window.PROGRESS_END) {
              // We want to set the progress value before testing for visibility
              // so that when the progress bar becomes visible again, it has the
              // correct level.
              horizontalProgressBar.setProgress(value - Window.PROGRESS_START);
  
              if (value < Window.PROGRESS_END) {
                  showProgressBars(horizontalProgressBar, circularProgressBar);
              } else {
                  hideProgressBars(horizontalProgressBar, circularProgressBar);
              }
          } else if (Window.PROGRESS_SECONDARY_START <= value && value <= Window.PROGRESS_SECONDARY_END) {
              horizontalProgressBar.setSecondaryProgress(value - Window.PROGRESS_SECONDARY_START);
  
              showProgressBars(horizontalProgressBar, circularProgressBar);
          }
      }
  
      private void showProgressBars(IcsProgressBar horizontalProgressBar, IcsProgressBar spinnyProgressBar) {
          final int features = mFeatures;//getLocalFeatures();
          if ((features & (1 << Window.FEATURE_INDETERMINATE_PROGRESS)) != 0 &&
                  spinnyProgressBar.getVisibility() == View.INVISIBLE) {
              spinnyProgressBar.setVisibility(View.VISIBLE);
          }
          // Only show the progress bars if the primary progress is not complete
          if ((features & (1 << Window.FEATURE_PROGRESS)) != 0 &&
                  horizontalProgressBar.getProgress() < 10000) {
              horizontalProgressBar.setVisibility(View.VISIBLE);
          }
      }
  
      private void hideProgressBars(IcsProgressBar horizontalProgressBar, IcsProgressBar spinnyProgressBar) {
          final int features = mFeatures;//getLocalFeatures();
          Animation anim = AnimationUtils.loadAnimation(mActivity, android.R.anim.fade_out);
          anim.setDuration(1000);
          if ((features & (1 << Window.FEATURE_INDETERMINATE_PROGRESS)) != 0 &&
                  spinnyProgressBar.getVisibility() == View.VISIBLE) {
              spinnyProgressBar.startAnimation(anim);
              spinnyProgressBar.setVisibility(View.INVISIBLE);
          }
          if ((features & (1 << Window.FEATURE_PROGRESS)) != 0 &&
                  horizontalProgressBar.getVisibility() == View.VISIBLE) {
              horizontalProgressBar.startAnimation(anim);
              horizontalProgressBar.setVisibility(View.INVISIBLE);
          }
      }
  
      private IcsProgressBar getCircularProgressBar(boolean shouldInstallDecor) {
          if (mCircularProgressBar != null) {
              return mCircularProgressBar;
          }
          if (mContentParent == null && shouldInstallDecor) {
              installDecor();
          }
          mCircularProgressBar = (IcsProgressBar)mDecor.findViewById(R.id.abs__progress_circular);
          if (mCircularProgressBar != null) {
              mCircularProgressBar.setVisibility(View.INVISIBLE);
          }
          return mCircularProgressBar;
      }
  
      private IcsProgressBar getHorizontalProgressBar(boolean shouldInstallDecor) {
          if (mHorizontalProgressBar != null) {
              return mHorizontalProgressBar;
          }
          if (mContentParent == null && shouldInstallDecor) {
              installDecor();
          }
          mHorizontalProgressBar = (IcsProgressBar)mDecor.findViewById(R.id.abs__progress_horizontal);
          if (mHorizontalProgressBar != null) {
              mHorizontalProgressBar.setVisibility(View.INVISIBLE);
          }
          return mHorizontalProgressBar;
      }
  
  
      ///////////////////////////////////////////////////////////////////////////
      // Feature management and content interaction and creation
      ///////////////////////////////////////////////////////////////////////////
  
      private int getFeatures() {
          if (BuildConfig.DEBUG) Log.d(TAG, "[getFeatures] returning " + mFeatures);
  
          return mFeatures;
      }
  
      @Override
      public boolean hasFeature(int featureId) {
          if (BuildConfig.DEBUG) Log.d(TAG, "[hasFeature] featureId: " + featureId);
  
          boolean result = (mFeatures & (1 << featureId)) != 0;
          if (BuildConfig.DEBUG) Log.d(TAG, "[hasFeature] returning " + result);
          return result;
      }
  
      @Override
      public boolean requestFeature(int featureId) {
          if (BuildConfig.DEBUG) Log.d(TAG, "[requestFeature] featureId: " + featureId);
  
          if (mContentParent != null) {
              throw new AndroidRuntimeException("requestFeature() must be called before adding content");
          }
  
          switch (featureId) {
              case Window.FEATURE_ACTION_BAR:
              case Window.FEATURE_ACTION_BAR_OVERLAY:
              case Window.FEATURE_ACTION_MODE_OVERLAY:
              case Window.FEATURE_INDETERMINATE_PROGRESS:
              case Window.FEATURE_NO_TITLE:
              case Window.FEATURE_PROGRESS:
                  mFeatures |= (1 << featureId);
                  return true;
  
              default:
                  return false;
          }
      }
  
      @Override
      public void setUiOptions(int uiOptions) {
          if (BuildConfig.DEBUG) Log.d(TAG, "[setUiOptions] uiOptions: " + uiOptions);
  
          mUiOptions = uiOptions;
      }
  
      @Override
      public void setUiOptions(int uiOptions, int mask) {
          if (BuildConfig.DEBUG) Log.d(TAG, "[setUiOptions] uiOptions: " + uiOptions + ", mask: " + mask);
  
          mUiOptions = (mUiOptions & ~mask) | (uiOptions & mask);
      }
  
      @Override
      public void setContentView(int layoutResId) {
          if (BuildConfig.DEBUG) Log.d(TAG, "[setContentView] layoutResId: " + layoutResId);
  
          if (mContentParent == null) {
              installDecor();
          } else {
              mContentParent.removeAllViews();
          }
          mActivity.getLayoutInflater().inflate(layoutResId, mContentParent);
  
          android.view.Window.Callback callback = mActivity.getWindow().getCallback();
          if (callback != null) {
              callback.onContentChanged();
          }
  
          initActionBar();
      }
  
      @Override
      public void setContentView(View view, ViewGroup.LayoutParams params) {
          if (BuildConfig.DEBUG) Log.d(TAG, "[setContentView] view: " + view + ", params: " + params);
  
          if (mContentParent == null) {
              installDecor();
          } else {
              mContentParent.removeAllViews();
          }
          mContentParent.addView(view, params);
  
          android.view.Window.Callback callback = mActivity.getWindow().getCallback();
          if (callback != null) {
              callback.onContentChanged();
          }
  
          initActionBar();
      }
  
      @Override
      public void addContentView(View view, ViewGroup.LayoutParams params) {
          if (BuildConfig.DEBUG) Log.d(TAG, "[addContentView] view: " + view + ", params: " + params);
  
          if (mContentParent == null) {
              installDecor();
          }
          mContentParent.addView(view, params);
  
          initActionBar();
      }
  
      private void installDecor() {
          if (BuildConfig.DEBUG) Log.d(TAG, "[installDecor]");
  
          if (mDecor == null) {
              mDecor = (ViewGroup)mActivity.getWindow().getDecorView().findViewById(android.R.id.content);
          }
          if (mContentParent == null) {
              //Since we are not operating at the window level we need to take
              //into account the fact that the true decor may have already been
              //initialized and had content attached to it. If that is the case,
              //copy over its children to our new content container.
              List<View> views = null;
              if (mDecor.getChildCount() > 0) {
                  views = new ArrayList<View>(1); //Usually there's only one child
                  for (int i = 0, children = mDecor.getChildCount(); i < children; i++) {
                      View child = mDecor.getChildAt(0);
                      mDecor.removeView(child);
                      views.add(child);
                  }
              }
  
              mContentParent = generateLayout();
  
              //Copy over the old children. See above for explanation.
              if (views != null) {
                  for (View child : views) {
                      mContentParent.addView(child);
                  }
              }
  
              wActionBar = (ActionBarView)mDecor.findViewById(R.id.abs__action_bar);
              if (wActionBar != null) {
                  wActionBar.setWindowCallback(this);
                  if (wActionBar.getTitle() == null) {
                      wActionBar.setWindowTitle(mActivity.getTitle());
                  }
                  if (hasFeature(Window.FEATURE_PROGRESS)) {
                      wActionBar.initProgress();
                  }
                  if (hasFeature(Window.FEATURE_INDETERMINATE_PROGRESS)) {
                      wActionBar.initIndeterminateProgress();
                  }
  
                  //Since we don't require onCreate dispatching, parse for uiOptions here
                  int uiOptions = loadUiOptionsFromManifest(mActivity);
                  if (uiOptions != 0) {
                      mUiOptions = uiOptions;
                  }
  
                  boolean splitActionBar = false;
                  final boolean splitWhenNarrow = (mUiOptions & ActivityInfo.UIOPTION_SPLIT_ACTION_BAR_WHEN_NARROW) != 0;
                  if (splitWhenNarrow) {
                      splitActionBar = getResources_getBoolean(mActivity, R.bool.abs__split_action_bar_is_narrow);
                  } else {
                      splitActionBar = mActivity.getTheme()
                              .obtainStyledAttributes(R.styleable.SherlockTheme)
                              .getBoolean(R.styleable.SherlockTheme_windowSplitActionBar, false);
                  }
                  final ActionBarContainer splitView = (ActionBarContainer)mDecor.findViewById(R.id.abs__split_action_bar);
                  if (splitView != null) {
                      wActionBar.setSplitView(splitView);
                      wActionBar.setSplitActionBar(splitActionBar);
                      wActionBar.setSplitWhenNarrow(splitWhenNarrow);
  
                      mActionModeView = (ActionBarContextView)mDecor.findViewById(R.id.abs__action_context_bar);
                      mActionModeView.setSplitView(splitView);
                      mActionModeView.setSplitActionBar(splitActionBar);
                      mActionModeView.setSplitWhenNarrow(splitWhenNarrow);
                  } else if (splitActionBar) {
                      Log.e(TAG, "Requested split action bar with incompatible window decor! Ignoring request.");
                  }
  
                  // Post the panel invalidate for later; avoid application onCreateOptionsMenu
                  // being called in the middle of onCreate or similar.
                  mDecor.post(new Runnable() {
                      @Override
                      public void run() {
                          //Invalidate if the panel menu hasn't been created before this.
                          if (!mIsDestroyed && !mActivity.isFinishing() && mMenu == null) {
                              dispatchInvalidateOptionsMenu();
                          }
                      }
                  });
              }
          }
      }
  
      private ViewGroup generateLayout() {
          if (BuildConfig.DEBUG) Log.d(TAG, "[generateLayout]");
  
          // Apply data from current theme.
  
          TypedArray a = mActivity.getTheme().obtainStyledAttributes(R.styleable.SherlockTheme);
  
          if (!a.hasValue(R.styleable.SherlockTheme_windowActionBar)) {
              throw new IllegalStateException("You must use Theme.Sherlock, Theme.Sherlock.Light, Theme.Sherlock.Light.DarkActionBar, or a derivative.");
          }
  
          if (a.getBoolean(R.styleable.SherlockTheme_windowNoTitle, false)) {
              requestFeature(Window.FEATURE_NO_TITLE);
          } else if (a.getBoolean(R.styleable.SherlockTheme_windowActionBar, false)) {
              // Don't allow an action bar if there is no title.
              requestFeature(Window.FEATURE_ACTION_BAR);
          }
  
          if (a.getBoolean(R.styleable.SherlockTheme_windowActionBarOverlay, false)) {
              requestFeature(Window.FEATURE_ACTION_BAR_OVERLAY);
          }
  
          if (a.getBoolean(R.styleable.SherlockTheme_windowActionModeOverlay, false)) {
              requestFeature(Window.FEATURE_ACTION_MODE_OVERLAY);
          }
  
          a.recycle();
  
          int layoutResource;
          if (!hasFeature(Window.FEATURE_NO_TITLE)) {
              if (hasFeature(Window.FEATURE_ACTION_BAR_OVERLAY)) {
                  layoutResource = R.layout.abs__screen_action_bar_overlay;
              } else {
                  layoutResource = R.layout.abs__screen_action_bar;
              }
          } else if (hasFeature(Window.FEATURE_ACTION_MODE_OVERLAY) && !hasFeature(Window.FEATURE_NO_TITLE)) {
              layoutResource = R.layout.abs__screen_simple_overlay_action_mode;
          } else {
              layoutResource = R.layout.abs__screen_simple;
          }
  
          if (BuildConfig.DEBUG) Log.d(TAG, "[generateLayout] using screen XML " + mActivity.getResources().getString(layoutResource));
          View in = mActivity.getLayoutInflater().inflate(layoutResource, null);
          mDecor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
  
          ViewGroup contentParent = (ViewGroup)mDecor.findViewById(R.id.abs__content);
          if (contentParent == null) {
              throw new RuntimeException("Couldn't find content container view");
          }
  
          //Make our new child the true content view (for fragments). VERY VOLATILE!
          mDecor.setId(View.NO_ID);
          contentParent.setId(android.R.id.content);
  
          if (hasFeature(Window.FEATURE_INDETERMINATE_PROGRESS)) {
              IcsProgressBar progress = getCircularProgressBar(false);
              if (progress != null) {
                  progress.setIndeterminate(true);
              }
          }
  
          return contentParent;
      }
  
  
      ///////////////////////////////////////////////////////////////////////////
      // Miscellaneous
      ///////////////////////////////////////////////////////////////////////////
  
      /**
       * Determine whether or not the device has a dedicated menu key.
       *
       * @return {@code true} if native menu key is present.
       */
      private boolean isReservingOverflow() {
          if (!mReserveOverflowSet) {
              mReserveOverflow = ActionMenuPresenter.reserveOverflow(mActivity);
              mReserveOverflowSet = true;
          }
          return mReserveOverflow;
      }
  
      private static int loadUiOptionsFromManifest(Activity activity) {
          int uiOptions = 0;
          try {
              final String thisPackage = activity.getClass().getName();
              if (BuildConfig.DEBUG) Log.i(TAG, "Parsing AndroidManifest.xml for " + thisPackage);
  
              final String packageName = activity.getApplicationInfo().packageName;
              final AssetManager am = activity.createPackageContext(packageName, 0).getAssets();
              final XmlResourceParser xml = am.openXmlResourceParser("AndroidManifest.xml");
  
              int eventType = xml.getEventType();
              while (eventType != XmlPullParser.END_DOCUMENT) {
                  if (eventType == XmlPullParser.START_TAG) {
                      String name = xml.getName();
  
                      if ("application".equals(name)) {
                          //Check if the <application> has the attribute
                          if (BuildConfig.DEBUG) Log.d(TAG, "Got <application>");
  
                          for (int i = xml.getAttributeCount() - 1; i >= 0; i--) {
                              if (BuildConfig.DEBUG) Log.d(TAG, xml.getAttributeName(i) + ": " + xml.getAttributeValue(i));
  
                              if ("uiOptions".equals(xml.getAttributeName(i))) {
                                  uiOptions = xml.getAttributeIntValue(i, 0);
                                  break; //out of for loop
                              }
                          }
                      } else if ("activity".equals(name)) {
                          //Check if the <activity> is us and has the attribute
                          if (BuildConfig.DEBUG) Log.d(TAG, "Got <activity>");
                          Integer activityUiOptions = null;
                          String activityPackage = null;
                          boolean isOurActivity = false;
  
                          for (int i = xml.getAttributeCount() - 1; i >= 0; i--) {
                              if (BuildConfig.DEBUG) Log.d(TAG, xml.getAttributeName(i) + ": " + xml.getAttributeValue(i));
  
                              //We need both uiOptions and name attributes
                              String attrName = xml.getAttributeName(i);
                              if ("uiOptions".equals(attrName)) {
                                  activityUiOptions = xml.getAttributeIntValue(i, 0);
                              } else if ("name".equals(attrName)) {
                                  activityPackage = cleanActivityName(packageName, xml.getAttributeValue(i));
                                  if (!thisPackage.equals(activityPackage)) {
                                      break; //out of for loop
                                  }
                                  isOurActivity = true;
                              }
  
                              //Make sure we have both attributes before processing
                              if ((activityUiOptions != null) && (activityPackage != null)) {
                                  //Our activity, uiOptions specified, override with our value
                                  uiOptions = activityUiOptions.intValue();
                              }
                          }
                          if (isOurActivity) {
                              //If we matched our activity but it had no logo don't
                              //do any more processing of the manifest
                              break;
                          }
                      }
                  }
                  eventType = xml.nextToken();
              }
          } catch (Exception e) {
              e.printStackTrace();
          }
          if (BuildConfig.DEBUG) Log.i(TAG, "Returning " + Integer.toHexString(uiOptions));
          return uiOptions;
      }
  
      public static String cleanActivityName(String manifestPackage, String activityName) {
          if (activityName.charAt(0) == '.') {
              //Relative activity name (e.g., android:name=".ui.SomeClass")
              return manifestPackage + activityName;
          }
          if (activityName.indexOf('.', 1) == -1) {
              //Unqualified activity name (e.g., android:name="SomeClass")
              return manifestPackage + "." + activityName;
          }
          //Fully-qualified activity name (e.g., "com.my.package.SomeClass")
          return activityName;
      }
  
      /**
       * Clears out internal reference when the action mode is destroyed.
       */
      private class ActionModeCallbackWrapper implements ActionMode.Callback {
          private final ActionMode.Callback mWrapped;
  
          public ActionModeCallbackWrapper(ActionMode.Callback wrapped) {
              mWrapped = wrapped;
          }
  
          public boolean onCreateActionMode(ActionMode mode, Menu menu) {
              return mWrapped.onCreateActionMode(mode, menu);
          }
  
          public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
              return mWrapped.onPrepareActionMode(mode, menu);
          }
  
          public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
              return mWrapped.onActionItemClicked(mode, item);
          }
  
          public void onDestroyActionMode(ActionMode mode) {
              mWrapped.onDestroyActionMode(mode);
              if (mActionModeView != null) {
                  mActionModeView.setVisibility(View.GONE);
                  mActionModeView.removeAllViews();
              }
              if (mActivity instanceof OnActionModeFinishedListener) {
                  ((OnActionModeFinishedListener)mActivity).onActionModeFinished(mActionMode);
              }
              mActionMode = null;
          }
      }
  
      @Override
      public void ensureActionBar() {
          if (BuildConfig.DEBUG) Log.d(TAG, "[ensureActionBar]");
  
          if (mDecor == null) {
              initActionBar();
          }
      }
  }
  