blob: b13560c10326143529fdf3710787fa6244d71bd6 [file] [log] [blame]
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001/*
Jeff Brown37df39a92015-02-25 15:42:31 -08002 * Copyright (C) 2006 The Android Open Source Project
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Adam Powell6711f3b2015-05-06 15:57:09 -070017package com.android.internal.policy;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080018
Jaewan Kimd98dcab2016-05-03 02:52:18 +090019import static android.provider.Settings.Global.DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES;
Romain Guycc6828c2010-01-08 15:06:37 -080020import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
svetoslavganov491293e2009-04-28 19:17:02 -070021import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
Dianne Hackbornc652de82013-02-15 16:32:56 -080022import static android.view.WindowManager.LayoutParams.*;
svetoslavganov491293e2009-04-28 19:17:02 -070023
Sudheer Shankadc589ac2016-11-10 15:30:17 -080024import android.app.ActivityManager;
Dianne Hackbornfdf5b352014-10-08 17:43:48 -070025import android.app.SearchManager;
26import android.os.UserHandle;
Clara Bayarried2a54c2015-02-05 16:58:00 +000027
Phil Weaver396d5492016-03-22 17:53:50 -070028import android.text.TextUtils;
Adam Powell6711f3b2015-05-06 15:57:09 -070029import android.view.ContextThemeWrapper;
Adam Powell6711f3b2015-05-06 15:57:09 -070030import android.view.Gravity;
31import android.view.IRotationWatcher.Stub;
32import android.view.IWindowManager;
33import android.view.InputDevice;
34import android.view.InputEvent;
35import android.view.InputQueue;
36import android.view.KeyCharacterMap;
37import android.view.KeyEvent;
38import android.view.LayoutInflater;
39import android.view.Menu;
40import android.view.MenuItem;
41import android.view.MotionEvent;
42import android.view.SearchEvent;
43import android.view.SurfaceHolder.Callback2;
44import android.view.View;
45import android.view.ViewConfiguration;
46import android.view.ViewGroup;
47import android.view.ViewManager;
48import android.view.ViewParent;
49import android.view.ViewRootImpl;
Andrii Kulian51c1b672017-04-07 18:39:32 -070050import android.view.ViewRootImpl.ActivityConfigCallback;
Adam Powell6711f3b2015-05-06 15:57:09 -070051import android.view.Window;
Adam Powell6711f3b2015-05-06 15:57:09 -070052import android.view.WindowManager;
John Spurlockae3349e2013-10-18 17:34:42 -040053import com.android.internal.R;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080054import com.android.internal.view.menu.ContextMenuBuilder;
Adam Powell696cba52011-03-29 10:38:16 -070055import com.android.internal.view.menu.IconMenuPresenter;
Adam Powell640a66e2011-04-29 10:18:53 -070056import com.android.internal.view.menu.ListMenuPresenter;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080057import com.android.internal.view.menu.MenuBuilder;
58import com.android.internal.view.menu.MenuDialogHelper;
Alan Viverette021627e2015-11-25 14:22:00 -050059import com.android.internal.view.menu.MenuHelper;
Adam Powell696cba52011-03-29 10:38:16 -070060import com.android.internal.view.menu.MenuPresenter;
Adam Powell640a66e2011-04-29 10:18:53 -070061import com.android.internal.view.menu.MenuView;
Adam Powell4369e7d2014-05-17 14:16:08 -070062import com.android.internal.widget.DecorContentParent;
Will Haldean Brownca6234e2014-02-12 10:23:41 -080063import com.android.internal.widget.SwipeDismissLayout;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080064
Adrian Roosea562512014-05-05 13:33:03 +020065import android.app.ActivityManager;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080066import android.app.KeyguardManager;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080067import android.content.Context;
Tim Kilbourn0e5f1102015-06-05 16:18:09 -070068import android.content.Intent;
Aaron Whyte1fb617f2014-05-12 22:08:53 -070069import android.content.pm.PackageManager;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080070import android.content.res.Configuration;
Alan Viverette4b002d32014-06-03 17:32:19 -070071import android.content.res.Resources.Theme;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080072import android.content.res.TypedArray;
Adrian Roosea562512014-05-05 13:33:03 +020073import android.graphics.Color;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080074import android.graphics.drawable.Drawable;
75import android.media.AudioManager;
RoboErik55011652014-07-09 15:05:53 -070076import android.media.session.MediaController;
RoboErik55011652014-07-09 15:05:53 -070077import android.media.session.MediaSessionLegacyHelper;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080078import android.net.Uri;
79import android.os.Bundle;
Adam Powelldfee59a2011-08-05 20:48:30 -070080import android.os.Handler;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080081import android.os.Parcel;
82import android.os.Parcelable;
Adam Powelldfee59a2011-08-05 20:48:30 -070083import android.os.RemoteException;
84import android.os.ServiceManager;
Jaewan Kimd98dcab2016-05-03 02:52:18 +090085import android.provider.Settings;
George Mount31a21722014-03-24 17:44:36 -070086import android.transition.Scene;
87import android.transition.Transition;
88import android.transition.TransitionInflater;
89import android.transition.TransitionManager;
George Mount68f96d82014-07-31 13:13:10 -070090import android.transition.TransitionSet;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080091import android.util.AndroidRuntimeException;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080092import android.util.EventLog;
93import android.util.Log;
94import android.util.SparseArray;
Adam Powell85446e92010-10-22 17:43:56 -070095import android.util.TypedValue;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080096import android.view.animation.Animation;
97import android.view.animation.AnimationUtils;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080098import android.widget.FrameLayout;
99import android.widget.ImageView;
100import android.widget.ProgressBar;
101import android.widget.TextView;
102
Adam Powelldfee59a2011-08-05 20:48:30 -0700103import java.lang.ref.WeakReference;
104import java.util.ArrayList;
105
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800106/**
107 * Android-specific Window.
108 * <p>
109 * todo: need to pull the generic functionality out into a base class
110 * in android.widget.
Jorim Jaggib10e33f2015-02-04 21:57:40 +0100111 *
112 * @hide
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800113 */
114public class PhoneWindow extends Window implements MenuBuilder.Callback {
svetoslavganov491293e2009-04-28 19:17:02 -0700115
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800116 private final static String TAG = "PhoneWindow";
117
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -0800118 private static final boolean DEBUG = false;
119
George Mounted1e01d2014-06-05 13:49:12 -0700120 private final static int DEFAULT_BACKGROUND_FADE_DURATION_MS = 300;
121
Adam Powell166c8e32014-07-01 17:37:48 -0700122 private static final int CUSTOM_TITLE_COMPATIBLE_FEATURES = DEFAULT_FEATURES |
123 (1 << FEATURE_CUSTOM_TITLE) |
124 (1 << FEATURE_CONTENT_TRANSITIONS) |
George Mount9826f632014-09-11 08:50:09 -0700125 (1 << FEATURE_ACTIVITY_TRANSITIONS) |
Adam Powell166c8e32014-07-01 17:37:48 -0700126 (1 << FEATURE_ACTION_MODE_OVERLAY);
127
George Mount68f96d82014-07-31 13:13:10 -0700128 private static final Transition USE_DEFAULT_TRANSITION = new TransitionSet();
129
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800130 /**
131 * Simple callback used by the context menu and its submenus. The options
132 * menu submenus do not use this (their behavior is more complex).
133 */
Alan Viverette77fb85e2015-12-14 11:42:44 -0500134 final PhoneWindowMenuCallback mContextMenuCallback = new PhoneWindowMenuCallback(this);
Dianne Hackborn60145272011-01-11 23:45:09 -0800135
136 final TypedValue mMinWidthMajor = new TypedValue();
137 final TypedValue mMinWidthMinor = new TypedValue();
Adam Powell40eec4c2012-02-15 17:10:58 -0800138 TypedValue mFixedWidthMajor;
139 TypedValue mFixedWidthMinor;
140 TypedValue mFixedHeightMajor;
141 TypedValue mFixedHeightMinor;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800142
143 // This is the top-level view of the window, containing the window decor.
144 private DecorView mDecor;
145
Filip Gruszczynskia59ac9c2015-09-10 18:28:48 -0700146 // When we reuse decor views, we need to recreate the content root. This happens when the decor
147 // view is requested, so we need to force the recreating without introducing an infinite loop.
148 private boolean mForceDecorInstall = false;
149
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800150 // This is the view in which the window contents are placed. It is either
151 // mDecor itself, or a child of mDecor where the contents go.
Wale Ogunwale8804af22015-11-17 09:18:15 -0800152 ViewGroup mContentParent;
Filip Gruszczynskif4bdaeb2016-01-06 14:34:00 -0800153 // Whether the client has explicitly set the content view. If false and mContentParent is not
154 // null, then the content parent was set due to window preservation.
155 private boolean mContentParentExplicitlySet = false;
Adrian Roosf5e9b5c2014-09-10 15:27:41 +0200156
Adam Powell6711f3b2015-05-06 15:57:09 -0700157 Callback2 mTakeSurfaceCallback;
George Mount0a778ed2013-12-13 13:35:36 -0800158
Dianne Hackborn1e4b9f32010-06-23 14:10:57 -0700159 InputQueue.Callback mTakeInputQueueCallback;
George Mount0a778ed2013-12-13 13:35:36 -0800160
Wale Ogunwale8804af22015-11-17 09:18:15 -0800161 boolean mIsFloating;
Jorim Jaggic39c7b02016-03-24 10:47:07 -0700162 private boolean mIsTranslucent;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800163
164 private LayoutInflater mLayoutInflater;
165
166 private TextView mTitleView;
George Mount0a778ed2013-12-13 13:35:36 -0800167
Wale Ogunwale8804af22015-11-17 09:18:15 -0800168 DecorContentParent mDecorContentParent;
Adam Powell696cba52011-03-29 10:38:16 -0700169 private ActionMenuPresenterCallback mActionMenuPresenterCallback;
170 private PanelMenuPresenterCallback mPanelMenuPresenterCallback;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800171
Adam Powell18e905f2013-10-24 14:27:48 -0700172 private TransitionManager mTransitionManager;
Adam Powellcfbe9be2013-11-06 14:58:58 -0800173 private Scene mContentScene;
Adam Powell18e905f2013-10-24 14:27:48 -0700174
Adam Powell0a317e92013-06-13 13:15:43 -0700175 // The icon resource has been explicitly set elsewhere
176 // and should not be overwritten with a default.
Adam Powell04fe6eb2013-05-31 14:39:48 -0700177 static final int FLAG_RESOURCE_SET_ICON = 1 << 0;
Adam Powell0a317e92013-06-13 13:15:43 -0700178
179 // The logo resource has been explicitly set elsewhere
180 // and should not be overwritten with a default.
Adam Powell04fe6eb2013-05-31 14:39:48 -0700181 static final int FLAG_RESOURCE_SET_LOGO = 1 << 1;
Adam Powell0a317e92013-06-13 13:15:43 -0700182
183 // The icon resource is currently configured to use the system fallback
184 // as no default was previously specified. Anything can override this.
185 static final int FLAG_RESOURCE_SET_ICON_FALLBACK = 1 << 2;
186
Adam Powell04fe6eb2013-05-31 14:39:48 -0700187 int mResourcesSetFlags;
188 int mIconRes;
189 int mLogoRes;
190
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800191 private DrawableFeatureState[] mDrawables;
192
193 private PanelFeatureState[] mPanels;
194
195 /**
196 * The panel that is prepared or opened (the most recent one if there are
197 * multiple panels). Shortcuts will go to this panel. It gets set in
198 * {@link #preparePanel} and cleared in {@link #closePanel}.
199 */
Wale Ogunwale8804af22015-11-17 09:18:15 -0800200 PanelFeatureState mPreparedPanel;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800201
202 /**
203 * The keycode that is currently held down (as a modifier) for chording. If
204 * this is 0, there is no key held down.
205 */
Wale Ogunwale8804af22015-11-17 09:18:15 -0800206 int mPanelChordingKey;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800207
Jaewan Kimd98dcab2016-05-03 02:52:18 +0900208 // This stores if the system supports Picture-in-Picture
209 // to see if KEYCODE_WINDOW should be handled here or not.
210 private boolean mSupportsPictureInPicture;
211
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800212 private ImageView mLeftIconView;
213
214 private ImageView mRightIconView;
215
216 private ProgressBar mCircularProgressBar;
217
218 private ProgressBar mHorizontalProgressBar;
219
Wale Ogunwale0d7e9122015-11-17 10:45:06 -0800220 int mBackgroundResource = 0;
221 int mBackgroundFallbackResource = 0;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800222
223 private Drawable mBackgroundDrawable;
224
Wale Ogunwale0d7e9122015-11-17 10:45:06 -0800225 private boolean mLoadElevation = true;
Alan Viverette49a22e82014-07-12 20:01:27 -0700226 private float mElevation;
227
Alan Viverette40982d42014-07-25 17:48:55 -0700228 /** Whether window content should be clipped to the background outline. */
229 private boolean mClipToOutline;
230
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800231 private int mFrameResource = 0;
232
233 private int mTextColor = 0;
Wale Ogunwale8804af22015-11-17 09:18:15 -0800234 int mStatusBarColor = 0;
235 int mNavigationBarColor = 0;
Jason Monka750e992017-09-01 12:40:06 -0400236 int mNavigationBarDividerColor = 0;
Adrian Roos34e65442014-05-17 02:35:33 +0200237 private boolean mForcedStatusBarColor = false;
238 private boolean mForcedNavigationBarColor = false;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800239
240 private CharSequence mTitle = null;
241
242 private int mTitleColor = 0;
243
Dianne Hackborncfaf8872011-01-18 13:57:54 -0800244 private boolean mAlwaysReadCloseOnTouchAttr = false;
Alan Viveretteeb1d3792014-06-03 18:36:03 -0700245
Wale Ogunwale8804af22015-11-17 09:18:15 -0800246 ContextMenuBuilder mContextMenu;
Alan Viverette021627e2015-11-25 14:22:00 -0500247 MenuHelper mContextMenuHelper;
Adam Powell8515ee82010-11-30 14:09:55 -0800248 private boolean mClosingActionMenu;
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -0800249
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800250 private int mVolumeControlStreamType = AudioManager.USE_DEFAULT_STREAM_TYPE;
RoboErik55011652014-07-09 15:05:53 -0700251 private MediaController mMediaController;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800252
Joe Onorato86f67862010-11-05 18:57:34 -0700253 private AudioManager mAudioManager;
254 private KeyguardManager mKeyguardManager;
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -0800255
Adam Powell269248d2011-08-02 10:26:54 -0700256 private int mUiOptions = 0;
257
Adam Powell4b6d93f2012-09-18 18:34:08 -0700258 private boolean mInvalidatePanelMenuPosted;
259 private int mInvalidatePanelMenuFeatures;
260 private final Runnable mInvalidatePanelMenuRunnable = new Runnable() {
261 @Override public void run() {
262 for (int i = 0; i <= FEATURE_MAX; i++) {
263 if ((mInvalidatePanelMenuFeatures & 1 << i) != 0) {
264 doInvalidatePanelMenu(i);
265 }
266 }
267 mInvalidatePanelMenuPosted = false;
268 mInvalidatePanelMenuFeatures = 0;
269 }
270 };
271
George Mount68f96d82014-07-31 13:13:10 -0700272 private Transition mEnterTransition = null;
273 private Transition mReturnTransition = USE_DEFAULT_TRANSITION;
274 private Transition mExitTransition = null;
275 private Transition mReenterTransition = USE_DEFAULT_TRANSITION;
276 private Transition mSharedElementEnterTransition = null;
277 private Transition mSharedElementReturnTransition = USE_DEFAULT_TRANSITION;
278 private Transition mSharedElementExitTransition = null;
279 private Transition mSharedElementReenterTransition = USE_DEFAULT_TRANSITION;
George Mountc03da0e2014-08-22 17:04:02 -0700280 private Boolean mAllowReturnTransitionOverlap;
George Mount31a21722014-03-24 17:44:36 -0700281 private Boolean mAllowEnterTransitionOverlap;
George Mounted1e01d2014-06-05 13:49:12 -0700282 private long mBackgroundFadeDurationMillis = -1;
George Mountb89d5cc2014-08-18 16:50:50 -0700283 private Boolean mSharedElementsUseOverlay;
George Mount0a778ed2013-12-13 13:35:36 -0800284
Jorim Jaggia16cc152015-06-01 16:55:05 -0700285 private boolean mIsStartingWindow;
Filip Gruszczynski0daf2102015-09-29 08:39:07 -0700286 private int mTheme = -1;
Jorim Jaggia16cc152015-06-01 16:55:05 -0700287
Filip Gruszczynski3dec0812015-12-09 08:42:41 -0800288 private int mDecorCaptionShade = DECOR_CAPTION_SHADE_AUTO;
289
Filip Gruszczynski796b8c12015-12-22 14:46:21 -0800290 private boolean mUseDecorContext = false;
291
Andrii Kulian51c1b672017-04-07 18:39:32 -0700292 /** @see ViewRootImpl#mActivityConfigCallback */
293 private ActivityConfigCallback mActivityConfigCallback;
294
Adam Powelldfee59a2011-08-05 20:48:30 -0700295 static class WindowManagerHolder {
296 static final IWindowManager sWindowManager = IWindowManager.Stub.asInterface(
297 ServiceManager.getService("window"));
298 }
299
300 static final RotationWatcher sRotationWatcher = new RotationWatcher();
301
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800302 public PhoneWindow(Context context) {
303 super(context);
304 mLayoutInflater = LayoutInflater.from(context);
305 }
306
Filip Gruszczynski796b8c12015-12-22 14:46:21 -0800307 /**
308 * Constructor for main window of an activity.
309 */
Andrii Kulian51c1b672017-04-07 18:39:32 -0700310 public PhoneWindow(Context context, Window preservedWindow,
311 ActivityConfigCallback activityConfigCallback) {
Filip Gruszczynskia59ac9c2015-09-10 18:28:48 -0700312 this(context);
Filip Gruszczynski796b8c12015-12-22 14:46:21 -0800313 // Only main activity windows use decor context, all the other windows depend on whatever
314 // context that was given to them.
315 mUseDecorContext = true;
Filip Gruszczynskia59ac9c2015-09-10 18:28:48 -0700316 if (preservedWindow != null) {
317 mDecor = (DecorView) preservedWindow.getDecorView();
318 mElevation = preservedWindow.getElevation();
Wale Ogunwale0d7e9122015-11-17 10:45:06 -0800319 mLoadElevation = false;
Filip Gruszczynskia59ac9c2015-09-10 18:28:48 -0700320 mForceDecorInstall = true;
Chong Zhanga8be1b92015-09-29 13:54:44 -0700321 // If we're preserving window, carry over the app token from the preserved
322 // window, as we'll be skipping the addView in handleResumeActivity(), and
323 // the token will not be updated as for a new window.
324 getAttributes().token = preservedWindow.getAttributes().token;
Filip Gruszczynskia59ac9c2015-09-10 18:28:48 -0700325 }
Jaewan Kimd98dcab2016-05-03 02:52:18 +0900326 // Even though the device doesn't support picture-in-picture mode,
327 // an user can force using it through developer options.
328 boolean forceResizable = Settings.Global.getInt(context.getContentResolver(),
329 DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES, 0) != 0;
330 mSupportsPictureInPicture = forceResizable || context.getPackageManager().hasSystemFeature(
331 PackageManager.FEATURE_PICTURE_IN_PICTURE);
Andrii Kulian51c1b672017-04-07 18:39:32 -0700332 mActivityConfigCallback = activityConfigCallback;
Filip Gruszczynskia59ac9c2015-09-10 18:28:48 -0700333 }
334
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800335 @Override
336 public final void setContainer(Window container) {
337 super.setContainer(container);
338 }
339
340 @Override
341 public boolean requestFeature(int featureId) {
Filip Gruszczynskif4bdaeb2016-01-06 14:34:00 -0800342 if (mContentParentExplicitlySet) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800343 throw new AndroidRuntimeException("requestFeature() must be called before adding content");
344 }
345 final int features = getFeatures();
Adam Powell166c8e32014-07-01 17:37:48 -0700346 final int newFeatures = features | (1 << featureId);
347 if ((newFeatures & (1 << FEATURE_CUSTOM_TITLE)) != 0 &&
348 (newFeatures & ~CUSTOM_TITLE_COMPATIBLE_FEATURES) != 0) {
349 // Another feature is enabled and the user is trying to enable the custom title feature
350 // or custom title feature is enabled and the user is trying to enable another feature
351 throw new AndroidRuntimeException(
352 "You cannot combine custom titles with other title features");
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800353 }
Adam Powellf4a6ec42010-08-24 14:18:10 -0700354 if ((features & (1 << FEATURE_NO_TITLE)) != 0 && featureId == FEATURE_ACTION_BAR) {
355 return false; // Ignore. No title dominates.
356 }
357 if ((features & (1 << FEATURE_ACTION_BAR)) != 0 && featureId == FEATURE_NO_TITLE) {
358 // Remove the action bar feature if we have no title. No title dominates.
359 removeFeature(FEATURE_ACTION_BAR);
360 }
Will Haldean Brownca6234e2014-02-12 10:23:41 -0800361
362 if ((features & (1 << FEATURE_ACTION_BAR)) != 0 && featureId == FEATURE_SWIPE_TO_DISMISS) {
363 throw new AndroidRuntimeException(
364 "You cannot combine swipe dismissal and the action bar.");
365 }
366 if ((features & (1 << FEATURE_SWIPE_TO_DISMISS)) != 0 && featureId == FEATURE_ACTION_BAR) {
367 throw new AndroidRuntimeException(
368 "You cannot combine swipe dismissal and the action bar.");
369 }
Aaron Whyte1fb617f2014-05-12 22:08:53 -0700370
371 if (featureId == FEATURE_INDETERMINATE_PROGRESS &&
372 getContext().getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH)) {
373 throw new AndroidRuntimeException("You cannot use indeterminate progress on a watch.");
374 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800375 return super.requestFeature(featureId);
376 }
377
378 @Override
Adam Powell269248d2011-08-02 10:26:54 -0700379 public void setUiOptions(int uiOptions) {
380 mUiOptions = uiOptions;
381 }
382
383 @Override
Adam Powelle43fca92011-08-16 12:57:01 -0700384 public void setUiOptions(int uiOptions, int mask) {
385 mUiOptions = (mUiOptions & ~mask) | (uiOptions & mask);
386 }
387
388 @Override
Adam Powellcfbe9be2013-11-06 14:58:58 -0800389 public TransitionManager getTransitionManager() {
390 return mTransitionManager;
391 }
392
393 @Override
394 public void setTransitionManager(TransitionManager tm) {
395 mTransitionManager = tm;
396 }
397
398 @Override
399 public Scene getContentScene() {
400 return mContentScene;
401 }
402
403 @Override
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800404 public void setContentView(int layoutResID) {
Adam Powell18e905f2013-10-24 14:27:48 -0700405 // Note: FEATURE_CONTENT_TRANSITIONS may be set in the process of installing the window
406 // decor, when theme attributes and the like are crystalized. Do not check the feature
407 // before this happens.
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800408 if (mContentParent == null) {
409 installDecor();
Adam Powell18e905f2013-10-24 14:27:48 -0700410 } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800411 mContentParent.removeAllViews();
412 }
Adam Powell18e905f2013-10-24 14:27:48 -0700413
414 if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
415 final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,
416 getContext());
Adam Powellcfbe9be2013-11-06 14:58:58 -0800417 transitionTo(newScene);
Adam Powell18e905f2013-10-24 14:27:48 -0700418 } else {
419 mLayoutInflater.inflate(layoutResID, mContentParent);
420 }
Adam Powell41607d52015-06-17 13:37:06 -0700421 mContentParent.requestApplyInsets();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800422 final Callback cb = getCallback();
Dianne Hackbornb66ad572011-03-01 17:10:30 -0800423 if (cb != null && !isDestroyed()) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800424 cb.onContentChanged();
425 }
Filip Gruszczynskif4bdaeb2016-01-06 14:34:00 -0800426 mContentParentExplicitlySet = true;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800427 }
428
429 @Override
430 public void setContentView(View view) {
Romain Guycc6828c2010-01-08 15:06:37 -0800431 setContentView(view, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800432 }
433
434 @Override
435 public void setContentView(View view, ViewGroup.LayoutParams params) {
Adam Powell18e905f2013-10-24 14:27:48 -0700436 // Note: FEATURE_CONTENT_TRANSITIONS may be set in the process of installing the window
437 // decor, when theme attributes and the like are crystalized. Do not check the feature
438 // before this happens.
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800439 if (mContentParent == null) {
440 installDecor();
Adam Powell18e905f2013-10-24 14:27:48 -0700441 } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800442 mContentParent.removeAllViews();
443 }
Adam Powell18e905f2013-10-24 14:27:48 -0700444
445 if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
446 view.setLayoutParams(params);
447 final Scene newScene = new Scene(mContentParent, view);
Adam Powellcfbe9be2013-11-06 14:58:58 -0800448 transitionTo(newScene);
Adam Powell18e905f2013-10-24 14:27:48 -0700449 } else {
450 mContentParent.addView(view, params);
451 }
Adam Powell41607d52015-06-17 13:37:06 -0700452 mContentParent.requestApplyInsets();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800453 final Callback cb = getCallback();
Dianne Hackbornb66ad572011-03-01 17:10:30 -0800454 if (cb != null && !isDestroyed()) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800455 cb.onContentChanged();
456 }
Filip Gruszczynskif4bdaeb2016-01-06 14:34:00 -0800457 mContentParentExplicitlySet = true;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800458 }
459
460 @Override
461 public void addContentView(View view, ViewGroup.LayoutParams params) {
462 if (mContentParent == null) {
463 installDecor();
464 }
Adam Powell18e905f2013-10-24 14:27:48 -0700465 if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
466 // TODO Augment the scenes/transitions API to support this.
George Mount7e208842014-07-02 07:22:43 -0700467 Log.v(TAG, "addContentView does not support content transitions");
Adam Powell18e905f2013-10-24 14:27:48 -0700468 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800469 mContentParent.addView(view, params);
Adam Powell41607d52015-06-17 13:37:06 -0700470 mContentParent.requestApplyInsets();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800471 final Callback cb = getCallback();
Dianne Hackbornb66ad572011-03-01 17:10:30 -0800472 if (cb != null && !isDestroyed()) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800473 cb.onContentChanged();
474 }
475 }
476
Wale Ogunwale0d7e9122015-11-17 10:45:06 -0800477 @Override
Filip Gruszczynskia59ac9c2015-09-10 18:28:48 -0700478 public void clearContentView() {
Wale Ogunwale0d7e9122015-11-17 10:45:06 -0800479 if (mDecor != null) {
480 mDecor.clearContentView();
Filip Gruszczynskia59ac9c2015-09-10 18:28:48 -0700481 }
482 }
483
Adam Powellcfbe9be2013-11-06 14:58:58 -0800484 private void transitionTo(Scene scene) {
George Mount0a778ed2013-12-13 13:35:36 -0800485 if (mContentScene == null) {
486 scene.enter();
Adam Powellcfbe9be2013-11-06 14:58:58 -0800487 } else {
488 mTransitionManager.transitionTo(scene);
489 }
490 mContentScene = scene;
491 }
492
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800493 @Override
494 public View getCurrentFocus() {
495 return mDecor != null ? mDecor.findFocus() : null;
496 }
497
498 @Override
Adam Powell6711f3b2015-05-06 15:57:09 -0700499 public void takeSurface(Callback2 callback) {
Dianne Hackborndc8a7f62010-05-10 11:29:34 -0700500 mTakeSurfaceCallback = callback;
501 }
George Mount0a778ed2013-12-13 13:35:36 -0800502
Dianne Hackborn1e4b9f32010-06-23 14:10:57 -0700503 public void takeInputQueue(InputQueue.Callback callback) {
504 mTakeInputQueueCallback = callback;
Dianne Hackborna95e4cb2010-06-18 18:09:33 -0700505 }
George Mount0a778ed2013-12-13 13:35:36 -0800506
Dianne Hackborndc8a7f62010-05-10 11:29:34 -0700507 @Override
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800508 public boolean isFloating() {
509 return mIsFloating;
510 }
511
Jorim Jaggic39c7b02016-03-24 10:47:07 -0700512 public boolean isTranslucent() {
513 return mIsTranslucent;
514 }
515
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800516 /**
Jorim Jaggi8e879f12016-05-25 16:41:49 -0700517 * @return Whether the window is currently showing the wallpaper.
518 */
519 boolean isShowingWallpaper() {
520 return (getAttributes().flags & FLAG_SHOW_WALLPAPER) != 0;
521 }
522
523 /**
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800524 * Return a LayoutInflater instance that can be used to inflate XML view layout
525 * resources for use in this Window.
526 *
527 * @return LayoutInflater The shared LayoutInflater.
528 */
529 @Override
530 public LayoutInflater getLayoutInflater() {
531 return mLayoutInflater;
532 }
533
534 @Override
535 public void setTitle(CharSequence title) {
Phil Weaver155edc62016-06-09 10:24:53 -0700536 setTitle(title, true);
537 }
538
539 public void setTitle(CharSequence title, boolean updateAccessibilityTitle) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800540 if (mTitleView != null) {
541 mTitleView.setText(title);
Adam Powell4369e7d2014-05-17 14:16:08 -0700542 } else if (mDecorContentParent != null) {
543 mDecorContentParent.setWindowTitle(title);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800544 }
545 mTitle = title;
Phil Weaver155edc62016-06-09 10:24:53 -0700546 if (updateAccessibilityTitle) {
547 WindowManager.LayoutParams params = getAttributes();
548 if (!TextUtils.equals(title, params.accessibilityTitle)) {
549 params.accessibilityTitle = TextUtils.stringOrSpannedString(title);
Phil Weaver964c68e2016-10-27 16:22:05 -0700550 if (mDecor != null) {
551 // ViewRootImpl will make sure the change propagates to WindowManagerService
552 ViewRootImpl vr = mDecor.getViewRootImpl();
553 if (vr != null) {
554 vr.onWindowTitleChanged();
555 }
556 }
Phil Weaver155edc62016-06-09 10:24:53 -0700557 dispatchWindowAttributesChanged(getAttributes());
558 }
Phil Weaver396d5492016-03-22 17:53:50 -0700559 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800560 }
561
562 @Override
Alan Viverette2525d9c2013-11-15 14:42:19 -0800563 @Deprecated
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800564 public void setTitleColor(int textColor) {
565 if (mTitleView != null) {
566 mTitleView.setTextColor(textColor);
567 }
568 mTitleColor = textColor;
569 }
570
571 /**
572 * Prepares the panel to either be opened or chorded. This creates the Menu
573 * instance for the panel and populates it via the Activity callbacks.
574 *
575 * @param st The panel state to prepare.
576 * @param event The event that triggered the preparing of the panel.
577 * @return Whether the panel was prepared. If the panel should not be shown,
578 * returns false.
579 */
580 public final boolean preparePanel(PanelFeatureState st, KeyEvent event) {
Dianne Hackbornb66ad572011-03-01 17:10:30 -0800581 if (isDestroyed()) {
582 return false;
583 }
584
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800585 // Already prepared (isPrepared will be reset to false later)
Adam Powellc6d51882011-10-13 11:33:24 -0700586 if (st.isPrepared) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800587 return true;
Adam Powellc6d51882011-10-13 11:33:24 -0700588 }
Alan Viveretteeb1d3792014-06-03 18:36:03 -0700589
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800590 if ((mPreparedPanel != null) && (mPreparedPanel != st)) {
591 // Another Panel is prepared and possibly open, so close it
592 closePanel(mPreparedPanel, false);
593 }
594
595 final Callback cb = getCallback();
596
597 if (cb != null) {
598 st.createdPanelView = cb.onCreatePanelView(st.featureId);
599 }
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -0800600
Adam Powell8c16aa92013-04-04 10:47:52 -0700601 final boolean isActionBarMenu =
602 (st.featureId == FEATURE_OPTIONS_PANEL || st.featureId == FEATURE_ACTION_BAR);
603
Adam Powell4369e7d2014-05-17 14:16:08 -0700604 if (isActionBarMenu && mDecorContentParent != null) {
Adam Powell8c16aa92013-04-04 10:47:52 -0700605 // Enforce ordering guarantees around events so that the action bar never
606 // dispatches menu-related events before the panel is prepared.
Adam Powell4369e7d2014-05-17 14:16:08 -0700607 mDecorContentParent.setMenuPrepared();
Adam Powell8c16aa92013-04-04 10:47:52 -0700608 }
609
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800610 if (st.createdPanelView == null) {
611 // Init the panel state's menu--return false if init failed
Dianne Hackbornb31e84bc2010-06-08 18:04:35 -0700612 if (st.menu == null || st.refreshMenuContent) {
613 if (st.menu == null) {
614 if (!initializePanelMenu(st) || (st.menu == null)) {
615 return false;
616 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800617 }
Adam Powell696cba52011-03-29 10:38:16 -0700618
Adam Powell4369e7d2014-05-17 14:16:08 -0700619 if (isActionBarMenu && mDecorContentParent != null) {
Adam Powellccdd4ee2011-07-27 20:05:14 -0700620 if (mActionMenuPresenterCallback == null) {
621 mActionMenuPresenterCallback = new ActionMenuPresenterCallback();
622 }
Adam Powell4369e7d2014-05-17 14:16:08 -0700623 mDecorContentParent.setMenu(st.menu, mActionMenuPresenterCallback);
Adam Powellccdd4ee2011-07-27 20:05:14 -0700624 }
625
Adam Powell696cba52011-03-29 10:38:16 -0700626 // Call callback, and return if it doesn't want to display menu.
627
628 // Creating the panel menu will involve a lot of manipulation;
629 // don't dispatch change events to presenters until we're done.
630 st.menu.stopDispatchingItemsChanged();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800631 if ((cb == null) || !cb.onCreatePanelMenu(st.featureId, st.menu)) {
632 // Ditch the menu created above
Adam Powell1d07e162011-09-07 20:46:24 -0700633 st.setMenu(null);
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -0800634
Adam Powell4369e7d2014-05-17 14:16:08 -0700635 if (isActionBarMenu && mDecorContentParent != null) {
Adam Powell84f49362011-08-18 11:09:57 -0700636 // Don't show it in the action bar either
Adam Powell4369e7d2014-05-17 14:16:08 -0700637 mDecorContentParent.setMenu(null, mActionMenuPresenterCallback);
Adam Powell84f49362011-08-18 11:09:57 -0700638 }
Adam Powellf35d0492011-08-17 13:56:47 -0700639
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800640 return false;
641 }
Alan Viveretteeb1d3792014-06-03 18:36:03 -0700642
Dianne Hackbornb31e84bc2010-06-08 18:04:35 -0700643 st.refreshMenuContent = false;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800644 }
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -0800645
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800646 // Callback and return if the callback does not want to show the menu
Adam Powell696cba52011-03-29 10:38:16 -0700647
648 // Preparing the panel menu can involve a lot of manipulation;
649 // don't dispatch change events to presenters until we're done.
650 st.menu.stopDispatchingItemsChanged();
Adam Powell97a30012011-08-09 17:15:48 -0700651
652 // Restore action view state before we prepare. This gives apps
653 // an opportunity to override frozen/restored state in onPrepare.
654 if (st.frozenActionViewState != null) {
655 st.menu.restoreActionViewStates(st.frozenActionViewState);
656 st.frozenActionViewState = null;
657 }
658
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800659 if (!cb.onPreparePanel(st.featureId, st.createdPanelView, st.menu)) {
Adam Powell4369e7d2014-05-17 14:16:08 -0700660 if (isActionBarMenu && mDecorContentParent != null) {
Adam Powell84f49362011-08-18 11:09:57 -0700661 // The app didn't want to show the menu for now but it still exists.
662 // Clear it out of the action bar.
Adam Powell4369e7d2014-05-17 14:16:08 -0700663 mDecorContentParent.setMenu(null, mActionMenuPresenterCallback);
Adam Powell84f49362011-08-18 11:09:57 -0700664 }
Adam Powell696cba52011-03-29 10:38:16 -0700665 st.menu.startDispatchingItemsChanged();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800666 return false;
667 }
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -0800668
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800669 // Set the proper keymap
Jeff Brown6b53e8d2010-11-10 16:03:06 -0800670 KeyCharacterMap kmap = KeyCharacterMap.load(
671 event != null ? event.getDeviceId() : KeyCharacterMap.VIRTUAL_KEYBOARD);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800672 st.qwertyMode = kmap.getKeyboardType() != KeyCharacterMap.NUMERIC;
673 st.menu.setQwertyMode(st.qwertyMode);
Adam Powell89b09da2011-07-27 11:55:29 -0700674 st.menu.startDispatchingItemsChanged();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800675 }
676
677 // Set other state
678 st.isPrepared = true;
679 st.isHandled = false;
680 mPreparedPanel = st;
681
682 return true;
683 }
684
685 @Override
686 public void onConfigurationChanged(Configuration newConfig) {
Adam Powell6c6f5752010-08-20 18:34:46 -0700687 // Action bars handle their own menu state
Adam Powell4369e7d2014-05-17 14:16:08 -0700688 if (mDecorContentParent == null) {
Adam Powell6c6f5752010-08-20 18:34:46 -0700689 PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, false);
690 if ((st != null) && (st.menu != null)) {
Adam Powell6c6f5752010-08-20 18:34:46 -0700691 if (st.isOpen) {
692 // Freeze state
693 final Bundle state = new Bundle();
Adam Powell696cba52011-03-29 10:38:16 -0700694 if (st.iconMenuPresenter != null) {
695 st.iconMenuPresenter.saveHierarchyState(state);
696 }
Adam Powelldfee59a2011-08-05 20:48:30 -0700697 if (st.listMenuPresenter != null) {
698 st.listMenuPresenter.saveHierarchyState(state);
Adam Powell696cba52011-03-29 10:38:16 -0700699 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800700
Adam Powell6c6f5752010-08-20 18:34:46 -0700701 // Remove the menu views since they need to be recreated
702 // according to the new configuration
703 clearMenuViews(st);
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -0800704
Adam Powell6c6f5752010-08-20 18:34:46 -0700705 // Re-open the same menu
706 reopenMenu(false);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800707
Adam Powell6c6f5752010-08-20 18:34:46 -0700708 // Restore state
Adam Powell696cba52011-03-29 10:38:16 -0700709 if (st.iconMenuPresenter != null) {
710 st.iconMenuPresenter.restoreHierarchyState(state);
711 }
Adam Powelldfee59a2011-08-05 20:48:30 -0700712 if (st.listMenuPresenter != null) {
713 st.listMenuPresenter.restoreHierarchyState(state);
Adam Powell696cba52011-03-29 10:38:16 -0700714 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800715
Adam Powell6c6f5752010-08-20 18:34:46 -0700716 } else {
717 // Clear menu views so on next menu opening, it will use
718 // the proper layout
719 clearMenuViews(st);
720 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800721 }
722 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800723 }
724
Wale Ogunwaleeb6722c2015-12-08 11:43:43 -0800725 @Override
Andrii Kulian933076d2016-03-29 17:04:42 -0700726 public void onMultiWindowModeChanged() {
Wale Ogunwaleeb6722c2015-12-08 11:43:43 -0800727 if (mDecor != null) {
Filip Gruszczynski1937a4c2016-01-19 16:17:13 -0800728 mDecor.onConfigurationChanged(getContext().getResources().getConfiguration());
Wale Ogunwaleeb6722c2015-12-08 11:43:43 -0800729 }
730 }
731
Jorim Jaggi4846ee32016-01-07 17:39:12 +0100732 @Override
Winson Chung4d8681f2017-05-23 16:22:08 -0700733 public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode) {
734 if (mDecor != null) {
735 mDecor.updatePictureInPictureOutlineProvider(isInPictureInPictureMode);
736 }
737 }
738
739 @Override
Jorim Jaggi4846ee32016-01-07 17:39:12 +0100740 public void reportActivityRelaunched() {
741 if (mDecor != null && mDecor.getViewRootImpl() != null) {
742 mDecor.getViewRootImpl().reportActivityRelaunched();
743 }
744 }
745
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800746 private static void clearMenuViews(PanelFeatureState st) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800747 // This can be called on config changes, so we should make sure
748 // the views will be reconstructed based on the new orientation, etc.
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -0800749
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800750 // Allow the callback to create a new panel view
751 st.createdPanelView = null;
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -0800752
753 // Causes the decor view to be recreated
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800754 st.refreshDecorView = true;
Alan Viveretteeb1d3792014-06-03 18:36:03 -0700755
Adam Powell696cba52011-03-29 10:38:16 -0700756 st.clearMenuPresenters();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800757 }
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -0800758
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800759 @Override
760 public final void openPanel(int featureId, KeyEvent event) {
Adam Powell4369e7d2014-05-17 14:16:08 -0700761 if (featureId == FEATURE_OPTIONS_PANEL && mDecorContentParent != null &&
762 mDecorContentParent.canShowOverflowMenu() &&
Adam Powell5fcf5b92013-09-11 08:45:36 -0700763 !ViewConfiguration.get(getContext()).hasPermanentMenuKey()) {
Adam Powell4369e7d2014-05-17 14:16:08 -0700764 mDecorContentParent.showOverflowMenu();
Adam Powellf75eeb22010-08-10 15:59:40 -0700765 } else {
766 openPanel(getPanelState(featureId, true), event);
767 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800768 }
769
Adam Powell5fcf5b92013-09-11 08:45:36 -0700770 private void openPanel(final PanelFeatureState st, KeyEvent event) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800771 // System.out.println("Open panel: isOpen=" + st.isOpen);
772
773 // Already open, return
Dianne Hackbornb66ad572011-03-01 17:10:30 -0800774 if (st.isOpen || isDestroyed()) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800775 return;
776 }
777
Adam Powell0d69fae2011-01-08 15:07:08 -0800778 // Don't open an options panel for honeycomb apps on xlarge devices.
779 // (The app should be using an action bar for menu items.)
780 if (st.featureId == FEATURE_OPTIONS_PANEL) {
781 Context context = getContext();
782 Configuration config = context.getResources().getConfiguration();
783 boolean isXLarge = (config.screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) ==
784 Configuration.SCREENLAYOUT_SIZE_XLARGE;
785 boolean isHoneycombApp = context.getApplicationInfo().targetSdkVersion >=
786 android.os.Build.VERSION_CODES.HONEYCOMB;
787
788 if (isXLarge && isHoneycombApp) {
789 return;
790 }
791 }
792
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800793 Callback cb = getCallback();
794 if ((cb != null) && (!cb.onMenuOpened(st.featureId, st.menu))) {
795 // Callback doesn't want the menu to open, reset any state
796 closePanel(st, true);
797 return;
798 }
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -0800799
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800800 final WindowManager wm = getWindowManager();
801 if (wm == null) {
802 return;
803 }
804
805 // Prepare panel (should have been done before, but just in case)
806 if (!preparePanel(st, event)) {
807 return;
808 }
809
Adam Powella3e3c532011-06-22 11:21:54 -0700810 int width = WRAP_CONTENT;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800811 if (st.decorView == null || st.refreshDecorView) {
812 if (st.decorView == null) {
813 // Initialize the panel decor, this will populate st.decorView
814 if (!initializePanelDecor(st) || (st.decorView == null))
815 return;
816 } else if (st.refreshDecorView && (st.decorView.getChildCount() > 0)) {
817 // Decor needs refreshing, so remove its views
818 st.decorView.removeAllViews();
819 }
820
821 // This will populate st.shownPanelView
Adam Powell526b9312011-04-22 15:42:05 -0700822 if (!initializePanelContent(st) || !st.hasPanelItems()) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800823 return;
824 }
825
826 ViewGroup.LayoutParams lp = st.shownPanelView.getLayoutParams();
827 if (lp == null) {
828 lp = new ViewGroup.LayoutParams(WRAP_CONTENT, WRAP_CONTENT);
829 }
830
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -0800831 int backgroundResId;
Romain Guycc6828c2010-01-08 15:06:37 -0800832 if (lp.width == ViewGroup.LayoutParams.MATCH_PARENT) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800833 // If the contents is fill parent for the width, set the
834 // corresponding background
835 backgroundResId = st.fullBackground;
Adam Powella3e3c532011-06-22 11:21:54 -0700836 width = MATCH_PARENT;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800837 } else {
838 // Otherwise, set the normal panel background
839 backgroundResId = st.background;
840 }
Alan Viverette8eea3ea2014-02-03 18:40:20 -0800841 st.decorView.setWindowBackground(getContext().getDrawable(
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800842 backgroundResId));
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -0800843
Adam Powella60314c2012-05-15 14:33:13 -0700844 ViewParent shownPanelParent = st.shownPanelView.getParent();
845 if (shownPanelParent != null && shownPanelParent instanceof ViewGroup) {
846 ((ViewGroup) shownPanelParent).removeView(st.shownPanelView);
847 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800848 st.decorView.addView(st.shownPanelView, lp);
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -0800849
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800850 /*
851 * Give focus to the view, if it or one of its children does not
852 * already have it.
853 */
854 if (!st.shownPanelView.hasFocus()) {
855 st.shownPanelView.requestFocus();
856 }
Adam Powelldfee59a2011-08-05 20:48:30 -0700857 } else if (!st.isInListMode()) {
Adam Powelldc5facd2011-08-03 16:45:45 -0700858 width = MATCH_PARENT;
Adam Powell3429ff52011-08-18 18:32:48 -0700859 } else if (st.createdPanelView != null) {
860 // If we already had a panel view, carry width=MATCH_PARENT through
861 // as we did above when it was created.
862 ViewGroup.LayoutParams lp = st.createdPanelView.getLayoutParams();
863 if (lp != null && lp.width == ViewGroup.LayoutParams.MATCH_PARENT) {
864 width = MATCH_PARENT;
865 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800866 }
867
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800868 st.isHandled = false;
869
870 WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
Adam Powella3e3c532011-06-22 11:21:54 -0700871 width, WRAP_CONTENT,
Dianne Hackbornd3715102009-09-15 19:28:03 -0700872 st.x, st.y, WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG,
Jeff Brown3cc321e2012-07-16 16:04:23 -0700873 WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
Jeff Brown46e75292010-11-10 16:53:45 -0800874 | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800875 st.decorView.mDefaultOpacity);
876
Adam Powelldfee59a2011-08-05 20:48:30 -0700877 if (st.isCompact) {
878 lp.gravity = getOptionsPanelGravity();
879 sRotationWatcher.addWindow(this);
880 } else {
881 lp.gravity = st.gravity;
882 }
883
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800884 lp.windowAnimations = st.windowAnimations;
Craig Mautner9b407282013-07-01 12:57:51 -0700885
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800886 wm.addView(st.decorView, lp);
Craig Mautner9b407282013-07-01 12:57:51 -0700887 st.isOpen = true;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800888 // Log.v(TAG, "Adding main menu to window manager.");
889 }
890
891 @Override
892 public final void closePanel(int featureId) {
Adam Powell4369e7d2014-05-17 14:16:08 -0700893 if (featureId == FEATURE_OPTIONS_PANEL && mDecorContentParent != null &&
894 mDecorContentParent.canShowOverflowMenu() &&
Adam Powell5fcf5b92013-09-11 08:45:36 -0700895 !ViewConfiguration.get(getContext()).hasPermanentMenuKey()) {
Adam Powell4369e7d2014-05-17 14:16:08 -0700896 mDecorContentParent.hideOverflowMenu();
Adam Powellf75eeb22010-08-10 15:59:40 -0700897 } else if (featureId == FEATURE_CONTEXT_MENU) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800898 closeContextMenu();
899 } else {
900 closePanel(getPanelState(featureId, true), true);
901 }
902 }
903
904 /**
905 * Closes the given panel.
906 *
907 * @param st The panel to be closed.
908 * @param doCallback Whether to notify the callback that the panel was
909 * closed. If the panel is in the process of re-opening or
910 * opening another panel (e.g., menu opening a sub menu), the
911 * callback should not happen and this variable should be false.
912 * In addition, this method internally will only perform the
913 * callback if the panel is open.
914 */
915 public final void closePanel(PanelFeatureState st, boolean doCallback) {
916 // System.out.println("Close panel: isOpen=" + st.isOpen);
Adam Powell696cba52011-03-29 10:38:16 -0700917 if (doCallback && st.featureId == FEATURE_OPTIONS_PANEL &&
Adam Powell4369e7d2014-05-17 14:16:08 -0700918 mDecorContentParent != null && mDecorContentParent.isOverflowMenuShowing()) {
Adam Powell696cba52011-03-29 10:38:16 -0700919 checkCloseActionMenu(st.menu);
920 return;
921 }
922
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800923 final ViewManager wm = getWindowManager();
924 if ((wm != null) && st.isOpen) {
925 if (st.decorView != null) {
926 wm.removeView(st.decorView);
927 // Log.v(TAG, "Removing main menu from window manager.");
Adam Powelldfee59a2011-08-05 20:48:30 -0700928 if (st.isCompact) {
929 sRotationWatcher.removeWindow(this);
930 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800931 }
932
933 if (doCallback) {
934 callOnPanelClosed(st.featureId, st, null);
935 }
936 }
Adam Powell696cba52011-03-29 10:38:16 -0700937
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800938 st.isPrepared = false;
939 st.isHandled = false;
940 st.isOpen = false;
941
942 // This view is no longer shown, so null it out
943 st.shownPanelView = null;
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -0800944
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800945 if (st.isInExpandedMode) {
946 // Next time the menu opens, it should not be in expanded mode, so
947 // force a refresh of the decor
948 st.refreshDecorView = true;
949 st.isInExpandedMode = false;
950 }
951
952 if (mPreparedPanel == st) {
953 mPreparedPanel = null;
954 mPanelChordingKey = 0;
955 }
956 }
957
Adam Powell640a66e2011-04-29 10:18:53 -0700958 void checkCloseActionMenu(Menu menu) {
Adam Powell8515ee82010-11-30 14:09:55 -0800959 if (mClosingActionMenu) {
960 return;
961 }
962
Adam Powell8515ee82010-11-30 14:09:55 -0800963 mClosingActionMenu = true;
Adam Powell4369e7d2014-05-17 14:16:08 -0700964 mDecorContentParent.dismissPopups();
Adam Powell8515ee82010-11-30 14:09:55 -0800965 Callback cb = getCallback();
Adam Powell696cba52011-03-29 10:38:16 -0700966 if (cb != null && !isDestroyed()) {
Adam Powell8515ee82010-11-30 14:09:55 -0800967 cb.onPanelClosed(FEATURE_ACTION_BAR, menu);
968 }
969 mClosingActionMenu = false;
970 }
971
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800972 @Override
973 public final void togglePanel(int featureId, KeyEvent event) {
974 PanelFeatureState st = getPanelState(featureId, true);
975 if (st.isOpen) {
976 closePanel(st, true);
977 } else {
978 openPanel(st, event);
979 }
980 }
981
Dianne Hackbornb31e84bc2010-06-08 18:04:35 -0700982 @Override
983 public void invalidatePanelMenu(int featureId) {
Adam Powell4b6d93f2012-09-18 18:34:08 -0700984 mInvalidatePanelMenuFeatures |= 1 << featureId;
985
986 if (!mInvalidatePanelMenuPosted && mDecor != null) {
987 mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
988 mInvalidatePanelMenuPosted = true;
989 }
990 }
991
Adam Powell31c91c82014-08-22 17:20:00 -0700992 void doPendingInvalidatePanelMenu() {
993 if (mInvalidatePanelMenuPosted) {
994 mDecor.removeCallbacks(mInvalidatePanelMenuRunnable);
995 mInvalidatePanelMenuRunnable.run();
996 }
997 }
998
Adam Powell4b6d93f2012-09-18 18:34:08 -0700999 void doInvalidatePanelMenu(int featureId) {
Jose Lima7a22fc62015-01-23 17:24:22 -08001000 PanelFeatureState st = getPanelState(featureId, false);
1001 if (st == null) {
1002 return;
1003 }
Adam Powell038f1c82011-07-21 14:28:10 -07001004 Bundle savedActionViewStates = null;
Dianne Hackbornb31e84bc2010-06-08 18:04:35 -07001005 if (st.menu != null) {
Adam Powell038f1c82011-07-21 14:28:10 -07001006 savedActionViewStates = new Bundle();
1007 st.menu.saveActionViewStates(savedActionViewStates);
1008 if (savedActionViewStates.size() > 0) {
1009 st.frozenActionViewState = savedActionViewStates;
1010 }
Adam Powell89b09da2011-07-27 11:55:29 -07001011 // This will be started again when the panel is prepared.
1012 st.menu.stopDispatchingItemsChanged();
Dianne Hackbornb31e84bc2010-06-08 18:04:35 -07001013 st.menu.clear();
1014 }
1015 st.refreshMenuContent = true;
1016 st.refreshDecorView = true;
Alan Viveretteeb1d3792014-06-03 18:36:03 -07001017
Adam Powell96675b12010-06-10 18:58:59 -07001018 // Prepare the options panel if we have an action bar
1019 if ((featureId == FEATURE_ACTION_BAR || featureId == FEATURE_OPTIONS_PANEL)
Adam Powell4369e7d2014-05-17 14:16:08 -07001020 && mDecorContentParent != null) {
Adam Powell96675b12010-06-10 18:58:59 -07001021 st = getPanelState(Window.FEATURE_OPTIONS_PANEL, false);
1022 if (st != null) {
1023 st.isPrepared = false;
1024 preparePanel(st, null);
1025 }
1026 }
Dianne Hackbornb31e84bc2010-06-08 18:04:35 -07001027 }
Alan Viveretteeb1d3792014-06-03 18:36:03 -07001028
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001029 /**
1030 * Called when the panel key is pushed down.
1031 * @param featureId The feature ID of the relevant panel (defaults to FEATURE_OPTIONS_PANEL}.
1032 * @param event The key event.
1033 * @return Whether the key was handled.
1034 */
1035 public final boolean onKeyDownPanel(int featureId, KeyEvent event) {
Dianne Hackborna207baa2009-09-13 16:14:44 -07001036 final int keyCode = event.getKeyCode();
Alan Viveretteeb1d3792014-06-03 18:36:03 -07001037
Dianne Hackborna207baa2009-09-13 16:14:44 -07001038 if (event.getRepeatCount() == 0) {
1039 // The panel key was pushed, so set the chording key
1040 mPanelChordingKey = keyCode;
Adam Powellf6148c52010-08-11 21:10:16 -07001041
Jose Lima7a22fc62015-01-23 17:24:22 -08001042 PanelFeatureState st = getPanelState(featureId, false);
1043 if (st != null && !st.isOpen) {
Dianne Hackborna207baa2009-09-13 16:14:44 -07001044 return preparePanel(st, event);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001045 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001046 }
1047
1048 return false;
1049 }
1050
1051 /**
1052 * Called when the panel key is released.
1053 * @param featureId The feature ID of the relevant panel (defaults to FEATURE_OPTIONS_PANEL}.
1054 * @param event The key event.
1055 */
1056 public final void onKeyUpPanel(int featureId, KeyEvent event) {
1057 // The panel key was released, so clear the chording key
1058 if (mPanelChordingKey != 0) {
1059 mPanelChordingKey = 0;
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -08001060
Jose Lima7a22fc62015-01-23 17:24:22 -08001061 final PanelFeatureState st = getPanelState(featureId, false);
1062
Clara Bayarri80c38562015-03-04 17:10:57 +00001063 if (event.isCanceled() || (mDecor != null && mDecor.mPrimaryActionMode != null) ||
Jose Lima7a22fc62015-01-23 17:24:22 -08001064 (st == null)) {
Dianne Hackborn0041e972009-07-24 17:14:43 -07001065 return;
1066 }
Alan Viveretteeb1d3792014-06-03 18:36:03 -07001067
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001068 boolean playSoundEffect = false;
Adam Powell4369e7d2014-05-17 14:16:08 -07001069 if (featureId == FEATURE_OPTIONS_PANEL && mDecorContentParent != null &&
1070 mDecorContentParent.canShowOverflowMenu() &&
Adam Powell5fcf5b92013-09-11 08:45:36 -07001071 !ViewConfiguration.get(getContext()).hasPermanentMenuKey()) {
Adam Powell4369e7d2014-05-17 14:16:08 -07001072 if (!mDecorContentParent.isOverflowMenuShowing()) {
1073 if (!isDestroyed() && preparePanel(st, event)) {
1074 playSoundEffect = mDecorContentParent.showOverflowMenu();
Adam Powellf6148c52010-08-11 21:10:16 -07001075 }
Adam Powell4369e7d2014-05-17 14:16:08 -07001076 } else {
1077 playSoundEffect = mDecorContentParent.hideOverflowMenu();
Adam Powellf6148c52010-08-11 21:10:16 -07001078 }
1079 } else {
1080 if (st.isOpen || st.isHandled) {
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -08001081
Adam Powellf6148c52010-08-11 21:10:16 -07001082 // Play the sound effect if the user closed an open menu (and not if
1083 // they just released a menu shortcut)
1084 playSoundEffect = st.isOpen;
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -08001085
Adam Powellf6148c52010-08-11 21:10:16 -07001086 // Close menu
1087 closePanel(st, true);
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -08001088
Adam Powellf6148c52010-08-11 21:10:16 -07001089 } else if (st.isPrepared) {
Adam Powellc6d51882011-10-13 11:33:24 -07001090 boolean show = true;
1091 if (st.refreshMenuContent) {
1092 // Something may have invalidated the menu since we prepared it.
1093 // Re-prepare it to refresh.
1094 st.isPrepared = false;
1095 show = preparePanel(st, event);
1096 }
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -08001097
Adam Powellc6d51882011-10-13 11:33:24 -07001098 if (show) {
1099 // Write 'menu opened' to event log
1100 EventLog.writeEvent(50001, 0);
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -08001101
Adam Powellc6d51882011-10-13 11:33:24 -07001102 // Show menu
1103 openPanel(st, event);
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -08001104
Adam Powellc6d51882011-10-13 11:33:24 -07001105 playSoundEffect = true;
1106 }
Adam Powellf6148c52010-08-11 21:10:16 -07001107 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001108 }
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -08001109
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001110 if (playSoundEffect) {
1111 AudioManager audioManager = (AudioManager) getContext().getSystemService(
1112 Context.AUDIO_SERVICE);
1113 if (audioManager != null) {
1114 audioManager.playSoundEffect(AudioManager.FX_KEY_CLICK);
1115 } else {
1116 Log.w(TAG, "Couldn't get audio manager");
1117 }
1118 }
1119 }
1120 }
1121
1122 @Override
1123 public final void closeAllPanels() {
1124 final ViewManager wm = getWindowManager();
1125 if (wm == null) {
1126 return;
1127 }
1128
1129 final PanelFeatureState[] panels = mPanels;
1130 final int N = panels != null ? panels.length : 0;
1131 for (int i = 0; i < N; i++) {
1132 final PanelFeatureState panel = panels[i];
1133 if (panel != null) {
1134 closePanel(panel, true);
1135 }
1136 }
1137
1138 closeContextMenu();
1139 }
1140
1141 /**
1142 * Closes the context menu. This notifies the menu logic of the close, along
1143 * with dismissing it from the UI.
1144 */
1145 private synchronized void closeContextMenu() {
1146 if (mContextMenu != null) {
1147 mContextMenu.close();
1148 dismissContextMenu();
1149 }
1150 }
1151
1152 /**
1153 * Dismisses just the context menu UI. To close the context menu, use
1154 * {@link #closeContextMenu()}.
1155 */
1156 private synchronized void dismissContextMenu() {
1157 mContextMenu = null;
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -08001158
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001159 if (mContextMenuHelper != null) {
1160 mContextMenuHelper.dismiss();
1161 mContextMenuHelper = null;
1162 }
1163 }
1164
1165 @Override
1166 public boolean performPanelShortcut(int featureId, int keyCode, KeyEvent event, int flags) {
Jose Lima7a22fc62015-01-23 17:24:22 -08001167 return performPanelShortcut(getPanelState(featureId, false), keyCode, event, flags);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001168 }
1169
Wale Ogunwale8804af22015-11-17 09:18:15 -08001170 boolean performPanelShortcut(PanelFeatureState st, int keyCode, KeyEvent event,
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001171 int flags) {
1172 if (event.isSystem() || (st == null)) {
1173 return false;
1174 }
1175
1176 boolean handled = false;
1177
1178 // Only try to perform menu shortcuts if preparePanel returned true (possible false
1179 // return value from application not wanting to show the menu).
1180 if ((st.isPrepared || preparePanel(st, event)) && st.menu != null) {
1181 // The menu is prepared now, perform the shortcut on it
1182 handled = st.menu.performShortcut(keyCode, event, flags);
1183 }
1184
1185 if (handled) {
1186 // Mark as handled
1187 st.isHandled = true;
1188
Adam Powell6055f3e2011-08-28 14:20:24 -07001189 // Only close down the menu if we don't have an action bar keeping it open.
Adam Powell4369e7d2014-05-17 14:16:08 -07001190 if ((flags & Menu.FLAG_PERFORM_NO_CLOSE) == 0 && mDecorContentParent == null) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001191 closePanel(st, true);
1192 }
1193 }
1194
1195 return handled;
1196 }
1197
1198 @Override
1199 public boolean performPanelIdentifierAction(int featureId, int id, int flags) {
1200
1201 PanelFeatureState st = getPanelState(featureId, true);
1202 if (!preparePanel(st, new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MENU))) {
1203 return false;
1204 }
1205 if (st.menu == null) {
1206 return false;
1207 }
1208
1209 boolean res = st.menu.performIdentifierAction(id, flags);
1210
Adam Powell6055f3e2011-08-28 14:20:24 -07001211 // Only close down the menu if we don't have an action bar keeping it open.
Adam Powell4369e7d2014-05-17 14:16:08 -07001212 if (mDecorContentParent == null) {
Adam Powell6055f3e2011-08-28 14:20:24 -07001213 closePanel(st, true);
1214 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001215
1216 return res;
1217 }
1218
1219 public PanelFeatureState findMenuPanel(Menu menu) {
1220 final PanelFeatureState[] panels = mPanels;
1221 final int N = panels != null ? panels.length : 0;
1222 for (int i = 0; i < N; i++) {
1223 final PanelFeatureState panel = panels[i];
1224 if (panel != null && panel.menu == menu) {
1225 return panel;
1226 }
1227 }
1228 return null;
1229 }
1230
1231 public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) {
1232 final Callback cb = getCallback();
Dianne Hackbornb66ad572011-03-01 17:10:30 -08001233 if (cb != null && !isDestroyed()) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001234 final PanelFeatureState panel = findMenuPanel(menu.getRootMenu());
1235 if (panel != null) {
1236 return cb.onMenuItemSelected(panel.featureId, item);
1237 }
1238 }
1239 return false;
1240 }
1241
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001242 public void onMenuModeChange(MenuBuilder menu) {
1243 reopenMenu(true);
1244 }
1245
1246 private void reopenMenu(boolean toggleMenuMode) {
Adam Powell4369e7d2014-05-17 14:16:08 -07001247 if (mDecorContentParent != null && mDecorContentParent.canShowOverflowMenu() &&
Adam Powell5fcf5b92013-09-11 08:45:36 -07001248 (!ViewConfiguration.get(getContext()).hasPermanentMenuKey() ||
Adam Powell4369e7d2014-05-17 14:16:08 -07001249 mDecorContentParent.isOverflowMenuShowPending())) {
Adam Powell8515ee82010-11-30 14:09:55 -08001250 final Callback cb = getCallback();
Adam Powell4369e7d2014-05-17 14:16:08 -07001251 if (!mDecorContentParent.isOverflowMenuShowing() || !toggleMenuMode) {
1252 if (cb != null && !isDestroyed()) {
Adam Powell5c8f9b52013-03-27 12:22:27 -07001253 // If we have a menu invalidation pending, do it now.
1254 if (mInvalidatePanelMenuPosted &&
1255 (mInvalidatePanelMenuFeatures & (1 << FEATURE_OPTIONS_PANEL)) != 0) {
1256 mDecor.removeCallbacks(mInvalidatePanelMenuRunnable);
1257 mInvalidatePanelMenuRunnable.run();
1258 }
1259
Jose Lima7a22fc62015-01-23 17:24:22 -08001260 final PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, false);
Adam Powell6a5b0a32012-09-28 14:24:48 -07001261
1262 // If we don't have a menu or we're waiting for a full content refresh,
1263 // forget it. This is a lingering event that no longer matters.
Jose Lima7a22fc62015-01-23 17:24:22 -08001264 if (st != null && st.menu != null && !st.refreshMenuContent &&
Adam Powell6a5b0a32012-09-28 14:24:48 -07001265 cb.onPreparePanel(FEATURE_OPTIONS_PANEL, st.createdPanelView, st.menu)) {
Adam Powell8515ee82010-11-30 14:09:55 -08001266 cb.onMenuOpened(FEATURE_ACTION_BAR, st.menu);
Adam Powell4369e7d2014-05-17 14:16:08 -07001267 mDecorContentParent.showOverflowMenu();
Adam Powellf6148c52010-08-11 21:10:16 -07001268 }
1269 }
1270 } else {
Adam Powell4369e7d2014-05-17 14:16:08 -07001271 mDecorContentParent.hideOverflowMenu();
Jose Lima7a22fc62015-01-23 17:24:22 -08001272 final PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, false);
1273 if (st != null && cb != null && !isDestroyed()) {
Adam Powell8515ee82010-11-30 14:09:55 -08001274 cb.onPanelClosed(FEATURE_ACTION_BAR, st.menu);
1275 }
Adam Powellf6148c52010-08-11 21:10:16 -07001276 }
1277 return;
1278 }
1279
Jose Lima7a22fc62015-01-23 17:24:22 -08001280 PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, false);
1281
1282 if (st == null) {
1283 return;
1284 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001285
1286 // Save the future expanded mode state since closePanel will reset it
1287 boolean newExpandedMode = toggleMenuMode ? !st.isInExpandedMode : st.isInExpandedMode;
1288
1289 st.refreshDecorView = true;
1290 closePanel(st, false);
1291
1292 // Set the expanded mode state
1293 st.isInExpandedMode = newExpandedMode;
1294
1295 openPanel(st, null);
1296 }
1297
1298 /**
1299 * Initializes the menu associated with the given panel feature state. You
1300 * must at the very least set PanelFeatureState.menu to the Menu to be
1301 * associated with the given panel state. The default implementation creates
1302 * a new menu for the panel state.
1303 *
1304 * @param st The panel whose menu is being initialized.
1305 * @return Whether the initialization was successful.
1306 */
1307 protected boolean initializePanelMenu(final PanelFeatureState st) {
Adam Powelld65b3b92011-09-22 16:38:11 -07001308 Context context = getContext();
1309
Alan Viveretteeb1d3792014-06-03 18:36:03 -07001310 // If we have an action bar, initialize the menu with the right theme.
Adam Powelld65b3b92011-09-22 16:38:11 -07001311 if ((st.featureId == FEATURE_OPTIONS_PANEL || st.featureId == FEATURE_ACTION_BAR) &&
Adam Powell4369e7d2014-05-17 14:16:08 -07001312 mDecorContentParent != null) {
Alan Viverette4b002d32014-06-03 17:32:19 -07001313 final TypedValue outValue = new TypedValue();
1314 final Theme baseTheme = context.getTheme();
Alan Viverette40982d42014-07-25 17:48:55 -07001315 baseTheme.resolveAttribute(R.attr.actionBarTheme, outValue, true);
Adam Powelld65b3b92011-09-22 16:38:11 -07001316
Alan Viverette4b002d32014-06-03 17:32:19 -07001317 Theme widgetTheme = null;
1318 if (outValue.resourceId != 0) {
1319 widgetTheme = context.getResources().newTheme();
1320 widgetTheme.setTo(baseTheme);
1321 widgetTheme.applyStyle(outValue.resourceId, true);
1322 widgetTheme.resolveAttribute(
Alan Viverette40982d42014-07-25 17:48:55 -07001323 R.attr.actionBarWidgetTheme, outValue, true);
Alan Viverette4b002d32014-06-03 17:32:19 -07001324 } else {
1325 baseTheme.resolveAttribute(
Alan Viverette40982d42014-07-25 17:48:55 -07001326 R.attr.actionBarWidgetTheme, outValue, true);
Alan Viverette4b002d32014-06-03 17:32:19 -07001327 }
1328
1329 if (outValue.resourceId != 0) {
1330 if (widgetTheme == null) {
1331 widgetTheme = context.getResources().newTheme();
1332 widgetTheme.setTo(baseTheme);
1333 }
1334 widgetTheme.applyStyle(outValue.resourceId, true);
1335 }
1336
1337 if (widgetTheme != null) {
1338 context = new ContextThemeWrapper(context, 0);
1339 context.getTheme().setTo(widgetTheme);
Adam Powelld65b3b92011-09-22 16:38:11 -07001340 }
1341 }
1342
1343 final MenuBuilder menu = new MenuBuilder(context);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001344 menu.setCallback(this);
1345 st.setMenu(menu);
1346
1347 return true;
1348 }
1349
1350 /**
1351 * Perform initial setup of a panel. This should at the very least set the
1352 * style information in the PanelFeatureState and must set
1353 * PanelFeatureState.decor to the panel's window decor view.
1354 *
1355 * @param st The panel being initialized.
1356 */
1357 protected boolean initializePanelDecor(PanelFeatureState st) {
Stefan Kuhne61b47bb2015-07-28 14:04:25 -07001358 st.decorView = generateDecor(st.featureId);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001359 st.gravity = Gravity.CENTER | Gravity.BOTTOM;
1360 st.setStyle(getContext());
Adam Powell594558d2014-09-18 18:22:29 -07001361 TypedArray a = getContext().obtainStyledAttributes(null,
1362 R.styleable.Window, 0, st.listPresenterTheme);
1363 final float elevation = a.getDimension(R.styleable.Window_windowElevation, 0);
1364 if (elevation != 0) {
1365 st.decorView.setElevation(elevation);
1366 }
1367 a.recycle();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001368
1369 return true;
1370 }
1371
1372 /**
Adam Powelldfee59a2011-08-05 20:48:30 -07001373 * Determine the gravity value for the options panel. This can
1374 * differ in compact mode.
1375 *
1376 * @return gravity value to use for the panel window
1377 */
1378 private int getOptionsPanelGravity() {
1379 try {
1380 return WindowManagerHolder.sWindowManager.getPreferredOptionsPanelGravity();
1381 } catch (RemoteException ex) {
1382 Log.e(TAG, "Couldn't getOptionsPanelGravity; using default", ex);
1383 return Gravity.CENTER | Gravity.BOTTOM;
1384 }
1385 }
1386
1387 void onOptionsPanelRotationChanged() {
1388 final PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, false);
1389 if (st == null) return;
1390
1391 final WindowManager.LayoutParams lp = st.decorView != null ?
1392 (WindowManager.LayoutParams) st.decorView.getLayoutParams() : null;
1393 if (lp != null) {
1394 lp.gravity = getOptionsPanelGravity();
1395 final ViewManager wm = getWindowManager();
1396 if (wm != null) {
1397 wm.updateViewLayout(st.decorView, lp);
1398 }
1399 }
1400 }
1401
1402 /**
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001403 * Initializes the panel associated with the panel feature state. You must
1404 * at the very least set PanelFeatureState.panel to the View implementing
1405 * its contents. The default implementation gets the panel from the menu.
1406 *
1407 * @param st The panel state being initialized.
1408 * @return Whether the initialization was successful.
1409 */
1410 protected boolean initializePanelContent(PanelFeatureState st) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001411 if (st.createdPanelView != null) {
1412 st.shownPanelView = st.createdPanelView;
1413 return true;
1414 }
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -08001415
Adam Powell696cba52011-03-29 10:38:16 -07001416 if (st.menu == null) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001417 return false;
1418 }
1419
Adam Powell696cba52011-03-29 10:38:16 -07001420 if (mPanelMenuPresenterCallback == null) {
1421 mPanelMenuPresenterCallback = new PanelMenuPresenterCallback();
1422 }
1423
Adam Powelldfee59a2011-08-05 20:48:30 -07001424 MenuView menuView = st.isInListMode()
Adam Powell538e5652011-10-11 13:47:08 -07001425 ? st.getListMenuView(getContext(), mPanelMenuPresenterCallback)
1426 : st.getIconMenuView(getContext(), mPanelMenuPresenterCallback);
Adam Powell696cba52011-03-29 10:38:16 -07001427
1428 st.shownPanelView = (View) menuView;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001429
1430 if (st.shownPanelView != null) {
1431 // Use the menu View's default animations if it has any
Adam Powell696cba52011-03-29 10:38:16 -07001432 final int defaultAnimations = menuView.getWindowAnimations();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001433 if (defaultAnimations != 0) {
1434 st.windowAnimations = defaultAnimations;
1435 }
1436 return true;
1437 } else {
1438 return false;
1439 }
1440 }
1441
1442 @Override
1443 public boolean performContextMenuIdentifierAction(int id, int flags) {
1444 return (mContextMenu != null) ? mContextMenu.performIdentifierAction(id, flags) : false;
1445 }
1446
1447 @Override
Alan Viverette79c067c52014-10-29 14:27:47 -07001448 public final void setElevation(float elevation) {
1449 mElevation = elevation;
Wale Ogunwale246c2092016-04-07 14:12:44 -07001450 final WindowManager.LayoutParams attrs = getAttributes();
Alan Viverette79c067c52014-10-29 14:27:47 -07001451 if (mDecor != null) {
1452 mDecor.setElevation(elevation);
Wale Ogunwale246c2092016-04-07 14:12:44 -07001453 attrs.setSurfaceInsets(mDecor, true /*manual*/, false /*preservePrevious*/);
Alan Viverette79c067c52014-10-29 14:27:47 -07001454 }
Wale Ogunwale246c2092016-04-07 14:12:44 -07001455 dispatchWindowAttributesChanged(attrs);
Alan Viverette79c067c52014-10-29 14:27:47 -07001456 }
1457
1458 @Override
Filip Gruszczynskia59ac9c2015-09-10 18:28:48 -07001459 public float getElevation() {
1460 return mElevation;
1461 }
1462
1463 @Override
Alan Viverette79c067c52014-10-29 14:27:47 -07001464 public final void setClipToOutline(boolean clipToOutline) {
1465 mClipToOutline = clipToOutline;
1466 if (mDecor != null) {
1467 mDecor.setClipToOutline(clipToOutline);
1468 }
1469 }
1470
1471 @Override
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001472 public final void setBackgroundDrawable(Drawable drawable) {
Dianne Hackborna7c176c2009-06-22 20:56:57 -07001473 if (drawable != mBackgroundDrawable || mBackgroundResource != 0) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001474 mBackgroundResource = 0;
1475 mBackgroundDrawable = drawable;
1476 if (mDecor != null) {
1477 mDecor.setWindowBackground(drawable);
1478 }
Adam Powellf849a5e2014-09-11 15:09:36 -07001479 if (mBackgroundFallbackResource != 0) {
1480 mDecor.setBackgroundFallback(drawable != null ? 0 : mBackgroundFallbackResource);
1481 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001482 }
1483 }
1484
1485 @Override
1486 public final void setFeatureDrawableResource(int featureId, int resId) {
1487 if (resId != 0) {
1488 DrawableFeatureState st = getDrawableState(featureId, true);
1489 if (st.resid != resId) {
1490 st.resid = resId;
1491 st.uri = null;
Alan Viverette8eea3ea2014-02-03 18:40:20 -08001492 st.local = getContext().getDrawable(resId);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001493 updateDrawable(featureId, st, false);
1494 }
1495 } else {
1496 setFeatureDrawable(featureId, null);
1497 }
1498 }
1499
1500 @Override
1501 public final void setFeatureDrawableUri(int featureId, Uri uri) {
1502 if (uri != null) {
1503 DrawableFeatureState st = getDrawableState(featureId, true);
1504 if (st.uri == null || !st.uri.equals(uri)) {
1505 st.resid = 0;
1506 st.uri = uri;
1507 st.local = loadImageURI(uri);
1508 updateDrawable(featureId, st, false);
1509 }
1510 } else {
1511 setFeatureDrawable(featureId, null);
1512 }
1513 }
1514
1515 @Override
1516 public final void setFeatureDrawable(int featureId, Drawable drawable) {
1517 DrawableFeatureState st = getDrawableState(featureId, true);
1518 st.resid = 0;
1519 st.uri = null;
1520 if (st.local != drawable) {
1521 st.local = drawable;
1522 updateDrawable(featureId, st, false);
1523 }
1524 }
1525
1526 @Override
1527 public void setFeatureDrawableAlpha(int featureId, int alpha) {
1528 DrawableFeatureState st = getDrawableState(featureId, true);
1529 if (st.alpha != alpha) {
1530 st.alpha = alpha;
1531 updateDrawable(featureId, st, false);
1532 }
1533 }
1534
1535 protected final void setFeatureDefaultDrawable(int featureId, Drawable drawable) {
1536 DrawableFeatureState st = getDrawableState(featureId, true);
1537 if (st.def != drawable) {
1538 st.def = drawable;
1539 updateDrawable(featureId, st, false);
1540 }
1541 }
1542
1543 @Override
1544 public final void setFeatureInt(int featureId, int value) {
1545 // XXX Should do more management (as with drawable features) to
1546 // deal with interactions between multiple window policies.
1547 updateInt(featureId, value, false);
1548 }
1549
1550 /**
1551 * Update the state of a drawable feature. This should be called, for every
1552 * drawable feature supported, as part of onActive(), to make sure that the
1553 * contents of a containing window is properly updated.
1554 *
1555 * @see #onActive
1556 * @param featureId The desired drawable feature to change.
1557 * @param fromActive Always true when called from onActive().
1558 */
1559 protected final void updateDrawable(int featureId, boolean fromActive) {
1560 final DrawableFeatureState st = getDrawableState(featureId, false);
1561 if (st != null) {
1562 updateDrawable(featureId, st, fromActive);
1563 }
1564 }
1565
1566 /**
1567 * Called when a Drawable feature changes, for the window to update its
1568 * graphics.
1569 *
1570 * @param featureId The feature being changed.
1571 * @param drawable The new Drawable to show, or null if none.
1572 * @param alpha The new alpha blending of the Drawable.
1573 */
1574 protected void onDrawableChanged(int featureId, Drawable drawable, int alpha) {
1575 ImageView view;
1576 if (featureId == FEATURE_LEFT_ICON) {
1577 view = getLeftIconView();
1578 } else if (featureId == FEATURE_RIGHT_ICON) {
1579 view = getRightIconView();
1580 } else {
1581 return;
1582 }
1583
1584 if (drawable != null) {
1585 drawable.setAlpha(alpha);
1586 view.setImageDrawable(drawable);
1587 view.setVisibility(View.VISIBLE);
1588 } else {
1589 view.setVisibility(View.GONE);
1590 }
1591 }
1592
1593 /**
1594 * Called when an int feature changes, for the window to update its
1595 * graphics.
1596 *
1597 * @param featureId The feature being changed.
1598 * @param value The new integer value.
1599 */
1600 protected void onIntChanged(int featureId, int value) {
1601 if (featureId == FEATURE_PROGRESS || featureId == FEATURE_INDETERMINATE_PROGRESS) {
1602 updateProgressBars(value);
1603 } else if (featureId == FEATURE_CUSTOM_TITLE) {
Alan Viverette51efddb2017-04-05 10:00:01 -04001604 FrameLayout titleContainer = findViewById(R.id.title_container);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001605 if (titleContainer != null) {
1606 mLayoutInflater.inflate(value, titleContainer);
1607 }
1608 }
1609 }
1610
1611 /**
1612 * Updates the progress bars that are shown in the title bar.
1613 *
1614 * @param value Can be one of {@link Window#PROGRESS_VISIBILITY_ON},
1615 * {@link Window#PROGRESS_VISIBILITY_OFF},
1616 * {@link Window#PROGRESS_INDETERMINATE_ON},
1617 * {@link Window#PROGRESS_INDETERMINATE_OFF}, or a value
1618 * starting at {@link Window#PROGRESS_START} through
1619 * {@link Window#PROGRESS_END} for setting the default
1620 * progress (if {@link Window#PROGRESS_END} is given,
1621 * the progress bar widgets in the title will be hidden after an
1622 * animation), a value between
1623 * {@link Window#PROGRESS_SECONDARY_START} -
1624 * {@link Window#PROGRESS_SECONDARY_END} for the
1625 * secondary progress (if
1626 * {@link Window#PROGRESS_SECONDARY_END} is given, the
1627 * progress bar widgets will still be shown with the secondary
1628 * progress bar will be completely filled in.)
1629 */
1630 private void updateProgressBars(int value) {
1631 ProgressBar circularProgressBar = getCircularProgressBar(true);
1632 ProgressBar horizontalProgressBar = getHorizontalProgressBar(true);
1633
1634 final int features = getLocalFeatures();
1635 if (value == PROGRESS_VISIBILITY_ON) {
1636 if ((features & (1 << FEATURE_PROGRESS)) != 0) {
Adam Powelleec8f0c2014-05-30 11:00:00 -07001637 if (horizontalProgressBar != null) {
1638 int level = horizontalProgressBar.getProgress();
1639 int visibility = (horizontalProgressBar.isIndeterminate() || level < 10000) ?
1640 View.VISIBLE : View.INVISIBLE;
1641 horizontalProgressBar.setVisibility(visibility);
1642 } else {
1643 Log.e(TAG, "Horizontal progress bar not located in current window decor");
1644 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001645 }
1646 if ((features & (1 << FEATURE_INDETERMINATE_PROGRESS)) != 0) {
Adam Powelleec8f0c2014-05-30 11:00:00 -07001647 if (circularProgressBar != null) {
1648 circularProgressBar.setVisibility(View.VISIBLE);
1649 } else {
1650 Log.e(TAG, "Circular progress bar not located in current window decor");
1651 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001652 }
1653 } else if (value == PROGRESS_VISIBILITY_OFF) {
1654 if ((features & (1 << FEATURE_PROGRESS)) != 0) {
Adam Powelleec8f0c2014-05-30 11:00:00 -07001655 if (horizontalProgressBar != null) {
1656 horizontalProgressBar.setVisibility(View.GONE);
1657 } else {
1658 Log.e(TAG, "Horizontal progress bar not located in current window decor");
1659 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001660 }
1661 if ((features & (1 << FEATURE_INDETERMINATE_PROGRESS)) != 0) {
Adam Powelleec8f0c2014-05-30 11:00:00 -07001662 if (circularProgressBar != null) {
1663 circularProgressBar.setVisibility(View.GONE);
1664 } else {
1665 Log.e(TAG, "Circular progress bar not located in current window decor");
1666 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001667 }
1668 } else if (value == PROGRESS_INDETERMINATE_ON) {
Adam Powelleec8f0c2014-05-30 11:00:00 -07001669 if (horizontalProgressBar != null) {
1670 horizontalProgressBar.setIndeterminate(true);
1671 } else {
1672 Log.e(TAG, "Horizontal progress bar not located in current window decor");
1673 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001674 } else if (value == PROGRESS_INDETERMINATE_OFF) {
Adam Powelleec8f0c2014-05-30 11:00:00 -07001675 if (horizontalProgressBar != null) {
1676 horizontalProgressBar.setIndeterminate(false);
1677 } else {
1678 Log.e(TAG, "Horizontal progress bar not located in current window decor");
1679 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001680 } else if (PROGRESS_START <= value && value <= PROGRESS_END) {
1681 // We want to set the progress value before testing for visibility
1682 // so that when the progress bar becomes visible again, it has the
1683 // correct level.
Adam Powelleec8f0c2014-05-30 11:00:00 -07001684 if (horizontalProgressBar != null) {
1685 horizontalProgressBar.setProgress(value - PROGRESS_START);
1686 } else {
1687 Log.e(TAG, "Horizontal progress bar not located in current window decor");
1688 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001689
1690 if (value < PROGRESS_END) {
1691 showProgressBars(horizontalProgressBar, circularProgressBar);
1692 } else {
1693 hideProgressBars(horizontalProgressBar, circularProgressBar);
1694 }
1695 } else if (PROGRESS_SECONDARY_START <= value && value <= PROGRESS_SECONDARY_END) {
Adam Powelleec8f0c2014-05-30 11:00:00 -07001696 if (horizontalProgressBar != null) {
1697 horizontalProgressBar.setSecondaryProgress(value - PROGRESS_SECONDARY_START);
1698 } else {
1699 Log.e(TAG, "Horizontal progress bar not located in current window decor");
1700 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001701
1702 showProgressBars(horizontalProgressBar, circularProgressBar);
1703 }
1704
1705 }
1706
1707 private void showProgressBars(ProgressBar horizontalProgressBar, ProgressBar spinnyProgressBar) {
1708 final int features = getLocalFeatures();
1709 if ((features & (1 << FEATURE_INDETERMINATE_PROGRESS)) != 0 &&
Adam Powelleec8f0c2014-05-30 11:00:00 -07001710 spinnyProgressBar != null && spinnyProgressBar.getVisibility() == View.INVISIBLE) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001711 spinnyProgressBar.setVisibility(View.VISIBLE);
1712 }
1713 // Only show the progress bars if the primary progress is not complete
Adam Powelleec8f0c2014-05-30 11:00:00 -07001714 if ((features & (1 << FEATURE_PROGRESS)) != 0 && horizontalProgressBar != null &&
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001715 horizontalProgressBar.getProgress() < 10000) {
1716 horizontalProgressBar.setVisibility(View.VISIBLE);
1717 }
1718 }
1719
1720 private void hideProgressBars(ProgressBar horizontalProgressBar, ProgressBar spinnyProgressBar) {
1721 final int features = getLocalFeatures();
Alan Viverette40982d42014-07-25 17:48:55 -07001722 Animation anim = AnimationUtils.loadAnimation(getContext(), R.anim.fade_out);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001723 anim.setDuration(1000);
1724 if ((features & (1 << FEATURE_INDETERMINATE_PROGRESS)) != 0 &&
Adam Powelleec8f0c2014-05-30 11:00:00 -07001725 spinnyProgressBar != null &&
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001726 spinnyProgressBar.getVisibility() == View.VISIBLE) {
1727 spinnyProgressBar.startAnimation(anim);
1728 spinnyProgressBar.setVisibility(View.INVISIBLE);
1729 }
Adam Powelleec8f0c2014-05-30 11:00:00 -07001730 if ((features & (1 << FEATURE_PROGRESS)) != 0 && horizontalProgressBar != null &&
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001731 horizontalProgressBar.getVisibility() == View.VISIBLE) {
1732 horizontalProgressBar.startAnimation(anim);
1733 horizontalProgressBar.setVisibility(View.INVISIBLE);
1734 }
1735 }
1736
Adam Powell04fe6eb2013-05-31 14:39:48 -07001737 @Override
1738 public void setIcon(int resId) {
1739 mIconRes = resId;
1740 mResourcesSetFlags |= FLAG_RESOURCE_SET_ICON;
Adam Powell0a317e92013-06-13 13:15:43 -07001741 mResourcesSetFlags &= ~FLAG_RESOURCE_SET_ICON_FALLBACK;
Adam Powell4369e7d2014-05-17 14:16:08 -07001742 if (mDecorContentParent != null) {
1743 mDecorContentParent.setIcon(resId);
Adam Powell04fe6eb2013-05-31 14:39:48 -07001744 }
1745 }
1746
1747 @Override
1748 public void setDefaultIcon(int resId) {
1749 if ((mResourcesSetFlags & FLAG_RESOURCE_SET_ICON) != 0) {
1750 return;
1751 }
1752 mIconRes = resId;
Adam Powell4369e7d2014-05-17 14:16:08 -07001753 if (mDecorContentParent != null && (!mDecorContentParent.hasIcon() ||
Adam Powell0a317e92013-06-13 13:15:43 -07001754 (mResourcesSetFlags & FLAG_RESOURCE_SET_ICON_FALLBACK) != 0)) {
1755 if (resId != 0) {
Adam Powell4369e7d2014-05-17 14:16:08 -07001756 mDecorContentParent.setIcon(resId);
Adam Powell0a317e92013-06-13 13:15:43 -07001757 mResourcesSetFlags &= ~FLAG_RESOURCE_SET_ICON_FALLBACK;
1758 } else {
Adam Powell4369e7d2014-05-17 14:16:08 -07001759 mDecorContentParent.setIcon(
1760 getContext().getPackageManager().getDefaultActivityIcon());
Adam Powell0a317e92013-06-13 13:15:43 -07001761 mResourcesSetFlags |= FLAG_RESOURCE_SET_ICON_FALLBACK;
1762 }
Adam Powell04fe6eb2013-05-31 14:39:48 -07001763 }
1764 }
1765
1766 @Override
1767 public void setLogo(int resId) {
1768 mLogoRes = resId;
1769 mResourcesSetFlags |= FLAG_RESOURCE_SET_LOGO;
Adam Powell4369e7d2014-05-17 14:16:08 -07001770 if (mDecorContentParent != null) {
1771 mDecorContentParent.setLogo(resId);
Adam Powell04fe6eb2013-05-31 14:39:48 -07001772 }
1773 }
1774
1775 @Override
1776 public void setDefaultLogo(int resId) {
1777 if ((mResourcesSetFlags & FLAG_RESOURCE_SET_LOGO) != 0) {
1778 return;
1779 }
1780 mLogoRes = resId;
Adam Powell4369e7d2014-05-17 14:16:08 -07001781 if (mDecorContentParent != null && !mDecorContentParent.hasLogo()) {
1782 mDecorContentParent.setLogo(resId);
Adam Powell04fe6eb2013-05-31 14:39:48 -07001783 }
1784 }
1785
keunyoung30f420f2013-08-02 14:23:10 -07001786 @Override
1787 public void setLocalFocus(boolean hasFocus, boolean inTouchMode) {
1788 getViewRootImpl().windowFocusChanged(hasFocus, inTouchMode);
1789
1790 }
1791
1792 @Override
1793 public void injectInputEvent(InputEvent event) {
1794 getViewRootImpl().dispatchInputEvent(event);
1795 }
1796
1797 private ViewRootImpl getViewRootImpl() {
1798 if (mDecor != null) {
1799 ViewRootImpl viewRootImpl = mDecor.getViewRootImpl();
1800 if (viewRootImpl != null) {
1801 return viewRootImpl;
1802 }
1803 }
1804 throw new IllegalStateException("view not added");
1805 }
1806
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001807 /**
1808 * Request that key events come to this activity. Use this if your activity
1809 * has no views with focus, but the activity still wants a chance to process
1810 * key events.
1811 */
1812 @Override
1813 public void takeKeyEvents(boolean get) {
1814 mDecor.setFocusable(get);
1815 }
1816
1817 @Override
1818 public boolean superDispatchKeyEvent(KeyEvent event) {
1819 return mDecor.superDispatchKeyEvent(event);
1820 }
1821
1822 @Override
Jeff Brown64da12a2011-01-04 19:57:47 -08001823 public boolean superDispatchKeyShortcutEvent(KeyEvent event) {
1824 return mDecor.superDispatchKeyShortcutEvent(event);
1825 }
1826
1827 @Override
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001828 public boolean superDispatchTouchEvent(MotionEvent event) {
1829 return mDecor.superDispatchTouchEvent(event);
1830 }
1831
1832 @Override
1833 public boolean superDispatchTrackballEvent(MotionEvent event) {
1834 return mDecor.superDispatchTrackballEvent(event);
1835 }
1836
Jeff Browncb1404e2011-01-15 18:14:15 -08001837 @Override
1838 public boolean superDispatchGenericMotionEvent(MotionEvent event) {
1839 return mDecor.superDispatchGenericMotionEvent(event);
1840 }
1841
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001842 /**
1843 * A key was pressed down and not handled by anything else in the window.
1844 *
1845 * @see #onKeyUp
1846 * @see android.view.KeyEvent
1847 */
1848 protected boolean onKeyDown(int featureId, int keyCode, KeyEvent event) {
Joe Onorato86f67862010-11-05 18:57:34 -07001849 /* ****************************************************************************
1850 * HOW TO DECIDE WHERE YOUR KEY HANDLING GOES.
1851 *
1852 * If your key handling must happen before the app gets a crack at the event,
1853 * it goes in PhoneWindowManager.
1854 *
1855 * If your key handling should happen in all windows, and does not depend on
1856 * the state of the current application, other than that the current
1857 * application can override the behavior by handling the event itself, it
1858 * should go in PhoneFallbackEventHandler.
1859 *
1860 * Only if your handling depends on the window, and the fact that it has
1861 * a DecorView, should it go here.
1862 * ****************************************************************************/
1863
Dianne Hackborna207baa2009-09-13 16:14:44 -07001864 final KeyEvent.DispatcherState dispatcher =
1865 mDecor != null ? mDecor.getKeyDispatcherState() : null;
1866 //Log.i(TAG, "Key down: repeat=" + event.getRepeatCount()
1867 // + " flags=0x" + Integer.toHexString(event.getFlags()));
Alan Viveretteeb1d3792014-06-03 18:36:03 -07001868
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001869 switch (keyCode) {
1870 case KeyEvent.KEYCODE_VOLUME_UP:
RoboErik5452e252015-02-06 15:33:53 -08001871 case KeyEvent.KEYCODE_VOLUME_DOWN:
1872 case KeyEvent.KEYCODE_VOLUME_MUTE: {
RoboErik55011652014-07-09 15:05:53 -07001873 // If we have a session send it the volume command, otherwise
1874 // use the suggested stream.
1875 if (mMediaController != null) {
Jaewan Kim50269362016-12-23 11:22:02 +09001876 int direction = 0;
1877 switch (keyCode) {
1878 case KeyEvent.KEYCODE_VOLUME_UP:
1879 direction = AudioManager.ADJUST_RAISE;
1880 break;
1881 case KeyEvent.KEYCODE_VOLUME_DOWN:
1882 direction = AudioManager.ADJUST_LOWER;
1883 break;
1884 case KeyEvent.KEYCODE_VOLUME_MUTE:
1885 direction = AudioManager.ADJUST_TOGGLE_MUTE;
1886 break;
1887 }
RoboErik1ff5b162014-07-15 17:23:18 -07001888 mMediaController.adjustVolume(direction, AudioManager.FLAG_SHOW_UI);
RoboErik55011652014-07-09 15:05:53 -07001889 } else {
Jaewan Kim50269362016-12-23 11:22:02 +09001890 MediaSessionLegacyHelper.getHelper(getContext()).sendVolumeKeyEvent(
1891 event, mVolumeControlStreamType, false);
RoboErik55011652014-07-09 15:05:53 -07001892 }
1893 return true;
1894 }
RoboErik55011652014-07-09 15:05:53 -07001895 // These are all the recognized media key codes in
1896 // KeyEvent.isMediaKey()
1897 case KeyEvent.KEYCODE_MEDIA_PLAY:
1898 case KeyEvent.KEYCODE_MEDIA_PAUSE:
1899 case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
1900 case KeyEvent.KEYCODE_MUTE:
1901 case KeyEvent.KEYCODE_HEADSETHOOK:
1902 case KeyEvent.KEYCODE_MEDIA_STOP:
1903 case KeyEvent.KEYCODE_MEDIA_NEXT:
1904 case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
1905 case KeyEvent.KEYCODE_MEDIA_REWIND:
1906 case KeyEvent.KEYCODE_MEDIA_RECORD:
1907 case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: {
1908 if (mMediaController != null) {
1909 if (mMediaController.dispatchMediaButtonEvent(event)) {
1910 return true;
1911 }
1912 }
RoboErik28204a72014-07-17 12:17:27 -07001913 return false;
RoboErik55011652014-07-09 15:05:53 -07001914 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001915
1916 case KeyEvent.KEYCODE_MENU: {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001917 onKeyDownPanel((featureId < 0) ? FEATURE_OPTIONS_PANEL : featureId, event);
1918 return true;
1919 }
1920
1921 case KeyEvent.KEYCODE_BACK: {
1922 if (event.getRepeatCount() > 0) break;
1923 if (featureId < 0) break;
Dianne Hackbornfed9cb52009-09-14 21:23:11 -07001924 // Currently don't do anything with long press.
Winson Chung45d378b2011-09-08 19:02:06 -07001925 if (dispatcher != null) {
1926 dispatcher.startTracking(event, this);
1927 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001928 return true;
1929 }
1930
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001931 }
1932
1933 return false;
1934 }
1935
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001936 private KeyguardManager getKeyguardManager() {
1937 if (mKeyguardManager == null) {
Joe Onorato86f67862010-11-05 18:57:34 -07001938 mKeyguardManager = (KeyguardManager) getContext().getSystemService(
1939 Context.KEYGUARD_SERVICE);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001940 }
1941 return mKeyguardManager;
1942 }
Joe Onorato86f67862010-11-05 18:57:34 -07001943
1944 AudioManager getAudioManager() {
1945 if (mAudioManager == null) {
1946 mAudioManager = (AudioManager)getContext().getSystemService(Context.AUDIO_SERVICE);
Mike LeBeaubfd25ca2010-03-22 17:40:35 -07001947 }
Joe Onorato86f67862010-11-05 18:57:34 -07001948 return mAudioManager;
Mike LeBeaubfd25ca2010-03-22 17:40:35 -07001949 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001950
1951 /**
1952 * A key was released and not handled by anything else in the window.
1953 *
1954 * @see #onKeyDown
1955 * @see android.view.KeyEvent
1956 */
1957 protected boolean onKeyUp(int featureId, int keyCode, KeyEvent event) {
Dianne Hackborna207baa2009-09-13 16:14:44 -07001958 final KeyEvent.DispatcherState dispatcher =
1959 mDecor != null ? mDecor.getKeyDispatcherState() : null;
1960 if (dispatcher != null) {
1961 dispatcher.handleUpEvent(event);
1962 }
1963 //Log.i(TAG, "Key up: repeat=" + event.getRepeatCount()
1964 // + " flags=0x" + Integer.toHexString(event.getFlags()));
Alan Viveretteeb1d3792014-06-03 18:36:03 -07001965
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001966 switch (keyCode) {
1967 case KeyEvent.KEYCODE_VOLUME_UP:
RoboErik55011652014-07-09 15:05:53 -07001968 case KeyEvent.KEYCODE_VOLUME_DOWN: {
1969 // If we have a session send it the volume command, otherwise
1970 // use the suggested stream.
1971 if (mMediaController != null) {
Jaewan Kim50269362016-12-23 11:22:02 +09001972 final int flags = AudioManager.FLAG_PLAY_SOUND | AudioManager.FLAG_VIBRATE
1973 | AudioManager.FLAG_FROM_KEY;
John Spurlockb94f2d62015-03-17 14:11:57 -04001974 mMediaController.adjustVolume(0, flags);
RoboErik55011652014-07-09 15:05:53 -07001975 } else {
Jaewan Kim50269362016-12-23 11:22:02 +09001976 MediaSessionLegacyHelper.getHelper(getContext()).sendVolumeKeyEvent(
1977 event, mVolumeControlStreamType, false);
RoboErik55011652014-07-09 15:05:53 -07001978 }
1979 return true;
1980 }
Jeff Brownb0418da2010-11-01 15:24:01 -07001981 case KeyEvent.KEYCODE_VOLUME_MUTE: {
Joe Onorato86f67862010-11-05 18:57:34 -07001982 // Similar code is in PhoneFallbackEventHandler in case the window
1983 // doesn't have one of these. In this case, we execute it here and
1984 // eat the event instead, because we have mVolumeControlStreamType
1985 // and they don't.
Jaewan Kim50269362016-12-23 11:22:02 +09001986 MediaSessionLegacyHelper.getHelper(getContext()).sendVolumeKeyEvent(
1987 event, AudioManager.USE_DEFAULT_STREAM_TYPE, false);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001988 return true;
1989 }
RoboErik55011652014-07-09 15:05:53 -07001990 // These are all the recognized media key codes in
1991 // KeyEvent.isMediaKey()
1992 case KeyEvent.KEYCODE_MEDIA_PLAY:
1993 case KeyEvent.KEYCODE_MEDIA_PAUSE:
1994 case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
1995 case KeyEvent.KEYCODE_MUTE:
1996 case KeyEvent.KEYCODE_HEADSETHOOK:
1997 case KeyEvent.KEYCODE_MEDIA_STOP:
1998 case KeyEvent.KEYCODE_MEDIA_NEXT:
1999 case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
2000 case KeyEvent.KEYCODE_MEDIA_REWIND:
2001 case KeyEvent.KEYCODE_MEDIA_RECORD:
2002 case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: {
2003 if (mMediaController != null) {
2004 if (mMediaController.dispatchMediaButtonEvent(event)) {
2005 return true;
2006 }
2007 }
RoboErik28204a72014-07-17 12:17:27 -07002008 return false;
RoboErik55011652014-07-09 15:05:53 -07002009 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002010
2011 case KeyEvent.KEYCODE_MENU: {
Adam Powellf6148c52010-08-11 21:10:16 -07002012 onKeyUpPanel(featureId < 0 ? FEATURE_OPTIONS_PANEL : featureId,
2013 event);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002014 return true;
2015 }
2016
Dianne Hackborna207baa2009-09-13 16:14:44 -07002017 case KeyEvent.KEYCODE_BACK: {
2018 if (featureId < 0) break;
Dianne Hackbornfed9cb52009-09-14 21:23:11 -07002019 if (event.isTracking() && !event.isCanceled()) {
2020 if (featureId == FEATURE_OPTIONS_PANEL) {
2021 PanelFeatureState st = getPanelState(featureId, false);
2022 if (st != null && st.isInExpandedMode) {
2023 // If the user is in an expanded menu and hits back, it
2024 // should go back to the icon menu
2025 reopenMenu(true);
2026 return true;
2027 }
Dianne Hackborna207baa2009-09-13 16:14:44 -07002028 }
Dianne Hackbornfed9cb52009-09-14 21:23:11 -07002029 closePanel(featureId);
2030 return true;
Dianne Hackborna207baa2009-09-13 16:14:44 -07002031 }
Dianne Hackbornfed9cb52009-09-14 21:23:11 -07002032 break;
Dianne Hackborna207baa2009-09-13 16:14:44 -07002033 }
2034
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002035 case KeyEvent.KEYCODE_SEARCH: {
2036 /*
2037 * Do this in onKeyUp since the Search key is also used for
2038 * chording quick launch shortcuts.
2039 */
Dianne Hackborna207baa2009-09-13 16:14:44 -07002040 if (getKeyguardManager().inKeyguardRestrictedInputMode()) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002041 break;
2042 }
Dianne Hackborna207baa2009-09-13 16:14:44 -07002043 if (event.isTracking() && !event.isCanceled()) {
Tim Kilbourn6a975b32015-04-09 17:14:34 -07002044 launchDefaultSearch(event);
Dianne Hackborn0041e972009-07-24 17:14:43 -07002045 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002046 return true;
2047 }
Jaewan Kimf0fd2182016-04-20 21:17:58 +09002048
2049 case KeyEvent.KEYCODE_WINDOW: {
Jaewan Kimd98dcab2016-05-03 02:52:18 +09002050 if (mSupportsPictureInPicture && !event.isCanceled()) {
2051 getWindowControllerCallback().enterPictureInPictureModeIfPossible();
Jaewan Kimf0fd2182016-04-20 21:17:58 +09002052 }
2053 return true;
2054 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002055 }
2056
2057 return false;
2058 }
2059
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002060 @Override
2061 protected void onActive() {
2062 }
2063
2064 @Override
2065 public final View getDecorView() {
Filip Gruszczynskia59ac9c2015-09-10 18:28:48 -07002066 if (mDecor == null || mForceDecorInstall) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002067 installDecor();
2068 }
2069 return mDecor;
2070 }
2071
2072 @Override
2073 public final View peekDecorView() {
2074 return mDecor;
2075 }
2076
Andrii Kulian51c1b672017-04-07 18:39:32 -07002077 /** Notify when decor view is attached to window and {@link ViewRootImpl} is available. */
2078 void onViewRootImplSet(ViewRootImpl viewRoot) {
2079 viewRoot.setActivityConfigCallback(mActivityConfigCallback);
2080 }
2081
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002082 static private final String FOCUSED_ID_TAG = "android:focusedViewId";
2083 static private final String VIEWS_TAG = "android:views";
2084 static private final String PANELS_TAG = "android:Panels";
Adam Powell6c6f5752010-08-20 18:34:46 -07002085 static private final String ACTION_BAR_TAG = "android:ActionBar";
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002086
Alan Viveretteeae66cd2015-08-13 20:05:35 +00002087 /** {@inheritDoc} */
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002088 @Override
2089 public Bundle saveHierarchyState() {
Alan Viveretteeae66cd2015-08-13 20:05:35 +00002090 Bundle outState = new Bundle();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002091 if (mContentParent == null) {
2092 return outState;
2093 }
2094
Alan Viveretteeae66cd2015-08-13 20:05:35 +00002095 SparseArray<Parcelable> states = new SparseArray<Parcelable>();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002096 mContentParent.saveHierarchyState(states);
2097 outState.putSparseParcelableArray(VIEWS_TAG, states);
2098
Alan Viveretteec6cf182015-08-13 15:31:57 -04002099 // Save the focused view ID.
2100 final View focusedView = mContentParent.findFocus();
2101 if (focusedView != null && focusedView.getId() != View.NO_ID) {
2102 outState.putInt(FOCUSED_ID_TAG, focusedView.getId());
2103 }
2104
Alan Viveretteeae66cd2015-08-13 20:05:35 +00002105 // save the panels
2106 SparseArray<Parcelable> panelStates = new SparseArray<Parcelable>();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002107 savePanelState(panelStates);
2108 if (panelStates.size() > 0) {
2109 outState.putSparseParcelableArray(PANELS_TAG, panelStates);
2110 }
2111
Adam Powell4369e7d2014-05-17 14:16:08 -07002112 if (mDecorContentParent != null) {
Alan Viveretteeae66cd2015-08-13 20:05:35 +00002113 SparseArray<Parcelable> actionBarStates = new SparseArray<Parcelable>();
Adam Powell4369e7d2014-05-17 14:16:08 -07002114 mDecorContentParent.saveToolbarHierarchyState(actionBarStates);
Adam Powell8d02dea2011-05-31 21:35:13 -07002115 outState.putSparseParcelableArray(ACTION_BAR_TAG, actionBarStates);
Adam Powell6c6f5752010-08-20 18:34:46 -07002116 }
2117
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002118 return outState;
2119 }
2120
Alan Viveretteeae66cd2015-08-13 20:05:35 +00002121 /** {@inheritDoc} */
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002122 @Override
2123 public void restoreHierarchyState(Bundle savedInstanceState) {
2124 if (mContentParent == null) {
2125 return;
2126 }
2127
Alan Viveretteeae66cd2015-08-13 20:05:35 +00002128 SparseArray<Parcelable> savedStates
2129 = savedInstanceState.getSparseParcelableArray(VIEWS_TAG);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002130 if (savedStates != null) {
2131 mContentParent.restoreHierarchyState(savedStates);
2132 }
2133
Alan Viveretteeae66cd2015-08-13 20:05:35 +00002134 // restore the focused view
2135 int focusedViewId = savedInstanceState.getInt(FOCUSED_ID_TAG, View.NO_ID);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002136 if (focusedViewId != View.NO_ID) {
Alan Viveretteeae66cd2015-08-13 20:05:35 +00002137 View needsFocus = mContentParent.findViewById(focusedViewId);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002138 if (needsFocus != null) {
2139 needsFocus.requestFocus();
2140 } else {
Alan Viveretteeae66cd2015-08-13 20:05:35 +00002141 Log.w(TAG,
2142 "Previously focused view reported id " + focusedViewId
2143 + " during save, but can't be found during restore.");
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002144 }
2145 }
2146
Alan Viveretteec6cf182015-08-13 15:31:57 -04002147 // Restore the panels.
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002148 SparseArray<Parcelable> panelStates = savedInstanceState.getSparseParcelableArray(PANELS_TAG);
2149 if (panelStates != null) {
2150 restorePanelState(panelStates);
2151 }
Adam Powell6c6f5752010-08-20 18:34:46 -07002152
Adam Powell4369e7d2014-05-17 14:16:08 -07002153 if (mDecorContentParent != null) {
Adam Powell8d02dea2011-05-31 21:35:13 -07002154 SparseArray<Parcelable> actionBarStates =
2155 savedInstanceState.getSparseParcelableArray(ACTION_BAR_TAG);
Adam Powellfb5f1bc2012-05-17 19:30:35 -07002156 if (actionBarStates != null) {
Adam Powell31c91c82014-08-22 17:20:00 -07002157 doPendingInvalidatePanelMenu();
Adam Powell4369e7d2014-05-17 14:16:08 -07002158 mDecorContentParent.restoreToolbarHierarchyState(actionBarStates);
Adam Powellfb5f1bc2012-05-17 19:30:35 -07002159 } else {
2160 Log.w(TAG, "Missing saved instance states for action bar views! " +
2161 "State will not be restored.");
2162 }
Adam Powell6c6f5752010-08-20 18:34:46 -07002163 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002164 }
2165
2166 /**
2167 * Invoked when the panels should freeze their state.
2168 *
2169 * @param icicles Save state into this. This is usually indexed by the
2170 * featureId. This will be given to {@link #restorePanelState} in the
2171 * future.
2172 */
2173 private void savePanelState(SparseArray<Parcelable> icicles) {
2174 PanelFeatureState[] panels = mPanels;
2175 if (panels == null) {
2176 return;
2177 }
2178
2179 for (int curFeatureId = panels.length - 1; curFeatureId >= 0; curFeatureId--) {
2180 if (panels[curFeatureId] != null) {
2181 icicles.put(curFeatureId, panels[curFeatureId].onSaveInstanceState());
2182 }
2183 }
2184 }
2185
2186 /**
2187 * Invoked when the panels should thaw their state from a previously frozen state.
2188 *
2189 * @param icicles The state saved by {@link #savePanelState} that needs to be thawed.
2190 */
2191 private void restorePanelState(SparseArray<Parcelable> icicles) {
2192 PanelFeatureState st;
Dmitry Tsyganyuk554bb012012-04-02 13:10:52 -05002193 int curFeatureId;
2194 for (int i = icicles.size() - 1; i >= 0; i--) {
2195 curFeatureId = icicles.keyAt(i);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002196 st = getPanelState(curFeatureId, false /* required */);
2197 if (st == null) {
2198 // The panel must not have been required, and is currently not around, skip it
2199 continue;
2200 }
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -08002201
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002202 st.onRestoreInstanceState(icicles.get(curFeatureId));
Adam Powell31bb97d2011-05-03 20:58:31 -07002203 invalidatePanelMenu(curFeatureId);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002204 }
2205
2206 /*
2207 * Implementation note: call openPanelsAfterRestore later to actually open the
2208 * restored panels.
2209 */
2210 }
2211
2212 /**
2213 * Opens the panels that have had their state restored. This should be
2214 * called sometime after {@link #restorePanelState} when it is safe to add
2215 * to the window manager.
2216 */
Wale Ogunwale8804af22015-11-17 09:18:15 -08002217 void openPanelsAfterRestore() {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002218 PanelFeatureState[] panels = mPanels;
2219
2220 if (panels == null) {
2221 return;
2222 }
2223
2224 PanelFeatureState st;
2225 for (int i = panels.length - 1; i >= 0; i--) {
2226 st = panels[i];
Dianne Hackbornd0071442009-09-25 01:35:29 -07002227 // We restore the panel if it was last open; we skip it if it
2228 // now is open, to avoid a race condition if the user immediately
2229 // opens it when we are resuming.
Adam Powell11ed1d62011-07-11 21:19:59 -07002230 if (st != null) {
2231 st.applyFrozenState();
2232 if (!st.isOpen && st.wasLastOpen) {
2233 st.isInExpandedMode = st.wasLastExpanded;
2234 openPanel(st, null);
2235 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002236 }
2237 }
2238 }
2239
Adam Powell696cba52011-03-29 10:38:16 -07002240 private class PanelMenuPresenterCallback implements MenuPresenter.Callback {
2241 @Override
2242 public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) {
2243 final Menu parentMenu = menu.getRootMenu();
2244 final boolean isSubMenu = parentMenu != menu;
2245 final PanelFeatureState panel = findMenuPanel(isSubMenu ? parentMenu : menu);
2246 if (panel != null) {
2247 if (isSubMenu) {
2248 callOnPanelClosed(panel.featureId, panel, parentMenu);
2249 closePanel(panel, true);
2250 } else {
2251 // Close the panel and only do the callback if the menu is being
2252 // closed completely, not if opening a sub menu
2253 closePanel(panel, allMenusAreClosing);
2254 }
2255 }
2256 }
2257
2258 @Override
2259 public boolean onOpenSubMenu(MenuBuilder subMenu) {
2260 if (subMenu == null && hasFeature(FEATURE_ACTION_BAR)) {
2261 Callback cb = getCallback();
2262 if (cb != null && !isDestroyed()) {
2263 cb.onMenuOpened(FEATURE_ACTION_BAR, subMenu);
2264 }
2265 }
2266
2267 return true;
2268 }
2269 }
2270
2271 private final class ActionMenuPresenterCallback implements MenuPresenter.Callback {
2272 @Override
2273 public boolean onOpenSubMenu(MenuBuilder subMenu) {
2274 Callback cb = getCallback();
2275 if (cb != null) {
2276 cb.onMenuOpened(FEATURE_ACTION_BAR, subMenu);
2277 return true;
2278 }
2279 return false;
2280 }
2281
2282 @Override
2283 public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) {
2284 checkCloseActionMenu(menu);
2285 }
2286 }
2287
Stefan Kuhne61b47bb2015-07-28 14:04:25 -07002288 protected DecorView generateDecor(int featureId) {
Filip Gruszczynski0daf2102015-09-29 08:39:07 -07002289 // System process doesn't have application context and in that case we need to directly use
2290 // the context we have. Otherwise we want the application context, so we don't cling to the
2291 // activity.
Filip Gruszczynski0daf2102015-09-29 08:39:07 -07002292 Context context;
Filip Gruszczynski796b8c12015-12-22 14:46:21 -08002293 if (mUseDecorContext) {
2294 Context applicationContext = getContext().getApplicationContext();
2295 if (applicationContext == null) {
2296 context = getContext();
2297 } else {
Adam Lesinskiff22a562016-04-18 12:14:12 -07002298 context = new DecorContext(applicationContext, getContext().getResources());
Filip Gruszczynski796b8c12015-12-22 14:46:21 -08002299 if (mTheme != -1) {
2300 context.setTheme(mTheme);
2301 }
Filip Gruszczynski0daf2102015-09-29 08:39:07 -07002302 }
Filip Gruszczynski796b8c12015-12-22 14:46:21 -08002303 } else {
2304 context = getContext();
Filip Gruszczynski0daf2102015-09-29 08:39:07 -07002305 }
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08002306 return new DecorView(context, featureId, this, getAttributes());
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002307 }
2308
2309 protected ViewGroup generateLayout(DecorView decor) {
2310 // Apply data from current theme.
2311
2312 TypedArray a = getWindowStyle();
2313
2314 if (false) {
2315 System.out.println("From style:");
2316 String s = "Attrs:";
Alan Viverette40982d42014-07-25 17:48:55 -07002317 for (int i = 0; i < R.styleable.Window.length; i++) {
2318 s = s + " " + Integer.toHexString(R.styleable.Window[i]) + "="
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002319 + a.getString(i);
2320 }
2321 System.out.println(s);
2322 }
2323
Alan Viverette40982d42014-07-25 17:48:55 -07002324 mIsFloating = a.getBoolean(R.styleable.Window_windowIsFloating, false);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002325 int flagsToUpdate = (FLAG_LAYOUT_IN_SCREEN|FLAG_LAYOUT_INSET_DECOR)
2326 & (~getForcedWindowFlags());
2327 if (mIsFloating) {
2328 setLayout(WRAP_CONTENT, WRAP_CONTENT);
2329 setFlags(0, flagsToUpdate);
2330 } else {
2331 setFlags(FLAG_LAYOUT_IN_SCREEN|FLAG_LAYOUT_INSET_DECOR, flagsToUpdate);
2332 }
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -08002333
Alan Viverette40982d42014-07-25 17:48:55 -07002334 if (a.getBoolean(R.styleable.Window_windowNoTitle, false)) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002335 requestFeature(FEATURE_NO_TITLE);
Alan Viverette40982d42014-07-25 17:48:55 -07002336 } else if (a.getBoolean(R.styleable.Window_windowActionBar, false)) {
Adam Powell33b97432010-04-20 10:01:14 -07002337 // Don't allow an action bar if there is no title.
2338 requestFeature(FEATURE_ACTION_BAR);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002339 }
2340
Alan Viverette40982d42014-07-25 17:48:55 -07002341 if (a.getBoolean(R.styleable.Window_windowActionBarOverlay, false)) {
Adam Powell6b336f82010-08-10 20:13:01 -07002342 requestFeature(FEATURE_ACTION_BAR_OVERLAY);
2343 }
2344
Alan Viverette40982d42014-07-25 17:48:55 -07002345 if (a.getBoolean(R.styleable.Window_windowActionModeOverlay, false)) {
Adam Powell5d279772010-07-27 16:34:07 -07002346 requestFeature(FEATURE_ACTION_MODE_OVERLAY);
2347 }
2348
Alan Viverette40982d42014-07-25 17:48:55 -07002349 if (a.getBoolean(R.styleable.Window_windowSwipeToDismiss, false)) {
Will Haldean Brownca6234e2014-02-12 10:23:41 -08002350 requestFeature(FEATURE_SWIPE_TO_DISMISS);
2351 }
2352
Alan Viverette40982d42014-07-25 17:48:55 -07002353 if (a.getBoolean(R.styleable.Window_windowFullscreen, false)) {
Dianne Hackbornc652de82013-02-15 16:32:56 -08002354 setFlags(FLAG_FULLSCREEN, FLAG_FULLSCREEN & (~getForcedWindowFlags()));
2355 }
2356
Alan Viverette40982d42014-07-25 17:48:55 -07002357 if (a.getBoolean(R.styleable.Window_windowTranslucentStatus,
John Spurlockbd957402013-10-03 11:38:39 -04002358 false)) {
2359 setFlags(FLAG_TRANSLUCENT_STATUS, FLAG_TRANSLUCENT_STATUS
2360 & (~getForcedWindowFlags()));
2361 }
2362
Alan Viverette40982d42014-07-25 17:48:55 -07002363 if (a.getBoolean(R.styleable.Window_windowTranslucentNavigation,
John Spurlockbd957402013-10-03 11:38:39 -04002364 false)) {
2365 setFlags(FLAG_TRANSLUCENT_NAVIGATION, FLAG_TRANSLUCENT_NAVIGATION
2366 & (~getForcedWindowFlags()));
2367 }
2368
Alan Viverette40982d42014-07-25 17:48:55 -07002369 if (a.getBoolean(R.styleable.Window_windowOverscan, false)) {
Dianne Hackbornc652de82013-02-15 16:32:56 -08002370 setFlags(FLAG_LAYOUT_IN_OVERSCAN, FLAG_LAYOUT_IN_OVERSCAN&(~getForcedWindowFlags()));
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002371 }
2372
Alan Viverette40982d42014-07-25 17:48:55 -07002373 if (a.getBoolean(R.styleable.Window_windowShowWallpaper, false)) {
Dianne Hackborn4bf7bcf2009-08-09 17:23:00 -07002374 setFlags(FLAG_SHOW_WALLPAPER, FLAG_SHOW_WALLPAPER&(~getForcedWindowFlags()));
2375 }
2376
Alan Viverette40982d42014-07-25 17:48:55 -07002377 if (a.getBoolean(R.styleable.Window_windowEnableSplitTouch,
Jeff Brown46e75292010-11-10 16:53:45 -08002378 getContext().getApplicationInfo().targetSdkVersion
2379 >= android.os.Build.VERSION_CODES.HONEYCOMB)) {
2380 setFlags(FLAG_SPLIT_TOUCH, FLAG_SPLIT_TOUCH&(~getForcedWindowFlags()));
2381 }
2382
Alan Viverette40982d42014-07-25 17:48:55 -07002383 a.getValue(R.styleable.Window_windowMinWidthMajor, mMinWidthMajor);
2384 a.getValue(R.styleable.Window_windowMinWidthMinor, mMinWidthMinor);
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08002385 if (DEBUG) Log.d(TAG, "Min width minor: " + mMinWidthMinor.coerceToString()
2386 + ", major: " + mMinWidthMajor.coerceToString());
Alan Viverette40982d42014-07-25 17:48:55 -07002387 if (a.hasValue(R.styleable.Window_windowFixedWidthMajor)) {
Adam Powell40eec4c2012-02-15 17:10:58 -08002388 if (mFixedWidthMajor == null) mFixedWidthMajor = new TypedValue();
Alan Viverette40982d42014-07-25 17:48:55 -07002389 a.getValue(R.styleable.Window_windowFixedWidthMajor,
Adam Powell40eec4c2012-02-15 17:10:58 -08002390 mFixedWidthMajor);
2391 }
Alan Viverette40982d42014-07-25 17:48:55 -07002392 if (a.hasValue(R.styleable.Window_windowFixedWidthMinor)) {
Adam Powell40eec4c2012-02-15 17:10:58 -08002393 if (mFixedWidthMinor == null) mFixedWidthMinor = new TypedValue();
Alan Viverette40982d42014-07-25 17:48:55 -07002394 a.getValue(R.styleable.Window_windowFixedWidthMinor,
Adam Powell40eec4c2012-02-15 17:10:58 -08002395 mFixedWidthMinor);
2396 }
Alan Viverette40982d42014-07-25 17:48:55 -07002397 if (a.hasValue(R.styleable.Window_windowFixedHeightMajor)) {
Adam Powell40eec4c2012-02-15 17:10:58 -08002398 if (mFixedHeightMajor == null) mFixedHeightMajor = new TypedValue();
Alan Viverette40982d42014-07-25 17:48:55 -07002399 a.getValue(R.styleable.Window_windowFixedHeightMajor,
Adam Powell40eec4c2012-02-15 17:10:58 -08002400 mFixedHeightMajor);
2401 }
Alan Viverette40982d42014-07-25 17:48:55 -07002402 if (a.hasValue(R.styleable.Window_windowFixedHeightMinor)) {
Adam Powell40eec4c2012-02-15 17:10:58 -08002403 if (mFixedHeightMinor == null) mFixedHeightMinor = new TypedValue();
Alan Viverette40982d42014-07-25 17:48:55 -07002404 a.getValue(R.styleable.Window_windowFixedHeightMinor,
Adam Powell40eec4c2012-02-15 17:10:58 -08002405 mFixedHeightMinor);
2406 }
Alan Viverette40982d42014-07-25 17:48:55 -07002407 if (a.getBoolean(R.styleable.Window_windowContentTransitions, false)) {
Adam Powell18e905f2013-10-24 14:27:48 -07002408 requestFeature(FEATURE_CONTENT_TRANSITIONS);
Michael Kolb4bb047f2014-04-01 14:38:57 -07002409 }
George Mount9826f632014-09-11 08:50:09 -07002410 if (a.getBoolean(R.styleable.Window_windowActivityTransitions, false)) {
2411 requestFeature(FEATURE_ACTIVITY_TRANSITIONS);
2412 }
Filip Gruszczynskib57503c2014-07-16 16:35:18 -07002413
Jorim Jaggic39c7b02016-03-24 10:47:07 -07002414 mIsTranslucent = a.getBoolean(R.styleable.Window_windowIsTranslucent, false);
2415
Adam Powell82349c52011-08-23 13:53:56 -07002416 final Context context = getContext();
2417 final int targetSdk = context.getApplicationInfo().targetSdkVersion;
2418 final boolean targetPreHoneycomb = targetSdk < android.os.Build.VERSION_CODES.HONEYCOMB;
2419 final boolean targetPreIcs = targetSdk < android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH;
Dianne Hackborn955d8d62014-10-07 20:17:19 -07002420 final boolean targetPreL = targetSdk < android.os.Build.VERSION_CODES.LOLLIPOP;
Adam Powell82349c52011-08-23 13:53:56 -07002421 final boolean targetHcNeedsOptions = context.getResources().getBoolean(
Alan Viverette40982d42014-07-25 17:48:55 -07002422 R.bool.target_honeycomb_needs_options_menu);
Adam Powell82349c52011-08-23 13:53:56 -07002423 final boolean noActionBar = !hasFeature(FEATURE_ACTION_BAR) || hasFeature(FEATURE_NO_TITLE);
2424
2425 if (targetPreHoneycomb || (targetPreIcs && targetHcNeedsOptions && noActionBar)) {
Wale Ogunwale393b1c12014-10-18 16:22:01 -07002426 setNeedsMenuKey(WindowManager.LayoutParams.NEEDS_MENU_SET_TRUE);
Dianne Hackborn73ab6a42011-12-13 11:16:23 -08002427 } else {
Wale Ogunwale393b1c12014-10-18 16:22:01 -07002428 setNeedsMenuKey(WindowManager.LayoutParams.NEEDS_MENU_SET_FALSE);
Daniel Sandlere02d8082010-10-08 15:13:22 -04002429 }
Adrian Roosea562512014-05-05 13:33:03 +02002430
Jorim Jaggi6e0ce282015-12-01 15:19:49 -08002431 if (!mForcedStatusBarColor) {
2432 mStatusBarColor = a.getColor(R.styleable.Window_statusBarColor, 0xFF000000);
2433 }
2434 if (!mForcedNavigationBarColor) {
2435 mNavigationBarColor = a.getColor(R.styleable.Window_navigationBarColor, 0xFF000000);
Jason Monka750e992017-09-01 12:40:06 -04002436 mNavigationBarDividerColor = a.getColor(R.styleable.Window_navigationBarDividerColor,
2437 0x00000000);
Jorim Jaggi6e0ce282015-12-01 15:19:49 -08002438 }
2439
Jorim Jaggi8f5701b2016-04-04 18:36:02 -07002440 WindowManager.LayoutParams params = getAttributes();
2441
Adrian Roosea562512014-05-05 13:33:03 +02002442 // Non-floating windows on high end devices must put up decor beneath the system bars and
2443 // therefore must know about visibility changes of those.
Matthew Nge6b393b2017-09-01 12:45:04 -07002444 if (!mIsFloating) {
Adrian Roosea562512014-05-05 13:33:03 +02002445 if (!targetPreL && a.getBoolean(
Alan Viverette40982d42014-07-25 17:48:55 -07002446 R.styleable.Window_windowDrawsSystemBarBackgrounds,
Adrian Roosea562512014-05-05 13:33:03 +02002447 false)) {
2448 setFlags(FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
2449 FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS & ~getForcedWindowFlags());
2450 }
Jorim Jaggi8f5701b2016-04-04 18:36:02 -07002451 if (mDecor.mForceWindowDrawsStatusBarBackground) {
2452 params.privateFlags |= PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND;
2453 }
Adrian Roosea562512014-05-05 13:33:03 +02002454 }
Adrian Roosf4f84c92015-04-28 13:44:43 -07002455 if (a.getBoolean(R.styleable.Window_windowLightStatusBar, false)) {
Adrian Roos75fa3852015-01-27 20:21:44 +01002456 decor.setSystemUiVisibility(
2457 decor.getSystemUiVisibility() | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
2458 }
Jason Monkd7acd162017-09-11 08:54:12 -07002459 if (a.getBoolean(R.styleable.Window_windowLightNavigationBar, false)) {
2460 decor.setSystemUiVisibility(
2461 decor.getSystemUiVisibility() | View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR);
2462 }
Adrian Roosea562512014-05-05 13:33:03 +02002463
Dianne Hackborncfaf8872011-01-18 13:57:54 -08002464 if (mAlwaysReadCloseOnTouchAttr || getContext().getApplicationInfo().targetSdkVersion
2465 >= android.os.Build.VERSION_CODES.HONEYCOMB) {
Dianne Hackbornef575752011-01-18 17:35:17 -08002466 if (a.getBoolean(
Alan Viverette40982d42014-07-25 17:48:55 -07002467 R.styleable.Window_windowCloseOnTouchOutside,
Dianne Hackbornef575752011-01-18 17:35:17 -08002468 false)) {
2469 setCloseOnTouchOutsideIfNotSet(true);
Dianne Hackborncfaf8872011-01-18 13:57:54 -08002470 }
2471 }
Alan Viveretteeb1d3792014-06-03 18:36:03 -07002472
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002473 if (!hasSoftInputMode()) {
2474 params.softInputMode = a.getInt(
Alan Viverette40982d42014-07-25 17:48:55 -07002475 R.styleable.Window_windowSoftInputMode,
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002476 params.softInputMode);
2477 }
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -08002478
Alan Viverette40982d42014-07-25 17:48:55 -07002479 if (a.getBoolean(R.styleable.Window_backgroundDimEnabled,
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002480 mIsFloating)) {
2481 /* All dialogs should have the window dimmed */
2482 if ((getForcedWindowFlags()&WindowManager.LayoutParams.FLAG_DIM_BEHIND) == 0) {
2483 params.flags |= WindowManager.LayoutParams.FLAG_DIM_BEHIND;
2484 }
Dianne Hackborn661cd522011-08-22 00:26:20 -07002485 if (!haveDimAmount()) {
2486 params.dimAmount = a.getFloat(
2487 android.R.styleable.Window_backgroundDimAmount, 0.5f);
2488 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002489 }
2490
2491 if (params.windowAnimations == 0) {
2492 params.windowAnimations = a.getResourceId(
Alan Viverette40982d42014-07-25 17:48:55 -07002493 R.styleable.Window_windowAnimationStyle, 0);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002494 }
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -08002495
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002496 // The rest are only done if this window is not embedded; otherwise,
2497 // the values are inherited from our container.
2498 if (getContainer() == null) {
2499 if (mBackgroundDrawable == null) {
2500 if (mBackgroundResource == 0) {
2501 mBackgroundResource = a.getResourceId(
Alan Viverette40982d42014-07-25 17:48:55 -07002502 R.styleable.Window_windowBackground, 0);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002503 }
2504 if (mFrameResource == 0) {
Alan Viverette40982d42014-07-25 17:48:55 -07002505 mFrameResource = a.getResourceId(R.styleable.Window_windowFrame, 0);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002506 }
Adam Powellf849a5e2014-09-11 15:09:36 -07002507 mBackgroundFallbackResource = a.getResourceId(
2508 R.styleable.Window_windowBackgroundFallback, 0);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002509 if (false) {
2510 System.out.println("Background: "
2511 + Integer.toHexString(mBackgroundResource) + " Frame: "
2512 + Integer.toHexString(mFrameResource));
2513 }
2514 }
Wale Ogunwale0d7e9122015-11-17 10:45:06 -08002515 if (mLoadElevation) {
Filip Gruszczynskia59ac9c2015-09-10 18:28:48 -07002516 mElevation = a.getDimension(R.styleable.Window_windowElevation, 0);
2517 }
Alan Viverette40982d42014-07-25 17:48:55 -07002518 mClipToOutline = a.getBoolean(R.styleable.Window_windowClipToOutline, false);
2519 mTextColor = a.getColor(R.styleable.Window_textColor, Color.TRANSPARENT);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002520 }
2521
2522 // Inflate the window decor.
2523
2524 int layoutResource;
2525 int features = getLocalFeatures();
2526 // System.out.println("Features: 0x" + Integer.toHexString(features));
Will Haldean Brownca6234e2014-02-12 10:23:41 -08002527 if ((features & (1 << FEATURE_SWIPE_TO_DISMISS)) != 0) {
Alan Viverette40982d42014-07-25 17:48:55 -07002528 layoutResource = R.layout.screen_swipe_dismiss;
Michael Kwanf7964be2016-11-30 16:44:33 -08002529 setCloseOnSwipeEnabled(true);
Will Haldean Brownca6234e2014-02-12 10:23:41 -08002530 } else if ((features & ((1 << FEATURE_LEFT_ICON) | (1 << FEATURE_RIGHT_ICON))) != 0) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002531 if (mIsFloating) {
Adam Powell32aa2c92011-01-11 15:37:04 -08002532 TypedValue res = new TypedValue();
2533 getContext().getTheme().resolveAttribute(
Alan Viverette40982d42014-07-25 17:48:55 -07002534 R.attr.dialogTitleIconsDecorLayout, res, true);
Adam Powell32aa2c92011-01-11 15:37:04 -08002535 layoutResource = res.resourceId;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002536 } else {
Alan Viverette40982d42014-07-25 17:48:55 -07002537 layoutResource = R.layout.screen_title_icons;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002538 }
Adam Powellf4a6ec42010-08-24 14:18:10 -07002539 // XXX Remove this once action bar supports these features.
2540 removeFeature(FEATURE_ACTION_BAR);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002541 // System.out.println("Title Icons!");
Adam Powell6af97e12010-11-11 21:11:53 -08002542 } else if ((features & ((1 << FEATURE_PROGRESS) | (1 << FEATURE_INDETERMINATE_PROGRESS))) != 0
2543 && (features & (1 << FEATURE_ACTION_BAR)) == 0) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002544 // Special case for a window with only a progress bar (and title).
2545 // XXX Need to have a no-title version of embedded windows.
Alan Viverette40982d42014-07-25 17:48:55 -07002546 layoutResource = R.layout.screen_progress;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002547 // System.out.println("Progress!");
2548 } else if ((features & (1 << FEATURE_CUSTOM_TITLE)) != 0) {
2549 // Special case for a window with a custom title.
2550 // If the window is floating, we need a dialog layout
2551 if (mIsFloating) {
Adam Powell32aa2c92011-01-11 15:37:04 -08002552 TypedValue res = new TypedValue();
2553 getContext().getTheme().resolveAttribute(
Alan Viverette40982d42014-07-25 17:48:55 -07002554 R.attr.dialogCustomTitleDecorLayout, res, true);
Adam Powell32aa2c92011-01-11 15:37:04 -08002555 layoutResource = res.resourceId;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002556 } else {
Alan Viverette40982d42014-07-25 17:48:55 -07002557 layoutResource = R.layout.screen_custom_title;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002558 }
Adam Powellf4a6ec42010-08-24 14:18:10 -07002559 // XXX Remove this once action bar supports these features.
2560 removeFeature(FEATURE_ACTION_BAR);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002561 } else if ((features & (1 << FEATURE_NO_TITLE)) == 0) {
2562 // If no other features and not embedded, only need a title.
2563 // If the window is floating, we need a dialog layout
2564 if (mIsFloating) {
Adam Powell32aa2c92011-01-11 15:37:04 -08002565 TypedValue res = new TypedValue();
2566 getContext().getTheme().resolveAttribute(
Alan Viverette40982d42014-07-25 17:48:55 -07002567 R.attr.dialogTitleDecorLayout, res, true);
Adam Powell32aa2c92011-01-11 15:37:04 -08002568 layoutResource = res.resourceId;
Adam Powell33b97432010-04-20 10:01:14 -07002569 } else if ((features & (1 << FEATURE_ACTION_BAR)) != 0) {
Adam Powelle021e6e2014-05-23 17:27:24 -07002570 layoutResource = a.getResourceId(
Alan Viverette40982d42014-07-25 17:48:55 -07002571 R.styleable.Window_windowActionBarFullscreenDecorLayout,
2572 R.layout.screen_action_bar);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002573 } else {
Alan Viverette40982d42014-07-25 17:48:55 -07002574 layoutResource = R.layout.screen_title;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002575 }
2576 // System.out.println("Title!");
Adam Powellf8419a02011-10-03 12:08:54 -07002577 } else if ((features & (1 << FEATURE_ACTION_MODE_OVERLAY)) != 0) {
Alan Viverette40982d42014-07-25 17:48:55 -07002578 layoutResource = R.layout.screen_simple_overlay_action_mode;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002579 } else {
2580 // Embedded, so no decoration is needed.
Alan Viverette40982d42014-07-25 17:48:55 -07002581 layoutResource = R.layout.screen_simple;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002582 // System.out.println("Simple!");
2583 }
2584
2585 mDecor.startChanging();
Filip Gruszczynski3dec0812015-12-09 08:42:41 -08002586 mDecor.onResourcesLoaded(mLayoutInflater, layoutResource);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002587
2588 ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
2589 if (contentParent == null) {
2590 throw new RuntimeException("Window couldn't find content container view");
2591 }
2592
2593 if ((features & (1 << FEATURE_INDETERMINATE_PROGRESS)) != 0) {
2594 ProgressBar progress = getCircularProgressBar(false);
2595 if (progress != null) {
2596 progress.setIndeterminate(true);
2597 }
2598 }
2599
Will Haldean Brownca6234e2014-02-12 10:23:41 -08002600 if ((features & (1 << FEATURE_SWIPE_TO_DISMISS)) != 0) {
Michael Kwanf7964be2016-11-30 16:44:33 -08002601 registerSwipeCallbacks(contentParent);
Will Haldean Brownca6234e2014-02-12 10:23:41 -08002602 }
2603
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002604 // Remaining setup -- of background and title -- that only applies
2605 // to top-level windows.
2606 if (getContainer() == null) {
Alan Viverette49a22e82014-07-12 20:01:27 -07002607 final Drawable background;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002608 if (mBackgroundResource != 0) {
Alan Viverette49a22e82014-07-12 20:01:27 -07002609 background = getContext().getDrawable(mBackgroundResource);
2610 } else {
2611 background = mBackgroundDrawable;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002612 }
Alan Viverette49a22e82014-07-12 20:01:27 -07002613 mDecor.setWindowBackground(background);
2614
2615 final Drawable frame;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002616 if (mFrameResource != 0) {
Alan Viverette49a22e82014-07-12 20:01:27 -07002617 frame = getContext().getDrawable(mFrameResource);
2618 } else {
2619 frame = null;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002620 }
Alan Viverette49a22e82014-07-12 20:01:27 -07002621 mDecor.setWindowFrame(frame);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002622
Alan Viverette49a22e82014-07-12 20:01:27 -07002623 mDecor.setElevation(mElevation);
Alan Viverette2c183332014-08-07 13:43:05 -07002624 mDecor.setClipToOutline(mClipToOutline);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002625
2626 if (mTitle != null) {
2627 setTitle(mTitle);
2628 }
Alan Viverette49a22e82014-07-12 20:01:27 -07002629
2630 if (mTitleColor == 0) {
2631 mTitleColor = mTextColor;
2632 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002633 setTitleColor(mTitleColor);
2634 }
2635
2636 mDecor.finishChanging();
2637
2638 return contentParent;
2639 }
2640
Dianne Hackborncfaf8872011-01-18 13:57:54 -08002641 /** @hide */
2642 public void alwaysReadCloseOnTouchAttr() {
2643 mAlwaysReadCloseOnTouchAttr = true;
2644 }
2645
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002646 private void installDecor() {
Filip Gruszczynskia59ac9c2015-09-10 18:28:48 -07002647 mForceDecorInstall = false;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002648 if (mDecor == null) {
Stefan Kuhne61b47bb2015-07-28 14:04:25 -07002649 mDecor = generateDecor(-1);
Adam Powell00f4d982010-03-24 11:17:03 -07002650 mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002651 mDecor.setIsRootNamespace(true);
Adam Powell4b6d93f2012-09-18 18:34:08 -07002652 if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) {
2653 mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
2654 }
Filip Gruszczynski0daf2102015-09-29 08:39:07 -07002655 } else {
2656 mDecor.setWindow(this);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002657 }
2658 if (mContentParent == null) {
2659 mContentParent = generateLayout(mDecor);
2660
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002661 // Set up decor part of UI to ignore fitsSystemWindows if appropriate.
2662 mDecor.makeOptionalFitsSystemWindows();
2663
Adam Powell4369e7d2014-05-17 14:16:08 -07002664 final DecorContentParent decorContentParent = (DecorContentParent) mDecor.findViewById(
Alan Viverette40982d42014-07-25 17:48:55 -07002665 R.id.decor_content_parent);
Adam Powell4369e7d2014-05-17 14:16:08 -07002666
2667 if (decorContentParent != null) {
2668 mDecorContentParent = decorContentParent;
2669 mDecorContentParent.setWindowCallback(getCallback());
2670 if (mDecorContentParent.getTitle() == null) {
2671 mDecorContentParent.setWindowTitle(mTitle);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002672 }
Adam Powell9b4bee02011-04-27 19:24:47 -07002673
Adam Powell4369e7d2014-05-17 14:16:08 -07002674 final int localFeatures = getLocalFeatures();
2675 for (int i = 0; i < FEATURE_MAX; i++) {
2676 if ((localFeatures & (1 << i)) != 0) {
2677 mDecorContentParent.initFeature(i);
Adam Powell9b0dc282013-07-31 13:58:43 -07002678 }
Adam Powell4369e7d2014-05-17 14:16:08 -07002679 }
Adam Powell9b0dc282013-07-31 13:58:43 -07002680
Adam Powell4369e7d2014-05-17 14:16:08 -07002681 mDecorContentParent.setUiOptions(mUiOptions);
Adam Powell640a66e2011-04-29 10:18:53 -07002682
Adam Powell4369e7d2014-05-17 14:16:08 -07002683 if ((mResourcesSetFlags & FLAG_RESOURCE_SET_ICON) != 0 ||
2684 (mIconRes != 0 && !mDecorContentParent.hasIcon())) {
2685 mDecorContentParent.setIcon(mIconRes);
2686 } else if ((mResourcesSetFlags & FLAG_RESOURCE_SET_ICON) == 0 &&
2687 mIconRes == 0 && !mDecorContentParent.hasIcon()) {
2688 mDecorContentParent.setIcon(
2689 getContext().getPackageManager().getDefaultActivityIcon());
2690 mResourcesSetFlags |= FLAG_RESOURCE_SET_ICON_FALLBACK;
2691 }
2692 if ((mResourcesSetFlags & FLAG_RESOURCE_SET_LOGO) != 0 ||
2693 (mLogoRes != 0 && !mDecorContentParent.hasLogo())) {
2694 mDecorContentParent.setLogo(mLogoRes);
2695 }
Adam Powell9b4bee02011-04-27 19:24:47 -07002696
Adam Powell31c91c82014-08-22 17:20:00 -07002697 // Invalidate if the panel menu hasn't been created before this.
2698 // Panel menu invalidation is deferred avoiding application onCreateOptionsMenu
Adam Powell4369e7d2014-05-17 14:16:08 -07002699 // being called in the middle of onCreate or similar.
Adam Powell31c91c82014-08-22 17:20:00 -07002700 // A pending invalidation will typically be resolved before the posted message
2701 // would run normally in order to satisfy instance state restoration.
2702 PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, false);
Jorim Jaggia16cc152015-06-01 16:55:05 -07002703 if (!isDestroyed() && (st == null || st.menu == null) && !mIsStartingWindow) {
Adam Powell31c91c82014-08-22 17:20:00 -07002704 invalidatePanelMenu(FEATURE_ACTION_BAR);
2705 }
Adam Powell4369e7d2014-05-17 14:16:08 -07002706 } else {
Alan Viverette51efddb2017-04-05 10:00:01 -04002707 mTitleView = findViewById(R.id.title);
Adam Powell4369e7d2014-05-17 14:16:08 -07002708 if (mTitleView != null) {
Adam Powell4369e7d2014-05-17 14:16:08 -07002709 if ((getLocalFeatures() & (1 << FEATURE_NO_TITLE)) != 0) {
Alan Viverette891c9ee2016-01-08 13:43:15 -05002710 final View titleContainer = findViewById(R.id.title_container);
Adam Powell4369e7d2014-05-17 14:16:08 -07002711 if (titleContainer != null) {
2712 titleContainer.setVisibility(View.GONE);
2713 } else {
2714 mTitleView.setVisibility(View.GONE);
2715 }
Alan Viverette891c9ee2016-01-08 13:43:15 -05002716 mContentParent.setForeground(null);
Adam Powell4369e7d2014-05-17 14:16:08 -07002717 } else {
2718 mTitleView.setText(mTitle);
2719 }
Adam Powell33b97432010-04-20 10:01:14 -07002720 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002721 }
Adam Powell18e905f2013-10-24 14:27:48 -07002722
Adam Powellf849a5e2014-09-11 15:09:36 -07002723 if (mDecor.getBackground() == null && mBackgroundFallbackResource != 0) {
2724 mDecor.setBackgroundFallback(mBackgroundFallbackResource);
2725 }
2726
Adam Powell18e905f2013-10-24 14:27:48 -07002727 // Only inflate or create a new TransitionManager if the caller hasn't
2728 // already set a custom one.
George Mount9826f632014-09-11 08:50:09 -07002729 if (hasFeature(FEATURE_ACTIVITY_TRANSITIONS)) {
George Mount31a21722014-03-24 17:44:36 -07002730 if (mTransitionManager == null) {
2731 final int transitionRes = getWindowStyle().getResourceId(
Alan Viverette40982d42014-07-25 17:48:55 -07002732 R.styleable.Window_windowContentTransitionManager,
George Mount31a21722014-03-24 17:44:36 -07002733 0);
2734 if (transitionRes != 0) {
2735 final TransitionInflater inflater = TransitionInflater.from(getContext());
2736 mTransitionManager = inflater.inflateTransitionManager(transitionRes,
2737 mContentParent);
2738 } else {
2739 mTransitionManager = new TransitionManager();
2740 }
2741 }
2742
George Mount68f96d82014-07-31 13:13:10 -07002743 mEnterTransition = getTransition(mEnterTransition, null,
Alan Viverette40982d42014-07-25 17:48:55 -07002744 R.styleable.Window_windowEnterTransition);
George Mount68f96d82014-07-31 13:13:10 -07002745 mReturnTransition = getTransition(mReturnTransition, USE_DEFAULT_TRANSITION,
2746 R.styleable.Window_windowReturnTransition);
2747 mExitTransition = getTransition(mExitTransition, null,
Alan Viverette40982d42014-07-25 17:48:55 -07002748 R.styleable.Window_windowExitTransition);
George Mount68f96d82014-07-31 13:13:10 -07002749 mReenterTransition = getTransition(mReenterTransition, USE_DEFAULT_TRANSITION,
2750 R.styleable.Window_windowReenterTransition);
2751 mSharedElementEnterTransition = getTransition(mSharedElementEnterTransition, null,
Alan Viverette40982d42014-07-25 17:48:55 -07002752 R.styleable.Window_windowSharedElementEnterTransition);
George Mount68f96d82014-07-31 13:13:10 -07002753 mSharedElementReturnTransition = getTransition(mSharedElementReturnTransition,
2754 USE_DEFAULT_TRANSITION,
2755 R.styleable.Window_windowSharedElementReturnTransition);
2756 mSharedElementExitTransition = getTransition(mSharedElementExitTransition, null,
Alan Viverette40982d42014-07-25 17:48:55 -07002757 R.styleable.Window_windowSharedElementExitTransition);
George Mount68f96d82014-07-31 13:13:10 -07002758 mSharedElementReenterTransition = getTransition(mSharedElementReenterTransition,
2759 USE_DEFAULT_TRANSITION,
2760 R.styleable.Window_windowSharedElementReenterTransition);
George Mount31a21722014-03-24 17:44:36 -07002761 if (mAllowEnterTransitionOverlap == null) {
2762 mAllowEnterTransitionOverlap = getWindowStyle().getBoolean(
George Mount68f96d82014-07-31 13:13:10 -07002763 R.styleable.Window_windowAllowEnterTransitionOverlap, true);
George Mount31a21722014-03-24 17:44:36 -07002764 }
George Mountc03da0e2014-08-22 17:04:02 -07002765 if (mAllowReturnTransitionOverlap == null) {
2766 mAllowReturnTransitionOverlap = getWindowStyle().getBoolean(
2767 R.styleable.Window_windowAllowReturnTransitionOverlap, true);
Adam Powell18e905f2013-10-24 14:27:48 -07002768 }
George Mounted1e01d2014-06-05 13:49:12 -07002769 if (mBackgroundFadeDurationMillis < 0) {
2770 mBackgroundFadeDurationMillis = getWindowStyle().getInteger(
George Mount68f96d82014-07-31 13:13:10 -07002771 R.styleable.Window_windowTransitionBackgroundFadeDuration,
George Mounted1e01d2014-06-05 13:49:12 -07002772 DEFAULT_BACKGROUND_FADE_DURATION_MS);
2773 }
George Mountb89d5cc2014-08-18 16:50:50 -07002774 if (mSharedElementsUseOverlay == null) {
2775 mSharedElementsUseOverlay = getWindowStyle().getBoolean(
2776 R.styleable.Window_windowSharedElementsUseOverlay, true);
2777 }
Adam Powell18e905f2013-10-24 14:27:48 -07002778 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002779 }
2780 }
2781
George Mount68f96d82014-07-31 13:13:10 -07002782 private Transition getTransition(Transition currentValue, Transition defaultValue, int id) {
2783 if (currentValue != defaultValue) {
George Mount31a21722014-03-24 17:44:36 -07002784 return currentValue;
2785 }
2786 int transitionId = getWindowStyle().getResourceId(id, -1);
George Mount68f96d82014-07-31 13:13:10 -07002787 Transition transition = defaultValue;
Alan Viverette40982d42014-07-25 17:48:55 -07002788 if (transitionId != -1 && transitionId != R.transition.no_transition) {
George Mount31a21722014-03-24 17:44:36 -07002789 TransitionInflater inflater = TransitionInflater.from(getContext());
2790 transition = inflater.inflateTransition(transitionId);
George Mount7f151642014-08-18 16:24:21 -07002791 if (transition instanceof TransitionSet &&
2792 ((TransitionSet)transition).getTransitionCount() == 0) {
2793 transition = null;
2794 }
George Mount31a21722014-03-24 17:44:36 -07002795 }
2796 return transition;
2797 }
2798
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002799 private Drawable loadImageURI(Uri uri) {
2800 try {
Alan Viverettead3c4a12014-06-02 17:12:58 -07002801 return Drawable.createFromStream(
2802 getContext().getContentResolver().openInputStream(uri), null);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002803 } catch (Exception e) {
2804 Log.w(TAG, "Unable to open content: " + uri);
2805 }
2806 return null;
2807 }
2808
2809 private DrawableFeatureState getDrawableState(int featureId, boolean required) {
2810 if ((getFeatures() & (1 << featureId)) == 0) {
2811 if (!required) {
2812 return null;
2813 }
2814 throw new RuntimeException("The feature has not been requested");
2815 }
2816
2817 DrawableFeatureState[] ar;
2818 if ((ar = mDrawables) == null || ar.length <= featureId) {
2819 DrawableFeatureState[] nar = new DrawableFeatureState[featureId + 1];
2820 if (ar != null) {
2821 System.arraycopy(ar, 0, nar, 0, ar.length);
2822 }
2823 mDrawables = ar = nar;
2824 }
2825
2826 DrawableFeatureState st = ar[featureId];
2827 if (st == null) {
2828 ar[featureId] = st = new DrawableFeatureState(featureId);
2829 }
2830 return st;
2831 }
2832
2833 /**
2834 * Gets a panel's state based on its feature ID.
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -08002835 *
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002836 * @param featureId The feature ID of the panel.
2837 * @param required Whether the panel is required (if it is required and it
2838 * isn't in our features, this throws an exception).
2839 * @return The panel state.
2840 */
Wale Ogunwale8804af22015-11-17 09:18:15 -08002841 PanelFeatureState getPanelState(int featureId, boolean required) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002842 return getPanelState(featureId, required, null);
2843 }
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -08002844
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002845 /**
2846 * Gets a panel's state based on its feature ID.
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -08002847 *
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002848 * @param featureId The feature ID of the panel.
2849 * @param required Whether the panel is required (if it is required and it
2850 * isn't in our features, this throws an exception).
2851 * @param convertPanelState Optional: If the panel state does not exist, use
2852 * this as the panel state.
2853 * @return The panel state.
2854 */
2855 private PanelFeatureState getPanelState(int featureId, boolean required,
2856 PanelFeatureState convertPanelState) {
2857 if ((getFeatures() & (1 << featureId)) == 0) {
2858 if (!required) {
2859 return null;
2860 }
2861 throw new RuntimeException("The feature has not been requested");
2862 }
2863
2864 PanelFeatureState[] ar;
2865 if ((ar = mPanels) == null || ar.length <= featureId) {
2866 PanelFeatureState[] nar = new PanelFeatureState[featureId + 1];
2867 if (ar != null) {
2868 System.arraycopy(ar, 0, nar, 0, ar.length);
2869 }
2870 mPanels = ar = nar;
2871 }
2872
2873 PanelFeatureState st = ar[featureId];
2874 if (st == null) {
2875 ar[featureId] = st = (convertPanelState != null)
2876 ? convertPanelState
2877 : new PanelFeatureState(featureId);
2878 }
2879 return st;
2880 }
2881
2882 @Override
2883 public final void setChildDrawable(int featureId, Drawable drawable) {
2884 DrawableFeatureState st = getDrawableState(featureId, true);
2885 st.child = drawable;
2886 updateDrawable(featureId, st, false);
2887 }
2888
2889 @Override
2890 public final void setChildInt(int featureId, int value) {
2891 updateInt(featureId, value, false);
2892 }
2893
2894 @Override
2895 public boolean isShortcutKey(int keyCode, KeyEvent event) {
Jose Lima7a22fc62015-01-23 17:24:22 -08002896 PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, false);
2897 return st != null && st.menu != null && st.menu.isShortcutKey(keyCode, event);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002898 }
2899
2900 private void updateDrawable(int featureId, DrawableFeatureState st, boolean fromResume) {
2901 // Do nothing if the decor is not yet installed... an update will
2902 // need to be forced when we eventually become active.
2903 if (mContentParent == null) {
2904 return;
2905 }
2906
2907 final int featureMask = 1 << featureId;
2908
2909 if ((getFeatures() & featureMask) == 0 && !fromResume) {
2910 return;
2911 }
2912
2913 Drawable drawable = null;
2914 if (st != null) {
2915 drawable = st.child;
2916 if (drawable == null)
2917 drawable = st.local;
2918 if (drawable == null)
2919 drawable = st.def;
2920 }
2921 if ((getLocalFeatures() & featureMask) == 0) {
2922 if (getContainer() != null) {
2923 if (isActive() || fromResume) {
2924 getContainer().setChildDrawable(featureId, drawable);
2925 }
2926 }
2927 } else if (st != null && (st.cur != drawable || st.curAlpha != st.alpha)) {
2928 // System.out.println("Drawable changed: old=" + st.cur
2929 // + ", new=" + drawable);
2930 st.cur = drawable;
2931 st.curAlpha = st.alpha;
2932 onDrawableChanged(featureId, drawable, st.alpha);
2933 }
2934 }
2935
2936 private void updateInt(int featureId, int value, boolean fromResume) {
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -08002937
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002938 // Do nothing if the decor is not yet installed... an update will
2939 // need to be forced when we eventually become active.
2940 if (mContentParent == null) {
2941 return;
2942 }
2943
2944 final int featureMask = 1 << featureId;
2945
2946 if ((getFeatures() & featureMask) == 0 && !fromResume) {
2947 return;
2948 }
2949
2950 if ((getLocalFeatures() & featureMask) == 0) {
2951 if (getContainer() != null) {
2952 getContainer().setChildInt(featureId, value);
2953 }
2954 } else {
2955 onIntChanged(featureId, value);
2956 }
2957 }
2958
2959 private ImageView getLeftIconView() {
2960 if (mLeftIconView != null) {
2961 return mLeftIconView;
2962 }
2963 if (mContentParent == null) {
2964 installDecor();
2965 }
Alan Viverette40982d42014-07-25 17:48:55 -07002966 return (mLeftIconView = (ImageView)findViewById(R.id.left_icon));
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002967 }
2968
Adrian Roosea562512014-05-05 13:33:03 +02002969 @Override
2970 protected void dispatchWindowAttributesChanged(WindowManager.LayoutParams attrs) {
2971 super.dispatchWindowAttributesChanged(attrs);
2972 if (mDecor != null) {
Adrian Roos05054bd2014-10-27 17:04:10 +01002973 mDecor.updateColorViews(null /* insets */, true /* animate */);
Adrian Roosea562512014-05-05 13:33:03 +02002974 }
2975 }
2976
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002977 private ProgressBar getCircularProgressBar(boolean shouldInstallDecor) {
2978 if (mCircularProgressBar != null) {
2979 return mCircularProgressBar;
2980 }
2981 if (mContentParent == null && shouldInstallDecor) {
2982 installDecor();
2983 }
Alan Viverette51efddb2017-04-05 10:00:01 -04002984 mCircularProgressBar = findViewById(R.id.progress_circular);
Adam Powell6af97e12010-11-11 21:11:53 -08002985 if (mCircularProgressBar != null) {
2986 mCircularProgressBar.setVisibility(View.INVISIBLE);
2987 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002988 return mCircularProgressBar;
2989 }
2990
2991 private ProgressBar getHorizontalProgressBar(boolean shouldInstallDecor) {
2992 if (mHorizontalProgressBar != null) {
2993 return mHorizontalProgressBar;
2994 }
2995 if (mContentParent == null && shouldInstallDecor) {
2996 installDecor();
2997 }
Alan Viverette51efddb2017-04-05 10:00:01 -04002998 mHorizontalProgressBar = findViewById(R.id.progress_horizontal);
Adam Powell6af97e12010-11-11 21:11:53 -08002999 if (mHorizontalProgressBar != null) {
3000 mHorizontalProgressBar.setVisibility(View.INVISIBLE);
3001 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003002 return mHorizontalProgressBar;
3003 }
3004
3005 private ImageView getRightIconView() {
3006 if (mRightIconView != null) {
3007 return mRightIconView;
3008 }
3009 if (mContentParent == null) {
3010 installDecor();
3011 }
Alan Viverette40982d42014-07-25 17:48:55 -07003012 return (mRightIconView = (ImageView)findViewById(R.id.right_icon));
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003013 }
3014
Michael Kwanf7964be2016-11-30 16:44:33 -08003015 private void registerSwipeCallbacks(ViewGroup contentParent) {
3016 if (!(contentParent instanceof SwipeDismissLayout)) {
3017 Log.w(TAG, "contentParent is not a SwipeDismissLayout: " + contentParent);
3018 return;
3019 }
3020 SwipeDismissLayout swipeDismiss = (SwipeDismissLayout) contentParent;
Will Haldean Brownca6234e2014-02-12 10:23:41 -08003021 swipeDismiss.setOnDismissedListener(new SwipeDismissLayout.OnDismissedListener() {
3022 @Override
3023 public void onDismissed(SwipeDismissLayout layout) {
Michael Kwan67639a52016-12-16 12:38:10 -08003024 dispatchOnWindowSwipeDismissed();
Ned Burns7d6cb912016-12-02 17:25:33 -05003025 dispatchOnWindowDismissed(false /*finishTask*/, true /*suppressWindowTransition*/);
Will Haldean Brownca6234e2014-02-12 10:23:41 -08003026 }
3027 });
3028 swipeDismiss.setOnSwipeProgressChangedListener(
3029 new SwipeDismissLayout.OnSwipeProgressChangedListener() {
Will Haldean Brownca6234e2014-02-12 10:23:41 -08003030 @Override
3031 public void onSwipeProgressChanged(
Ned Burns7d6cb912016-12-02 17:25:33 -05003032 SwipeDismissLayout layout, float alpha, float translate) {
Will Haldean Brownca6234e2014-02-12 10:23:41 -08003033 WindowManager.LayoutParams newParams = getAttributes();
3034 newParams.x = (int) translate;
Ned Burns7d6cb912016-12-02 17:25:33 -05003035 newParams.alpha = alpha;
Will Haldean Brownca6234e2014-02-12 10:23:41 -08003036 setAttributes(newParams);
3037
3038 int flags = 0;
3039 if (newParams.x == 0) {
3040 flags = FLAG_FULLSCREEN;
3041 } else {
3042 flags = FLAG_LAYOUT_NO_LIMITS;
3043 }
3044 setFlags(flags, FLAG_FULLSCREEN | FLAG_LAYOUT_NO_LIMITS);
3045 }
3046
3047 @Override
3048 public void onSwipeCancelled(SwipeDismissLayout layout) {
3049 WindowManager.LayoutParams newParams = getAttributes();
Michael Kwan134ad6e2017-02-10 18:38:34 -08003050 // Swipe changes only affect the x-translation and alpha, check to see if
3051 // those values have changed first before resetting them.
3052 if (newParams.x != 0 || newParams.alpha != 1) {
3053 newParams.x = 0;
3054 newParams.alpha = 1;
3055 setAttributes(newParams);
3056 setFlags(FLAG_FULLSCREEN, FLAG_FULLSCREEN | FLAG_LAYOUT_NO_LIMITS);
3057 }
Will Haldean Brownca6234e2014-02-12 10:23:41 -08003058 }
3059 });
3060 }
3061
Michael Kwanf7964be2016-11-30 16:44:33 -08003062 /** @hide */
3063 @Override
3064 public void setCloseOnSwipeEnabled(boolean closeOnSwipeEnabled) {
3065 if (hasFeature(Window.FEATURE_SWIPE_TO_DISMISS) // swipe-to-dismiss feature is requested
3066 && mContentParent instanceof SwipeDismissLayout) { // check casting mContentParent
3067 ((SwipeDismissLayout) mContentParent).setDismissable(closeOnSwipeEnabled);
3068 }
3069 super.setCloseOnSwipeEnabled(closeOnSwipeEnabled);
3070 }
3071
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003072 /**
3073 * Helper method for calling the {@link Callback#onPanelClosed(int, Menu)}
3074 * callback. This method will grab whatever extra state is needed for the
3075 * callback that isn't given in the parameters. If the panel is not open,
3076 * this will not perform the callback.
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -08003077 *
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003078 * @param featureId Feature ID of the panel that was closed. Must be given.
3079 * @param panel Panel that was closed. Optional but useful if there is no
3080 * menu given.
3081 * @param menu The menu that was closed. Optional, but give if you have.
3082 */
3083 private void callOnPanelClosed(int featureId, PanelFeatureState panel, Menu menu) {
3084 final Callback cb = getCallback();
3085 if (cb == null)
3086 return;
3087
3088 // Try to get a menu
3089 if (menu == null) {
3090 // Need a panel to grab the menu, so try to get that
3091 if (panel == null) {
3092 if ((featureId >= 0) && (featureId < mPanels.length)) {
3093 panel = mPanels[featureId];
3094 }
3095 }
3096
3097 if (panel != null) {
3098 // menu still may be null, which is okay--we tried our best
3099 menu = panel.menu;
3100 }
3101 }
3102
3103 // If the panel is not open, do not callback
3104 if ((panel != null) && (!panel.isOpen))
3105 return;
3106
Dianne Hackbornb66ad572011-03-01 17:10:30 -08003107 if (!isDestroyed()) {
3108 cb.onPanelClosed(featureId, menu);
3109 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003110 }
3111
3112 /**
Sujith Ramakrishnan0390fff2017-06-08 18:18:12 -07003113 * Check if Setup or Post-Setup update is completed on TV
3114 * @return true if completed
3115 */
3116 private boolean isTvUserSetupComplete() {
3117 boolean isTvSetupComplete = Settings.Secure.getInt(getContext().getContentResolver(),
3118 Settings.Secure.USER_SETUP_COMPLETE, 0) != 0;
3119 isTvSetupComplete &= Settings.Secure.getInt(getContext().getContentResolver(),
3120 Settings.Secure.TV_USER_SETUP_COMPLETE, 0) != 0;
3121 return isTvSetupComplete;
3122 }
3123
3124 /**
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003125 * Helper method for adding launch-search to most applications. Opens the
3126 * search window using default settings.
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -08003127 *
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003128 * @return true if search window opened
3129 */
Tim Kilbourn6a975b32015-04-09 17:14:34 -07003130 private boolean launchDefaultSearch(KeyEvent event) {
Sujith Ramakrishnan0390fff2017-06-08 18:18:12 -07003131 if (getContext().getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK)
3132 && !isTvUserSetupComplete()) {
3133 // If we are in Setup or Post-Setup update mode on TV, consume the search key
3134 return false;
3135 }
Dianne Hackbornfdf5b352014-10-08 17:43:48 -07003136 boolean result;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003137 final Callback cb = getCallback();
Dianne Hackbornb66ad572011-03-01 17:10:30 -08003138 if (cb == null || isDestroyed()) {
Dianne Hackbornfdf5b352014-10-08 17:43:48 -07003139 result = false;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003140 } else {
Karl Rosaen323216b2009-07-20 14:00:29 -07003141 sendCloseSystemWindows("search");
Tim Kilbourn6a975b32015-04-09 17:14:34 -07003142 int deviceId = event.getDeviceId();
3143 SearchEvent searchEvent = null;
3144 if (deviceId != 0) {
3145 searchEvent = new SearchEvent(InputDevice.getDevice(deviceId));
3146 }
Adam Powell97900342015-04-15 13:12:52 -07003147 try {
3148 result = cb.onSearchRequested(searchEvent);
3149 } catch (AbstractMethodError e) {
3150 Log.e(TAG, "WindowCallback " + cb.getClass().getName() + " does not implement"
3151 + " method onSearchRequested(SearchEvent); fa", e);
3152 result = cb.onSearchRequested();
3153 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003154 }
Dianne Hackbornfdf5b352014-10-08 17:43:48 -07003155 if (!result && (getContext().getResources().getConfiguration().uiMode
3156 & Configuration.UI_MODE_TYPE_MASK) == Configuration.UI_MODE_TYPE_TELEVISION) {
3157 // On TVs, if the app doesn't implement search, we want to launch assist.
Tim Kilbourn0e5f1102015-06-05 16:18:09 -07003158 Bundle args = new Bundle();
3159 args.putInt(Intent.EXTRA_ASSIST_INPUT_DEVICE_ID, event.getDeviceId());
Dianne Hackbornfdf5b352014-10-08 17:43:48 -07003160 return ((SearchManager)getContext().getSystemService(Context.SEARCH_SERVICE))
Jorim Jaggi165ce062015-07-06 16:18:11 -07003161 .launchLegacyAssist(null, UserHandle.myUserId(), args);
Dianne Hackbornfdf5b352014-10-08 17:43:48 -07003162 }
3163 return result;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003164 }
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -08003165
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003166 @Override
3167 public void setVolumeControlStream(int streamType) {
3168 mVolumeControlStreamType = streamType;
3169 }
3170
3171 @Override
3172 public int getVolumeControlStream() {
3173 return mVolumeControlStreamType;
3174 }
3175
RoboErik55011652014-07-09 15:05:53 -07003176 @Override
3177 public void setMediaController(MediaController controller) {
3178 mMediaController = controller;
3179 }
3180
3181 @Override
3182 public MediaController getMediaController() {
3183 return mMediaController;
3184 }
3185
George Mount31a21722014-03-24 17:44:36 -07003186 @Override
3187 public void setEnterTransition(Transition enterTransition) {
3188 mEnterTransition = enterTransition;
3189 }
3190
3191 @Override
George Mount68f96d82014-07-31 13:13:10 -07003192 public void setReturnTransition(Transition transition) {
3193 mReturnTransition = transition;
3194 }
3195
3196 @Override
George Mount31a21722014-03-24 17:44:36 -07003197 public void setExitTransition(Transition exitTransition) {
3198 mExitTransition = exitTransition;
3199 }
3200
3201 @Override
George Mount68f96d82014-07-31 13:13:10 -07003202 public void setReenterTransition(Transition transition) {
3203 mReenterTransition = transition;
3204 }
3205
3206 @Override
George Mount31a21722014-03-24 17:44:36 -07003207 public void setSharedElementEnterTransition(Transition sharedElementEnterTransition) {
3208 mSharedElementEnterTransition = sharedElementEnterTransition;
3209 }
3210
3211 @Override
George Mount68f96d82014-07-31 13:13:10 -07003212 public void setSharedElementReturnTransition(Transition transition) {
3213 mSharedElementReturnTransition = transition;
3214 }
3215
3216 @Override
George Mount31a21722014-03-24 17:44:36 -07003217 public void setSharedElementExitTransition(Transition sharedElementExitTransition) {
3218 mSharedElementExitTransition = sharedElementExitTransition;
3219 }
3220
3221 @Override
George Mount68f96d82014-07-31 13:13:10 -07003222 public void setSharedElementReenterTransition(Transition transition) {
3223 mSharedElementReenterTransition = transition;
3224 }
3225
3226 @Override
George Mount31a21722014-03-24 17:44:36 -07003227 public Transition getEnterTransition() {
3228 return mEnterTransition;
3229 }
3230
3231 @Override
George Mount68f96d82014-07-31 13:13:10 -07003232 public Transition getReturnTransition() {
3233 return mReturnTransition == USE_DEFAULT_TRANSITION ? getEnterTransition()
3234 : mReturnTransition;
3235 }
3236
3237 @Override
George Mount31a21722014-03-24 17:44:36 -07003238 public Transition getExitTransition() {
3239 return mExitTransition;
3240 }
3241
3242 @Override
George Mount68f96d82014-07-31 13:13:10 -07003243 public Transition getReenterTransition() {
3244 return mReenterTransition == USE_DEFAULT_TRANSITION ? getExitTransition()
3245 : mReenterTransition;
3246 }
3247
3248 @Override
George Mount31a21722014-03-24 17:44:36 -07003249 public Transition getSharedElementEnterTransition() {
3250 return mSharedElementEnterTransition;
3251 }
3252
3253 @Override
George Mount68f96d82014-07-31 13:13:10 -07003254 public Transition getSharedElementReturnTransition() {
3255 return mSharedElementReturnTransition == USE_DEFAULT_TRANSITION
3256 ? getSharedElementEnterTransition() : mSharedElementReturnTransition;
3257 }
3258
3259 @Override
George Mount31a21722014-03-24 17:44:36 -07003260 public Transition getSharedElementExitTransition() {
3261 return mSharedElementExitTransition;
3262 }
3263
3264 @Override
George Mount68f96d82014-07-31 13:13:10 -07003265 public Transition getSharedElementReenterTransition() {
3266 return mSharedElementReenterTransition == USE_DEFAULT_TRANSITION
3267 ? getSharedElementExitTransition() : mSharedElementReenterTransition;
3268 }
3269
3270 @Override
George Mount31a21722014-03-24 17:44:36 -07003271 public void setAllowEnterTransitionOverlap(boolean allow) {
3272 mAllowEnterTransitionOverlap = allow;
3273 }
3274
3275 @Override
3276 public boolean getAllowEnterTransitionOverlap() {
3277 return (mAllowEnterTransitionOverlap == null) ? true : mAllowEnterTransitionOverlap;
3278 }
3279
3280 @Override
George Mountc03da0e2014-08-22 17:04:02 -07003281 public void setAllowReturnTransitionOverlap(boolean allowExitTransitionOverlap) {
3282 mAllowReturnTransitionOverlap = allowExitTransitionOverlap;
George Mount31a21722014-03-24 17:44:36 -07003283 }
3284
3285 @Override
George Mountc03da0e2014-08-22 17:04:02 -07003286 public boolean getAllowReturnTransitionOverlap() {
3287 return (mAllowReturnTransitionOverlap == null) ? true : mAllowReturnTransitionOverlap;
George Mount31a21722014-03-24 17:44:36 -07003288 }
3289
George Mounted1e01d2014-06-05 13:49:12 -07003290 @Override
3291 public long getTransitionBackgroundFadeDuration() {
3292 return (mBackgroundFadeDurationMillis < 0) ? DEFAULT_BACKGROUND_FADE_DURATION_MS
3293 : mBackgroundFadeDurationMillis;
3294 }
3295
3296 @Override
3297 public void setTransitionBackgroundFadeDuration(long fadeDurationMillis) {
3298 if (fadeDurationMillis < 0) {
3299 throw new IllegalArgumentException("negative durations are not allowed");
3300 }
3301 mBackgroundFadeDurationMillis = fadeDurationMillis;
3302 }
3303
George Mountb89d5cc2014-08-18 16:50:50 -07003304 @Override
3305 public void setSharedElementsUseOverlay(boolean sharedElementsUseOverlay) {
3306 mSharedElementsUseOverlay = sharedElementsUseOverlay;
3307 }
3308
3309 @Override
3310 public boolean getSharedElementsUseOverlay() {
3311 return (mSharedElementsUseOverlay == null) ? true : mSharedElementsUseOverlay;
3312 }
3313
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003314 private static final class DrawableFeatureState {
3315 DrawableFeatureState(int _featureId) {
3316 featureId = _featureId;
3317 }
3318
3319 final int featureId;
3320
3321 int resid;
3322
3323 Uri uri;
3324
3325 Drawable local;
3326
3327 Drawable child;
3328
3329 Drawable def;
3330
3331 Drawable cur;
3332
3333 int alpha = 255;
3334
3335 int curAlpha = 255;
3336 }
3337
Wale Ogunwale8804af22015-11-17 09:18:15 -08003338 static final class PanelFeatureState {
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -08003339
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003340 /** Feature ID for this panel. */
3341 int featureId;
3342
3343 // Information pulled from the style for this panel.
3344
3345 int background;
3346
3347 /** The background when the panel spans the entire available width. */
3348 int fullBackground;
3349
3350 int gravity;
3351
3352 int x;
3353
3354 int y;
3355
3356 int windowAnimations;
3357
3358 /** Dynamic state of the panel. */
3359 DecorView decorView;
3360
3361 /** The panel that was returned by onCreatePanelView(). */
3362 View createdPanelView;
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -08003363
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003364 /** The panel that we are actually showing. */
3365 View shownPanelView;
3366
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -08003367 /** Use {@link #setMenu} to set this. */
Adam Powell696cba52011-03-29 10:38:16 -07003368 MenuBuilder menu;
3369
3370 IconMenuPresenter iconMenuPresenter;
Adam Powelldfee59a2011-08-05 20:48:30 -07003371 ListMenuPresenter listMenuPresenter;
3372
3373 /** true if this menu will show in single-list compact mode */
3374 boolean isCompact;
3375
3376 /** Theme resource ID for list elements of the panel menu */
3377 int listPresenterTheme;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003378
3379 /**
3380 * Whether the panel has been prepared (see
3381 * {@link PhoneWindow#preparePanel}).
3382 */
3383 boolean isPrepared;
3384
3385 /**
3386 * Whether an item's action has been performed. This happens in obvious
3387 * scenarios (user clicks on menu item), but can also happen with
3388 * chording menu+(shortcut key).
3389 */
3390 boolean isHandled;
3391
3392 boolean isOpen;
3393
3394 /**
3395 * True if the menu is in expanded mode, false if the menu is in icon
3396 * mode
3397 */
3398 boolean isInExpandedMode;
3399
3400 public boolean qwertyMode;
3401
3402 boolean refreshDecorView;
3403
Dianne Hackbornb31e84bc2010-06-08 18:04:35 -07003404 boolean refreshMenuContent;
Alan Viveretteeb1d3792014-06-03 18:36:03 -07003405
Dianne Hackbornd0071442009-09-25 01:35:29 -07003406 boolean wasLastOpen;
Alan Viveretteeb1d3792014-06-03 18:36:03 -07003407
Dianne Hackbornd0071442009-09-25 01:35:29 -07003408 boolean wasLastExpanded;
Alan Viveretteeb1d3792014-06-03 18:36:03 -07003409
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003410 /**
3411 * Contains the state of the menu when told to freeze.
3412 */
3413 Bundle frozenMenuState;
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -08003414
Adam Powell038f1c82011-07-21 14:28:10 -07003415 /**
3416 * Contains the state of associated action views when told to freeze.
3417 * These are saved across invalidations.
3418 */
3419 Bundle frozenActionViewState;
3420
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003421 PanelFeatureState(int featureId) {
3422 this.featureId = featureId;
3423
3424 refreshDecorView = false;
3425 }
3426
Adam Powelldfee59a2011-08-05 20:48:30 -07003427 public boolean isInListMode() {
3428 return isInExpandedMode || isCompact;
3429 }
3430
Adam Powell526b9312011-04-22 15:42:05 -07003431 public boolean hasPanelItems() {
3432 if (shownPanelView == null) return false;
Adam Powell4fd8d5332011-08-17 14:54:41 -07003433 if (createdPanelView != null) return true;
Adam Powell526b9312011-04-22 15:42:05 -07003434
Adam Powelldfee59a2011-08-05 20:48:30 -07003435 if (isCompact || isInExpandedMode) {
3436 return listMenuPresenter.getAdapter().getCount() > 0;
Adam Powell526b9312011-04-22 15:42:05 -07003437 } else {
3438 return ((ViewGroup) shownPanelView).getChildCount() > 0;
3439 }
3440 }
3441
Adam Powell696cba52011-03-29 10:38:16 -07003442 /**
3443 * Unregister and free attached MenuPresenters. They will be recreated as needed.
3444 */
3445 public void clearMenuPresenters() {
3446 if (menu != null) {
3447 menu.removeMenuPresenter(iconMenuPresenter);
Adam Powelldfee59a2011-08-05 20:48:30 -07003448 menu.removeMenuPresenter(listMenuPresenter);
Adam Powell696cba52011-03-29 10:38:16 -07003449 }
3450 iconMenuPresenter = null;
Adam Powelldfee59a2011-08-05 20:48:30 -07003451 listMenuPresenter = null;
Adam Powell696cba52011-03-29 10:38:16 -07003452 }
3453
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003454 void setStyle(Context context) {
Alan Viverette40982d42014-07-25 17:48:55 -07003455 TypedArray a = context.obtainStyledAttributes(R.styleable.Theme);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003456 background = a.getResourceId(
Alan Viverette40982d42014-07-25 17:48:55 -07003457 R.styleable.Theme_panelBackground, 0);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003458 fullBackground = a.getResourceId(
Alan Viverette40982d42014-07-25 17:48:55 -07003459 R.styleable.Theme_panelFullBackground, 0);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003460 windowAnimations = a.getResourceId(
Alan Viverette40982d42014-07-25 17:48:55 -07003461 R.styleable.Theme_windowAnimationStyle, 0);
Adam Powelldfee59a2011-08-05 20:48:30 -07003462 isCompact = a.getBoolean(
Alan Viverette40982d42014-07-25 17:48:55 -07003463 R.styleable.Theme_panelMenuIsCompact, false);
Adam Powelldfee59a2011-08-05 20:48:30 -07003464 listPresenterTheme = a.getResourceId(
Alan Viverette40982d42014-07-25 17:48:55 -07003465 R.styleable.Theme_panelMenuListTheme,
3466 R.style.Theme_ExpandedMenu);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003467 a.recycle();
3468 }
3469
Adam Powell696cba52011-03-29 10:38:16 -07003470 void setMenu(MenuBuilder menu) {
Adam Powell1d07e162011-09-07 20:46:24 -07003471 if (menu == this.menu) return;
3472
3473 if (this.menu != null) {
3474 this.menu.removeMenuPresenter(iconMenuPresenter);
3475 this.menu.removeMenuPresenter(listMenuPresenter);
3476 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003477 this.menu = menu;
Adam Powell1d07e162011-09-07 20:46:24 -07003478 if (menu != null) {
3479 if (iconMenuPresenter != null) menu.addMenuPresenter(iconMenuPresenter);
3480 if (listMenuPresenter != null) menu.addMenuPresenter(listMenuPresenter);
3481 }
Adam Powell696cba52011-03-29 10:38:16 -07003482 }
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -08003483
Adam Powell538e5652011-10-11 13:47:08 -07003484 MenuView getListMenuView(Context context, MenuPresenter.Callback cb) {
Adam Powell696cba52011-03-29 10:38:16 -07003485 if (menu == null) return null;
3486
Adam Powelldfee59a2011-08-05 20:48:30 -07003487 if (!isCompact) {
Adam Powell538e5652011-10-11 13:47:08 -07003488 getIconMenuView(context, cb); // Need this initialized to know where our offset goes
Adam Powell696cba52011-03-29 10:38:16 -07003489 }
3490
Adam Powelldfee59a2011-08-05 20:48:30 -07003491 if (listMenuPresenter == null) {
3492 listMenuPresenter = new ListMenuPresenter(
Alan Viverette40982d42014-07-25 17:48:55 -07003493 R.layout.list_menu_item_layout, listPresenterTheme);
Adam Powelldfee59a2011-08-05 20:48:30 -07003494 listMenuPresenter.setCallback(cb);
Alan Viverette40982d42014-07-25 17:48:55 -07003495 listMenuPresenter.setId(R.id.list_menu_presenter);
Adam Powelldfee59a2011-08-05 20:48:30 -07003496 menu.addMenuPresenter(listMenuPresenter);
3497 }
3498
3499 if (iconMenuPresenter != null) {
3500 listMenuPresenter.setItemIndexOffset(
3501 iconMenuPresenter.getNumActualItemsShown());
3502 }
3503 MenuView result = listMenuPresenter.getMenuView(decorView);
Adam Powell696cba52011-03-29 10:38:16 -07003504
Adam Powell696cba52011-03-29 10:38:16 -07003505 return result;
3506 }
3507
Adam Powell538e5652011-10-11 13:47:08 -07003508 MenuView getIconMenuView(Context context, MenuPresenter.Callback cb) {
Adam Powell696cba52011-03-29 10:38:16 -07003509 if (menu == null) return null;
3510
Adam Powell696cba52011-03-29 10:38:16 -07003511 if (iconMenuPresenter == null) {
Adam Powell538e5652011-10-11 13:47:08 -07003512 iconMenuPresenter = new IconMenuPresenter(context);
Adam Powell696cba52011-03-29 10:38:16 -07003513 iconMenuPresenter.setCallback(cb);
Alan Viverette40982d42014-07-25 17:48:55 -07003514 iconMenuPresenter.setId(R.id.icon_menu_presenter);
Adam Powell696cba52011-03-29 10:38:16 -07003515 menu.addMenuPresenter(iconMenuPresenter);
Adam Powell696cba52011-03-29 10:38:16 -07003516 }
3517
3518 MenuView result = iconMenuPresenter.getMenuView(decorView);
3519
Adam Powell696cba52011-03-29 10:38:16 -07003520 return result;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003521 }
3522
3523 Parcelable onSaveInstanceState() {
3524 SavedState savedState = new SavedState();
3525 savedState.featureId = featureId;
3526 savedState.isOpen = isOpen;
3527 savedState.isInExpandedMode = isInExpandedMode;
3528
3529 if (menu != null) {
3530 savedState.menuState = new Bundle();
Adam Powell11ed1d62011-07-11 21:19:59 -07003531 menu.savePresenterStates(savedState.menuState);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003532 }
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -08003533
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003534 return savedState;
3535 }
3536
3537 void onRestoreInstanceState(Parcelable state) {
3538 SavedState savedState = (SavedState) state;
3539 featureId = savedState.featureId;
Dianne Hackbornd0071442009-09-25 01:35:29 -07003540 wasLastOpen = savedState.isOpen;
3541 wasLastExpanded = savedState.isInExpandedMode;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003542 frozenMenuState = savedState.menuState;
3543
3544 /*
3545 * A LocalActivityManager keeps the same instance of this class around.
3546 * The first time the menu is being shown after restoring, the
3547 * Activity.onCreateOptionsMenu should be called. But, if it is the
3548 * same instance then menu != null and we won't call that method.
Adam Powell31bb97d2011-05-03 20:58:31 -07003549 * We clear any cached views here. The caller should invalidatePanelMenu.
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003550 */
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003551 createdPanelView = null;
3552 shownPanelView = null;
3553 decorView = null;
3554 }
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -08003555
Adam Powell11ed1d62011-07-11 21:19:59 -07003556 void applyFrozenState() {
3557 if (menu != null && frozenMenuState != null) {
3558 menu.restorePresenterStates(frozenMenuState);
3559 frozenMenuState = null;
3560 }
3561 }
3562
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003563 private static class SavedState implements Parcelable {
3564 int featureId;
3565 boolean isOpen;
3566 boolean isInExpandedMode;
3567 Bundle menuState;
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -08003568
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003569 public int describeContents() {
3570 return 0;
3571 }
3572
3573 public void writeToParcel(Parcel dest, int flags) {
3574 dest.writeInt(featureId);
3575 dest.writeInt(isOpen ? 1 : 0);
3576 dest.writeInt(isInExpandedMode ? 1 : 0);
3577
3578 if (isOpen) {
3579 dest.writeBundle(menuState);
3580 }
3581 }
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -08003582
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003583 private static SavedState readFromParcel(Parcel source) {
3584 SavedState savedState = new SavedState();
3585 savedState.featureId = source.readInt();
3586 savedState.isOpen = source.readInt() == 1;
3587 savedState.isInExpandedMode = source.readInt() == 1;
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -08003588
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003589 if (savedState.isOpen) {
3590 savedState.menuState = source.readBundle();
3591 }
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -08003592
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003593 return savedState;
3594 }
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -08003595
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003596 public static final Parcelable.Creator<SavedState> CREATOR
3597 = new Parcelable.Creator<SavedState>() {
3598 public SavedState createFromParcel(Parcel in) {
3599 return readFromParcel(in);
3600 }
3601
3602 public SavedState[] newArray(int size) {
3603 return new SavedState[size];
3604 }
3605 };
3606 }
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -08003607
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003608 }
3609
Adam Powell6711f3b2015-05-06 15:57:09 -07003610 static class RotationWatcher extends Stub {
Adam Powelldfee59a2011-08-05 20:48:30 -07003611 private Handler mHandler;
3612 private final Runnable mRotationChanged = new Runnable() {
3613 public void run() {
3614 dispatchRotationChanged();
3615 }
3616 };
3617 private final ArrayList<WeakReference<PhoneWindow>> mWindows =
3618 new ArrayList<WeakReference<PhoneWindow>>();
3619 private boolean mIsWatching;
3620
3621 @Override
3622 public void onRotationChanged(int rotation) throws RemoteException {
3623 mHandler.post(mRotationChanged);
3624 }
3625
3626 public void addWindow(PhoneWindow phoneWindow) {
3627 synchronized (mWindows) {
3628 if (!mIsWatching) {
3629 try {
Andrii Kulian35fa3c22017-03-11 09:37:28 -08003630 WindowManagerHolder.sWindowManager.watchRotation(this,
3631 phoneWindow.getContext().getDisplay().getDisplayId());
Adam Powelldfee59a2011-08-05 20:48:30 -07003632 mHandler = new Handler();
3633 mIsWatching = true;
3634 } catch (RemoteException ex) {
3635 Log.e(TAG, "Couldn't start watching for device rotation", ex);
3636 }
3637 }
3638 mWindows.add(new WeakReference<PhoneWindow>(phoneWindow));
3639 }
3640 }
3641
3642 public void removeWindow(PhoneWindow phoneWindow) {
3643 synchronized (mWindows) {
3644 int i = 0;
3645 while (i < mWindows.size()) {
3646 final WeakReference<PhoneWindow> ref = mWindows.get(i);
3647 final PhoneWindow win = ref.get();
3648 if (win == null || win == phoneWindow) {
3649 mWindows.remove(i);
3650 } else {
3651 i++;
3652 }
3653 }
3654 }
3655 }
3656
3657 void dispatchRotationChanged() {
3658 synchronized (mWindows) {
3659 int i = 0;
3660 while (i < mWindows.size()) {
3661 final WeakReference<PhoneWindow> ref = mWindows.get(i);
3662 final PhoneWindow win = ref.get();
3663 if (win != null) {
3664 win.onOptionsPanelRotationChanged();
3665 i++;
3666 } else {
3667 mWindows.remove(i);
3668 }
3669 }
3670 }
3671 }
3672 }
3673
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003674 /**
3675 * Simple implementation of MenuBuilder.Callback that:
3676 * <li> Opens a submenu when selected.
3677 * <li> Calls back to the callback's onMenuItemSelected when an item is
3678 * selected.
3679 */
Alan Viverette77fb85e2015-12-14 11:42:44 -05003680 public static final class PhoneWindowMenuCallback
3681 implements MenuBuilder.Callback, MenuPresenter.Callback {
3682 private static final int FEATURE_ID = FEATURE_CONTEXT_MENU;
3683
3684 private final PhoneWindow mWindow;
3685
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003686 private MenuDialogHelper mSubMenuHelper;
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -08003687
Alan Viverette77fb85e2015-12-14 11:42:44 -05003688 private boolean mShowDialogForSubmenu;
3689
3690 public PhoneWindowMenuCallback(PhoneWindow window) {
3691 mWindow = window;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003692 }
3693
Alan Viverette77fb85e2015-12-14 11:42:44 -05003694 @Override
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003695 public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) {
Adam Powelld1f42072011-05-03 17:20:14 -07003696 if (menu.getRootMenu() != menu) {
3697 onCloseSubMenu(menu);
3698 }
3699
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003700 if (allMenusAreClosing) {
Alan Viverette77fb85e2015-12-14 11:42:44 -05003701 final Callback callback = mWindow.getCallback();
3702 if (callback != null && !mWindow.isDestroyed()) {
3703 callback.onPanelClosed(FEATURE_ID, menu);
Dianne Hackbornb66ad572011-03-01 17:10:30 -08003704 }
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -08003705
Alan Viverette77fb85e2015-12-14 11:42:44 -05003706 if (menu == mWindow.mContextMenu) {
3707 mWindow.dismissContextMenu();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003708 }
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -08003709
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003710 // Dismiss the submenu, if it is showing
3711 if (mSubMenuHelper != null) {
3712 mSubMenuHelper.dismiss();
3713 mSubMenuHelper = null;
3714 }
3715 }
3716 }
3717
Alan Viverette77fb85e2015-12-14 11:42:44 -05003718 private void onCloseSubMenu(MenuBuilder menu) {
3719 final Callback callback = mWindow.getCallback();
3720 if (callback != null && !mWindow.isDestroyed()) {
3721 callback.onPanelClosed(FEATURE_ID, menu.getRootMenu());
Dianne Hackbornb66ad572011-03-01 17:10:30 -08003722 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003723 }
3724
Alan Viverette77fb85e2015-12-14 11:42:44 -05003725 @Override
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003726 public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) {
Alan Viverette77fb85e2015-12-14 11:42:44 -05003727 final Callback callback = mWindow.getCallback();
3728 return callback != null && !mWindow.isDestroyed()
3729 && callback.onMenuItemSelected(FEATURE_ID, item);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003730 }
3731
Alan Viverette77fb85e2015-12-14 11:42:44 -05003732 @Override
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003733 public void onMenuModeChange(MenuBuilder menu) {
3734 }
3735
Alan Viverette77fb85e2015-12-14 11:42:44 -05003736 @Override
Adam Powelld1f42072011-05-03 17:20:14 -07003737 public boolean onOpenSubMenu(MenuBuilder subMenu) {
Alan Viverette77fb85e2015-12-14 11:42:44 -05003738 if (subMenu == null) {
3739 return false;
3740 }
Adam Powell823f0742011-09-21 17:17:01 -07003741
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003742 // Set a simple callback for the submenu
3743 subMenu.setCallback(this);
3744
Alan Viverette77fb85e2015-12-14 11:42:44 -05003745 if (mShowDialogForSubmenu) {
3746 // The window manager will give us a valid window token
3747 mSubMenuHelper = new MenuDialogHelper(subMenu);
3748 mSubMenuHelper.show(null);
3749 return true;
3750 }
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -08003751
Alan Viverette77fb85e2015-12-14 11:42:44 -05003752 return false;
3753 }
3754
3755 public void setShowDialogForSubmenu(boolean enabled) {
3756 mShowDialogForSubmenu = enabled;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003757 }
3758 }
3759
Wale Ogunwale8804af22015-11-17 09:18:15 -08003760 int getLocalFeaturesPrivate() {
3761 return super.getLocalFeatures();
3762 }
Adrian Roos05054bd2014-10-27 17:04:10 +01003763
Wale Ogunwale8804af22015-11-17 09:18:15 -08003764 protected void setDefaultWindowFormat(int format) {
3765 super.setDefaultWindowFormat(format);
Adrian Roos05054bd2014-10-27 17:04:10 +01003766 }
3767
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003768 void sendCloseSystemWindows() {
Jorim Jaggib10e33f2015-02-04 21:57:40 +01003769 sendCloseSystemWindows(getContext(), null);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003770 }
3771
3772 void sendCloseSystemWindows(String reason) {
Jorim Jaggib10e33f2015-02-04 21:57:40 +01003773 sendCloseSystemWindows(getContext(), reason);
3774 }
3775
3776 public static void sendCloseSystemWindows(Context context, String reason) {
Sudheer Shankadc589ac2016-11-10 15:30:17 -08003777 if (ActivityManager.isSystemReady()) {
Jorim Jaggib10e33f2015-02-04 21:57:40 +01003778 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -08003779 ActivityManager.getService().closeSystemDialogs(reason);
Jorim Jaggib10e33f2015-02-04 21:57:40 +01003780 } catch (RemoteException e) {
3781 }
3782 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003783 }
Adrian Roos217ccd22014-05-09 14:29:04 +02003784
3785 @Override
3786 public int getStatusBarColor() {
Adrian Roos34e65442014-05-17 02:35:33 +02003787 return mStatusBarColor;
Adrian Roos217ccd22014-05-09 14:29:04 +02003788 }
3789
3790 @Override
3791 public void setStatusBarColor(int color) {
Adrian Roos34e65442014-05-17 02:35:33 +02003792 mStatusBarColor = color;
3793 mForcedStatusBarColor = true;
3794 if (mDecor != null) {
Adrian Roos05054bd2014-10-27 17:04:10 +01003795 mDecor.updateColorViews(null, false /* animate */);
Adrian Roos34e65442014-05-17 02:35:33 +02003796 }
Adrian Roos217ccd22014-05-09 14:29:04 +02003797 }
3798
3799 @Override
3800 public int getNavigationBarColor() {
Adrian Roos34e65442014-05-17 02:35:33 +02003801 return mNavigationBarColor;
Adrian Roos217ccd22014-05-09 14:29:04 +02003802 }
3803
3804 @Override
3805 public void setNavigationBarColor(int color) {
Adrian Roos34e65442014-05-17 02:35:33 +02003806 mNavigationBarColor = color;
3807 mForcedNavigationBarColor = true;
3808 if (mDecor != null) {
Adrian Roos05054bd2014-10-27 17:04:10 +01003809 mDecor.updateColorViews(null, false /* animate */);
Seigo Nonaka0a9d1ea2015-11-18 22:29:06 +09003810 mDecor.updateNavigationGuardColor();
Adrian Roos34e65442014-05-17 02:35:33 +02003811 }
Adrian Roos217ccd22014-05-09 14:29:04 +02003812 }
Jorim Jaggia16cc152015-06-01 16:55:05 -07003813
3814 public void setIsStartingWindow(boolean isStartingWindow) {
3815 mIsStartingWindow = isStartingWindow;
3816 }
Stefan Kuhnef4dd71a2015-08-07 09:28:52 -07003817
Filip Gruszczynskia59ac9c2015-09-10 18:28:48 -07003818 @Override
Filip Gruszczynski0daf2102015-09-29 08:39:07 -07003819 public void setTheme(int resid) {
3820 mTheme = resid;
3821 if (mDecor != null) {
3822 Context context = mDecor.getContext();
3823 if (context instanceof DecorContext) {
3824 context.setTheme(resid);
3825 }
3826 }
3827 }
Filip Gruszczynski3dec0812015-12-09 08:42:41 -08003828
3829 @Override
3830 public void setResizingCaptionDrawable(Drawable drawable) {
3831 mDecor.setUserCaptionBackgroundDrawable(drawable);
3832 }
3833
3834 @Override
3835 public void setDecorCaptionShade(int decorCaptionShade) {
3836 mDecorCaptionShade = decorCaptionShade;
3837 if (mDecor != null) {
3838 mDecor.updateDecorCaptionShade();
3839 }
3840 }
3841
3842 int getDecorCaptionShade() {
3843 return mDecorCaptionShade;
3844 }
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08003845
3846 @Override
3847 public void setAttributes(WindowManager.LayoutParams params) {
3848 super.setAttributes(params);
3849 if (mDecor != null) {
3850 mDecor.updateLogTag(params);
3851 }
3852 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003853}