blob: 7ea023eb50b2503209c7d250db40b98842d6db64 [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 }
Erik Wolsheimerac5cecd2017-12-05 13:11:50 -08002043 if ((getContext().getResources().getConfiguration().uiMode
2044 & Configuration.UI_MODE_TYPE_MASK) == Configuration.UI_MODE_TYPE_WATCH) {
2045 break;
2046 }
Dianne Hackborna207baa2009-09-13 16:14:44 -07002047 if (event.isTracking() && !event.isCanceled()) {
Tim Kilbourn6a975b32015-04-09 17:14:34 -07002048 launchDefaultSearch(event);
Dianne Hackborn0041e972009-07-24 17:14:43 -07002049 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002050 return true;
2051 }
Jaewan Kimf0fd2182016-04-20 21:17:58 +09002052
2053 case KeyEvent.KEYCODE_WINDOW: {
Jaewan Kimd98dcab2016-05-03 02:52:18 +09002054 if (mSupportsPictureInPicture && !event.isCanceled()) {
2055 getWindowControllerCallback().enterPictureInPictureModeIfPossible();
Jaewan Kimf0fd2182016-04-20 21:17:58 +09002056 }
2057 return true;
2058 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002059 }
2060
2061 return false;
2062 }
2063
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002064 @Override
2065 protected void onActive() {
2066 }
2067
2068 @Override
2069 public final View getDecorView() {
Filip Gruszczynskia59ac9c2015-09-10 18:28:48 -07002070 if (mDecor == null || mForceDecorInstall) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002071 installDecor();
2072 }
2073 return mDecor;
2074 }
2075
2076 @Override
2077 public final View peekDecorView() {
2078 return mDecor;
2079 }
2080
Andrii Kulian51c1b672017-04-07 18:39:32 -07002081 /** Notify when decor view is attached to window and {@link ViewRootImpl} is available. */
2082 void onViewRootImplSet(ViewRootImpl viewRoot) {
2083 viewRoot.setActivityConfigCallback(mActivityConfigCallback);
2084 }
2085
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002086 static private final String FOCUSED_ID_TAG = "android:focusedViewId";
2087 static private final String VIEWS_TAG = "android:views";
2088 static private final String PANELS_TAG = "android:Panels";
Adam Powell6c6f5752010-08-20 18:34:46 -07002089 static private final String ACTION_BAR_TAG = "android:ActionBar";
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002090
Alan Viveretteeae66cd2015-08-13 20:05:35 +00002091 /** {@inheritDoc} */
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002092 @Override
2093 public Bundle saveHierarchyState() {
Alan Viveretteeae66cd2015-08-13 20:05:35 +00002094 Bundle outState = new Bundle();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002095 if (mContentParent == null) {
2096 return outState;
2097 }
2098
Alan Viveretteeae66cd2015-08-13 20:05:35 +00002099 SparseArray<Parcelable> states = new SparseArray<Parcelable>();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002100 mContentParent.saveHierarchyState(states);
2101 outState.putSparseParcelableArray(VIEWS_TAG, states);
2102
Alan Viveretteec6cf182015-08-13 15:31:57 -04002103 // Save the focused view ID.
2104 final View focusedView = mContentParent.findFocus();
2105 if (focusedView != null && focusedView.getId() != View.NO_ID) {
2106 outState.putInt(FOCUSED_ID_TAG, focusedView.getId());
2107 }
2108
Alan Viveretteeae66cd2015-08-13 20:05:35 +00002109 // save the panels
2110 SparseArray<Parcelable> panelStates = new SparseArray<Parcelable>();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002111 savePanelState(panelStates);
2112 if (panelStates.size() > 0) {
2113 outState.putSparseParcelableArray(PANELS_TAG, panelStates);
2114 }
2115
Adam Powell4369e7d2014-05-17 14:16:08 -07002116 if (mDecorContentParent != null) {
Alan Viveretteeae66cd2015-08-13 20:05:35 +00002117 SparseArray<Parcelable> actionBarStates = new SparseArray<Parcelable>();
Adam Powell4369e7d2014-05-17 14:16:08 -07002118 mDecorContentParent.saveToolbarHierarchyState(actionBarStates);
Adam Powell8d02dea2011-05-31 21:35:13 -07002119 outState.putSparseParcelableArray(ACTION_BAR_TAG, actionBarStates);
Adam Powell6c6f5752010-08-20 18:34:46 -07002120 }
2121
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002122 return outState;
2123 }
2124
Alan Viveretteeae66cd2015-08-13 20:05:35 +00002125 /** {@inheritDoc} */
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002126 @Override
2127 public void restoreHierarchyState(Bundle savedInstanceState) {
2128 if (mContentParent == null) {
2129 return;
2130 }
2131
Alan Viveretteeae66cd2015-08-13 20:05:35 +00002132 SparseArray<Parcelable> savedStates
2133 = savedInstanceState.getSparseParcelableArray(VIEWS_TAG);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002134 if (savedStates != null) {
2135 mContentParent.restoreHierarchyState(savedStates);
2136 }
2137
Alan Viveretteeae66cd2015-08-13 20:05:35 +00002138 // restore the focused view
2139 int focusedViewId = savedInstanceState.getInt(FOCUSED_ID_TAG, View.NO_ID);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002140 if (focusedViewId != View.NO_ID) {
Alan Viveretteeae66cd2015-08-13 20:05:35 +00002141 View needsFocus = mContentParent.findViewById(focusedViewId);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002142 if (needsFocus != null) {
2143 needsFocus.requestFocus();
2144 } else {
Alan Viveretteeae66cd2015-08-13 20:05:35 +00002145 Log.w(TAG,
2146 "Previously focused view reported id " + focusedViewId
2147 + " during save, but can't be found during restore.");
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002148 }
2149 }
2150
Alan Viveretteec6cf182015-08-13 15:31:57 -04002151 // Restore the panels.
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002152 SparseArray<Parcelable> panelStates = savedInstanceState.getSparseParcelableArray(PANELS_TAG);
2153 if (panelStates != null) {
2154 restorePanelState(panelStates);
2155 }
Adam Powell6c6f5752010-08-20 18:34:46 -07002156
Adam Powell4369e7d2014-05-17 14:16:08 -07002157 if (mDecorContentParent != null) {
Adam Powell8d02dea2011-05-31 21:35:13 -07002158 SparseArray<Parcelable> actionBarStates =
2159 savedInstanceState.getSparseParcelableArray(ACTION_BAR_TAG);
Adam Powellfb5f1bc2012-05-17 19:30:35 -07002160 if (actionBarStates != null) {
Adam Powell31c91c82014-08-22 17:20:00 -07002161 doPendingInvalidatePanelMenu();
Adam Powell4369e7d2014-05-17 14:16:08 -07002162 mDecorContentParent.restoreToolbarHierarchyState(actionBarStates);
Adam Powellfb5f1bc2012-05-17 19:30:35 -07002163 } else {
2164 Log.w(TAG, "Missing saved instance states for action bar views! " +
2165 "State will not be restored.");
2166 }
Adam Powell6c6f5752010-08-20 18:34:46 -07002167 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002168 }
2169
2170 /**
2171 * Invoked when the panels should freeze their state.
2172 *
2173 * @param icicles Save state into this. This is usually indexed by the
2174 * featureId. This will be given to {@link #restorePanelState} in the
2175 * future.
2176 */
2177 private void savePanelState(SparseArray<Parcelable> icicles) {
2178 PanelFeatureState[] panels = mPanels;
2179 if (panels == null) {
2180 return;
2181 }
2182
2183 for (int curFeatureId = panels.length - 1; curFeatureId >= 0; curFeatureId--) {
2184 if (panels[curFeatureId] != null) {
2185 icicles.put(curFeatureId, panels[curFeatureId].onSaveInstanceState());
2186 }
2187 }
2188 }
2189
2190 /**
2191 * Invoked when the panels should thaw their state from a previously frozen state.
2192 *
2193 * @param icicles The state saved by {@link #savePanelState} that needs to be thawed.
2194 */
2195 private void restorePanelState(SparseArray<Parcelable> icicles) {
2196 PanelFeatureState st;
Dmitry Tsyganyuk554bb012012-04-02 13:10:52 -05002197 int curFeatureId;
2198 for (int i = icicles.size() - 1; i >= 0; i--) {
2199 curFeatureId = icicles.keyAt(i);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002200 st = getPanelState(curFeatureId, false /* required */);
2201 if (st == null) {
2202 // The panel must not have been required, and is currently not around, skip it
2203 continue;
2204 }
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -08002205
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002206 st.onRestoreInstanceState(icicles.get(curFeatureId));
Adam Powell31bb97d2011-05-03 20:58:31 -07002207 invalidatePanelMenu(curFeatureId);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002208 }
2209
2210 /*
2211 * Implementation note: call openPanelsAfterRestore later to actually open the
2212 * restored panels.
2213 */
2214 }
2215
2216 /**
2217 * Opens the panels that have had their state restored. This should be
2218 * called sometime after {@link #restorePanelState} when it is safe to add
2219 * to the window manager.
2220 */
Wale Ogunwale8804af22015-11-17 09:18:15 -08002221 void openPanelsAfterRestore() {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002222 PanelFeatureState[] panels = mPanels;
2223
2224 if (panels == null) {
2225 return;
2226 }
2227
2228 PanelFeatureState st;
2229 for (int i = panels.length - 1; i >= 0; i--) {
2230 st = panels[i];
Dianne Hackbornd0071442009-09-25 01:35:29 -07002231 // We restore the panel if it was last open; we skip it if it
2232 // now is open, to avoid a race condition if the user immediately
2233 // opens it when we are resuming.
Adam Powell11ed1d62011-07-11 21:19:59 -07002234 if (st != null) {
2235 st.applyFrozenState();
2236 if (!st.isOpen && st.wasLastOpen) {
2237 st.isInExpandedMode = st.wasLastExpanded;
2238 openPanel(st, null);
2239 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002240 }
2241 }
2242 }
2243
Adam Powell696cba52011-03-29 10:38:16 -07002244 private class PanelMenuPresenterCallback implements MenuPresenter.Callback {
2245 @Override
2246 public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) {
2247 final Menu parentMenu = menu.getRootMenu();
2248 final boolean isSubMenu = parentMenu != menu;
2249 final PanelFeatureState panel = findMenuPanel(isSubMenu ? parentMenu : menu);
2250 if (panel != null) {
2251 if (isSubMenu) {
2252 callOnPanelClosed(panel.featureId, panel, parentMenu);
2253 closePanel(panel, true);
2254 } else {
2255 // Close the panel and only do the callback if the menu is being
2256 // closed completely, not if opening a sub menu
2257 closePanel(panel, allMenusAreClosing);
2258 }
2259 }
2260 }
2261
2262 @Override
2263 public boolean onOpenSubMenu(MenuBuilder subMenu) {
2264 if (subMenu == null && hasFeature(FEATURE_ACTION_BAR)) {
2265 Callback cb = getCallback();
2266 if (cb != null && !isDestroyed()) {
2267 cb.onMenuOpened(FEATURE_ACTION_BAR, subMenu);
2268 }
2269 }
2270
2271 return true;
2272 }
2273 }
2274
2275 private final class ActionMenuPresenterCallback implements MenuPresenter.Callback {
2276 @Override
2277 public boolean onOpenSubMenu(MenuBuilder subMenu) {
2278 Callback cb = getCallback();
2279 if (cb != null) {
2280 cb.onMenuOpened(FEATURE_ACTION_BAR, subMenu);
2281 return true;
2282 }
2283 return false;
2284 }
2285
2286 @Override
2287 public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) {
2288 checkCloseActionMenu(menu);
2289 }
2290 }
2291
Stefan Kuhne61b47bb2015-07-28 14:04:25 -07002292 protected DecorView generateDecor(int featureId) {
Filip Gruszczynski0daf2102015-09-29 08:39:07 -07002293 // System process doesn't have application context and in that case we need to directly use
2294 // the context we have. Otherwise we want the application context, so we don't cling to the
2295 // activity.
Filip Gruszczynski0daf2102015-09-29 08:39:07 -07002296 Context context;
Filip Gruszczynski796b8c12015-12-22 14:46:21 -08002297 if (mUseDecorContext) {
2298 Context applicationContext = getContext().getApplicationContext();
2299 if (applicationContext == null) {
2300 context = getContext();
2301 } else {
chaviwa213d302018-04-23 13:34:36 -07002302 context = new DecorContext(applicationContext, getContext());
Filip Gruszczynski796b8c12015-12-22 14:46:21 -08002303 if (mTheme != -1) {
2304 context.setTheme(mTheme);
2305 }
Filip Gruszczynski0daf2102015-09-29 08:39:07 -07002306 }
Filip Gruszczynski796b8c12015-12-22 14:46:21 -08002307 } else {
2308 context = getContext();
Filip Gruszczynski0daf2102015-09-29 08:39:07 -07002309 }
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08002310 return new DecorView(context, featureId, this, getAttributes());
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002311 }
2312
2313 protected ViewGroup generateLayout(DecorView decor) {
2314 // Apply data from current theme.
2315
2316 TypedArray a = getWindowStyle();
2317
2318 if (false) {
2319 System.out.println("From style:");
2320 String s = "Attrs:";
Alan Viverette40982d42014-07-25 17:48:55 -07002321 for (int i = 0; i < R.styleable.Window.length; i++) {
2322 s = s + " " + Integer.toHexString(R.styleable.Window[i]) + "="
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002323 + a.getString(i);
2324 }
2325 System.out.println(s);
2326 }
2327
Alan Viverette40982d42014-07-25 17:48:55 -07002328 mIsFloating = a.getBoolean(R.styleable.Window_windowIsFloating, false);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002329 int flagsToUpdate = (FLAG_LAYOUT_IN_SCREEN|FLAG_LAYOUT_INSET_DECOR)
2330 & (~getForcedWindowFlags());
2331 if (mIsFloating) {
2332 setLayout(WRAP_CONTENT, WRAP_CONTENT);
2333 setFlags(0, flagsToUpdate);
2334 } else {
2335 setFlags(FLAG_LAYOUT_IN_SCREEN|FLAG_LAYOUT_INSET_DECOR, flagsToUpdate);
2336 }
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -08002337
Alan Viverette40982d42014-07-25 17:48:55 -07002338 if (a.getBoolean(R.styleable.Window_windowNoTitle, false)) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002339 requestFeature(FEATURE_NO_TITLE);
Alan Viverette40982d42014-07-25 17:48:55 -07002340 } else if (a.getBoolean(R.styleable.Window_windowActionBar, false)) {
Adam Powell33b97432010-04-20 10:01:14 -07002341 // Don't allow an action bar if there is no title.
2342 requestFeature(FEATURE_ACTION_BAR);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002343 }
2344
Alan Viverette40982d42014-07-25 17:48:55 -07002345 if (a.getBoolean(R.styleable.Window_windowActionBarOverlay, false)) {
Adam Powell6b336f82010-08-10 20:13:01 -07002346 requestFeature(FEATURE_ACTION_BAR_OVERLAY);
2347 }
2348
Alan Viverette40982d42014-07-25 17:48:55 -07002349 if (a.getBoolean(R.styleable.Window_windowActionModeOverlay, false)) {
Adam Powell5d279772010-07-27 16:34:07 -07002350 requestFeature(FEATURE_ACTION_MODE_OVERLAY);
2351 }
2352
Alan Viverette40982d42014-07-25 17:48:55 -07002353 if (a.getBoolean(R.styleable.Window_windowSwipeToDismiss, false)) {
Will Haldean Brownca6234e2014-02-12 10:23:41 -08002354 requestFeature(FEATURE_SWIPE_TO_DISMISS);
2355 }
2356
Alan Viverette40982d42014-07-25 17:48:55 -07002357 if (a.getBoolean(R.styleable.Window_windowFullscreen, false)) {
Dianne Hackbornc652de82013-02-15 16:32:56 -08002358 setFlags(FLAG_FULLSCREEN, FLAG_FULLSCREEN & (~getForcedWindowFlags()));
2359 }
2360
Alan Viverette40982d42014-07-25 17:48:55 -07002361 if (a.getBoolean(R.styleable.Window_windowTranslucentStatus,
John Spurlockbd957402013-10-03 11:38:39 -04002362 false)) {
2363 setFlags(FLAG_TRANSLUCENT_STATUS, FLAG_TRANSLUCENT_STATUS
2364 & (~getForcedWindowFlags()));
2365 }
2366
Alan Viverette40982d42014-07-25 17:48:55 -07002367 if (a.getBoolean(R.styleable.Window_windowTranslucentNavigation,
John Spurlockbd957402013-10-03 11:38:39 -04002368 false)) {
2369 setFlags(FLAG_TRANSLUCENT_NAVIGATION, FLAG_TRANSLUCENT_NAVIGATION
2370 & (~getForcedWindowFlags()));
2371 }
2372
Alan Viverette40982d42014-07-25 17:48:55 -07002373 if (a.getBoolean(R.styleable.Window_windowOverscan, false)) {
Dianne Hackbornc652de82013-02-15 16:32:56 -08002374 setFlags(FLAG_LAYOUT_IN_OVERSCAN, FLAG_LAYOUT_IN_OVERSCAN&(~getForcedWindowFlags()));
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002375 }
2376
Alan Viverette40982d42014-07-25 17:48:55 -07002377 if (a.getBoolean(R.styleable.Window_windowShowWallpaper, false)) {
Dianne Hackborn4bf7bcf2009-08-09 17:23:00 -07002378 setFlags(FLAG_SHOW_WALLPAPER, FLAG_SHOW_WALLPAPER&(~getForcedWindowFlags()));
2379 }
2380
Alan Viverette40982d42014-07-25 17:48:55 -07002381 if (a.getBoolean(R.styleable.Window_windowEnableSplitTouch,
Jeff Brown46e75292010-11-10 16:53:45 -08002382 getContext().getApplicationInfo().targetSdkVersion
2383 >= android.os.Build.VERSION_CODES.HONEYCOMB)) {
2384 setFlags(FLAG_SPLIT_TOUCH, FLAG_SPLIT_TOUCH&(~getForcedWindowFlags()));
2385 }
2386
Alan Viverette40982d42014-07-25 17:48:55 -07002387 a.getValue(R.styleable.Window_windowMinWidthMajor, mMinWidthMajor);
2388 a.getValue(R.styleable.Window_windowMinWidthMinor, mMinWidthMinor);
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08002389 if (DEBUG) Log.d(TAG, "Min width minor: " + mMinWidthMinor.coerceToString()
2390 + ", major: " + mMinWidthMajor.coerceToString());
Alan Viverette40982d42014-07-25 17:48:55 -07002391 if (a.hasValue(R.styleable.Window_windowFixedWidthMajor)) {
Adam Powell40eec4c2012-02-15 17:10:58 -08002392 if (mFixedWidthMajor == null) mFixedWidthMajor = new TypedValue();
Alan Viverette40982d42014-07-25 17:48:55 -07002393 a.getValue(R.styleable.Window_windowFixedWidthMajor,
Adam Powell40eec4c2012-02-15 17:10:58 -08002394 mFixedWidthMajor);
2395 }
Alan Viverette40982d42014-07-25 17:48:55 -07002396 if (a.hasValue(R.styleable.Window_windowFixedWidthMinor)) {
Adam Powell40eec4c2012-02-15 17:10:58 -08002397 if (mFixedWidthMinor == null) mFixedWidthMinor = new TypedValue();
Alan Viverette40982d42014-07-25 17:48:55 -07002398 a.getValue(R.styleable.Window_windowFixedWidthMinor,
Adam Powell40eec4c2012-02-15 17:10:58 -08002399 mFixedWidthMinor);
2400 }
Alan Viverette40982d42014-07-25 17:48:55 -07002401 if (a.hasValue(R.styleable.Window_windowFixedHeightMajor)) {
Adam Powell40eec4c2012-02-15 17:10:58 -08002402 if (mFixedHeightMajor == null) mFixedHeightMajor = new TypedValue();
Alan Viverette40982d42014-07-25 17:48:55 -07002403 a.getValue(R.styleable.Window_windowFixedHeightMajor,
Adam Powell40eec4c2012-02-15 17:10:58 -08002404 mFixedHeightMajor);
2405 }
Alan Viverette40982d42014-07-25 17:48:55 -07002406 if (a.hasValue(R.styleable.Window_windowFixedHeightMinor)) {
Adam Powell40eec4c2012-02-15 17:10:58 -08002407 if (mFixedHeightMinor == null) mFixedHeightMinor = new TypedValue();
Alan Viverette40982d42014-07-25 17:48:55 -07002408 a.getValue(R.styleable.Window_windowFixedHeightMinor,
Adam Powell40eec4c2012-02-15 17:10:58 -08002409 mFixedHeightMinor);
2410 }
Alan Viverette40982d42014-07-25 17:48:55 -07002411 if (a.getBoolean(R.styleable.Window_windowContentTransitions, false)) {
Adam Powell18e905f2013-10-24 14:27:48 -07002412 requestFeature(FEATURE_CONTENT_TRANSITIONS);
Michael Kolb4bb047f2014-04-01 14:38:57 -07002413 }
George Mount9826f632014-09-11 08:50:09 -07002414 if (a.getBoolean(R.styleable.Window_windowActivityTransitions, false)) {
2415 requestFeature(FEATURE_ACTIVITY_TRANSITIONS);
2416 }
Filip Gruszczynskib57503c2014-07-16 16:35:18 -07002417
Jorim Jaggic39c7b02016-03-24 10:47:07 -07002418 mIsTranslucent = a.getBoolean(R.styleable.Window_windowIsTranslucent, false);
2419
Adam Powell82349c52011-08-23 13:53:56 -07002420 final Context context = getContext();
2421 final int targetSdk = context.getApplicationInfo().targetSdkVersion;
2422 final boolean targetPreHoneycomb = targetSdk < android.os.Build.VERSION_CODES.HONEYCOMB;
2423 final boolean targetPreIcs = targetSdk < android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH;
Dianne Hackborn955d8d62014-10-07 20:17:19 -07002424 final boolean targetPreL = targetSdk < android.os.Build.VERSION_CODES.LOLLIPOP;
Adam Powell82349c52011-08-23 13:53:56 -07002425 final boolean targetHcNeedsOptions = context.getResources().getBoolean(
Alan Viverette40982d42014-07-25 17:48:55 -07002426 R.bool.target_honeycomb_needs_options_menu);
Adam Powell82349c52011-08-23 13:53:56 -07002427 final boolean noActionBar = !hasFeature(FEATURE_ACTION_BAR) || hasFeature(FEATURE_NO_TITLE);
2428
2429 if (targetPreHoneycomb || (targetPreIcs && targetHcNeedsOptions && noActionBar)) {
Wale Ogunwale393b1c12014-10-18 16:22:01 -07002430 setNeedsMenuKey(WindowManager.LayoutParams.NEEDS_MENU_SET_TRUE);
Dianne Hackborn73ab6a42011-12-13 11:16:23 -08002431 } else {
Wale Ogunwale393b1c12014-10-18 16:22:01 -07002432 setNeedsMenuKey(WindowManager.LayoutParams.NEEDS_MENU_SET_FALSE);
Daniel Sandlere02d8082010-10-08 15:13:22 -04002433 }
Adrian Roosea562512014-05-05 13:33:03 +02002434
Jorim Jaggi6e0ce282015-12-01 15:19:49 -08002435 if (!mForcedStatusBarColor) {
2436 mStatusBarColor = a.getColor(R.styleable.Window_statusBarColor, 0xFF000000);
2437 }
2438 if (!mForcedNavigationBarColor) {
2439 mNavigationBarColor = a.getColor(R.styleable.Window_navigationBarColor, 0xFF000000);
Jason Monka750e992017-09-01 12:40:06 -04002440 mNavigationBarDividerColor = a.getColor(R.styleable.Window_navigationBarDividerColor,
2441 0x00000000);
Jorim Jaggi6e0ce282015-12-01 15:19:49 -08002442 }
2443
Jorim Jaggi8f5701b2016-04-04 18:36:02 -07002444 WindowManager.LayoutParams params = getAttributes();
2445
Adrian Roosea562512014-05-05 13:33:03 +02002446 // Non-floating windows on high end devices must put up decor beneath the system bars and
2447 // therefore must know about visibility changes of those.
Matthew Nge6b393b2017-09-01 12:45:04 -07002448 if (!mIsFloating) {
Adrian Roosea562512014-05-05 13:33:03 +02002449 if (!targetPreL && a.getBoolean(
Alan Viverette40982d42014-07-25 17:48:55 -07002450 R.styleable.Window_windowDrawsSystemBarBackgrounds,
Adrian Roosea562512014-05-05 13:33:03 +02002451 false)) {
2452 setFlags(FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
2453 FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS & ~getForcedWindowFlags());
2454 }
Jorim Jaggi8f5701b2016-04-04 18:36:02 -07002455 if (mDecor.mForceWindowDrawsStatusBarBackground) {
2456 params.privateFlags |= PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND;
2457 }
Adrian Roosea562512014-05-05 13:33:03 +02002458 }
Adrian Roosf4f84c92015-04-28 13:44:43 -07002459 if (a.getBoolean(R.styleable.Window_windowLightStatusBar, false)) {
Adrian Roos75fa3852015-01-27 20:21:44 +01002460 decor.setSystemUiVisibility(
2461 decor.getSystemUiVisibility() | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
2462 }
Jason Monkd7acd162017-09-11 08:54:12 -07002463 if (a.getBoolean(R.styleable.Window_windowLightNavigationBar, false)) {
2464 decor.setSystemUiVisibility(
2465 decor.getSystemUiVisibility() | View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR);
2466 }
Adrian Roos22920312018-02-23 14:33:42 +01002467 if (a.hasValue(R.styleable.Window_windowLayoutInDisplayCutoutMode)) {
2468 int mode = a.getInt(R.styleable.Window_windowLayoutInDisplayCutoutMode, -1);
2469 if (mode < LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT
2470 || mode > LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER) {
2471 throw new UnsupportedOperationException("Unknown windowLayoutInDisplayCutoutMode: "
2472 + a.getString(R.styleable.Window_windowLayoutInDisplayCutoutMode));
2473 }
2474 params.layoutInDisplayCutoutMode = mode;
2475 }
Adrian Roosea562512014-05-05 13:33:03 +02002476
Dianne Hackborncfaf8872011-01-18 13:57:54 -08002477 if (mAlwaysReadCloseOnTouchAttr || getContext().getApplicationInfo().targetSdkVersion
2478 >= android.os.Build.VERSION_CODES.HONEYCOMB) {
Dianne Hackbornef575752011-01-18 17:35:17 -08002479 if (a.getBoolean(
Alan Viverette40982d42014-07-25 17:48:55 -07002480 R.styleable.Window_windowCloseOnTouchOutside,
Dianne Hackbornef575752011-01-18 17:35:17 -08002481 false)) {
2482 setCloseOnTouchOutsideIfNotSet(true);
Dianne Hackborncfaf8872011-01-18 13:57:54 -08002483 }
2484 }
Alan Viveretteeb1d3792014-06-03 18:36:03 -07002485
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002486 if (!hasSoftInputMode()) {
2487 params.softInputMode = a.getInt(
Alan Viverette40982d42014-07-25 17:48:55 -07002488 R.styleable.Window_windowSoftInputMode,
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002489 params.softInputMode);
2490 }
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -08002491
Alan Viverette40982d42014-07-25 17:48:55 -07002492 if (a.getBoolean(R.styleable.Window_backgroundDimEnabled,
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002493 mIsFloating)) {
2494 /* All dialogs should have the window dimmed */
2495 if ((getForcedWindowFlags()&WindowManager.LayoutParams.FLAG_DIM_BEHIND) == 0) {
2496 params.flags |= WindowManager.LayoutParams.FLAG_DIM_BEHIND;
2497 }
Dianne Hackborn661cd522011-08-22 00:26:20 -07002498 if (!haveDimAmount()) {
2499 params.dimAmount = a.getFloat(
2500 android.R.styleable.Window_backgroundDimAmount, 0.5f);
2501 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002502 }
2503
2504 if (params.windowAnimations == 0) {
2505 params.windowAnimations = a.getResourceId(
Alan Viverette40982d42014-07-25 17:48:55 -07002506 R.styleable.Window_windowAnimationStyle, 0);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002507 }
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -08002508
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002509 // The rest are only done if this window is not embedded; otherwise,
2510 // the values are inherited from our container.
2511 if (getContainer() == null) {
2512 if (mBackgroundDrawable == null) {
2513 if (mBackgroundResource == 0) {
2514 mBackgroundResource = a.getResourceId(
Alan Viverette40982d42014-07-25 17:48:55 -07002515 R.styleable.Window_windowBackground, 0);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002516 }
2517 if (mFrameResource == 0) {
Alan Viverette40982d42014-07-25 17:48:55 -07002518 mFrameResource = a.getResourceId(R.styleable.Window_windowFrame, 0);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002519 }
Adam Powellf849a5e2014-09-11 15:09:36 -07002520 mBackgroundFallbackResource = a.getResourceId(
2521 R.styleable.Window_windowBackgroundFallback, 0);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002522 if (false) {
2523 System.out.println("Background: "
2524 + Integer.toHexString(mBackgroundResource) + " Frame: "
2525 + Integer.toHexString(mFrameResource));
2526 }
2527 }
Wale Ogunwale0d7e9122015-11-17 10:45:06 -08002528 if (mLoadElevation) {
Filip Gruszczynskia59ac9c2015-09-10 18:28:48 -07002529 mElevation = a.getDimension(R.styleable.Window_windowElevation, 0);
2530 }
Alan Viverette40982d42014-07-25 17:48:55 -07002531 mClipToOutline = a.getBoolean(R.styleable.Window_windowClipToOutline, false);
2532 mTextColor = a.getColor(R.styleable.Window_textColor, Color.TRANSPARENT);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002533 }
2534
2535 // Inflate the window decor.
2536
2537 int layoutResource;
2538 int features = getLocalFeatures();
2539 // System.out.println("Features: 0x" + Integer.toHexString(features));
Will Haldean Brownca6234e2014-02-12 10:23:41 -08002540 if ((features & (1 << FEATURE_SWIPE_TO_DISMISS)) != 0) {
Alan Viverette40982d42014-07-25 17:48:55 -07002541 layoutResource = R.layout.screen_swipe_dismiss;
Michael Kwanf7964be2016-11-30 16:44:33 -08002542 setCloseOnSwipeEnabled(true);
Will Haldean Brownca6234e2014-02-12 10:23:41 -08002543 } else if ((features & ((1 << FEATURE_LEFT_ICON) | (1 << FEATURE_RIGHT_ICON))) != 0) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002544 if (mIsFloating) {
Adam Powell32aa2c92011-01-11 15:37:04 -08002545 TypedValue res = new TypedValue();
2546 getContext().getTheme().resolveAttribute(
Alan Viverette40982d42014-07-25 17:48:55 -07002547 R.attr.dialogTitleIconsDecorLayout, res, true);
Adam Powell32aa2c92011-01-11 15:37:04 -08002548 layoutResource = res.resourceId;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002549 } else {
Alan Viverette40982d42014-07-25 17:48:55 -07002550 layoutResource = R.layout.screen_title_icons;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002551 }
Adam Powellf4a6ec42010-08-24 14:18:10 -07002552 // XXX Remove this once action bar supports these features.
2553 removeFeature(FEATURE_ACTION_BAR);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002554 // System.out.println("Title Icons!");
Adam Powell6af97e12010-11-11 21:11:53 -08002555 } else if ((features & ((1 << FEATURE_PROGRESS) | (1 << FEATURE_INDETERMINATE_PROGRESS))) != 0
2556 && (features & (1 << FEATURE_ACTION_BAR)) == 0) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002557 // Special case for a window with only a progress bar (and title).
2558 // XXX Need to have a no-title version of embedded windows.
Alan Viverette40982d42014-07-25 17:48:55 -07002559 layoutResource = R.layout.screen_progress;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002560 // System.out.println("Progress!");
2561 } else if ((features & (1 << FEATURE_CUSTOM_TITLE)) != 0) {
2562 // Special case for a window with a custom 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.dialogCustomTitleDecorLayout, res, true);
Adam Powell32aa2c92011-01-11 15:37:04 -08002568 layoutResource = res.resourceId;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002569 } else {
Alan Viverette40982d42014-07-25 17:48:55 -07002570 layoutResource = R.layout.screen_custom_title;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002571 }
Adam Powellf4a6ec42010-08-24 14:18:10 -07002572 // XXX Remove this once action bar supports these features.
2573 removeFeature(FEATURE_ACTION_BAR);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002574 } else if ((features & (1 << FEATURE_NO_TITLE)) == 0) {
2575 // If no other features and not embedded, only need a title.
2576 // If the window is floating, we need a dialog layout
2577 if (mIsFloating) {
Adam Powell32aa2c92011-01-11 15:37:04 -08002578 TypedValue res = new TypedValue();
2579 getContext().getTheme().resolveAttribute(
Alan Viverette40982d42014-07-25 17:48:55 -07002580 R.attr.dialogTitleDecorLayout, res, true);
Adam Powell32aa2c92011-01-11 15:37:04 -08002581 layoutResource = res.resourceId;
Adam Powell33b97432010-04-20 10:01:14 -07002582 } else if ((features & (1 << FEATURE_ACTION_BAR)) != 0) {
Adam Powelle021e6e2014-05-23 17:27:24 -07002583 layoutResource = a.getResourceId(
Alan Viverette40982d42014-07-25 17:48:55 -07002584 R.styleable.Window_windowActionBarFullscreenDecorLayout,
2585 R.layout.screen_action_bar);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002586 } else {
Alan Viverette40982d42014-07-25 17:48:55 -07002587 layoutResource = R.layout.screen_title;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002588 }
2589 // System.out.println("Title!");
Adam Powellf8419a02011-10-03 12:08:54 -07002590 } else if ((features & (1 << FEATURE_ACTION_MODE_OVERLAY)) != 0) {
Alan Viverette40982d42014-07-25 17:48:55 -07002591 layoutResource = R.layout.screen_simple_overlay_action_mode;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002592 } else {
2593 // Embedded, so no decoration is needed.
Alan Viverette40982d42014-07-25 17:48:55 -07002594 layoutResource = R.layout.screen_simple;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002595 // System.out.println("Simple!");
2596 }
2597
2598 mDecor.startChanging();
Filip Gruszczynski3dec0812015-12-09 08:42:41 -08002599 mDecor.onResourcesLoaded(mLayoutInflater, layoutResource);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002600
2601 ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
2602 if (contentParent == null) {
2603 throw new RuntimeException("Window couldn't find content container view");
2604 }
2605
2606 if ((features & (1 << FEATURE_INDETERMINATE_PROGRESS)) != 0) {
2607 ProgressBar progress = getCircularProgressBar(false);
2608 if (progress != null) {
2609 progress.setIndeterminate(true);
2610 }
2611 }
2612
Will Haldean Brownca6234e2014-02-12 10:23:41 -08002613 if ((features & (1 << FEATURE_SWIPE_TO_DISMISS)) != 0) {
Michael Kwanf7964be2016-11-30 16:44:33 -08002614 registerSwipeCallbacks(contentParent);
Will Haldean Brownca6234e2014-02-12 10:23:41 -08002615 }
2616
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002617 // Remaining setup -- of background and title -- that only applies
2618 // to top-level windows.
2619 if (getContainer() == null) {
Alan Viverette49a22e82014-07-12 20:01:27 -07002620 final Drawable background;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002621 if (mBackgroundResource != 0) {
Alan Viverette49a22e82014-07-12 20:01:27 -07002622 background = getContext().getDrawable(mBackgroundResource);
2623 } else {
2624 background = mBackgroundDrawable;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002625 }
Alan Viverette49a22e82014-07-12 20:01:27 -07002626 mDecor.setWindowBackground(background);
2627
2628 final Drawable frame;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002629 if (mFrameResource != 0) {
Alan Viverette49a22e82014-07-12 20:01:27 -07002630 frame = getContext().getDrawable(mFrameResource);
2631 } else {
2632 frame = null;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002633 }
Alan Viverette49a22e82014-07-12 20:01:27 -07002634 mDecor.setWindowFrame(frame);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002635
Alan Viverette49a22e82014-07-12 20:01:27 -07002636 mDecor.setElevation(mElevation);
Alan Viverette2c183332014-08-07 13:43:05 -07002637 mDecor.setClipToOutline(mClipToOutline);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002638
2639 if (mTitle != null) {
2640 setTitle(mTitle);
2641 }
Alan Viverette49a22e82014-07-12 20:01:27 -07002642
2643 if (mTitleColor == 0) {
2644 mTitleColor = mTextColor;
2645 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002646 setTitleColor(mTitleColor);
2647 }
2648
2649 mDecor.finishChanging();
2650
2651 return contentParent;
2652 }
2653
Dianne Hackborncfaf8872011-01-18 13:57:54 -08002654 /** @hide */
2655 public void alwaysReadCloseOnTouchAttr() {
2656 mAlwaysReadCloseOnTouchAttr = true;
2657 }
2658
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002659 private void installDecor() {
Filip Gruszczynskia59ac9c2015-09-10 18:28:48 -07002660 mForceDecorInstall = false;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002661 if (mDecor == null) {
Stefan Kuhne61b47bb2015-07-28 14:04:25 -07002662 mDecor = generateDecor(-1);
Adam Powell00f4d982010-03-24 11:17:03 -07002663 mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002664 mDecor.setIsRootNamespace(true);
Adam Powell4b6d93f2012-09-18 18:34:08 -07002665 if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) {
2666 mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
2667 }
Filip Gruszczynski0daf2102015-09-29 08:39:07 -07002668 } else {
2669 mDecor.setWindow(this);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002670 }
2671 if (mContentParent == null) {
2672 mContentParent = generateLayout(mDecor);
2673
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002674 // Set up decor part of UI to ignore fitsSystemWindows if appropriate.
2675 mDecor.makeOptionalFitsSystemWindows();
2676
Adam Powell4369e7d2014-05-17 14:16:08 -07002677 final DecorContentParent decorContentParent = (DecorContentParent) mDecor.findViewById(
Alan Viverette40982d42014-07-25 17:48:55 -07002678 R.id.decor_content_parent);
Adam Powell4369e7d2014-05-17 14:16:08 -07002679
2680 if (decorContentParent != null) {
2681 mDecorContentParent = decorContentParent;
2682 mDecorContentParent.setWindowCallback(getCallback());
2683 if (mDecorContentParent.getTitle() == null) {
2684 mDecorContentParent.setWindowTitle(mTitle);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002685 }
Adam Powell9b4bee02011-04-27 19:24:47 -07002686
Adam Powell4369e7d2014-05-17 14:16:08 -07002687 final int localFeatures = getLocalFeatures();
2688 for (int i = 0; i < FEATURE_MAX; i++) {
2689 if ((localFeatures & (1 << i)) != 0) {
2690 mDecorContentParent.initFeature(i);
Adam Powell9b0dc282013-07-31 13:58:43 -07002691 }
Adam Powell4369e7d2014-05-17 14:16:08 -07002692 }
Adam Powell9b0dc282013-07-31 13:58:43 -07002693
Adam Powell4369e7d2014-05-17 14:16:08 -07002694 mDecorContentParent.setUiOptions(mUiOptions);
Adam Powell640a66e2011-04-29 10:18:53 -07002695
Adam Powell4369e7d2014-05-17 14:16:08 -07002696 if ((mResourcesSetFlags & FLAG_RESOURCE_SET_ICON) != 0 ||
2697 (mIconRes != 0 && !mDecorContentParent.hasIcon())) {
2698 mDecorContentParent.setIcon(mIconRes);
2699 } else if ((mResourcesSetFlags & FLAG_RESOURCE_SET_ICON) == 0 &&
2700 mIconRes == 0 && !mDecorContentParent.hasIcon()) {
2701 mDecorContentParent.setIcon(
2702 getContext().getPackageManager().getDefaultActivityIcon());
2703 mResourcesSetFlags |= FLAG_RESOURCE_SET_ICON_FALLBACK;
2704 }
2705 if ((mResourcesSetFlags & FLAG_RESOURCE_SET_LOGO) != 0 ||
2706 (mLogoRes != 0 && !mDecorContentParent.hasLogo())) {
2707 mDecorContentParent.setLogo(mLogoRes);
2708 }
Adam Powell9b4bee02011-04-27 19:24:47 -07002709
Adam Powell31c91c82014-08-22 17:20:00 -07002710 // Invalidate if the panel menu hasn't been created before this.
2711 // Panel menu invalidation is deferred avoiding application onCreateOptionsMenu
Adam Powell4369e7d2014-05-17 14:16:08 -07002712 // being called in the middle of onCreate or similar.
Adam Powell31c91c82014-08-22 17:20:00 -07002713 // A pending invalidation will typically be resolved before the posted message
2714 // would run normally in order to satisfy instance state restoration.
2715 PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, false);
Jorim Jaggia16cc152015-06-01 16:55:05 -07002716 if (!isDestroyed() && (st == null || st.menu == null) && !mIsStartingWindow) {
Adam Powell31c91c82014-08-22 17:20:00 -07002717 invalidatePanelMenu(FEATURE_ACTION_BAR);
2718 }
Adam Powell4369e7d2014-05-17 14:16:08 -07002719 } else {
Alan Viverette51efddb2017-04-05 10:00:01 -04002720 mTitleView = findViewById(R.id.title);
Adam Powell4369e7d2014-05-17 14:16:08 -07002721 if (mTitleView != null) {
Adam Powell4369e7d2014-05-17 14:16:08 -07002722 if ((getLocalFeatures() & (1 << FEATURE_NO_TITLE)) != 0) {
Alan Viverette891c9ee2016-01-08 13:43:15 -05002723 final View titleContainer = findViewById(R.id.title_container);
Adam Powell4369e7d2014-05-17 14:16:08 -07002724 if (titleContainer != null) {
2725 titleContainer.setVisibility(View.GONE);
2726 } else {
2727 mTitleView.setVisibility(View.GONE);
2728 }
Alan Viverette891c9ee2016-01-08 13:43:15 -05002729 mContentParent.setForeground(null);
Adam Powell4369e7d2014-05-17 14:16:08 -07002730 } else {
2731 mTitleView.setText(mTitle);
2732 }
Adam Powell33b97432010-04-20 10:01:14 -07002733 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002734 }
Adam Powell18e905f2013-10-24 14:27:48 -07002735
Adam Powellf849a5e2014-09-11 15:09:36 -07002736 if (mDecor.getBackground() == null && mBackgroundFallbackResource != 0) {
2737 mDecor.setBackgroundFallback(mBackgroundFallbackResource);
2738 }
2739
Adam Powell18e905f2013-10-24 14:27:48 -07002740 // Only inflate or create a new TransitionManager if the caller hasn't
2741 // already set a custom one.
George Mount9826f632014-09-11 08:50:09 -07002742 if (hasFeature(FEATURE_ACTIVITY_TRANSITIONS)) {
George Mount31a21722014-03-24 17:44:36 -07002743 if (mTransitionManager == null) {
2744 final int transitionRes = getWindowStyle().getResourceId(
Alan Viverette40982d42014-07-25 17:48:55 -07002745 R.styleable.Window_windowContentTransitionManager,
George Mount31a21722014-03-24 17:44:36 -07002746 0);
2747 if (transitionRes != 0) {
2748 final TransitionInflater inflater = TransitionInflater.from(getContext());
2749 mTransitionManager = inflater.inflateTransitionManager(transitionRes,
2750 mContentParent);
2751 } else {
2752 mTransitionManager = new TransitionManager();
2753 }
2754 }
2755
George Mount68f96d82014-07-31 13:13:10 -07002756 mEnterTransition = getTransition(mEnterTransition, null,
Alan Viverette40982d42014-07-25 17:48:55 -07002757 R.styleable.Window_windowEnterTransition);
George Mount68f96d82014-07-31 13:13:10 -07002758 mReturnTransition = getTransition(mReturnTransition, USE_DEFAULT_TRANSITION,
2759 R.styleable.Window_windowReturnTransition);
2760 mExitTransition = getTransition(mExitTransition, null,
Alan Viverette40982d42014-07-25 17:48:55 -07002761 R.styleable.Window_windowExitTransition);
George Mount68f96d82014-07-31 13:13:10 -07002762 mReenterTransition = getTransition(mReenterTransition, USE_DEFAULT_TRANSITION,
2763 R.styleable.Window_windowReenterTransition);
2764 mSharedElementEnterTransition = getTransition(mSharedElementEnterTransition, null,
Alan Viverette40982d42014-07-25 17:48:55 -07002765 R.styleable.Window_windowSharedElementEnterTransition);
George Mount68f96d82014-07-31 13:13:10 -07002766 mSharedElementReturnTransition = getTransition(mSharedElementReturnTransition,
2767 USE_DEFAULT_TRANSITION,
2768 R.styleable.Window_windowSharedElementReturnTransition);
2769 mSharedElementExitTransition = getTransition(mSharedElementExitTransition, null,
Alan Viverette40982d42014-07-25 17:48:55 -07002770 R.styleable.Window_windowSharedElementExitTransition);
George Mount68f96d82014-07-31 13:13:10 -07002771 mSharedElementReenterTransition = getTransition(mSharedElementReenterTransition,
2772 USE_DEFAULT_TRANSITION,
2773 R.styleable.Window_windowSharedElementReenterTransition);
George Mount31a21722014-03-24 17:44:36 -07002774 if (mAllowEnterTransitionOverlap == null) {
2775 mAllowEnterTransitionOverlap = getWindowStyle().getBoolean(
George Mount68f96d82014-07-31 13:13:10 -07002776 R.styleable.Window_windowAllowEnterTransitionOverlap, true);
George Mount31a21722014-03-24 17:44:36 -07002777 }
George Mountc03da0e2014-08-22 17:04:02 -07002778 if (mAllowReturnTransitionOverlap == null) {
2779 mAllowReturnTransitionOverlap = getWindowStyle().getBoolean(
2780 R.styleable.Window_windowAllowReturnTransitionOverlap, true);
Adam Powell18e905f2013-10-24 14:27:48 -07002781 }
George Mounted1e01d2014-06-05 13:49:12 -07002782 if (mBackgroundFadeDurationMillis < 0) {
2783 mBackgroundFadeDurationMillis = getWindowStyle().getInteger(
George Mount68f96d82014-07-31 13:13:10 -07002784 R.styleable.Window_windowTransitionBackgroundFadeDuration,
George Mounted1e01d2014-06-05 13:49:12 -07002785 DEFAULT_BACKGROUND_FADE_DURATION_MS);
2786 }
George Mountb89d5cc2014-08-18 16:50:50 -07002787 if (mSharedElementsUseOverlay == null) {
2788 mSharedElementsUseOverlay = getWindowStyle().getBoolean(
2789 R.styleable.Window_windowSharedElementsUseOverlay, true);
2790 }
Adam Powell18e905f2013-10-24 14:27:48 -07002791 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002792 }
2793 }
2794
George Mount68f96d82014-07-31 13:13:10 -07002795 private Transition getTransition(Transition currentValue, Transition defaultValue, int id) {
2796 if (currentValue != defaultValue) {
George Mount31a21722014-03-24 17:44:36 -07002797 return currentValue;
2798 }
2799 int transitionId = getWindowStyle().getResourceId(id, -1);
George Mount68f96d82014-07-31 13:13:10 -07002800 Transition transition = defaultValue;
Alan Viverette40982d42014-07-25 17:48:55 -07002801 if (transitionId != -1 && transitionId != R.transition.no_transition) {
George Mount31a21722014-03-24 17:44:36 -07002802 TransitionInflater inflater = TransitionInflater.from(getContext());
2803 transition = inflater.inflateTransition(transitionId);
George Mount7f151642014-08-18 16:24:21 -07002804 if (transition instanceof TransitionSet &&
2805 ((TransitionSet)transition).getTransitionCount() == 0) {
2806 transition = null;
2807 }
George Mount31a21722014-03-24 17:44:36 -07002808 }
2809 return transition;
2810 }
2811
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002812 private Drawable loadImageURI(Uri uri) {
2813 try {
Alan Viverettead3c4a12014-06-02 17:12:58 -07002814 return Drawable.createFromStream(
2815 getContext().getContentResolver().openInputStream(uri), null);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002816 } catch (Exception e) {
2817 Log.w(TAG, "Unable to open content: " + uri);
2818 }
2819 return null;
2820 }
2821
2822 private DrawableFeatureState getDrawableState(int featureId, boolean required) {
2823 if ((getFeatures() & (1 << featureId)) == 0) {
2824 if (!required) {
2825 return null;
2826 }
2827 throw new RuntimeException("The feature has not been requested");
2828 }
2829
2830 DrawableFeatureState[] ar;
2831 if ((ar = mDrawables) == null || ar.length <= featureId) {
2832 DrawableFeatureState[] nar = new DrawableFeatureState[featureId + 1];
2833 if (ar != null) {
2834 System.arraycopy(ar, 0, nar, 0, ar.length);
2835 }
2836 mDrawables = ar = nar;
2837 }
2838
2839 DrawableFeatureState st = ar[featureId];
2840 if (st == null) {
2841 ar[featureId] = st = new DrawableFeatureState(featureId);
2842 }
2843 return st;
2844 }
2845
2846 /**
2847 * Gets a panel's state based on its feature ID.
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -08002848 *
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002849 * @param featureId The feature ID of the panel.
2850 * @param required Whether the panel is required (if it is required and it
2851 * isn't in our features, this throws an exception).
2852 * @return The panel state.
2853 */
Wale Ogunwale8804af22015-11-17 09:18:15 -08002854 PanelFeatureState getPanelState(int featureId, boolean required) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002855 return getPanelState(featureId, required, null);
2856 }
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -08002857
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002858 /**
2859 * Gets a panel's state based on its feature ID.
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -08002860 *
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002861 * @param featureId The feature ID of the panel.
2862 * @param required Whether the panel is required (if it is required and it
2863 * isn't in our features, this throws an exception).
2864 * @param convertPanelState Optional: If the panel state does not exist, use
2865 * this as the panel state.
2866 * @return The panel state.
2867 */
2868 private PanelFeatureState getPanelState(int featureId, boolean required,
2869 PanelFeatureState convertPanelState) {
2870 if ((getFeatures() & (1 << featureId)) == 0) {
2871 if (!required) {
2872 return null;
2873 }
2874 throw new RuntimeException("The feature has not been requested");
2875 }
2876
2877 PanelFeatureState[] ar;
2878 if ((ar = mPanels) == null || ar.length <= featureId) {
2879 PanelFeatureState[] nar = new PanelFeatureState[featureId + 1];
2880 if (ar != null) {
2881 System.arraycopy(ar, 0, nar, 0, ar.length);
2882 }
2883 mPanels = ar = nar;
2884 }
2885
2886 PanelFeatureState st = ar[featureId];
2887 if (st == null) {
2888 ar[featureId] = st = (convertPanelState != null)
2889 ? convertPanelState
2890 : new PanelFeatureState(featureId);
2891 }
2892 return st;
2893 }
2894
2895 @Override
2896 public final void setChildDrawable(int featureId, Drawable drawable) {
2897 DrawableFeatureState st = getDrawableState(featureId, true);
2898 st.child = drawable;
2899 updateDrawable(featureId, st, false);
2900 }
2901
2902 @Override
2903 public final void setChildInt(int featureId, int value) {
2904 updateInt(featureId, value, false);
2905 }
2906
2907 @Override
2908 public boolean isShortcutKey(int keyCode, KeyEvent event) {
Jose Lima7a22fc62015-01-23 17:24:22 -08002909 PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, false);
2910 return st != null && st.menu != null && st.menu.isShortcutKey(keyCode, event);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002911 }
2912
2913 private void updateDrawable(int featureId, DrawableFeatureState st, boolean fromResume) {
2914 // Do nothing if the decor is not yet installed... an update will
2915 // need to be forced when we eventually become active.
2916 if (mContentParent == null) {
2917 return;
2918 }
2919
2920 final int featureMask = 1 << featureId;
2921
2922 if ((getFeatures() & featureMask) == 0 && !fromResume) {
2923 return;
2924 }
2925
2926 Drawable drawable = null;
2927 if (st != null) {
2928 drawable = st.child;
2929 if (drawable == null)
2930 drawable = st.local;
2931 if (drawable == null)
2932 drawable = st.def;
2933 }
2934 if ((getLocalFeatures() & featureMask) == 0) {
2935 if (getContainer() != null) {
2936 if (isActive() || fromResume) {
2937 getContainer().setChildDrawable(featureId, drawable);
2938 }
2939 }
2940 } else if (st != null && (st.cur != drawable || st.curAlpha != st.alpha)) {
2941 // System.out.println("Drawable changed: old=" + st.cur
2942 // + ", new=" + drawable);
2943 st.cur = drawable;
2944 st.curAlpha = st.alpha;
2945 onDrawableChanged(featureId, drawable, st.alpha);
2946 }
2947 }
2948
2949 private void updateInt(int featureId, int value, boolean fromResume) {
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -08002950
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002951 // Do nothing if the decor is not yet installed... an update will
2952 // need to be forced when we eventually become active.
2953 if (mContentParent == null) {
2954 return;
2955 }
2956
2957 final int featureMask = 1 << featureId;
2958
2959 if ((getFeatures() & featureMask) == 0 && !fromResume) {
2960 return;
2961 }
2962
2963 if ((getLocalFeatures() & featureMask) == 0) {
2964 if (getContainer() != null) {
2965 getContainer().setChildInt(featureId, value);
2966 }
2967 } else {
2968 onIntChanged(featureId, value);
2969 }
2970 }
2971
2972 private ImageView getLeftIconView() {
2973 if (mLeftIconView != null) {
2974 return mLeftIconView;
2975 }
2976 if (mContentParent == null) {
2977 installDecor();
2978 }
Alan Viverette40982d42014-07-25 17:48:55 -07002979 return (mLeftIconView = (ImageView)findViewById(R.id.left_icon));
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002980 }
2981
Adrian Roosea562512014-05-05 13:33:03 +02002982 @Override
2983 protected void dispatchWindowAttributesChanged(WindowManager.LayoutParams attrs) {
2984 super.dispatchWindowAttributesChanged(attrs);
2985 if (mDecor != null) {
Adrian Roos05054bd2014-10-27 17:04:10 +01002986 mDecor.updateColorViews(null /* insets */, true /* animate */);
Adrian Roosea562512014-05-05 13:33:03 +02002987 }
2988 }
2989
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002990 private ProgressBar getCircularProgressBar(boolean shouldInstallDecor) {
2991 if (mCircularProgressBar != null) {
2992 return mCircularProgressBar;
2993 }
2994 if (mContentParent == null && shouldInstallDecor) {
2995 installDecor();
2996 }
Alan Viverette51efddb2017-04-05 10:00:01 -04002997 mCircularProgressBar = findViewById(R.id.progress_circular);
Adam Powell6af97e12010-11-11 21:11:53 -08002998 if (mCircularProgressBar != null) {
2999 mCircularProgressBar.setVisibility(View.INVISIBLE);
3000 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003001 return mCircularProgressBar;
3002 }
3003
3004 private ProgressBar getHorizontalProgressBar(boolean shouldInstallDecor) {
3005 if (mHorizontalProgressBar != null) {
3006 return mHorizontalProgressBar;
3007 }
3008 if (mContentParent == null && shouldInstallDecor) {
3009 installDecor();
3010 }
Alan Viverette51efddb2017-04-05 10:00:01 -04003011 mHorizontalProgressBar = findViewById(R.id.progress_horizontal);
Adam Powell6af97e12010-11-11 21:11:53 -08003012 if (mHorizontalProgressBar != null) {
3013 mHorizontalProgressBar.setVisibility(View.INVISIBLE);
3014 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003015 return mHorizontalProgressBar;
3016 }
3017
3018 private ImageView getRightIconView() {
3019 if (mRightIconView != null) {
3020 return mRightIconView;
3021 }
3022 if (mContentParent == null) {
3023 installDecor();
3024 }
Alan Viverette40982d42014-07-25 17:48:55 -07003025 return (mRightIconView = (ImageView)findViewById(R.id.right_icon));
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003026 }
3027
Michael Kwanf7964be2016-11-30 16:44:33 -08003028 private void registerSwipeCallbacks(ViewGroup contentParent) {
3029 if (!(contentParent instanceof SwipeDismissLayout)) {
3030 Log.w(TAG, "contentParent is not a SwipeDismissLayout: " + contentParent);
3031 return;
3032 }
3033 SwipeDismissLayout swipeDismiss = (SwipeDismissLayout) contentParent;
Will Haldean Brownca6234e2014-02-12 10:23:41 -08003034 swipeDismiss.setOnDismissedListener(new SwipeDismissLayout.OnDismissedListener() {
3035 @Override
3036 public void onDismissed(SwipeDismissLayout layout) {
Michael Kwan67639a52016-12-16 12:38:10 -08003037 dispatchOnWindowSwipeDismissed();
Ned Burns7d6cb912016-12-02 17:25:33 -05003038 dispatchOnWindowDismissed(false /*finishTask*/, true /*suppressWindowTransition*/);
Will Haldean Brownca6234e2014-02-12 10:23:41 -08003039 }
3040 });
3041 swipeDismiss.setOnSwipeProgressChangedListener(
3042 new SwipeDismissLayout.OnSwipeProgressChangedListener() {
Will Haldean Brownca6234e2014-02-12 10:23:41 -08003043 @Override
3044 public void onSwipeProgressChanged(
Ned Burns7d6cb912016-12-02 17:25:33 -05003045 SwipeDismissLayout layout, float alpha, float translate) {
Will Haldean Brownca6234e2014-02-12 10:23:41 -08003046 WindowManager.LayoutParams newParams = getAttributes();
3047 newParams.x = (int) translate;
Ned Burns7d6cb912016-12-02 17:25:33 -05003048 newParams.alpha = alpha;
Will Haldean Brownca6234e2014-02-12 10:23:41 -08003049 setAttributes(newParams);
3050
3051 int flags = 0;
3052 if (newParams.x == 0) {
3053 flags = FLAG_FULLSCREEN;
3054 } else {
3055 flags = FLAG_LAYOUT_NO_LIMITS;
3056 }
3057 setFlags(flags, FLAG_FULLSCREEN | FLAG_LAYOUT_NO_LIMITS);
3058 }
3059
3060 @Override
3061 public void onSwipeCancelled(SwipeDismissLayout layout) {
3062 WindowManager.LayoutParams newParams = getAttributes();
Michael Kwan134ad6e2017-02-10 18:38:34 -08003063 // Swipe changes only affect the x-translation and alpha, check to see if
3064 // those values have changed first before resetting them.
3065 if (newParams.x != 0 || newParams.alpha != 1) {
3066 newParams.x = 0;
3067 newParams.alpha = 1;
3068 setAttributes(newParams);
3069 setFlags(FLAG_FULLSCREEN, FLAG_FULLSCREEN | FLAG_LAYOUT_NO_LIMITS);
3070 }
Will Haldean Brownca6234e2014-02-12 10:23:41 -08003071 }
3072 });
3073 }
3074
Michael Kwanf7964be2016-11-30 16:44:33 -08003075 /** @hide */
3076 @Override
3077 public void setCloseOnSwipeEnabled(boolean closeOnSwipeEnabled) {
3078 if (hasFeature(Window.FEATURE_SWIPE_TO_DISMISS) // swipe-to-dismiss feature is requested
3079 && mContentParent instanceof SwipeDismissLayout) { // check casting mContentParent
3080 ((SwipeDismissLayout) mContentParent).setDismissable(closeOnSwipeEnabled);
3081 }
3082 super.setCloseOnSwipeEnabled(closeOnSwipeEnabled);
3083 }
3084
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003085 /**
3086 * Helper method for calling the {@link Callback#onPanelClosed(int, Menu)}
3087 * callback. This method will grab whatever extra state is needed for the
3088 * callback that isn't given in the parameters. If the panel is not open,
3089 * this will not perform the callback.
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -08003090 *
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003091 * @param featureId Feature ID of the panel that was closed. Must be given.
3092 * @param panel Panel that was closed. Optional but useful if there is no
3093 * menu given.
3094 * @param menu The menu that was closed. Optional, but give if you have.
3095 */
3096 private void callOnPanelClosed(int featureId, PanelFeatureState panel, Menu menu) {
3097 final Callback cb = getCallback();
3098 if (cb == null)
3099 return;
3100
3101 // Try to get a menu
3102 if (menu == null) {
3103 // Need a panel to grab the menu, so try to get that
3104 if (panel == null) {
3105 if ((featureId >= 0) && (featureId < mPanels.length)) {
3106 panel = mPanels[featureId];
3107 }
3108 }
3109
3110 if (panel != null) {
3111 // menu still may be null, which is okay--we tried our best
3112 menu = panel.menu;
3113 }
3114 }
3115
3116 // If the panel is not open, do not callback
3117 if ((panel != null) && (!panel.isOpen))
3118 return;
3119
Dianne Hackbornb66ad572011-03-01 17:10:30 -08003120 if (!isDestroyed()) {
3121 cb.onPanelClosed(featureId, menu);
3122 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003123 }
3124
3125 /**
Sujith Ramakrishnan0390fff2017-06-08 18:18:12 -07003126 * Check if Setup or Post-Setup update is completed on TV
3127 * @return true if completed
3128 */
3129 private boolean isTvUserSetupComplete() {
3130 boolean isTvSetupComplete = Settings.Secure.getInt(getContext().getContentResolver(),
3131 Settings.Secure.USER_SETUP_COMPLETE, 0) != 0;
3132 isTvSetupComplete &= Settings.Secure.getInt(getContext().getContentResolver(),
3133 Settings.Secure.TV_USER_SETUP_COMPLETE, 0) != 0;
3134 return isTvSetupComplete;
3135 }
3136
3137 /**
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003138 * Helper method for adding launch-search to most applications. Opens the
3139 * search window using default settings.
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -08003140 *
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003141 * @return true if search window opened
3142 */
Tim Kilbourn6a975b32015-04-09 17:14:34 -07003143 private boolean launchDefaultSearch(KeyEvent event) {
Sujith Ramakrishnan0390fff2017-06-08 18:18:12 -07003144 if (getContext().getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK)
3145 && !isTvUserSetupComplete()) {
3146 // If we are in Setup or Post-Setup update mode on TV, consume the search key
3147 return false;
3148 }
Dianne Hackbornfdf5b352014-10-08 17:43:48 -07003149 boolean result;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003150 final Callback cb = getCallback();
Dianne Hackbornb66ad572011-03-01 17:10:30 -08003151 if (cb == null || isDestroyed()) {
Dianne Hackbornfdf5b352014-10-08 17:43:48 -07003152 result = false;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003153 } else {
Karl Rosaen323216b2009-07-20 14:00:29 -07003154 sendCloseSystemWindows("search");
Tim Kilbourn6a975b32015-04-09 17:14:34 -07003155 int deviceId = event.getDeviceId();
3156 SearchEvent searchEvent = null;
3157 if (deviceId != 0) {
3158 searchEvent = new SearchEvent(InputDevice.getDevice(deviceId));
3159 }
Adam Powell97900342015-04-15 13:12:52 -07003160 try {
3161 result = cb.onSearchRequested(searchEvent);
3162 } catch (AbstractMethodError e) {
3163 Log.e(TAG, "WindowCallback " + cb.getClass().getName() + " does not implement"
3164 + " method onSearchRequested(SearchEvent); fa", e);
3165 result = cb.onSearchRequested();
3166 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003167 }
Dianne Hackbornfdf5b352014-10-08 17:43:48 -07003168 if (!result && (getContext().getResources().getConfiguration().uiMode
3169 & Configuration.UI_MODE_TYPE_MASK) == Configuration.UI_MODE_TYPE_TELEVISION) {
3170 // On TVs, if the app doesn't implement search, we want to launch assist.
Tim Kilbourn0e5f1102015-06-05 16:18:09 -07003171 Bundle args = new Bundle();
3172 args.putInt(Intent.EXTRA_ASSIST_INPUT_DEVICE_ID, event.getDeviceId());
Dianne Hackbornfdf5b352014-10-08 17:43:48 -07003173 return ((SearchManager)getContext().getSystemService(Context.SEARCH_SERVICE))
Jeff Sharkeyad357d12018-02-02 13:25:31 -07003174 .launchLegacyAssist(null, getContext().getUserId(), args);
Dianne Hackbornfdf5b352014-10-08 17:43:48 -07003175 }
3176 return result;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003177 }
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -08003178
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003179 @Override
3180 public void setVolumeControlStream(int streamType) {
3181 mVolumeControlStreamType = streamType;
3182 }
3183
3184 @Override
3185 public int getVolumeControlStream() {
3186 return mVolumeControlStreamType;
3187 }
3188
RoboErik55011652014-07-09 15:05:53 -07003189 @Override
3190 public void setMediaController(MediaController controller) {
3191 mMediaController = controller;
3192 }
3193
3194 @Override
3195 public MediaController getMediaController() {
3196 return mMediaController;
3197 }
3198
George Mount31a21722014-03-24 17:44:36 -07003199 @Override
3200 public void setEnterTransition(Transition enterTransition) {
3201 mEnterTransition = enterTransition;
3202 }
3203
3204 @Override
George Mount68f96d82014-07-31 13:13:10 -07003205 public void setReturnTransition(Transition transition) {
3206 mReturnTransition = transition;
3207 }
3208
3209 @Override
George Mount31a21722014-03-24 17:44:36 -07003210 public void setExitTransition(Transition exitTransition) {
3211 mExitTransition = exitTransition;
3212 }
3213
3214 @Override
George Mount68f96d82014-07-31 13:13:10 -07003215 public void setReenterTransition(Transition transition) {
3216 mReenterTransition = transition;
3217 }
3218
3219 @Override
George Mount31a21722014-03-24 17:44:36 -07003220 public void setSharedElementEnterTransition(Transition sharedElementEnterTransition) {
3221 mSharedElementEnterTransition = sharedElementEnterTransition;
3222 }
3223
3224 @Override
George Mount68f96d82014-07-31 13:13:10 -07003225 public void setSharedElementReturnTransition(Transition transition) {
3226 mSharedElementReturnTransition = transition;
3227 }
3228
3229 @Override
George Mount31a21722014-03-24 17:44:36 -07003230 public void setSharedElementExitTransition(Transition sharedElementExitTransition) {
3231 mSharedElementExitTransition = sharedElementExitTransition;
3232 }
3233
3234 @Override
George Mount68f96d82014-07-31 13:13:10 -07003235 public void setSharedElementReenterTransition(Transition transition) {
3236 mSharedElementReenterTransition = transition;
3237 }
3238
3239 @Override
George Mount31a21722014-03-24 17:44:36 -07003240 public Transition getEnterTransition() {
3241 return mEnterTransition;
3242 }
3243
3244 @Override
George Mount68f96d82014-07-31 13:13:10 -07003245 public Transition getReturnTransition() {
3246 return mReturnTransition == USE_DEFAULT_TRANSITION ? getEnterTransition()
3247 : mReturnTransition;
3248 }
3249
3250 @Override
George Mount31a21722014-03-24 17:44:36 -07003251 public Transition getExitTransition() {
3252 return mExitTransition;
3253 }
3254
3255 @Override
George Mount68f96d82014-07-31 13:13:10 -07003256 public Transition getReenterTransition() {
3257 return mReenterTransition == USE_DEFAULT_TRANSITION ? getExitTransition()
3258 : mReenterTransition;
3259 }
3260
3261 @Override
George Mount31a21722014-03-24 17:44:36 -07003262 public Transition getSharedElementEnterTransition() {
3263 return mSharedElementEnterTransition;
3264 }
3265
3266 @Override
George Mount68f96d82014-07-31 13:13:10 -07003267 public Transition getSharedElementReturnTransition() {
3268 return mSharedElementReturnTransition == USE_DEFAULT_TRANSITION
3269 ? getSharedElementEnterTransition() : mSharedElementReturnTransition;
3270 }
3271
3272 @Override
George Mount31a21722014-03-24 17:44:36 -07003273 public Transition getSharedElementExitTransition() {
3274 return mSharedElementExitTransition;
3275 }
3276
3277 @Override
George Mount68f96d82014-07-31 13:13:10 -07003278 public Transition getSharedElementReenterTransition() {
3279 return mSharedElementReenterTransition == USE_DEFAULT_TRANSITION
3280 ? getSharedElementExitTransition() : mSharedElementReenterTransition;
3281 }
3282
3283 @Override
George Mount31a21722014-03-24 17:44:36 -07003284 public void setAllowEnterTransitionOverlap(boolean allow) {
3285 mAllowEnterTransitionOverlap = allow;
3286 }
3287
3288 @Override
3289 public boolean getAllowEnterTransitionOverlap() {
3290 return (mAllowEnterTransitionOverlap == null) ? true : mAllowEnterTransitionOverlap;
3291 }
3292
3293 @Override
George Mountc03da0e2014-08-22 17:04:02 -07003294 public void setAllowReturnTransitionOverlap(boolean allowExitTransitionOverlap) {
3295 mAllowReturnTransitionOverlap = allowExitTransitionOverlap;
George Mount31a21722014-03-24 17:44:36 -07003296 }
3297
3298 @Override
George Mountc03da0e2014-08-22 17:04:02 -07003299 public boolean getAllowReturnTransitionOverlap() {
3300 return (mAllowReturnTransitionOverlap == null) ? true : mAllowReturnTransitionOverlap;
George Mount31a21722014-03-24 17:44:36 -07003301 }
3302
George Mounted1e01d2014-06-05 13:49:12 -07003303 @Override
3304 public long getTransitionBackgroundFadeDuration() {
3305 return (mBackgroundFadeDurationMillis < 0) ? DEFAULT_BACKGROUND_FADE_DURATION_MS
3306 : mBackgroundFadeDurationMillis;
3307 }
3308
3309 @Override
3310 public void setTransitionBackgroundFadeDuration(long fadeDurationMillis) {
3311 if (fadeDurationMillis < 0) {
3312 throw new IllegalArgumentException("negative durations are not allowed");
3313 }
3314 mBackgroundFadeDurationMillis = fadeDurationMillis;
3315 }
3316
George Mountb89d5cc2014-08-18 16:50:50 -07003317 @Override
3318 public void setSharedElementsUseOverlay(boolean sharedElementsUseOverlay) {
3319 mSharedElementsUseOverlay = sharedElementsUseOverlay;
3320 }
3321
3322 @Override
3323 public boolean getSharedElementsUseOverlay() {
3324 return (mSharedElementsUseOverlay == null) ? true : mSharedElementsUseOverlay;
3325 }
3326
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003327 private static final class DrawableFeatureState {
3328 DrawableFeatureState(int _featureId) {
3329 featureId = _featureId;
3330 }
3331
3332 final int featureId;
3333
3334 int resid;
3335
3336 Uri uri;
3337
3338 Drawable local;
3339
3340 Drawable child;
3341
3342 Drawable def;
3343
3344 Drawable cur;
3345
3346 int alpha = 255;
3347
3348 int curAlpha = 255;
3349 }
3350
Wale Ogunwale8804af22015-11-17 09:18:15 -08003351 static final class PanelFeatureState {
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -08003352
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003353 /** Feature ID for this panel. */
3354 int featureId;
3355
3356 // Information pulled from the style for this panel.
3357
3358 int background;
3359
3360 /** The background when the panel spans the entire available width. */
3361 int fullBackground;
3362
3363 int gravity;
3364
3365 int x;
3366
3367 int y;
3368
3369 int windowAnimations;
3370
3371 /** Dynamic state of the panel. */
3372 DecorView decorView;
3373
3374 /** The panel that was returned by onCreatePanelView(). */
3375 View createdPanelView;
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -08003376
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003377 /** The panel that we are actually showing. */
3378 View shownPanelView;
3379
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -08003380 /** Use {@link #setMenu} to set this. */
Adam Powell696cba52011-03-29 10:38:16 -07003381 MenuBuilder menu;
3382
3383 IconMenuPresenter iconMenuPresenter;
Adam Powelldfee59a2011-08-05 20:48:30 -07003384 ListMenuPresenter listMenuPresenter;
3385
3386 /** true if this menu will show in single-list compact mode */
3387 boolean isCompact;
3388
3389 /** Theme resource ID for list elements of the panel menu */
3390 int listPresenterTheme;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003391
3392 /**
3393 * Whether the panel has been prepared (see
3394 * {@link PhoneWindow#preparePanel}).
3395 */
3396 boolean isPrepared;
3397
3398 /**
3399 * Whether an item's action has been performed. This happens in obvious
3400 * scenarios (user clicks on menu item), but can also happen with
3401 * chording menu+(shortcut key).
3402 */
3403 boolean isHandled;
3404
3405 boolean isOpen;
3406
3407 /**
3408 * True if the menu is in expanded mode, false if the menu is in icon
3409 * mode
3410 */
3411 boolean isInExpandedMode;
3412
3413 public boolean qwertyMode;
3414
3415 boolean refreshDecorView;
3416
Dianne Hackbornb31e84bc2010-06-08 18:04:35 -07003417 boolean refreshMenuContent;
Alan Viveretteeb1d3792014-06-03 18:36:03 -07003418
Dianne Hackbornd0071442009-09-25 01:35:29 -07003419 boolean wasLastOpen;
Alan Viveretteeb1d3792014-06-03 18:36:03 -07003420
Dianne Hackbornd0071442009-09-25 01:35:29 -07003421 boolean wasLastExpanded;
Alan Viveretteeb1d3792014-06-03 18:36:03 -07003422
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003423 /**
3424 * Contains the state of the menu when told to freeze.
3425 */
3426 Bundle frozenMenuState;
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -08003427
Adam Powell038f1c82011-07-21 14:28:10 -07003428 /**
3429 * Contains the state of associated action views when told to freeze.
3430 * These are saved across invalidations.
3431 */
3432 Bundle frozenActionViewState;
3433
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003434 PanelFeatureState(int featureId) {
3435 this.featureId = featureId;
3436
3437 refreshDecorView = false;
3438 }
3439
Adam Powelldfee59a2011-08-05 20:48:30 -07003440 public boolean isInListMode() {
3441 return isInExpandedMode || isCompact;
3442 }
3443
Adam Powell526b9312011-04-22 15:42:05 -07003444 public boolean hasPanelItems() {
3445 if (shownPanelView == null) return false;
Adam Powell4fd8d5332011-08-17 14:54:41 -07003446 if (createdPanelView != null) return true;
Adam Powell526b9312011-04-22 15:42:05 -07003447
Adam Powelldfee59a2011-08-05 20:48:30 -07003448 if (isCompact || isInExpandedMode) {
3449 return listMenuPresenter.getAdapter().getCount() > 0;
Adam Powell526b9312011-04-22 15:42:05 -07003450 } else {
3451 return ((ViewGroup) shownPanelView).getChildCount() > 0;
3452 }
3453 }
3454
Adam Powell696cba52011-03-29 10:38:16 -07003455 /**
3456 * Unregister and free attached MenuPresenters. They will be recreated as needed.
3457 */
3458 public void clearMenuPresenters() {
3459 if (menu != null) {
3460 menu.removeMenuPresenter(iconMenuPresenter);
Adam Powelldfee59a2011-08-05 20:48:30 -07003461 menu.removeMenuPresenter(listMenuPresenter);
Adam Powell696cba52011-03-29 10:38:16 -07003462 }
3463 iconMenuPresenter = null;
Adam Powelldfee59a2011-08-05 20:48:30 -07003464 listMenuPresenter = null;
Adam Powell696cba52011-03-29 10:38:16 -07003465 }
3466
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003467 void setStyle(Context context) {
Alan Viverette40982d42014-07-25 17:48:55 -07003468 TypedArray a = context.obtainStyledAttributes(R.styleable.Theme);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003469 background = a.getResourceId(
Alan Viverette40982d42014-07-25 17:48:55 -07003470 R.styleable.Theme_panelBackground, 0);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003471 fullBackground = a.getResourceId(
Alan Viverette40982d42014-07-25 17:48:55 -07003472 R.styleable.Theme_panelFullBackground, 0);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003473 windowAnimations = a.getResourceId(
Alan Viverette40982d42014-07-25 17:48:55 -07003474 R.styleable.Theme_windowAnimationStyle, 0);
Adam Powelldfee59a2011-08-05 20:48:30 -07003475 isCompact = a.getBoolean(
Alan Viverette40982d42014-07-25 17:48:55 -07003476 R.styleable.Theme_panelMenuIsCompact, false);
Adam Powelldfee59a2011-08-05 20:48:30 -07003477 listPresenterTheme = a.getResourceId(
Alan Viverette40982d42014-07-25 17:48:55 -07003478 R.styleable.Theme_panelMenuListTheme,
3479 R.style.Theme_ExpandedMenu);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003480 a.recycle();
3481 }
3482
Adam Powell696cba52011-03-29 10:38:16 -07003483 void setMenu(MenuBuilder menu) {
Adam Powell1d07e162011-09-07 20:46:24 -07003484 if (menu == this.menu) return;
3485
3486 if (this.menu != null) {
3487 this.menu.removeMenuPresenter(iconMenuPresenter);
3488 this.menu.removeMenuPresenter(listMenuPresenter);
3489 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003490 this.menu = menu;
Adam Powell1d07e162011-09-07 20:46:24 -07003491 if (menu != null) {
3492 if (iconMenuPresenter != null) menu.addMenuPresenter(iconMenuPresenter);
3493 if (listMenuPresenter != null) menu.addMenuPresenter(listMenuPresenter);
3494 }
Adam Powell696cba52011-03-29 10:38:16 -07003495 }
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -08003496
Adam Powell538e5652011-10-11 13:47:08 -07003497 MenuView getListMenuView(Context context, MenuPresenter.Callback cb) {
Adam Powell696cba52011-03-29 10:38:16 -07003498 if (menu == null) return null;
3499
Adam Powelldfee59a2011-08-05 20:48:30 -07003500 if (!isCompact) {
Adam Powell538e5652011-10-11 13:47:08 -07003501 getIconMenuView(context, cb); // Need this initialized to know where our offset goes
Adam Powell696cba52011-03-29 10:38:16 -07003502 }
3503
Adam Powelldfee59a2011-08-05 20:48:30 -07003504 if (listMenuPresenter == null) {
3505 listMenuPresenter = new ListMenuPresenter(
Alan Viverette40982d42014-07-25 17:48:55 -07003506 R.layout.list_menu_item_layout, listPresenterTheme);
Adam Powelldfee59a2011-08-05 20:48:30 -07003507 listMenuPresenter.setCallback(cb);
Alan Viverette40982d42014-07-25 17:48:55 -07003508 listMenuPresenter.setId(R.id.list_menu_presenter);
Adam Powelldfee59a2011-08-05 20:48:30 -07003509 menu.addMenuPresenter(listMenuPresenter);
3510 }
3511
3512 if (iconMenuPresenter != null) {
3513 listMenuPresenter.setItemIndexOffset(
3514 iconMenuPresenter.getNumActualItemsShown());
3515 }
3516 MenuView result = listMenuPresenter.getMenuView(decorView);
Adam Powell696cba52011-03-29 10:38:16 -07003517
Adam Powell696cba52011-03-29 10:38:16 -07003518 return result;
3519 }
3520
Adam Powell538e5652011-10-11 13:47:08 -07003521 MenuView getIconMenuView(Context context, MenuPresenter.Callback cb) {
Adam Powell696cba52011-03-29 10:38:16 -07003522 if (menu == null) return null;
3523
Adam Powell696cba52011-03-29 10:38:16 -07003524 if (iconMenuPresenter == null) {
Adam Powell538e5652011-10-11 13:47:08 -07003525 iconMenuPresenter = new IconMenuPresenter(context);
Adam Powell696cba52011-03-29 10:38:16 -07003526 iconMenuPresenter.setCallback(cb);
Alan Viverette40982d42014-07-25 17:48:55 -07003527 iconMenuPresenter.setId(R.id.icon_menu_presenter);
Adam Powell696cba52011-03-29 10:38:16 -07003528 menu.addMenuPresenter(iconMenuPresenter);
Adam Powell696cba52011-03-29 10:38:16 -07003529 }
3530
3531 MenuView result = iconMenuPresenter.getMenuView(decorView);
3532
Adam Powell696cba52011-03-29 10:38:16 -07003533 return result;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003534 }
3535
3536 Parcelable onSaveInstanceState() {
3537 SavedState savedState = new SavedState();
3538 savedState.featureId = featureId;
3539 savedState.isOpen = isOpen;
3540 savedState.isInExpandedMode = isInExpandedMode;
3541
3542 if (menu != null) {
3543 savedState.menuState = new Bundle();
Adam Powell11ed1d62011-07-11 21:19:59 -07003544 menu.savePresenterStates(savedState.menuState);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003545 }
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -08003546
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003547 return savedState;
3548 }
3549
3550 void onRestoreInstanceState(Parcelable state) {
3551 SavedState savedState = (SavedState) state;
3552 featureId = savedState.featureId;
Dianne Hackbornd0071442009-09-25 01:35:29 -07003553 wasLastOpen = savedState.isOpen;
3554 wasLastExpanded = savedState.isInExpandedMode;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003555 frozenMenuState = savedState.menuState;
3556
3557 /*
3558 * A LocalActivityManager keeps the same instance of this class around.
3559 * The first time the menu is being shown after restoring, the
3560 * Activity.onCreateOptionsMenu should be called. But, if it is the
3561 * same instance then menu != null and we won't call that method.
Adam Powell31bb97d2011-05-03 20:58:31 -07003562 * We clear any cached views here. The caller should invalidatePanelMenu.
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003563 */
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003564 createdPanelView = null;
3565 shownPanelView = null;
3566 decorView = null;
3567 }
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -08003568
Adam Powell11ed1d62011-07-11 21:19:59 -07003569 void applyFrozenState() {
3570 if (menu != null && frozenMenuState != null) {
3571 menu.restorePresenterStates(frozenMenuState);
3572 frozenMenuState = null;
3573 }
3574 }
3575
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003576 private static class SavedState implements Parcelable {
3577 int featureId;
3578 boolean isOpen;
3579 boolean isInExpandedMode;
3580 Bundle menuState;
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -08003581
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003582 public int describeContents() {
3583 return 0;
3584 }
3585
3586 public void writeToParcel(Parcel dest, int flags) {
3587 dest.writeInt(featureId);
3588 dest.writeInt(isOpen ? 1 : 0);
3589 dest.writeInt(isInExpandedMode ? 1 : 0);
3590
3591 if (isOpen) {
3592 dest.writeBundle(menuState);
3593 }
3594 }
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -08003595
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003596 private static SavedState readFromParcel(Parcel source) {
3597 SavedState savedState = new SavedState();
3598 savedState.featureId = source.readInt();
3599 savedState.isOpen = source.readInt() == 1;
3600 savedState.isInExpandedMode = source.readInt() == 1;
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -08003601
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003602 if (savedState.isOpen) {
3603 savedState.menuState = source.readBundle();
3604 }
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -08003605
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003606 return savedState;
3607 }
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -08003608
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003609 public static final Parcelable.Creator<SavedState> CREATOR
3610 = new Parcelable.Creator<SavedState>() {
3611 public SavedState createFromParcel(Parcel in) {
3612 return readFromParcel(in);
3613 }
3614
3615 public SavedState[] newArray(int size) {
3616 return new SavedState[size];
3617 }
3618 };
3619 }
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -08003620
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003621 }
3622
Adam Powell6711f3b2015-05-06 15:57:09 -07003623 static class RotationWatcher extends Stub {
Adam Powelldfee59a2011-08-05 20:48:30 -07003624 private Handler mHandler;
3625 private final Runnable mRotationChanged = new Runnable() {
3626 public void run() {
3627 dispatchRotationChanged();
3628 }
3629 };
3630 private final ArrayList<WeakReference<PhoneWindow>> mWindows =
3631 new ArrayList<WeakReference<PhoneWindow>>();
3632 private boolean mIsWatching;
3633
3634 @Override
3635 public void onRotationChanged(int rotation) throws RemoteException {
3636 mHandler.post(mRotationChanged);
3637 }
3638
3639 public void addWindow(PhoneWindow phoneWindow) {
3640 synchronized (mWindows) {
3641 if (!mIsWatching) {
3642 try {
Andrii Kulian35fa3c22017-03-11 09:37:28 -08003643 WindowManagerHolder.sWindowManager.watchRotation(this,
3644 phoneWindow.getContext().getDisplay().getDisplayId());
Adam Powelldfee59a2011-08-05 20:48:30 -07003645 mHandler = new Handler();
3646 mIsWatching = true;
3647 } catch (RemoteException ex) {
3648 Log.e(TAG, "Couldn't start watching for device rotation", ex);
3649 }
3650 }
3651 mWindows.add(new WeakReference<PhoneWindow>(phoneWindow));
3652 }
3653 }
3654
3655 public void removeWindow(PhoneWindow phoneWindow) {
3656 synchronized (mWindows) {
3657 int i = 0;
3658 while (i < mWindows.size()) {
3659 final WeakReference<PhoneWindow> ref = mWindows.get(i);
3660 final PhoneWindow win = ref.get();
3661 if (win == null || win == phoneWindow) {
3662 mWindows.remove(i);
3663 } else {
3664 i++;
3665 }
3666 }
3667 }
3668 }
3669
3670 void dispatchRotationChanged() {
3671 synchronized (mWindows) {
3672 int i = 0;
3673 while (i < mWindows.size()) {
3674 final WeakReference<PhoneWindow> ref = mWindows.get(i);
3675 final PhoneWindow win = ref.get();
3676 if (win != null) {
3677 win.onOptionsPanelRotationChanged();
3678 i++;
3679 } else {
3680 mWindows.remove(i);
3681 }
3682 }
3683 }
3684 }
3685 }
3686
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003687 /**
3688 * Simple implementation of MenuBuilder.Callback that:
3689 * <li> Opens a submenu when selected.
3690 * <li> Calls back to the callback's onMenuItemSelected when an item is
3691 * selected.
3692 */
Alan Viverette77fb85e2015-12-14 11:42:44 -05003693 public static final class PhoneWindowMenuCallback
3694 implements MenuBuilder.Callback, MenuPresenter.Callback {
3695 private static final int FEATURE_ID = FEATURE_CONTEXT_MENU;
3696
3697 private final PhoneWindow mWindow;
3698
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003699 private MenuDialogHelper mSubMenuHelper;
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -08003700
Alan Viverette77fb85e2015-12-14 11:42:44 -05003701 private boolean mShowDialogForSubmenu;
3702
3703 public PhoneWindowMenuCallback(PhoneWindow window) {
3704 mWindow = window;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003705 }
3706
Alan Viverette77fb85e2015-12-14 11:42:44 -05003707 @Override
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003708 public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) {
Adam Powelld1f42072011-05-03 17:20:14 -07003709 if (menu.getRootMenu() != menu) {
3710 onCloseSubMenu(menu);
3711 }
3712
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003713 if (allMenusAreClosing) {
Alan Viverette77fb85e2015-12-14 11:42:44 -05003714 final Callback callback = mWindow.getCallback();
3715 if (callback != null && !mWindow.isDestroyed()) {
3716 callback.onPanelClosed(FEATURE_ID, menu);
Dianne Hackbornb66ad572011-03-01 17:10:30 -08003717 }
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -08003718
Alan Viverette77fb85e2015-12-14 11:42:44 -05003719 if (menu == mWindow.mContextMenu) {
3720 mWindow.dismissContextMenu();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003721 }
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -08003722
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003723 // Dismiss the submenu, if it is showing
3724 if (mSubMenuHelper != null) {
3725 mSubMenuHelper.dismiss();
3726 mSubMenuHelper = null;
3727 }
3728 }
3729 }
3730
Alan Viverette77fb85e2015-12-14 11:42:44 -05003731 private void onCloseSubMenu(MenuBuilder menu) {
3732 final Callback callback = mWindow.getCallback();
3733 if (callback != null && !mWindow.isDestroyed()) {
3734 callback.onPanelClosed(FEATURE_ID, menu.getRootMenu());
Dianne Hackbornb66ad572011-03-01 17:10:30 -08003735 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003736 }
3737
Alan Viverette77fb85e2015-12-14 11:42:44 -05003738 @Override
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003739 public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) {
Alan Viverette77fb85e2015-12-14 11:42:44 -05003740 final Callback callback = mWindow.getCallback();
3741 return callback != null && !mWindow.isDestroyed()
3742 && callback.onMenuItemSelected(FEATURE_ID, item);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003743 }
3744
Alan Viverette77fb85e2015-12-14 11:42:44 -05003745 @Override
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003746 public void onMenuModeChange(MenuBuilder menu) {
3747 }
3748
Alan Viverette77fb85e2015-12-14 11:42:44 -05003749 @Override
Adam Powelld1f42072011-05-03 17:20:14 -07003750 public boolean onOpenSubMenu(MenuBuilder subMenu) {
Alan Viverette77fb85e2015-12-14 11:42:44 -05003751 if (subMenu == null) {
3752 return false;
3753 }
Adam Powell823f0742011-09-21 17:17:01 -07003754
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003755 // Set a simple callback for the submenu
3756 subMenu.setCallback(this);
3757
Alan Viverette77fb85e2015-12-14 11:42:44 -05003758 if (mShowDialogForSubmenu) {
3759 // The window manager will give us a valid window token
3760 mSubMenuHelper = new MenuDialogHelper(subMenu);
3761 mSubMenuHelper.show(null);
3762 return true;
3763 }
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -08003764
Alan Viverette77fb85e2015-12-14 11:42:44 -05003765 return false;
3766 }
3767
3768 public void setShowDialogForSubmenu(boolean enabled) {
3769 mShowDialogForSubmenu = enabled;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003770 }
3771 }
3772
Wale Ogunwale8804af22015-11-17 09:18:15 -08003773 int getLocalFeaturesPrivate() {
3774 return super.getLocalFeatures();
3775 }
Adrian Roos05054bd2014-10-27 17:04:10 +01003776
Wale Ogunwale8804af22015-11-17 09:18:15 -08003777 protected void setDefaultWindowFormat(int format) {
3778 super.setDefaultWindowFormat(format);
Adrian Roos05054bd2014-10-27 17:04:10 +01003779 }
3780
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003781 void sendCloseSystemWindows() {
Jorim Jaggib10e33f2015-02-04 21:57:40 +01003782 sendCloseSystemWindows(getContext(), null);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003783 }
3784
3785 void sendCloseSystemWindows(String reason) {
Jorim Jaggib10e33f2015-02-04 21:57:40 +01003786 sendCloseSystemWindows(getContext(), reason);
3787 }
3788
3789 public static void sendCloseSystemWindows(Context context, String reason) {
Sudheer Shankadc589ac2016-11-10 15:30:17 -08003790 if (ActivityManager.isSystemReady()) {
Jorim Jaggib10e33f2015-02-04 21:57:40 +01003791 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -08003792 ActivityManager.getService().closeSystemDialogs(reason);
Jorim Jaggib10e33f2015-02-04 21:57:40 +01003793 } catch (RemoteException e) {
3794 }
3795 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003796 }
Adrian Roos217ccd22014-05-09 14:29:04 +02003797
3798 @Override
3799 public int getStatusBarColor() {
Adrian Roos34e65442014-05-17 02:35:33 +02003800 return mStatusBarColor;
Adrian Roos217ccd22014-05-09 14:29:04 +02003801 }
3802
3803 @Override
3804 public void setStatusBarColor(int color) {
Adrian Roos34e65442014-05-17 02:35:33 +02003805 mStatusBarColor = color;
3806 mForcedStatusBarColor = true;
3807 if (mDecor != null) {
Adrian Roos05054bd2014-10-27 17:04:10 +01003808 mDecor.updateColorViews(null, false /* animate */);
Adrian Roos34e65442014-05-17 02:35:33 +02003809 }
Adrian Roos217ccd22014-05-09 14:29:04 +02003810 }
3811
3812 @Override
3813 public int getNavigationBarColor() {
Adrian Roos34e65442014-05-17 02:35:33 +02003814 return mNavigationBarColor;
Adrian Roos217ccd22014-05-09 14:29:04 +02003815 }
3816
3817 @Override
3818 public void setNavigationBarColor(int color) {
Adrian Roos34e65442014-05-17 02:35:33 +02003819 mNavigationBarColor = color;
3820 mForcedNavigationBarColor = true;
3821 if (mDecor != null) {
Adrian Roos05054bd2014-10-27 17:04:10 +01003822 mDecor.updateColorViews(null, false /* animate */);
Adrian Roos34e65442014-05-17 02:35:33 +02003823 }
Adrian Roos217ccd22014-05-09 14:29:04 +02003824 }
Jorim Jaggia16cc152015-06-01 16:55:05 -07003825
Jorim Jaggia0b78d52018-01-22 19:01:42 +01003826 @Override
3827 public void setNavigationBarDividerColor(int navigationBarDividerColor) {
3828 mNavigationBarDividerColor = navigationBarDividerColor;
3829 if (mDecor != null) {
3830 mDecor.updateColorViews(null, false /* animate */);
3831 }
3832 }
3833
3834 @Override
3835 public int getNavigationBarDividerColor() {
3836 return mNavigationBarDividerColor;
3837 }
3838
Jorim Jaggia16cc152015-06-01 16:55:05 -07003839 public void setIsStartingWindow(boolean isStartingWindow) {
3840 mIsStartingWindow = isStartingWindow;
3841 }
Stefan Kuhnef4dd71a2015-08-07 09:28:52 -07003842
Filip Gruszczynskia59ac9c2015-09-10 18:28:48 -07003843 @Override
Filip Gruszczynski0daf2102015-09-29 08:39:07 -07003844 public void setTheme(int resid) {
3845 mTheme = resid;
3846 if (mDecor != null) {
3847 Context context = mDecor.getContext();
3848 if (context instanceof DecorContext) {
3849 context.setTheme(resid);
3850 }
3851 }
3852 }
Filip Gruszczynski3dec0812015-12-09 08:42:41 -08003853
3854 @Override
3855 public void setResizingCaptionDrawable(Drawable drawable) {
3856 mDecor.setUserCaptionBackgroundDrawable(drawable);
3857 }
3858
3859 @Override
3860 public void setDecorCaptionShade(int decorCaptionShade) {
3861 mDecorCaptionShade = decorCaptionShade;
3862 if (mDecor != null) {
3863 mDecor.updateDecorCaptionShade();
3864 }
3865 }
3866
3867 int getDecorCaptionShade() {
3868 return mDecorCaptionShade;
3869 }
Filip Gruszczynski34dab0b2015-12-22 08:29:07 -08003870
3871 @Override
3872 public void setAttributes(WindowManager.LayoutParams params) {
3873 super.setAttributes(params);
3874 if (mDecor != null) {
3875 mDecor.updateLogTag(params);
3876 }
3877 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003878}