FileDocCategorySizeDatePackage
PhoneWindow.javaAPI DocAndroid 1.5 API100632Wed May 06 22:42:06 BST 2009com.android.internal.policy.impl

PhoneWindow

public class PhoneWindow extends android.view.Window implements MenuBuilder.Callback
Android-specific Window.

todo: need to pull the generic functionality out into a base class in android.widget.

Fields Summary
private static final String
TAG
private static final boolean
SWEEP_OPEN_MENU
ContextMenuCallback
mContextMenuCallback
Simple callback used by the context menu and its submenus. The options menu submenus do not use this (their behavior is more complex).
private DecorView
mDecor
private android.view.ViewGroup
mContentParent
private boolean
mIsFloating
private android.view.LayoutInflater
mLayoutInflater
private android.widget.TextView
mTitleView
private DrawableFeatureState[]
mDrawables
private PanelFeatureState[]
mPanels
private PanelFeatureState
mPreparedPanel
The panel that is prepared or opened (the most recent one if there are multiple panels). Shortcuts will go to this panel. It gets set in {@link #preparePanel} and cleared in {@link #closePanel}.
private int
mPanelChordingKey
The keycode that is currently held down (as a modifier) for chording. If this is 0, there is no key held down.
private android.widget.ImageView
mLeftIconView
private android.widget.ImageView
mRightIconView
private android.widget.ProgressBar
mCircularProgressBar
private android.widget.ProgressBar
mHorizontalProgressBar
private int
mBackgroundResource
private android.graphics.drawable.Drawable
mBackgroundDrawable
private int
mFrameResource
private int
mTextColor
private CharSequence
mTitle
private int
mTitleColor
private com.android.internal.view.menu.ContextMenuBuilder
mContextMenu
private com.android.internal.view.menu.MenuDialogHelper
mContextMenuHelper
private int
mVolumeControlStreamType
private long
mVolumeKeyUpTime
private android.app.KeyguardManager
mKeyguardManager
private android.telephony.TelephonyManager
mTelephonyManager
private boolean
mSearchKeyDownReceived
private boolean
mKeycodeCallTimeoutActive
private boolean
mKeycodeCameraTimeoutActive
static final int
MSG_MENU_LONG_PRESS
static final int
MSG_MENU_LONG_PRESS_COMPLETE
static final int
MSG_CALL_LONG_PRESS
static final int
MSG_CALL_LONG_PRESS_COMPLETE
static final int
MSG_CAMERA_LONG_PRESS
static final int
MSG_CAMERA_LONG_PRESS_COMPLETE
static final int
MSG_SEARCH_LONG_PRESS
static final int
MSG_SEARCH_LONG_PRESS_COMPLETE
private final android.os.Handler
mKeycodeMenuTimeoutHandler
private static final String
FOCUSED_ID_TAG
private static final String
VIEWS_TAG
private static final String
PANELS_TAG
Constructors Summary
public PhoneWindow(android.content.Context context)


       
        super(context);
        mLayoutInflater = LayoutInflater.from(context);
    
Methods Summary
public voidaddContentView(android.view.View view, ViewGroup.LayoutParams params)

        if (mContentParent == null) {
            installDecor();
        }
        mContentParent.addView(view, params);
        final Callback cb = getCallback();
        if (cb != null) {
            cb.onContentChanged();
        }
    
private voidcallOnPanelClosed(int featureId, com.android.internal.policy.impl.PhoneWindow$PanelFeatureState panel, android.view.Menu menu)
Helper method for calling the {@link Callback#onPanelClosed(int, Menu)} callback. This method will grab whatever extra state is needed for the callback that isn't given in the parameters. If the panel is not open, this will not perform the callback.

param
featureId Feature ID of the panel that was closed. Must be given.
param
panel Panel that was closed. Optional but useful if there is no menu given.
param
menu The menu that was closed. Optional, but give if you have.

        final Callback cb = getCallback();
        if (cb == null)
            return;

        // Try to get a menu
        if (menu == null) {
            // Need a panel to grab the menu, so try to get that
            if (panel == null) {
                if ((featureId >= 0) && (featureId < mPanels.length)) {
                    panel = mPanels[featureId];
                }
            }

            if (panel != null) {
                // menu still may be null, which is okay--we tried our best
                menu = panel.menu;
            }
        }

        // If the panel is not open, do not callback
        if ((panel != null) && (!panel.isOpen))
            return;

        cb.onPanelClosed(featureId, menu);
    
private static voidclearMenuViews(com.android.internal.policy.impl.PhoneWindow$PanelFeatureState st)


        // This can be called on config changes, so we should make sure
        // the views will be reconstructed based on the new orientation, etc.

        // Allow the callback to create a new panel view
        st.createdPanelView = null;

        // Causes the decor view to be recreated
        st.refreshDecorView = true;

        ((MenuBuilder) st.menu).clearMenuViews();
    
public final voidcloseAllPanels()

        final ViewManager wm = getWindowManager();
        if (wm == null) {
            return;
        }

        final PanelFeatureState[] panels = mPanels;
        final int N = panels != null ? panels.length : 0;
        for (int i = 0; i < N; i++) {
            final PanelFeatureState panel = panels[i];
            if (panel != null) {
                closePanel(panel, true);
            }
        }

        closeContextMenu();
    
private synchronized voidcloseContextMenu()
Closes the context menu. This notifies the menu logic of the close, along with dismissing it from the UI.

        if (mContextMenu != null) {
            mContextMenu.close();
            dismissContextMenu();
        }
    
public final voidclosePanel(int featureId)

        if (featureId == FEATURE_CONTEXT_MENU) {
            closeContextMenu();
        } else {
            closePanel(getPanelState(featureId, true), true);
        }
    
public final voidclosePanel(com.android.internal.policy.impl.PhoneWindow$PanelFeatureState st, boolean doCallback)
Closes the given panel.

param
st The panel to be closed.
param
doCallback Whether to notify the callback that the panel was closed. If the panel is in the process of re-opening or opening another panel (e.g., menu opening a sub menu), the callback should not happen and this variable should be false. In addition, this method internally will only perform the callback if the panel is open.

        // System.out.println("Close panel: isOpen=" + st.isOpen);
        final ViewManager wm = getWindowManager();
        if ((wm != null) && st.isOpen) {
            if (st.decorView != null) {
                wm.removeView(st.decorView);
                // Log.v(TAG, "Removing main menu from window manager.");
            }

            if (doCallback) {
                callOnPanelClosed(st.featureId, st, null);
            }
        }
        st.isPrepared = false;
        st.isHandled = false;
        st.isOpen = false;

        // This view is no longer shown, so null it out
        st.shownPanelView = null;

        if (st.isInExpandedMode) {
            // Next time the menu opens, it should not be in expanded mode, so
            // force a refresh of the decor
            st.refreshDecorView = true;
            st.isInExpandedMode = false;
        }

        if (mPreparedPanel == st) {
            mPreparedPanel = null;
            mPanelChordingKey = 0;
        }
    
private synchronized voiddismissContextMenu()
Dismisses just the context menu UI. To close the context menu, use {@link #closeContextMenu()}.

        mContextMenu = null;

        if (mContextMenuHelper != null) {
            mContextMenuHelper.dismiss();
            mContextMenuHelper = null;
        }
    
public com.android.internal.policy.impl.PhoneWindow$PanelFeatureStatefindMenuPanel(android.view.Menu menu)

        final PanelFeatureState[] panels = mPanels;
        final int N = panels != null ? panels.length : 0;
        for (int i = 0; i < N; i++) {
            final PanelFeatureState panel = panels[i];
            if (panel != null && panel.menu == menu) {
                return panel;
            }
        }
        return null;
    
protected com.android.internal.policy.impl.PhoneWindow$DecorViewgenerateDecor()

        return new DecorView(getContext(), -1);
    
protected android.view.ViewGroupgenerateLayout(com.android.internal.policy.impl.PhoneWindow$DecorView decor)

        // Apply data from current theme.

        TypedArray a = getWindowStyle();

        if (false) {
            System.out.println("From style:");
            String s = "Attrs:";
            for (int i = 0; i < com.android.internal.R.styleable.Window.length; i++) {
                s = s + " " + Integer.toHexString(com.android.internal.R.styleable.Window[i]) + "="
                        + a.getString(i);
            }
            System.out.println(s);
        }

        mIsFloating = a.getBoolean(com.android.internal.R.styleable.Window_windowIsFloating, false);
        int flagsToUpdate = (FLAG_LAYOUT_IN_SCREEN|FLAG_LAYOUT_INSET_DECOR)
                & (~getForcedWindowFlags());
        if (mIsFloating) {
            setLayout(WRAP_CONTENT, WRAP_CONTENT);
            setFlags(0, flagsToUpdate);
        } else {
            setFlags(FLAG_LAYOUT_IN_SCREEN|FLAG_LAYOUT_INSET_DECOR, flagsToUpdate);
        }

        if (a.getBoolean(com.android.internal.R.styleable.Window_windowNoTitle, false)) {
            requestFeature(FEATURE_NO_TITLE);
        }

        if (a.getBoolean(com.android.internal.R.styleable.Window_windowFullscreen, false)) {
            setFlags(FLAG_FULLSCREEN, FLAG_FULLSCREEN&(~getForcedWindowFlags()));
        }

        WindowManager.LayoutParams params = getAttributes();

        if (!hasSoftInputMode()) {
            params.softInputMode = a.getInt(
                    com.android.internal.R.styleable.Window_windowSoftInputMode,
                    params.softInputMode);
        }

        if (a.getBoolean(com.android.internal.R.styleable.Window_backgroundDimEnabled,
                mIsFloating)) {
            /* All dialogs should have the window dimmed */
            if ((getForcedWindowFlags()&WindowManager.LayoutParams.FLAG_DIM_BEHIND) == 0) {
                params.flags |= WindowManager.LayoutParams.FLAG_DIM_BEHIND;
            }
            params.dimAmount = a.getFloat(
                    android.R.styleable.Window_backgroundDimAmount, 0.5f);
        }

        if (params.windowAnimations == 0) {
            params.windowAnimations = a.getResourceId(
                    com.android.internal.R.styleable.Window_windowAnimationStyle, 0);
        }

        // The rest are only done if this window is not embedded; otherwise,
        // the values are inherited from our container.
        if (getContainer() == null) {
            if (mBackgroundDrawable == null) {
                if (mBackgroundResource == 0) {
                    mBackgroundResource = a.getResourceId(
                            com.android.internal.R.styleable.Window_windowBackground, 0);
                }
                if (mFrameResource == 0) {
                    mFrameResource = a.getResourceId(com.android.internal.R.styleable.Window_windowFrame, 0);
                }
                if (false) {
                    System.out.println("Background: "
                            + Integer.toHexString(mBackgroundResource) + " Frame: "
                            + Integer.toHexString(mFrameResource));
                }
            }
            mTextColor = a.getColor(com.android.internal.R.styleable.Window_textColor, 0xFF000000);
        }

        // Inflate the window decor.

        int layoutResource;
        int features = getLocalFeatures();
        // System.out.println("Features: 0x" + Integer.toHexString(features));
        if ((features & ((1 << FEATURE_LEFT_ICON) | (1 << FEATURE_RIGHT_ICON))) != 0) {
            if (mIsFloating) {
                layoutResource = com.android.internal.R.layout.dialog_title_icons;
            } else {
                layoutResource = com.android.internal.R.layout.screen_title_icons;
            }
            // System.out.println("Title Icons!");
        } else if ((features & ((1 << FEATURE_PROGRESS) | (1 << FEATURE_INDETERMINATE_PROGRESS))) != 0) {
            // Special case for a window with only a progress bar (and title).
            // XXX Need to have a no-title version of embedded windows.
            layoutResource = com.android.internal.R.layout.screen_progress;
            // System.out.println("Progress!");
        } else if ((features & (1 << FEATURE_CUSTOM_TITLE)) != 0) {
            // Special case for a window with a custom title.
            // If the window is floating, we need a dialog layout
            if (mIsFloating) {
                layoutResource = com.android.internal.R.layout.dialog_custom_title;
            } else {
                layoutResource = com.android.internal.R.layout.screen_custom_title;
            }
        } else if ((features & (1 << FEATURE_NO_TITLE)) == 0) {
            // If no other features and not embedded, only need a title.
            // If the window is floating, we need a dialog layout
            if (mIsFloating) {
                layoutResource = com.android.internal.R.layout.dialog_title;
            } else {
                layoutResource = com.android.internal.R.layout.screen_title;
            }
            // System.out.println("Title!");
        } else {
            // Embedded, so no decoration is needed.
            layoutResource = com.android.internal.R.layout.screen_simple;
            // System.out.println("Simple!");
        }

        mDecor.startChanging();

        View in = mLayoutInflater.inflate(layoutResource, null);
        decor.addView(in, new ViewGroup.LayoutParams(FILL_PARENT, FILL_PARENT));

        ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
        if (contentParent == null) {
            throw new RuntimeException("Window couldn't find content container view");
        }

        if ((features & (1 << FEATURE_INDETERMINATE_PROGRESS)) != 0) {
            ProgressBar progress = getCircularProgressBar(false);
            if (progress != null) {
                progress.setIndeterminate(true);
            }
        }

        // Remaining setup -- of background and title -- that only applies
        // to top-level windows.
        if (getContainer() == null) {
            Drawable drawable = mBackgroundDrawable;
            if (mBackgroundResource != 0) {
                drawable = getContext().getResources().getDrawable(mBackgroundResource);
            }
            mDecor.setWindowBackground(drawable);
            drawable = null;
            if (mFrameResource != 0) {
                drawable = getContext().getResources().getDrawable(mFrameResource);
            }
            mDecor.setWindowFrame(drawable);

            // System.out.println("Text=" + Integer.toHexString(mTextColor) +
            // " Sel=" + Integer.toHexString(mTextSelectedColor) +
            // " Title=" + Integer.toHexString(mTitleColor));

            if (mTitleColor == 0) {
                mTitleColor = mTextColor;
            }

            if (mTitle != null) {
                setTitle(mTitle);
            }
            setTitleColor(mTitleColor);
        }

        mDecor.finishChanging();

        return contentParent;
    
private android.widget.ProgressBargetCircularProgressBar(boolean shouldInstallDecor)

        if (mCircularProgressBar != null) {
            return mCircularProgressBar;
        }
        if (mContentParent == null && shouldInstallDecor) {
            installDecor();
        }
        mCircularProgressBar = (ProgressBar)findViewById(com.android.internal.R.id.progress_circular);
        mCircularProgressBar.setVisibility(View.INVISIBLE);
        return mCircularProgressBar;
    
public android.view.ViewgetCurrentFocus()

        return mDecor != null ? mDecor.findFocus() : null;
    
public final android.view.ViewgetDecorView()

        if (mDecor == null) {
            installDecor();
        }
        return mDecor;
    
private com.android.internal.policy.impl.PhoneWindow$DrawableFeatureStategetDrawableState(int featureId, boolean required)

        if ((getFeatures() & (1 << featureId)) == 0) {
            if (!required) {
                return null;
            }
            throw new RuntimeException("The feature has not been requested");
        }

        DrawableFeatureState[] ar;
        if ((ar = mDrawables) == null || ar.length <= featureId) {
            DrawableFeatureState[] nar = new DrawableFeatureState[featureId + 1];
            if (ar != null) {
                System.arraycopy(ar, 0, nar, 0, ar.length);
            }
            mDrawables = ar = nar;
        }

        DrawableFeatureState st = ar[featureId];
        if (st == null) {
            ar[featureId] = st = new DrawableFeatureState(featureId);
        }
        return st;
    
private android.widget.ProgressBargetHorizontalProgressBar(boolean shouldInstallDecor)

        if (mHorizontalProgressBar != null) {
            return mHorizontalProgressBar;
        }
        if (mContentParent == null && shouldInstallDecor) {
            installDecor();
        }
        mHorizontalProgressBar = (ProgressBar)findViewById(com.android.internal.R.id.progress_horizontal);
        mHorizontalProgressBar.setVisibility(View.INVISIBLE);
        return mHorizontalProgressBar;
    
private android.app.KeyguardManagergetKeyguardManager()

return
A handle to the keyguard manager.

        if (mKeyguardManager == null) {
            mKeyguardManager = (KeyguardManager) getContext().getSystemService(Context.KEYGUARD_SERVICE);
        }
        return mKeyguardManager;
    
public android.view.LayoutInflatergetLayoutInflater()
Return a LayoutInflater instance that can be used to inflate XML view layout resources for use in this Window.

return
LayoutInflater The shared LayoutInflater.

        return mLayoutInflater;
    
private android.widget.ImageViewgetLeftIconView()

        if (mLeftIconView != null) {
            return mLeftIconView;
        }
        if (mContentParent == null) {
            installDecor();
        }
        return (mLeftIconView = (ImageView)findViewById(com.android.internal.R.id.left_icon));
    
private com.android.internal.policy.impl.PhoneWindow$PanelFeatureStategetPanelState(int featureId, boolean required)
Gets a panel's state based on its feature ID.

param
featureId The feature ID of the panel.
param
required Whether the panel is required (if it is required and it isn't in our features, this throws an exception).
return
The panel state.

        return getPanelState(featureId, required, null);
    
private com.android.internal.policy.impl.PhoneWindow$PanelFeatureStategetPanelState(int featureId, boolean required, com.android.internal.policy.impl.PhoneWindow$PanelFeatureState convertPanelState)
Gets a panel's state based on its feature ID.

param
featureId The feature ID of the panel.
param
required Whether the panel is required (if it is required and it isn't in our features, this throws an exception).
param
convertPanelState Optional: If the panel state does not exist, use this as the panel state.
return
The panel state.

        if ((getFeatures() & (1 << featureId)) == 0) {
            if (!required) {
                return null;
            }
            throw new RuntimeException("The feature has not been requested");
        }

        PanelFeatureState[] ar;
        if ((ar = mPanels) == null || ar.length <= featureId) {
            PanelFeatureState[] nar = new PanelFeatureState[featureId + 1];
            if (ar != null) {
                System.arraycopy(ar, 0, nar, 0, ar.length);
            }
            mPanels = ar = nar;
        }

        PanelFeatureState st = ar[featureId];
        if (st == null) {
            ar[featureId] = st = (convertPanelState != null)
                    ? convertPanelState
                    : new PanelFeatureState(featureId);
        }
        return st;
    
private android.widget.ImageViewgetRightIconView()

        if (mRightIconView != null) {
            return mRightIconView;
        }
        if (mContentParent == null) {
            installDecor();
        }
        return (mRightIconView = (ImageView)findViewById(com.android.internal.R.id.right_icon));
    
public intgetVolumeControlStream()

        return mVolumeControlStreamType;
    
private voidhideProgressBars(android.widget.ProgressBar horizontalProgressBar, android.widget.ProgressBar spinnyProgressBar)

        final int features = getLocalFeatures();
        Animation anim = AnimationUtils.loadAnimation(getContext(), com.android.internal.R.anim.fade_out);
        anim.setDuration(1000);
        if ((features & (1 << FEATURE_INDETERMINATE_PROGRESS)) != 0 &&
                spinnyProgressBar.getVisibility() == View.VISIBLE) {
            spinnyProgressBar.startAnimation(anim);
            spinnyProgressBar.setVisibility(View.INVISIBLE);
        }
        if ((features & (1 << FEATURE_PROGRESS)) != 0 &&
                horizontalProgressBar.getVisibility() == View.VISIBLE) {
            horizontalProgressBar.startAnimation(anim);
            horizontalProgressBar.setVisibility(View.INVISIBLE);
        }
    
protected booleaninitializePanelContent(com.android.internal.policy.impl.PhoneWindow$PanelFeatureState st)
Initializes the panel associated with the panel feature state. You must at the very least set PanelFeatureState.panel to the View implementing its contents. The default implementation gets the panel from the menu.

param
st The panel state being initialized.
return
Whether the initialization was successful.


        if (st.createdPanelView != null) {
            st.shownPanelView = st.createdPanelView;
            return true;
        }

        final MenuBuilder menu = (MenuBuilder)st.menu;
        if (menu == null) {
            return false;
        }

        st.shownPanelView = menu.getMenuView((st.isInExpandedMode) ? MenuBuilder.TYPE_EXPANDED
                : MenuBuilder.TYPE_ICON, st.decorView);

        if (st.shownPanelView != null) {
            // Use the menu View's default animations if it has any
            final int defaultAnimations = ((MenuView) st.shownPanelView).getWindowAnimations();
            if (defaultAnimations != 0) {
                st.windowAnimations = defaultAnimations;
            }
            return true;
        } else {
            return false;
        }
    
protected booleaninitializePanelDecor(com.android.internal.policy.impl.PhoneWindow$PanelFeatureState st)
Perform initial setup of a panel. This should at the very least set the style information in the PanelFeatureState and must set PanelFeatureState.decor to the panel's window decor view.

param
st The panel being initialized.

        st.decorView = new DecorView(getContext(), st.featureId);
        st.gravity = Gravity.CENTER | Gravity.BOTTOM;
        st.setStyle(getContext());

        return true;
    
protected booleaninitializePanelMenu(com.android.internal.policy.impl.PhoneWindow$PanelFeatureState st)
Initializes the menu associated with the given panel feature state. You must at the very least set PanelFeatureState.menu to the Menu to be associated with the given panel state. The default implementation creates a new menu for the panel state.

param
st The panel whose menu is being initialized.
return
Whether the initialization was successful.

        final MenuBuilder menu = new MenuBuilder(getContext());

        menu.setCallback(this);
        st.setMenu(menu);

        return true;
    
private voidinstallDecor()

        if (mDecor == null) {
            mDecor = generateDecor();
            mDecor.setIsRootNamespace(true);
        }
        if (mContentParent == null) {
            mContentParent = generateLayout(mDecor);

            mTitleView = (TextView)findViewById(com.android.internal.R.id.title);
            if (mTitleView != null) {
                if ((getLocalFeatures() & (1 << FEATURE_NO_TITLE)) != 0) {
                    View titleContainer = findViewById(com.android.internal.R.id.title_container);
                    if (titleContainer != null) {
                        titleContainer.setVisibility(View.GONE);
                    } else {
                        mTitleView.setVisibility(View.GONE);
                    }
                    if (mContentParent instanceof FrameLayout) {
                        ((FrameLayout)mContentParent).setForeground(null);
                    }
                } else {
                    mTitleView.setText(mTitle);
                }
            }
        }
    
public booleanisFloating()

        return mIsFloating;
    
public booleanisShortcutKey(int keyCode, android.view.KeyEvent event)

        PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, true);
        return st.menu != null && st.menu.isShortcutKey(keyCode, event);
    
private booleanlaunchDefaultSearch()
Helper method for adding launch-search to most applications. Opens the search window using default settings.

return
true if search window opened

        final Callback cb = getCallback();
        if (cb == null) {
            return false;
        } else {
            return cb.onSearchRequested();
        }
    
private android.graphics.drawable.DrawableloadImageURI(android.net.Uri uri)

        try {
            return Drawable.createFromStream(
                    getContext().getContentResolver().openInputStream(uri), null);
        } catch (Exception e) {
            Log.w(TAG, "Unable to open content: " + uri);
        }
        return null;
    
protected voidonActive()

    
public voidonCloseMenu(com.android.internal.view.menu.MenuBuilder menu, boolean allMenusAreClosing)

        final PanelFeatureState panel = findMenuPanel(menu);
        if (panel != null) {
            // Close the panel and only do the callback if the menu is being
            // closed
            // completely, not if opening a sub menu
            closePanel(panel, allMenusAreClosing);
        }
    
public voidonCloseSubMenu(com.android.internal.view.menu.SubMenuBuilder subMenu)

        final Menu parentMenu = subMenu.getRootMenu();
        final PanelFeatureState panel = findMenuPanel(parentMenu);

        // Callback
        if (panel != null) {
            callOnPanelClosed(panel.featureId, panel, parentMenu);
            closePanel(panel, true);
        }
    
public voidonConfigurationChanged(android.content.res.Configuration newConfig)

        PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, false);
        if ((st != null) && (st.menu != null)) {
            final MenuBuilder menuBuilder = (MenuBuilder) st.menu;

            if (st.isOpen) {
                // Freeze state
                final Bundle state = new Bundle();
                menuBuilder.saveHierarchyState(state);

                // Remove the menu views since they need to be recreated
                // according to the new configuration
                clearMenuViews(st);

                // Re-open the same menu
                reopenMenu(false);

                // Restore state
                menuBuilder.restoreHierarchyState(state);

            } else {
                // Clear menu views so on next menu opening, it will use
                // the proper layout
                clearMenuViews(st);
            }
        }

    
protected voidonDrawableChanged(int featureId, android.graphics.drawable.Drawable drawable, int alpha)
Called when a Drawable feature changes, for the window to update its graphics.

param
featureId The feature being changed.
param
drawable The new Drawable to show, or null if none.
param
alpha The new alpha blending of the Drawable.

        ImageView view;
        if (featureId == FEATURE_LEFT_ICON) {
            view = getLeftIconView();
        } else if (featureId == FEATURE_RIGHT_ICON) {
            view = getRightIconView();
        } else {
            return;
        }

        if (drawable != null) {
            drawable.setAlpha(alpha);
            view.setImageDrawable(drawable);
            view.setVisibility(View.VISIBLE);
        } else {
            view.setVisibility(View.GONE);
        }
    
protected voidonIntChanged(int featureId, int value)
Called when an int feature changes, for the window to update its graphics.

param
featureId The feature being changed.
param
value The new integer value.

        if (featureId == FEATURE_PROGRESS || featureId == FEATURE_INDETERMINATE_PROGRESS) {
            updateProgressBars(value);
        } else if (featureId == FEATURE_CUSTOM_TITLE) {
            FrameLayout titleContainer = (FrameLayout) findViewById(com.android.internal.R.id.title_container);
            if (titleContainer != null) {
                mLayoutInflater.inflate(value, titleContainer);
            }
        }
    
protected booleanonKeyDown(int featureId, int keyCode, android.view.KeyEvent event)
A key was pressed down and not handled by anything else in the window.

see
#onKeyUp
see
android.view.KeyEvent

        switch (keyCode) {
            case KeyEvent.KEYCODE_VOLUME_UP:
            case KeyEvent.KEYCODE_VOLUME_DOWN: {
                AudioManager audioManager = (AudioManager) getContext().getSystemService(
                        Context.AUDIO_SERVICE);
                if (audioManager != null) {
                    /*
                     * Adjust the volume in on key down since it is more
                     * responsive to the user.
                     */
                    audioManager.adjustSuggestedStreamVolume(
                            keyCode == KeyEvent.KEYCODE_VOLUME_UP
                                    ? AudioManager.ADJUST_RAISE
                                    : AudioManager.ADJUST_LOWER,
                            mVolumeControlStreamType,
                            AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_VIBRATE);
                }
                return true;
            }


            case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
                /* Suppress PLAYPAUSE toggle when phone is ringing or in-call
                 * to avoid music playback */
                if (mTelephonyManager == null) {
                    mTelephonyManager = (TelephonyManager) getContext().getSystemService(
                            Context.TELEPHONY_SERVICE);
                }
                if (mTelephonyManager != null &&
                        mTelephonyManager.getCallState() != TelephonyManager.CALL_STATE_IDLE) {
                    return true;  // suppress key event
                }
            case KeyEvent.KEYCODE_MUTE:
            case KeyEvent.KEYCODE_HEADSETHOOK:
            case KeyEvent.KEYCODE_MEDIA_STOP:
            case KeyEvent.KEYCODE_MEDIA_NEXT:
            case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
            case KeyEvent.KEYCODE_MEDIA_REWIND:
            case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: {
                Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON, null);
                intent.putExtra(Intent.EXTRA_KEY_EVENT, event);
                getContext().sendOrderedBroadcast(intent, null);
                return true;
            }

            case KeyEvent.KEYCODE_CAMERA: {
                if (getKeyguardManager().inKeyguardRestrictedInputMode()) {
                    break;
                }
                if (event.getRepeatCount() > 0) break;
                mKeycodeCameraTimeoutActive = true;
                mKeycodeMenuTimeoutHandler.removeMessages(MSG_CAMERA_LONG_PRESS);
                Message message = mKeycodeMenuTimeoutHandler.obtainMessage(MSG_CAMERA_LONG_PRESS);
                message.obj = event;
                mKeycodeMenuTimeoutHandler.sendMessageDelayed(message,
                        ViewConfiguration.getLongPressTimeout());
                return true;
            }

            case KeyEvent.KEYCODE_MENU: {
                if (event.getRepeatCount() > 0) break;
                onKeyDownPanel((featureId < 0) ? FEATURE_OPTIONS_PANEL : featureId, event);
                return true;
            }

            case KeyEvent.KEYCODE_BACK: {
                if (event.getRepeatCount() > 0) break;
                if (featureId < 0) break;
                if (featureId == FEATURE_OPTIONS_PANEL) {
                    PanelFeatureState st = getPanelState(featureId, false);
                    if (st != null && st.isInExpandedMode) {
                        // If the user is in an expanded menu and hits back, it
                        // should go back to the icon menu
                        reopenMenu(true);
                        return true;
                    }
                }
                closePanel(featureId);
                return true;
            }

            case KeyEvent.KEYCODE_CALL: {
                if (getKeyguardManager().inKeyguardRestrictedInputMode()) {
                    break;
                }
                if (event.getRepeatCount() > 0) break;
                mKeycodeCallTimeoutActive = true;
                mKeycodeMenuTimeoutHandler.removeMessages(MSG_CALL_LONG_PRESS);
                mKeycodeMenuTimeoutHandler.sendMessageDelayed(
                        mKeycodeMenuTimeoutHandler.obtainMessage(MSG_CALL_LONG_PRESS),
                        ViewConfiguration.getLongPressTimeout());
                return true;
            }

            case KeyEvent.KEYCODE_SEARCH: {
                if (event.getRepeatCount() == 0) {
                    mSearchKeyDownReceived = true;
                    Configuration config = getContext().getResources().getConfiguration(); 
                    if (config.keyboard == Configuration.KEYBOARD_NOKEYS
                            || config.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_YES) {
                        // If this device does not have a hardware keyboard,
                        // or that keyboard is hidden, then we can't use the
                        // search key for chording to perform shortcuts;
                        // instead, we will let the user long press,
                        mKeycodeMenuTimeoutHandler.removeMessages(MSG_SEARCH_LONG_PRESS);
                        mKeycodeMenuTimeoutHandler.sendMessageDelayed(
                                mKeycodeMenuTimeoutHandler.obtainMessage(MSG_SEARCH_LONG_PRESS),
                                ViewConfiguration.getLongPressTimeout());
                    }
                    return true;
                }
                break;
            }
        }

        return false;
    
public final booleanonKeyDownPanel(int featureId, android.view.KeyEvent event)
Called when the panel key is pushed down.

param
featureId The feature ID of the relevant panel (defaults to FEATURE_OPTIONS_PANEL}.
param
event The key event.
return
Whether the key was handled.

        // The panel key was pushed, so set the chording key
        mPanelChordingKey = event.getKeyCode();

        PanelFeatureState st = getPanelState(featureId, true);
        if (!st.isOpen) {
            if (getContext().getResources().getConfiguration().keyboard
                    == Configuration.KEYBOARD_NOKEYS) {
                mKeycodeMenuTimeoutHandler.removeMessages(MSG_MENU_LONG_PRESS);
                mKeycodeMenuTimeoutHandler.sendMessageDelayed(
                        mKeycodeMenuTimeoutHandler.obtainMessage(MSG_MENU_LONG_PRESS),
                        ViewConfiguration.getLongPressTimeout());
            }
            return preparePanel(st, event);
        }

        return false;
    
protected booleanonKeyUp(int featureId, int keyCode, android.view.KeyEvent event)
A key was released and not handled by anything else in the window.

see
#onKeyDown
see
android.view.KeyEvent

        switch (keyCode) {
            case KeyEvent.KEYCODE_VOLUME_UP:
            case KeyEvent.KEYCODE_VOLUME_DOWN: {
                AudioManager audioManager = (AudioManager) getContext().getSystemService(
                        Context.AUDIO_SERVICE);
                if (audioManager != null) {
                    /*
                     * Play a sound. This is done on key up since we don't want the
                     * sound to play when a user holds down volume down to mute.
                     */
                    audioManager.adjustSuggestedStreamVolume(
                            AudioManager.ADJUST_SAME,
                            mVolumeControlStreamType,
                            AudioManager.FLAG_PLAY_SOUND);
                    mVolumeKeyUpTime = SystemClock.uptimeMillis();
                }
                return true;
            }

            case KeyEvent.KEYCODE_MENU: {
                onKeyUpPanel(featureId < 0 ? FEATURE_OPTIONS_PANEL : featureId,
                        event);
                return true;
            }

            case KeyEvent.KEYCODE_HEADSETHOOK:
            case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
            case KeyEvent.KEYCODE_MEDIA_STOP:
            case KeyEvent.KEYCODE_MEDIA_NEXT:
            case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
            case KeyEvent.KEYCODE_MEDIA_REWIND:
            case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: {
                Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON, null);
                intent.putExtra(Intent.EXTRA_KEY_EVENT, event);
                getContext().sendOrderedBroadcast(intent, null);
                return true;
            }

            case KeyEvent.KEYCODE_CAMERA: {
                if (getKeyguardManager().inKeyguardRestrictedInputMode()) {
                    break;
                }
                if (event.getRepeatCount() > 0) break; // Can a key up event repeat?
                mKeycodeMenuTimeoutHandler.removeMessages(MSG_CAMERA_LONG_PRESS);
                if (!mKeycodeCameraTimeoutActive) break;
                mKeycodeCameraTimeoutActive = false;
                // Add short press behavior here if desired
                return true;
            }

            case KeyEvent.KEYCODE_CALL: {
                if (getKeyguardManager().inKeyguardRestrictedInputMode()) {
                    break;
                }
                if (event.getRepeatCount() > 0) break;
                mKeycodeMenuTimeoutHandler.removeMessages(MSG_CALL_LONG_PRESS);
                if (!mKeycodeCallTimeoutActive) break;
                mKeycodeCallTimeoutActive = false;
                startCallActivity();
                return true;
            }

            case KeyEvent.KEYCODE_SEARCH: {
                /*
                 * Do this in onKeyUp since the Search key is also used for
                 * chording quick launch shortcuts.
                 */
                if (getKeyguardManager().inKeyguardRestrictedInputMode() ||
                        !mSearchKeyDownReceived) {
                    mSearchKeyDownReceived = false;
                    break;
                }
                mSearchKeyDownReceived = false;
                launchDefaultSearch();
                return true;
            }
        }

        return false;
    
public final voidonKeyUpPanel(int featureId, android.view.KeyEvent event)
Called when the panel key is released.

param
featureId The feature ID of the relevant panel (defaults to FEATURE_OPTIONS_PANEL}.
param
event The key event.

        // The panel key was released, so clear the chording key
        if (mPanelChordingKey != 0) {
            mPanelChordingKey = 0;
            mKeycodeMenuTimeoutHandler.removeMessages(MSG_MENU_LONG_PRESS);

            boolean playSoundEffect = false;
            PanelFeatureState st = getPanelState(featureId, true);
            if (st.isOpen || st.isHandled) {

                // Play the sound effect if the user closed an open menu (and not if
                // they just released a menu shortcut)
                playSoundEffect = st.isOpen;

                // Close menu
                closePanel(st, true);

            } else if (st.isPrepared) {

                // Write 'menu opened' to event log
                EventLog.writeEvent(50001, 0);

                // Show menu
                openPanel(st, event);

                playSoundEffect = true;
            }

            if (playSoundEffect) {
                AudioManager audioManager = (AudioManager) getContext().getSystemService(
                        Context.AUDIO_SERVICE);
                if (audioManager != null) {
                    audioManager.playSoundEffect(AudioManager.FX_KEY_CLICK);
                } else {
                    Log.w(TAG, "Couldn't get audio manager");
                }
            }
        }
    
public booleanonMenuItemSelected(com.android.internal.view.menu.MenuBuilder menu, android.view.MenuItem item)

        final Callback cb = getCallback();
        if (cb != null) {
            final PanelFeatureState panel = findMenuPanel(menu.getRootMenu());
            if (panel != null) {
                return cb.onMenuItemSelected(panel.featureId, item);
            }
        }
        return false;
    
public voidonMenuModeChange(com.android.internal.view.menu.MenuBuilder menu)

        reopenMenu(true);
    
public booleanonSubMenuSelected(com.android.internal.view.menu.SubMenuBuilder subMenu)

        if (!subMenu.hasVisibleItems()) {
            return true;
        }

        // The window manager will give us a valid window token
        new MenuDialogHelper(subMenu).show(null);

        return true;
    
public final voidopenPanel(int featureId, android.view.KeyEvent event)

        openPanel(getPanelState(featureId, true), event);
    
private voidopenPanel(com.android.internal.policy.impl.PhoneWindow$PanelFeatureState st, android.view.KeyEvent event)

        // System.out.println("Open panel: isOpen=" + st.isOpen);

        // Already open, return
        if (st.isOpen) {
            return;
        }

        Callback cb = getCallback();
        if ((cb != null) && (!cb.onMenuOpened(st.featureId, st.menu))) {
            // Callback doesn't want the menu to open, reset any state
            closePanel(st, true);
            return;
        }

        final WindowManager wm = getWindowManager();
        if (wm == null) {
            return;
        }

        // Prepare panel (should have been done before, but just in case)
        if (!preparePanel(st, event)) {
            return;
        }

        if (st.decorView == null || st.refreshDecorView) {
            if (st.decorView == null) {
                // Initialize the panel decor, this will populate st.decorView
                if (!initializePanelDecor(st) || (st.decorView == null))
                    return;
            } else if (st.refreshDecorView && (st.decorView.getChildCount() > 0)) {
                // Decor needs refreshing, so remove its views
                st.decorView.removeAllViews();
            }

            // This will populate st.shownPanelView
            if (!initializePanelContent(st) || (st.shownPanelView == null)) {
                return;
            }

            ViewGroup.LayoutParams lp = st.shownPanelView.getLayoutParams();
            if (lp == null) {
                lp = new ViewGroup.LayoutParams(WRAP_CONTENT, WRAP_CONTENT);
            }

            int backgroundResId;
            if (lp.width == ViewGroup.LayoutParams.FILL_PARENT) {
                // If the contents is fill parent for the width, set the
                // corresponding background
                backgroundResId = st.fullBackground;
            } else {
                // Otherwise, set the normal panel background
                backgroundResId = st.background;
            }
            st.decorView.setWindowBackground(getContext().getResources().getDrawable(
                    backgroundResId));


            st.decorView.addView(st.shownPanelView, lp);

            /*
             * Give focus to the view, if it or one of its children does not
             * already have it.
             */
            if (!st.shownPanelView.hasFocus()) {
                st.shownPanelView.requestFocus();
            }
        }

        st.isOpen = true;
        st.isHandled = false;

        WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
                WRAP_CONTENT, WRAP_CONTENT,
                st.x, st.y, WindowManager.LayoutParams.TYPE_APPLICATION_PANEL,
                WindowManager.LayoutParams.FLAG_DITHER
                | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
                st.decorView.mDefaultOpacity);

        lp.gravity = st.gravity;
        lp.windowAnimations = st.windowAnimations;
        wm.addView(st.decorView, lp);
        // Log.v(TAG, "Adding main menu to window manager.");
    
