diff options
60 files changed, 1040 insertions, 539 deletions
diff --git a/core/java/android/accounts/ChooseAccountTypeActivity.java b/core/java/android/accounts/ChooseAccountTypeActivity.java index 448b2c0c49ae..acc85496ba22 100644 --- a/core/java/android/accounts/ChooseAccountTypeActivity.java +++ b/core/java/android/accounts/ChooseAccountTypeActivity.java @@ -43,7 +43,7 @@ import java.util.Set; * @hide */ public class ChooseAccountTypeActivity extends Activity { - private static final String TAG = "AccountManager"; + private static final String TAG = "AccountChooser"; private HashMap<String, AuthInfo> mTypeToAuthenticatorInfo = new HashMap<String, AuthInfo>(); private ArrayList<AuthInfo> mAuthenticatorInfosToDisplay; @@ -52,6 +52,11 @@ public class ChooseAccountTypeActivity extends Activity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + if (Log.isLoggable(TAG, Log.VERBOSE)) { + Log.v(TAG, "ChooseAccountTypeActivity.onCreate(savedInstanceState=" + + savedInstanceState + ")"); + } + // Read the validAccountTypes, if present, and add them to the setOfAllowableAccountTypes Set<String> setOfAllowableAccountTypes = null; String[] validAccountTypes = getIntent().getStringArrayExtra( @@ -111,8 +116,10 @@ public class ChooseAccountTypeActivity extends Activity { Bundle bundle = new Bundle(); bundle.putString(AccountManager.KEY_ACCOUNT_TYPE, type); setResult(Activity.RESULT_OK, new Intent().putExtras(bundle)); - Log.d(TAG, "ChooseAccountTypeActivity.setResultAndFinish: " - + "selected account type " + type); + if (Log.isLoggable(TAG, Log.VERBOSE)) { + Log.v(TAG, "ChooseAccountTypeActivity.setResultAndFinish: " + + "selected account type " + type); + } finish(); } diff --git a/core/java/android/accounts/ChooseTypeAndAccountActivity.java b/core/java/android/accounts/ChooseTypeAndAccountActivity.java index 8cc200250ba3..5f38eb4d9813 100644 --- a/core/java/android/accounts/ChooseTypeAndAccountActivity.java +++ b/core/java/android/accounts/ChooseTypeAndAccountActivity.java @@ -47,7 +47,7 @@ import java.util.Set; */ public class ChooseTypeAndAccountActivity extends Activity implements AccountManagerCallback<Bundle> { - private static final String TAG = "AccountManager"; + private static final String TAG = "AccountChooser"; /** * A Parcelable ArrayList of Account objects that limits the choosable accounts to those @@ -100,13 +100,39 @@ public class ChooseTypeAndAccountActivity extends Activity public static final String EXTRA_DESCRIPTION_TEXT_OVERRIDE = "descriptionTextOverride"; + public static final int REQUEST_NULL = 0; + public static final int REQUEST_CHOOSE_TYPE = 1; + public static final int REQUEST_ADD_ACCOUNT = 2; + + private static final String KEY_INSTANCE_STATE_PENDING_REQUEST = "pendingRequest"; + private static final String KEY_INSTANCE_STATE_EXISTING_ACCOUNTS = "existingAccounts"; + private ArrayList<AccountInfo> mAccountInfos; + private int mPendingRequest = REQUEST_NULL; + private Parcelable[] mExistingAccounts = null; + private Parcelable[] mSavedAccounts = null; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + if (Log.isLoggable(TAG, Log.VERBOSE)) { + Log.v(TAG, "ChooseTypeAndAccountActivity.onCreate(savedInstanceState=" + + savedInstanceState + ")"); + } + setContentView(R.layout.choose_type_and_account); + if (savedInstanceState != null) { + mPendingRequest = savedInstanceState.getInt(KEY_INSTANCE_STATE_PENDING_REQUEST); + mSavedAccounts = + savedInstanceState.getParcelableArray(KEY_INSTANCE_STATE_EXISTING_ACCOUNTS); + mExistingAccounts = null; + } else { + mPendingRequest = REQUEST_NULL; + mSavedAccounts = null; + mExistingAccounts = null; + } + // save some items we use frequently final AccountManager accountManager = AccountManager.get(this); final Intent intent = getIntent(); @@ -171,20 +197,6 @@ public class ChooseTypeAndAccountActivity extends Activity account.equals(selectedAccount))); } - // If there are no allowable accounts go directly to add account - if (mAccountInfos.isEmpty()) { - startChooseAccountTypeActivity(); - return; - } - - // if there is only one allowable account return it - if (!intent.getBooleanExtra(EXTRA_ALWAYS_PROMPT_FOR_ACCOUNT, false) - && mAccountInfos.size() == 1) { - Account account = mAccountInfos.get(0).account; - setResultAndFinish(account.name, account.type); - return; - } - // there is more than one allowable account. initialize the list adapter to allow // the user to select an account. ListView list = (ListView) findViewById(android.R.id.list); @@ -204,6 +216,37 @@ public class ChooseTypeAndAccountActivity extends Activity startChooseAccountTypeActivity(); } }); + + if (mPendingRequest == REQUEST_NULL) { + // If there are no allowable accounts go directly to add account + if (mAccountInfos.isEmpty()) { + startChooseAccountTypeActivity(); + return; + } + + // if there is only one allowable account return it + if (!intent.getBooleanExtra(EXTRA_ALWAYS_PROMPT_FOR_ACCOUNT, false) + && mAccountInfos.size() == 1) { + Account account = mAccountInfos.get(0).account; + setResultAndFinish(account.name, account.type); + return; + } + } + } + + @Override + protected void onDestroy() { + if (Log.isLoggable(TAG, Log.VERBOSE)) { + Log.v(TAG, "ChooseTypeAndAccountActivity.onDestroy()"); + } + super.onDestroy(); + } + + @Override + protected void onSaveInstanceState(final Bundle outState) { + super.onSaveInstanceState(outState); + outState.putInt(KEY_INSTANCE_STATE_PENDING_REQUEST, mPendingRequest); + outState.putParcelableArray(KEY_INSTANCE_STATE_EXISTING_ACCOUNTS, mExistingAccounts); } // Called when the choose account type activity (for adding an account) returns. @@ -212,20 +255,75 @@ public class ChooseTypeAndAccountActivity extends Activity @Override protected void onActivityResult(final int requestCode, final int resultCode, final Intent data) { - if (resultCode == RESULT_OK && data != null) { - String accountType = data.getStringExtra(AccountManager.KEY_ACCOUNT_TYPE); - if (accountType != null) { - runAddAccountForAuthenticator(accountType); - return; + if (Log.isLoggable(TAG, Log.VERBOSE)) { + if (data != null && data.getExtras() != null) data.getExtras().keySet(); + Bundle extras = data != null ? data.getExtras() : null; + Log.v(TAG, "ChooseTypeAndAccountActivity.onActivityResult(reqCode=" + requestCode + + ", resCode=" + resultCode + ", extras=" + extras + ")"); + } + + // we got our result, so clear the fact that we had a pending request + mPendingRequest = REQUEST_NULL; + mExistingAccounts = null; + + if (resultCode == RESULT_CANCELED) { + return; + } + + if (resultCode == RESULT_OK) { + if (requestCode == REQUEST_CHOOSE_TYPE) { + if (data != null) { + String accountType = data.getStringExtra(AccountManager.KEY_ACCOUNT_TYPE); + if (accountType != null) { + runAddAccountForAuthenticator(accountType); + return; + } + } + Log.d(TAG, "ChooseTypeAndAccountActivity.onActivityResult: unable to find account " + + "type, pretending the request was canceled"); + } else if (requestCode == REQUEST_ADD_ACCOUNT) { + String accountName = null; + String accountType = null; + + if (data != null) { + accountName = data.getStringExtra(AccountManager.KEY_ACCOUNT_NAME); + accountType = data.getStringExtra(AccountManager.KEY_ACCOUNT_TYPE); + } + + if (accountName == null || accountType == null) { + Account[] currentAccounts = AccountManager.get(this).getAccounts(); + Set<Account> preExistingAccounts = new HashSet<Account>(); + for (Parcelable accountParcel : mSavedAccounts) { + preExistingAccounts.add((Account) accountParcel); + } + for (Account account : currentAccounts) { + if (!preExistingAccounts.contains(account)) { + accountName = account.name; + accountType = account.type; + break; + } + } + } + + if (accountName != null || accountType != null) { + setResultAndFinish(accountName, accountType); + return; + } } + Log.d(TAG, "ChooseTypeAndAccountActivity.onActivityResult: unable to find added " + + "account, pretending the request was canceled"); + } + if (Log.isLoggable(TAG, Log.VERBOSE)) { + Log.v(TAG, "ChooseTypeAndAccountActivity.onActivityResult: canceled"); } - Log.d(TAG, "ChooseTypeAndAccountActivity.onActivityResult: canceled"); setResult(Activity.RESULT_CANCELED); finish(); } protected void runAddAccountForAuthenticator(String type) { - Log.d(TAG, "selected account type " + type); + if (Log.isLoggable(TAG, Log.VERBOSE)) { + Log.v(TAG, "runAddAccountForAuthenticator: " + type); + } final Bundle options = getIntent().getBundleExtra( ChooseTypeAndAccountActivity.EXTRA_ADD_ACCOUNT_OPTIONS_BUNDLE); final String[] requiredFeatures = getIntent().getStringArrayExtra( @@ -233,20 +331,19 @@ public class ChooseTypeAndAccountActivity extends Activity final String authTokenType = getIntent().getStringExtra( ChooseTypeAndAccountActivity.EXTRA_ADD_ACCOUNT_AUTH_TOKEN_TYPE_STRING); AccountManager.get(this).addAccount(type, authTokenType, requiredFeatures, - options, this, this, null /* Handler */); + options, null /* activity */, this /* callback */, null /* Handler */); } public void run(final AccountManagerFuture<Bundle> accountManagerFuture) { try { final Bundle accountManagerResult = accountManagerFuture.getResult(); - final String name = accountManagerResult.getString(AccountManager.KEY_ACCOUNT_NAME); - final String type = accountManagerResult.getString(AccountManager.KEY_ACCOUNT_TYPE); - if (name != null && type != null) { - final Bundle bundle = new Bundle(); - bundle.putString(AccountManager.KEY_ACCOUNT_NAME, name); - bundle.putString(AccountManager.KEY_ACCOUNT_TYPE, type); - setResult(Activity.RESULT_OK, new Intent().putExtras(bundle)); - finish(); + final Intent intent = (Intent)accountManagerResult.getParcelable( + AccountManager.KEY_INTENT); + if (intent != null) { + mPendingRequest = REQUEST_ADD_ACCOUNT; + mExistingAccounts = AccountManager.get(this).getAccounts(); + intent.setFlags(intent.getFlags() & ~Intent.FLAG_ACTIVITY_NEW_TASK); + startActivityForResult(intent, REQUEST_ADD_ACCOUNT); return; } } catch (OperationCanceledException e) { @@ -297,12 +394,17 @@ public class ChooseTypeAndAccountActivity extends Activity bundle.putString(AccountManager.KEY_ACCOUNT_NAME, accountName); bundle.putString(AccountManager.KEY_ACCOUNT_TYPE, accountType); setResult(Activity.RESULT_OK, new Intent().putExtras(bundle)); - Log.d(TAG, "ChooseTypeAndAccountActivity.setResultAndFinish: " - + "selected account " + accountName + ", " + accountType); + if (Log.isLoggable(TAG, Log.VERBOSE)) { + Log.v(TAG, "ChooseTypeAndAccountActivity.setResultAndFinish: " + + "selected account " + accountName + ", " + accountType); + } finish(); } private void startChooseAccountTypeActivity() { + if (Log.isLoggable(TAG, Log.VERBOSE)) { + Log.v(TAG, "ChooseAccountTypeActivity.startChooseAccountTypeActivity()"); + } final Intent intent = new Intent(this, ChooseAccountTypeActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); intent.putExtra(EXTRA_ALLOWABLE_ACCOUNT_TYPES_STRING_ARRAY, @@ -313,7 +415,8 @@ public class ChooseTypeAndAccountActivity extends Activity getIntent().getStringArrayExtra(EXTRA_ADD_ACCOUNT_REQUIRED_FEATURES_STRING_ARRAY)); intent.putExtra(EXTRA_ADD_ACCOUNT_AUTH_TOKEN_TYPE_STRING, getIntent().getStringExtra(EXTRA_ADD_ACCOUNT_AUTH_TOKEN_TYPE_STRING)); - startActivityForResult(intent, 0); + startActivityForResult(intent, REQUEST_CHOOSE_TYPE); + mPendingRequest = REQUEST_CHOOSE_TYPE; } private static class AccountInfo { diff --git a/core/java/android/app/StatusBarManager.java b/core/java/android/app/StatusBarManager.java index ca64c88e8fb7..c5ee48d967ab 100644 --- a/core/java/android/app/StatusBarManager.java +++ b/core/java/android/app/StatusBarManager.java @@ -40,15 +40,20 @@ public class StatusBarManager { public static final int DISABLE_NOTIFICATION_TICKER = View.STATUS_BAR_DISABLE_NOTIFICATION_TICKER; public static final int DISABLE_SYSTEM_INFO = View.STATUS_BAR_DISABLE_SYSTEM_INFO; - public static final int DISABLE_NAVIGATION = View.STATUS_BAR_DISABLE_NAVIGATION; + public static final int DISABLE_HOME = View.STATUS_BAR_DISABLE_HOME; + public static final int DISABLE_RECENT = View.STATUS_BAR_DISABLE_RECENT; public static final int DISABLE_BACK = View.STATUS_BAR_DISABLE_BACK; public static final int DISABLE_CLOCK = View.STATUS_BAR_DISABLE_CLOCK; + @Deprecated + public static final int DISABLE_NAVIGATION = + View.STATUS_BAR_DISABLE_HOME | View.STATUS_BAR_DISABLE_RECENT; + public static final int DISABLE_NONE = 0x00000000; public static final int DISABLE_MASK = DISABLE_EXPAND | DISABLE_NOTIFICATION_ICONS | DISABLE_NOTIFICATION_ALERTS | DISABLE_NOTIFICATION_TICKER - | DISABLE_SYSTEM_INFO| DISABLE_NAVIGATION | DISABLE_BACK | DISABLE_CLOCK; + | DISABLE_SYSTEM_INFO | DISABLE_RECENT | DISABLE_HOME | DISABLE_BACK | DISABLE_CLOCK; private Context mContext; private IStatusBarService mService; diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index 2be515376453..45a42e44f1cd 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -57,8 +57,8 @@ import java.util.Set; * * <p>An Intent provides a facility for performing late runtime binding between the code in * different applications. Its most significant use is in the launching of activities, where it - * can be thought of as the glue between activities. It is basically a passive data structure - * holding an abstract description of an action to be performed.</p> + * can be thought of as the glue between activities. It is basically a passive data structure + * holding an abstract description of an action to be performed.</p> * * <div class="special reference"> * <h3>Developer Guides</h3> @@ -2566,7 +2566,7 @@ public class Intent implements Parcelable, Cloneable { */ public static final String EXTRA_LOCAL_ONLY = "android.intent.extra.LOCAL_ONLY"; - + // --------------------------------------------------------------------- // --------------------------------------------------------------------- // Intent flags (see mFlags variable). @@ -5291,7 +5291,7 @@ public class Intent implements Parcelable, Cloneable { if (r != null) { mSourceBounds = new Rect(r); } else { - r = null; + mSourceBounds = null; } } diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java index 9bd4a3be3622..d3387648ab6b 100644 --- a/core/java/android/hardware/Camera.java +++ b/core/java/android/hardware/Camera.java @@ -337,7 +337,7 @@ public class Camera { * Camera objects are locked by default unless {@link #unlock()} is * called. Normally {@link #reconnect()} is used instead. * - * <p>Since API level 13, camera is automatically locked for applications in + * <p>Since API level 14, camera is automatically locked for applications in * {@link android.media.MediaRecorder#start()}. Applications can use the * camera (ex: zoom) after recording starts. There is no need to call this * after recording starts or stops. @@ -356,7 +356,7 @@ public class Camera { * which will re-acquire the lock and allow you to continue using the * camera. * - * <p>Since API level 13, camera is automatically locked for applications in + * <p>Since API level 14, camera is automatically locked for applications in * {@link android.media.MediaRecorder#start()}. Applications can use the * camera (ex: zoom) after recording starts. There is no need to call this * after recording starts or stops. @@ -781,7 +781,7 @@ public class Camera { * @see android.hardware.Camera.Parameters#setAutoWhiteBalanceLock(boolean) */ void onAutoFocus(boolean success, Camera camera); - }; + } /** * Starts camera auto-focus and registers a callback function to run when @@ -804,11 +804,17 @@ public class Camera { * {@link android.hardware.Camera.Parameters#FLASH_MODE_OFF}, flash may be * fired during auto-focus, depending on the driver and camera hardware.<p> * - * Auto-exposure lock {@link android.hardware.Camera.Parameters#getAutoExposureLock()} + * <p>Auto-exposure lock {@link android.hardware.Camera.Parameters#getAutoExposureLock()} * and auto-white balance locks {@link android.hardware.Camera.Parameters#getAutoWhiteBalanceLock()} * do not change during and after autofocus. But auto-focus routine may stop * auto-exposure and auto-white balance transiently during focusing. * + * <p>Stopping preview with {@link #stopPreview()}, or triggering still + * image capture with {@link #takePicture(Camera.ShutterCallback, + * Camera.PictureCallback, Camera.PictureCallback)}, will not change the + * the focus position. Applications must call cancelAutoFocus to reset the + * focus.</p> + * * @param cb the callback to run * @see #cancelAutoFocus() * @see android.hardware.Camera.Parameters#setAutoExposureLock(boolean) @@ -1059,8 +1065,7 @@ public class Camera { /** * Notify the listener of the detected faces in the preview frame. * - * @param faces The detected faces in a list sorted by the confidence score. - * The highest scored face is the first element. + * @param faces The detected faces in a list * @param camera The {@link Camera} service object */ void onFaceDetection(Face[] faces, Camera camera); @@ -1121,7 +1126,7 @@ public class Camera { /** * Information about a face identified through camera face detection. - * + * * <p>When face detection is used with a camera, the {@link FaceDetectionListener} returns a * list of face objects for use in focusing and metering.</p> * @@ -1140,7 +1145,9 @@ public class Camera { * the field of view. For example, suppose the size of the viewfinder UI * is 800x480. The rect passed from the driver is (-1000, -1000, 0, 0). * The corresponding viewfinder rect should be (0, 0, 400, 240). The - * width and height of the rect will not be 0 or negative. + * width and height of the rect will not be 0 or negative. The + * coordinates can be smaller than -1000 or bigger than 1000. But at + * least one vertex will be within (-1000, -1000) and (1000, 1000). * * <p>The direction is relative to the sensor orientation, that is, what * the sensor sees. The direction is not affected by the rotation or @@ -1653,9 +1660,18 @@ public class Camera { * call {@link #takePicture(Camera.ShutterCallback, * Camera.PictureCallback, Camera.PictureCallback)} in this mode but the * subject may not be in focus. Auto focus starts when the parameter is - * set. Applications should not call {@link - * #autoFocus(AutoFocusCallback)} in this mode. To stop continuous - * focus, applications should change the focus mode to other modes. + * set. + * + * <p>Since API level 14, applications can call {@link + * #autoFocus(AutoFocusCallback)} in this mode. The focus callback will + * immediately return with a boolean that indicates whether the focus is + * sharp or not. The focus position is locked after autoFocus call. If + * applications want to resume the continuous focus, cancelAutoFocus + * must be called. Restarting the preview will not resume the continuous + * autofocus. To stop continuous focus, applications should change the + * focus mode to other modes. + * + * @see #FOCUS_MODE_CONTINUOUS_PICTURE */ public static final String FOCUS_MODE_CONTINUOUS_VIDEO = "continuous-video"; @@ -1663,13 +1679,17 @@ public class Camera { * Continuous auto focus mode intended for taking pictures. The camera * continuously tries to focus. The speed of focus change is more * aggressive than {@link #FOCUS_MODE_CONTINUOUS_VIDEO}. Auto focus - * starts when the parameter is set. If applications call {@link - * #autoFocus(AutoFocusCallback)} in this mode, the focus callback will - * immediately return with a boolean that indicates whether the focus is - * sharp or not. The apps can then decide if they want to take a picture - * immediately or to change the focus mode to auto, and run a full - * autofocus cycle. To stop continuous focus, applications should change - * the focus mode to other modes. + * starts when the parameter is set. + * + * <p>If applications call {@link #autoFocus(AutoFocusCallback)} in this + * mode, the focus callback will immediately return with a boolean that + * indicates whether the focus is sharp or not. The apps can then decide + * if they want to take a picture immediately or to change the focus + * mode to auto, and run a full autofocus cycle. The focus position is + * locked after autoFocus call. If applications want to resume the + * continuous focus, cancelAutoFocus must be called. Restarting the + * preview will not resume the continuous autofocus. To stop continuous + * focus, applications should change the focus mode to other modes. * * @see #FOCUS_MODE_CONTINUOUS_VIDEO */ @@ -3061,8 +3081,9 @@ public class Camera { * when using zoom.</p> * * <p>Focus area only has effect if the current focus mode is - * {@link #FOCUS_MODE_AUTO}, {@link #FOCUS_MODE_MACRO}, or - * {@link #FOCUS_MODE_CONTINUOUS_VIDEO}.</p> + * {@link #FOCUS_MODE_AUTO}, {@link #FOCUS_MODE_MACRO}, + * {@link #FOCUS_MODE_CONTINUOUS_VIDEO}, or + * {@link #FOCUS_MODE_CONTINUOUS_PICTURE}.</p> * * @return a list of current focus areas */ diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java index 3bd0f76dfc3b..ad2283ea9285 100644 --- a/core/java/android/view/Display.java +++ b/core/java/android/view/Display.java @@ -117,6 +117,11 @@ public class Display { outSize.x = getRawWidth(); outSize.y = getRawHeight(); } + if (false) { + RuntimeException here = new RuntimeException("here"); + here.fillInStackTrace(); + Slog.v(TAG, "Returning display size: " + outSize, here); + } if (DEBUG_DISPLAY_SIZE && doCompat) Slog.v( TAG, "Returning display size: " + outSize); } catch (RemoteException e) { diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 86be28a534da..73e5026df6f5 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -1891,12 +1891,10 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked * out of the public fields to keep the undefined bits out of the developer's way. * - * Flag to hide only the navigation buttons. Don't use this + * Flag to hide only the home button. Don't use this * unless you're a special part of the system UI (i.e., setup wizard, keyguard). - * - * THIS DOES NOT DISABLE THE BACK BUTTON */ - public static final int STATUS_BAR_DISABLE_NAVIGATION = 0x00200000; + public static final int STATUS_BAR_DISABLE_HOME = 0x00200000; /** * @hide @@ -1904,7 +1902,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked * out of the public fields to keep the undefined bits out of the developer's way. * - * Flag to hide only the back button. Don't use this + * Flag to hide only the back button. Don't use this * unless you're a special part of the system UI (i.e., setup wizard, keyguard). */ public static final int STATUS_BAR_DISABLE_BACK = 0x00400000; @@ -1922,6 +1920,28 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal /** * @hide + * + * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked + * out of the public fields to keep the undefined bits out of the developer's way. + * + * Flag to hide only the recent apps button. Don't use this + * unless you're a special part of the system UI (i.e., setup wizard, keyguard). + */ + public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000; + + /** + * @hide + * + * NOTE: This flag may only be used in subtreeSystemUiVisibility, etc. etc. + * + * This hides HOME and RECENT and is provided for compatibility with interim implementations. + */ + @Deprecated + public static final int STATUS_BAR_DISABLE_NAVIGATION = + STATUS_BAR_DISABLE_HOME | STATUS_BAR_DISABLE_RECENT; + + /** + * @hide */ public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x0000FFFF; diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java index bfd29595b2dc..17bdff2c9628 100644 --- a/core/java/android/view/WindowManagerPolicy.java +++ b/core/java/android/view/WindowManagerPolicy.java @@ -104,23 +104,23 @@ public interface WindowManagerPolicy { */ public final static String EXTRA_HDMI_PLUGGED_STATE = "state"; - // flags for interceptKeyTq /** - * Pass this event to the user / app. To be returned from {@link #interceptKeyTq}. + * Pass this event to the user / app. To be returned from + * {@link #interceptKeyBeforeQueueing}. */ public final static int ACTION_PASS_TO_USER = 0x00000001; /** * This key event should extend the user activity timeout and turn the lights on. - * To be returned from {@link #interceptKeyTq}. Do not return this and - * {@link #ACTION_GO_TO_SLEEP} or {@link #ACTION_PASS_TO_USER}. + * To be returned from {@link #interceptKeyBeforeQueueing}. + * Do not return this and {@link #ACTION_GO_TO_SLEEP} or {@link #ACTION_PASS_TO_USER}. */ public final static int ACTION_POKE_USER_ACTIVITY = 0x00000002; /** * This key event should put the device to sleep (and engage keyguard if necessary) - * To be returned from {@link #interceptKeyTq}. Do not return this and - * {@link #ACTION_POKE_USER_ACTIVITY} or {@link #ACTION_PASS_TO_USER}. + * To be returned from {@link #interceptKeyBeforeQueueing}. + * Do not return this and {@link #ACTION_POKE_USER_ACTIVITY} or {@link #ACTION_PASS_TO_USER}. */ public final static int ACTION_GO_TO_SLEEP = 0x00000004; @@ -677,10 +677,12 @@ public interface WindowManagerPolicy { * event will normally go. * @param event The key event. * @param policyFlags The policy flags associated with the key. - * @return Returns true if the policy consumed the event and it should - * not be further dispatched. + * @return 0 if the key should be dispatched immediately, -1 if the key should + * not be dispatched ever, or a positive value indicating the number of + * milliseconds by which the key dispatch should be delayed before trying + * again. */ - public boolean interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags); + public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags); /** * Called from the input dispatcher thread when an application did not handle diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java index 9c44138f03e5..f1c2bdead14d 100644 --- a/core/java/android/webkit/WebSettings.java +++ b/core/java/android/webkit/WebSettings.java @@ -211,6 +211,7 @@ public class WebSettings { private ZoomDensity mDefaultZoom = ZoomDensity.MEDIUM; private RenderPriority mRenderPriority = RenderPriority.NORMAL; private int mOverrideCacheMode = LOAD_DEFAULT; + private int mDoubleTapZoom = 100; private boolean mSaveFormData = true; private boolean mAutoFillEnabled = false; private boolean mSavePassword = true; @@ -769,6 +770,27 @@ public class WebSettings { } /** + * Set the double-tap zoom of the page in percent. Default is 100. + * @param doubleTapZoom A percent value for increasing or decreasing the double-tap zoom. + * @hide + */ + public void setDoubleTapZoom(int doubleTapZoom) { + if (mDoubleTapZoom != doubleTapZoom) { + mDoubleTapZoom = doubleTapZoom; + mWebView.updateDoubleTapZoom(); + } + } + + /** + * Get the double-tap zoom of the page in percent. + * @return A percent value describing the double-tap zoom. + * @hide + */ + public int getDoubleTapZoom() { + return mDoubleTapZoom; + } + + /** * Set the default zoom density of the page. This should be called from UI * thread. * @param zoom A ZoomDensity value diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index 9648cd015d74..8da1820e4725 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -2986,6 +2986,13 @@ public class WebView extends AbsoluteLayout return false; } + /** + * Update the double-tap zoom. + */ + /* package */ void updateDoubleTapZoom() { + mZoomManager.updateDoubleTapZoom(); + } + private int computeRealHorizontalScrollRange() { if (mDrawHistory) { return mHistoryWidth; diff --git a/core/java/android/webkit/ZoomManager.java b/core/java/android/webkit/ZoomManager.java index 7f526e7e7c1b..206142a5b38b 100644 --- a/core/java/android/webkit/ZoomManager.java +++ b/core/java/android/webkit/ZoomManager.java @@ -145,11 +145,11 @@ class ZoomManager { private float mInvDefaultScale; /* - * The scale factor that is used to determine the zoom level for reading text. - * The value is initially set to equal the display density. - * TODO: Support changing this in WebSettings + * The logical density of the display. This is a scaling factor for the + * Density Independent Pixel unit, where one DIP is one pixel on an + * approximately 160 dpi screen (see android.util.DisplayMetrics.density) */ - private float mReadingLevelScale; + private float mDisplayDensity; /* * The scale factor that is used as the minimum increment when going from @@ -233,11 +233,11 @@ class ZoomManager { public void init(float density) { assert density > 0; + mDisplayDensity = density; setDefaultZoomScale(density); mActualScale = density; mInvActualScale = 1 / density; - mReadingLevelScale = density; - mTextWrapScale = density; + mTextWrapScale = getReadingLevelScale(); } /** @@ -310,8 +310,11 @@ class ZoomManager { return mInitialScale > 0 ? mInitialScale : mDefaultScale; } + /** + * Returns the zoom scale used for reading text on a double-tap. + */ public final float getReadingLevelScale() { - return mReadingLevelScale; + return mDisplayDensity * mWebView.getSettings().getDoubleTapZoom() / 100.0f; } public final float getInvDefaultScale() { @@ -510,6 +513,13 @@ class ZoomManager { return mZoomScale != 0 || mInHWAcceleratedZoom; } + public void updateDoubleTapZoom() { + if (mInZoomOverview) { + mTextWrapScale = getReadingLevelScale(); + refreshZoomScale(true); + } + } + public void refreshZoomScale(boolean reflowText) { setZoomScale(mActualScale, reflowText, true); } diff --git a/core/java/android/widget/AbsSeekBar.java b/core/java/android/widget/AbsSeekBar.java index 475b8eeaf028..bdaf89edf826 100644 --- a/core/java/android/widget/AbsSeekBar.java +++ b/core/java/android/widget/AbsSeekBar.java @@ -335,7 +335,9 @@ public abstract class AbsSeekBar extends ProgressBar { mTouchDownX = event.getX(); } else { setPressed(true); - invalidate(mThumb.getBounds()); // This may be within the padding region + if (mThumb != null) { + invalidate(mThumb.getBounds()); // This may be within the padding region + } onStartTrackingTouch(); trackTouchEvent(event); attemptClaimDrag(); @@ -349,7 +351,9 @@ public abstract class AbsSeekBar extends ProgressBar { final float x = event.getX(); if (Math.abs(x - mTouchDownX) > mScaledTouchSlop) { setPressed(true); - invalidate(mThumb.getBounds()); // This may be within the padding region + if (mThumb != null) { + invalidate(mThumb.getBounds()); // This may be within the padding region + } onStartTrackingTouch(); trackTouchEvent(event); attemptClaimDrag(); diff --git a/core/java/com/android/internal/widget/LockPatternView.java b/core/java/com/android/internal/widget/LockPatternView.java index 5b49bffd8f02..a2fc6e2efdcd 100644 --- a/core/java/com/android/internal/widget/LockPatternView.java +++ b/core/java/com/android/internal/widget/LockPatternView.java @@ -32,9 +32,9 @@ import android.os.Debug; import android.os.Parcel; import android.os.Parcelable; import android.os.SystemClock; -import android.os.Vibrator; import android.util.AttributeSet; import android.util.Log; +import android.view.HapticFeedbackConstants; import android.view.MotionEvent; import android.view.View; import android.view.accessibility.AccessibilityEvent; @@ -59,9 +59,6 @@ public class LockPatternView extends View { private static final int ASPECT_LOCK_WIDTH = 1; // Fixed width; height will be minimum of (w,h) private static final int ASPECT_LOCK_HEIGHT = 2; // Fixed height; width will be minimum of (w,h) - // Vibrator pattern for creating a tactile bump - private static final long[] DEFAULT_VIBE_PATTERN = {0, 1, 40, 41}; - private static final boolean PROFILE_DRAWING = false; private boolean mDrawingProfilingStarted = false; @@ -102,7 +99,7 @@ public class LockPatternView extends View { private DisplayMode mPatternDisplayMode = DisplayMode.Correct; private boolean mInputEnabled = true; private boolean mInStealthMode = false; - private boolean mTactileFeedbackEnabled = true; + private boolean mEnableHapticFeedback = true; private boolean mPatternInProgress = false; private float mDiameterFactor = 0.10f; // TODO: move to attrs @@ -127,11 +124,6 @@ public class LockPatternView extends View { private int mBitmapWidth; private int mBitmapHeight; - - private Vibrator vibe; // Vibrator for creating tactile feedback - - private long[] mVibePattern; - private int mAspect; private final Matrix mArrowMatrix = new Matrix(); private final Matrix mCircleMatrix = new Matrix(); @@ -250,7 +242,6 @@ public class LockPatternView extends View { public LockPatternView(Context context, AttributeSet attrs) { super(context, attrs); - vibe = new Vibrator(); TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.LockPatternView); @@ -295,26 +286,6 @@ public class LockPatternView extends View { mBitmapHeight = Math.max(mBitmapHeight, bitmap.getHeight()); } - // allow vibration pattern to be customized - mVibePattern = loadVibratePattern(com.android.internal.R.array.config_virtualKeyVibePattern); - } - - private long[] loadVibratePattern(int id) { - int[] pattern = null; - try { - pattern = getResources().getIntArray(id); - } catch (Resources.NotFoundException e) { - Log.e(TAG, "Vibrate pattern missing, using default", e); - } - if (pattern == null) { - return DEFAULT_VIBE_PATTERN; - } - - long[] tmpPattern = new long[pattern.length]; - for (int i = 0; i < pattern.length; i++) { - tmpPattern[i] = pattern[i]; - } - return tmpPattern; } private Bitmap getBitmapFor(int resId) { @@ -332,7 +303,7 @@ public class LockPatternView extends View { * @return Whether the view has tactile feedback enabled. */ public boolean isTactileFeedbackEnabled() { - return mTactileFeedbackEnabled; + return mEnableHapticFeedback; } /** @@ -352,7 +323,7 @@ public class LockPatternView extends View { * @param tactileFeedbackEnabled Whether tactile feedback is enabled */ public void setTactileFeedbackEnabled(boolean tactileFeedbackEnabled) { - mTactileFeedbackEnabled = tactileFeedbackEnabled; + mEnableHapticFeedback = tactileFeedbackEnabled; } /** @@ -573,8 +544,10 @@ public class LockPatternView extends View { addCellToPattern(fillInGapCell); } addCellToPattern(cell); - if (mTactileFeedbackEnabled){ - vibe.vibrate(mVibePattern, -1); // Generate tactile feedback + if (mEnableHapticFeedback) { + performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY, + HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING + | HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); } return cell; } @@ -1114,7 +1087,7 @@ public class LockPatternView extends View { return new SavedState(superState, LockPatternUtils.patternToString(mPattern), mPatternDisplayMode.ordinal(), - mInputEnabled, mInStealthMode, mTactileFeedbackEnabled); + mInputEnabled, mInStealthMode, mEnableHapticFeedback); } @Override @@ -1127,7 +1100,7 @@ public class LockPatternView extends View { mPatternDisplayMode = DisplayMode.values()[ss.getDisplayMode()]; mInputEnabled = ss.isInputEnabled(); mInStealthMode = ss.isInStealthMode(); - mTactileFeedbackEnabled = ss.isTactileFeedbackEnabled(); + mEnableHapticFeedback = ss.isTactileFeedbackEnabled(); } /** diff --git a/core/java/com/android/internal/widget/PasswordEntryKeyboardHelper.java b/core/java/com/android/internal/widget/PasswordEntryKeyboardHelper.java index 01df48acd144..2e7810fa1139 100644 --- a/core/java/com/android/internal/widget/PasswordEntryKeyboardHelper.java +++ b/core/java/com/android/internal/widget/PasswordEntryKeyboardHelper.java @@ -26,6 +26,7 @@ import android.os.SystemClock; import android.os.Vibrator; import android.provider.Settings; import android.util.Log; +import android.view.HapticFeedbackConstants; import android.view.KeyCharacterMap; import android.view.KeyEvent; import android.view.View; @@ -52,7 +53,7 @@ public class PasswordEntryKeyboardHelper implements OnKeyboardActionListener { private final View mTargetView; private final KeyboardView mKeyboardView; private long[] mVibratePattern; - private final Vibrator mVibrator; + private boolean mEnableHaptics = false; public PasswordEntryKeyboardHelper(Context context, KeyboardView keyboardView, View targetView) { this(context, keyboardView, targetView, true); @@ -71,7 +72,10 @@ public class PasswordEntryKeyboardHelper implements OnKeyboardActionListener { mKeyboardView.getLayoutParams().height); } mKeyboardView.setOnKeyboardActionListener(this); - mVibrator = new Vibrator(); + } + + public void setEnableHaptics(boolean enabled) { + mEnableHaptics = enabled; } public boolean isAlpha() { @@ -230,6 +234,7 @@ public class PasswordEntryKeyboardHelper implements OnKeyboardActionListener { public void handleBackspace() { sendDownUpKeyEvents(KeyEvent.KEYCODE_DEL); + performHapticFeedback(); } private void handleShift() { @@ -272,8 +277,14 @@ public class PasswordEntryKeyboardHelper implements OnKeyboardActionListener { } public void onPress(int primaryCode) { - if (mVibratePattern != null) { - mVibrator.vibrate(mVibratePattern, -1); + performHapticFeedback(); + } + + private void performHapticFeedback() { + if (mEnableHaptics) { + mKeyboardView.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY, + HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING + | HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); } } diff --git a/core/res/res/drawable-hdpi/list_selector_background_disabled.9.png b/core/res/res/drawable-hdpi/list_selector_background_disabled.9.png Binary files differindex 9e1c42a675ba..f8092ea3d40c 100755..100644 --- a/core/res/res/drawable-hdpi/list_selector_background_disabled.9.png +++ b/core/res/res/drawable-hdpi/list_selector_background_disabled.9.png diff --git a/core/res/res/drawable-hdpi/list_selector_background_focus.9.png b/core/res/res/drawable-hdpi/list_selector_background_focus.9.png Binary files differindex 5563c80d1e98..3a21d356fb65 100755..100644 --- a/core/res/res/drawable-hdpi/list_selector_background_focus.9.png +++ b/core/res/res/drawable-hdpi/list_selector_background_focus.9.png diff --git a/core/res/res/drawable-hdpi/list_selector_background_longpress.9.png b/core/res/res/drawable-hdpi/list_selector_background_longpress.9.png Binary files differindex 72d3a08484f9..19558e93c8bd 100755..100644 --- a/core/res/res/drawable-hdpi/list_selector_background_longpress.9.png +++ b/core/res/res/drawable-hdpi/list_selector_background_longpress.9.png diff --git a/core/res/res/drawable-hdpi/list_selector_background_pressed.9.png b/core/res/res/drawable-hdpi/list_selector_background_pressed.9.png Binary files differindex 7568b30c22e2..0f3b4443c530 100755..100644 --- a/core/res/res/drawable-hdpi/list_selector_background_pressed.9.png +++ b/core/res/res/drawable-hdpi/list_selector_background_pressed.9.png diff --git a/core/res/res/drawable-mdpi/list_selector_background_disabled.9.png b/core/res/res/drawable-mdpi/list_selector_background_disabled.9.png Binary files differindex 43c36cb9e1d2..dbe395377615 100644 --- a/core/res/res/drawable-mdpi/list_selector_background_disabled.9.png +++ b/core/res/res/drawable-mdpi/list_selector_background_disabled.9.png diff --git a/core/res/res/drawable-mdpi/list_selector_background_focus.9.png b/core/res/res/drawable-mdpi/list_selector_background_focus.9.png Binary files differindex 53a7eaccbee3..da625af3b817 100644 --- a/core/res/res/drawable-mdpi/list_selector_background_focus.9.png +++ b/core/res/res/drawable-mdpi/list_selector_background_focus.9.png diff --git a/core/res/res/drawable-mdpi/list_selector_background_longpress.9.png b/core/res/res/drawable-mdpi/list_selector_background_longpress.9.png Binary files differindex 0818761cb2c8..fbf7ef031a90 100644 --- a/core/res/res/drawable-mdpi/list_selector_background_longpress.9.png +++ b/core/res/res/drawable-mdpi/list_selector_background_longpress.9.png diff --git a/core/res/res/drawable-mdpi/list_selector_background_pressed.9.png b/core/res/res/drawable-mdpi/list_selector_background_pressed.9.png Binary files differindex 8bd86b2b81b3..dd2a02477db7 100644 --- a/core/res/res/drawable-mdpi/list_selector_background_pressed.9.png +++ b/core/res/res/drawable-mdpi/list_selector_background_pressed.9.png diff --git a/core/res/res/drawable-xhdpi/list_selector_background_disabled.9.png b/core/res/res/drawable-xhdpi/list_selector_background_disabled.9.png Binary files differindex d599976c634c..980bbd73775c 100644 --- a/core/res/res/drawable-xhdpi/list_selector_background_disabled.9.png +++ b/core/res/res/drawable-xhdpi/list_selector_background_disabled.9.png diff --git a/core/res/res/drawable-xhdpi/list_selector_background_focus.9.png b/core/res/res/drawable-xhdpi/list_selector_background_focus.9.png Binary files differindex 17987f39a093..79c457756aad 100644 --- a/core/res/res/drawable-xhdpi/list_selector_background_focus.9.png +++ b/core/res/res/drawable-xhdpi/list_selector_background_focus.9.png diff --git a/core/res/res/drawable-xhdpi/list_selector_background_longpress.9.png b/core/res/res/drawable-xhdpi/list_selector_background_longpress.9.png Binary files differindex 5a64592d3784..73fc7839d559 100644 --- a/core/res/res/drawable-xhdpi/list_selector_background_longpress.9.png +++ b/core/res/res/drawable-xhdpi/list_selector_background_longpress.9.png diff --git a/core/res/res/drawable-xhdpi/list_selector_background_pressed.9.png b/core/res/res/drawable-xhdpi/list_selector_background_pressed.9.png Binary files differindex 1593577a406c..5b3ebe1b940b 100644 --- a/core/res/res/drawable-xhdpi/list_selector_background_pressed.9.png +++ b/core/res/res/drawable-xhdpi/list_selector_background_pressed.9.png diff --git a/core/res/res/layout/volume_adjust_item.xml b/core/res/res/layout/volume_adjust_item.xml index fb900f741ec6..d3fa7e93b565 100644 --- a/core/res/res/layout/volume_adjust_item.xml +++ b/core/res/res/layout/volume_adjust_item.xml @@ -27,7 +27,6 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="16dip" - android:layout_marginLeft="8dip" android:background="?attr/selectableItemBackground" /> @@ -38,8 +37,6 @@ android:layout_height="wrap_content" android:layout_weight="1" android:padding="16dip" - android:layout_marginRight="8dip" /> + android:layout_marginRight="16dip" /> </LinearLayout> - - diff --git a/docs/html/guide/guide_toc.cs b/docs/html/guide/guide_toc.cs index 2f50ce7ccb08..f3540e272e96 100644 --- a/docs/html/guide/guide_toc.cs +++ b/docs/html/guide/guide_toc.cs @@ -233,23 +233,32 @@ </ul> <ul> - <li class="toggle-list"> + <li class="toggle-list"> <div><a href="<?cs var:toroot ?>guide/topics/graphics/index.html"> <span class="en">Graphics</span> - </a></div> + </a><span class="new-child">new!</span></div> <ul> <li><a href="<?cs var:toroot ?>guide/topics/graphics/2d-graphics.html"> - <span class="en">2D Graphics</span> - </a></li> + <span class="en">Canvas and Drawables</span></a></li> + <li><a href="<?cs var:toroot ?>guide/topics/graphics/hardware-accel.html"> + <span class="en">Hardware Acceleration</span></a> + <span class="new">new!</span></li> <li><a href="<?cs var:toroot ?>guide/topics/graphics/opengl.html"> - <span class="en">3D with OpenGL</span> - </a></li> - <li><a href="<?cs var:toroot ?>guide/topics/graphics/animation.html"> - <span class="en">Property Animation</span> - </a></li> + <span class="en">OpenGL</span> + </a><span class="new">updated</span></li> + </ul> + </li> + <li class="toggle-list"> + <div><a href="<?cs var:toroot ?>guide/topics/graphics/animation.html"> + <span class="en">Animation</span> + </a></div> + <ul> + <li><a href="<?cs var:toroot ?>guide/topics/graphics/prop-animation.html"> + <span class="en">Property Animation</span></a></li> <li><a href="<?cs var:toroot ?>guide/topics/graphics/view-animation.html"> - <span class="en">View Animation</span> - </a></li> + <span class="en">View Animation</span></a></li> + <li><a href="<?cs var:toroot ?>guide/topics/graphics/drawable-animation.html"> + <span class="en">Drawable Animation</span></a></li> </ul> </li> <li class="toggle-list"> @@ -258,7 +267,7 @@ </a></div> <ul> <li><a href="<?cs var:toroot ?>guide/topics/renderscript/graphics.html"> - <span class="en">3D Graphics</span> + <span class="en">Graphics</span> </a> </li> <li><a href="<?cs var:toroot ?>guide/topics/renderscript/compute.html"> diff --git a/docs/html/guide/practices/screen-compat-mode.jd b/docs/html/guide/practices/screen-compat-mode.jd index a792386293d0..6a77d60f69fe 100644 --- a/docs/html/guide/practices/screen-compat-mode.jd +++ b/docs/html/guide/practices/screen-compat-mode.jd @@ -48,7 +48,7 @@ Mode</a>.</p> to resize for larger screens such as tablets. Since Android 1.6, Android has supported a variety of screen sizes and does most of the work to resize application layouts so that they properly fit each screen. However, if your application does not successfully follow the guide to -<a href="{@docRoot}guide/topics/practices/screens_support.html">Supporting Multiple Screens</a>, +<a href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple Screens</a>, then it might encounter some rendering issues on larger screens. For applications with this problem, screen compatibility mode can make the application a little more usable on larger screens.</p> @@ -83,7 +83,7 @@ which will usually cause artifacts such as blurring and pixelation in your UI. <p>This was introduced with Android 3.2 to further assist applications on the latest tablet devices when the applications have not yet implemented techniques for <a -href="{@docRoot}guide/topics/practices/screens_support.html">Supporting Multiple +href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple Screens</a>.</p> <p>In general, large screen devices running Android 3.2 or higher allow users to enable screen compatibility mode when the application does not <strong>explicitly declare that it supports @@ -211,7 +211,7 @@ href="{@docRoot}guide/topics/manifest/supports-screens-element.html">{@code which you should want your application to run—it causes pixelation and blurring in your UI, due to zooming. The proper way to make your application work well on large screens is to follow the guide to <a -href="{@docRoot}guide/topics/practices/screens_support.html">Supporting Multiple Screens</a> and +href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple Screens</a> and provide alternative layouts for different screen sizes.</p> <p>By default, when you've set either <a diff --git a/docs/html/guide/topics/manifest/activity-element.jd b/docs/html/guide/topics/manifest/activity-element.jd index 5a9313e7f70c..02a8a8e42505 100644 --- a/docs/html/guide/topics/manifest/activity-element.jd +++ b/docs/html/guide/topics/manifest/activity-element.jd @@ -10,8 +10,8 @@ parent.link=manifest-intro.html android:<a href="#clear">clearTaskOnLaunch</a>=["true" | "false"] android:<a href="#config">configChanges</a>=["mcc", "mnc", "locale", "touchscreen", "keyboard", "keyboardHidden", - "navigation", "orientation", "screenLayout", - "fontScale", "uiMode"] + "navigation", "screenLayout", "fontScale", "uiMode", + "orientation", "screenSize", "smallestScreenSize"] android:<a href="#enabled">enabled</a>=["true" | "false"] android:<a href="#exclude">excludeFromRecents</a>=["true" | "false"] android:<a href="#exported">exported</a>=["true" | "false"] @@ -205,10 +205,6 @@ separated by '{@code |}' — for example, "{@code locale|navigation|orientat <td>"{@code navigation}"</td> <td>The navigation type (trackball/dpad) has changed. (This should never normally happen.)</td> </tr><tr> - <td>"{@code orientation}"</td> - <td>The screen orientation has changed — the user has rotated - the device.</td> - </tr><tr> <td>"{@code screenLayout}"</td> <td>The screen layout has changed — this might be caused by a different display being activated.</td> @@ -221,7 +217,34 @@ separated by '{@code |}' — for example, "{@code locale|navigation|orientat <td>The user interface mode has changed — this can be caused when the user places the device into a desk/car dock or when the the night mode changes. See {@link android.app.UiModeManager}. <em>Introduced in API Level 8</em>.</td> - </tr> + </tr><tr> + <td>"{@code orientation}"</td> + <td>The screen orientation has changed — the user has rotated the device. + <p class="note"><strong>Note:</strong> If your application targets API level 13 or higher (as +declared by the <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code +minSdkVersion}</a> and <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code +targetSdkVersion}</a> attributes), then you should also declare the {@code "screenSize"} +configuration, because it also changes when a device switches between portrait and landscape +orientations.</p></td> + </tr><tr> + <td>"{@code screenSize}"</td> + <td>The current available screen size has changed. This represents a change in the currently +available size, relative to the current aspect ratio, so will change when the user switches between +landscape and portrait. However, if your application targets API level 12 or lower, then your +activity always handles this configuration change itself (this configuration change does not restart +your activity, even when running on an Android 3.2 or higher device). + <p><em>Added in API level 13.</em></p></td> + </tr><tr> + <td>"{@code smallestScreenSize}"</td> + <td>The physical screen size has changed. This represents a change in size regardless of +orientation, so will only change when the actual physical screen size has changed such as switching +to an external display. A change to this configuration corresponds to a change in the <a +href="{@docRoot}guide/topics/resources/providing-resources.html#SmallestScreenWidthQualifier"> +smallestWidth configuration</a>. However, if your application targets API level 12 or lower, then +your activity always handles this configuration change itself (this configuration change does not +restart your activity, even when running on an Android 3.2 or higher device). + <p><em>Added in API level 13.</em></p></td> + </tr> </table> <p> diff --git a/docs/html/guide/topics/resources/runtime-changes.jd b/docs/html/guide/topics/resources/runtime-changes.jd index 74a90735bf66..871b06320cde 100644 --- a/docs/html/guide/topics/resources/runtime-changes.jd +++ b/docs/html/guide/topics/resources/runtime-changes.jd @@ -25,80 +25,78 @@ Orientation Change</a></li> <p>Some device configurations can change during runtime (such as screen orientation, keyboard availability, and language). When such a change occurs, Android restarts the running -Activity ({@link android.app.Activity#onDestroy()} is called, followed by {@link +{@link android.app.Activity} ({@link android.app.Activity#onDestroy()} is called, followed by {@link android.app.Activity#onCreate(Bundle) onCreate()}). The restart behavior is designed to help your application adapt to new configurations by automatically reloading your application with -alternative resources.</p> +alternative resources that match the new device configuration.</p> -<p>To properly handle a restart, it is important that your Activity restores its previous +<p>To properly handle a restart, it is important that your activity restores its previous state through the normal <a href="{@docRoot}guide/topics/fundamentals/activities.html#Lifecycle">Activity lifecycle</a>, in which Android calls {@link android.app.Activity#onSaveInstanceState(Bundle) onSaveInstanceState()} before it destroys -your Activity so that you can save data about the application state. You can then restore the state +your activity so that you can save data about the application state. You can then restore the state during {@link android.app.Activity#onCreate(Bundle) onCreate()} or {@link -android.app.Activity#onRestoreInstanceState(Bundle) onRestoreInstanceState()}. To test -that your application restarts itself with the application state intact, you should -invoke configuration changes (such as changing the screen orientation) while performing various -tasks in your application.</p> +android.app.Activity#onRestoreInstanceState(Bundle) onRestoreInstanceState()}.</p> -<p>Your application should be able to restart at any time without loss of user data or -state in order to handle events such as when the user receives an incoming phone call and then -returns to your application (read about the -<a href="{@docRoot}guide/topics/fundamentals/activities.html#Lifecycle">Activity lifecycle</a>).</p> +<p>To test that your application restarts itself with the application state intact, you should +invoke configuration changes (such as changing the screen orientation) while performing various +tasks in your application. Your application should be able to restart at any time without loss of +user data or state in order to handle events such as configuration changes or when the user receives +an incoming phone call and then returns to your application much later after your application +process may have been destroyed. To learn how you can restore your activity state, read about the <a +href="{@docRoot}guide/topics/fundamentals/activities.html#Lifecycle">Activity lifecycle</a>.</p> <p>However, you might encounter a situation in which restarting your application and restoring significant amounts of data can be costly and create a poor user experience. In such a -situation, you have two options:</p> +situation, you have two other options:</p> <ol type="a"> <li><a href="#RetainingAnObject">Retain an object during a configuration change</a> - <p>Allow your Activity to restart when a configuration changes, but carry a stateful -{@link java.lang.Object} to the new instance of your Activity.</p> + <p>Allow your activity to restart when a configuration changes, but carry a stateful +{@link java.lang.Object} to the new instance of your activity.</p> </li> <li><a href="#HandlingTheChange">Handle the configuration change yourself</a> - <p>Prevent the system from restarting your Activity during certain configuration -changes and receive a callback when the configurations do change, so that you can manually update -your Activity as necessary.</p> + <p>Prevent the system from restarting your activity during certain configuration +changes, but receive a callback when the configurations do change, so that you can manually update +your activity as necessary.</p> </li> </ol> <h2 id="RetainingAnObject">Retaining an Object During a Configuration Change</h2> -<p>If restarting your Activity requires that you recover large sets of data, re-establish a -network connection, or perform other intensive operations, then a full restart due to a -configuration change might -be an unpleasant user experience. Also, it may not be possible for you to completely -maintain your Activity state with the {@link android.os.Bundle} that the system saves for you during -the Activity lifecycle—it is not designed to carry large objects (such as bitmaps) and the -data within it must be serialized then deserialized, which can consume a lot of memory and make the -configuration change slow. In such a situation, you can alleviate the burden of reinitializing -your Activity by retaining a stateful Object when your Activity is restarted due to a configuration -change.</p> - -<p>To retain an Object during a runtime configuration change:</p> +<p>If restarting your activity requires that you recover large sets of data, re-establish a network +connection, or perform other intensive operations, then a full restart due to a configuration change +might be a slow user experience. Also, it might not be possible for you to completely restore your +activity state with the {@link android.os.Bundle} that the system saves for you with the {@link +android.app.Activity#onSaveInstanceState(Bundle) onSaveInstanceState()} callback—it is not +designed to carry large objects (such as bitmaps) and the data within it must be serialized then +deserialized, which can consume a lot of memory and make the configuration change slow. In such a +situation, you can alleviate the burden of reinitializing your activity by retaining a stateful +{@link java.lang.Object} when your activity is restarted due to a configuration change.</p> + +<p>To retain an object during a runtime configuration change:</p> <ol> <li>Override the {@link android.app.Activity#onRetainNonConfigurationInstance()} method to return -the Object you would like to retain.</li> - <li>When your Activity is created again, call {@link -android.app.Activity#getLastNonConfigurationInstance()} to recover your Object.</li> +the object you would like to retain.</li> + <li>When your activity is created again, call {@link +android.app.Activity#getLastNonConfigurationInstance()} to recover your object.</li> </ol> -<p>Android calls {@link android.app.Activity#onRetainNonConfigurationInstance()} between {@link -android.app.Activity#onStop()} and {@link -android.app.Activity#onDestroy()} when it shuts down your Activity due to a configuration -change. In your implementation of {@link -android.app.Activity#onRetainNonConfigurationInstance()}, you can return any {@link -java.lang.Object} that you need in order to efficiently restore your state after the configuration -change.</p> +<p>When the Android system shuts down your activity due to a configuration change, it calls {@link +android.app.Activity#onRetainNonConfigurationInstance()} between the {@link +android.app.Activity#onStop()} and {@link android.app.Activity#onDestroy()} callbacks. In your +implementation of {@link android.app.Activity#onRetainNonConfigurationInstance()}, you can return +any {@link java.lang.Object} that you need in order to efficiently restore your state after the +configuration change.</p> <p>A scenario in which this can be valuable is if your application loads a lot of data from the -web. If the user changes the orientation of the device and the Activity restarts, your application +web. If the user changes the orientation of the device and the activity restarts, your application must re-fetch the data, which could be slow. What you can do instead is implement {@link android.app.Activity#onRetainNonConfigurationInstance()} to return an object carrying your -data and then retrieve the data when your Activity starts again with {@link +data and then retrieve the data when your activity starts again with {@link android.app.Activity#getLastNonConfigurationInstance()}. For example:</p> <pre> @@ -113,11 +111,11 @@ public Object onRetainNonConfigurationInstance() { should never pass an object that is tied to the {@link android.app.Activity}, such as a {@link android.graphics.drawable.Drawable}, an {@link android.widget.Adapter}, a {@link android.view.View} or any other object that's associated with a {@link android.content.Context}. If you do, it will -leak all the Views and resources of the original Activity instance. (To leak the resources +leak all the views and resources of the original activity instance. (Leaking resources means that your application maintains a hold on them and they cannot be garbage-collected, so lots of memory can be lost.)</p> -<p>Then retrieve the {@code data} when your Activity starts again:</p> +<p>Then retrieve the data when your activity starts again:</p> <pre> @Override @@ -133,11 +131,10 @@ public void onCreate(Bundle savedInstanceState) { } </pre> -<p>In this case, {@link android.app.Activity#getLastNonConfigurationInstance()} retrieves -the data saved by {@link android.app.Activity#onRetainNonConfigurationInstance()}. If {@code data} -is null (which happens when the -Activity starts due to any reason other than a configuration change) then the data object is loaded -from the original source.</p> +<p>In this case, {@link android.app.Activity#getLastNonConfigurationInstance()} returns the data +saved by {@link android.app.Activity#onRetainNonConfigurationInstance()}. If {@code data} is null +(which happens when the activity starts due to any reason other than a configuration change) then +this code loads the data object from the original source.</p> @@ -147,27 +144,27 @@ from the original source.</p> <p>If your application doesn't need to update resources during a specific configuration change <em>and</em> you have a performance limitation that requires you to -avoid the Activity restart, then you can declare that your Activity handles the configuration change -itself, which prevents the system from restarting your Activity.</p> +avoid the activity restart, then you can declare that your activity handles the configuration change +itself, which prevents the system from restarting your activity.</p> <p class="note"><strong>Note:</strong> Handling the configuration change yourself can make it much more difficult to use alternative resources, because the system does not automatically apply them -for you. This technique should be considered a last resort and is not recommended for most -applications.</p> +for you. This technique should be considered a last resort when you must avoid restarts due to a +configuration change and is not recommended for most applications.</p> -<p>To declare that your Activity handles a configuration change, edit the appropriate <a -href="{@docRoot}guide/topics/manifest/activity-element.html">{@code <activity>}</a> element -in your manifest file to include the <a +<p>To declare that your activity handles a configuration change, edit the appropriate <a +href="{@docRoot}guide/topics/manifest/activity-element.html">{@code <activity>}</a> element in +your manifest file to include the <a +href="{@docRoot}guide/topics/manifest/activity-element.html#config">{@code +android:configChanges}</a> attribute with a value that represents the configuration you want to +handle. Possible values are listed in the documentation for the <a href="{@docRoot}guide/topics/manifest/activity-element.html#config">{@code -android:configChanges}</a> attribute with a string value that represents the configuration that you -want to handle. Possible values are listed in the documentation for -the <a href="{@docRoot}guide/topics/manifest/activity-element.html#config">{@code -android:configChanges}</a> attribute (the most commonly used values are {@code orientation} to -handle when the screen orientation changes and {@code keyboardHidden} to handle when the -keyboard availability changes). You can declare multiple configuration values in the attribute -by separating them with a pipe character ("|").</p> - -<p>For example, the following manifest snippet declares an Activity that handles both the +android:configChanges}</a> attribute (the most commonly used values are {@code "orientation"} to +prevent restarts when the screen orientation changes and {@code "keyboardHidden"} to prevent +restarts when the keyboard availability changes). You can declare multiple configuration values in +the attribute by separating them with a pipe {@code |} character.</p> + +<p>For example, the following manifest code declares an activity that handles both the screen orientation change and keyboard availability change:</p> <pre> @@ -176,20 +173,32 @@ screen orientation change and keyboard availability change:</p> android:label="@string/app_name"> </pre> -<p>Now when one of these configurations change, {@code MyActivity} is not restarted. -Instead, the Activity receives a call to {@link +<p>Now, when one of these configurations change, {@code MyActivity} does not restart. +Instead, the {@code MyActivity} receives a call to {@link android.app.Activity#onConfigurationChanged(Configuration) onConfigurationChanged()}. This method is passed a {@link android.content.res.Configuration} object that specifies the new device configuration. By reading fields in the {@link android.content.res.Configuration}, you can determine the new configuration and make appropriate changes by updating the resources used in your interface. At the -time this method is called, your Activity's {@link android.content.res.Resources} object is updated +time this method is called, your activity's {@link android.content.res.Resources} object is updated to return resources based on the new configuration, so you can easily -reset elements of your UI without the system restarting your Activity.</p> +reset elements of your UI without the system restarting your activity.</p> + +<p class="caution"><strong>Caution:</strong> Beginning with Android 3.2 (API level 13), <strong>the +"screen size" also changes</strong> when the device switches between portrait and landscape +orientation. Thus, if you want to prevent runtime restarts due to orientation change when developing +for API level 13 or higher (as declared by the <a +href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code minSdkVersion}</a> and <a +href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code targetSdkVersion}</a> +attributes), you must include the {@code "screenSize"} value in addition to the {@code +"orientation"} value. That is, you must decalare {@code +android:configChanges="orientation|screenSize"}. However, if your application targets API level +12 or lower, then your activity always handles this configuration change itself (this configuration +change does not restart your activity, even when running on an Android 3.2 or higher device).</p> <p>For example, the following {@link android.app.Activity#onConfigurationChanged(Configuration) onConfigurationChanged()} implementation -checks the availability of a hardware keyboard and the current device orientation:</p> +checks the current device orientation:</p> <pre> @Override @@ -202,12 +211,6 @@ public void onConfigurationChanged(Configuration newConfig) { } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){ Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show(); } - // Checks whether a hardware keyboard is available - if (newConfig.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO) { - Toast.makeText(this, "keyboard visible", Toast.LENGTH_SHORT).show(); - } else if (newConfig.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_YES) { - Toast.makeText(this, "keyboard hidden", Toast.LENGTH_SHORT).show(); - } } </pre> @@ -216,7 +219,8 @@ configurations, not just the ones that have changed. Most of the time, you won't the configuration has changed and can simply re-assign all your resources that provide alternatives to the configuration that you're handling. For example, because the {@link android.content.res.Resources} object is now updated, you can reset -any {@link android.widget.ImageView}s with {@link android.widget.ImageView#setImageResource(int)} +any {@link android.widget.ImageView}s with {@link android.widget.ImageView#setImageResource(int) +setImageResource()} and the appropriate resource for the new configuration is used (as described in <a href="providing-resources.html#AlternateResources">Providing Resources</a>).</p> @@ -226,9 +230,9 @@ from the {@link android.content.res.Configuration} class. For documentation abou to use with each field, refer to the appropriate field in the {@link android.content.res.Configuration} reference.</p> -<p class="note"><strong>Remember:</strong> When you declare your Activity to handle a configuration +<p class="note"><strong>Remember:</strong> When you declare your activity to handle a configuration change, you are responsible for resetting any elements for which you provide alternatives. If you -declare your Activity to handle the orientation change and have images that should change +declare your activity to handle the orientation change and have images that should change between landscape and portrait, you must re-assign each resource to each element during {@link android.app.Activity#onConfigurationChanged(Configuration) onConfigurationChanged()}.</p> @@ -236,13 +240,14 @@ android.app.Activity#onConfigurationChanged(Configuration) onConfigurationChange changes, you can instead <em>not</em> implement {@link android.app.Activity#onConfigurationChanged(Configuration) onConfigurationChanged()}. In which case, all of the resources used before the configuration change are still used -and you've only avoided the restart of your Activity. However, your application should always be -able to shutdown and restart with its previous state intact. Not only because -there are other configuration changes that you cannot prevent from restarting your application but -also in order to handle events such as when the user receives an incoming phone call and then -returns to your application.</p> - -<p>For more about which configuration changes you can handle in your Activity, see the <a +and you've only avoided the restart of your activity. However, your application should always be +able to shutdown and restart with its previous state intact, so you should not consider this +technique an escape from retaining your state during normal activity lifecycle. Not only because +there are other configuration changes that you cannot prevent from restarting your application, but +also because you should handle events such as when the user leaves your application and it gets +destroyed before the user returns to it.</p> + +<p>For more about which configuration changes you can handle in your activity, see the <a href="{@docRoot}guide/topics/manifest/activity-element.html#config">{@code android:configChanges}</a> documentation and the {@link android.content.res.Configuration} class.</p> diff --git a/include/camera/CameraParameters.h b/include/camera/CameraParameters.h index cd2c0a37aa3e..ef4cf5c705fc 100644 --- a/include/camera/CameraParameters.h +++ b/include/camera/CameraParameters.h @@ -283,7 +283,8 @@ public: // outside the current field of view, even when using zoom. // // Focus area only has effect if the current focus mode is FOCUS_MODE_AUTO, - // FOCUS_MODE_MACRO, or FOCUS_MODE_CONTINOUS_VIDEO. + // FOCUS_MODE_MACRO, FOCUS_MODE_CONTINUOUS_VIDEO, or + // FOCUS_MODE_CONTINUOUS_PICTURE. // Example value: "(-10,-10,0,0,300),(0,0,10,10,700)". Read/write. static const char KEY_FOCUS_AREAS[]; // Focal length in millimeter. @@ -629,19 +630,29 @@ public: // recording because the focus changes smoothly . Applications still can // call CameraHardwareInterface.takePicture in this mode but the subject may // not be in focus. Auto focus starts when the parameter is set. - // Applications should not call CameraHardwareInterface.autoFocus in this - // mode. To stop continuous focus, applications should change the focus mode - // to other modes. + // + // Applications can call CameraHardwareInterface.autoFocus in this mode. The + // focus callback will immediately return with a boolean that indicates + // whether the focus is sharp or not. The focus position is locked after + // autoFocus call. If applications want to resume the continuous focus, + // cancelAutoFocus must be called. Restarting the preview will not resume + // the continuous autofocus. To stop continuous focus, applications should + // change the focus mode to other modes. static const char FOCUS_MODE_CONTINUOUS_VIDEO[]; // Continuous auto focus mode intended for taking pictures. The camera // continuously tries to focus. The speed of focus change is more aggressive // than FOCUS_MODE_CONTINUOUS_VIDEO. Auto focus starts when the parameter is - // set. If applications call autoFocus in this mode, the focus callback will - // immediately return with a boolean that indicates the focus is sharp or - // not. The apps can then decide if they want to take a picture immediately - // or to change the focus mode to auto, and run a full autofocus cycle. To - // stop continuous focus, applications should change the focus mode to other - // modes. + // set. + // + // If applications call CameraHardwareInterface.autoFocus in this mode, the + // focus callback will immediately return with a boolean that indicates + // whether the focus is sharp or not. The apps can then decide if they want + // to take a picture immediately or to change the focus mode to auto, and + // run a full autofocus cycle. The focus position is locked after autoFocus + // call. If applications want to resume the continuous focus, + // cancelAutoFocus must be called. Restarting the preview will not resume + // the continuous autofocus. To stop continuous focus, applications should + // change the focus mode to other modes. static const char FOCUS_MODE_CONTINUOUS_PICTURE[]; private: diff --git a/media/mtp/MtpServer.cpp b/media/mtp/MtpServer.cpp index a9b539b022a6..dc6c0119e908 100644 --- a/media/mtp/MtpServer.cpp +++ b/media/mtp/MtpServer.cpp @@ -947,7 +947,12 @@ MtpResponseCode MtpServer::doSendObject() { if (mSendObjectFileSize - initialData > 0) { mfr.offset = initialData; - mfr.length = mSendObjectFileSize - initialData; + if (mSendObjectFileSize == 0xFFFFFFFF) { + // tell driver to read until it receives a short packet + mfr.length = 0xFFFFFFFF; + } else { + mfr.length = mSendObjectFileSize - initialData; + } LOGV("receiving %s\n", (const char *)mSendObjectFilePath); // transfer the file diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java index 5b4c33e1890d..d3c4a6143c30 100644 --- a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java @@ -483,7 +483,8 @@ public class RecentsPanelView extends RelativeLayout } else { Intent intent = ad.intent; intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY - | Intent.FLAG_ACTIVITY_TASK_ON_HOME); + | Intent.FLAG_ACTIVITY_TASK_ON_HOME + | Intent.FLAG_ACTIVITY_NEW_TASK); if (DEBUG) Log.v(TAG, "Starting activity " + intent); context.startActivity(intent); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java index e3a64a88b737..694da2088354 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java @@ -116,15 +116,13 @@ public class NavigationBarView extends LinearLayout { mDisabledFlags = disabledFlags; - final boolean disableNavigation = ((disabledFlags & View.STATUS_BAR_DISABLE_NAVIGATION) != 0); + final boolean disableHome = ((disabledFlags & View.STATUS_BAR_DISABLE_HOME) != 0); + final boolean disableRecent = ((disabledFlags & View.STATUS_BAR_DISABLE_RECENT) != 0); final boolean disableBack = ((disabledFlags & View.STATUS_BAR_DISABLE_BACK) != 0); getBackButton() .setVisibility(disableBack ? View.INVISIBLE : View.VISIBLE); - getHomeButton() .setVisibility(disableNavigation ? View.INVISIBLE : View.VISIBLE); - getRecentsButton().setVisibility(disableNavigation ? View.INVISIBLE : View.VISIBLE); - - getMenuButton() .setVisibility((disableNavigation || !mShowMenu) - ? View.INVISIBLE : View.VISIBLE); + getHomeButton() .setVisibility(disableHome ? View.INVISIBLE : View.VISIBLE); + getRecentsButton().setVisibility(disableRecent ? View.INVISIBLE : View.VISIBLE); } public void setMenuVisibility(final boolean show) { @@ -136,9 +134,7 @@ public class NavigationBarView extends LinearLayout { mShowMenu = show; - getMenuButton().setVisibility( - (0 != (mDisabledFlags & View.STATUS_BAR_DISABLE_NAVIGATION) || !mShowMenu) - ? View.INVISIBLE : View.VISIBLE); + getMenuButton().setVisibility(mShowMenu ? View.VISIBLE : View.INVISIBLE); } public void setLowProfile(final boolean lightsOut) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java index e54de59ced75..9c8c229f8dbc 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -300,18 +300,6 @@ public class PhoneStatusBar extends StatusBar { (NavigationBarView) View.inflate(context, R.layout.navigation_bar, null); mNavigationBarView.setDisabledFlags(mDisabled); - - sb.setOnSystemUiVisibilityChangeListener( - new View.OnSystemUiVisibilityChangeListener() { - @Override - public void onSystemUiVisibilityChange(int visibility) { - if (DEBUG) { - Slog.d(TAG, "systemUi: " + visibility); - } - boolean hide = (0 != (visibility & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION)); - mNavigationBarView.setHidden(hide); - } - }); } } catch (Resources.NotFoundException ex) { // no nav bar for you @@ -1064,10 +1052,12 @@ public class PhoneStatusBar extends StatusBar { flagdbg.append(((diff & StatusBarManager.DISABLE_NOTIFICATION_TICKER) != 0) ? "* " : " "); flagdbg.append(((state & StatusBarManager.DISABLE_SYSTEM_INFO) != 0) ? "SYSTEM_INFO" : "system_info"); flagdbg.append(((diff & StatusBarManager.DISABLE_SYSTEM_INFO) != 0) ? "* " : " "); - flagdbg.append(((state & StatusBarManager.DISABLE_NAVIGATION) != 0) ? "NAVIGATION" : "navigation"); - flagdbg.append(((diff & StatusBarManager.DISABLE_NAVIGATION) != 0) ? "* " : " "); flagdbg.append(((state & StatusBarManager.DISABLE_BACK) != 0) ? "BACK" : "back"); flagdbg.append(((diff & StatusBarManager.DISABLE_BACK) != 0) ? "* " : " "); + flagdbg.append(((state & StatusBarManager.DISABLE_HOME) != 0) ? "HOME" : "home"); + flagdbg.append(((diff & StatusBarManager.DISABLE_HOME) != 0) ? "* " : " "); + flagdbg.append(((state & StatusBarManager.DISABLE_RECENT) != 0) ? "RECENT" : "recent"); + flagdbg.append(((diff & StatusBarManager.DISABLE_RECENT) != 0) ? "* " : " "); flagdbg.append(((state & StatusBarManager.DISABLE_CLOCK) != 0) ? "CLOCK" : "clock"); flagdbg.append(((diff & StatusBarManager.DISABLE_CLOCK) != 0) ? "* " : " "); flagdbg.append(">"); @@ -1083,11 +1073,13 @@ public class PhoneStatusBar extends StatusBar { } } - if ((diff & (StatusBarManager.DISABLE_NAVIGATION | StatusBarManager.DISABLE_BACK)) != 0) { - // the nav bar will take care of DISABLE_NAVIGATION and DISABLE_BACK + if ((diff & (StatusBarManager.DISABLE_HOME + | StatusBarManager.DISABLE_RECENT + | StatusBarManager.DISABLE_BACK)) != 0) { + // the nav bar will take care of these if (mNavigationBarView != null) mNavigationBarView.setDisabledFlags(state); - if ((state & StatusBarManager.DISABLE_NAVIGATION) != 0) { + if ((state & StatusBarManager.DISABLE_RECENT) != 0) { // close recents if it's visible mHandler.removeMessages(MSG_CLOSE_RECENTS_PANEL); mHandler.sendEmptyMessage(MSG_CLOSE_RECENTS_PANEL); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java index 271e508bd714..415a9a4bf265 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java @@ -964,34 +964,24 @@ public class TabletStatusBar extends StatusBar implements mTicker.halt(); } } - if ((diff & (StatusBarManager.DISABLE_NAVIGATION | StatusBarManager.DISABLE_BACK)) != 0) { - setNavigationVisibility(state & - (StatusBarManager.DISABLE_NAVIGATION | StatusBarManager.DISABLE_BACK)); + if ((diff & (StatusBarManager.DISABLE_RECENT + | StatusBarManager.DISABLE_BACK + | StatusBarManager.DISABLE_HOME)) != 0) { + setNavigationVisibility(state); } } private void setNavigationVisibility(int visibility) { - boolean disableNavigation = ((visibility & StatusBarManager.DISABLE_NAVIGATION) != 0); + boolean disableHome = ((visibility & StatusBarManager.DISABLE_HOME) != 0); + boolean disableRecent = ((visibility & StatusBarManager.DISABLE_RECENT) != 0); boolean disableBack = ((visibility & StatusBarManager.DISABLE_BACK) != 0); - Slog.i(TAG, "DISABLE_BACK: " + (disableBack ? "yes" : "no")); - Slog.i(TAG, "DISABLE_NAVIGATION: " + (disableNavigation ? "yes" : "no")); + mBackButton.setVisibility(disableBack ? View.INVISIBLE : View.VISIBLE); + mHomeButton.setVisibility(disableHome ? View.INVISIBLE : View.VISIBLE); + mRecentButton.setVisibility(disableRecent ? View.INVISIBLE : View.VISIBLE); - if (disableNavigation && disableBack) { - mNavigationArea.setVisibility(View.INVISIBLE); - } else { - int backVisiblity = (disableBack ? View.INVISIBLE : View.VISIBLE); - int navVisibility = (disableNavigation ? View.INVISIBLE : View.VISIBLE); - - mBackButton.setVisibility(backVisiblity); - mHomeButton.setVisibility(navVisibility); - mRecentButton.setVisibility(navVisibility); - // don't change menu button visibility here - - mNavigationArea.setVisibility(View.VISIBLE); - } - - mInputMethodSwitchButton.setScreenLocked(disableNavigation); + mInputMethodSwitchButton.setScreenLocked( + (visibility & StatusBarManager.DISABLE_SYSTEM_INFO) != 0); } private boolean hasTicker(Notification n) { diff --git a/policy/src/com/android/internal/policy/impl/GlobalActions.java b/policy/src/com/android/internal/policy/impl/GlobalActions.java index 856914359517..11b6c15185d3 100644 --- a/policy/src/com/android/internal/policy/impl/GlobalActions.java +++ b/policy/src/com/android/internal/policy/impl/GlobalActions.java @@ -18,7 +18,6 @@ package com.android.internal.policy.impl; import android.app.Activity; import android.app.AlertDialog; -import android.app.StatusBarManager; import android.content.BroadcastReceiver; import android.content.Context; import android.content.DialogInterface; @@ -57,8 +56,6 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac private static final String TAG = "GlobalActions"; - private StatusBarManager mStatusBar; - private final Context mContext; private final AudioManager mAudioManager; @@ -103,13 +100,12 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac mKeyguardShowing = keyguardShowing; mDeviceProvisioned = isDeviceProvisioned; if (mDialog == null) { - mStatusBar = (StatusBarManager)mContext.getSystemService(Context.STATUS_BAR_SERVICE); mDialog = createDialog(); } prepareDialog(); - mStatusBar.disable(StatusBarManager.DISABLE_EXPAND); mDialog.show(); + mDialog.getWindow().getDecorView().setSystemUiVisibility(View.STATUS_BAR_DISABLE_EXPAND); } /** @@ -249,7 +245,6 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac /** {@inheritDoc} */ public void onDismiss(DialogInterface dialog) { - mStatusBar.disable(StatusBarManager.DISABLE_NONE); } /** {@inheritDoc} */ diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java b/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java index 59b546ddecfe..de156c9ba48f 100644 --- a/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java +++ b/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java @@ -50,8 +50,6 @@ public abstract class KeyguardViewBase extends FrameLayout { public KeyguardViewBase(Context context) { super(context); - setSystemUiVisibility(STATUS_BAR_DISABLE_BACK); - // This is a faster way to draw the background on devices without hardware acceleration setBackgroundDrawable(new Drawable() { @Override diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java b/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java index 90972da1b591..2fd165a93695 100644 --- a/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java +++ b/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java @@ -171,6 +171,17 @@ public class KeyguardViewManager implements KeyguardWindowController { } } + // Disable aspects of the system/status/navigation bars that are not appropriate or + // useful for the lockscreen but can be re-shown by dialogs or SHOW_WHEN_LOCKED activities. + // Other disabled bits are handled by the KeyguardViewMediator talking directly to the + // status bar service. + int visFlags = + ( View.STATUS_BAR_DISABLE_BACK + | View.STATUS_BAR_DISABLE_HOME + | View.STATUS_BAR_DISABLE_CLOCK + ); + mKeyguardHost.setSystemUiVisibility(visFlags); + mViewManager.updateViewLayout(mKeyguardHost, mWindowLayoutParams); mKeyguardHost.setVisibility(View.VISIBLE); mKeyguardView.requestFocus(); diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java index c25e3ca07814..bbfc5137cb8e 100644 --- a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java +++ b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java @@ -1188,19 +1188,12 @@ public class KeyguardViewMediator implements KeyguardViewCallback, } } + // Disable aspects of the system/status/navigation bars that must not be re-enabled by + // windows that appear on top, ever int flags = StatusBarManager.DISABLE_NONE; if (mShowing) { - // disable navigation status bar components if lock screen is up - flags |= StatusBarManager.DISABLE_NAVIGATION; - if (!mHidden) { - // showing lockscreen exclusively (no activities in front of it) - // disable back button too - flags |= StatusBarManager.DISABLE_BACK; - if (mUpdateMonitor.isClockVisible()) { - // lockscreen showing a clock, so hide statusbar clock - flags |= StatusBarManager.DISABLE_CLOCK; - } - } + // disable navigation status bar components (home, recents) if lock screen is up + flags |= StatusBarManager.DISABLE_RECENT; if (isSecure() || !ENABLE_INSECURE_STATUS_BAR_EXPAND) { // showing secure lockscreen; disable expanding. flags |= StatusBarManager.DISABLE_EXPAND; diff --git a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java index 265024be98b5..0c44e45884d7 100644 --- a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java +++ b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java @@ -117,9 +117,14 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler private final int MSG_SHOW_FACELOCK_AREA_VIEW = 0; private final int MSG_HIDE_FACELOCK_AREA_VIEW = 1; - // Long enough to stay black while dialer comes up - // Short enough to not be black if the user goes back immediately - private final int FACELOCK_VIEW_AREA_EMERGENCY_HIDE_TIMEOUT = 1000; + // Long enough to stay visible while dialer comes up + // Short enough to not be visible if the user goes back immediately + private final int FACELOCK_VIEW_AREA_EMERGENCY_DIALER_TIMEOUT = 1000; + + // Long enough to stay visible while the service starts + // Short enough to not have to wait long for backup if service fails to start or crashes + // The service can take a couple of seconds to start on the first try after boot + private final int FACELOCK_VIEW_AREA_SERVICE_TIMEOUT = 3000; /** * The current {@link KeyguardScreen} will use this to communicate back to us. @@ -128,6 +133,7 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler private boolean mRequiresSim; + private volatile boolean mEmergencyCall; /** @@ -268,6 +274,7 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler mUpdateMonitor = updateMonitor; mLockPatternUtils = lockPatternUtils; mWindowController = controller; + mEmergencyCall = false; mUpdateMonitor.registerInfoCallback(this); @@ -322,12 +329,12 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler } public void takeEmergencyCallAction() { + mEmergencyCall = true; // FaceLock must be stopped if it is running when emergency call is pressed stopAndUnbindFromFaceLock(); - // Delay hiding FaceLock area so unlock doesn't display while dialer is coming up - mHandler.sendEmptyMessageDelayed(MSG_HIDE_FACELOCK_AREA_VIEW, - FACELOCK_VIEW_AREA_EMERGENCY_HIDE_TIMEOUT); + // Continue showing FaceLock area until dialer comes up + showFaceLockAreaWithTimeout(FACELOCK_VIEW_AREA_EMERGENCY_DIALER_TIMEOUT); pokeWakelock(EMERGENCY_CALL_TIMEOUT); if (TelephonyManager.getDefault().getCallState() @@ -506,6 +513,7 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler public void onScreenTurnedOff() { mScreenOn = false; mForgotPattern = false; + mEmergencyCall = false; if (mMode == Mode.LockScreen) { ((KeyguardScreen) mLockScreen).onPause(); } else { @@ -525,11 +533,11 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler if (mUpdateMonitor.getPhoneState() == TelephonyManager.CALL_STATE_IDLE && transportInvisible) { bindToFaceLock(); - //Eliminate the black background so that the lockpattern will be visible - //If FaceUnlock is cancelled - mHandler.sendEmptyMessageDelayed(MSG_HIDE_FACELOCK_AREA_VIEW, 4000); + // Show FaceLock area, but only for a little bit so lockpattern will become visible if + // FaceLock fails to start or crashes + showFaceLockAreaWithTimeout(FACELOCK_VIEW_AREA_SERVICE_TIMEOUT); } else { - mHandler.sendEmptyMessage(MSG_HIDE_FACELOCK_AREA_VIEW); + hideFaceLockArea(); } } @@ -550,6 +558,7 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler */ @Override public void onWindowFocusChanged (boolean hasWindowFocus) { + if(DEBUG) Log.d(TAG, hasWindowFocus ? "focused" : "unfocused"); boolean runFaceLock = false; //Make sure to start facelock iff the screen is both on and focused synchronized(mFaceLockStartupLock) { @@ -558,9 +567,13 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler } if(!hasWindowFocus) { stopAndUnbindFromFaceLock(); - mHandler.sendEmptyMessage(MSG_HIDE_FACELOCK_AREA_VIEW); + hideFaceLockArea(); } else if (runFaceLock) { - activateFaceLockIfAble(); + //Don't activate facelock while the user is calling 911! + if(mEmergencyCall) mEmergencyCall = false; + else { + activateFaceLockIfAble(); + } } } @@ -574,9 +587,9 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler if (mLockPatternUtils.usingBiometricWeak() && mLockPatternUtils.isBiometricWeakInstalled()) { - mHandler.sendEmptyMessage(MSG_SHOW_FACELOCK_AREA_VIEW); + showFaceLockArea(); } else { - mHandler.sendEmptyMessage(MSG_HIDE_FACELOCK_AREA_VIEW); + hideFaceLockArea(); } } @@ -640,9 +653,10 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler //We need to stop faceunlock when a phonecall comes in @Override public void onPhoneStateChanged(int phoneState) { + if (DEBUG) Log.d(TAG, "phone state: " + phoneState); if(phoneState == TelephonyManager.CALL_STATE_RINGING) { stopAndUnbindFromFaceLock(); - mHandler.sendEmptyMessage(MSG_HIDE_FACELOCK_AREA_VIEW); + hideFaceLockArea(); } } @@ -1075,6 +1089,32 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler return true; } + // Removes show and hide messages from the message queue + private void removeFaceLockAreaDisplayMessages() { + mHandler.removeMessages(MSG_SHOW_FACELOCK_AREA_VIEW); + mHandler.removeMessages(MSG_HIDE_FACELOCK_AREA_VIEW); + } + + // Shows the FaceLock area immediately + private void showFaceLockArea() { + // Remove messages to prevent a delayed hide message from undo-ing the show + removeFaceLockAreaDisplayMessages(); + mHandler.sendEmptyMessage(MSG_SHOW_FACELOCK_AREA_VIEW); + } + + // Hides the FaceLock area immediately + private void hideFaceLockArea() { + // Remove messages to prevent a delayed show message from undo-ing the hide + removeFaceLockAreaDisplayMessages(); + mHandler.sendEmptyMessage(MSG_HIDE_FACELOCK_AREA_VIEW); + } + + // Shows the FaceLock area for a period of time + private void showFaceLockAreaWithTimeout(long timeoutMillis) { + showFaceLockArea(); + mHandler.sendEmptyMessageDelayed(MSG_HIDE_FACELOCK_AREA_VIEW, timeoutMillis); + } + // Binds to FaceLock service, but does not tell it to start public void bindToFaceLock() { if (mLockPatternUtils.usingBiometricWeak() && @@ -1120,7 +1160,10 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler try { mFaceLockService.registerCallback(mFaceLockCallback); } catch (RemoteException e) { - throw new RuntimeException("Remote exception"); + Log.e(TAG, "Caught exception connecting to FaceLock: " + e.toString()); + mFaceLockService = null; + mBoundToFaceLockService = false; + return; } if (mFaceLockAreaView != null) { @@ -1137,6 +1180,7 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler mFaceLockService = null; mFaceLockServiceRunning = false; } + mBoundToFaceLockService = false; Log.w(TAG, "Unexpected disconnect from FaceLock service"); } }; @@ -1152,7 +1196,8 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler try { mFaceLockService.startUi(windowToken, x, y, h, w); } catch (RemoteException e) { - throw new RuntimeException("Remote exception"); + Log.e(TAG, "Caught exception starting FaceLock: " + e.toString()); + return; } mFaceLockServiceRunning = true; } else { @@ -1176,7 +1221,7 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler if (DEBUG) Log.d(TAG, "Stopping FaceLock"); mFaceLockService.stopUi(); } catch (RemoteException e) { - throw new RuntimeException("Remote exception"); + Log.e(TAG, "Caught exception stopping FaceLock: " + e.toString()); } mFaceLockServiceRunning = false; } @@ -1191,7 +1236,7 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler @Override public void unlock() { if (DEBUG) Log.d(TAG, "FaceLock unlock()"); - mHandler.sendEmptyMessage(MSG_SHOW_FACELOCK_AREA_VIEW); // Keep fallback covered + showFaceLockArea(); // Keep fallback covered stopFaceLock(); mKeyguardScreenCallback.keyguardDone(true); @@ -1203,7 +1248,7 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler @Override public void cancel() { if (DEBUG) Log.d(TAG, "FaceLock cancel()"); - mHandler.sendEmptyMessage(MSG_HIDE_FACELOCK_AREA_VIEW); // Expose fallback + hideFaceLockArea(); // Expose fallback stopFaceLock(); } diff --git a/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java b/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java index ec0072c3c210..3ad716b7117d 100644 --- a/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java +++ b/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java @@ -28,6 +28,7 @@ import com.android.internal.widget.PasswordEntryKeyboardView; import android.os.CountDownTimer; import android.os.SystemClock; +import android.provider.Settings; import android.security.KeyStore; import android.text.Editable; import android.text.InputType; @@ -109,6 +110,10 @@ public class PasswordUnlockScreen extends LinearLayout implements KeyguardScreen mPasswordEntry.setOnEditorActionListener(this); mKeyboardHelper = new PasswordEntryKeyboardHelper(context, mKeyboardView, this, false); + mKeyboardHelper.setEnableHaptics( + Settings.Secure.getInt(mContext.getContentResolver(), + Settings.Secure.LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED, 0) + != 0); if (mIsAlpha) { // We always use the system IME for alpha keyboard, so hide lockscreen's soft keyboard mKeyboardHelper.setKeyboardMode(PasswordEntryKeyboardHelper.KEYBOARD_MODE_ALPHA); @@ -150,9 +155,6 @@ public class PasswordUnlockScreen extends LinearLayout implements KeyguardScreen //KeyguardStatusViewManager.LOCK_ICON); } - mKeyboardHelper.setVibratePattern(mLockPatternUtils.isTactileFeedbackEnabled() ? - com.android.internal.R.array.config_virtualKeyVibePattern : 0); - // Poke the wakelock any time the text is selected or modified mPasswordEntry.setOnClickListener(new OnClickListener() { public void onClick(View v) { diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java index 487063d2907b..aac320940cb8 100755 --- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java @@ -128,7 +128,6 @@ import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS; import android.view.WindowManagerImpl; import android.view.WindowManagerPolicy; import android.view.KeyCharacterMap.FallbackAction; -import android.view.WindowManagerPolicy.WindowManagerFuncs; import android.view.accessibility.AccessibilityEvent; import android.view.animation.Animation; import android.view.animation.AnimationUtils; @@ -180,26 +179,26 @@ public class PhoneWindowManager implements WindowManagerPolicy { static final int PRIORITY_PHONE_LAYER = 7; // like the ANR / app crashed dialogs static final int SYSTEM_ALERT_LAYER = 8; - // system-level error dialogs - static final int SYSTEM_ERROR_LAYER = 9; // on-screen keyboards and other such input method user interfaces go here. - static final int INPUT_METHOD_LAYER = 10; + static final int INPUT_METHOD_LAYER = 9; // on-screen keyboards and other such input method user interfaces go here. - static final int INPUT_METHOD_DIALOG_LAYER = 11; + static final int INPUT_METHOD_DIALOG_LAYER = 10; // the keyguard; nothing on top of these can take focus, since they are // responsible for power management when displayed. - static final int KEYGUARD_LAYER = 12; - static final int KEYGUARD_DIALOG_LAYER = 13; - static final int STATUS_BAR_SUB_PANEL_LAYER = 14; - static final int STATUS_BAR_LAYER = 15; - static final int STATUS_BAR_PANEL_LAYER = 16; + static final int KEYGUARD_LAYER = 11; + static final int KEYGUARD_DIALOG_LAYER = 12; + static final int STATUS_BAR_SUB_PANEL_LAYER = 13; + static final int STATUS_BAR_LAYER = 14; + static final int STATUS_BAR_PANEL_LAYER = 15; // the on-screen volume indicator and controller shown when the user // changes the device volume - static final int VOLUME_OVERLAY_LAYER = 17; + static final int VOLUME_OVERLAY_LAYER = 16; // things in here CAN NOT take focus, but are shown on top of everything else. - static final int SYSTEM_OVERLAY_LAYER = 18; + static final int SYSTEM_OVERLAY_LAYER = 17; // the navigation bar, if available, shows atop most things - static final int NAVIGATION_BAR_LAYER = 19; + static final int NAVIGATION_BAR_LAYER = 18; + // system-level error dialogs + static final int SYSTEM_ERROR_LAYER = 19; // the drag layer: input for drag-and-drop is associated with this window, // which sits above all other focusable windows static final int DRAG_LAYER = 20; @@ -267,7 +266,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { WindowState mKeyguard = null; KeyguardViewMediator mKeyguardMediator; GlobalActions mGlobalActions; - volatile boolean mPowerKeyHandled; + volatile boolean mPowerKeyHandled; // accessed from input reader and handler thread + boolean mPendingPowerKeyUpCanceled; RecentApplicationsDialog mRecentAppsDialog; Handler mHandler; @@ -403,8 +403,14 @@ public class PhoneWindowManager implements WindowManagerPolicy { private int mLongPressOnHomeBehavior = -1; // Screenshot trigger states - private boolean mVolumeDownTriggered; - private boolean mPowerDownTriggered; + // Time to volume and power must be pressed within this interval of each other. + private static final long SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS = 150; + private boolean mVolumeDownKeyTriggered; + private long mVolumeDownKeyTime; + private boolean mVolumeDownKeyConsumedByScreenshotChord; + private boolean mVolumeUpKeyTriggered; + private boolean mPowerKeyTriggered; + private long mPowerKeyTime; ShortcutManager mShortcutManager; PowerManager.WakeLock mBroadcastWakeLock; @@ -552,40 +558,67 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (!mPowerKeyHandled) { mHandler.removeCallbacks(mPowerLongPress); return !canceled; - } else { - mPowerKeyHandled = true; - return false; } + return false; + } + + private void cancelPendingPowerKeyAction() { + if (!mPowerKeyHandled) { + mHandler.removeCallbacks(mPowerLongPress); + } + mPendingPowerKeyUpCanceled = true; + } + + private void interceptScreenshotChord() { + if (mVolumeDownKeyTriggered && mPowerKeyTriggered && !mVolumeUpKeyTriggered) { + final long now = SystemClock.uptimeMillis(); + if (now <= mVolumeDownKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS + && now <= mPowerKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS) { + mVolumeDownKeyConsumedByScreenshotChord = true; + cancelPendingPowerKeyAction(); + + mHandler.postDelayed(mScreenshotChordLongPress, + ViewConfiguration.getGlobalActionKeyTimeout()); + } + } + } + + private void cancelPendingScreenshotChordAction() { + mHandler.removeCallbacks(mScreenshotChordLongPress); } private final Runnable mPowerLongPress = new Runnable() { public void run() { - if (!mPowerKeyHandled) { - // The context isn't read - if (mLongPressOnPowerBehavior < 0) { - mLongPressOnPowerBehavior = mContext.getResources().getInteger( - com.android.internal.R.integer.config_longPressOnPowerBehavior); - } - switch (mLongPressOnPowerBehavior) { - case LONG_PRESS_POWER_NOTHING: - break; - case LONG_PRESS_POWER_GLOBAL_ACTIONS: - mPowerKeyHandled = true; - performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false); - sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS); - showGlobalActionsDialog(); - break; - case LONG_PRESS_POWER_SHUT_OFF: - mPowerKeyHandled = true; - performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false); - sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS); - ShutdownThread.shutdown(mContext, true); - break; - } + // The context isn't read + if (mLongPressOnPowerBehavior < 0) { + mLongPressOnPowerBehavior = mContext.getResources().getInteger( + com.android.internal.R.integer.config_longPressOnPowerBehavior); + } + switch (mLongPressOnPowerBehavior) { + case LONG_PRESS_POWER_NOTHING: + break; + case LONG_PRESS_POWER_GLOBAL_ACTIONS: + mPowerKeyHandled = true; + performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false); + sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS); + showGlobalActionsDialog(); + break; + case LONG_PRESS_POWER_SHUT_OFF: + mPowerKeyHandled = true; + performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false); + sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS); + ShutdownThread.shutdown(mContext, true); + break; } } }; + private final Runnable mScreenshotChordLongPress = new Runnable() { + public void run() { + takeScreenshot(); + } + }; + void showGlobalActionsDialog() { if (mGlobalActions == null) { mGlobalActions = new GlobalActions(mContext); @@ -1381,11 +1414,12 @@ public class PhoneWindowManager implements WindowManagerPolicy { /** {@inheritDoc} */ @Override - public boolean interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags) { + public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags) { final boolean keyguardOn = keyguardOn(); final int keyCode = event.getKeyCode(); final int repeatCount = event.getRepeatCount(); final int metaState = event.getMetaState(); + final int flags = event.getFlags(); final boolean down = event.getAction() == KeyEvent.ACTION_DOWN; final boolean canceled = event.isCanceled(); @@ -1394,6 +1428,26 @@ public class PhoneWindowManager implements WindowManagerPolicy { + repeatCount + " keyguardOn=" + keyguardOn + " mHomePressed=" + mHomePressed); } + // If we think we might have a volume down & power key chord on the way + // but we're not sure, then tell the dispatcher to wait a little while and + // try again later before dispatching. + if ((flags & KeyEvent.FLAG_FALLBACK) == 0) { + if (mVolumeDownKeyTriggered && !mPowerKeyTriggered) { + final long now = SystemClock.uptimeMillis(); + final long timeoutTime = mVolumeDownKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS; + if (now < timeoutTime) { + return timeoutTime - now; + } + } + if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN + && mVolumeDownKeyConsumedByScreenshotChord) { + if (!down) { + mVolumeDownKeyConsumedByScreenshotChord = false; + } + return -1; + } + } + // First we always handle the home key here, so applications // can never break it, although if keyguard is on, we do let // it handle it, because that gives us the correct 5 second @@ -1425,7 +1479,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { } else { Log.i(TAG, "Ignoring HOME; event canceled."); } - return true; + return -1; } // If a system window has focus, then it doesn't make sense @@ -1436,13 +1490,13 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (type == WindowManager.LayoutParams.TYPE_KEYGUARD || type == WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG) { // the "app" is keyguard, so give it the key - return false; + return 0; } final int typeCount = WINDOW_TYPES_WHERE_HOME_DOESNT_WORK.length; for (int i=0; i<typeCount; i++) { if (type == WINDOW_TYPES_WHERE_HOME_DOESNT_WORK[i]) { // don't do anything, but also don't pass it to the app - return true; + return -1; } } } @@ -1456,7 +1510,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } } - return true; + return -1; } else if (keyCode == KeyEvent.KEYCODE_MENU) { // Hijack modified menu keys for debugging features final int chordBug = KeyEvent.META_SHIFT_ON; @@ -1465,7 +1519,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (mEnableShiftMenuBugReports && (metaState & chordBug) == chordBug) { Intent intent = new Intent(Intent.ACTION_BUG_REPORT); mContext.sendOrderedBroadcast(intent, null); - return true; + return -1; } else if (SHOW_PROCESSES_ON_ALT_MENU && (metaState & KeyEvent.META_ALT_ON) == KeyEvent.META_ALT_ON) { Intent service = new Intent(); @@ -1480,7 +1534,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { } Settings.System.putInt( res, Settings.System.SHOW_PROCESSES, shown ? 0 : 1); - return true; + return -1; } } } else if (keyCode == KeyEvent.KEYCODE_SEARCH) { @@ -1493,15 +1547,15 @@ public class PhoneWindowManager implements WindowManagerPolicy { mShortcutKeyPressed = -1; if (mConsumeShortcutKeyUp) { mConsumeShortcutKeyUp = false; - return true; + return -1; } } - return false; + return 0; } else if (keyCode == KeyEvent.KEYCODE_APP_SWITCH) { if (down && repeatCount == 0) { showOrHideRecentAppsDialog(0, true /*dismissIfShown*/); } - return true; + return -1; } // Shortcuts are invoked through Search+key, so intercept those here @@ -1531,11 +1585,11 @@ public class PhoneWindowManager implements WindowManagerPolicy { + "+" + KeyEvent.keyCodeToString(keyCode)); } } - return true; + return -1; } } - return false; + return 0; } /** {@inheritDoc} */ @@ -1606,7 +1660,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { flags, event.getSource(), null); int actions = interceptKeyBeforeQueueing(fallbackEvent, policyFlags, true); if ((actions & ACTION_PASS_TO_USER) != 0) { - if (!interceptKeyBeforeDispatching(win, fallbackEvent, policyFlags)) { + long delayMillis = interceptKeyBeforeDispatching( + win, fallbackEvent, policyFlags); + if (delayMillis == 0) { if (DEBUG_FALLBACK) { Slog.d(TAG, "Performing fallback."); } @@ -2472,76 +2528,65 @@ public class PhoneWindowManager implements WindowManagerPolicy { final Object mScreenshotLock = new Object(); ServiceConnection mScreenshotConnection = null; - Runnable mScreenshotTimeout = null; - void finishScreenshotLSS(ServiceConnection conn) { - if (mScreenshotConnection == conn) { - mContext.unbindService(conn); - mScreenshotConnection = null; - if (mScreenshotTimeout != null) { - mHandler.removeCallbacks(mScreenshotTimeout); - mScreenshotTimeout = null; + final Runnable mScreenshotTimeout = new Runnable() { + @Override public void run() { + synchronized (mScreenshotLock) { + if (mScreenshotConnection != null) { + mContext.unbindService(mScreenshotConnection); + mScreenshotConnection = null; + } } } - } + }; + // Assume this is called from the Handler thread. private void takeScreenshot() { - mHandler.post(new Runnable() { - @Override - public void run() { - synchronized (mScreenshotLock) { - if (mScreenshotConnection != null) { - return; - } - ComponentName cn = new ComponentName("com.android.systemui", - "com.android.systemui.screenshot.TakeScreenshotService"); - Intent intent = new Intent(); - intent.setComponent(cn); - ServiceConnection conn = new ServiceConnection() { - @Override - public void onServiceConnected(ComponentName name, IBinder service) { - synchronized (mScreenshotLock) { - if (mScreenshotConnection != this) { - return; - } - Messenger messenger = new Messenger(service); - Message msg = Message.obtain(null, 1); - final ServiceConnection myConn = this; - Handler h = new Handler(mHandler.getLooper()) { - @Override - public void handleMessage(Message msg) { - synchronized (mScreenshotLock) { - finishScreenshotLSS(myConn); - } - } - }; - msg.replyTo = new Messenger(h); - try { - messenger.send(msg); - } catch (RemoteException e) { - } - } + synchronized (mScreenshotLock) { + if (mScreenshotConnection != null) { + return; + } + ComponentName cn = new ComponentName("com.android.systemui", + "com.android.systemui.screenshot.TakeScreenshotService"); + Intent intent = new Intent(); + intent.setComponent(cn); + ServiceConnection conn = new ServiceConnection() { + @Override + public void onServiceConnected(ComponentName name, IBinder service) { + synchronized (mScreenshotLock) { + if (mScreenshotConnection != this) { + return; } - @Override - public void onServiceDisconnected(ComponentName name) {} - }; - if (mContext.bindService(intent, conn, Context.BIND_AUTO_CREATE)) { - mScreenshotConnection = conn; - mScreenshotTimeout = new Runnable() { - @Override public void run() { + Messenger messenger = new Messenger(service); + Message msg = Message.obtain(null, 1); + final ServiceConnection myConn = this; + Handler h = new Handler(mHandler.getLooper()) { + @Override + public void handleMessage(Message msg) { synchronized (mScreenshotLock) { - if (mScreenshotConnection != null) { - finishScreenshotLSS(mScreenshotConnection); + if (mScreenshotConnection == myConn) { + mContext.unbindService(mScreenshotConnection); + mScreenshotConnection = null; + mHandler.removeCallbacks(mScreenshotTimeout); } } } - }; - mHandler.postDelayed(mScreenshotTimeout, 10000); + msg.replyTo = new Messenger(h); + try { + messenger.send(msg); + } catch (RemoteException e) { + } } } + @Override + public void onServiceDisconnected(ComponentName name) {} + }; + if (mContext.bindService(intent, conn, Context.BIND_AUTO_CREATE)) { + mScreenshotConnection = conn; + mHandler.postDelayed(mScreenshotTimeout, 10000); } - }); + } } /** {@inheritDoc} */ @@ -2609,28 +2654,35 @@ public class PhoneWindowManager implements WindowManagerPolicy { // Handle special keys. switch (keyCode) { case KeyEvent.KEYCODE_VOLUME_DOWN: - if (down) { - if (isScreenOn) { - // If the power key down was already triggered, take the screenshot - if (mPowerDownTriggered) { - // Dismiss the power-key longpress - mHandler.removeCallbacks(mPowerLongPress); - mPowerKeyHandled = true; - - // Take the screenshot - takeScreenshot(); - - // Prevent the event from being passed through to the current activity - result &= ~ACTION_PASS_TO_USER; - break; + case KeyEvent.KEYCODE_VOLUME_UP: + case KeyEvent.KEYCODE_VOLUME_MUTE: { + if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) { + if (down) { + if (isScreenOn && !mVolumeDownKeyTriggered + && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) { + mVolumeDownKeyTriggered = true; + mVolumeDownKeyTime = event.getDownTime(); + mVolumeDownKeyConsumedByScreenshotChord = false; + cancelPendingPowerKeyAction(); + interceptScreenshotChord(); + } + } else { + mVolumeDownKeyTriggered = false; + cancelPendingScreenshotChordAction(); + } + } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) { + if (down) { + if (isScreenOn && !mVolumeUpKeyTriggered + && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) { + mVolumeUpKeyTriggered = true; + cancelPendingPowerKeyAction(); + cancelPendingScreenshotChordAction(); } - mVolumeDownTriggered = true; + } else { + mVolumeUpKeyTriggered = false; + cancelPendingScreenshotChordAction(); } - } else { - mVolumeDownTriggered = false; } - case KeyEvent.KEYCODE_VOLUME_UP: - case KeyEvent.KEYCODE_VOLUME_MUTE: { if (down) { ITelephony telephonyService = getTelephonyService(); if (telephonyService != null) { @@ -2709,17 +2761,11 @@ public class PhoneWindowManager implements WindowManagerPolicy { case KeyEvent.KEYCODE_POWER: { result &= ~ACTION_PASS_TO_USER; if (down) { - if (isScreenOn) { - // If the volume down key has been triggered, then just take the screenshot - if (mVolumeDownTriggered) { - // Take the screenshot - takeScreenshot(); - mPowerKeyHandled = true; - - // Prevent the event from being passed through to the current activity - break; - } - mPowerDownTriggered = true; + if (isScreenOn && !mPowerKeyTriggered + && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) { + mPowerKeyTriggered = true; + mPowerKeyTime = event.getDownTime(); + interceptScreenshotChord(); } ITelephony telephonyService = getTelephonyService(); @@ -2741,12 +2787,15 @@ public class PhoneWindowManager implements WindowManagerPolicy { Log.w(TAG, "ITelephony threw RemoteException", ex); } } - interceptPowerKeyDown(!isScreenOn || hungUp); + interceptPowerKeyDown(!isScreenOn || hungUp + || mVolumeDownKeyTriggered || mVolumeUpKeyTriggered); } else { - mPowerDownTriggered = false; - if (interceptPowerKeyUp(canceled)) { + mPowerKeyTriggered = false; + cancelPendingScreenshotChordAction(); + if (interceptPowerKeyUp(canceled || mPendingPowerKeyUpCanceled)) { result = (result & ~ACTION_POKE_USER_ACTIVITY) | ACTION_GO_TO_SLEEP; } + mPendingPowerKeyUpCanceled = false; } break; } diff --git a/services/input/InputDispatcher.cpp b/services/input/InputDispatcher.cpp index 1eb5f0e73e50..04b4855d6238 100644 --- a/services/input/InputDispatcher.cpp +++ b/services/input/InputDispatcher.cpp @@ -804,6 +804,18 @@ bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, KeyEntry* entry, logOutboundKeyDetailsLocked("dispatchKey - ", entry); } + // Handle case where the policy asked us to try again later last time. + if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER) { + if (currentTime < entry->interceptKeyWakeupTime) { + if (entry->interceptKeyWakeupTime < *nextWakeupTime) { + *nextWakeupTime = entry->interceptKeyWakeupTime; + } + return false; // wait until next wakeup + } + entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN; + entry->interceptKeyWakeupTime = 0; + } + // Give the policy a chance to intercept the key. if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN) { if (entry->policyFlags & POLICY_FLAG_PASS_TO_USER) { @@ -3827,14 +3839,19 @@ void InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible( mLock.unlock(); - bool consumed = mPolicy->interceptKeyBeforeDispatching(commandEntry->inputWindowHandle, + nsecs_t delay = mPolicy->interceptKeyBeforeDispatching(commandEntry->inputWindowHandle, &event, entry->policyFlags); mLock.lock(); - entry->interceptKeyResult = consumed - ? KeyEntry::INTERCEPT_KEY_RESULT_SKIP - : KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE; + if (delay < 0) { + entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_SKIP; + } else if (!delay) { + entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE; + } else { + entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER; + entry->interceptKeyWakeupTime = now() + delay; + } entry->release(); } @@ -4156,7 +4173,8 @@ InputDispatcher::KeyEntry::KeyEntry(nsecs_t eventTime, deviceId(deviceId), source(source), action(action), flags(flags), keyCode(keyCode), scanCode(scanCode), metaState(metaState), repeatCount(repeatCount), downTime(downTime), - syntheticRepeat(false), interceptKeyResult(KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN) { + syntheticRepeat(false), interceptKeyResult(KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN), + interceptKeyWakeupTime(0) { } InputDispatcher::KeyEntry::~KeyEntry() { @@ -4168,6 +4186,7 @@ void InputDispatcher::KeyEntry::recycle() { dispatchInProgress = false; syntheticRepeat = false; interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN; + interceptKeyWakeupTime = 0; } diff --git a/services/input/InputDispatcher.h b/services/input/InputDispatcher.h index e78f7bd0a4cd..8ae5a56ba837 100644 --- a/services/input/InputDispatcher.h +++ b/services/input/InputDispatcher.h @@ -242,7 +242,7 @@ public: virtual void interceptMotionBeforeQueueing(nsecs_t when, uint32_t& policyFlags) = 0; /* Allows the policy a chance to intercept a key before dispatching. */ - virtual bool interceptKeyBeforeDispatching(const sp<InputWindowHandle>& inputWindowHandle, + virtual nsecs_t interceptKeyBeforeDispatching(const sp<InputWindowHandle>& inputWindowHandle, const KeyEvent* keyEvent, uint32_t policyFlags) = 0; /* Allows the policy a chance to perform default processing for an unhandled key. @@ -481,8 +481,10 @@ private: INTERCEPT_KEY_RESULT_UNKNOWN, INTERCEPT_KEY_RESULT_SKIP, INTERCEPT_KEY_RESULT_CONTINUE, + INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER, }; InterceptKeyResult interceptKeyResult; // set based on the interception result + nsecs_t interceptKeyWakeupTime; // used with INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER KeyEntry(nsecs_t eventTime, int32_t deviceId, uint32_t source, uint32_t policyFlags, int32_t action, diff --git a/services/input/tests/InputDispatcher_test.cpp b/services/input/tests/InputDispatcher_test.cpp index 8dfb44b376a0..961566fe8157 100644 --- a/services/input/tests/InputDispatcher_test.cpp +++ b/services/input/tests/InputDispatcher_test.cpp @@ -75,9 +75,9 @@ private: virtual void interceptMotionBeforeQueueing(nsecs_t when, uint32_t& policyFlags) { } - virtual bool interceptKeyBeforeDispatching(const sp<InputWindowHandle>& inputWindowHandle, + virtual nsecs_t interceptKeyBeforeDispatching(const sp<InputWindowHandle>& inputWindowHandle, const KeyEvent* keyEvent, uint32_t policyFlags) { - return false; + return 0; } virtual bool dispatchUnhandledKey(const sp<InputWindowHandle>& inputWindowHandle, diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index d038d767828d..55fb371d1753 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -3427,8 +3427,10 @@ public final class ActivityManagerService extends ActivityManagerNative ac.removePackage(name); } } - mMainStack.resumeTopActivityLocked(null); - mMainStack.scheduleIdleLocked(); + if (mBooted) { + mMainStack.resumeTopActivityLocked(null); + mMainStack.scheduleIdleLocked(); + } } return didSomething; diff --git a/services/java/com/android/server/am/AppErrorDialog.java b/services/java/com/android/server/am/AppErrorDialog.java index a769c05c1648..57e11cf2f43c 100644 --- a/services/java/com/android/server/am/AppErrorDialog.java +++ b/services/java/com/android/server/am/AppErrorDialog.java @@ -24,6 +24,7 @@ import android.content.res.Resources; import android.os.Handler; import android.os.Message; import android.util.Slog; +import android.view.WindowManager; class AppErrorDialog extends BaseErrorDialog { private final static String TAG = "AppErrorDialog"; @@ -73,6 +74,9 @@ class AppErrorDialog extends BaseErrorDialog { setTitle(res.getText(com.android.internal.R.string.aerr_title)); getWindow().addFlags(FLAG_SYSTEM_ERROR); getWindow().setTitle("Application Error: " + app.info.processName); + if (app.persistent) { + getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR); + } // After the timeout, pretend the user clicked the quit button mHandler.sendMessageDelayed( diff --git a/services/java/com/android/server/wm/DragState.java b/services/java/com/android/server/wm/DragState.java index 25cc259ac776..73cd64e9f735 100644 --- a/services/java/com/android/server/wm/DragState.java +++ b/services/java/com/android/server/wm/DragState.java @@ -274,7 +274,8 @@ class DragState { final int myPid = Process.myPid(); // Move the surface to the given touch - if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, ">>> OPEN TRANSACTION notifyMoveLw"); + if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS) Slog.i( + WindowManagerService.TAG, ">>> OPEN TRANSACTION notifyMoveLw"); Surface.openTransaction(); try { mSurface.setPosition(x - mThumbOffsetX, y - mThumbOffsetY); @@ -283,7 +284,8 @@ class DragState { (int)(x - mThumbOffsetX) + "," + (int)(y - mThumbOffsetY) + ")"); } finally { Surface.closeTransaction(); - if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, "<<< CLOSE TRANSACTION notifyMoveLw"); + if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS) Slog.i( + WindowManagerService.TAG, "<<< CLOSE TRANSACTION notifyMoveLw"); } // Tell the affected window diff --git a/services/java/com/android/server/wm/InputManager.java b/services/java/com/android/server/wm/InputManager.java index 60333a3bf3f3..df7e0e18b7f5 100644 --- a/services/java/com/android/server/wm/InputManager.java +++ b/services/java/com/android/server/wm/InputManager.java @@ -575,7 +575,7 @@ public class InputManager implements Watchdog.Monitor { } @SuppressWarnings("unused") - public boolean interceptKeyBeforeDispatching(InputWindowHandle focus, + public long interceptKeyBeforeDispatching(InputWindowHandle focus, KeyEvent event, int policyFlags) { return mWindowManagerService.mInputMonitor.interceptKeyBeforeDispatching( focus, event, policyFlags); diff --git a/services/java/com/android/server/wm/InputMonitor.java b/services/java/com/android/server/wm/InputMonitor.java index 9a559e004412..fb74d2764280 100644 --- a/services/java/com/android/server/wm/InputMonitor.java +++ b/services/java/com/android/server/wm/InputMonitor.java @@ -288,7 +288,7 @@ final class InputMonitor { /* Provides an opportunity for the window manager policy to process a key before * ordinary dispatch. */ - public boolean interceptKeyBeforeDispatching( + public long interceptKeyBeforeDispatching( InputWindowHandle focus, KeyEvent event, int policyFlags) { WindowState windowState = focus != null ? (WindowState) focus.windowState : null; return mService.mPolicy.interceptKeyBeforeDispatching(windowState, event, policyFlags); diff --git a/services/java/com/android/server/wm/ScreenRotationAnimation.java b/services/java/com/android/server/wm/ScreenRotationAnimation.java index e25638f24888..91576e7ac0d6 100644 --- a/services/java/com/android/server/wm/ScreenRotationAnimation.java +++ b/services/java/com/android/server/wm/ScreenRotationAnimation.java @@ -81,7 +81,7 @@ class ScreenRotationAnimation { mOriginalHeight = originalHeight; if (!inTransaction) { - if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, + if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS) Slog.i(WindowManagerService.TAG, ">>> OPEN TRANSACTION ScreenRotationAnimation"); Surface.openTransaction(); } @@ -117,7 +117,7 @@ class ScreenRotationAnimation { mSurface = null; return; } - + Paint paint = new Paint(0); paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC)); c.drawBitmap(screenshot, 0, 0, paint); @@ -127,7 +127,7 @@ class ScreenRotationAnimation { } finally { if (!inTransaction) { Surface.closeTransaction(); - if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, + if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS) Slog.i(WindowManagerService.TAG, "<<< CLOSE TRANSACTION ScreenRotationAnimation"); } @@ -254,7 +254,7 @@ class ScreenRotationAnimation { mEnterAnimation.restrictDuration(maxAnimationDuration); mEnterAnimation.scaleCurrentDuration(animationScale); - if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, + if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS) Slog.i(WindowManagerService.TAG, ">>> OPEN TRANSACTION ScreenRotationAnimation.dismiss"); Surface.openTransaction(); @@ -266,7 +266,7 @@ class ScreenRotationAnimation { Slog.w(TAG, "Unable to allocate black surface", e); } finally { Surface.closeTransaction(); - if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, + if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS) Slog.i(WindowManagerService.TAG, "<<< CLOSE TRANSACTION ScreenRotationAnimation.dismiss"); } diff --git a/services/java/com/android/server/wm/Session.java b/services/java/com/android/server/wm/Session.java index 10882f9cbd34..03b7546f8a7c 100644 --- a/services/java/com/android/server/wm/Session.java +++ b/services/java/com/android/server/wm/Session.java @@ -278,7 +278,8 @@ final class Session extends IWindowSession.Stub // Make the surface visible at the proper location final Surface surface = mService.mDragState.mSurface; - if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, ">>> OPEN TRANSACTION performDrag"); + if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS) Slog.i( + WindowManagerService.TAG, ">>> OPEN TRANSACTION performDrag"); Surface.openTransaction(); try { surface.setPosition(touchX - thumbCenterX, @@ -288,7 +289,8 @@ final class Session extends IWindowSession.Stub surface.show(); } finally { Surface.closeTransaction(); - if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, "<<< CLOSE TRANSACTION performDrag"); + if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS) Slog.i( + WindowManagerService.TAG, "<<< CLOSE TRANSACTION performDrag"); } } diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java index 595c256fb8eb..68f0e66dfdac 100644 --- a/services/java/com/android/server/wm/WindowManagerService.java +++ b/services/java/com/android/server/wm/WindowManagerService.java @@ -167,8 +167,10 @@ public class WindowManagerService extends IWindowManager.Stub static final boolean DEBUG_DRAG = false; static final boolean DEBUG_SCREEN_ON = false; static final boolean DEBUG_SCREENSHOT = false; + static final boolean DEBUG_BOOT = false; static final boolean SHOW_SURFACE_ALLOC = false; static final boolean SHOW_TRANSACTIONS = false; + static final boolean SHOW_LIGHT_TRANSACTIONS = false || SHOW_TRANSACTIONS; static final boolean HIDE_STACK_CRAWLS = true; static final boolean PROFILE_ORIENTATION = false; @@ -2369,7 +2371,7 @@ public class WindowManagerService extends IWindowManager.Stub synchronized (mWindowMap) { WindowState w = windowForClientLocked(session, client, false); if ((w != null) && (w.mSurface != null)) { - if (SHOW_TRANSACTIONS) Slog.i(TAG, + if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setTransparentRegion"); Surface.openTransaction(); try { @@ -2378,7 +2380,7 @@ public class WindowManagerService extends IWindowManager.Stub w.mSurface.setTransparentRegionHint(region); } finally { Surface.closeTransaction(); - if (SHOW_TRANSACTIONS) Slog.i(TAG, + if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION setTransparentRegion"); } } @@ -4727,6 +4729,14 @@ public class WindowManagerService extends IWindowManager.Stub public void enableScreenAfterBoot() { synchronized(mWindowMap) { + if (DEBUG_BOOT) { + RuntimeException here = new RuntimeException("here"); + here.fillInStackTrace(); + Slog.i(TAG, "enableScreenAfterBoot: mDisplayEnabled=" + mDisplayEnabled + + " mForceDisplayEnabled=" + mForceDisplayEnabled + + " mShowingBootMessages=" + mShowingBootMessages + + " mSystemBooted=" + mSystemBooted, here); + } if (mSystemBooted) { return; } @@ -4744,6 +4754,14 @@ public class WindowManagerService extends IWindowManager.Stub } void enableScreenIfNeededLocked() { + if (DEBUG_BOOT) { + RuntimeException here = new RuntimeException("here"); + here.fillInStackTrace(); + Slog.i(TAG, "enableScreenIfNeededLocked: mDisplayEnabled=" + mDisplayEnabled + + " mForceDisplayEnabled=" + mForceDisplayEnabled + + " mShowingBootMessages=" + mShowingBootMessages + + " mSystemBooted=" + mSystemBooted, here); + } if (mDisplayEnabled) { return; } @@ -4766,6 +4784,14 @@ public class WindowManagerService extends IWindowManager.Stub public void performEnableScreen() { synchronized(mWindowMap) { + if (DEBUG_BOOT) { + RuntimeException here = new RuntimeException("here"); + here.fillInStackTrace(); + Slog.i(TAG, "performEnableScreen: mDisplayEnabled=" + mDisplayEnabled + + " mForceDisplayEnabled=" + mForceDisplayEnabled + + " mShowingBootMessages=" + mShowingBootMessages + + " mSystemBooted=" + mSystemBooted, here); + } if (mDisplayEnabled) { return; } @@ -4779,10 +4805,22 @@ public class WindowManagerService extends IWindowManager.Stub boolean haveBootMsg = false; boolean haveApp = false; boolean haveWallpaper = false; - boolean haveKeyguard = false; + boolean haveKeyguard = true; final int N = mWindows.size(); for (int i=0; i<N; i++) { WindowState w = mWindows.get(i); + if (w.mAttrs.type == WindowManager.LayoutParams.TYPE_KEYGUARD) { + // Only if there is a keyguard attached to the window manager + // will we consider ourselves as having a keyguard. If it + // isn't attached, we don't know if it wants to be shown or + // hidden. If it is attached, we will say we have a keyguard + // if the window doesn't want to be visible, because in that + // case it explicitly doesn't want to be shown so we should + // not delay turning the screen on for it. + boolean vis = w.mViewVisibility == View.VISIBLE + && w.mPolicyVisibility; + haveKeyguard = !vis; + } if (w.isVisibleLw() && !w.mObscured && !w.isDrawnLw()) { return; } @@ -4799,7 +4837,7 @@ public class WindowManagerService extends IWindowManager.Stub } } - if (DEBUG_SCREEN_ON) { + if (DEBUG_SCREEN_ON || DEBUG_BOOT) { Slog.i(TAG, "******** booted=" + mSystemBooted + " msg=" + mShowingBootMessages + " haveBoot=" + haveBootMsg + " haveApp=" + haveApp + " haveWall=" + haveWallpaper + " haveKeyguard=" + haveKeyguard); @@ -4820,7 +4858,7 @@ public class WindowManagerService extends IWindowManager.Stub } mDisplayEnabled = true; - if (DEBUG_SCREEN_ON) Slog.i(TAG, "******************** ENABLING SCREEN!"); + if (DEBUG_SCREEN_ON || DEBUG_BOOT) Slog.i(TAG, "******************** ENABLING SCREEN!"); if (false) { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); @@ -4851,6 +4889,14 @@ public class WindowManagerService extends IWindowManager.Stub public void showBootMessage(final CharSequence msg, final boolean always) { boolean first = false; synchronized(mWindowMap) { + if (DEBUG_BOOT) { + RuntimeException here = new RuntimeException("here"); + here.fillInStackTrace(); + Slog.i(TAG, "showBootMessage: msg=" + msg + " always=" + always + + " mAllowBootMessages=" + mAllowBootMessages + + " mShowingBootMessages=" + mShowingBootMessages + + " mSystemBooted=" + mSystemBooted, here); + } if (!mAllowBootMessages) { return; } @@ -4872,6 +4918,14 @@ public class WindowManagerService extends IWindowManager.Stub } public void hideBootMessagesLocked() { + if (DEBUG_BOOT) { + RuntimeException here = new RuntimeException("here"); + here.fillInStackTrace(); + Slog.i(TAG, "hideBootMessagesLocked: mDisplayEnabled=" + mDisplayEnabled + + " mForceDisplayEnabled=" + mForceDisplayEnabled + + " mShowingBootMessages=" + mShowingBootMessages + + " mSystemBooted=" + mSystemBooted, here); + } if (mShowingBootMessages) { mShowingBootMessages = false; mPolicy.hideBootMessages(); @@ -4905,7 +4959,8 @@ public class WindowManagerService extends IWindowManager.Stub } } - if (SHOW_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION showStrictModeViolation"); + if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, + ">>> OPEN TRANSACTION showStrictModeViolation"); Surface.openTransaction(); try { if (mStrictModeFlash == null) { @@ -4914,7 +4969,8 @@ public class WindowManagerService extends IWindowManager.Stub mStrictModeFlash.setVisibility(on); } finally { Surface.closeTransaction(); - if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION showStrictModeViolation"); + if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, + "<<< CLOSE TRANSACTION showStrictModeViolation"); } } } @@ -5231,7 +5287,7 @@ public class WindowManagerService extends IWindowManager.Stub mInputManager.setDisplayOrientation(0, rotation); if (!inTransaction) { - if (SHOW_TRANSACTIONS) Slog.i(TAG, + if (SHOW_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setRotationUnchecked"); Surface.openTransaction(); } @@ -5246,7 +5302,7 @@ public class WindowManagerService extends IWindowManager.Stub } finally { if (!inTransaction) { Surface.closeTransaction(); - if (SHOW_TRANSACTIONS) Slog.i(TAG, + if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION setRotationUnchecked"); } } @@ -5843,6 +5899,10 @@ public class WindowManagerService extends IWindowManager.Stub final DisplayMetrics dm = mDisplayMetrics; mAppDisplayWidth = mPolicy.getNonDecorDisplayWidth(dw, dh, mRotation); mAppDisplayHeight = mPolicy.getNonDecorDisplayHeight(dw, dh, mRotation); + if (false) { + Slog.i(TAG, "Set app display size: " + mAppDisplayWidth + + " x " + mAppDisplayHeight); + } mDisplay.getMetricsWithSize(dm, mAppDisplayWidth, mAppDisplayHeight); mCompatibleScreenScale = CompatibilityInfo.computeCompatibleScaling(dm, @@ -5860,8 +5920,8 @@ public class WindowManagerService extends IWindowManager.Stub // Compute the screen layout size class. int screenLayout; - int longSize = dw; - int shortSize = dh; + int longSize = mAppDisplayWidth; + int shortSize = mAppDisplayHeight; if (longSize < shortSize) { int tmp = longSize; longSize = shortSize; @@ -6847,7 +6907,7 @@ public class WindowManagerService extends IWindowManager.Stub private void rebuildBlackFrame(boolean inTransaction) { if (!inTransaction) { - if (SHOW_TRANSACTIONS) Slog.i(TAG, + if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION rebuildBlackFrame"); Surface.openTransaction(); } @@ -6882,7 +6942,7 @@ public class WindowManagerService extends IWindowManager.Stub } finally { if (!inTransaction) { Surface.closeTransaction(); - if (SHOW_TRANSACTIONS) Slog.i(TAG, + if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION rebuildBlackFrame"); } } @@ -7354,7 +7414,8 @@ public class WindowManagerService extends IWindowManager.Stub createWatermark = true; } - if (SHOW_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION performLayoutAndPlaceSurfaces"); + if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, + ">>> OPEN TRANSACTION performLayoutAndPlaceSurfaces"); Surface.openTransaction(); @@ -8463,7 +8524,8 @@ public class WindowManagerService extends IWindowManager.Stub Surface.closeTransaction(); - if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces"); + if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, + "<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces"); if (mWatermark != null) { mWatermark.drawIfNeeded(); diff --git a/services/java/com/android/server/wm/WindowState.java b/services/java/com/android/server/wm/WindowState.java index 47f74fb4a676..e9218181ab87 100644 --- a/services/java/com/android/server/wm/WindowState.java +++ b/services/java/com/android/server/wm/WindowState.java @@ -57,6 +57,7 @@ import java.util.ArrayList; final class WindowState implements WindowManagerPolicy.WindowState { static final boolean DEBUG_VISIBILITY = WindowManagerService.DEBUG_VISIBILITY; static final boolean SHOW_TRANSACTIONS = WindowManagerService.SHOW_TRANSACTIONS; + static final boolean SHOW_LIGHT_TRANSACTIONS = WindowManagerService.SHOW_LIGHT_TRANSACTIONS; static final boolean SHOW_SURFACE_ALLOC = WindowManagerService.SHOW_SURFACE_ALLOC; final WindowManagerService mService; @@ -671,7 +672,7 @@ final class WindowState implements WindowManagerPolicy.WindowState { WindowManagerService.TAG, "Got surface: " + mSurface + ", set left=" + mFrame.left + " top=" + mFrame.top + ", animLayer=" + mAnimLayer); - if (SHOW_TRANSACTIONS) { + if (SHOW_LIGHT_TRANSACTIONS) { Slog.i(WindowManagerService.TAG, ">>> OPEN TRANSACTION createSurfaceLocked"); WindowManagerService.logSurface(this, "CREATE pos=(" + mFrame.left + "," + mFrame.top + ") (" + @@ -700,7 +701,8 @@ final class WindowState implements WindowManagerPolicy.WindowState { mLastHidden = true; } finally { Surface.closeTransaction(); - if (SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, "<<< CLOSE TRANSACTION createSurfaceLocked"); + if (SHOW_LIGHT_TRANSACTIONS) Slog.i(WindowManagerService.TAG, + "<<< CLOSE TRANSACTION createSurfaceLocked"); } if (WindowManagerService.localLOGV) Slog.v( WindowManagerService.TAG, "Created surface " + this); diff --git a/services/jni/com_android_server_InputManager.cpp b/services/jni/com_android_server_InputManager.cpp index f9763016ceba..7e9fba891946 100644 --- a/services/jni/com_android_server_InputManager.cpp +++ b/services/jni/com_android_server_InputManager.cpp @@ -149,6 +149,12 @@ static void loadSystemIconAsSprite(JNIEnv* env, jobject contextObj, int32_t styl } } +enum { + WM_ACTION_PASS_TO_USER = 1, + WM_ACTION_POKE_USER_ACTIVITY = 2, + WM_ACTION_GO_TO_SLEEP = 4, +}; + // --- NativeInputManager --- @@ -199,7 +205,8 @@ public: virtual bool isKeyRepeatEnabled(); virtual void interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags); virtual void interceptMotionBeforeQueueing(nsecs_t when, uint32_t& policyFlags); - virtual bool interceptKeyBeforeDispatching(const sp<InputWindowHandle>& inputWindowHandle, + virtual nsecs_t interceptKeyBeforeDispatching( + const sp<InputWindowHandle>& inputWindowHandle, const KeyEvent* keyEvent, uint32_t policyFlags); virtual bool dispatchUnhandledKey(const sp<InputWindowHandle>& inputWindowHandle, const KeyEvent* keyEvent, uint32_t policyFlags, KeyEvent* outFallbackKeyEvent); @@ -819,12 +826,6 @@ void NativeInputManager::interceptMotionBeforeQueueing(nsecs_t when, uint32_t& p void NativeInputManager::handleInterceptActions(jint wmActions, nsecs_t when, uint32_t& policyFlags) { - enum { - WM_ACTION_PASS_TO_USER = 1, - WM_ACTION_POKE_USER_ACTIVITY = 2, - WM_ACTION_GO_TO_SLEEP = 4, - }; - if (wmActions & WM_ACTION_GO_TO_SLEEP) { #if DEBUG_INPUT_DISPATCHER_POLICY LOGD("handleInterceptActions: Going to sleep."); @@ -848,14 +849,14 @@ void NativeInputManager::handleInterceptActions(jint wmActions, nsecs_t when, } } -bool NativeInputManager::interceptKeyBeforeDispatching( +nsecs_t NativeInputManager::interceptKeyBeforeDispatching( const sp<InputWindowHandle>& inputWindowHandle, const KeyEvent* keyEvent, uint32_t policyFlags) { // Policy: // - Ignore untrusted events and pass them along. // - Filter normal events and trusted injected events through the window manager policy to // handle the HOME key and the like. - bool result = false; + nsecs_t result = 0; if (policyFlags & POLICY_FLAG_TRUSTED) { JNIEnv* env = jniEnv(); @@ -863,13 +864,19 @@ bool NativeInputManager::interceptKeyBeforeDispatching( jobject inputWindowHandleObj = getInputWindowHandleObjLocalRef(env, inputWindowHandle); jobject keyEventObj = android_view_KeyEvent_fromNative(env, keyEvent); if (keyEventObj) { - jboolean consumed = env->CallBooleanMethod(mCallbacksObj, + jlong delayMillis = env->CallLongMethod(mCallbacksObj, gCallbacksClassInfo.interceptKeyBeforeDispatching, inputWindowHandleObj, keyEventObj, policyFlags); bool error = checkAndClearExceptionFromCallback(env, "interceptKeyBeforeDispatching"); android_view_KeyEvent_recycle(env, keyEventObj); env->DeleteLocalRef(keyEventObj); - result = consumed && !error; + if (!error) { + if (delayMillis < 0) { + result = -1; + } else if (delayMillis > 0) { + result = milliseconds_to_nanoseconds(delayMillis); + } + } } else { LOGE("Failed to obtain key event object for interceptKeyBeforeDispatching."); } @@ -1433,7 +1440,7 @@ int register_android_server_InputManager(JNIEnv* env) { GET_METHOD_ID(gCallbacksClassInfo.interceptKeyBeforeDispatching, clazz, "interceptKeyBeforeDispatching", - "(Lcom/android/server/wm/InputWindowHandle;Landroid/view/KeyEvent;I)Z"); + "(Lcom/android/server/wm/InputWindowHandle;Landroid/view/KeyEvent;I)J"); GET_METHOD_ID(gCallbacksClassInfo.dispatchUnhandledKey, clazz, "dispatchUnhandledKey", diff --git a/telephony/java/com/android/internal/telephony/cdma/CDMALTEPhone.java b/telephony/java/com/android/internal/telephony/cdma/CDMALTEPhone.java index c2b9e4f3b22e..4f50d2483f26 100644 --- a/telephony/java/com/android/internal/telephony/cdma/CDMALTEPhone.java +++ b/telephony/java/com/android/internal/telephony/cdma/CDMALTEPhone.java @@ -18,13 +18,17 @@ package com.android.internal.telephony.cdma; import android.content.ContentValues; import android.content.Context; +import android.content.SharedPreferences; import android.database.SQLException; import android.net.Uri; +import android.os.AsyncResult; import android.os.Message; +import android.preference.PreferenceManager; import android.provider.Telephony; import android.util.Log; import com.android.internal.telephony.CommandsInterface; +import com.android.internal.telephony.OperatorInfo; import com.android.internal.telephony.Phone; import com.android.internal.telephony.PhoneNotifier; import com.android.internal.telephony.PhoneProxy; @@ -41,6 +45,18 @@ public class CDMALTEPhone extends CDMAPhone { /** Secondary SMSDispatcher for 3GPP format messages. */ SMSDispatcher m3gppSMS; + /** + * Small container class used to hold information relevant to + * the carrier selection process. operatorNumeric can be "" + * if we are looking for automatic selection. operatorAlphaLong is the + * corresponding operator name. + */ + private static class NetworkSelectMessage { + public Message message; + public String operatorNumeric; + public String operatorAlphaLong; + } + // Constructors public CDMALTEPhone(Context context, CommandsInterface ci, PhoneNotifier notifier) { super(context, ci, notifier, false); @@ -48,6 +64,20 @@ public class CDMALTEPhone extends CDMAPhone { } @Override + public void handleMessage (Message msg) { + AsyncResult ar; + Message onComplete; + switch (msg.what) { + // handle the select network completion callbacks. + case EVENT_SET_NETWORK_MANUAL_COMPLETE: + handleSetSelectNetwork((AsyncResult) msg.obj); + break; + default: + super.handleMessage(msg); + } + } + + @Override protected void initSstIcc() { mSST = new CdmaLteServiceStateTracker(this); mIccRecords = new CdmaLteUiccRecords(this); @@ -109,6 +139,58 @@ public class CDMALTEPhone extends CDMAPhone { } @Override + public void + selectNetworkManually(OperatorInfo network, + Message response) { + // wrap the response message in our own message along with + // the operator's id. + NetworkSelectMessage nsm = new NetworkSelectMessage(); + nsm.message = response; + nsm.operatorNumeric = network.getOperatorNumeric(); + nsm.operatorAlphaLong = network.getOperatorAlphaLong(); + + // get the message + Message msg = obtainMessage(EVENT_SET_NETWORK_MANUAL_COMPLETE, nsm); + + mCM.setNetworkSelectionModeManual(network.getOperatorNumeric(), msg); + } + + /** + * Used to track the settings upon completion of the network change. + */ + private void handleSetSelectNetwork(AsyncResult ar) { + // look for our wrapper within the asyncresult, skip the rest if it + // is null. + if (!(ar.userObj instanceof NetworkSelectMessage)) { + if (DBG) Log.d(LOG_TAG, "unexpected result from user object."); + return; + } + + NetworkSelectMessage nsm = (NetworkSelectMessage) ar.userObj; + + // found the object, now we send off the message we had originally + // attached to the request. + if (nsm.message != null) { + if (DBG) Log.d(LOG_TAG, "sending original message to recipient"); + AsyncResult.forMessage(nsm.message, ar.result, ar.exception); + nsm.message.sendToTarget(); + } + + // open the shared preferences editor, and write the value. + // nsm.operatorNumeric is "" if we're in automatic.selection. + SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext()); + SharedPreferences.Editor editor = sp.edit(); + editor.putString(NETWORK_SELECTION_KEY, nsm.operatorNumeric); + editor.putString(NETWORK_SELECTION_NAME_KEY, nsm.operatorAlphaLong); + + // commit and log the result. + if (! editor.commit()) { + Log.e(LOG_TAG, "failed to commit network selection preference"); + } + + } + + @Override public boolean updateCurrentCarrierInProvider() { if (mIccRecords != null) { try { diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java index 8f5a2eb930a7..3d6cd6821c40 100755 --- a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java +++ b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java @@ -726,7 +726,7 @@ public class CdmaServiceStateTracker extends ServiceStateTracker { isPrlLoaded = false; } if (!isPrlLoaded) { - newSS.setCdmaRoamingIndicator(EriInfo.ROAMING_INDICATOR_FLASH); + newSS.setCdmaRoamingIndicator(EriInfo.ROAMING_INDICATOR_OFF); } else if (!isSidsAllZeros()) { if (!namMatch && !mIsInPrl) { // Use default diff --git a/tests/StatusBar/src/com/android/statusbartest/StatusBarTest.java b/tests/StatusBar/src/com/android/statusbartest/StatusBarTest.java index 7c94c2d078de..94ad620bd801 100644 --- a/tests/StatusBar/src/com/android/statusbartest/StatusBarTest.java +++ b/tests/StatusBar/src/com/android/statusbartest/StatusBarTest.java @@ -114,9 +114,9 @@ public class StatusBarTest extends TestActivity // v.setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE); // } // }, - new Test("systemUiVisibility: STATUS_BAR_DISABLE_NAVIGATION") { + new Test("systemUiVisibility: STATUS_BAR_DISABLE_HOME") { public void run() { - mListView.setSystemUiVisibility(View.STATUS_BAR_DISABLE_NAVIGATION); + mListView.setSystemUiVisibility(View.STATUS_BAR_DISABLE_HOME); } }, new Test("Double Remove") { @@ -227,16 +227,21 @@ public class StatusBarTest extends TestActivity }, 3000); } }, - new Test("Disable Navigation") { + new Test("Disable Home (StatusBarManager)") { public void run() { - mStatusBarManager.disable(StatusBarManager.DISABLE_NAVIGATION); + mStatusBarManager.disable(StatusBarManager.DISABLE_HOME); } }, - new Test("Disable Back") { + new Test("Disable Back (StatusBarManager)") { public void run() { mStatusBarManager.disable(StatusBarManager.DISABLE_BACK); } }, + new Test("Disable Recent (StatusBarManager)") { + public void run() { + mStatusBarManager.disable(StatusBarManager.DISABLE_RECENT); + } + }, new Test("Disable Clock") { public void run() { mStatusBarManager.disable(StatusBarManager.DISABLE_CLOCK); |