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