1 /*
2  * Copyright (C) 2010 The Android Open Source Project
3  *
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 
17 package com.android.gallery3d.app;
18 
19 import android.app.ActionBar;
20 import android.app.Activity;
21 import android.content.BroadcastReceiver;
22 import android.content.Context;
23 import android.content.Intent;
24 import android.content.IntentFilter;
25 import android.content.res.Configuration;
26 import android.os.BatteryManager;
27 import android.os.Bundle;
28 import android.view.HapticFeedbackConstants;
29 import android.view.Menu;
30 import android.view.MenuInflater;
31 import android.view.MenuItem;
32 import android.view.Window;
33 import android.view.WindowManager;
34 
35 import com.android.gallery3d.R;
36 import com.android.gallery3d.anim.StateTransitionAnimation;
37 import com.android.gallery3d.glrenderer.RawTexture;
38 import com.android.gallery3d.ui.GLView;
39 import com.android.gallery3d.ui.PreparePageFadeoutTexture;
40 import com.android.gallery3d.util.GalleryUtils;
41 
42 abstract public class ActivityState {
43     protected static final int FLAG_HIDE_ACTION_BAR = 1;
44     protected static final int FLAG_HIDE_STATUS_BAR = 2;
45     protected static final int FLAG_SCREEN_ON_WHEN_PLUGGED = 4;
46     protected static final int FLAG_SCREEN_ON_ALWAYS = 8;
47     protected static final int FLAG_ALLOW_LOCK_WHILE_SCREEN_ON = 16;
48     protected static final int FLAG_SHOW_WHEN_LOCKED = 32;
49 
50     protected AbstractGalleryActivity mActivity;
51     protected Bundle mData;
52     protected int mFlags;
53 
54     protected ResultEntry mReceivedResults;
55     protected ResultEntry mResult;
56 
57     protected static class ResultEntry {
58         public int requestCode;
59         public int resultCode = Activity.RESULT_CANCELED;
60         public Intent resultData;
61     }
62 
63     private boolean mDestroyed = false;
64     private boolean mPlugged = false;
65     boolean mIsFinishing = false;
66 
67     private static final String KEY_TRANSITION_IN = "transition-in";
68 
69     private StateTransitionAnimation.Transition mNextTransition =
70             StateTransitionAnimation.Transition.None;
71     private StateTransitionAnimation mIntroAnimation;
72     private GLView mContentPane;
73 
ActivityState()74     protected ActivityState() {
75     }
76 
setContentPane(GLView content)77     protected void setContentPane(GLView content) {
78         mContentPane = content;
79         if (mIntroAnimation != null) {
80             mContentPane.setIntroAnimation(mIntroAnimation);
81             mIntroAnimation = null;
82         }
83         mContentPane.setBackgroundColor(getBackgroundColor());
84         mActivity.getGLRoot().setContentPane(mContentPane);
85     }
86 
initialize(AbstractGalleryActivity activity, Bundle data)87     void initialize(AbstractGalleryActivity activity, Bundle data) {
88         mActivity = activity;
89         mData = data;
90     }
91 
getData()92     public Bundle getData() {
93         return mData;
94     }
95 
onBackPressed()96     protected void onBackPressed() {
97         mActivity.getStateManager().finishState(this);
98     }
99 
setStateResult(int resultCode, Intent data)100     protected void setStateResult(int resultCode, Intent data) {
101         if (mResult == null) return;
102         mResult.resultCode = resultCode;
103         mResult.resultData = data;
104     }
105 
onConfigurationChanged(Configuration config)106     protected void onConfigurationChanged(Configuration config) {
107     }
108 
onSaveState(Bundle outState)109     protected void onSaveState(Bundle outState) {
110     }
111 
onStateResult(int requestCode, int resultCode, Intent data)112     protected void onStateResult(int requestCode, int resultCode, Intent data) {
113     }
114 
115     protected float[] mBackgroundColor;
116 
getBackgroundColorId()117     protected int getBackgroundColorId() {
118         return R.color.default_background;
119     }
120 
getBackgroundColor()121     protected float[] getBackgroundColor() {
122         return mBackgroundColor;
123     }
124 
onCreate(Bundle data, Bundle storedState)125     protected void onCreate(Bundle data, Bundle storedState) {
126         mBackgroundColor = GalleryUtils.intColorToFloatARGBArray(
127                 mActivity.getResources().getColor(getBackgroundColorId()));
128     }
129 
clearStateResult()130     protected void clearStateResult() {
131     }
132 
133     BroadcastReceiver mPowerIntentReceiver = new BroadcastReceiver() {
134         @Override
135         public void onReceive(Context context, Intent intent) {
136             final String action = intent.getAction();
137             if (Intent.ACTION_BATTERY_CHANGED.equals(action)) {
138                 boolean plugged = (0 != intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0));
139 
140                 if (plugged != mPlugged) {
141                     mPlugged = plugged;
142                     setScreenFlags();
143                 }
144             }
145         }
146     };
147 
setScreenFlags()148     private void setScreenFlags() {
149         final Window win = mActivity.getWindow();
150         final WindowManager.LayoutParams params = win.getAttributes();
151         if ((0 != (mFlags & FLAG_SCREEN_ON_ALWAYS)) ||
152                 (mPlugged && 0 != (mFlags & FLAG_SCREEN_ON_WHEN_PLUGGED))) {
153             params.flags |= WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
154         } else {
155             params.flags &= ~WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
156         }
157         if (0 != (mFlags & FLAG_ALLOW_LOCK_WHILE_SCREEN_ON)) {
158             params.flags |= WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON;
159         } else {
160             params.flags &= ~WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON;
161         }
162         if (0 != (mFlags & FLAG_SHOW_WHEN_LOCKED)) {
163             params.flags |= WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
164         } else {
165             params.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
166         }
167         win.setAttributes(params);
168     }
169 
transitionOnNextPause(Class<? extends ActivityState> outgoing, Class<? extends ActivityState> incoming, StateTransitionAnimation.Transition hint)170     protected void transitionOnNextPause(Class<? extends ActivityState> outgoing,
171             Class<? extends ActivityState> incoming, StateTransitionAnimation.Transition hint) {
172         if (outgoing == SinglePhotoPage.class && incoming == AlbumPage.class) {
173             mNextTransition = StateTransitionAnimation.Transition.Outgoing;
174         } else if (outgoing == AlbumPage.class && incoming == SinglePhotoPage.class) {
175             mNextTransition = StateTransitionAnimation.Transition.PhotoIncoming;
176         } else {
177             mNextTransition = hint;
178         }
179     }
180 
performHapticFeedback(int feedbackConstant)181     protected void performHapticFeedback(int feedbackConstant) {
182         mActivity.getWindow().getDecorView().performHapticFeedback(feedbackConstant,
183                 HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
184     }
185 
onPause()186     protected void onPause() {
187         if (0 != (mFlags & FLAG_SCREEN_ON_WHEN_PLUGGED)) {
188             ((Activity) mActivity).unregisterReceiver(mPowerIntentReceiver);
189         }
190         if (mNextTransition != StateTransitionAnimation.Transition.None) {
191             mActivity.getTransitionStore().put(KEY_TRANSITION_IN, mNextTransition);
192             PreparePageFadeoutTexture.prepareFadeOutTexture(mActivity, mContentPane);
193             mNextTransition = StateTransitionAnimation.Transition.None;
194         }
195     }
196 
197     // should only be called by StateManager
resume()198     void resume() {
199         AbstractGalleryActivity activity = mActivity;
200         ActionBar actionBar = activity.getActionBar();
201         if (actionBar != null) {
202             if ((mFlags & FLAG_HIDE_ACTION_BAR) != 0) {
203                 actionBar.hide();
204             } else {
205                 actionBar.show();
206             }
207             int stateCount = mActivity.getStateManager().getStateCount();
208             mActivity.getGalleryActionBar().setDisplayOptions(stateCount > 1, true);
209             // Default behavior, this can be overridden in ActivityState's onResume.
210             actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
211         }
212 
213         activity.invalidateOptionsMenu();
214 
215         setScreenFlags();
216 
217         boolean lightsOut = ((mFlags & FLAG_HIDE_STATUS_BAR) != 0);
218         mActivity.getGLRoot().setLightsOutMode(lightsOut);
219 
220         ResultEntry entry = mReceivedResults;
221         if (entry != null) {
222             mReceivedResults = null;
223             onStateResult(entry.requestCode, entry.resultCode, entry.resultData);
224         }
225 
226         if (0 != (mFlags & FLAG_SCREEN_ON_WHEN_PLUGGED)) {
227             // we need to know whether the device is plugged in to do this correctly
228             final IntentFilter filter = new IntentFilter();
229             filter.addAction(Intent.ACTION_BATTERY_CHANGED);
230             activity.registerReceiver(mPowerIntentReceiver, filter);
231         }
232 
233         onResume();
234 
235         // the transition store should be cleared after resume;
236         mActivity.getTransitionStore().clear();
237     }
238 
239     // a subclass of ActivityState should override the method to resume itself
onResume()240     protected void onResume() {
241         RawTexture fade = mActivity.getTransitionStore().get(
242                 PreparePageFadeoutTexture.KEY_FADE_TEXTURE);
243         mNextTransition = mActivity.getTransitionStore().get(
244                 KEY_TRANSITION_IN, StateTransitionAnimation.Transition.None);
245         if (mNextTransition != StateTransitionAnimation.Transition.None) {
246             mIntroAnimation = new StateTransitionAnimation(mNextTransition, fade);
247             mNextTransition = StateTransitionAnimation.Transition.None;
248         }
249     }
250 
onCreateActionBar(Menu menu)251     protected boolean onCreateActionBar(Menu menu) {
252         // TODO: we should return false if there is no menu to show
253         //       this is a workaround for a bug in system
254         return true;
255     }
256 
onItemSelected(MenuItem item)257     protected boolean onItemSelected(MenuItem item) {
258         return false;
259     }
260 
onDestroy()261     protected void onDestroy() {
262         mDestroyed = true;
263     }
264 
isDestroyed()265     boolean isDestroyed() {
266         return mDestroyed;
267     }
268 
isFinishing()269     public boolean isFinishing() {
270         return mIsFinishing;
271     }
272 
getSupportMenuInflater()273     protected MenuInflater getSupportMenuInflater() {
274         return mActivity.getMenuInflater();
275     }
276 }
277