private voidopenPanelsAfterRestore()
Opens the panels that have had their state restored. This should be called sometime after {@link #restorePanelState} when it is safe to add to the window manager.

        PanelFeatureState[] panels = mPanels;

        if (panels == null) {
            return;
        }

        PanelFeatureState st;
        for (int i = panels.length - 1; i >= 0; i--) {
            st = panels[i];
            if ((st != null) && st.isOpen) {
                // Clear st.isOpen (openPanel will not open if it's already open)
                st.isOpen = false;
                openPanel(st, null);
            }
        }
    
public final android.view.ViewpeekDecorView()

        return mDecor;
    
public booleanperformContextMenuIdentifierAction(int id, int flags)

        return (mContextMenu != null) ? mContextMenu.performIdentifierAction(id, flags) : false;
    
public booleanperformPanelIdentifierAction(int featureId, int id, int flags)


        PanelFeatureState st = getPanelState(featureId, true);
        if (!preparePanel(st, new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MENU))) {
            return false;
        }
        if (st.menu == null) {
            return false;
        }

        boolean res = st.menu.performIdentifierAction(id, flags);

        closePanel(st, true);

        return res;
    
public booleanperformPanelShortcut(int featureId, int keyCode, android.view.KeyEvent event, int flags)

        return performPanelShortcut(getPanelState(featureId, true), keyCode, event, flags);
    
