diff options
103 files changed, 1508 insertions, 925 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/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index 7a7e4f4b54ab..3eb764759140 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -2124,6 +2124,9 @@ public abstract class PackageManager { if (pkg == null) { return null; } + if ((flags & GET_SIGNATURES) != 0) { + packageParser.collectCertificates(pkg, 0); + } return PackageParser.generatePackageInfo(pkg, null, flags, 0, 0); } diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java index 8483b4f0cf44..4bc0892d3d75 100644 --- a/core/java/android/provider/ContactsContract.java +++ b/core/java/android/provider/ContactsContract.java @@ -187,6 +187,59 @@ public final class ContactsContract { public static final String DEFERRED_SNIPPETING_QUERY = "deferred_snippeting_query"; /** + * <p> + * API for obtaining a pre-authorized version of a URI that normally requires special + * permission (beyond READ_CONTACTS) to read. The caller obtaining the pre-authorized URI + * must already have the necessary permissions to access the URI; otherwise a + * {@link SecurityException} will be thrown. + * </p> + * <p> + * The authorized URI returned in the bundle contains an expiring token that allows the + * caller to execute the query without having the special permissions that would normally + * be required. + * </p> + * <p> + * This API does not access disk, and should be safe to invoke from the UI thread. + * </p> + * <p> + * Example usage: + * <pre> + * Uri profileUri = ContactsContract.Profile.CONTENT_VCARD_URI; + * Bundle uriBundle = new Bundle(); + * uriBundle.putParcelable(ContactsContract.Authorization.KEY_URI_TO_AUTHORIZE, uri); + * Bundle authResponse = getContext().getContentResolver().call( + * ContactsContract.AUTHORITY_URI, + * ContactsContract.Authorization.AUTHORIZATION_METHOD, + * null, // String arg, not used. + * uriBundle); + * if (authResponse != null) { + * Uri preauthorizedProfileUri = (Uri) authResponse.getParcelable( + * ContactsContract.Authorization.KEY_AUTHORIZED_URI); + * // This pre-authorized URI can be queried by a caller without READ_PROFILE + * // permission. + * } + * </pre> + * </p> + * @hide + */ + public static final class Authorization { + /** + * The method to invoke to create a pre-authorized URI out of the input argument. + */ + public static final String AUTHORIZATION_METHOD = "authorize"; + + /** + * The key to set in the outbound Bundle with the URI that should be authorized. + */ + public static final String KEY_URI_TO_AUTHORIZE = "uri_to_authorize"; + + /** + * The key to retrieve from the returned Bundle to obtain the pre-authorized URI. + */ + public static final String KEY_AUTHORIZED_URI = "authorized_uri"; + } + + /** * @hide */ public static final class Preferences { diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 3d2a3cefeab2..5754e60d0815 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -4053,6 +4053,14 @@ public final class Settings { public static final String PACKAGE_VERIFIER_TIMEOUT = "verifier_timeout"; /** + * Duration in milliseconds before pre-authorized URIs for the contacts + * provider should expire. + * @hide + */ + public static final String CONTACTS_PREAUTH_URI_EXPIRATION = + "contacts_preauth_uri_expiration"; + + /** * This are the settings to be backed up. * * NOTE: Settings are backed up and restored in the order they appear 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/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..1c22a0b733f0 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -2079,10 +2079,12 @@ public class WebView extends AbsoluteLayout * <p> * The 'data' scheme URL formed by this method uses the default US-ASCII * charset. If you need need to set a different charset, you should form a - * 'data' scheme URL which specifies a charset parameter and call - * {@link #loadUrl(String)} instead. + * 'data' scheme URL which explicitly specifies a charset parameter in the + * mediatype portion of the URL and call {@link #loadUrl(String)} instead. + * Note that the charset obtained from the mediatype portion of a data URL + * always overrides that specified in the HTML or XML document itself. * @param data A String of data in the given encoding. - * @param mimeType The MIMEType of the data, e.g. 'text/html'. + * @param mimeType The MIME type of the data, e.g. 'text/html'. * @param encoding The encoding of the data. */ public void loadData(String data, String mimeType, String encoding) { @@ -2986,6 +2988,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/res/res/drawable-hdpi/ic_menu_cut_holo_dark.png b/core/res/res/drawable-hdpi/ic_menu_cut_holo_dark.png Binary files differindex 81c52b0b5ea1..3e00747b27a2 100644 --- a/core/res/res/drawable-hdpi/ic_menu_cut_holo_dark.png +++ b/core/res/res/drawable-hdpi/ic_menu_cut_holo_dark.png diff --git a/core/res/res/drawable-hdpi/ic_menu_cut_holo_light.png b/core/res/res/drawable-hdpi/ic_menu_cut_holo_light.png Binary files differindex 15500c341ed6..c760936ee152 100644 --- a/core/res/res/drawable-hdpi/ic_menu_cut_holo_light.png +++ b/core/res/res/drawable-hdpi/ic_menu_cut_holo_light.png diff --git a/core/res/res/drawable-hdpi/stat_notify_wifi_in_range.png b/core/res/res/drawable-hdpi/stat_notify_wifi_in_range.png Binary files differindex f3aaa276fc8a..8148ab8f8427 100644 --- a/core/res/res/drawable-hdpi/stat_notify_wifi_in_range.png +++ b/core/res/res/drawable-hdpi/stat_notify_wifi_in_range.png diff --git a/core/res/res/drawable-hdpi/stat_sys_speakerphone.png b/core/res/res/drawable-hdpi/stat_sys_speakerphone.png Binary files differindex a9af4a88c849..c63ca94db2ab 100644 --- a/core/res/res/drawable-hdpi/stat_sys_speakerphone.png +++ b/core/res/res/drawable-hdpi/stat_sys_speakerphone.png diff --git a/core/res/res/drawable-mdpi/ic_menu_cut_holo_dark.png b/core/res/res/drawable-mdpi/ic_menu_cut_holo_dark.png Binary files differindex 85f3cb2ad632..baa5427ef3bd 100644 --- a/core/res/res/drawable-mdpi/ic_menu_cut_holo_dark.png +++ b/core/res/res/drawable-mdpi/ic_menu_cut_holo_dark.png diff --git a/core/res/res/drawable-mdpi/ic_menu_cut_holo_light.png b/core/res/res/drawable-mdpi/ic_menu_cut_holo_light.png Binary files differindex 77f92fb56874..8e6a93fe4fd0 100644 --- a/core/res/res/drawable-mdpi/ic_menu_cut_holo_light.png +++ b/core/res/res/drawable-mdpi/ic_menu_cut_holo_light.png diff --git a/core/res/res/drawable-mdpi/stat_notify_wifi_in_range.png b/core/res/res/drawable-mdpi/stat_notify_wifi_in_range.png Binary files differindex 747cb97a5a36..b7e2a6a5d446 100644 --- a/core/res/res/drawable-mdpi/stat_notify_wifi_in_range.png +++ b/core/res/res/drawable-mdpi/stat_notify_wifi_in_range.png diff --git a/core/res/res/drawable-mdpi/stat_sys_speakerphone.png b/core/res/res/drawable-mdpi/stat_sys_speakerphone.png Binary files differindex e8c6374d2b41..ec7ef0cf4f22 100644 --- a/core/res/res/drawable-mdpi/stat_sys_speakerphone.png +++ b/core/res/res/drawable-mdpi/stat_sys_speakerphone.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_cut_holo_dark.png b/core/res/res/drawable-xhdpi/ic_menu_cut_holo_dark.png Binary files differindex 16632b196392..7aa875030826 100644 --- a/core/res/res/drawable-xhdpi/ic_menu_cut_holo_dark.png +++ b/core/res/res/drawable-xhdpi/ic_menu_cut_holo_dark.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_cut_holo_light.png b/core/res/res/drawable-xhdpi/ic_menu_cut_holo_light.png Binary files differindex 6e007c76d2fd..d4e4d81f367d 100644 --- a/core/res/res/drawable-xhdpi/ic_menu_cut_holo_light.png +++ b/core/res/res/drawable-xhdpi/ic_menu_cut_holo_light.png diff --git a/core/res/res/drawable-xhdpi/stat_notify_wifi_in_range.png b/core/res/res/drawable-xhdpi/stat_notify_wifi_in_range.png Binary files differindex 6bb7512cbf82..0dbae577346c 100644 --- a/core/res/res/drawable-xhdpi/stat_notify_wifi_in_range.png +++ b/core/res/res/drawable-xhdpi/stat_notify_wifi_in_range.png diff --git a/core/res/res/drawable-xhdpi/stat_sys_speakerphone.png b/core/res/res/drawable-xhdpi/stat_sys_speakerphone.png Binary files differindex 3ac1b88d28a2..6938ab4de18a 100644 --- a/core/res/res/drawable-xhdpi/stat_sys_speakerphone.png +++ b/core/res/res/drawable-xhdpi/stat_sys_speakerphone.png diff --git a/docs/html/guide/developing/devices/emulator.jd b/docs/html/guide/developing/devices/emulator.jd index fe00531b6221..821127526a45 100644 --- a/docs/html/guide/developing/devices/emulator.jd +++ b/docs/html/guide/developing/devices/emulator.jd @@ -32,6 +32,12 @@ parent.link=index.html </ol> </li> </ol> + + <h2>See also</h2> + <ol> + <li><a href="{@docRoot}guide/developing/tools/emulator.html">Android Emulator</a></li> + <li><a href="{@docRoot}guide/developing/devices/managing-avds.html">Managing AVDs with AVD Manager</a></li> + </ol> </div> </div> @@ -63,8 +69,6 @@ on the data channel.</p> - - <h2 id="overview">Overview</h2> <p>The Android emulator is a QEMU-based application that provides a virtual ARM @@ -166,7 +170,8 @@ on the Emulator</a> for information about how to install your application.</p> <p>To stop an emulator instance, just close the emulator's window.</p> - +<p>For a reference of the emulator's startup commands and keyboard mapping, see +the <a href="{@docRoot}guide/developing/tools/emulator.html">Android Emulator</a> document.</p> diff --git a/docs/html/guide/developing/tools/emulator.jd b/docs/html/guide/developing/tools/emulator.jd index ff667f2176fb..5151ec14db47 100644 --- a/docs/html/guide/developing/tools/emulator.jd +++ b/docs/html/guide/developing/tools/emulator.jd @@ -3,6 +3,25 @@ parent.title=Tools parent.link=index.html @jd:body +<div id="qv-wrapper"> +<div id="qv"> + + <h2>In this document</h2> + <ol> + <li><a href="#startup-options">Emulator Startup Options</a></li> + <li><a href="#KeyMapping">Emulator Keyboard Mapping</a></li> + </ol> + + <h2>See also</h2> + <ol> + <li><a href="{@docRoot}guide/developing/devices/emulator.html">Using the Android Emulator</a></li> + <li><a href="{@docRoot}guide/developing/devices/index.html">Managing Virtual Devices</a></li> + </ol> + +</div> +</div> + + <p>The Android SDK includes a mobile device emulator — a virtual mobile device that runs on your computer. The emulator lets you develop and test Android applications without using a physical device.</p> @@ -451,7 +470,10 @@ Managing Virtual Devices with AVD Manager</a>. <td>See comments for <code>-skin</code>, above.</td></tr> </table> -<h2>Emulator Keyboard Mapping</h2> + + +<h2 id="KeyMapping">Emulator Keyboard Mapping</h2> + <p>The table below summarizes the mappings between the emulator keys and and the keys of your keyboard. </p> <p class="table-caption"><strong>Table 2.</strong> Emulator keyboard mapping</p> diff --git a/docs/html/index.jd b/docs/html/index.jd index a8b61bfb9999..d4129938132c 100644 --- a/docs/html/index.jd +++ b/docs/html/index.jd @@ -129,15 +129,14 @@ href="{@docRoot}resources/dashboard/platform-versions.html">Learn more »</ 'sdk': { 'layout':"imgLeft", 'icon':"sdk-small.png", - 'name':"Android 3.2", - 'img':"honeycomb-android.png", - 'title':"Android 3.2 is here!", - 'desc': "<p>Android 3.2 is a minor feature update that includes new APIs that allow you to " -+ "better target your layouts for specific screen sizes and other miscellaneous new APIs.</p>" + 'name':"Android 4.0", + 'img':"ics-android.png", + 'title':"Ice Cream Sandwich!", + 'desc': "<br/><br/><br/><p>Oh my goodness, that looks tasty!</p>" +/* + "<p>For more information about all the changes in Android 3.2, read the " + "<a href='{@docRoot}sdk/android-3.2.html'>version notes</a> and <a " + "href='{@docRoot}sdk/api_diff/13/changes.html'>diff report</a>.</p>" -/* + "<p>If you have an existing SDK, add Android 3.0 as an " + "<a href='{@docRoot}sdk/adding-components.html'>SDK " + "component</a>. If you're new to Android, install the " diff --git a/docs/html/offline.jd b/docs/html/offline.jd index 1064a9924ef8..5f8e37ce91ad 100644 --- a/docs/html/offline.jd +++ b/docs/html/offline.jd @@ -29,7 +29,7 @@ application</li> especially <a href="{@docRoot}resources/samples/ApiDemos/index.html">API Demos</a></li> <li>Read the <a href="{@docRoot}guide/topics/fundamentals/index.html">Application Fundamentals</a></li> - <li>Read the <a href="{@docRoot}guide/developing/index.html">Overview</a> for using the SDK + <li>Read the <a href="{@docRoot}guide/developing/index.html">Introduction</a> for using the SDK tools</li> </ul> </div> @@ -44,9 +44,6 @@ will help you setup your development environment.</p> <p>There's no additional setup.</p> -<p>New Android platforms are saved in the <code><sdk>/platforms/</code> directory of -your existing SDK and new add-ons are saved in the <code><sdk>/add-ons/</code> directory.</p> - <div class="note"> <p><strong>Note:</strong> You are currently viewing the offline version of the Android developer diff --git a/docs/html/resources/resources-data.js b/docs/html/resources/resources-data.js index 3e673a554d0d..b15e8474a353 100644 --- a/docs/html/resources/resources-data.js +++ b/docs/html/resources/resources-data.js @@ -608,7 +608,7 @@ var ANDROID_RESOURCES = [ } }, { - tags: ['sample', 'accountsync'], + tags: ['sample', 'accountsync', 'updated'], path: 'samples/SampleSyncAdapter/index.html', title: { en: 'SampleSyncAdapter' diff --git a/docs/html/resources/samples/images/hcgallery-phone1.png b/docs/html/resources/samples/images/hcgallery-phone1.png Binary files differnew file mode 100644 index 000000000000..9f0c2805581d --- /dev/null +++ b/docs/html/resources/samples/images/hcgallery-phone1.png diff --git a/docs/html/resources/samples/images/hcgallery-phone2.png b/docs/html/resources/samples/images/hcgallery-phone2.png Binary files differnew file mode 100644 index 000000000000..b049a6559ab8 --- /dev/null +++ b/docs/html/resources/samples/images/hcgallery-phone2.png diff --git a/docs/html/sdk/android-4.0.jd b/docs/html/sdk/android-4.0.jd index 8f7ac5585936..b4fbe724979b 100644 --- a/docs/html/sdk/android-4.0.jd +++ b/docs/html/sdk/android-4.0.jd @@ -10,6 +10,7 @@ sdk.platform.apiLevel=14 <ol> <li><a href="#relnotes">Revisions</a></li> <li><a href="#api">API Overview</a></li> + <li><a href="#Honeycomb">Previous APIs</a></li> <li><a href="#api-diff">API Differences Report</a></li> <li><a href="#api-level">API Level</a></li> <li><a href="#apps">Built-in Applications</a></li> @@ -45,14 +46,14 @@ information, see <a href="{@docRoot}sdk/adding-components.html">Adding SDK Components</a>. If you are new to Android, <a href="{@docRoot}sdk/index.html">download the SDK Starter Package</a> first.</p> -<p>For a high-level introduction to the new user and developer features in Android 4.0, see the -<a href="http://developer.android.com/sdk/android-4.0-highlights.html">Platform Highlights</a>.</p> - <p class="note"><strong>Reminder:</strong> If you've already published an Android application, please test your application on Android {@sdkPlatformVersion} as soon as possible to be sure your application provides the best experience possible on the latest Android-powered devices.</p> +<p>For a high-level introduction to the new user and developer features in Android 4.0, see the +<a href="http://developer.android.com/sdk/android-4.0-highlights.html">Platform Highlights</a>.</p> + <h2 id="relnotes">Revisions</h2> @@ -92,21 +93,21 @@ class="toggle-content-img" alt="" /> <div class="toggle-content-toggleme" style="padding-left:2em;"> <ol class="toc" style="margin-left:-1em"> - <li><a href="#Contacts">Contacts</a></li> - <li><a href="#Calendar">Calendar</a></li> + <li><a href="#Contacts">Contact Provider</a></li> + <li><a href="#Calendar">Calendar Provider</a></li> + <li><a href="#Voicemail">Voicemail Provider</a></li> <li><a href="#Camera">Camera</a></li> <li><a href="#Multimedia">Multimedia</a></li> <li><a href="#Bluetooth">Bluetooth</a></li> <li><a href="#AndroidBeam">Android Beam (NDEF Push with NFC)</a></li> <li><a href="#P2pWiFi">Peer-to-peer Wi-Fi</a></li> <li><a href="#NetworkData">Network Data</a></li> - <li><a href="#Sensors">Device Sensors</a></li> - <li><a href="#Renderscript">Renderscript</a></li> + <li><a href="#RenderScript">RenderScript</a></li> <li><a href="#A11y">Accessibility</a></li> <li><a href="#Enterprise">Enterprise</a></li> - <li><a href="#Voicemail">Voicemail</a></li> - <li><a href="#SpellChecker">Spell Checker Services</a></li> + <li><a href="#Sensors">Device Sensors</a></li> <li><a href="#TTS">Text-to-speech Engines</a></li> + <li><a href="#SpellChecker">Spell Checker Services</a></li> <li><a href="#ActionBar">Action Bar</a></li> <li><a href="#UI">User Interface and Views</a></li> <li><a href="#Properties">Properties</a></li> @@ -123,86 +124,96 @@ class="toggle-content-img" alt="" /> -<h3 id="Contacts">Contacts</h3> +<h3 id="Contacts">Contact Provider</h3> -<p>The Contact APIs that are defined by the {@link android.provider.ContactsContract} provider have -been extended to support new features such as a personal profile for the device owner, large contact -photos, and the ability for users to invite individual contacts to social networks that are -installed on the device.</p> +<p>The contact APIs that are defined by the {@link android.provider.ContactsContract} provider have +been extended to support new features such as a personal profile for the device owner, high +resolution contact photos, and the ability for users to invite individual contacts to social +networks that are installed on the device.</p> <h4>User Profile</h4> <p>Android now includes a personal profile that represents the device owner, as defined by the -{@link -android.provider.ContactsContract.Profile} table. Social apps that maintain a user identity can -contribute to the user's profile data by creating a new {@link +{@link android.provider.ContactsContract.Profile} table. Social apps that maintain a user identity +can contribute to the user's profile data by creating a new {@link android.provider.ContactsContract.RawContacts} entry within the {@link android.provider.ContactsContract.Profile}. That is, raw contacts that represent the device user do not belong in the traditional raw contacts table defined by the {@link android.provider.ContactsContract.RawContacts} Uri; instead, you must add a profile raw contact in the table at {@link android.provider.ContactsContract.Profile#CONTENT_RAW_CONTACTS_URI}. Raw -contacts in this table are then aggregated into the single user-visible profile information.</p> +contacts in this table are then aggregated into the single user-visible profile labeled "Me".</p> <p>Adding a new raw contact for the profile requires the {@link android.Manifest.permission#WRITE_PROFILE} permission. Likewise, in order to read from the profile table, you must request the {@link android.Manifest.permission#READ_PROFILE} permission. However, -reading the user profile should not be required by most apps, even when contributing data to the -profile. Reading the user profile is a sensitive permission and users will be very skeptical of apps -that request reading their profile information.</p> +most apps should need to read the user profile, even when contributing data to the +profile. Reading the user profile is a sensitive permission and you should expect users to be +skeptical of apps that request it.</p> + <h4>Large photos</h4> <p>Android now supports high resolution photos for contacts. Now, when you push a photo into a -contact -record, the system processes it into both a 96x96 thumbnail (as it has previously) and a 256x256 -"display photo" stored in a new file-based photo store (the exact dimensions that the system chooses -may vary in the future). You can add a large photo to a contact by putting a large photo in the -usual {@link android.provider.ContactsContract.CommonDataKinds.Photo#PHOTO} column of a data row, -which the system will then process into the appropriate thumbnail and display photo records.</p> +contact record, the system processes it into both a 96x96 thumbnail (as it has previously) and a +256x256 "display photo" that's stored in a new file-based photo store (the exact dimensions that the +system chooses may vary in the future). You can add a large photo to a contact by putting a large +photo in the usual {@link android.provider.ContactsContract.CommonDataKinds.Photo#PHOTO} column of a +data row, which the system will then process into the appropriate thumbnail and display photo +records.</p> + <h4>Invite Intent</h4> -<p>The {@link android.provider.ContactsContract.Intents#INVITE_CONTACT} intent action allows you to -invoke an action that indicates the user wants to add a contact to a social network that understand -this intent and use it to invite the contact specified in the contact to that social network.</p> - -<p>Apps that use a sync adapter to provide information about contacts can register with the system -to -receive the invite intent when there’s an opportunity for the user to “invite†a contact to the -app’s social network (such as from a contact card in the People app). To receive the invite intent, -you simply need to add the {@code inviteContactActivity} attribute to your app’s XML sync -configuration file, providing a fully-qualified name of the activity that the system should start -when the user wants to “invite†a contact in your social network. The activity that starts can then -retrieve the URI for the contact in question from the intent’s data and perform the necessary work -to -invite that contact to the network or add the person to the user’s connections.</p> +<p>The {@link android.provider.ContactsContract.Intents#INVITE_CONTACT} intent action allows an app +to invoke an action that indicates the user wants to add a contact to a social network. The app +receiving the app uses it to invite the specified contact to that +social network. Most apps will be on the receiving-end of this operation. For example, the +built-in People app invokes the invite intent when the user selects "Add connection" for a specific +social app that's listed in a person's contact details.</p> + +<p>To make your app visible as in the "Add connection" list, your app must provide a sync adapter to +sync contact information from your social network. You must then indicate to the system that your +app responds to the {@link android.provider.ContactsContract.Intents#INVITE_CONTACT} intent by +adding the {@code inviteContactActivity} attribute to your app’s sync configuration file, with a +fully-qualified name of the activity that the system should start when sending the invite intent. +The activity that starts can then retrieve the URI for the contact in question from the intent’s +data and perform the necessary work to invite that contact to the network or add the person to the +user’s connections.</p> + +<p>See the <a href="{@docRoot}resources/samples/SampleSyncAdapter/index.html">Sample Sync +Adapter</a> app for an example (specifically, see the <a +href="{@docRoot}resources/samples/SampleSyncAdapter/res/xml-v14/contacts.html">contacts.xml</a> +file).</p> + <h4>Contact Usage Feedback</h4> <p>The new {@link android.provider.ContactsContract.DataUsageFeedback} APIs allow you to help track how often the user uses particular methods of contacting people, such as how often the user uses each phone number or e-mail address. This information helps improve the ranking for each contact -method associated with each person and provide such contact methods as suggestions.</p> +method associated with each person and provide better suggestions for contacting each person.</p> -<h3 id="Calendar">Calendar</h3> +<h3 id="Calendar">Calendar Provider</h3> -<p>The new calendar API allows you to access and modify the user’s calendars and events. The -calendar -APIs are provided with the {@link android.provider.CalendarContract} provider. Using the calendar -provider, you can:</p> -<ul> -<li>Read, write, and modify calendars.</li> -<li>Add and modify events, attendees, reminders, and alarms.</li> -</ul> +<p>The new calendar APIs allow you to access and modify the user’s calendars and events using the +Calendar Provider. You can read, add, modify and delete calendars, events, attendees, reminders and +alerts.</p> + +<p>A variety of apps and widgets can use these APIs to read and modify calendar events. However, +some of the most compelling use cases are sync adapters that synchronize the user's calendar from +other calendar services with the Calendar Provider, in order to offer a unified location for +all the user's events. Google Calendar, for example, uses a sync adapter to synchronize Google +Calendar events with the Calendar Provider, which can then be viewed with Android's built-in +Calendar app.</p> -<p>{@link android.provider.CalendarContract} defines the data model of calendar and event-related -information. All of the user’s calendar data is stored in a number of tables defined by subclasses -of {@link android.provider.CalendarContract}:</p> +<p>The data model for calendars and event-related information in the Calendar Provider is +defined by {@link android.provider.CalendarContract}. All the user’s calendar data is stored in a +number of tables defined by various subclasses of {@link android.provider.CalendarContract}:</p> <ul> <li>The {@link android.provider.CalendarContract.Calendars} table holds the calendar-specific @@ -210,11 +221,10 @@ information. Each row in this table contains the details for a single calendar, color, sync information, and so on.</li> <li>The {@link android.provider.CalendarContract.Events} table holds event-specific information. -Each -row in this table has the information for a single event. It contains information such as event -title, location, start time, end time, and so on. The event can occur one-time or can recur multiple -times. Attendees, reminders, and extended properties are stored in separate tables and reference the -event’s _ID to link them with the event.</li> +Each row in this table contains the information for a single event, such as the +event title, location, start time, end time, and so on. The event can occur one time or recur +multiple times. Attendees, reminders, and extended properties are stored in separate tables and +use the event’s {@code _ID} to link them with the event.</li> <li>The {@link android.provider.CalendarContract.Instances} table holds the start and end time for occurrences of an event. Each row in this table represents a single occurrence. For one-time events @@ -223,47 +233,93 @@ automatically generated to correspond to the multiple occurrences of that event. <li>The {@link android.provider.CalendarContract.Attendees} table holds the event attendee or guest information. Each row represents a single guest of an event. It specifies the type of guest the -person is and the person’s attendance response for the event.</li> +person is and the person’s response for the event.</li> <li>The {@link android.provider.CalendarContract.Reminders} table holds the alert/notification data. Each row represents a single alert for an event. An event can have multiple reminders. The number of -reminders per event is specified in MAX_REMINDERS, which is set by the Sync Adapter that owns the -given calendar. Reminders are specified in minutes before the event and have a type.</li> +reminders per event is specified in {@code MAX_REMINDERS}, which is set by the sync adapter that +owns the given calendar. Reminders are specified in number-of-minutes before the event is +scheduled and specify an alarm method such as to use an alert, email, or SMS to remind +the user.</li> <li>The {@link android.provider.CalendarContract.ExtendedProperties} table hold opaque data fields -used -by the sync adapter. The provider takes no action with items in this table except to delete them -when their related events are deleted.</li> +used by the sync adapter. The provider takes no action with items in this table except to delete +them when their related events are deleted.</li> +</ul> + +<p>To access a user’s calendar data with the Calendar Provider, your application must request +the {@link android.Manifest.permission#READ_CALENDAR} permission (for read access) and +{@link android.Manifest.permission#WRITE_CALENDAR} (for write access).</p> + + +<h4>Event intent</h4> + +<p>If all you want to do is add an event to the user’s calendar, you can use an +{@link android.content.Intent#ACTION_INSERT} intent with a {@code "vnd.android.cursor.item/event"} +MIME type to start an activity in the Calendar app that creates new events. Using the intent does +not require any permission and you can specify event details with the following extras:</p> + +<ul> + <li>{@link android.provider.CalendarContract.EventsColumns#TITLE Events.TITLE}: Name for the +event</li> + <li>{@link +android.provider.CalendarContract#EXTRA_EVENT_BEGIN_TIME CalendarContract.EXTRA_EVENT_BEGIN_TIME}: +Event begin time in milliseconds from the +epoch</li> + <li>{@link +android.provider.CalendarContract#EXTRA_EVENT_END_TIME CalendarContract.EXTRA_EVENT_END_TIME}: Event +end time in milliseconds from the epoch</li> + <li>{@link android.provider.CalendarContract.EventsColumns#EVENT_LOCATION Events.EVENT_LOCATION}: +Location of the event</li> + <li>{@link android.provider.CalendarContract.EventsColumns#DESCRIPTION Events.DESCRIPTION}: Event +description</li> + <li>{@link android.content.Intent#EXTRA_EMAIL Intent.EXTRA_EMAIL}: Email addresses of those to +invite</li> + <li>{@link android.provider.CalendarContract.EventsColumns#RRULE Events.RRULE}: The recurrence +rule for the event</li> + <li>{@link android.provider.CalendarContract.EventsColumns#ACCESS_LEVEL Events.ACCESS_LEVEL}: +Whether the event is private or public</li> + <li>{@link android.provider.CalendarContract.EventsColumns#AVAILABILITY Events.AVAILABILITY}: +Whether the time period of this event allows for other events to be scheduled at the same time</li> </ul> -<p>To access a user’s calendar data with the calendar provider, your application must request -permission from the user by declaring <uses-permission -android:name="android.permission.READ_CALENDAR" /> (for read access) and <uses-permission -android:name="android.permission.WRITE_CALENDAR" /> (for write access) in their manifest files.</p> -<p>However, if all you want to do is add an event to the user’s calendar, you can instead use an -INSERT -{@link android.content.Intent} to start an activity in the Calendar app that creates new events. -Using the intent does not require the WRITE_CALENDAR permission and you can specify the {@link -android.provider.CalendarContract#EXTRA_EVENT_BEGIN_TIME} and {@link -android.provider.CalendarContract#EXTRA_EVENT_END_TIME} extra fields to pre-populate the form with -the time of the event. The values for these times must be in milliseconds from the epoch. You must -also specify {@code “vnd.android.cursor.item/eventâ€} as the intent type.</p> +<h3 id="Voicemail">Voicemail Provider</h3> + +<p>The new voicemail APIs allows applications to add voicemails to a content provider on the device. +Because the APIs currently do not allow third party apps to read all the voicemails from the system, +the only third-party apps that should use the voicemail APIs are those that have voicemail to +deliver to the user. For instance, it’s possible that a user has multiple voicemail sources, such as +one provided by the phone’s service provider and others from VoIP or other alternative voice +services. These apps can use the APIs to add their voicemails to the system for quick playback. The +built-in Phone application presents all voicemails from the Voicemail Provider with a single list. +Although the system’s Phone application is the only application that can read all the voicemails, +each application that provides voicemails can read those that it has added to the system (but cannot +read voicemails from other services).</p> + +<p>The {@link android.provider.VoicemailContract} class defines the content provider for the +voicemail APIs. The subclasses {@link android.provider.VoicemailContract.Voicemails} and {@link +android.provider.VoicemailContract.Status} provide tables in which the Voicemail Providers can +insert voicemail data for storage on the device. For an example of a voicemail provider app, see the +<a href=â€{@docRoot}resources/samples/VoicemailProviderDemo/index.htmlâ€>Voicemail Provider +Demo</a>.</p> + <h3 id="Camera">Camera</h3> -<p>The {@link android.hardware.Camera} APIs now support face detection and control for metering and -focus areas.</p> +<p>The {@link android.hardware.Camera} class now includes APIs for detecting faces and controlling +focus and metering areas.</p> -<h4>Face Detection</h4> -<p>Camera apps can now enhance their abilities with Android’s face detection software, which not -only -detects the face of a subject, but also specific facial features, such as the eyes and mouth. </p> +<h4>Face detection</h4> + +<p>Camera apps can now enhance their abilities with Android’s face detection APIs, which not +only detect the face of a subject, but also specific facial features, such as the eyes and mouth. +</p> <p>To detect faces in your camera application, you must register a {@link android.hardware.Camera.FaceDetectionListener} by calling {@link @@ -271,41 +327,38 @@ android.hardware.Camera#setFaceDetectionListener setFaceDetectionListener()}. Yo your camera surface and start detecting faces by calling {@link android.hardware.Camera#startFaceDetection}.</p> -<p>When the system detects a face, it calls the {@link +<p>When the system detects one or more faces in the camera scene, it calls the {@link android.hardware.Camera.FaceDetectionListener#onFaceDetection onFaceDetection()} callback in your implementation of {@link android.hardware.Camera.FaceDetectionListener}, including an array of {@link android.hardware.Camera.Face} objects.</p> <p>An instance of the {@link android.hardware.Camera.Face} class provides various information about -the -face detected by the camera, including:</p> +the face detected, including:</p> <ul> <li>A {@link android.graphics.Rect} that specifies the bounds of the face, relative to the camera's current field of view</li> <li>An integer betwen 0 and 100 that indicates how confident the system is that the object is a -human -face</li> +human face</li> <li>A unique ID so you can track multiple faces</li> <li>Several {@link android.graphics.Point} objects that indicate where the eyes and mouth are located</li> </ul> -<h4>Focus and Metering Areas</h4> +<h4>Focus and metering areas</h4> -<p>Camera apps can now control the areas that the camera uses for focus and when metering white +<p>Camera apps can now control the areas that the camera uses for focus and for metering white balance -and auto-exposure (when supported by the hardware). Both features use the new {@link -android.hardware.Camera.Area} class to specify the region of the camera’s current view that should -be focused or metered. An instance of the {@link android.hardware.Camera.Area} class defines the -bounds of the area with a {@link android.graphics.Rect} and the weight of the -area—representing the level of importance of that area, relative to other areas in -consideration—with an integer.</p> +and auto-exposure. Both features use the new {@link android.hardware.Camera.Area} class to specify +the region of the camera’s current view that should be focused or metered. An instance of the {@link +android.hardware.Camera.Area} class defines the bounds of the area with a {@link +android.graphics.Rect} and the area's weight—representing the level of importance of that +area, relative to other areas in consideration—with an integer.</p> <p>Before setting either a focus area or metering area, you should first call {@link android.hardware.Camera.Parameters#getMaxNumFocusAreas} or {@link android.hardware.Camera.Parameters#getMaxNumMeteringAreas}, respectively. If these return zero, then -the device does not support the respective feature. </p> +the device does not support the corresponding feature.</p> <p>To specify the focus or metering areas to use, simply call {@link android.hardware.Camera.Parameters#setFocusAreas setFocusAreas()} or {@link @@ -313,17 +366,17 @@ android.hardware.Camera.Parameters#setFocusAreas setMeteringAreas()}. Each take java.util.List} of {@link android.hardware.Camera.Area} objects that indicate the areas to consider for focus or metering. For example, you might implement a feature that allows the user to set the focus area by touching an area of the preview, which you then translate to an {@link -android.hardware.Camera.Area} object and set the focus to that spot. The focus or exposure in that -area will continually update as the scene in the area changes.</p> +android.hardware.Camera.Area} object and request that the camera focus on that area of the scene. +The focus or exposure in that area will continually update as the scene in the area changes.</p> + +<h4>Other camera features</h4> -<h4>Other Camera Features</h4> <ul> -<li>Capture photos during video recording -While recording video, you can now call {@link android.hardware.Camera#takePicture takePicture()} to -save a photo without interrupting the video session. Before doing so, you should call {@link -android.hardware.Camera.Parameters#isVideoSnapshotSupported} to be sure the hardware supports -it.</li> +<li>While recording video, you can now call {@link android.hardware.Camera#takePicture +takePicture()} to save a photo without interrupting the video session. Before doing so, you should +call {@link android.hardware.Camera.Parameters#isVideoSnapshotSupported} to be sure the hardware +supports it.</li> <li>Lock auto exposure and white balance with {@link android.hardware.Camera.Parameters#setAutoExposureLock setAutoExposureLock()} and {@link @@ -331,45 +384,50 @@ android.hardware.Camera.Parameters#setAutoWhiteBalanceLock setAutoWhiteBalanceLo these properties from changing.</li> </ul> -<h4>Camera Broadcast Intents</h4> + +<h4>Camera broadcast intents</h4> <ul> -<li>{@link android.hardware.Camera#ACTION_NEW_PICTURE Camera.ACTION_NEW_PICTURE} -This indicates that the user has captured a new photo. The built-in camera app invokes this +<li>{@link android.hardware.Camera#ACTION_NEW_PICTURE Camera.ACTION_NEW_PICTURE}: +This indicates that the user has captured a new photo. The built-in Camera app invokes this broadcast after a photo is captured and third-party camera apps should also broadcast this intent after capturing a photo.</li> -<li>{@link android.hardware.Camera#ACTION_NEW_VIDEO Camera.ACTION_NEW_VIDEO} -This indicates that the user has captured a new video. The built-in camera app invokes this +<li>{@link android.hardware.Camera#ACTION_NEW_VIDEO Camera.ACTION_NEW_VIDEO}: +This indicates that the user has captured a new video. The built-in Camera app invokes this broadcast after a video is recorded and third-party camera apps should also broadcast this intent after capturing a video.</li> </ul> - - - + + + <h3 id="Multimedia">Multimedia</h3> <p>Android 4.0 adds several new APIs for applications that interact with media such as photos, -videos, -and music.</p> +videos, and music.</p> -<h4>Media Player</h4> +<h4>Media player</h4> <ul> -<li>Streaming online media from {@link android.media.MediaPlayer} now requires {@link +<li>Streaming online media from {@link android.media.MediaPlayer} now requires the {@link android.Manifest.permission#INTERNET} permission. If you use {@link android.media.MediaPlayer} to -play content from the internet, be sure to add the {@link android.Manifest.permission#INTERNET} -permission or else your media playback will not work beginning with Android 4.0.</li> +play content from the Internet, be sure to add the {@link android.Manifest.permission#INTERNET} +permission to your manifest or else your media playback will not work beginning with Android +4.0.</li> + <li>{@link android.media.MediaPlayer#setSurface(Surface) setSurface()} allows you define a {@link android.view.Surface} to behave as the video sink.</li> + <li>{@link android.media.MediaPlayer#setDataSource(Context,Uri,Map) setDataSource()} allows you to send additional HTTP headers with your request, which can be useful for HTTP(S) live streaming</li> + <li>HTTP(S) live streaming now respects HTTP cookies across requests</li> </ul> -<h4>Media Type Support</h4> + +<h4>Media types</h4> <p>Android 4.0 adds support for:</p> <ul> @@ -382,16 +440,17 @@ send additional HTTP headers with your request, which can be useful for HTTP(S) Formats</a>.</p> -<h4>Remote Control Client</h4> + +<h4>Remote control client</h4> <p>The new {@link android.media.RemoteControlClient} allows media players to enable playback -controls -from remote control clients such as the device lock screen. Media players can also expose +controls from remote control clients such as the device lock screen. Media players can also expose information about the media currently playing for display on the remote control, such as track information and album art.</p> <p>To enable remote control clients for your media player, instantiate a {@link -android.media.RemoteControlClient} with a {@link android.app.PendingIntent} that broadcasts {@link +android.media.RemoteControlClient} with its constructor, passing it a {@link +android.app.PendingIntent} that broadcasts {@link android.content.Intent#ACTION_MEDIA_BUTTON}. The intent must also declare the explicit {@link android.content.BroadcastReceiver} component in your app that handles the {@link android.content.Intent#ACTION_MEDIA_BUTTON} event.</p> @@ -419,21 +478,19 @@ android.media.MediaMetadataRetriever}.</p> <p>For a sample implementation, see the <a href=â€{@docRoot}resources/samples/RandomMusicPlayer/index.htmlâ€>Random Music Player</a>, which -provides compatibility logic such that it enables the remote control client while continuing to -support Android 2.1 devices.</p> +provides compatibility logic such that it enables the remote control client on Android 4.0 +devices while continuing to support devices back to Android 2.1.</p> <h4>Media Effects</h4> <p>A new media effects framework allows you to apply a variety of visual effects to images and -videos. -The system performs all effects processing on the GPU to obtain maximum performance. Applications in -Android 4.0 such as Google Talk or the Gallery editor make use of the effects API to apply real-time -effects to video and photos.</p> +videos. The system performs all effects processing on the GPU to obtain maximum performance. +New applications for Android 4.0 such as Google Talk and the Gallery editor make use of the +effects API to apply real-time effects to video and photos.</p> <p>For maximum performance, effects are applied directly to OpenGL textures, so your application -must -have a valid OpenGL context before it can use the effects APIs. The textures to which you apply +must have a valid OpenGL context before it can use the effects APIs. The textures to which you apply effects may be from bitmaps, videos or even the camera. However, there are certain restrictions that textures must meet:</p> <ol> @@ -442,8 +499,7 @@ textures must meet:</p> </ol> <p>An {@link android.media.effect.Effect} object defines a single media effect that you can apply to -an -image frame. The basic workflow to create an {@link android.media.effect.Effect} is:</p> +an image frame. The basic workflow to create an {@link android.media.effect.Effect} is:</p> <ol> <li>Call {@link android.media.effect.EffectContext#createWithCurrentGlContext @@ -452,17 +508,15 @@ EffectContext.createWithCurrentGlContext()} from your OpenGL ES 2.0 context.</li android.media.effect.EffectContext#getFactory EffectContext.getFactory()}, which returns an instance of {@link android.media.effect.EffectFactory}.</li> <li>Call {@link android.media.effect.EffectFactory#createEffect createEffect()}, passing it an -effect -name from @link android.media.effect.EffectFactory}, such as {@link +effect name from @link android.media.effect.EffectFactory}, such as {@link android.media.effect.EffectFactory#EFFECT_FISHEYE} or {@link android.media.effect.EffectFactory#EFFECT_VIGNETTE}.</li> </ol> <p>Not all devices support all effects, so you must first check if the desired effect is supported -by -calling {@link android.media.effect.EffectFactory#isEffectSupported isEffectSupported()}.</p> +by calling {@link android.media.effect.EffectFactory#isEffectSupported isEffectSupported()}.</p> -<p>You can adjust the effect’s parameters by calling {@link android.media.effect.Effect#setParameter +<p>You can adjust an effect’s parameters by calling {@link android.media.effect.Effect#setParameter setParameter()} and passing a parameter name and parameter value. Each type of effect accepts different parameters, which are documented with the effect name. For example, {@link android.media.effect.EffectFactory#EFFECT_FISHEYE} has one parameter for the {@code scale} of the @@ -475,7 +529,7 @@ texture. The input texture must be bound to a {@link android.opengl.GLES20#GL_T image (usually done by calling the {@link android.opengl.GLES20#glTexImage2D glTexImage2D()} function). You may provide multiple mipmap levels. If the output texture has not been bound to a texture image, it will be automatically bound by the effect as a {@link -android.opengl.GLES20#GL_TEXTURE_2D}. It will contain one mipmap level (0), which will have the same +android.opengl.GLES20#GL_TEXTURE_2D} and with one mipmap level (0), which will have the same size as the input.</p> @@ -496,7 +550,7 @@ android.bluetooth.BluetoothProfile.ServiceListener} and the {@link android.bluetooth.BluetoothProfile#HEALTH} profile type to establish a connection with the profile proxy object.</p> -<p>Once you’ve acquired the Health profile proxy (the {@link android.bluetooth.BluetoothHealth} +<p>Once you’ve acquired the Health Profile proxy (the {@link android.bluetooth.BluetoothHealth} object), connecting to and communicating with paired health devices involves the following new Bluetooth classes:</p> <ul> @@ -510,15 +564,15 @@ to perform various operations such as initiate and terminate connections with th android.bluetooth.BluetoothHealth} APIs.</li> </ul> -<p>For more information about using the Bluetooth Health profile, see the documentation for {@link +<p>For more information about using the Bluetooth Health Profile, see the documentation for {@link android.bluetooth.BluetoothHealth}.</p> + <h3 id="AndroidBeam">Android Beam (NDEF Push with NFC)</h3> -<p>Android Beam allows you to send NDEF messages (an NFC standard for data stored on NFC tags) from -one -device to another (a process also known as “NDEF Pushâ€). The data transfer is initiated when two +<p>Android Beam is a new NFC feature that allows you to send NDEF messages from one device to +another (a process also known as “NDEF Pushâ€). The data transfer is initiated when two Android-powered devices that support Android Beam are in close proximity (about 4 cm), usually with their backs touching. The data inside the NDEF message can contain any data that you wish to share between devices. For example, the People app shares contacts, YouTube shares videos, and Browser @@ -526,29 +580,30 @@ shares URLs using Android Beam.</p> <p>To transmit data between devices using Android Beam, you need to create an {@link android.nfc.NdefMessage} that contains the information you want to share while your activity is in -the foreground. You must then pass the -{@link android.nfc.NdefMessage} to the system in one of two ways:</p> +the foreground. You must then pass the {@link android.nfc.NdefMessage} to the system in one of two +ways:</p> <ul> -<li>Define a single {@link android.nfc.NdefMessage} to use from the activity: +<li>Define a single {@link android.nfc.NdefMessage} to push while in the activity: <p>Call {@link android.nfc.NfcAdapter#setNdefPushMessage setNdefPushMessage()} at any time to set -the -message you want to send. For instance, you might call this method and pass it your {@link +the message you want to send. For instance, you might call this method and pass it your {@link android.nfc.NdefMessage} during your activity’s {@link android.app.Activity#onCreate onCreate()} -method. Then, whenever Android Beam is activated with another device while your activity is in the -foreground, the system sends that {@link android.nfc.NdefMessage} to the other device.</p></li> +method. Then, whenever Android Beam is activated with another device while the activity is in the +foreground, the system sends the {@link android.nfc.NdefMessage} to the other device.</p></li> -<li>Define the {@link android.nfc.NdefMessage} depending on the current context: -<p>Implement {@link android.nfc.NfcAdapter.CreateNdefMessageCallback}, in which the {@link -android.nfc.NfcAdapter.CreateNdefMessageCallback#createNdefMessage createNdefMessage()} callback +<li>Define the {@link android.nfc.NdefMessage} to push at the time that Android Beam is initiated: +<p>Implement {@link android.nfc.NfcAdapter.CreateNdefMessageCallback}, in which your +implementation of the {@link +android.nfc.NfcAdapter.CreateNdefMessageCallback#createNdefMessage createNdefMessage()} method returns the {@link android.nfc.NdefMessage} you want to send. Then pass the {@link -android.nfc.NfcAdapter.CreateNdefMessageCallback} to {@link -android.nfc.NfcAdapter#setNdefPushMessageCallback setNdefPushMessageCallback()}. In this case, when -Android Beam is activated with another device while your activity is in the foreground, the system -calls {@link android.nfc.NfcAdapter.CreateNdefMessageCallback#createNdefMessage createNdefMessage()} -to retrieve the {@link android.nfc.NdefMessage} you want to send. This allows you to create a -different {@link android.nfc.NdefMessage} for each occurrence, depending on the user context (such -as which contact in the People app is currently visible).</p></li> +android.nfc.NfcAdapter.CreateNdefMessageCallback} implementation to {@link +android.nfc.NfcAdapter#setNdefPushMessageCallback setNdefPushMessageCallback()}.</p> +<p>In this case, when Android Beam is activated with another device while your activity is in the +foreground, the system calls {@link +android.nfc.NfcAdapter.CreateNdefMessageCallback#createNdefMessage createNdefMessage()} to retrieve +the {@link android.nfc.NdefMessage} you want to send. This allows you to define the {@link +android.nfc.NdefMessage} to deliver only once Android Beam is initiated, in case the contents +of the message might vary throughout the life of the activity.</p></li> </ul> <p>In case you want to run some specific code once the system has successfully delivered your NDEF @@ -562,7 +617,7 @@ onNdefPushComplete()} when the message is delivered.</p> tags. The system invokes an intent with the {@link android.nfc.NfcAdapter#ACTION_NDEF_DISCOVERED} action to start an activity, with either a URL or a MIME type set according to the first {@link android.nfc.NdefRecord} in the {@link android.nfc.NdefMessage}. For the activity you want to -respond, you can set intent filters for the URLs or MIME types your app cares about. For more +respond, you can declare intent filters for the URLs or MIME types your app cares about. For more information about Tag Dispatch see the <a href=â€{@docRoot}guide/topics/nfc/index.html#dispatchâ€>NFC</a> developer guide.</p> @@ -573,46 +628,51 @@ a special format that you want your application to also receive during an Androi should create an intent filter for your activity using the same URI scheme in order to receive the incoming NDEF message.</p> -<p>You may also want to pass an “Android application record†with your {@link -android.nfc.NdefMessage} -in order to guarantee a specific application handles an NDEF message, regardless of whether other -applications filter for the same intent. You can create an Android application record by calling -{@link android.nfc.NdefRecord#createApplicationRecord createApplicationRecord()}, passing it the -application’s package name. When the other device receives the NDEF message with this record, the -system automatically starts the application matching the package name. If the target device does not -currently have the application installed, the system uses the Android application record to launch -Android Market and take the user to the application to install it.</p> +<p>You should also pass an “Android application record†with your {@link android.nfc.NdefMessage} in +order to guarantee that your application handles the incoming NDEF message, even if other +applications filter for the same intent action. You can create an Android application record by +calling {@link android.nfc.NdefRecord#createApplicationRecord createApplicationRecord()}, passing it +your application’s package name. When the other device receives the NDEF message with the +application record and multiple applications contain activities that handle the specified intent, +the system always delivers the message to the activity in your application (based on the matching +application record). If the target device does not currently have your application installed, the +system uses the Android application record to launch Android Market and take the user to the +application in order to install it.</p> <p>If your application doesn’t use NFC APIs to perform NDEF Push messaging, then Android provides a default behavior: When your application is in the foreground on one device and Android Beam is invoked with another Android-powered device, then the other device receives an NDEF message with an Android application record that identifies your application. If the receiving device has the application installed, the system launches it; if it’s not installed, Android Market opens and takes -the user to your application so they can install it.</p> +the user to your application in order to install it.</p> +<p>For some example code, see the <a +href="{@docRoot}resources/samples/AndroidBeamDemo/src/com/example/android/beam/Beam.html">Android +Beam Demo</a> sample app.</p> <h3 id="P2pWiFi">Peer-to-peer Wi-Fi</h3> -<p>Android now supports Wi-Fi Direct™ for peer-to-peer (P2P) connections between -Android-powered +<p>Android now supports Wi-Fi Direct for peer-to-peer (P2P) connections between Android-powered devices and other device types without a hotspot or Internet connection. The Android framework provides a set of Wi-Fi P2P APIs that allow you to discover and connect to other devices when each -device supports Wi-Fi Direct™, then communicate over a speedy connection across distances much -longer than a Bluetooth connection.</p> +device supports Wi-Fi Direct, then communicate over a speedy connection across distances much longer +than a Bluetooth connection.</p> <p>A new package, {@link android.net.wifi.p2p}, contains all the APIs for performing peer-to-peer connections with Wi-Fi. The primary class you need to work with is {@link -android.net.wifi.p2p.WifiP2pManager}, for which you can get an instance by calling {@link +android.net.wifi.p2p.WifiP2pManager}, which you can acquire by calling {@link android.app.Activity#getSystemService getSystemService(WIFI_P2P_SERVICE)}. The {@link -android.net.wifi.p2p.WifiP2pManager} provides methods that allow you to:</p> +android.net.wifi.p2p.WifiP2pManager} includes APIs that allow you to:</p> <ul> <li>Initialize your application for P2P connections by calling {@link android.net.wifi.p2p.WifiP2pManager#initialize initialize()}</li> + <li>Discover nearby devices by calling {@link android.net.wifi.p2p.WifiP2pManager#discoverPeers discoverPeers()}</li> + <li>Start a P2P connection by calling {@link android.net.wifi.p2p.WifiP2pManager#connect connect()}</li> <li>And more</li> @@ -622,18 +682,20 @@ connect()}</li> <ul> <li>The {@link android.net.wifi.p2p.WifiP2pManager.ActionListener} interface allows you to receive callbacks when an operation such as discovering peers or connecting to them succeeds or fails.</li> + <li>{@link android.net.wifi.p2p.WifiP2pManager.PeerListListener} interface allows you to receive information about discovered peers. The callback provides a {@link android.net.wifi.p2p.WifiP2pDeviceList}, from which you can retrieve a {@link android.net.wifi.p2p.WifiP2pDevice} object for each device within range and get information such as the device name, address, device type, the WPS configurations the device supports, and more.</li> + <li>The {@link android.net.wifi.p2p.WifiP2pManager.GroupInfoListener} interface allows you to -receive -information about a P2P group. The callback provides a {@link android.net.wifi.p2p.WifiP2pGroup} -object, which provides group information such as the owner, the network name, and passphrase.</li> +receive information about a P2P group. The callback provides a {@link +android.net.wifi.p2p.WifiP2pGroup} object, which provides group information such as the owner, the +network name, and passphrase.</li> + <li>{@link android.net.wifi.p2p.WifiP2pManager.ConnectionInfoListener} interface allows you to -receive -information about the current connection. The callback provides a {@link +receive information about the current connection. The callback provides a {@link android.net.wifi.p2p.WifiP2pInfo} object, which has information such as whether a group has been formed and who is the group owner.</li> </ul> @@ -642,37 +704,36 @@ formed and who is the group owner.</li> <ul> <li>{@link android.Manifest.permission#ACCESS_WIFI_STATE}</li> <li>{@link android.Manifest.permission#CHANGE_WIFI_STATE}</li> -<li>{@link android.Manifest.permission#INTERNET} (even though your app doesn’t technically connect -to -the Internet, the WiFi Direct implementation uses traditional sockets that do require Internet +<li>{@link android.Manifest.permission#INTERNET} (although your app doesn’t technically connect +to the Internet, the WiFi Direct implementation uses sockets that do require Internet permission to work).</li> </ul> <p>The Android system also broadcasts several different actions during certain Wi-Fi P2P events:</p> <ul> <li>{@link android.net.wifi.p2p.WifiP2pManager#WIFI_P2P_CONNECTION_CHANGED_ACTION}: The P2P -connection -state has changed. This carries {@link android.net.wifi.p2p.WifiP2pManager#EXTRA_WIFI_P2P_INFO} with -a {@link android.net.wifi.p2p.WifiP2pInfo} object and {@link +connection state has changed. This carries {@link +android.net.wifi.p2p.WifiP2pManager#EXTRA_WIFI_P2P_INFO} with a {@link +android.net.wifi.p2p.WifiP2pInfo} object and {@link android.net.wifi.p2p.WifiP2pManager#EXTRA_NETWORK_INFO} with a {@link android.net.NetworkInfo} object.</li> + <li>{@link android.net.wifi.p2p.WifiP2pManager#WIFI_P2P_STATE_CHANGED_ACTION}: The P2P state has -changed -between enabled and disabled. It carries {@link +changed between enabled and disabled. It carries {@link android.net.wifi.p2p.WifiP2pManager#EXTRA_WIFI_STATE} with either {@link android.net.wifi.p2p.WifiP2pManager#WIFI_P2P_STATE_DISABLED} or {@link android.net.wifi.p2p.WifiP2pManager#WIFI_P2P_STATE_ENABLED}</li> + <li>{@link android.net.wifi.p2p.WifiP2pManager#WIFI_P2P_PEERS_CHANGED_ACTION}: The list of peer -devices -has changed.</li> +devices has changed.</li> + <li>{@link android.net.wifi.p2p.WifiP2pManager#WIFI_P2P_THIS_DEVICE_CHANGED_ACTION}: The details for this device have changed.</li> </ul> <p>See the {@link android.net.wifi.p2p.WifiP2pManager} documentation for more information. Also -look -at the <a href=â€{@docRoot}resources/samples/WiFiDirectDemo/index.htmlâ€>Wi-Fi Direct</a> sample -application for example code.</p> +look at the <a href=â€{@docRoot}resources/samples/WiFiDirectDemo/index.htmlâ€>Wi-Fi Direct Demo</a> +sample application.</p> @@ -680,20 +741,20 @@ application for example code.</p> <h3 id="NetworkData">Network Data</h3> -<p>Android 4.0 gives users precise visibility of how much network data applications are using. The -Settings app provides controls that allow users to manage set limits for network data usage and even -disable the use of background data for individual apps. In order to avoid users disabling your app’s -access to data from the background, you should develop strategies to use use the data connection -efficiently and vary your usage depending on the type of connection available.</p> +<p>Android 4.0 gives users precise visibility of how much network data their applications are using. +The Settings app provides controls that allow users to manage set limits for network data usage and +even disable the use of background data for individual apps. In order to avoid users disabling your +app’s access to data from the background, you should develop strategies to use use the data +connection efficiently and adjust your usage depending on the type of connection available.</p> <p>If your application performs a lot of network transactions, you should provide user settings that allow users to control your app’s data habits, such as how often your app syncs data, whether to perform uploads/downloads only when on Wi-Fi, whether to use data while roaming, etc. With these controls available to them, users are much less likely to disable your app’s access to data when they approach their limits, because they can instead precisely control how much data your app uses. -When you provide an activity with these settings, you should include in its manifest declaration an -intent filter for the {@link android.content.Intent#ACTION_MANAGE_NETWORK_USAGE} action. For -example:</p> +If you provide a preference activity with these settings, you should include in its manifest +declaration an intent filter for the {@link android.content.Intent#ACTION_MANAGE_NETWORK_USAGE} +action. For example:</p> <pre> <activity android:name="DataPreferences" android:label="@string/title_preferences"> @@ -704,10 +765,10 @@ example:</p> </activity> </pre> -<p>This intent filter indicates to the system that this is the application that controls your +<p>This intent filter indicates to the system that this is the activity that controls your application’s data usage. Thus, when the user inspects how much data your app is using from the -Settings app, a “View application settings†button is available that launches your activity so the -user can refine how much data your app uses.</p> +Settings app, a “View application settings†button is available that launches your +preference activity so the user can refine how much data your app uses.</p> <p>Also beware that {@link android.net.ConnectivityManager#getBackgroundDataSetting()} is now deprecated and always returns true—use {@link @@ -715,7 +776,7 @@ android.net.ConnectivityManager#getActiveNetworkInfo()} instead. Before you atte transactions, you should always call {@link android.net.ConnectivityManager#getActiveNetworkInfo()} to get the {@link android.net.NetworkInfo} that represents the current network and query {@link android.net.NetworkInfo#isConnected()} to check whether the device has a -connection. You can then check various other connection properties, such as whether the device is +connection. You can then check other connection properties, such as whether the device is roaming or connected to Wi-Fi.</p> @@ -724,43 +785,10 @@ roaming or connected to Wi-Fi.</p> -<h3 id="Sensors">Device Sensors</h3> - -<p>Two new sensor types have been added in Android 4.0: {@link -android.hardware.Sensor#TYPE_AMBIENT_TEMPERATURE} and {@link -android.hardware.Sensor#TYPE_RELATIVE_HUMIDITY}. </p> - -<p>{@link android.hardware.Sensor#TYPE_AMBIENT_TEMPERATURE} is a temperature sensor that provides -the ambient (room) temperature near a device. This sensor reports data in degrees Celsius. {@link -android.hardware.Sensor#TYPE_RELATIVE_HUMIDITY} is a humidity sensor that provides the relative -ambient (room) humidity. The sensor reports data as a percentage. If a device has both {@link -android.hardware.Sensor#TYPE_AMBIENT_TEMPERATURE} and {@link -android.hardware.Sensor#TYPE_RELATIVE_HUMIDITY} sensors, you can use them to calculate the dew point -and the absolute humidity.</p> - -<p>The existing temperature sensor ({@link android.hardware.Sensor#TYPE_TEMPERATURE}) has been -deprecated. You should use the {@link android.hardware.Sensor#TYPE_AMBIENT_TEMPERATURE} sensor -instead.</p> - -<p>Additionally, Android’s three synthetic sensors have been improved so they now have lower latency -and smoother output. These sensors include the gravity sensor ({@link -android.hardware.Sensor#TYPE_GRAVITY}), rotation vector sensor ({@link -android.hardware.Sensor#TYPE_ROTATION_VECTOR}), and linear acceleration sensor ({@link -android.hardware.Sensor#TYPE_LINEAR_ACCELERATION}). The improved sensors rely on the gyroscope -sensor to improve their output so the sensors appear only on devices that have a gyroscope. If a -device already provides one of the sensors, then that sensor appears as a second sensor on the -device. The three improved sensors have a version number of 2.</p> - - +<h3 id="RenderScript">RenderScript</h3> - - - - -<h3 id="Renderscript">Renderscript</h3> - -<p>Three major features have been added to Renderscript:</p> +<p>Three major features have been added to RenderScript:</p> <ul> <li>Off-screen rendering to a framebuffer object</li> @@ -771,24 +799,24 @@ device. The three improved sensors have a version number of 2.</p> <p>The {@link android.renderscript.Allocation} class now supports a {@link android.renderscript.Allocation#USAGE_GRAPHICS_RENDER_TARGET} memory space, which allows you to render things directly into the {@link android.renderscript.Allocation} and use it as a framebuffer -object. </p> +object.</p> -<p>{@link android.renderscript.RSTextureView} provides a means to display Renderscript graphics -inside -of a normal View, unlike {@link android.renderscript.RSSurfaceView}, which creates a separate -window. This key difference allows you to do things such as move, transform, or animate an {@link -android.renderscript.RSTextureView} as well as draw Renderscript graphics inside the View alongside -other traditional View widgets.</p> +<p>{@link android.renderscript.RSTextureView} provides a means to display RenderScript graphics +inside of a {@link android.view.View}, unlike {@link android.renderscript.RSSurfaceView}, which +creates a separate window. This key difference allows you to do things such as move, transform, or +animate an {@link android.renderscript.RSTextureView} as well as draw RenderScript graphics inside +a view that lies within an activity layout.</p> -<p>The {@link android.renderscript.Script#forEach forEach()} method allows you to call Renderscript -compute scripts from the VM level and have them automatically delegated to available cores on the -device. You do not use this method directly, but any compute Renderscript that you write will have a -{@link android.renderscript.Script#forEach forEach()} method that you can call in the reflected -Renderscript class. You can call the reflected {@link android.renderscript.Script#forEach forEach()} -method by passing in an input {@link android.renderscript.Allocation} to process, an output {@link -android.renderscript.Allocation} to write the result to, and a data structure if the Renderscript -needs more information in addition to the {@link android.renderscript.Allocation}s to. Only one of -the {@link android.renderscript.Allocation}s is necessary and the data structure is optional.</p> +<p>The {@link android.renderscript.Script#forEach Script.forEach()} method allows you to call +RenderScript compute scripts from the VM level and have them automatically delegated to available +cores on the device. You do not use this method directly, but any compute RenderScript that you +write will have a {@link android.renderscript.Script#forEach forEach()} method that you can call in +the reflected RenderScript class. You can call the reflected {@link +android.renderscript.Script#forEach forEach()} method by passing in an input {@link +android.renderscript.Allocation} to process, an output {@link android.renderscript.Allocation} to +write the result to, and a {@link android.renderscript.FieldPacker} data structure in case the +RenderScript needs more information. Only one of the {@link android.renderscript.Allocation}s is +necessary and the data structure is optional.</p> @@ -797,118 +825,154 @@ the {@link android.renderscript.Allocation}s is necessary and the data structure <h3 id="A11y">Accessibility</h3> -<p>Android 4.0 improves accessibility for users with disabilities with the Touch Exploration service -and provides extended APIs for developers of new accessibility services.</p> +<p>Android 4.0 improves accessibility for sight-impaired users with new explore-by-touch mode +and extended APIs that allow you to provide more information about view content or +develop advanced accessibility services.</p> -<h4>Touch Exploration</h4> -<p>Users with vision loss can now explore applications by touching areas of the screen and hearing -voice descriptions of the content. The “Explore by Touch†feature works like a virtual cursor as the -user drags a finger across the screen.</p> +<h4>Explore-by-touch mode</h4> -<p>You don’t have to use any new APIs to enhance touch exploration in your application, because the -existing {@link android.R.attr#contentDescription android:contentDescription} -attribute and {@link android.view.View#setContentDescription setContentDescription()} method is all -you need. Because touch exploration works like a virtual cursor, it allows screen readers to -identify the descriptive the same way that screen readers can when navigating with a d-pad or -trackball. So this is a reminder to provide descriptive text for the views in your application, -especially for {@link android.widget.ImageButton}, {@link android.widget.EditText}, {@link -android.widget.CheckBox} and other interactive widgets that might not contain text information by -default.</p> +<p>Users with vision loss can now explore the screen by touching and dragging a finger across the +screen to hear voice descriptions of the content. Because the explore-by-touch mode works like a +virtual cursor, it allows screen readers to identify the descriptive text the same way that screen +readers can when the user navigates with a d-pad or trackball—by reading information provided +by {@link android.R.attr#contentDescription android:contentDescription} and {@link +android.view.View#setContentDescription setContentDescription()} upon a simulated "hover" event. So, +consider this is a reminder that you should provide descriptive text for the views in your +application, especially for {@link android.widget.ImageButton}, {@link android.widget.EditText}, +{@link android.widget.ImageView} and other widgets that might not naturally contain descriptive +text.</p> -<h4>Accessibility for Custom Views</h4> -<p>Developers of custom Views, ViewGroups and widgets can make their components compatible with -accessibility services like Touch Exploration. For custom views and widgets targeted for Android 4.0 -and later, developers should implement the following accessibility API methods in their classes:</p> -<ul> -<li>These two methods initiate the accessibility event generation process and must be implemented by -your custom view class. - <ul> - <li>{@link android.view.View#sendAccessibilityEvent(int) sendAccessibilityEvent()} If -accessibility - is - not enabled, this call has no effect.</li> - <li>{@link - android.view.View#sendAccessibilityEventUnchecked(android.view.accessibility.AccessibilityEvent) - sendAccessibilityEventUnchecked()} - This method executes regardless of whether accessibility is - enabled or not.</li> - </ul> -</li> +<h4>Accessibility for views</h4> -<li>These methods are called in order by the sendAccessibilityEvent methods listed above to collect -accessibility information about the view, and its child views. - <ul> - <li>{@link - android.view.View#onInitializeAccessibilityEvent(android.view.accessibility.AccessibilityEvent) - onInitializeAccessibilityEvent()} - This method collects information about the view. If your - application has specific requirements for accessibility, you should extend this method to add that - information to the {@link android.view.accessibility.AccessibilityEvent}.</li> - - <li>{@link - -android.view.View#dispatchPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent) - dispatchPopulateAccessibilityEvent()} is called by the framework to request text information for - this view and its children. This method calls {@link - android.view.View#onPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent) - onPopulateAccessibilityEvent()} first on the current view and then on its children.</li> - </ul> +<p>To enhance the information available to accessibility services such as screen readers, you can +implement new callback methods for accessibility events in your custom {@link +android.view.View} components.</p> + +<p>It's important to first note that the behavior of the {@link +android.view.View#sendAccessibilityEvent sendAccessibilityEvent()} method has changed in Android +4.0. As with previous version of Android, when the user enables accessibility services on the device +and an input event such as a click or hover occurs, the respective view is notified with a call to +{@link android.view.View#sendAccessibilityEvent sendAccessibilityEvent()}. Previously, the +implementation of {@link android.view.View#sendAccessibilityEvent sendAccessibilityEvent()} would +initialize an {@link android.view.accessibility.AccessibilityEvent} and send it to {@link +android.view.accessibility.AccessibilityManager}. The new behavior involves some additional callback +methods that allow the view and its parents to add more contextual information to the event: +<ol> + <li>When invoked, the {@link +android.view.View#sendAccessibilityEvent sendAccessibilityEvent()} and {@link +android.view.View#sendAccessibilityEventUnchecked sendAccessibilityEventUnchecked()} methods defer +to {@link android.view.View#onInitializeAccessibilityEvent onInitializeAccessibilityEvent()}. + <p>Custom implementations of {@link android.view.View} might want to implement {@link +android.view.View#onInitializeAccessibilityEvent onInitializeAccessibilityEvent()} to +attach additional accessibility information to the {@link +android.view.accessibility.AccessibilityEvent}, but should also call the super implementation to +provide default information such as the standard content description, item index, and more. +However, you should not add additional text content in this callback—that happens +next.</p></li> + <li>Once initialized, if the event is one of several types that should be populated with text +information, the view then receives a call to {@link +android.view.View#dispatchPopulateAccessibilityEvent dispatchPopulateAccessibilityEvent()}, which +defers to the {@link android.view.View#onPopulateAccessibilityEvent onPopulateAccessibilityEvent()} +callback. + <p>Custom implementations of {@link android.view.View} should usually implement {@link +android.view.View#onPopulateAccessibilityEvent onPopulateAccessibilityEvent()} to add additional +text content to the {@link android.view.accessibility.AccessibilityEvent} if the {@link +android.R.attr#contentDescription android:contentDescription} text is missing or +insufficient. To add more text description to the +{@link android.view.accessibility.AccessibilityEvent}, call {@link +android.view.accessibility.AccessibilityEvent#getText()}.{@link java.util.List#add add()}.</p> </li> + <li>At this point, the {@link android.view.View} passes the event up the view hierarchy by calling +{@link android.view.ViewGroup#requestSendAccessibilityEvent requestSendAccessibilityEvent()} on the +parent view. Each parent view then has the chance to augment the accessibility information by +adding an {@link android.view.accessibility.AccessibilityRecord}, until it +ultimately reaches the root view, which sends the event to the {@link +android.view.accessibility.AccessibilityManager} with {@link +android.view.accessibility.AccessibilityManager#sendAccessibilityEvent +sendAccessibilityEvent()}.</li> +</ol> -<li>The {@link -android.view.View#onInitializeAccessibilityNodeInfo onInitializeAccessibilityNodeInfo()} method -provides additional context information for -accessibility services. You should implement or override this method to provide improved information -for accessibility services investigating your custom view.</li> +<p>In addition to the new methods above, which are useful when extending the {@link +android.view.View} class, you can also intercept these event callbacks on any {@link +android.view.View} by extending {@link +android.view.View.AccessibilityDelegate AccessibilityDelegate} and setting it on the view with +{@link android.view.View#setAccessibilityDelegate setAccessibilityDelegate()}. +When you do, each accessibility method in the view defers the call to the corresponding method in +the delegate. For example, when the view receives a call to {@link +android.view.View#onPopulateAccessibilityEvent onPopulateAccessibilityEvent()}, it passes it to the +same method in the {@link android.view.View.AccessibilityDelegate}. Any methods not handled by +the delegate are given right back to the view for default behavior. This allows you to override only +the methods necessary for any given view without extending the {@link android.view.View} class.</p> -<li>Custom {@link android.view.ViewGroup} classes should also implement {@link -android.view.ViewGroup#onRequestSendAccessibilityEvent(android.view.View, -android.view.accessibility.AccessibilityEvent) onRequestSendAccessibilityEvent()} </li> -</ul> -<p>Developers who want to maintain compatibility with Android versions prior to 4.0, while still -providing support for new the accessibility APIs, can use the {@link -android.view.View#setAccessibilityDelegate(android.view.View.AccessibilityDelegate) -setAccessibilityDelegate()} method to provide an {@link android.view.View.AccessibilityDelegate} -containing implementations of the new accessibility API methods while maintaining compatibility with -prior releases.</p> +<p>If you want to maintain compatibility with Android versions prior to 4.0, while also supporting +the new the accessibility APIs, you can do so with the latest version of the <em>v4 support +library</em> (in <a href="{@docRoot}sdk/compatibility-library.html">Compatibility Package, r4</a>) +using a set of utility classes that provide the new accessibility APIs in a backward-compatible +design.</p> -<h4>Accessibility Service APIs</h4> +<h4>Accessibility services</h4> -<p>Accessibility events have been significantly improved to provide better information for -accessibility services. In particular, events are generated based on view composition, providing -better context information and allowing accessibility service developers to traverse view -hierarchies to get additional view information and deal with special cases.</p> +<p>If you're developing an accessibility service, the information about various accessibility events +has been significantly expanded to enable more advanced accessibility feedback for users. In +particular, events are generated based on view composition, providing better context information and +allowing accessibility services to traverse view hierarchies to get additional view information and +deal with special cases.</p> -<p>To access additional content information and traverse view hierarchies, accessibility service -application developers should use the following procedure.</p> +<p>If you're developing an accessibility service (such as a screen reader), you can access +additional content information and traverse view hierarchies with the following procedure:</p> <ol> <li>Upon receiving an {@link android.view.accessibility.AccessibilityEvent} from an application, -call -the {@link android.view.accessibility.AccessibilityEvent#getRecord(int) -AccessibilityEvent.getRecord()} to retrieve new accessibility information about the state of the -view.</li> -<li>From the {@link android.view.accessibility.AccessibilityRecord}, call {@link +call the {@link android.view.accessibility.AccessibilityEvent#getRecord(int) +AccessibilityEvent.getRecord()} to retrieve a specific {@link +android.view.accessibility.AccessibilityRecord} (there may be several records attached to the +event).</li> + +<li>From either {@link android.view.accessibility.AccessibilityEvent} or an individual {@link +android.view.accessibility.AccessibilityRecord}, you can call {@link android.view.accessibility.AccessibilityRecord#getSource() getSource()} to retrieve a {@link -android.view.accessibility.AccessibilityNodeInfo} object.</li> -<li>With the {@link android.view.accessibility.AccessibilityNodeInfo}, call {@link +android.view.accessibility.AccessibilityNodeInfo} object. + <p>An {@link android.view.accessibility.AccessibilityNodeInfo} represents a single node +of the window content in a format that allows you to query accessibility information about that +node. The {@link android.view.accessibility.AccessibilityNodeInfo} object returned from {@link +android.view.accessibility.AccessibilityEvent} describes the event source, whereas the source from +an {@link android.view.accessibility.AccessibilityRecord} describes the predecessor of the event +source.</p></li> + +<li>With the {@link android.view.accessibility.AccessibilityNodeInfo}, you can query information +about it, call {@link android.view.accessibility.AccessibilityNodeInfo#getParent getParent()} or {@link android.view.accessibility.AccessibilityNodeInfo#getChild getChild()} to traverse the view -hierarchy and get additional context information.</li> +hierarchy, and even add child views to the node.</li> </ol> -<p>In order to retrieve {@link android.view.accessibility.AccessibilityNodeInfo} information, your -application must request permission to retrieve application window content through a manifest -declaration that includes a new, separate xml configuration file, which supercedes {@link -android.accessibilityservice.AccessibilityServiceInfo}. For more information, see {@link +<p>In order for your application to publish itself to the system as an accessibility service, it +must declare an XML configuration file that corresponds to {@link +android.accessibilityservice.AccessibilityServiceInfo}. For more information about creating an +accessibility service, see {@link android.accessibilityservice.AccessibilityService} and {@link android.accessibilityservice.AccessibilityService#SERVICE_META_DATA -AccessibilityService.SERVICE_META_DATA}.</p> +SERVICE_META_DATA} for information about the XML configuration.</p> +<h4>Other accessibility APIs</h4> +<p>If you're interested in the device's accessibility state, the {@link +android.view.accessibility.AccessibilityManager} has some new APIs such as:</p> +<ul> + <li>{@link android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener} +is an interface that allows you to receive a callback whenever accessibility is enabled or +disabled.</li> + <li>{@link android.view.accessibility.AccessibilityManager#getEnabledAccessibilityServiceList + getEnabledAccessibilityServiceList()} provides information about which accessibility services + are currently enabled.</li> + <li>{@link android.view.accessibility.AccessibilityManager#isTouchExplorationEnabled()} tells + you whether the explore-by-touch mode is enabled.</li> +</ul> @@ -916,13 +980,12 @@ AccessibilityService.SERVICE_META_DATA}.</p> <p>Android 4.0 expands the capabilities for enterprise application with the following features.</p> -<h4>VPN Services</h4> +<h4>VPN services</h4> <p>The new {@link android.net.VpnService} allows applications to build their own VPN (Virtual -Private -Network), running as a {@link android.app.Service}. A VPN service creates an interface for a virtual -network with its own address and routing rules and performs all reading and writing with a file -descriptor.</p> +Private Network), running as a {@link android.app.Service}. A VPN service creates an interface for a +virtual network with its own address and routing rules and performs all reading and writing with a +file descriptor.</p> <p>To create a VPN service, use {@link android.net.VpnService.Builder}, which allows you to specify the network address, DNS server, network route, and more. When complete, you can establish the @@ -936,7 +999,7 @@ the system is granted this permission—apps cannot request it). To then use users must manually enable it in the system settings.</p> -<h4>Device Restrictions</h4> +<h4>Device restrictions</h4> <p>Applications that manage the device restrictions can now disable the camera using {@link android.app.admin.DevicePolicyManager#setCameraDisabled setCameraDisabled()} and the {@link @@ -944,54 +1007,46 @@ android.app.admin.DeviceAdminInfo#USES_POLICY_DISABLE_CAMERA} property (applied <disable-camera />} element in the policy configuration file).</p> -<h4>Certificate Management</h4> +<h4>Certificate management</h4> <p>The new {@link android.security.KeyChain} class provides APIs that allow you to import and access -certificates and key stores in credential storage. See the {@link android.security.KeyChain} +certificates in the system key store. Certificates streamline the installation of both client +certificates (to validate the identity of the user) and certificate authority certificates (to +verify server identity). Applications such as web browsers or email clients can access the installed +certificates to authenticate users to servers. See the {@link android.security.KeyChain} documentation for more information.</p> -<h3 id="Voicemail">Voicemail</h3> -<p>A new voicemail APIs allows applications to add voicemails to the system. Because the APIs -currently -do not allow third party apps to read all the voicemails from the system, the only third-party apps -that should use the voicemail APIs are those that have voicemail to deliver to the user. For -instance, it’s possible that a users have multiple voicemail sources, such as one provided by their -phone’s service provider and others from VoIP or other alternative services. These kinds of apps can -use the APIs to add voicemail to the system. The built-in Phone application can then present all -voicemails to the user with a single list. Although the system’s Phone application is the only -application that can read all the voicemails, each application that provides voicemails can read -those that it has added to the system.</p> -<p>The {@link android.provider.VoicemailContract} class defines the content provider for the -voicemail -APIs. The subclasses {@link android.provider.VoicemailContract.Voicemails} and {@link -android.provider.VoicemailContract.Status} provide tables in which the voicemail providers can -insert voicemail data for storage on the device. For an example of a voicemail provider app, see the -<a href=â€{@docRoot}resources/samples/VoicemailProviderDemo/index.htmlâ€>Voicemail Provider -Demo</a>.</p> +<h3 id="Sensors">Device Sensors</h3> +<p>Two new sensor types have been added in Android 4.0:</p> +<ul> + <li>{@link android.hardware.Sensor#TYPE_AMBIENT_TEMPERATURE}: A temperature sensor that provides +the ambient (room) temperature in degrees Celsius.</li> + <li>{@link android.hardware.Sensor#TYPE_RELATIVE_HUMIDITY}: A humidity sensor that provides the +relative ambient (room) humidity as a percentage.</li> +</ul> -<h3 id="SpellChecker">Spell Checker Services</h3> +<p>If a device has both {@link android.hardware.Sensor#TYPE_AMBIENT_TEMPERATURE} and {@link +android.hardware.Sensor#TYPE_RELATIVE_HUMIDITY} sensors, you can use them to calculate the dew point +and the absolute humidity.</p> -<p>The new spell checker framework allows apps to create spell checkers in a manner similar to the -input method framework. To create a new spell checker, you must override the {@link -android.service.textservice.SpellCheckerService.Session} class to provide spelling suggestions based -on text provided by the interface callback methods, returning suggestions as a {@link -android.view.textservice.SuggestionsInfo} object. </p> +<p>The previous temperature sensor, {@link android.hardware.Sensor#TYPE_TEMPERATURE}, has been +deprecated. You should use the {@link android.hardware.Sensor#TYPE_AMBIENT_TEMPERATURE} sensor +instead.</p> -<p>Applications with a spell checker service must declare the {@link -android.Manifest.permission#BIND_TEXT_SERVICE} permission as required by the service, such that -other services must have this permission in order for them to bind with the spell checker service. -The service must also declare an intent filter with <action -android:name="android.service.textservice.SpellCheckerService" /> as the intent’s action and should -include a {@code <meta-data>} element that declares configuration information for the spell -checker. </p> +<p>Additionally, Android’s three synthetic sensors have been improved so they now have lower latency +and smoother output. These sensors include the gravity sensor ({@link +android.hardware.Sensor#TYPE_GRAVITY}), rotation vector sensor ({@link +android.hardware.Sensor#TYPE_ROTATION_VECTOR}), and linear acceleration sensor ({@link +android.hardware.Sensor#TYPE_LINEAR_ACCELERATION}). The improved sensors rely on the gyroscope +sensor to improve their output, so the sensors appear only on devices that have a gyroscope.</p> @@ -999,22 +1054,20 @@ checker. </p> <h3 id="TTS">Text-to-speech Engines</h3> -<p>Android’s text-to-speech (TTS) APIs have been greatly extended to allow applications to more -easily -implement custom TTS engines, while applications that want to use a TTS engine have a couple new -APIs for selecting the engine.</p> +<p>Android’s text-to-speech (TTS) APIs have been significantly extended to allow applications to +more easily implement custom TTS engines, while applications that want to use a TTS engine have a +couple new APIs for selecting an engine.</p> <h4>Using text-to-speech engines</h4> <p>In previous versions of Android, you could use the {@link android.speech.tts.TextToSpeech} class -to -perform text-to-speech (TTS) operations using the TTS engine provided by the system or set a custom -engine using {@link android.speech.tts.TextToSpeech#setEngineByPackageName -setEngineByPackageName()}. -In Android 4.0, the {@link android.speech.tts.TextToSpeech#setEngineByPackageName -setEngineByPackageName()} method has been deprecated and you can now specify the engine to use with -a new {@link android.speech.tts.TextToSpeech} that accepts the package name of a TTS engine.</p> +to perform text-to-speech (TTS) operations using the TTS engine provided by the system or set a +custom engine using {@link android.speech.tts.TextToSpeech#setEngineByPackageName +setEngineByPackageName()}. In Android 4.0, the {@link +android.speech.tts.TextToSpeech#setEngineByPackageName setEngineByPackageName()} method has been +deprecated and you can now specify the engine to use with a new {@link +android.speech.tts.TextToSpeech} constructor that accepts the package name of a TTS engine.</p> <p>You can also query the available TTS engines with {@link android.speech.tts.TextToSpeech#getEngines()}. This method returns a list of {@link @@ -1024,30 +1077,29 @@ icon, label, and package name.</p> <h4>Building text-to-speech engines</h4> -<p>Previously, custom engines required that the engine be built using native code, based on a TTS -engine header file. In Android 4.0, there is a framework API for building TTS engines. </p> +<p>Previously, custom engines required that the engine be built using an undocumented native header +file. In Android 4.0, there is a complete set of framework APIs for building TTS engines. </p> <p>The basic setup requires an implementation of {@link android.speech.tts.TextToSpeechService} that responds to the {@link android.speech.tts.TextToSpeech.Engine#INTENT_ACTION_TTS_SERVICE} intent. The primary work for a TTS engine happens during the {@link -android.speech.tts.TextToSpeechService#onSynthesizeText onSynthesizeText()} callback in the {@link -android.speech.tts.TextToSpeechService}. The system delivers this method two objects:</p> +android.speech.tts.TextToSpeechService#onSynthesizeText onSynthesizeText()} callback in a service +that extends {@link android.speech.tts.TextToSpeechService}. The system delivers this method two +objects:</p> <ul> <li>{@link android.speech.tts.SynthesisRequest}: This contains various data including the text to synthesize, the locale, the speech rate, and voice pitch.</li> <li>{@link android.speech.tts.SynthesisCallback}: This is the interface by which your TTS engine -delivers the resulting speech data as streaming audio, by calling {@link +delivers the resulting speech data as streaming audio. First the engine must call {@link android.speech.tts.SynthesisCallback#start start()} to indicate that the engine is ready to deliver -the -audio, then call {@link android.speech.tts.SynthesisCallback#audioAvailable audioAvailable()}, -passing it the audio -data in a byte buffer. Once your engine has passed all audio through the buffer, call {@link -android.speech.tts.SynthesisCallback#done()}.</li> +the audio, then call {@link android.speech.tts.SynthesisCallback#audioAvailable audioAvailable()}, +passing it the audio data in a byte buffer. Once your engine has passed all audio through the +buffer, call {@link android.speech.tts.SynthesisCallback#done()}.</li> </ul> -<p>Now that the framework supports a true API for creating TTS engines, support for the previous -technique using native code has been removed. Watch for a blog post about the compatibility layer -that you can use to convert TTS engines built using the previous technique to the new framework.</p> +<p>Now that the framework supports a true API for creating TTS engines, support for the native code +implementation has been removed. Look for a blog post about a compatibility layer +that you can use to convert your old TTS engines to the new framework.</p> <p>For an example TTS engine using the new APIs, see the <a href=â€{@docRoot}resources/samples/TtsEngine/index.htmlâ€>Text To Speech Engine</a> sample app.</p> @@ -1057,6 +1109,27 @@ href=â€{@docRoot}resources/samples/TtsEngine/index.htmlâ€>Text To Speech Engin +<h3 id="SpellChecker">Spell Checker Services</h3> + +<p>A new spell checker framework allows apps to create spell checkers in a manner similar to the +input method framework. To create a new spell checker, you must implement a service that extends +{@link android.service.textservice.SpellCheckerService} and extend the {@link +android.service.textservice.SpellCheckerService.Session} class to provide spelling suggestions based +on text provided by interface callback methods. In the {@link +android.service.textservice.SpellCheckerService.Session} callback methods, you must return the +spelling suggestions as {@link android.view.textservice.SuggestionsInfo} objects. </p> + +<p>Applications with a spell checker service must declare the {@link +android.Manifest.permission#BIND_TEXT_SERVICE} permission as required by the service, such that +other services must have this permission in order for them to bind with the spell checker service. +The service must also declare an intent filter with {@code <action +android:name="android.service.textservice.SpellCheckerService" />} as the intent’s action and should +include a {@code <meta-data>} element that declares configuration information for the spell +checker. </p> + + + + @@ -1066,34 +1139,36 @@ href=â€{@docRoot}resources/samples/TtsEngine/index.htmlâ€>Text To Speech Engin <p>The {@link android.app.ActionBar} has been updated to support several new behaviors. Most importantly, the system gracefully manages the action bar’s size and configuration when running on -smaller screens in order to provide an optimal user experience. For example, when the screen is -narrow (such as when a handset is in portrait orientation), the action bar’s navigation tabs appear -in a “stacked bar,†which appears directly below the main action bar. You can also opt-in to a -“split action bar,†which will place all action items in a separate bar at the bottom of the screen -when the screen is narrow.</p> +smaller screens in order to provide an optimal user experience on all screen sizes. For example, +when the screen is narrow (such as when a handset is in portrait orientation), the action bar’s +navigation tabs appear in a “stacked bar,†which appears directly below the main action bar. You can +also opt-in to a “split action bar,†which places all action items in a separate bar at the bottom +of the screen when the screen is narrow.</p> -<h4>Split Action Bar</h4> +<h4>Split action bar</h4> -<p>If your action bar includes several action items, not all of them will fit into the action bar -when on a narrow screen, so the system will place them into the overflow menu. However, Android 4.0 +<p>If your action bar includes several action items, not all of them will fit into the action bar on +a narrow screen, so the system will place more of them into the overflow menu. However, Android 4.0 allows you to enable “split action bar†so that more action items can appear on the screen in a separate bar at the bottom of the screen. To enable split action bar, add {@link android.R.attr#uiOptions android:uiOptions} with {@code â€splitActionBarWhenNarrowâ€} to either your -{@code <application>} tag or individual {@code <activity>} tags in your manifest file. -When enabled, the system will enable the additional bar for action items when the screen is narrow -and add all action items to the new bar (no action items will appear in the primary action bar).</p> +<a href="guide/topics/manifest/application-element.html">{@code <application>}</a> tag or +individual <a href="guide/topics/manifest/activity-element.html">{@code <activity>}</a> tags +in your manifest file. When enabled, the system will add an additional bar at the bottom of the +screen for all action items when the screen is narrow (no action items will appear in the primary +action bar).</p> <p>If you want to use the navigation tabs provided by the {@link android.app.ActionBar.Tab} APIs, -but -don’t want the stacked bar—you want only the tabs to appear, then enable the split action bar -as described above and also call {@link android.app.ActionBar#setDisplayShowHomeEnabled -setDisplayShowHomeEnabled(false)} to disable the application icon in the action bar. With nothing -left in the main action bar, it disappears—all that’s left are the navigation tabs at the top -and the action items at the bottom of the screen.</p> +but don’t need the main action bar on top (you want only the tabs to appear at the top), then enable +the split action bar as described above and also call {@link +android.app.ActionBar#setDisplayShowHomeEnabled setDisplayShowHomeEnabled(false)} to disable the +application icon in the action bar. With nothing left in the main action bar, it +disappears—all that’s left are the navigation tabs at the top and the action items at the +bottom of the screen.</p> -<h4>Action Bar Styles</h4> +<h4>Action bar styles</h4> <p>If you want to apply custom styling to the action bar, you can use new style properties {@link android.R.attr#backgroundStacked} and {@link android.R.attr#backgroundSplit} to apply a background @@ -1103,31 +1178,38 @@ setStackedBackgroundDrawable()} and {@link android.app.ActionBar#setSplitBackgro setSplitBackgroundDrawable()}.</p> -<h4>Action Provider</h4> +<h4>Action provider</h4> + +<p>The new {@link android.view.ActionProvider} class allows you to create a specialized handler for +action items. An action provider can define an action view, a default action behavior, and a submenu +for each action item to which it is associated. When you want to create an action item that has +dynamic behaviors (such as a variable action view, default action, or submenu), extending {@link +android.view.ActionProvider} is a good solution in order to create a reusable component, rather than +handling the various action item transformations in your fragment or activity.</p> -<p>The new {@link android.view.ActionProvider} class facilitates user actions to which several -different applications may respond. For example, a “share†action in your application might invoke -several different apps that can handle the {@link android.content.Intent#ACTION_SEND} intent and the -associated data. In this case, you can use the {@link android.widget.ShareActionProvider} (an -extension of {@link android.view.ActionProvider}) in your action bar, instead of a traditional menu -item that invokes the intent. The {@link android.widget.ShareActionProvider} populates a drop-down -menu with all the available apps that can handle the intent.</p> +<p>For example, the {@link android.widget.ShareActionProvider} is an extension of {@link +android.view.ActionProvider} that facilitates a “share†action from the action bar. Instead of using +traditional action item that invokes the {@link android.content.Intent#ACTION_SEND} intent, you can +use this action provider to present an action view with a drop-down list of applications that handle +the {@link android.content.Intent#ACTION_SEND} intent. When the user selects an application to use +for the action, {@link android.widget.ShareActionProvider} remembers that selection and provides it +in the action view for faster access to sharing with that app.</p> <p>To declare an action provider for an action item, include the {@code android:actionProviderClass} -attribute in the {@code <item>} element for your activity’s options menu, with the class name -of the action provider as the attribute value. For example:</p> +attribute in the <a href="{@docRoot}guide/topics/resources/menu-resource.html#item-element">{@code +<item>}</a> element for your activity’s options menu, with the class name of the action +provider as the value. For example:</p> <pre> <item android:id="@+id/menu_share" android:title="Share" - android:icon="@drawable/ic_share" android:showAsAction="ifRoom" android:actionProviderClass="android.widget.ShareActionProvider" /> </pre> <p>In your activity’s {@link android.app.Activity#onCreateOptionsMenu onCreateOptionsMenu()} -callback -method, retrieve an instance of the action provider from the menu item and set the intent:</p> +callback method, retrieve an instance of the action provider from the menu item and set the +intent:</p> <pre> public boolean onCreateOptionsMenu(Menu menu) { @@ -1146,17 +1228,18 @@ href=â€{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/Ac class in ApiDemos.</p> -<h4>Collapsible Action Views</h4> +<h4>Collapsible action views</h4> -<p>Menu items that appear as action items can now toggle between their action view state and +<p>Action items that provide an action view can now toggle between their action view state and traditional action item state. Previously only the {@link android.widget.SearchView} supported collapsing when used as an action view, but now you can add an action view for any action item and switch between the expanded state (action view is visible) and collapsed state (action item is visible).</p> <p>To declare that an action item that contains an action view be collapsible, include the {@code -“collapseActionViewâ€} flag in the {@code android:showAsAction} attribute for the {@code -<item>} element in the menu’s XML file.</p> +“collapseActionViewâ€} flag in the {@code android:showAsAction} attribute for the <a +href="{@docRoot}guide/topics/resources/menu-resource.html#item-element">{@code +<item>}</a> element in the menu’s XML file.</p> <p>To receive callbacks when an action view switches between expanded and collapsed, register an instance of {@link android.view.MenuItem.OnActionExpandListener} with the respective {@link @@ -1173,20 +1256,20 @@ android.view.CollapsibleActionView} interface to receive callbacks when the view collapsed.</p> -<h4>Other APIs for Action Bar</h4> +<h4>Other APIs for action bar</h4> <ul> -<li>{@link android.app.ActionBar#setHomeButtonEnabled setHomeButtonEnabled()} allows you to disable -the -default behavior in which the application icon/logo behaves as a button (pass “false†to disable it -as a button).</li> +<li>{@link android.app.ActionBar#setHomeButtonEnabled setHomeButtonEnabled()} allows you to specify +whether the icon/logo behaves as a button to navigate home or “up†(pass “true†to make it behave as +a button).</li> + <li>{@link android.app.ActionBar#setIcon setIcon()} and {@link android.app.ActionBar#setLogo -setLogo()} -to define the action bar icon or logo at runtime.</li> +setLogo()} allow you to define the action bar icon or logo at runtime.</li> + <li>{@link android.app.Fragment#setMenuVisibility Fragment.setMenuVisibility()} allows you to enable -or -disable the visibility of the options menu items declared by the fragment. This is useful if the +or disable the visibility of the options menu items declared by the fragment. This is useful if the fragment has been added to the activity, but is not visible, so the menu items should be hidden.</li> + <li>{@link android.app.FragmentManager#invalidateOptionsMenu FragmentManager.invalidateOptionsMenu()} allows you to invalidate the activity options menu during various states of the fragment lifecycle @@ -1204,6 +1287,7 @@ in which using the equivalent method from {@link android.app.Activity} might not <p>Android 4.0 introduces a variety of new views and other UI components.</p> + <h4>System UI</h4> <p>Since the early days of Android, the system has managed a UI component known as the <em>status @@ -1214,8 +1298,8 @@ Back, and so forth) and also an interface for elements traditionally provided by Android 4.0, the system provides a new type of system UI called the <em>navigation bar</em>. The navigation bar shares some qualities with the system bar, because it provides navigation controls for devices that don’t have hardware counterparts for navigating the system, but the navigation -controls is all that it provides (a device with the navigation bar, thus, also includes the status -bar at the top of the screen).</p> +controls is all that the navigation bar offers (a device with the navigation bar, thus, also +includes the status bar at the top of the screen).</p> <p>To this day, you can hide the status bar on handsets using the {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN} flag. In Android 4.0, the APIs that control @@ -1223,32 +1307,31 @@ the system bar’s visibility have been updated to better reflect the behavior o and navigation bar:</p> <ul> <li>The {@link android.view.View#SYSTEM_UI_FLAG_LOW_PROFILE} flag replaces View.STATUS_BAR_HIDDEN -flag -(now deprecated). When set, this flag enables “low profile†mode for the system bar or navigation -bar. Navigation buttons dim and other elements in the system bar also hide.</li> +flag. When set, this flag enables “low profile†mode for the system bar or +navigation bar. Navigation buttons dim and other elements in the system bar also hide.</li> + <li>The {@link android.view.View#SYSTEM_UI_FLAG_VISIBLE} flag replaces the {@code -STATUS_BAR_VISIBLE} -flag to request the system bar or navigation bar be visible.</li> +STATUS_BAR_VISIBLE} flag to request the system bar or navigation bar be visible.</li> + <li>The {@link android.view.View#SYSTEM_UI_FLAG_HIDE_NAVIGATION} is a new flag that requests that -the -navigation bar hide completely. Take note that this works only for the <em>navigation bar</em> used -by some handsets (it does <strong>not</strong> hide the system bar on tablets). The navigation bar -returns as soon as the system receives user input. As such, this mode is generally used for video -playback or other cases in which user input is not required.</li> +the navigation bar hide completely. Take note that this works only for the <em>navigation bar</em> +used by some handsets (it does <strong>not</strong> hide the system bar on tablets). The navigation +bar returns as soon as the system receives user input. As such, this mode is generally used for +video playback or other cases in which the whole screen is needed but user input is not +required.</li> </ul> -<p>You can set each of these flags for the system bar by calling {@link -android.view.View#setSystemUiVisibility setSystemUiVisibility()} on any view in your activity -window. The window manager will combine (OR-together) all flags from all views in your window and +<p>You can set each of these flags for the system bar and navigation bar by calling {@link +android.view.View#setSystemUiVisibility setSystemUiVisibility()} on any view in your activity. The +window manager will combine (OR-together) all flags from all views in your window and apply them to the system UI as long as your window has input focus. When your window loses input focus (the user navigates away from your app, or a dialog appears), your flags cease to have effect. Similarly, if you remove those views from the view hierarchy their flags no longer apply.</p> <p>To synchronize other events in your activity with visibility changes to the system UI (for -example, -hide the action bar or other UI controls when the system UI hides), you can register a {@link -android.view.View.OnSystemUiVisibilityChangeListener} to get a callback when the visibility -changes.</p> +example, hide the action bar or other UI controls when the system UI hides), you should register a +{@link android.view.View.OnSystemUiVisibilityChangeListener} to be notified when the visibility +of the system bar or navigation bar changes.</p> <p>See the <a href=â€{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/view/OverscanActivity.htmlâ€> @@ -1258,8 +1341,7 @@ OverscanActivity</a> class for a demonstration of different system UI options.</ <h4>GridLayout</h4> <p>{@link android.widget.GridLayout} is a new view group that places child views in a rectangular -grid. -Unlike {@link android.widget.TableLayout}, {@link android.widget.GridLayout} relies on a flat +grid. Unlike {@link android.widget.TableLayout}, {@link android.widget.GridLayout} relies on a flat hierarchy and does not make use of intermediate views such as table rows for providing structure. Instead, children specify which row(s) and column(s) they should occupy (cells can span multiple rows and/or columns), and by default are laid out sequentially across the grid’s rows and columns. @@ -1277,11 +1359,10 @@ for samples using {@link android.widget.GridLayout}.</p> <h4>TextureView</h4> <p>{@link android.view.TextureView} is a new view that allows you to display a content stream, such -as -a video or an OpenGL scene. Although similar to {@link android.view.SurfaceView}, {@link +as a video or an OpenGL scene. Although similar to {@link android.view.SurfaceView}, {@link android.view.TextureView} is unique in that it behaves like a regular view, rather than creating a separate window, so you can treat it like any other {@link android.view.View} object. For example, -you can apply transforms, animate it using {@link android.view.ViewPropertyAnimator}, or easily +you can apply transforms, animate it using {@link android.view.ViewPropertyAnimator}, or adjust its opacity with {@link android.view.View#setAlpha setAlpha()}.</p> <p>Beware that {@link android.view.TextureView} works only within a hardware accelerated window.</p> @@ -1289,16 +1370,14 @@ adjust its opacity with {@link android.view.View#setAlpha setAlpha()}.</p> <p>For more information, see the {@link android.view.TextureView} documentation.</p> -<h4>Switch Widget</h4> +<h4>Switch widget</h4> <p>The new {@link android.widget.Switch} widget is a two-state toggle that users can drag to one -side -or the other (or simply tap) to toggle an option between two states.</p> +side or the other (or simply tap) to toggle an option between two states.</p> -<p>You can declare a switch in your layout with the {@code <Switch>} element. You can use the -{@code android:textOn} and {@code android:textOff} attributes to specify the text to appear on the -switch when in the on and off setting. The {@code android:text} attribute also allows you to place a -label alongside the switch.</p> +<p>You can use the {@code android:textOn} and {@code android:textOff} attributes to specify the text +to appear on the switch when in the on and off setting. The {@code android:text} attribute also +allows you to place a label alongside the switch.</p> <p>For a sample using switches, see the <a href=â€{@docRoot}resources/samples/ApiDemos/res/layout/switches.htmlâ€>switches.xml</a> layout file @@ -1307,12 +1386,11 @@ href=â€{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/view/S </a> activity.</p> -<h4>Popup Menus</h4> +<h4>Popup menus</h4> <p>Android 3.0 introduced {@link android.widget.PopupMenu} to create short contextual menus that pop -up -at an anchor point you specify (usually at the point of the item selected). Android 4.0 extends the -{@link android.widget.PopupMenu} with a couple useful features:</p> +up at an anchor point you specify (usually at the point of the item selected). Android 4.0 extends +the {@link android.widget.PopupMenu} with a couple useful features:</p> <ul> <li>You can now easily inflate the contents of a popup menu from an XML <a href=â€{@docRoot}guide/topics/resources/menu-resource.htmlâ€>menu resource</a> with {@link @@ -1321,6 +1399,7 @@ android.widget.PopupMenu#inflate inflate()}, passing it the menu resource ID.</l callback when the menu is dismissed.</li> </ul> + <h4>Preferences</h4> <p>A new {@link android.preference.TwoStatePreference} abstract class serves as the basis for @@ -1332,10 +1411,10 @@ preference screen or dialog. For example, the Settings application uses a {@link android.preference.SwitchPreference} for the Wi-Fi and Bluetooth settings.</p> -<h4>Hover Events</h4> +<h4>Hover events</h4> <p>The {@link android.view.View} class now supports “hover†events to enable richer interactions -through the use of pointer devices (such as a mouse or other device that drives an on-screen +through the use of pointer devices (such as a mouse or other devices that drive an on-screen cursor).</p> <p>To receive hover events on a view, implement the {@link android.view.View.OnHoverListener} and @@ -1355,8 +1434,7 @@ android.view.View.OnHoverListener#onHover onHover()} if it handles the hover eve listener returns false, then the hover event will be dispatched to the parent view as usual.</p> <p>If your application uses buttons or other widgets that change their appearance based on the -current -state, you can now use the {@code android:state_hovered} attribute in a <a +current state, you can now use the {@code android:state_hovered} attribute in a <a href=â€{@docRoot}guide/topics/resources/drawable-resource.html#StateListâ€>state list drawable</a> to provide a different background drawable when a cursor hovers over the view.</p> @@ -1365,11 +1443,10 @@ href=â€{@docRoot}samples/ApiDemos/src/com/example/android/apis/view/Hover.htmlâ ApiDemos.</p> -<h4>Stylus and Mouse Button Input Events</h4> +<h4>Stylus and mouse button events</h4> <p>Android now provides APIs for receiving input from a stylus input device such as a digitizer -tablet -peripheral or a stylus-enabled touch screen.</p> +tablet peripheral or a stylus-enabled touch screen.</p> <p>Stylus input operates in a similar manner to touch or mouse input. When the stylus is in contact with the digitizer, applications receive touch events just like they would when a finger is used to @@ -1388,18 +1465,16 @@ can choose to handle stylus input in different ways from finger or mouse input.< <p>Your application can also query which mouse or stylus buttons are pressed by querying the “button state†of a {@link android.view.MotionEvent} using {@link android.view.MotionEvent#getButtonState getButtonState()}. The currently defined button states are: {@link -android.view.MotionEvent#BUTTON_PRIMARY}, {@link -android.view.MotionEvent#BUTTON_SECONDARY}, {@link -android.view.MotionEvent#BUTTON_TERTIARY}, {@link android.view.MotionEvent#BUTTON_BACK}, -and {@link android.view.MotionEvent#BUTTON_FORWARD}. -For convenience, the back and forward mouse buttons are automatically mapped to the {@link -android.view.KeyEvent#KEYCODE_BACK} and {@link android.view.KeyEvent#KEYCODE_FORWARD} keys. Your -application can handle these keys to support mouse button based back and forward navigation.</p> +android.view.MotionEvent#BUTTON_PRIMARY}, {@link android.view.MotionEvent#BUTTON_SECONDARY}, {@link +android.view.MotionEvent#BUTTON_TERTIARY}, {@link android.view.MotionEvent#BUTTON_BACK}, and {@link +android.view.MotionEvent#BUTTON_FORWARD}. For convenience, the back and forward mouse buttons are +automatically mapped to the {@link android.view.KeyEvent#KEYCODE_BACK} and {@link +android.view.KeyEvent#KEYCODE_FORWARD} keys. Your application can handle these keys to support +mouse button based back and forward navigation.</p> <p>In addition to precisely measuring the position and pressure of a contact, some stylus input -devices -also report the distance between the stylus tip and the digitizer, the stylus tilt angle, and the -stylus orientation angle. Your application can query this information using {@link +devices also report the distance between the stylus tip and the digitizer, the stylus tilt angle, +and the stylus orientation angle. Your application can query this information using {@link android.view.MotionEvent#getAxisValue getAxisValue()} with the axis codes {@link android.view.MotionEvent#AXIS_DISTANCE}, {@link android.view.MotionEvent#AXIS_TILT}, and {@link android.view.MotionEvent#AXIS_ORIENTATION}.</p> @@ -1474,29 +1549,31 @@ href="{@docRoot}guide/topics/manifest/application-element.html">{@code <appli element. You can alternatively disable hardware acceleration for individual views by calling {@link android.view.View#setLayerType setLayerType(LAYER_TYPE_SOFTWARE)}.</p> +<p>For more information about hardware acceleration, including a list of unsupported drawing +operations, see the <a href="{@docRoot}guide/topics/graphics/hardware-accel.html">Hardware +Acceleration</a> document.</p> + + <h3 id="Jni">JNI Changes</h3> -<p>In previous versions of Android, JNI local references weren’t indirect handles; we used direct -pointers. This didn’t seem like a problem as long as we didn’t have a garbage collector that moves -objects, but it was because it meant that it was possible to write buggy code that still seemed to -work. In Android 4.0, we’ve moved to using indirect references so we can detect these bugs before we -need third-party native code to be correct.</p> +<p>In previous versions of Android, JNI local references weren’t indirect handles; Android used +direct pointers. This wasn't a problem as long as the garbage collector didn't move objects, but it +seemed to work because it made it possible to write buggy code. In Android 4.0, the system now uses +indirect references in order to detect these bugs.</p> -<p>The ins and outs of JNI local references are described in “Local and Global References†in -<a href="{@docRoot}guide/practices/design/jni.html">JNI Tips</a>. In Android 4.0, <a -href="http://android-developers.blogspot.com/2011/07/debugging-android-jni-with-checkjni.html">CheckJNI</a> -has been -enhanced to detect these errors. Watch the <a href=â€http://android-developers.blogspot.com/â€>Android -Developers Blog</a> for an upcoming post about common errors with JNI references and how you can fix -them.</p> +<p>The ins and outs of JNI local references are described in “Local and Global References†in <a +href="{@docRoot}guide/practices/design/jni.html">JNI Tips</a>. In Android 4.0, <a +href="http://android-developers.blogspot.com/2011/07/debugging-android-jni-with-checkjni.html"> +CheckJNI</a> has been enhanced to detect these errors. Watch the <a +href=â€http://android-developers.blogspot.com/â€>Android Developers Blog</a> for an upcoming post +about common errors with JNI references and how you can fix them.</p> <p>This change in the JNI implementation only affects apps that target Android 4.0 by setting either -the <a -href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code targetSdkVersion}</a> or -<a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code minSdkVersion}</a> to -{@code “14â€} or higher. If you’ve set these attributes to any lower -value, then JNI local references will behave the same as in previous versions.</p> +the <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code +targetSdkVersion}</a> or <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code +minSdkVersion}</a> to {@code “14â€} or higher. If you’ve set these attributes to any lower value, +then JNI local references behave the same as in previous versions.</p> @@ -1564,42 +1641,145 @@ Wi-Fi for peer-to-peer communications.</li> +<h2 id="Honeycomb">Previous APIs</h2> +<p>In addition to everything above, Android 4.0 naturally supports all APIs from previous releases. +Because the Android 3.x (Honeycomb) platform is available only for large-screen devices, if you've +been developing primarily for handsets, then you might not be aware of all the APIs added to Android +in these recent releases.</p> +<p>Here's a look at some of the most notable APIs you might have missed that are now available +on handsets as well:</p> +<dl> + <dt><a href="android-3.0.html">Android 3.0</a></dt> + <dd> + <ul> + <li>{@link android.app.Fragment}: A framework component that allows you to separate distinct +elements of an activity into self-contained modules that define their own UI and lifecycle. See the +<a href="{@docRoot}guide/topics/fundamentals/fragments.html">Fragments</a> developer guide.</li> + <li>{@link android.app.ActionBar}: A replacement for the traditional title bar at the top of +the activity window. It includes the application logo in the left corner and provides a new +interface for menu items. See the +<a href="{@docRoot}guide/topics/ui/actionbar.html">Action Bar</a> developer guide.</li> + <li>{@link android.content.Loader}: A framework component that facilitates asynchronour +loading of data in combination with UI components to dynamically load data without blocking the +main thread. See the +<a href="{@docRoot}guide/topics/fundamentals/loaders.html">Loaders</a> developer guide.</li> + <li>System clipboard: Applications can copy and paste data (beyond mere text) to and from +the system-wide clipboard. Clipped data can be plain text, a URI, or an intent. See the +<a href="{@docRoot}guide/topics/clipboard/copy-paste.html">Copy and Paste</a> developer guide.</li> + <li>Drag and drop: A set of APIs built into the view framework that facilitates drag and drop +operations. See the +<a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</li> + <li>An all new flexible animation framework allows you to animate arbitrary properties of any +object (View, Drawable, Fragment, Object, or anything else) and define animation aspects such +as duration, interpolation, repeat and more. The new framework makes Animations in Android +simpler than ever. See the +<a href="{@docRoot}guide/topics/graphics/property-animation.html">Property Animation</a> developer +guide.</li> + <li>RenderScript graphics and compute engine: RenderScript offers a high performance 3D +graphics rendering and compute API at the native level, which you write in the C (C99 standard), +providing the type of performance you expect from a native environment while remaining portable +across various CPUs and GPUs. See the +<a href="{@docRoot}guide/topics/renderscript/index.html">RenderScript</a> developer +guide.</li> + <li>Hardware accelerated 2D graphics: You can now enable the OpenGL renderer for your +application by setting {android:hardwareAccelerated="true"} in your manifest element's <a +href="{@docRoot}guide/topics/manifest/application-element.html"><code><application></code></a> +element or for individual <a +href="{@docRoot}guide/topics/manifest/activity-element.html"><code><activity></code></a> +elements. This results +in smoother animations, smoother scrolling, and overall better performance and response to user +interaction. + <p class="note"><strong>Note:</strong> If you set your application's <a +href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code minSdkVersion}</a> or <a +href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code targetSdkVersion}</a> to +{@code "14"} or higher, hardware acceleration is enabled by default.</p></li> + <li>And much, much more. See the <a href="android-3.0.html">Android 3.0 Platform</a> +notes for more information.</li> + </ul> + </dd> + + <dt><a href="android-3.1.html">Android 3.1</a></dt> + <dd> + <ul> + <li>USB APIs: Powerful new APIs for integrating connected peripherals with +Android applications. The APIs are based on a USB stack and services that are +built into the platform, including support for both USB host and device interactions. See the <a +href="{@docRoot}guide/topics/usb/index.html">USB Host and Accessory</a> developer guide.</li> + <li>MTP/PTP APIs: Applications can interact directly with connected cameras and other PTP +devices to receive notifications when devices are attached and removed, manage files and storage on +those devices, and transfer files and metadata to and from them. The MTP API implements the PTP +(Picture Transfer Protocol) subset of the MTP (Media Transfer Protocol) specification. See the +{@link android.mtp} documentation.</li> + <li>RTP APIs: Android exposes an API to its built-in RTP (Real-time Transport Protocol) stack, +which applications can use to manage on-demand or interactive data streaming. In particular, apps +that provide VOIP, push-to-talk, conferencing, and audio streaming can use the API to initiate +sessions and transmit or receive data streams over any available network. See the {@link +android.net.rtp} documentation.</li> + <li>Support for joysticks and other generic motion inputs.</li> + <li>See the <a href="android-3.1.html">Android 3.1 Platform</a> +notes for many more new APIs.</li> + </ul> + </dd> + + <dt><a href="android-3.2.html">Android 3.2</a></dt> + <dd> + <ul> + <li>New screens support APIs that give you more control over how your applications are +displayed across different screen sizes. The API extends the existing screen support model with the +ability to precisely target specific screen size ranges by dimensions, measured in +density-independent pixel units (such as 600dp or 720dp wide), rather than by their generalized +screen sizes (such as large or xlarge). For example, this is important in order to help you +distinguish between a 5" device and a 7" device, which would both traditionally be bucketed as +"large" screens. See the blog post, <a +href="http://android-developers.blogspot.com/2011/07/new-tools-for-managing-screen-sizes.html"> +New Tools for Managing Screen Sizes</a>.</li> + <li>New constants for <a +href="{@docRoot}guide/topics/manifest/uses-feature-element.html">{@code <uses-feature>}</a> to +declare landscape or portrait screen orientation requirements.</li> + <li>The device "screen size" configuration now changes during a screen orientation +change. If your app targets API level 13 or higher, you must handle the {@code "screenSize"} +configuration change if you also want to handle the {@code "orientation"} configuration change. See +<a href="{@docRoot}guide/topics/manifest/activity-element.html#config">{@code +android:configChanges}</a> for more information.</li> + <li>See the <a href="android-3.2.html">Android 3.2 Platform</a> +notes for other new APIs.</li> + </ul> + </dd> +</dl> -<h2 id="api-diff">API Differences Report</h2> -<p>For a detailed view of all API changes in Android {@sdkPlatformVersion} (API -Level -{@sdkPlatformApiLevel}), see the <a -href="{@docRoot}sdk/api_diff/{@sdkPlatformApiLevel}/changes.html">API -Differences Report</a>.</p> +<h2 id="api-diff">API Differences Report</h2> +<p>For a detailed view of all API changes in Android {@sdkPlatformVersion} (API Level +{@sdkPlatformApiLevel}), see the <a +href="{@docRoot}sdk/api_diff/{@sdkPlatformApiLevel}/changes.html">API Differences Report</a>.</p> <h2 id="api-level">API Level</h2> -<p>The Android {@sdkPlatformVersion} platform delivers an updated version of the framework API. The -Android {@sdkPlatformVersion} API is assigned an integer identifier — -<strong>{@sdkPlatformApiLevel}</strong> — that is stored in the system itself. This -identifier, called the "API Level", allows the system to correctly determine whether an application -is compatible with the system, prior to installing the application. </p> +<p>The Android {@sdkPlatformVersion} API is assigned an integer +identifier—<strong>{@sdkPlatformApiLevel}</strong>—that is stored in the system itself. +This identifier, called the "API level", allows the system to correctly determine whether an +application is compatible with the system, prior to installing the application. </p> <p>To use APIs introduced in Android {@sdkPlatformVersion} in your application, you need compile the -application against the Android library that is provided in the Android {@sdkPlatformVersion} SDK -platform. Depending on your needs, you might also need to add an +application against an Android platform that supports API level {@sdkPlatformApiLevel} or +higher. Depending on your needs, you might also need to add an <code>android:minSdkVersion="{@sdkPlatformApiLevel}"</code> attribute to the -<code><uses-sdk></code> element in the application's manifest.</p> +<a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html">{@code <uses-sdk>}</a> +element.</p> -<p>For more information about how to use API Level, see the <a -href="{@docRoot}guide/appendix/api-levels.html">API Levels</a> document. </p> +<p>For more information, see the <a href="{@docRoot}guide/appendix/api-levels.html">API Levels</a> +document. </p> <h2 id="apps">Built-in Applications</h2> @@ -1614,6 +1794,7 @@ built-in applications:</p> <li>API Demos</li> <li>Browser</li> <li>Calculator</li> +<li>Calendar</li> <li>Camera</li> <li>Clock</li> <li>Custom Locale</li> @@ -1632,7 +1813,7 @@ built-in applications:</p> <li>Phone</li> <li>Search</li> <li>Settings</li> -<li>Spare Parts</li> +<li>Speech Recorder</li> <li>Speech Recorder</li> <li>Widget Preview</li> </ul> @@ -1643,13 +1824,10 @@ built-in applications:</p> <h2 id="locs" style="margin-top:.75em;">Locales</h2> -<p>The system image included in the downloadable SDK platform provides a variety -of -built-in locales. In some cases, region-specific strings are available for the -locales. In other cases, a default version of the language is used. The -languages that are available in the Android 3.0 system -image are listed below (with <em>language</em>_<em>country/region</em> locale -descriptor).</p> +<p>The system image included in the downloadable SDK platform provides a variety of built-in +locales. In some cases, region-specific strings are available for the locales. In other cases, a +default version of the language is used. The languages that are available in the Android 3.0 system +image are listed below (with <em>language</em>_<em>country/region</em> locale descriptor).</p> <table style="border:0;padding-bottom:0;margin-bottom:0;"> <tr> @@ -1726,15 +1904,45 @@ Project</a>.</p> <h2 id="skins">Emulator Skins</h2> -<p>The downloadable platform includes the following emulator skin:</p> +<p>The downloadable platform includes the following emulator skins:</p> <ul> <li> - WVGA800 (1280x800, extra high density, normal screen) + QVGA (240x320, low density, small screen) + </li> + <li> + WQVGA400 (240x400, low density, normal screen) + </li> + <li> + WQVGA432 (240x432, low density, normal screen) + </li> + <li> + HVGA (320x480, medium density, normal screen) + </li> + <li> + WVGA800 (480x800, high density, normal screen) + </li> + <li> + WVGA854 (480x854 high density, normal screen) + </li> + <li> + WXGA720 (1280x720, extra-high density, normal screen) <span class="new">new</span> + </li> + <li> + WSVGA (1024x600, medium density, large screen) <span class="new">new</span> + </li> + <li> + WXGA (1280x800, medium density, xlarge screen) </li> </ul> -<p>For more information about how to develop an application that displays -and functions properly on all Android-powered devices, see <a -href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple -Screens</a>.</p> +<p>To test your application on an emulator that represents the latest Android device, you can create +an AVD with the new WXGA720 skin (it's an xhdpi, normal screen device). Note that the emulator +currently doesn't support the new on-screen navigation bar for devices without hardware navigation +buttons, so when using this skin, you must use keyboard keys <em>Home</em> for the Home button, +<em>ESC</em> for the Back button, and <em>F2</em> or <em>Page-up</em> for the Menu button.</p> + +<p>However, due to performance issues in the emulator when running high-resolution screens such as +the one for the WXGA720 skin, we recommend that you primarily use the traditional WVGA800 skin +(hdpi, normal screen) to test your application.</p> + diff --git a/docs/html/sdk/eclipse-adt.jd b/docs/html/sdk/eclipse-adt.jd index 333efa27724c..dab5b29feac5 100644 --- a/docs/html/sdk/eclipse-adt.jd +++ b/docs/html/sdk/eclipse-adt.jd @@ -1,8 +1,8 @@ page.title=ADT Plugin for Eclipse adt.zip.version=14.0.0 adt.zip.download=ADT-14.0.0.zip -adt.zip.bytes=6745584 -adt.zip.checksum=a645330d90fd9dae6187662bb1c3c644 +adt.zip.bytes=6745047 +adt.zip.checksum=014312e1553e3b8da55cb6a24e33e432 @jd:body diff --git a/docs/html/sdk/index.jd b/docs/html/sdk/index.jd index 065f41b68226..67be5c9650da 100644 --- a/docs/html/sdk/index.jd +++ b/docs/html/sdk/index.jd @@ -2,20 +2,20 @@ page.title=Android SDK sdk.redirect=0 sdk.win_installer=installer_r14-windows.exe -sdk.win_installer_bytes=33860145 -sdk.win_installer_checksum=7a563491bf4671d09b9da0dcde85f212 +sdk.win_installer_bytes=33860326 +sdk.win_installer_checksum=6d4f76385daaee766ad901699cdae6cc sdk.win_download=android-sdk_r14-windows.zip -sdk.win_bytes=33852972 -sdk.win_checksum=d1381a0cc8e6f9358174aa6d051ba379 +sdk.win_bytes=33853090 +sdk.win_checksum=0c39628e296d6176ed928cc64498ba04 sdk.mac_download=android-sdk_r14-macosx.zip -sdk.mac_bytes=30426052 -sdk.mac_checksum=df0a5c5b5327ffcaf256ce735998e12a +sdk.mac_bytes=30426431 +sdk.mac_checksum=189ce3e26dfb46298a7def21d3bdf271 sdk.linux_download=android-sdk_r14-linux.tgz -sdk.linux_bytes=26083315 -sdk.linux_checksum=2049d5c1a164fcae47a5e93c52200752 +sdk.linux_bytes=26082867 +sdk.linux_checksum=500483f8acd0d3cae94c68c3dcefbb98 @jd:body diff --git a/docs/html/sdk/tools-notes.jd b/docs/html/sdk/tools-notes.jd index 2d044ed89918..6cb246cbf407 100644 --- a/docs/html/sdk/tools-notes.jd +++ b/docs/html/sdk/tools-notes.jd @@ -66,7 +66,12 @@ padding: .25em 1em; <a href="#" onclick="return toggleDiv(this)"> <img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-img" height="9px" width="9px" />SDK Tools, Revision 14</a> <em>(October 2011)</em> + <div class="toggleme"> + <p class="note"><strong>Important:</strong> To download the new Android + 4.0 system components from the Android SDK Manager, you must first update the + SDK tools to revision 14 and restart the Android SDK Manager. If you do not, + the Android 4.0 system components will not be available for download.</p> <dl> <dt>Dependencies:</dt> <dd> @@ -81,6 +86,9 @@ padding: .25em 1em; <dt>General notes:</dt> <dd> <ul> + <li>Added webcam support to Android 4.0 or later platforms to emulate rear-facing cameras when one webcam is present, + and to emulate both rear-facing and front-facing cameras when two webcams are present. Webcam suport is for Windows and Linux only. + Mac support will come in a later release.</li> <li>Changed <code>default.properties</code> to <code>project.properties</code> and <code>build.properties</code> to <code>ant.properties</code>. Any existing projects that you build with Ant must be updated with the <code>android update project</code> @@ -90,7 +98,6 @@ padding: .25em 1em; commands, see the <a href="{@docRoot}guide/developing/building/building-cmdline.html#AntReference">Ant Command Reference</a>.</li> - <li>Changed how library projects are built.</a></li> <li>Improved incremental builds, so that resource compilation runs less frequently. Builds no longer run when you edit strings or layouts (unless you add a new <code>id</code>) and no longer diff --git a/libs/rs/rsContext.cpp b/libs/rs/rsContext.cpp index 53d497004fc6..2d5120853b8d 100644 --- a/libs/rs/rsContext.cpp +++ b/libs/rs/rsContext.cpp @@ -319,8 +319,12 @@ void Context::destroyWorkerThreadResources() { void Context::printWatchdogInfo(void *ctx) { Context *rsc = (Context *)ctx; - LOGE("RS watchdog timeout: %i %s line %i %s", rsc->watchdog.inRoot, - rsc->watchdog.command, rsc->watchdog.line, rsc->watchdog.file); + if (rsc->watchdog.command && rsc->watchdog.file) { + LOGE("RS watchdog timeout: %i %s line %i %s", rsc->watchdog.inRoot, + rsc->watchdog.command, rsc->watchdog.line, rsc->watchdog.file); + } else { + LOGE("RS watchdog timeout: %i", rsc->watchdog.inRoot); + } } diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java index 4f4f9297e614..0c5e673a0fae 100644 --- a/media/java/android/media/AudioService.java +++ b/media/java/android/media/AudioService.java @@ -85,8 +85,7 @@ public class AudioService extends IAudioService.Stub { private static final String TAG = "AudioService"; /** Debug remote control client/display feature */ - // TODO set to false before release - protected static final boolean DEBUG_RC = true; + protected static final boolean DEBUG_RC = false; /** How long to delay before persisting a change in volume/ringer mode. */ private static final int PERSIST_DELAY = 3000; diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back.png Binary files differindex 3adcbec558d9..4a1d37e53001 100644 --- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back.png +++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back.png diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_highlight.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_highlight.png Binary files differindex d7a591c668d6..9378fac62a05 100644 --- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_highlight.png +++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_highlight.png diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_in.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_in.png Binary files differindex 277dcb8a49b0..6e845462f396 100644 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_in.png +++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_in.png diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_inout.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_inout.png Binary files differindex edc17606680f..c56905e09e81 100644 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_inout.png +++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_inout.png diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_out.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_out.png Binary files differindex fbc6b99115b9..11ffbde017f5 100644 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_out.png +++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_out.png diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_in.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_in.png Binary files differindex fb938e8f8bc5..2bb923e6dbd4 100644 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_in.png +++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_in.png diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_inout.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_inout.png Binary files differindex 2d35517f9356..783ad1755100 100644 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_inout.png +++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_inout.png diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_out.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_out.png Binary files differindex fe68c3c18e87..e499f9d42847 100644 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_out.png +++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_out.png diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back.png Binary files differindex 49411bd60564..39e3df07062d 100644 --- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back.png +++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back.png diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_highlight.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_highlight.png Binary files differindex 77924f04688d..b4920c3505df 100644 --- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_highlight.png +++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_highlight.png diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_in.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_in.png Binary files differindex 000e98b05af2..31c093662361 100644 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_in.png +++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_in.png diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_inout.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_inout.png Binary files differindex 62b940a205c5..7e9b752f7b9b 100644 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_inout.png +++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_inout.png diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_out.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_out.png Binary files differindex 5beb543f44cb..3209234d94a0 100644 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_out.png +++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_out.png diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_in.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_in.png Binary files differindex f70d3154cfa1..95c56ede38a5 100644 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_in.png +++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_in.png diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_inout.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_inout.png Binary files differindex be9953f64da7..11b9a93aaa0a 100644 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_inout.png +++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_inout.png diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_out.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_out.png Binary files differindex de20bdd23d71..0f85ca0d7380 100644 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_out.png +++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_out.png diff --git a/packages/SystemUI/res/drawable-sw600dp-hdpi/stat_sys_signal_in.png b/packages/SystemUI/res/drawable-sw600dp-hdpi/stat_sys_signal_in.png Binary files differindex 8a3d90c63a86..3d6776611d86 100644 --- a/packages/SystemUI/res/drawable-sw600dp-hdpi/stat_sys_signal_in.png +++ b/packages/SystemUI/res/drawable-sw600dp-hdpi/stat_sys_signal_in.png diff --git a/packages/SystemUI/res/drawable-sw600dp-hdpi/stat_sys_signal_inout.png b/packages/SystemUI/res/drawable-sw600dp-hdpi/stat_sys_signal_inout.png Binary files differindex 45dda51c63f6..b74e070e4378 100644 --- a/packages/SystemUI/res/drawable-sw600dp-hdpi/stat_sys_signal_inout.png +++ b/packages/SystemUI/res/drawable-sw600dp-hdpi/stat_sys_signal_inout.png diff --git a/packages/SystemUI/res/drawable-sw600dp-hdpi/stat_sys_signal_out.png b/packages/SystemUI/res/drawable-sw600dp-hdpi/stat_sys_signal_out.png Binary files differindex 18e019cf8c1d..24485e1c076c 100644 --- a/packages/SystemUI/res/drawable-sw600dp-hdpi/stat_sys_signal_out.png +++ b/packages/SystemUI/res/drawable-sw600dp-hdpi/stat_sys_signal_out.png diff --git a/packages/SystemUI/res/drawable-sw600dp-hdpi/stat_sys_wifi_in.png b/packages/SystemUI/res/drawable-sw600dp-hdpi/stat_sys_wifi_in.png Binary files differindex cb8ed3ac61e7..390d500d5181 100644 --- a/packages/SystemUI/res/drawable-sw600dp-hdpi/stat_sys_wifi_in.png +++ b/packages/SystemUI/res/drawable-sw600dp-hdpi/stat_sys_wifi_in.png diff --git a/packages/SystemUI/res/drawable-sw600dp-hdpi/stat_sys_wifi_inout.png b/packages/SystemUI/res/drawable-sw600dp-hdpi/stat_sys_wifi_inout.png Binary files differindex ab4ad05d1307..78998f9fee9e 100644 --- a/packages/SystemUI/res/drawable-sw600dp-hdpi/stat_sys_wifi_inout.png +++ b/packages/SystemUI/res/drawable-sw600dp-hdpi/stat_sys_wifi_inout.png diff --git a/packages/SystemUI/res/drawable-sw600dp-hdpi/stat_sys_wifi_out.png b/packages/SystemUI/res/drawable-sw600dp-hdpi/stat_sys_wifi_out.png Binary files differindex 956b6c1822ac..c539615c0e88 100644 --- a/packages/SystemUI/res/drawable-sw600dp-hdpi/stat_sys_wifi_out.png +++ b/packages/SystemUI/res/drawable-sw600dp-hdpi/stat_sys_wifi_out.png diff --git a/packages/SystemUI/res/drawable-sw600dp-mdpi/stat_sys_signal_in.png b/packages/SystemUI/res/drawable-sw600dp-mdpi/stat_sys_signal_in.png Binary files differindex 9d95f172b43b..5c38d45b2989 100644 --- a/packages/SystemUI/res/drawable-sw600dp-mdpi/stat_sys_signal_in.png +++ b/packages/SystemUI/res/drawable-sw600dp-mdpi/stat_sys_signal_in.png diff --git a/packages/SystemUI/res/drawable-sw600dp-mdpi/stat_sys_signal_inout.png b/packages/SystemUI/res/drawable-sw600dp-mdpi/stat_sys_signal_inout.png Binary files differindex e68d57dd91a8..6a7969572f3f 100644 --- a/packages/SystemUI/res/drawable-sw600dp-mdpi/stat_sys_signal_inout.png +++ b/packages/SystemUI/res/drawable-sw600dp-mdpi/stat_sys_signal_inout.png diff --git a/packages/SystemUI/res/drawable-sw600dp-mdpi/stat_sys_signal_out.png b/packages/SystemUI/res/drawable-sw600dp-mdpi/stat_sys_signal_out.png Binary files differindex 4ac361d9682b..99dbe1b9bb4b 100644 --- a/packages/SystemUI/res/drawable-sw600dp-mdpi/stat_sys_signal_out.png +++ b/packages/SystemUI/res/drawable-sw600dp-mdpi/stat_sys_signal_out.png diff --git a/packages/SystemUI/res/drawable-sw600dp-mdpi/stat_sys_wifi_in.png b/packages/SystemUI/res/drawable-sw600dp-mdpi/stat_sys_wifi_in.png Binary files differindex 5e7ecdcd7d56..6a73a89b7dc7 100644 --- a/packages/SystemUI/res/drawable-sw600dp-mdpi/stat_sys_wifi_in.png +++ b/packages/SystemUI/res/drawable-sw600dp-mdpi/stat_sys_wifi_in.png diff --git a/packages/SystemUI/res/drawable-sw600dp-mdpi/stat_sys_wifi_inout.png b/packages/SystemUI/res/drawable-sw600dp-mdpi/stat_sys_wifi_inout.png Binary files differindex 462fad4789ff..7042f2b6d8d2 100644 --- a/packages/SystemUI/res/drawable-sw600dp-mdpi/stat_sys_wifi_inout.png +++ b/packages/SystemUI/res/drawable-sw600dp-mdpi/stat_sys_wifi_inout.png diff --git a/packages/SystemUI/res/drawable-sw600dp-mdpi/stat_sys_wifi_out.png b/packages/SystemUI/res/drawable-sw600dp-mdpi/stat_sys_wifi_out.png Binary files differindex d284c021a88c..3da781e8e120 100644 --- a/packages/SystemUI/res/drawable-sw600dp-mdpi/stat_sys_wifi_out.png +++ b/packages/SystemUI/res/drawable-sw600dp-mdpi/stat_sys_wifi_out.png diff --git a/packages/SystemUI/res/drawable-sw600dp-xhdpi/stat_sys_signal_in.png b/packages/SystemUI/res/drawable-sw600dp-xhdpi/stat_sys_signal_in.png Binary files differindex 4a5e70180317..cf63e2416e34 100644 --- a/packages/SystemUI/res/drawable-sw600dp-xhdpi/stat_sys_signal_in.png +++ b/packages/SystemUI/res/drawable-sw600dp-xhdpi/stat_sys_signal_in.png diff --git a/packages/SystemUI/res/drawable-sw600dp-xhdpi/stat_sys_signal_inout.png b/packages/SystemUI/res/drawable-sw600dp-xhdpi/stat_sys_signal_inout.png Binary files differindex 9a089498d680..8f68e1f288d5 100644 --- a/packages/SystemUI/res/drawable-sw600dp-xhdpi/stat_sys_signal_inout.png +++ b/packages/SystemUI/res/drawable-sw600dp-xhdpi/stat_sys_signal_inout.png diff --git a/packages/SystemUI/res/drawable-sw600dp-xhdpi/stat_sys_signal_out.png b/packages/SystemUI/res/drawable-sw600dp-xhdpi/stat_sys_signal_out.png Binary files differindex 314f422316d8..894c63baa9de 100644 --- a/packages/SystemUI/res/drawable-sw600dp-xhdpi/stat_sys_signal_out.png +++ b/packages/SystemUI/res/drawable-sw600dp-xhdpi/stat_sys_signal_out.png diff --git a/packages/SystemUI/res/drawable-sw600dp-xhdpi/stat_sys_wifi_in.png b/packages/SystemUI/res/drawable-sw600dp-xhdpi/stat_sys_wifi_in.png Binary files differindex 4e0a48a339f6..1ec5b4907e1e 100644 --- a/packages/SystemUI/res/drawable-sw600dp-xhdpi/stat_sys_wifi_in.png +++ b/packages/SystemUI/res/drawable-sw600dp-xhdpi/stat_sys_wifi_in.png diff --git a/packages/SystemUI/res/drawable-sw600dp-xhdpi/stat_sys_wifi_inout.png b/packages/SystemUI/res/drawable-sw600dp-xhdpi/stat_sys_wifi_inout.png Binary files differindex 4eeae1dac53f..9ca3ca831111 100644 --- a/packages/SystemUI/res/drawable-sw600dp-xhdpi/stat_sys_wifi_inout.png +++ b/packages/SystemUI/res/drawable-sw600dp-xhdpi/stat_sys_wifi_inout.png diff --git a/packages/SystemUI/res/drawable-sw600dp-xhdpi/stat_sys_wifi_out.png b/packages/SystemUI/res/drawable-sw600dp-xhdpi/stat_sys_wifi_out.png Binary files differindex 1a6f1ef2db18..74241e0a1709 100644 --- a/packages/SystemUI/res/drawable-sw600dp-xhdpi/stat_sys_wifi_out.png +++ b/packages/SystemUI/res/drawable-sw600dp-xhdpi/stat_sys_wifi_out.png diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back.png Binary files differindex d85399324c6a..faeee290551c 100644 --- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back.png +++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back.png diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_highlight.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_highlight.png Binary files differindex 2e6e3ac46e23..f7e710255bce 100644 --- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_highlight.png +++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_highlight.png diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_in.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_in.png Binary files differindex 2864ec3792e2..cc9c49f3ed54 100644 --- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_in.png +++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_in.png diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_inout.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_inout.png Binary files differindex 0bb0c72ed3dd..5a313c514889 100644 --- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_inout.png +++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_inout.png diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_out.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_out.png Binary files differindex f23dd60fac65..373a4a4e0174 100644 --- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_out.png +++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_out.png diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_in.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_in.png Binary files differindex b1c316834e09..d299daf0bad8 100644 --- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_in.png +++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_in.png diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_inout.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_inout.png Binary files differindex 5e414706fefc..dcfdb7b41d91 100644 --- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_inout.png +++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_inout.png diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_out.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_out.png Binary files differindex 639842ba3209..fb8125ab785f 100644 --- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_out.png +++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_out.png diff --git a/packages/SystemUI/res/drawable/notification_row_bg.xml b/packages/SystemUI/res/drawable/notification_row_bg.xml index dc626d18163c..1bb21723af91 100644 --- a/packages/SystemUI/res/drawable/notification_row_bg.xml +++ b/packages/SystemUI/res/drawable/notification_row_bg.xml @@ -17,6 +17,6 @@ <selector xmlns:android="http://schemas.android.com/apk/res/android" android:exitFadeDuration="@android:integer/config_mediumAnimTime"> - <item android:state_pressed="true" android:drawable="@android:color/holo_blue_light" /> + <item android:state_pressed="true" android:drawable="@drawable/notification_item_background_color_pressed" /> <item android:state_pressed="false" android:drawable="@drawable/notification_item_background_color" /> </selector> diff --git a/packages/SystemUI/res/layout/status_bar_notification_row.xml b/packages/SystemUI/res/layout/status_bar_notification_row.xml index 3220e62d3075..abbc89abbd1f 100644 --- a/packages/SystemUI/res/layout/status_bar_notification_row.xml +++ b/packages/SystemUI/res/layout/status_bar_notification_row.xml @@ -41,7 +41,7 @@ android:layout_width="match_parent" android:layout_height="@dimen/notification_divider_height" android:layout_alignParentBottom="true" - android:background="@drawable/notification_item_background_color" + android:background="@drawable/status_bar_notification_row_background_color" /> </RelativeLayout> diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml index 5ba19084e066..c88d65134b50 100644 --- a/packages/SystemUI/res/values/colors.xml +++ b/packages/SystemUI/res/values/colors.xml @@ -19,6 +19,7 @@ <resources> <drawable name="notification_number_text_color">#ffffffff</drawable> <drawable name="notification_item_background_color">#ff111111</drawable> + <drawable name="notification_item_background_color_pressed">#ff257390</drawable> <drawable name="ticker_background_color">#ff1d1d1d</drawable> <drawable name="status_bar_background">#ff000000</drawable> <drawable name="status_bar_recents_background">#b3000000</drawable> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index e971896e9617..65d513853ccf 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -305,6 +305,9 @@ <!-- Content description of the ringer silent icon in the notification panel for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> <string name="accessibility_ringer_silent">Ringer silent.</string> + <!-- Content description to tell the user an application has been removed from recents --> + <string name="accessibility_recents_item_dismissed"><xliff:g id="app" example="Calendar">%s</xliff:g> dismissed.</string> + <!-- Title of dialog shown when 2G-3G data usage has exceeded limit and has been disabled. [CHAR LIMIT=48] --> <string name="data_usage_disabled_dialog_3g_title">2G-3G data disabled</string> <!-- Title of dialog shown when 4G data usage has exceeded limit and has been disabled. [CHAR LIMIT=48] --> diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java index 5b4c33e1890d..8d5c33f8beb1 100644 --- a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java @@ -38,6 +38,7 @@ import android.view.MenuItem; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; +import android.view.accessibility.AccessibilityEvent; import android.view.animation.AnimationUtils; import android.widget.AdapterView; import android.widget.BaseAdapter; @@ -483,7 +484,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); } @@ -511,6 +513,12 @@ public class RecentsPanelView extends RelativeLayout final ActivityManager am = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE); am.removeTask(ad.persistentTaskId, ActivityManager.REMOVE_TASK_KILL_PROCESS); + + // Accessibility feedback + setContentDescription( + mContext.getString(R.string.accessibility_recents_item_dismissed, ad.getLabel())); + sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED); + setContentDescription(null); } private void startApplicationDetailsActivity(String packageName) { 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/KeyguardStatusViewManager.java b/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java index 8343bbdf738e..6614d7929496 100644 --- a/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java +++ b/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java @@ -609,6 +609,10 @@ class KeyguardStatusViewManager implements OnClickListener { public void onClockVisibilityChanged() { // ignored } + + public void onDeviceProvisioned() { + // ignored + } }; private SimStateCallback mSimStateCallback = new SimStateCallback() { diff --git a/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java b/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java index f67f0e056d65..2d8185b4f33c 100644 --- a/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java +++ b/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java @@ -99,6 +99,7 @@ public class KeyguardUpdateMonitor { private static final int MSG_RINGER_MODE_CHANGED = 305; private static final int MSG_PHONE_STATE_CHANGED = 306; private static final int MSG_CLOCK_VISIBILITY_CHANGED = 307; + private static final int MSG_DEVICE_PROVISIONED = 308; /** * When we receive a @@ -178,6 +179,9 @@ public class KeyguardUpdateMonitor { case MSG_CLOCK_VISIBILITY_CHANGED: handleClockVisibilityChanged(); break; + case MSG_DEVICE_PROVISIONED: + handleDeviceProvisioned(); + break; } } }; @@ -197,10 +201,8 @@ public class KeyguardUpdateMonitor { super.onChange(selfChange); mDeviceProvisioned = Settings.Secure.getInt(mContext.getContentResolver(), Settings.Secure.DEVICE_PROVISIONED, 0) != 0; - if (mDeviceProvisioned && mContentObserver != null) { - // We don't need the observer anymore... - mContext.getContentResolver().unregisterContentObserver(mContentObserver); - mContentObserver = null; + if (mDeviceProvisioned) { + mHandler.sendMessage(mHandler.obtainMessage(MSG_DEVICE_PROVISIONED)); } if (DEBUG) Log.d(TAG, "DEVICE_PROVISIONED state = " + mDeviceProvisioned); } @@ -212,8 +214,14 @@ public class KeyguardUpdateMonitor { // prevent a race condition between where we check the flag and where we register the // observer by grabbing the value once again... - mDeviceProvisioned = Settings.Secure.getInt(mContext.getContentResolver(), + boolean provisioned = Settings.Secure.getInt(mContext.getContentResolver(), Settings.Secure.DEVICE_PROVISIONED, 0) != 0; + if (provisioned != mDeviceProvisioned) { + mDeviceProvisioned = provisioned; + if (mDeviceProvisioned) { + mHandler.sendMessage(mHandler.obtainMessage(MSG_DEVICE_PROVISIONED)); + } + } } // take a guess to start @@ -271,6 +279,17 @@ public class KeyguardUpdateMonitor { }, filter); } + protected void handleDeviceProvisioned() { + for (int i = 0; i < mInfoCallbacks.size(); i++) { + mInfoCallbacks.get(i).onDeviceProvisioned(); + } + if (mContentObserver != null) { + // We don't need the observer anymore... + mContext.getContentResolver().unregisterContentObserver(mContentObserver); + mContentObserver = null; + } + } + protected void handlePhoneStateChanged(String newState) { if (DEBUG) Log.d(TAG, "handlePhoneStateChanged(" + newState + ")"); if (TelephonyManager.EXTRA_STATE_IDLE.equals(newState)) { @@ -477,6 +496,10 @@ public class KeyguardUpdateMonitor { */ void onClockVisibilityChanged(); + /** + * Called when the device becomes provisioned + */ + void onDeviceProvisioned(); } /** 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..0471dfe8c1d9 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; @@ -1323,4 +1316,9 @@ public class KeyguardViewMediator implements KeyguardViewCallback, public void onTimeChanged() { // ignored } + + /** {@inheritDoc} */ + public void onDeviceProvisioned() { + mContext.sendBroadcast(mUserPresentIntent); + } } diff --git a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java index a010ba1f3a44..80275b127c18 100644 --- a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java +++ b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java @@ -117,9 +117,17 @@ 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; + + // So the user has a consistent amount of time when brought to the backup method from FaceLock + private final int BACKUP_LOCK_TIMEOUT = 5000; /** * The current {@link KeyguardScreen} will use this to communicate back to us. @@ -128,7 +136,10 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler private boolean mRequiresSim; - private volatile boolean mEmergencyCall; + //True if we have some sort of overlay on top of the Lockscreen + //Also true if we've activated a phone call, either emergency dialing or incoming + //This resets when the phone is turned off with no current call + private boolean mHasOverlay; /** @@ -235,8 +246,6 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler } }; - private TransportControlView mTransportControlView; - /** * @return Whether we are stuck on the lock screen because the sim is * missing. @@ -269,7 +278,7 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler mUpdateMonitor = updateMonitor; mLockPatternUtils = lockPatternUtils; mWindowController = controller; - mEmergencyCall = false; + mHasOverlay = false; mUpdateMonitor.registerInfoCallback(this); @@ -324,13 +333,15 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler } public void takeEmergencyCallAction() { - mEmergencyCall = true; + mHasOverlay = 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 + if (mLockPatternUtils.usingBiometricWeak() && + mLockPatternUtils.isBiometricWeakInstalled()) { + showFaceLockAreaWithTimeout(FACELOCK_VIEW_AREA_EMERGENCY_DIALER_TIMEOUT); + } pokeWakelock(EMERGENCY_CALL_TIMEOUT); if (TelephonyManager.getDefault().getCallState() @@ -507,9 +518,10 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler @Override public void onScreenTurnedOff() { + if (DEBUG) Log.d(TAG, "screen off"); mScreenOn = false; mForgotPattern = false; - mEmergencyCall = false; + mHasOverlay = mUpdateMonitor.getPhoneState() != TelephonyManager.CALL_STATE_IDLE; if (mMode == Mode.LockScreen) { ((KeyguardScreen) mLockScreen).onPause(); } else { @@ -524,21 +536,22 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler * FaceLock, but only if we're not dealing with a call */ private void activateFaceLockIfAble() { - final boolean transportInvisible = mTransportControlView == null ? true : - mTransportControlView.getVisibility() != View.VISIBLE; - if (mUpdateMonitor.getPhoneState() == TelephonyManager.CALL_STATE_IDLE - && transportInvisible) { + if (mUpdateMonitor.getPhoneState() == TelephonyManager.CALL_STATE_IDLE && !mHasOverlay) { 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 + if (mLockPatternUtils.usingBiometricWeak() && + mLockPatternUtils.isBiometricWeakInstalled()) { + showFaceLockAreaWithTimeout(FACELOCK_VIEW_AREA_SERVICE_TIMEOUT); + } } else { - mHandler.sendEmptyMessage(MSG_HIDE_FACELOCK_AREA_VIEW); + hideFaceLockArea(); } } @Override public void onScreenTurnedOn() { + if (DEBUG) Log.d(TAG, "screen on"); boolean runFaceLock = false; //Make sure to start facelock iff the screen is both on and focused synchronized(mFaceLockStartupLock) { @@ -554,7 +567,7 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler */ @Override public void onWindowFocusChanged (boolean hasWindowFocus) { - if(DEBUG) Log.d(TAG, hasWindowFocus ? "focused" : "unfocused"); + 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) { @@ -562,14 +575,11 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler mWindowFocused = hasWindowFocus; } if(!hasWindowFocus) { + mHasOverlay = true; stopAndUnbindFromFaceLock(); - mHandler.sendEmptyMessage(MSG_HIDE_FACELOCK_AREA_VIEW); + hideFaceLockArea(); } else if (runFaceLock) { - //Don't activate facelock while the user is calling 911! - if(mEmergencyCall) mEmergencyCall = false; - else { - activateFaceLockIfAble(); - } + activateFaceLockIfAble(); } } @@ -582,10 +592,14 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler } if (mLockPatternUtils.usingBiometricWeak() && - mLockPatternUtils.isBiometricWeakInstalled()) { - mHandler.sendEmptyMessage(MSG_SHOW_FACELOCK_AREA_VIEW); + mLockPatternUtils.isBiometricWeakInstalled() && !mHasOverlay) { + // Note that show() gets called before the screen turns off to set it up for next time + // it is turned on. We don't want to set a timeout on the FaceLock area here because it + // may be gone by the time the screen is turned on again. We set the timout when the + // screen turns on instead. + showFaceLockArea(); } else { - mHandler.sendEmptyMessage(MSG_HIDE_FACELOCK_AREA_VIEW); + hideFaceLockArea(); } } @@ -645,14 +659,17 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler public void onRingerModeChanged(int state) {} @Override public void onClockVisibilityChanged() {} + @Override + public void onDeviceProvisioned() {} //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) { + mHasOverlay = true; stopAndUnbindFromFaceLock(); - mHandler.sendEmptyMessage(MSG_HIDE_FACELOCK_AREA_VIEW); + hideFaceLockArea(); } } @@ -878,13 +895,13 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler } private void initializeTransportControlView(View view) { - mTransportControlView = (TransportControlView) view.findViewById(R.id.transport); - if (mTransportControlView == null) { + TransportControlView tcv = (TransportControlView) view.findViewById(R.id.transport); + if (tcv == null) { if (DEBUG) Log.w(TAG, "Couldn't find transport control widget"); } else { mUpdateMonitor.reportClockVisible(true); - mTransportControlView.setVisibility(View.GONE); // hide until it requests being shown. - mTransportControlView.setCallback(mWidgetCallback); + tcv.setVisibility(View.GONE); // hide until it requests being shown. + tcv.setCallback(mWidgetCallback); } } @@ -1085,6 +1102,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() && @@ -1130,7 +1173,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) { @@ -1147,6 +1193,7 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler mFaceLockService = null; mFaceLockServiceRunning = false; } + mBoundToFaceLockService = false; Log.w(TAG, "Unexpected disconnect from FaceLock service"); } }; @@ -1162,7 +1209,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 { @@ -1186,7 +1234,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; } @@ -1201,7 +1249,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); @@ -1213,8 +1261,9 @@ 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(); + mKeyguardScreenCallback.pokeWakelock(BACKUP_LOCK_TIMEOUT); } // Allows the Face Unlock service to poke the wake lock to keep the lockscreen alive diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java index de8d41a2808b..af86ae954794 100644 --- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java @@ -349,8 +349,9 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { } // Already prepared (isPrepared will be reset to false later) - if (st.isPrepared) + if (st.isPrepared) { return true; + } if ((mPreparedPanel != null) && (mPreparedPanel != st)) { // Another Panel is prepared and possibly open, so close it @@ -800,14 +801,23 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { closePanel(st, true); } else if (st.isPrepared) { + boolean show = true; + if (st.refreshMenuContent) { + // Something may have invalidated the menu since we prepared it. + // Re-prepare it to refresh. + st.isPrepared = false; + show = preparePanel(st, event); + } - // Write 'menu opened' to event log - EventLog.writeEvent(50001, 0); + if (show) { + // Write 'menu opened' to event log + EventLog.writeEvent(50001, 0); - // Show menu - openPanel(st, event); + // Show menu + openPanel(st, event); - playSoundEffect = true; + playSoundEffect = true; + } } } diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java index 3eb04cb304a1..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; diff --git a/services/java/com/android/server/AppWidgetService.java b/services/java/com/android/server/AppWidgetService.java index dd649e7e6061..eb75ebc1d1fb 100644 --- a/services/java/com/android/server/AppWidgetService.java +++ b/services/java/com/android/server/AppWidgetService.java @@ -16,24 +16,6 @@ package com.android.server; -import java.io.File; -import java.io.FileDescriptor; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Locale; - -import org.apache.commons.logging.impl.SimpleLog; -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; -import org.xmlpull.v1.XmlSerializer; - import android.app.AlarmManager; import android.app.PendingIntent; import android.appwidget.AppWidgetManager; @@ -42,9 +24,9 @@ import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; -import android.content.Intent.FilterComparison; import android.content.IntentFilter; import android.content.ServiceConnection; +import android.content.Intent.FilterComparison; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; @@ -58,7 +40,6 @@ import android.net.Uri; import android.os.Binder; import android.os.Bundle; import android.os.IBinder; -import android.os.Process; import android.os.RemoteException; import android.os.SystemClock; import android.util.AttributeSet; @@ -68,20 +49,37 @@ import android.util.Slog; import android.util.TypedValue; import android.util.Xml; import android.widget.RemoteViews; -import android.widget.RemoteViewsService; import com.android.internal.appwidget.IAppWidgetHost; import com.android.internal.appwidget.IAppWidgetService; +import com.android.internal.os.AtomicFile; import com.android.internal.util.FastXmlSerializer; import com.android.internal.widget.IRemoteViewsAdapterConnection; import com.android.internal.widget.IRemoteViewsFactory; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; +import org.xmlpull.v1.XmlSerializer; + +import java.io.File; +import java.io.FileDescriptor; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; + class AppWidgetService extends IAppWidgetService.Stub { private static final String TAG = "AppWidgetService"; private static final String SETTINGS_FILENAME = "appwidgets.xml"; - private static final String SETTINGS_TMP_FILENAME = SETTINGS_FILENAME + ".tmp"; private static final int MIN_UPDATE_PERIOD = 30 * 60 * 1000; // 30 minutes /* @@ -1159,70 +1157,46 @@ class AppWidgetService extends IAppWidgetService.Stub // only call from initialization -- it assumes that the data structures are all empty void loadStateLocked() { - File temp = savedStateTempFile(); - File real = savedStateRealFile(); - - // prefer the real file. If it doesn't exist, use the temp one, and then copy it to the - // real one. if there is both a real file and a temp one, assume that the temp one isn't - // fully written and delete it. - if (real.exists()) { - readStateFromFileLocked(real); - if (temp.exists()) { - //noinspection ResultOfMethodCallIgnored - temp.delete(); + AtomicFile file = savedStateFile(); + try { + FileInputStream stream = file.openRead(); + readStateFromFileLocked(stream); + + if (stream != null) { + try { + stream.close(); + } catch (IOException e) { + Slog.w(TAG, "Failed to close state FileInputStream " + e); + } } - } else if (temp.exists()) { - readStateFromFileLocked(temp); - //noinspection ResultOfMethodCallIgnored - temp.renameTo(real); + } catch (FileNotFoundException e) { + Slog.w(TAG, "Failed to read state: " + e); } } - + void saveStateLocked() { - File temp = savedStateTempFile(); - File real = savedStateRealFile(); - - if (!real.exists()) { - // If the real one doesn't exist, it's either because this is the first time - // or because something went wrong while copying them. In this case, we can't - // trust anything that's in temp. In order to have the loadState code not - // use the temporary one until it's fully written, create an empty file - // for real, which will we'll shortly delete. - try { - //noinspection ResultOfMethodCallIgnored - real.createNewFile(); - } catch (IOException e) { - // Ignore + AtomicFile file = savedStateFile(); + FileOutputStream stream; + try { + stream = file.startWrite(); + if (writeStateToFileLocked(stream)) { + file.finishWrite(stream); + } else { + file.failWrite(stream); + Slog.w(TAG, "Failed to save state, restoring backup."); } + } catch (IOException e) { + Slog.w(TAG, "Failed open state file for write: " + e); } - - if (temp.exists()) { - //noinspection ResultOfMethodCallIgnored - temp.delete(); - } - - if (!writeStateToFileLocked(temp)) { - Slog.w(TAG, "Failed to persist new settings"); - return; - } - - //noinspection ResultOfMethodCallIgnored - real.delete(); - //noinspection ResultOfMethodCallIgnored - temp.renameTo(real); } - boolean writeStateToFileLocked(File file) { - FileOutputStream stream = null; + boolean writeStateToFileLocked(FileOutputStream stream) { int N; try { - stream = new FileOutputStream(file, false); XmlSerializer out = new FastXmlSerializer(); out.setOutput(stream, "utf-8"); out.startDocument(null, true); - - out.startTag(null, "gs"); int providerIndex = 0; @@ -1264,31 +1238,17 @@ class AppWidgetService extends IAppWidgetService.Stub out.endTag(null, "gs"); out.endDocument(); - stream.close(); return true; } catch (IOException e) { - try { - if (stream != null) { - stream.close(); - } - } catch (IOException ex) { - // Ignore - } - if (file.exists()) { - //noinspection ResultOfMethodCallIgnored - file.delete(); - } + Slog.w(TAG, "Failed to write state: " + e); return false; } } - void readStateFromFileLocked(File file) { - FileInputStream stream = null; - + void readStateFromFileLocked(FileInputStream stream) { boolean success = false; try { - stream = new FileInputStream(file); XmlPullParser parser = Xml.newPullParser(); parser.setInput(stream, null); @@ -1390,22 +1350,15 @@ class AppWidgetService extends IAppWidgetService.Stub } while (type != XmlPullParser.END_DOCUMENT); success = true; } catch (NullPointerException e) { - Slog.w(TAG, "failed parsing " + file, e); + Slog.w(TAG, "failed parsing " + e); } catch (NumberFormatException e) { - Slog.w(TAG, "failed parsing " + file, e); + Slog.w(TAG, "failed parsing " + e); } catch (XmlPullParserException e) { - Slog.w(TAG, "failed parsing " + file, e); + Slog.w(TAG, "failed parsing " + e); } catch (IOException e) { - Slog.w(TAG, "failed parsing " + file, e); + Slog.w(TAG, "failed parsing " + e); } catch (IndexOutOfBoundsException e) { - Slog.w(TAG, "failed parsing " + file, e); - } - try { - if (stream != null) { - stream.close(); - } - } catch (IOException e) { - // Ignore + Slog.w(TAG, "failed parsing " + e); } if (success) { @@ -1416,6 +1369,8 @@ class AppWidgetService extends IAppWidgetService.Stub } } else { // failed reading, clean up + Slog.w(TAG, "Failed to read state, clearing widgets and hosts."); + mAppWidgetIds.clear(); mHosts.clear(); final int N = mInstalledProviders.size(); @@ -1425,14 +1380,8 @@ class AppWidgetService extends IAppWidgetService.Stub } } - File savedStateTempFile() { - return new File("/data/system/" + SETTINGS_TMP_FILENAME); - //return new File(mContext.getFilesDir(), SETTINGS_FILENAME); - } - - File savedStateRealFile() { - return new File("/data/system/" + SETTINGS_FILENAME); - //return new File(mContext.getFilesDir(), SETTINGS_TMP_FILENAME); + AtomicFile savedStateFile() { + return new AtomicFile(new File("/data/system/" + SETTINGS_FILENAME)); } BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java index 1941c6aa9342..994201b43705 100644 --- a/services/java/com/android/server/PowerManagerService.java +++ b/services/java/com/android/server/PowerManagerService.java @@ -1698,11 +1698,6 @@ public class PowerManagerService extends IPowerManager.Stub // make sure button and key backlights are off too mButtonLight.turnOff(); mKeyboardLight.turnOff(); - // clear current value so we will update based on the new conditions - // when the sensor is reenabled. - mLightSensorValue = -1; - // reset our highest light sensor value when the screen turns off - mHighestLightSensorValue = -1; } } } @@ -2472,6 +2467,7 @@ public class PowerManagerService extends IPowerManager.Stub synchronized (mLocks) { mIsDocked = (state != Intent.EXTRA_DOCK_STATE_UNDOCKED); if (mIsDocked) { + // allow brightness to decrease when docked mHighestLightSensorValue = -1; } if ((mPowerState & SCREEN_ON_BIT) != 0) { @@ -3047,11 +3043,21 @@ public class PowerManagerService extends IPowerManager.Stub long identity = Binder.clearCallingIdentity(); try { if (enable) { + // reset our highest value when reenabling + mHighestLightSensorValue = -1; + // force recompute of backlight values + if (mLightSensorValue >= 0) { + int value = (int)mLightSensorValue; + mLightSensorValue = -1; + handleLightSensorValue(value); + } mSensorManager.registerListener(mLightListener, mLightSensor, SensorManager.SENSOR_DELAY_NORMAL); } else { mSensorManager.unregisterListener(mLightListener); mHandler.removeCallbacks(mAutoBrightnessTask); + mLightSensorPendingDecrease = false; + mLightSensorPendingIncrease = false; } } finally { Binder.restoreCallingIdentity(identity); @@ -3103,43 +3109,45 @@ public class PowerManagerService extends IPowerManager.Stub } }; + private void handleLightSensorValue(int value) { + long milliseconds = SystemClock.elapsedRealtime(); + if (mLightSensorValue == -1 || + milliseconds < mLastScreenOnTime + mLightSensorWarmupTime) { + // process the value immediately if screen has just turned on + mHandler.removeCallbacks(mAutoBrightnessTask); + mLightSensorPendingDecrease = false; + mLightSensorPendingIncrease = false; + lightSensorChangedLocked(value); + } else { + if ((value > mLightSensorValue && mLightSensorPendingDecrease) || + (value < mLightSensorValue && mLightSensorPendingIncrease) || + (value == mLightSensorValue) || + (!mLightSensorPendingDecrease && !mLightSensorPendingIncrease)) { + // delay processing to debounce the sensor + mHandler.removeCallbacks(mAutoBrightnessTask); + mLightSensorPendingDecrease = (value < mLightSensorValue); + mLightSensorPendingIncrease = (value > mLightSensorValue); + if (mLightSensorPendingDecrease || mLightSensorPendingIncrease) { + mLightSensorPendingValue = value; + mHandler.postDelayed(mAutoBrightnessTask, LIGHT_SENSOR_DELAY); + } + } else { + mLightSensorPendingValue = value; + } + } + } + SensorEventListener mLightListener = new SensorEventListener() { public void onSensorChanged(SensorEvent event) { + if (mDebugLightSensor) { + Slog.d(TAG, "onSensorChanged: light value: " + event.values[0]); + } synchronized (mLocks) { // ignore light sensor while screen is turning off if (isScreenTurningOffLocked()) { return; } - - int value = (int)event.values[0]; - long milliseconds = SystemClock.elapsedRealtime(); - if (mDebugLightSensor) { - Slog.d(TAG, "onSensorChanged: light value: " + value); - } - if (mLightSensorValue == -1 || - milliseconds < mLastScreenOnTime + mLightSensorWarmupTime) { - // process the value immediately if screen has just turned on - mHandler.removeCallbacks(mAutoBrightnessTask); - mLightSensorPendingDecrease = false; - mLightSensorPendingIncrease = false; - lightSensorChangedLocked(value); - } else { - if ((value > mLightSensorValue && mLightSensorPendingDecrease) || - (value < mLightSensorValue && mLightSensorPendingIncrease) || - (value == mLightSensorValue) || - (!mLightSensorPendingDecrease && !mLightSensorPendingIncrease)) { - // delay processing to debounce the sensor - mHandler.removeCallbacks(mAutoBrightnessTask); - mLightSensorPendingDecrease = (value < mLightSensorValue); - mLightSensorPendingIncrease = (value > mLightSensorValue); - if (mLightSensorPendingDecrease || mLightSensorPendingIncrease) { - mLightSensorPendingValue = value; - mHandler.postDelayed(mAutoBrightnessTask, LIGHT_SENSOR_DELAY); - } - } else { - mLightSensorPendingValue = value; - } - } + handleLightSensorValue((int)event.values[0]); } } diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java index 660681bbdfd2..5bfe6f8bbc2f 100644 --- a/services/java/com/android/server/WifiService.java +++ b/services/java/com/android/server/WifiService.java @@ -1402,7 +1402,7 @@ public class WifiService extends IWifiManager.Stub { long ident = Binder.clearCallingIdentity(); try { if (hadLock) { - noteAcquireWifiLock(wifiLock); + noteReleaseWifiLock(wifiLock); switch(wifiLock.mMode) { case WifiManager.WIFI_MODE_FULL: ++mFullLocksReleased; 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/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java index b9d3d76bbd11..1aed7fe0a1d8 100644 --- a/services/java/com/android/server/am/ActivityStack.java +++ b/services/java/com/android/server/am/ActivityStack.java @@ -2067,7 +2067,7 @@ final class ActivityStack { * task starting at a specified index. */ private final void performClearTaskAtIndexLocked(int taskId, int i) { - while (i < (mHistory.size()-1)) { + while (i < mHistory.size()) { ActivityRecord r = mHistory.get(i); if (r.task.taskId != taskId) { // Whoops hit the end. 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/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java index 0a9ef3d6711f..68f0e66dfdac 100644 --- a/services/java/com/android/server/wm/WindowManagerService.java +++ b/services/java/com/android/server/wm/WindowManagerService.java @@ -167,6 +167,7 @@ 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; @@ -4728,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; } @@ -4745,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; } @@ -4767,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; } @@ -4780,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; } @@ -4800,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); @@ -4821,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); @@ -4852,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; } @@ -4873,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(); 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); |