private booleanperformPanelShortcut(com.android.internal.policy.impl.PhoneWindow$PanelFeatureState st, int keyCode, android.view.KeyEvent event, int flags)

        if (event.isSystem() || (st == null)) {
            return false;
        }

        boolean handled = false;

        // Only try to perform menu shortcuts if preparePanel returned true (possible false
        // return value from application not wanting to show the menu).
        if ((st.isPrepared || preparePanel(st, event)) && st.menu != null) {
            // The menu is prepared now, perform the shortcut on it
            handled = st.menu.performShortcut(keyCode, event, flags);
        }

        if (handled) {
            // Mark as handled
            st.isHandled = true;

            if ((flags & Menu.FLAG_PERFORM_NO_CLOSE) == 0) {
                closePanel(st, true);
            }
        }

        return handled;
    
public final booleanpreparePanel(com.android.internal.policy.impl.PhoneWindow$PanelFeatureState st, android.view.KeyEvent event)
Prepares the panel to either be opened or chorded. This creates the Menu instance for the panel and populates it via the Activity callbacks.

param
st The panel state to prepare.
param
event The event that triggered the preparing of the panel.
return
Whether the panel was prepared. If the panel should not be shown, returns false.

        // Already prepared (isPrepared will be reset to false later)
        if (st.isPrepared)
            return true;

        if ((mPreparedPanel != null) && (mPreparedPanel != st)) {
            // Another Panel is prepared and possibly open, so close it
            closePanel(mPreparedPanel, false);
        }

        final Callback cb = getCallback();

        if (cb != null) {
            st.createdPanelView = cb.onCreatePanelView(st.featureId);
        }

        if (st.createdPanelView == null) {
            // Init the panel state's menu--return false if init failed
            if (st.menu == null) {
                if (!initializePanelMenu(st) || (st.menu == null)) {
                    return false;
                }
                // Call callback, and return if it doesn't want to display menu
                if ((cb == null) || !cb.onCreatePanelMenu(st.featureId, st.menu)) {
                    // Ditch the menu created above
                    st.menu = null;

                    return false;
                }
            }

            // Callback and return if the callback does not want to show the menu
            if (!cb.onPreparePanel(st.featureId, st.createdPanelView, st.menu)) {
                return false;
            }

            // Set the proper keymap
            KeyCharacterMap kmap = KeyCharacterMap.load(event != null ? event.getDeviceId() : 0);
            st.qwertyMode = kmap.getKeyboardType() != KeyCharacterMap.NUMERIC;
            st.menu.setQwertyMode(st.qwertyMode);
        }

        // Set other state
        st.isPrepared = true;
        st.isHandled = false;
        mPreparedPanel = st;

        return true;
    
private voidreopenMenu(boolean toggleMenuMode)

        PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, true);

        // Save the future expanded mode state since closePanel will reset it
        boolean newExpandedMode = toggleMenuMode ? !st.isInExpandedMode : st.isInExpandedMode;

        st.refreshDecorView = true;
        closePanel(st, false);

        // Set the expanded mode state
        st.isInExpandedMode = newExpandedMode;

        openPanel(st, null);
    
public booleanrequestFeature(int featureId)

        if (mContentParent != null) {
            throw new AndroidRuntimeException("requestFeature() must be called before adding content");
        }
        final int features = getFeatures();
        if ((features != DEFAULT_FEATURES) && (featureId == FEATURE_CUSTOM_TITLE)) {

            /* Another feature is enabled and the user is trying to enable the custom title feature */
            throw new AndroidRuntimeException("You cannot combine custom titles with other title features");
        }
        if (((features & (1 << FEATURE_CUSTOM_TITLE)) != 0) && (featureId != FEATURE_CUSTOM_TITLE)) {

            /* Custom title feature is enabled and the user is trying to enable another feature */
            throw new AndroidRuntimeException("You cannot combine custom titles with other title features");
        }
        /*  FEATURE_OPENGL disabled for 1.0
        if (featureId == FEATURE_OPENGL) {
            getAttributes().memoryType = WindowManager.LayoutParams.MEMORY_TYPE_GPU;
        }
        */
        return super.requestFeature(featureId);
    
public voidrestoreHierarchyState(android.os.Bundle savedInstanceState)
{@inheritDoc}

        if (mContentParent == null) {
            return;
        }

        SparseArray<Parcelable> savedStates
                = savedInstanceState.getSparseParcelableArray(VIEWS_TAG);
        if (savedStates != null) {
            mContentParent.restoreHierarchyState(savedStates);
        }

        // restore the focused view
        int focusedViewId = savedInstanceState.getInt(FOCUSED_ID_TAG, View.NO_ID);
        if (focusedViewId != View.NO_ID) {
            View needsFocus = mContentParent.findViewById(focusedViewId);
            if (needsFocus != null) {
                needsFocus.requestFocus();
            } else {
                Log.w(TAG,
                        "Previously focused view reported id " + focusedViewId
                                + " during save, but can't be found during restore.");
            }
        }

        // restore the panels
        SparseArray<Parcelable> panelStates = savedInstanceState.getSparseParcelableArray(PANELS_TAG);
        if (panelStates != null) {
            restorePanelState(panelStates);
        }
    
private voidrestorePanelState(android.util.SparseArray icicles)
Invoked when the panels should thaw their state from a previously frozen state.

param
icicles The state saved by {@link #savePanelState} that needs to be thawed.

        PanelFeatureState st;
        for (int curFeatureId = icicles.size() - 1; curFeatureId >= 0; curFeatureId--) {
            st = getPanelState(curFeatureId, false /* required */);
            if (st == null) {
                // The panel must not have been required, and is currently not around, skip it
                continue;
            }

            st.onRestoreInstanceState(icicles.get(curFeatureId));
        }

        /*
         * Implementation note: call openPanelsAfterRestore later to actually open the
         * restored panels.
         */
    
public android.os.BundlesaveHierarchyState()
{@inheritDoc}


      
    
       
        Bundle outState = new Bundle();
        if (mContentParent == null) {
            return outState;
        }

        SparseArray<Parcelable> states = new SparseArray<Parcelable>();
        mContentParent.saveHierarchyState(states);
        outState.putSparseParcelableArray(VIEWS_TAG, states);

        // save the focused view id
        View focusedView = mContentParent.findFocus();
        if (focusedView != null) {
            if (focusedView.getId() != View.NO_ID) {
                outState.putInt(FOCUSED_ID_TAG, focusedView.getId());
            } else {
                if (Config.LOGD) {
                    Log.d(TAG, "couldn't save which view has focus because the focused view "
                            + focusedView + " has no id.");
                }
            }
        }

        // save the panels
        SparseArray<Parcelable> panelStates = new SparseArray<Parcelable>();
        savePanelState(panelStates);
        if (panelStates.size() > 0) {
            outState.putSparseParcelableArray(PANELS_TAG, panelStates);
        }

        return outState;
    
private voidsavePanelState(android.util.SparseArray icicles)
Invoked when the panels should freeze their state.

param
icicles Save state into this. This is usually indexed by the featureId. This will be given to {@link #restorePanelState} in the future.

        PanelFeatureState[] panels = mPanels;
        if (panels == null) {
            return;
        }

        for (int curFeatureId = panels.length - 1; curFeatureId >= 0; curFeatureId--) {
            if (panels[curFeatureId] != null) {
                icicles.put(curFeatureId, panels[curFeatureId].onSaveInstanceState());
            }
        }
    
voidsendCloseSystemWindows()

        PhoneWindowManager.sendCloseSystemWindows(getContext(), null);
    
voidsendCloseSystemWindows(java.lang.String reason)

        PhoneWindowManager.sendCloseSystemWindows(getContext(), reason);
    
public final voidsetBackgroundDrawable(android.graphics.drawable.Drawable drawable)

        if (drawable != mBackgroundDrawable) {
            mBackgroundResource = 0;
            mBackgroundDrawable = drawable;
            if (mDecor != null) {
                mDecor.setWindowBackground(drawable);
            }
        }
    
public final voidsetChildDrawable(int featureId, android.graphics.drawable.Drawable drawable)

        DrawableFeatureState st = getDrawableState(featureId, true);
        st.child = drawable;
        updateDrawable(featureId, st, false);
    
public final voidsetChildInt(int featureId, int value)

        updateInt(featureId, value, false);
    
public final voidsetContainer(android.view.Window container)

        super.setContainer(container);
    
public voidsetContentView(int layoutResID)

        if (mContentParent == null) {
            installDecor();
        } else {
            mContentParent.removeAllViews();
        }
        mLayoutInflater.inflate(layoutResID, mContentParent);
        final Callback cb = getCallback();
        if (cb != null) {
            cb.onContentChanged();
        }
    
public voidsetContentView(android.view.View view)

        setContentView(view, new ViewGroup.LayoutParams(FILL_PARENT, FILL_PARENT));
    
public voidsetContentView(android.view.View view, ViewGroup.LayoutParams params)

        if (mContentParent == null) {
            installDecor();
        } else {
            mContentParent.removeAllViews();
        }
        mContentParent.addView(view, params);
        final Callback cb = getCallback();
        if (cb != null) {
            cb.onContentChanged();
        }
    
protected final voidsetFeatureDefaultDrawable(int featureId, android.graphics.drawable.Drawable drawable)

        DrawableFeatureState st = getDrawableState(featureId, true);
        if (st.def != drawable) {
            st.def = drawable;
            updateDrawable(featureId, st, false);
        }
    
public final voidsetFeatureDrawable(int featureId, android.graphics.drawable.Drawable drawable)

        DrawableFeatureState st = getDrawableState(featureId, true);
        st.resid = 0;
        st.uri = null;
        if (st.local != drawable) {
            st.local = drawable;
            updateDrawable(featureId, st, false);
        }
    
public voidsetFeatureDrawableAlpha(int featureId, int alpha)

        DrawableFeatureState st = getDrawableState(featureId, true);
        if (st.alpha != alpha) {
            st.alpha = alpha;
            updateDrawable(featureId, st, false);
        }
    
public final voidsetFeatureDrawableResource(int featureId, int resId)

        if (resId != 0) {
            DrawableFeatureState st = getDrawableState(featureId, true);
            if (st.resid != resId) {
                st.resid = resId;
                st.uri = null;
                st.local = getContext().getResources().getDrawable(resId);
                updateDrawable(featureId, st, false);
            }
        } else {
            setFeatureDrawable(featureId, null);
        }
    
public final voidsetFeatureDrawableUri(int featureId, android.net.Uri uri)

        if (uri != null) {
            DrawableFeatureState st = getDrawableState(featureId, true);
            if (st.uri == null || !st.uri.equals(uri)) {
                st.resid = 0;
                st.uri = uri;
                st.local = loadImageURI(uri);
                updateDrawable(featureId, st, false);
            }
        } else {
            setFeatureDrawable(featureId, null);
        }
    
protected voidsetFeatureFromAttrs(int featureId, android.content.res.TypedArray attrs, int drawableAttr, int alphaAttr)

        Drawable d = attrs.getDrawable(drawableAttr);
        if (d != null) {
            requestFeature(featureId);
            setFeatureDefaultDrawable(featureId, d);
        }
        if ((getFeatures() & (1 << featureId)) != 0) {
            int alpha = attrs.getInt(alphaAttr, -1);
            if (alpha >= 0) {
                setFeatureDrawableAlpha(featureId, alpha);
            }
        }
    
public final voidsetFeatureInt(int featureId, int value)

        // XXX Should do more management (as with drawable features) to
        // deal with interactions between multiple window policies.
        updateInt(featureId, value, false);
    
public voidsetTitle(java.lang.CharSequence title)

        if (mTitleView != null) {
            mTitleView.setText(title);
        }
        mTitle = title;
    
public voidsetTitleColor(int textColor)

        if (mTitleView != null) {
            mTitleView.setTextColor(textColor);
        }
        mTitleColor = textColor;
    
public voidsetVolumeControlStream(int streamType)

        mVolumeControlStreamType = streamType;
    
private voidshowProgressBars(android.widget.ProgressBar horizontalProgressBar, android.widget.ProgressBar spinnyProgressBar)

        final int features = getLocalFeatures();
        if ((features & (1 << 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 << FEATURE_PROGRESS)) != 0 &&
                horizontalProgressBar.getProgress() < 10000) {
            horizontalProgressBar.setVisibility(View.VISIBLE);
        }
    
private voidstartCallActivity()

        sendCloseSystemWindows();
        Intent intent = new Intent(Intent.ACTION_CALL_BUTTON);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        getContext().startActivity(intent);
    
public booleansuperDispatchKeyEvent(android.view.KeyEvent event)

        return mDecor.superDispatchKeyEvent(event);
    
public booleansuperDispatchTouchEvent(android.view.MotionEvent event)

        return mDecor.superDispatchTouchEvent(event);
    
public booleansuperDispatchTrackballEvent(android.view.MotionEvent event)

        return mDecor.superDispatchTrackballEvent(event);
    
public voidtakeKeyEvents(boolean get)
Request that key events come to this activity. Use this if your activity has no views with focus, but the activity still wants a chance to process key events.

        mDecor.setFocusable(get);
    
public final voidtogglePanel(int featureId, android.view.KeyEvent event)

        PanelFeatureState st = getPanelState(featureId, true);
        if (st.isOpen) {
            closePanel(st, true);
        } else {
            openPanel(st, event);
        }
    
protected final voidupdateDrawable(int featureId, boolean fromActive)
Update the state of a drawable feature. This should be called, for every drawable feature supported, as part of onActive(), to make sure that the contents of a containing window is properly updated.

see
#onActive
param
featureId The desired drawable feature to change.
param
fromActive Always true when called from onActive().

        final DrawableFeatureState st = getDrawableState(featureId, false);
        if (st != null) {
            updateDrawable(featureId, st, fromActive);
        }
    
private voidupdateDrawable(int featureId, com.android.internal.policy.impl.PhoneWindow$DrawableFeatureState st, 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;
        }

        Drawable drawable = null;
        if (st != null) {
            drawable = st.child;
            if (drawable == null)
                drawable = st.local;
            if (drawable == null)
                drawable = st.def;
        }
        if ((getLocalFeatures() & featureMask) == 0) {
            if (getContainer() != null) {
                if (isActive() || fromResume) {
                    getContainer().setChildDrawable(featureId, drawable);
                }
            }
        } else if (st != null && (st.cur != drawable || st.curAlpha != st.alpha)) {
            // System.out.println("Drawable changed: old=" + st.cur
            // + ", new=" + drawable);
            st.cur = drawable;
            st.curAlpha = st.alpha;
            onDrawableChanged(featureId, drawable, st.alpha);
        }
    
private voidupdateInt(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;
        }

        if ((getLocalFeatures() & featureMask) == 0) {
            if (getContainer() != null) {
                getContainer().setChildInt(featureId, value);
            }
        } else {
            onIntChanged(featureId, value);
        }
    
private voidupdateProgressBars(int value)
Updates the progress bars that are shown in the title bar.

param
value Can be one of {@link Window#PROGRESS_VISIBILITY_ON}, {@link Window#PROGRESS_VISIBILITY_OFF}, {@link Window#PROGRESS_INDETERMINATE_ON}, {@link Window#PROGRESS_INDETERMINATE_OFF}, or a value starting at {@link Window#PROGRESS_START} through {@link Window#PROGRESS_END} for setting the default progress (if {@link Window#PROGRESS_END} is given, the progress bar widgets in the title will be hidden after an animation), a value between {@link Window#PROGRESS_SECONDARY_START} - {@link Window#PROGRESS_SECONDARY_END} for the secondary progress (if {@link Window#PROGRESS_SECONDARY_END} is given, the progress bar widgets will still be shown with the secondary progress bar will be completely filled in.)

        ProgressBar circularProgressBar = getCircularProgressBar(true);
        ProgressBar horizontalProgressBar = getHorizontalProgressBar(true);

        final int features = getLocalFeatures();
        if (value == PROGRESS_VISIBILITY_ON) {
            if ((features & (1 << FEATURE_PROGRESS)) != 0) {
                int level = horizontalProgressBar.getProgress();
                int visibility = (horizontalProgressBar.isIndeterminate() || level < 10000) ?
                        View.VISIBLE : View.INVISIBLE;
                horizontalProgressBar.setVisibility(visibility);
            }
            if ((features & (1 << FEATURE_INDETERMINATE_PROGRESS)) != 0) {
                circularProgressBar.setVisibility(View.VISIBLE);
            }
        } else if (value == PROGRESS_VISIBILITY_OFF) {
            if ((features & (1 << FEATURE_PROGRESS)) != 0) {
                horizontalProgressBar.setVisibility(View.GONE);
            }
            if ((features & (1 << FEATURE_INDETERMINATE_PROGRESS)) != 0) {
                circularProgressBar.setVisibility(View.GONE);
            }
        } else if (value == PROGRESS_INDETERMINATE_ON) {
            horizontalProgressBar.setIndeterminate(true);
        } else if (value == PROGRESS_INDETERMINATE_OFF) {
            horizontalProgressBar.setIndeterminate(false);
        } else if (PROGRESS_START <= value && value <= 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 - PROGRESS_START);

            if (value < PROGRESS_END) {
                showProgressBars(horizontalProgressBar, circularProgressBar);
            } else {
                hideProgressBars(horizontalProgressBar, circularProgressBar);
            }
        } else if (PROGRESS_SECONDARY_START <= value && value <= PROGRESS_SECONDARY_END) {
            horizontalProgressBar.setSecondaryProgress(value - PROGRESS_SECONDARY_START);

            showProgressBars(horizontalProgressBar, circularProgressBar);
        }