diff options
15 files changed, 409 insertions, 163 deletions
diff --git a/api/current.txt b/api/current.txt index d113e90..019ea3c 100644 --- a/api/current.txt +++ b/api/current.txt @@ -2075,7 +2075,8 @@ package android.accounts { method public android.accounts.Account[] getAccountsByType(java.lang.String); method public android.accounts.AccountManagerFuture<android.accounts.Account[]> getAccountsByTypeAndFeatures(java.lang.String, java.lang.String[], android.accounts.AccountManagerCallback<android.accounts.Account[]>, android.os.Handler); method public android.accounts.AccountManagerFuture<android.os.Bundle> getAuthToken(android.accounts.Account, java.lang.String, android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler); - method public android.accounts.AccountManagerFuture<android.os.Bundle> getAuthToken(android.accounts.Account, java.lang.String, boolean, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler); + method public deprecated android.accounts.AccountManagerFuture<android.os.Bundle> getAuthToken(android.accounts.Account, java.lang.String, boolean, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler); + method public android.accounts.AccountManagerFuture<android.os.Bundle> getAuthToken(android.accounts.Account, java.lang.String, android.os.Bundle, boolean, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler); method public android.accounts.AccountManagerFuture<android.os.Bundle> getAuthTokenByFeatures(java.lang.String, java.lang.String, java.lang.String[], android.app.Activity, android.os.Bundle, android.os.Bundle, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler); method public android.accounts.AuthenticatorDescription[] getAuthenticatorTypes(); method public java.lang.String getPassword(android.accounts.Account); @@ -2104,6 +2105,7 @@ package android.accounts { field public static final java.lang.String KEY_ACCOUNT_MANAGER_RESPONSE = "accountManagerResponse"; field public static final java.lang.String KEY_ACCOUNT_NAME = "authAccount"; field public static final java.lang.String KEY_ACCOUNT_TYPE = "accountType"; + field public static final java.lang.String KEY_ANDROID_PACKAGE_NAME = "androidPackageName"; field public static final java.lang.String KEY_AUTHENTICATOR_TYPES = "authenticator_types"; field public static final java.lang.String KEY_AUTHTOKEN = "authtoken"; field public static final java.lang.String KEY_AUTH_FAILED_MESSAGE = "authFailedMessage"; @@ -10326,6 +10328,7 @@ package android.media { method public void playSoundEffect(int); method public void playSoundEffect(int, float); method public void registerMediaButtonEventReceiver(android.content.ComponentName); + method public void registerRemoteControlClient(android.media.RemoteControlClient); method public int requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, int, int); method public deprecated void setBluetoothA2dpOn(boolean); method public void setBluetoothScoOn(boolean); @@ -10345,6 +10348,7 @@ package android.media { method public void stopBluetoothSco(); method public void unloadSoundEffects(); method public void unregisterMediaButtonEventReceiver(android.content.ComponentName); + method public void unregisterRemoteControlClient(android.media.RemoteControlClient); field public static final java.lang.String ACTION_AUDIO_BECOMING_NOISY = "android.media.AUDIO_BECOMING_NOISY"; field public static final deprecated java.lang.String ACTION_SCO_AUDIO_STATE_CHANGED = "android.media.SCO_AUDIO_STATE_CHANGED"; field public static final java.lang.String ACTION_SCO_AUDIO_STATE_UPDATED = "android.media.ACTION_SCO_AUDIO_STATE_UPDATED"; @@ -10885,6 +10889,40 @@ package android.media { field public static final int SEEK_FORWARD_AVAILABLE = 3; // 0x3 } + public class RemoteControlClient { + ctor public RemoteControlClient(android.content.ComponentName); + ctor public RemoteControlClient(android.content.ComponentName, android.os.Looper); + method public android.media.RemoteControlClient.MetadataEditor editMetadata(boolean); + method public void setPlaybackState(int); + method public void setTransportControlFlags(int); + field public static final int FLAG_KEY_MEDIA_FAST_FORWARD = 64; // 0x40 + field public static final int FLAG_KEY_MEDIA_NEXT = 128; // 0x80 + field public static final int FLAG_KEY_MEDIA_PAUSE = 16; // 0x10 + field public static final int FLAG_KEY_MEDIA_PLAY = 4; // 0x4 + field public static final int FLAG_KEY_MEDIA_PLAY_PAUSE = 8; // 0x8 + field public static final int FLAG_KEY_MEDIA_PREVIOUS = 1; // 0x1 + field public static final int FLAG_KEY_MEDIA_REWIND = 2; // 0x2 + field public static final int FLAG_KEY_MEDIA_STOP = 32; // 0x20 + field public static final int PLAYSTATE_BUFFERING = 8; // 0x8 + field public static final int PLAYSTATE_ERROR = 9; // 0x9 + field public static final int PLAYSTATE_FAST_FORWARDING = 4; // 0x4 + field public static final int PLAYSTATE_PAUSED = 2; // 0x2 + field public static final int PLAYSTATE_PLAYING = 3; // 0x3 + field public static final int PLAYSTATE_REWINDING = 5; // 0x5 + field public static final int PLAYSTATE_SKIPPING_BACKWARDS = 7; // 0x7 + field public static final int PLAYSTATE_SKIPPING_FORWARDS = 6; // 0x6 + field public static final int PLAYSTATE_STOPPED = 1; // 0x1 + } + + public class RemoteControlClient.MetadataEditor { + method public synchronized void apply(); + method public synchronized void clear(); + method public synchronized android.media.RemoteControlClient.MetadataEditor putBitmap(int, android.graphics.Bitmap) throws java.lang.IllegalArgumentException; + method public synchronized android.media.RemoteControlClient.MetadataEditor putLong(int, long) throws java.lang.IllegalArgumentException; + method public synchronized android.media.RemoteControlClient.MetadataEditor putString(int, java.lang.String) throws java.lang.IllegalArgumentException; + field public static final int BITMAP_KEY_ARTWORK = 100; // 0x64 + } + public class Ringtone { method public int getStreamType(); method public java.lang.String getTitle(android.content.Context); diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java index 2156425..029d107 100644 --- a/core/java/android/accounts/AccountManager.java +++ b/core/java/android/accounts/AccountManager.java @@ -197,6 +197,16 @@ public class AccountManager { public static final String KEY_CALLER_PID = "callerPid"; /** + * The Android package of the caller will be set in the options bundle by the + * {@link AccountManager} and will be passed to the AccountManagerService and + * to the AccountAuthenticators. The uid of the caller will be known by the + * AccountManagerService as well as the AccountAuthenticators so they will be able to + * verify that the package is consistent with the uid (a uid might be shared by many + * packages). + */ + public static final String KEY_ANDROID_PACKAGE_NAME = "androidPackageName"; + + /** * Boolean, if set and 'customTokens' the authenticator is responsible for * notifications. * @hide @@ -880,7 +890,10 @@ public class AccountManager { * If the account is no longer present on the device, the return value is * authenticator-dependent. The caller should verify the validity of the * account before requesting an auth token. + * @deprecated use {@link #getAuthToken(Account, String, android.os.Bundle, + * boolean, AccountManagerCallback, android.os.Handler)} instead */ + @Deprecated public AccountManagerFuture<Bundle> getAuthToken( final Account account, final String authTokenType, final boolean notifyAuthFailure, AccountManagerCallback<Bundle> callback, Handler handler) { @@ -895,6 +908,90 @@ public class AccountManager { } /** + * Gets an auth token of the specified type for a particular account, + * optionally raising a notification if the user must enter credentials. + * This method is intended for background tasks and services where the + * user should not be immediately interrupted with a password prompt. + * + * <p>If a previously generated auth token is cached for this account and + * type, then it is returned. Otherwise, if a saved password is + * available, it is sent to the server to generate a new auth token. + * Otherwise, an {@link Intent} is returned which, when started, will + * prompt the user for a password. If the notifyAuthFailure parameter is + * set, a status bar notification is also created with the same Intent, + * alerting the user that they need to enter a password at some point. + * + * <p>In that case, you may need to wait until the user responds, which + * could take hours or days or forever. When the user does respond and + * supply a new password, the account manager will broadcast the + * {@link #LOGIN_ACCOUNTS_CHANGED_ACTION} Intent, which applications can + * use to try again. + * + * <p>If notifyAuthFailure is not set, it is the application's + * responsibility to launch the returned Intent at some point. + * Either way, the result from this call will not wait for user action. + * + * <p>Some authenticators have auth token <em>types</em>, whose value + * is authenticator-dependent. Some services use different token types to + * access different functionality -- for example, Google uses different auth + * tokens to access Gmail and Google Calendar for the same account. + * + * <p>This method may be called from any thread, but the returned + * {@link AccountManagerFuture} must not be used on the main thread. + * + * <p>This method requires the caller to hold the permission + * {@link android.Manifest.permission#USE_CREDENTIALS}. + * + * @param account The account to fetch an auth token for + * @param authTokenType The auth token type, an authenticator-dependent + * string token, must not be null + * @param options Authenticator-specific options for the request, + * may be null or empty + * @param notifyAuthFailure True to add a notification to prompt the + * user for a password if necessary, false to leave that to the caller + * @param callback Callback to invoke when the request completes, + * null for no callback + * @param handler {@link Handler} identifying the callback thread, + * null for the main thread + * @return An {@link AccountManagerFuture} which resolves to a Bundle with + * at least the following fields on success: + * <ul> + * <li> {@link #KEY_ACCOUNT_NAME} - the name of the account you supplied + * <li> {@link #KEY_ACCOUNT_TYPE} - the type of the account + * <li> {@link #KEY_AUTHTOKEN} - the auth token you wanted + * </ul> + * + * (Other authenticator-specific values may be returned.) If the user + * must enter credentials, the returned Bundle contains only + * {@link #KEY_INTENT} with the {@link Intent} needed to launch a prompt. + * + * If an error occurred, {@link AccountManagerFuture#getResult()} throws: + * <ul> + * <li> {@link AuthenticatorException} if the authenticator failed to respond + * <li> {@link OperationCanceledException} if the operation is canceled for + * any reason, incluidng the user canceling a credential request + * <li> {@link IOException} if the authenticator experienced an I/O problem + * creating a new auth token, usually because of network trouble + * </ul> + * If the account is no longer present on the device, the return value is + * authenticator-dependent. The caller should verify the validity of the + * account before requesting an auth token. + */ + public AccountManagerFuture<Bundle> getAuthToken( + final Account account, final String authTokenType, + final Bundle options, final boolean notifyAuthFailure, + AccountManagerCallback<Bundle> callback, Handler handler) { + if (account == null) throw new IllegalArgumentException("account is null"); + if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null"); + return new AmsTask(null, handler, callback) { + public void doWork() throws RemoteException { + mService.getAuthToken(mResponse, account, authTokenType, + notifyAuthFailure, false /* expectActivityLaunch */, options); + } + }.start(); + } + + /** * Asks the user to add an account of a specified type. The authenticator * for this account type processes this request with the appropriate user * interface. If the user does elect to create a new account, the account diff --git a/core/java/android/provider/SyncStateContract.java b/core/java/android/provider/SyncStateContract.java index e8177ca..f1189e4 100644 --- a/core/java/android/provider/SyncStateContract.java +++ b/core/java/android/provider/SyncStateContract.java @@ -74,6 +74,12 @@ public class SyncStateContract { Account account) throws RemoteException { Cursor c = provider.query(uri, DATA_PROJECTION, SELECT_BY_ACCOUNT, new String[]{account.name, account.type}, null); + + // Unable to query the provider + if (c == null) { + throw new RemoteException(); + } + try { if (c.moveToNext()) { return c.getBlob(c.getColumnIndexOrThrow(Columns.DATA)); @@ -123,6 +129,11 @@ public class SyncStateContract { Account account) throws RemoteException { Cursor c = provider.query(uri, DATA_PROJECTION, SELECT_BY_ACCOUNT, new String[]{account.name, account.type}, null); + + if (c == null) { + throw new RemoteException(); + } + try { if (c.moveToNext()) { long rowId = c.getLong(1); diff --git a/data/videos/AndroidInSpace.240p.mp4 b/data/videos/AndroidInSpace.240p.mp4 Binary files differnew file mode 100644 index 0000000..e1445e4 --- /dev/null +++ b/data/videos/AndroidInSpace.240p.mp4 diff --git a/data/videos/Sunset.240p.mp4 b/data/videos/Sunset.240p.mp4 Binary files differnew file mode 100644 index 0000000..f5c533f --- /dev/null +++ b/data/videos/Sunset.240p.mp4 diff --git a/data/videos/VideoPackage1.mk b/data/videos/VideoPackage1.mk new file mode 100644 index 0000000..daff26f --- /dev/null +++ b/data/videos/VideoPackage1.mk @@ -0,0 +1,23 @@ +# +# Copyright (C) 2011 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +LOCAL_PATH := frameworks/base/data/videos +TARGET_PATH := system/media/video + +PRODUCT_COPY_FILES += \ + $(LOCAL_PATH)/AndroidInSpace.240p.mp4:$(TARGET_PATH)/AndroidInSpace.240p.mp4 \ + $(LOCAL_PATH)/Sunset.240p.mp4:$(TARGET_PATH)/Sunset.240p.mp4 + diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java index 25c4200..cd8bb1d 100644 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -1717,12 +1717,11 @@ public class AudioManager { /** - * @hide - * CANDIDATE FOR SDK * Registers the remote control client for providing information to display on the remote * controls. - * @param rcClient the remote control client associated responsible - * for providing the information to display on the remote control. + * @param rcClient The remote control client from which remote controls will receive + * information to display. + * @see RemoteControlClient */ public void registerRemoteControlClient(RemoteControlClient rcClient) { if ((rcClient == null) || (rcClient.getRcEventReceiver() == null)) { @@ -1741,11 +1740,9 @@ public class AudioManager { } /** - * @hide - * CANDIDATE FOR SDK * Unregisters the remote control client that was providing information to display on the - * remotes. - * @param rcClient the remote control client to unregister + * remote controls. + * @param rcClient The remote control client to unregister. * @see #registerRemoteControlClient(RemoteControlClient) */ public void unregisterRemoteControlClient(RemoteControlClient rcClient) { diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java index 9d9b6ea..f5e1416 100644 --- a/media/java/android/media/AudioService.java +++ b/media/java/android/media/AudioService.java @@ -343,9 +343,8 @@ public class AudioService extends IAudioService.Stub { readPersistedSettings(); mSettingsObserver = new SettingsObserver(); createStreamStates(); - // Call setMode() to initialize mSetModeDeathHandlers - mMode = AudioSystem.MODE_INVALID; - setMode(AudioSystem.MODE_NORMAL, null); + + mMode = AudioSystem.MODE_NORMAL; mMediaServerOk = true; // Call setRingerModeInt() to apply correct mute @@ -768,37 +767,27 @@ public class AudioService extends IAudioService.Stub { private int mPid; private int mMode = AudioSystem.MODE_NORMAL; // Current mode set by this client - SetModeDeathHandler(IBinder cb) { + SetModeDeathHandler(IBinder cb, int pid) { mCb = cb; - mPid = Binder.getCallingPid(); + mPid = pid; } public void binderDied() { + IBinder newModeOwner = null; synchronized(mSetModeDeathHandlers) { Log.w(TAG, "setMode() client died"); int index = mSetModeDeathHandlers.indexOf(this); if (index < 0) { Log.w(TAG, "unregistered setMode() client died"); } else { - mSetModeDeathHandlers.remove(this); - // If dead client was a the top of client list, - // apply next mode in the stack - if (index == 0) { - // mSetModeDeathHandlers is never empty as the initial entry - // created when AudioService starts is never removed - SetModeDeathHandler hdlr = mSetModeDeathHandlers.get(0); - int mode = hdlr.getMode(); - if (AudioService.this.mMode != mode) { - if (AudioSystem.setPhoneState(mode) == AudioSystem.AUDIO_STATUS_OK) { - AudioService.this.mMode = mode; - if (mode != AudioSystem.MODE_NORMAL) { - disconnectBluetoothSco(mCb); - } - } - } - } + newModeOwner = setModeInt(AudioSystem.MODE_NORMAL, mCb, mPid); } } + // when entering RINGTONE, IN_CALL or IN_COMMUNICATION mode, clear all + // SCO connections not started by the application changing the mode + if (newModeOwner != null) { + disconnectBluetoothSco(newModeOwner); + } } public int getPid() { @@ -828,60 +817,97 @@ public class AudioService extends IAudioService.Stub { return; } - synchronized (mSettingsLock) { + IBinder newModeOwner = null; + synchronized(mSetModeDeathHandlers) { if (mode == AudioSystem.MODE_CURRENT) { mode = mMode; } - if (mode != mMode) { + newModeOwner = setModeInt(mode, cb, Binder.getCallingPid()); + } + // when entering RINGTONE, IN_CALL or IN_COMMUNICATION mode, clear all + // SCO connections not started by the application changing the mode + if (newModeOwner != null) { + disconnectBluetoothSco(newModeOwner); + } + } - // automatically handle audio focus for mode changes - handleFocusForCalls(mMode, mode, cb); + // must be called synchronized on mSetModeDeathHandlers + // setModeInt() returns a non null IBInder if the audio mode was successfully set to + // any mode other than NORMAL. + IBinder setModeInt(int mode, IBinder cb, int pid) { + IBinder newModeOwner = null; + if (cb == null) { + Log.e(TAG, "setModeInt() called with null binder"); + return newModeOwner; + } - if (AudioSystem.setPhoneState(mode) == AudioSystem.AUDIO_STATUS_OK) { - mMode = mode; + SetModeDeathHandler hdlr = null; + Iterator iter = mSetModeDeathHandlers.iterator(); + while (iter.hasNext()) { + SetModeDeathHandler h = (SetModeDeathHandler)iter.next(); + if (h.getPid() == pid) { + hdlr = h; + // Remove from client list so that it is re-inserted at top of list + iter.remove(); + hdlr.getBinder().unlinkToDeath(hdlr, 0); + break; + } + } + int status = AudioSystem.AUDIO_STATUS_OK; + do { + if (mode == AudioSystem.MODE_NORMAL) { + // get new mode from client at top the list if any + if (!mSetModeDeathHandlers.isEmpty()) { + hdlr = mSetModeDeathHandlers.get(0); + cb = hdlr.getBinder(); + mode = hdlr.getMode(); + } + } else { + if (hdlr == null) { + hdlr = new SetModeDeathHandler(cb, pid); + } + // Register for client death notification + try { + cb.linkToDeath(hdlr, 0); + } catch (RemoteException e) { + // Client has died! + Log.w(TAG, "setMode() could not link to "+cb+" binder death"); + } - synchronized(mSetModeDeathHandlers) { - SetModeDeathHandler hdlr = null; - Iterator iter = mSetModeDeathHandlers.iterator(); - while (iter.hasNext()) { - SetModeDeathHandler h = (SetModeDeathHandler)iter.next(); - if (h.getBinder() == cb) { - hdlr = h; - // Remove from client list so that it is re-inserted at top of list - iter.remove(); - break; - } - } - if (hdlr == null) { - hdlr = new SetModeDeathHandler(cb); - // cb is null when setMode() is called by AudioService constructor - if (cb != null) { - // Register for client death notification - try { - cb.linkToDeath(hdlr, 0); - } catch (RemoteException e) { - // Client has died! - Log.w(TAG, "setMode() could not link to "+cb+" binder death"); - } - } - } - // Last client to call setMode() is always at top of client list - // as required by SetModeDeathHandler.binderDied() - mSetModeDeathHandlers.add(0, hdlr); - hdlr.setMode(mode); - } + // Last client to call setMode() is always at top of client list + // as required by SetModeDeathHandler.binderDied() + mSetModeDeathHandlers.add(0, hdlr); + hdlr.setMode(mode); + } - // when entering RINGTONE, IN_CALL or IN_COMMUNICATION mode, clear all - // SCO connections not started by the application changing the mode - if (mode != AudioSystem.MODE_NORMAL) { - disconnectBluetoothSco(cb); + if (mode != mMode) { + status = AudioSystem.setPhoneState(mode); + if (status == AudioSystem.AUDIO_STATUS_OK) { + // automatically handle audio focus for mode changes + handleFocusForCalls(mMode, mode, cb); + mMode = mode; + } else { + if (hdlr != null) { + mSetModeDeathHandlers.remove(hdlr); + cb.unlinkToDeath(hdlr, 0); } + // force reading new top of mSetModeDeathHandlers stack + mode = AudioSystem.MODE_NORMAL; } + } else { + status = AudioSystem.AUDIO_STATUS_OK; + } + } while (status != AudioSystem.AUDIO_STATUS_OK && !mSetModeDeathHandlers.isEmpty()); + + if (status == AudioSystem.AUDIO_STATUS_OK) { + if (mode != AudioSystem.MODE_NORMAL) { + newModeOwner = cb; } int streamType = getActiveStreamType(AudioManager.USE_DEFAULT_STREAM_TYPE); int index = mStreamStates[STREAM_VOLUME_ALIAS[streamType]].mIndex; setStreamVolumeInt(STREAM_VOLUME_ALIAS[streamType], index, true, false); } + return newModeOwner; } /** pre-condition: oldMode != newMode */ @@ -1345,28 +1371,30 @@ public class AudioService extends IAudioService.Stub { broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_CONNECTING); // Accept SCO audio activation only in NORMAL audio mode or if the mode is // currently controlled by the same client process. - if ((AudioService.this.mMode == AudioSystem.MODE_NORMAL || - mSetModeDeathHandlers.get(0).getPid() == mCreatorPid) && - (mScoAudioState == SCO_STATE_INACTIVE || - mScoAudioState == SCO_STATE_DEACTIVATE_REQ)) { - if (mScoAudioState == SCO_STATE_INACTIVE) { - if (mBluetoothHeadset != null && mBluetoothHeadsetDevice != null) { - if (mBluetoothHeadset.startScoUsingVirtualVoiceCall( - mBluetoothHeadsetDevice)) { - mScoAudioState = SCO_STATE_ACTIVE_INTERNAL; - } else { - broadcastScoConnectionState( - AudioManager.SCO_AUDIO_STATE_DISCONNECTED); + synchronized(mSetModeDeathHandlers) { + if ((mSetModeDeathHandlers.isEmpty() || + mSetModeDeathHandlers.get(0).getPid() == mCreatorPid) && + (mScoAudioState == SCO_STATE_INACTIVE || + mScoAudioState == SCO_STATE_DEACTIVATE_REQ)) { + if (mScoAudioState == SCO_STATE_INACTIVE) { + if (mBluetoothHeadset != null && mBluetoothHeadsetDevice != null) { + if (mBluetoothHeadset.startScoUsingVirtualVoiceCall( + mBluetoothHeadsetDevice)) { + mScoAudioState = SCO_STATE_ACTIVE_INTERNAL; + } else { + broadcastScoConnectionState( + AudioManager.SCO_AUDIO_STATE_DISCONNECTED); + } + } else if (getBluetoothHeadset()) { + mScoAudioState = SCO_STATE_ACTIVATE_REQ; } - } else if (getBluetoothHeadset()) { - mScoAudioState = SCO_STATE_ACTIVATE_REQ; + } else { + mScoAudioState = SCO_STATE_ACTIVE_INTERNAL; + broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_CONNECTED); } } else { - mScoAudioState = SCO_STATE_ACTIVE_INTERNAL; - broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_CONNECTED); + broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED); } - } else { - broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED); } } else if (state == BluetoothHeadset.STATE_AUDIO_DISCONNECTED && (mScoAudioState == SCO_STATE_ACTIVE_INTERNAL || diff --git a/media/java/android/media/RemoteControlClient.java b/media/java/android/media/RemoteControlClient.java index d7b85e4..daa25e0 100644 --- a/media/java/android/media/RemoteControlClient.java +++ b/media/java/android/media/RemoteControlClient.java @@ -17,7 +17,6 @@ package android.media; import android.content.ComponentName; -import android.content.SharedPreferences.Editor; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Paint; @@ -31,15 +30,14 @@ import android.os.RemoteException; import android.util.Log; import java.lang.IllegalArgumentException; -import java.util.HashMap; /** - * @hide - * CANDIDATE FOR SDK * RemoteControlClient enables exposing information meant to be consumed by remote controls - * capable of displaying metadata, album art and media transport control buttons. - * A remote control client object is associated with a media button event receiver - * when registered through + * capable of displaying metadata, artwork and media transport control buttons. + * A remote control client object is associated with a media button event receiver. This + * event receiver must have been previously registered with + * {@link AudioManager#registerMediaButtonEventReceiver(ComponentName)} before the + * RemoteControlClient can be registered through * {@link AudioManager#registerRemoteControlClient(RemoteControlClient)}. */ public class RemoteControlClient @@ -110,7 +108,8 @@ public class RemoteControlClient public final static int PLAYSTATE_ERROR = 9; /** * @hide - * The value of a playback state when none has been declared + * The value of a playback state when none has been declared. + * Intentionally hidden as an application shouldn't set such a playback state value. */ public final static int PLAYSTATE_NONE = 0; @@ -122,7 +121,7 @@ public class RemoteControlClient */ public final static int FLAG_KEY_MEDIA_PREVIOUS = 1 << 0; /** - * Flag indicating a RemoteControlClient makes use of the "rewing" media key. + * Flag indicating a RemoteControlClient makes use of the "rewind" media key. * * @see #setTransportControlFlags(int) * @see android.view.KeyEvent#KEYCODE_MEDIA_REWIND @@ -173,7 +172,9 @@ public class RemoteControlClient /** * @hide - * The flags for when no media keys are declared supported + * The flags for when no media keys are declared supported. + * Intentionally hidden as an application shouldn't set the transport control flags + * to this value. */ public final static int FLAGS_KEY_MEDIA_NONE = 0; @@ -184,29 +185,29 @@ public class RemoteControlClient public final static int FLAG_INFORMATION_REQUEST_METADATA = 1 << 0; /** * @hide - * FIXME doc not valid * Flag used to signal that the transport control buttons supported by the - * RemoteControlClient have changed. + * RemoteControlClient are requested. * This can for instance happen when playback is at the end of a playlist, and the "next" * operation is not supported anymore. */ public final static int FLAG_INFORMATION_REQUEST_KEY_MEDIA = 1 << 1; /** * @hide - * FIXME doc not valid - * Flag used to signal that the playback state of the RemoteControlClient has changed. + * Flag used to signal that the playback state of the RemoteControlClient is requested. */ public final static int FLAG_INFORMATION_REQUEST_PLAYSTATE = 1 << 2; /** * @hide - * FIXME doc not valid - * Flag used to signal that the album art for the RemoteControlClient has changed. + * Flag used to signal that the album art for the RemoteControlClient is requested. */ public final static int FLAG_INFORMATION_REQUEST_ALBUM_ART = 1 << 3; /** * Class constructor. - * @param mediaButtonEventReceiver the receiver for the media button events. + * @param mediaButtonEventReceiver The receiver for the media button events. It needs to have + * been registered with {@link AudioManager#registerMediaButtonEventReceiver(ComponentName)} + * before this new RemoteControlClient can itself be registered with + * {@link AudioManager#registerRemoteControlClient(RemoteControlClient)}. * @see AudioManager#registerMediaButtonEventReceiver(ComponentName) * @see AudioManager#registerRemoteControlClient(RemoteControlClient) */ @@ -227,8 +228,11 @@ public class RemoteControlClient /** * Class constructor for a remote control client whose internal event handling * happens on a user-provided Looper. - * @param mediaButtonEventReceiver the receiver for the media button events. - * @param looper the Looper running the event loop. + * @param mediaButtonEventReceiver The receiver for the media button events. It needs to have + * been registered with {@link AudioManager#registerMediaButtonEventReceiver(ComponentName)} + * before this new RemoteControlClient can itself be registered with + * {@link AudioManager#registerRemoteControlClient(RemoteControlClient)}. + * @param looper The Looper running the event loop. * @see AudioManager#registerMediaButtonEventReceiver(ComponentName) * @see AudioManager#registerRemoteControlClient(RemoteControlClient) */ @@ -257,11 +261,28 @@ public class RemoteControlClient /** * Class used to modify metadata in a {@link RemoteControlClient} object. + * Use {@link RemoteControlClient#editMetadata(boolean)} to create an instance of an editor, + * on which you set the metadata for the RemoteControlClient instance. Once all the information + * has been set, use {@link #apply()} to make it the new metadata that should be displayed + * for the associated client. Once the metadata has been "applied", you cannot reuse this + * instance of the MetadataEditor. */ public class MetadataEditor { + /** + * @hide + */ protected boolean mMetadataChanged; + /** + * @hide + */ protected boolean mArtworkChanged; + /** + * @hide + */ protected Bitmap mEditorArtwork; + /** + * @hide + */ protected Bundle mEditorMetadata; private boolean mApplied = false; @@ -277,13 +298,18 @@ public class RemoteControlClient /** * The metadata key for the content artwork / album art. */ - public final static int METADATA_KEY_ARTWORK = 100; + public final static int BITMAP_KEY_ARTWORK = 100; + /** + * @hide + * TODO(jmtrivi) have lockscreen and music move to the new key name + */ + public final static int METADATA_KEY_ARTWORK = BITMAP_KEY_ARTWORK; /** * Adds textual information to be displayed. * Note that none of the information added after {@link #apply()} has been called, * will be displayed. - * @param key the identifier of a the metadata field to set. Valid values are + * @param key The identifier of a the metadata field to set. Valid values are * {@link android.media.MediaMetadataRetriever#METADATA_KEY_ALBUM}, * {@link android.media.MediaMetadataRetriever#METADATA_KEY_ALBUMARTIST}, * {@link android.media.MediaMetadataRetriever#METADATA_KEY_TITLE}, @@ -294,11 +320,11 @@ public class RemoteControlClient * {@link android.media.MediaMetadataRetriever#METADATA_KEY_DATE}, * {@link android.media.MediaMetadataRetriever#METADATA_KEY_GENRE}, * {@link android.media.MediaMetadataRetriever#METADATA_KEY_TITLE}, - * {@link android.media.MediaMetadataRetriever#METADATA_KEY_WRITER}, - * . - * @param value the text for the given key, or {@code null} to signify there is no valid + * {@link android.media.MediaMetadataRetriever#METADATA_KEY_WRITER}. + * @param value The text for the given key, or {@code null} to signify there is no valid * information for the field. - * @return FIXME description + * @return Returns a reference to the same MetadataEditor object, so you can chain put + * calls together. */ public synchronized MetadataEditor putString(int key, String value) throws IllegalArgumentException { @@ -315,15 +341,18 @@ public class RemoteControlClient } /** - * FIXME javadoc + * Adds numerical information to be displayed. + * Note that none of the information added after {@link #apply()} has been called, + * will be displayed. * @param key the identifier of a the metadata field to set. Valid values are * {@link android.media.MediaMetadataRetriever#METADATA_KEY_CD_TRACK_NUMBER}, * {@link android.media.MediaMetadataRetriever#METADATA_KEY_DISC_NUMBER}, * {@link android.media.MediaMetadataRetriever#METADATA_KEY_DURATION} (with a value * expressed in milliseconds), * {@link android.media.MediaMetadataRetriever#METADATA_KEY_YEAR}. - * @param value FIXME javadoc - * @return FIXME javadoc + * @param value The long value for the given key + * @return Returns a reference to the same MetadataEditor object, so you can chain put + * calls together. * @throws IllegalArgumentException */ public synchronized MetadataEditor putLong(int key, long value) @@ -342,9 +371,11 @@ public class RemoteControlClient /** * Sets the album / artwork picture to be displayed on the remote control. - * @param key FIXME description - * @param bitmap the bitmap for the artwork, or null if there isn't any. - * @return FIXME description + * @param key the identifier of the bitmap to set. The only valid value is + * {@link #BITMAP_KEY_ARTWORK} + * @param bitmap The bitmap for the artwork, or null if there isn't any. + * @return Returns a reference to the same MetadataEditor object, so you can chain put + * calls together. * @throws IllegalArgumentException * @see android.graphics.Bitmap */ @@ -354,7 +385,7 @@ public class RemoteControlClient Log.e(TAG, "Can't edit a previously applied MetadataEditor"); return this; } - if (key != METADATA_KEY_ARTWORK) { + if (key != BITMAP_KEY_ARTWORK) { throw(new IllegalArgumentException("Invalid type 'Bitmap' for key "+ key)); } if ((mArtworkExpectedWidth > 0) && (mArtworkExpectedHeight > 0)) { @@ -369,7 +400,8 @@ public class RemoteControlClient } /** - * FIXME description + * Clears all the metadata that has been set since the MetadataEditor instance was + * created with {@link RemoteControlClient#editMetadata(boolean)}. */ public synchronized void clear() { if (mApplied) { @@ -381,7 +413,10 @@ public class RemoteControlClient } /** - * FIXME description + * Associates all the metadata that has been set since the MetadataEditor instance was + * created with {@link RemoteControlClient#editMetadata(boolean)}, or since + * {@link #clear()} was called, with the RemoteControlClient. Once "applied", + * this MetadataEditor cannot be reused to edit the RemoteControlClient's metadata. */ public synchronized void apply() { if (mApplied) { @@ -408,9 +443,10 @@ public class RemoteControlClient } /** - * FIXME description - * @param startEmpty - * @return + * Creates a {@link MetadataEditor}. + * @param startEmpty Set to false if you want the MetadataEditor to contain the metadata that + * was previously applied to the RemoteControlClient, or true if it is to be created empty. + * @return a new MetadataEditor instance. */ public MetadataEditor editMetadata(boolean startEmpty) { MetadataEditor editor = new MetadataEditor(); @@ -430,7 +466,7 @@ public class RemoteControlClient /** * Sets the current playback state. - * @param state the current playback state, one of the following values: + * @param state The current playback state, one of the following values: * {@link #PLAYSTATE_STOPPED}, * {@link #PLAYSTATE_PAUSED}, * {@link #PLAYSTATE_PLAYING}, @@ -453,7 +489,7 @@ public class RemoteControlClient /** * Sets the flags for the media transport control buttons that this client supports. - * @param a combination of the following flags: + * @param transportControlFlags A combination of the following flags: * {@link #FLAG_KEY_MEDIA_PREVIOUS}, * {@link #FLAG_KEY_MEDIA_REWIND}, * {@link #FLAG_KEY_MEDIA_PLAY}, diff --git a/packages/SystemUI/res/drawable-hdpi/status_bar_close_on.9.png b/packages/SystemUI/res/drawable-hdpi/status_bar_close_on.9.png Binary files differindex 35d0a06..0f0cbf1 100644 --- a/packages/SystemUI/res/drawable-hdpi/status_bar_close_on.9.png +++ b/packages/SystemUI/res/drawable-hdpi/status_bar_close_on.9.png diff --git a/packages/SystemUI/res/drawable-mdpi/status_bar_close_on.9.png b/packages/SystemUI/res/drawable-mdpi/status_bar_close_on.9.png Binary files differindex 79da092..5e8a116 100644 --- a/packages/SystemUI/res/drawable-mdpi/status_bar_close_on.9.png +++ b/packages/SystemUI/res/drawable-mdpi/status_bar_close_on.9.png diff --git a/packages/SystemUI/res/drawable-xhdpi/status_bar_close_on.9.png b/packages/SystemUI/res/drawable-xhdpi/status_bar_close_on.9.png Binary files differnew file mode 100644 index 0000000..efac368 --- /dev/null +++ b/packages/SystemUI/res/drawable-xhdpi/status_bar_close_on.9.png 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 55623f0..ee9aa41 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -1795,30 +1795,34 @@ public class PhoneStatusBar extends StatusBar { pw.println(" [" + i + "] icon=" + ic); } - pw.println("see the logcat for a dump of the views we have created."); - // must happen on ui thread - mHandler.post(new Runnable() { - public void run() { - mStatusBarView.getLocationOnScreen(mAbsPos); - Slog.d(TAG, "mStatusBarView: ----- (" + mAbsPos[0] + "," + mAbsPos[1] - + ") " + mStatusBarView.getWidth() + "x" - + mStatusBarView.getHeight()); - mStatusBarView.debug(); - - mExpandedView.getLocationOnScreen(mAbsPos); - Slog.d(TAG, "mExpandedView: ----- (" + mAbsPos[0] + "," + mAbsPos[1] - + ") " + mExpandedView.getWidth() + "x" - + mExpandedView.getHeight()); - mExpandedView.debug(); - - mTrackingView.getLocationOnScreen(mAbsPos); - Slog.d(TAG, "mTrackingView: ----- (" + mAbsPos[0] + "," + mAbsPos[1] - + ") " + mTrackingView.getWidth() + "x" - + mTrackingView.getHeight()); - mTrackingView.debug(); - } - }); + if (false) { + pw.println("see the logcat for a dump of the views we have created."); + // must happen on ui thread + mHandler.post(new Runnable() { + public void run() { + mStatusBarView.getLocationOnScreen(mAbsPos); + Slog.d(TAG, "mStatusBarView: ----- (" + mAbsPos[0] + "," + mAbsPos[1] + + ") " + mStatusBarView.getWidth() + "x" + + mStatusBarView.getHeight()); + mStatusBarView.debug(); + + mExpandedView.getLocationOnScreen(mAbsPos); + Slog.d(TAG, "mExpandedView: ----- (" + mAbsPos[0] + "," + mAbsPos[1] + + ") " + mExpandedView.getWidth() + "x" + + mExpandedView.getHeight()); + mExpandedView.debug(); + + mTrackingView.getLocationOnScreen(mAbsPos); + Slog.d(TAG, "mTrackingView: ----- (" + mAbsPos[0] + "," + mAbsPos[1] + + ") " + mTrackingView.getWidth() + "x" + + mTrackingView.getHeight()); + mTrackingView.debug(); + } + }); + } } + + mNetworkController.dump(fd, pw, args); } void onBarViewAttached() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java index 3c85814..b50ebcd 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java @@ -296,6 +296,7 @@ public class NetworkController extends BroadcastReceiver { } mServiceState = state; updateTelephonySignalStrength(); + updateDataNetType(); updateDataIcon(); refreshViews(); } @@ -831,7 +832,12 @@ public class NetworkController extends BroadcastReceiver { mHasMobileDataFeature ? mDataSignalIconId : mWifiIconId; mContentDescriptionCombinedSignal = mHasMobileDataFeature ? mContentDescriptionDataType : mContentDescriptionWifi; - mDataTypeIconId = 0; + + if ((isCdma() && isCdmaEri()) || mPhone.isNetworkRoaming()) { + mDataTypeIconId = R.drawable.stat_sys_data_connected_roam; + } else { + mDataTypeIconId = 0; + } } if (DEBUG) { @@ -969,6 +975,7 @@ public class NetworkController extends BroadcastReceiver { } public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + pw.println("Network Controller state:"); pw.println(" - telephony ------"); pw.print(" mHspaDataDistinguishable="); pw.println(mHspaDataDistinguishable); @@ -982,6 +989,10 @@ public class NetworkController extends BroadcastReceiver { pw.println(mDataState); pw.print(" mDataActivity="); pw.println(mDataActivity); + pw.print(" mDataNetType="); + pw.print(mDataNetType); + pw.print("/"); + pw.println(TelephonyManager.getNetworkTypeName(mDataNetType)); pw.print(" mServiceState="); pw.println(mServiceState); pw.print(" mNetworkName="); @@ -989,7 +1000,7 @@ public class NetworkController extends BroadcastReceiver { pw.print(" mNetworkNameDefault="); pw.println(mNetworkNameDefault); pw.print(" mNetworkNameSeparator="); - pw.println(mNetworkNameSeparator); + pw.println(mNetworkNameSeparator.replace("\n","\\n")); pw.print(" mPhoneSignalIconId=0x"); pw.print(Integer.toHexString(mPhoneSignalIconId)); pw.print("/"); @@ -1060,7 +1071,7 @@ public class NetworkController extends BroadcastReceiver { } private String getResourceName(int resId) { - if (resId == 0) { + if (resId != 0) { final Resources res = mContext.getResources(); try { return res.getResourceName(resId); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodsPanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodsPanel.java index 5911378..e406a0c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodsPanel.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodsPanel.java @@ -218,15 +218,16 @@ public class InputMethodsPanel extends LinearLayout implements StatusBarPanel, private View createInputMethodItem( final InputMethodInfo imi, final InputMethodSubtype subtype) { - CharSequence subtypeName = getSubtypeName(imi, subtype); - CharSequence imiName = getIMIName(imi); - Drawable icon = getSubtypeIcon(imi, subtype); - View view = View.inflate(mContext, R.layout.status_bar_input_methods_item, null); - ImageView subtypeIcon = (ImageView)view.findViewById(R.id.item_icon); - TextView itemTitle = (TextView)view.findViewById(R.id.item_title); - TextView itemSubtitle = (TextView)view.findViewById(R.id.item_subtitle); - ImageView settingsIcon = (ImageView)view.findViewById(R.id.item_settings_icon); - View subtypeView = view.findViewById(R.id.item_subtype); + final CharSequence subtypeName = subtype.overridesImplicitlyEnabledSubtype() + ? null : getSubtypeName(imi, subtype); + final CharSequence imiName = getIMIName(imi); + final Drawable icon = getSubtypeIcon(imi, subtype); + final View view = View.inflate(mContext, R.layout.status_bar_input_methods_item, null); + final ImageView subtypeIcon = (ImageView)view.findViewById(R.id.item_icon); + final TextView itemTitle = (TextView)view.findViewById(R.id.item_title); + final TextView itemSubtitle = (TextView)view.findViewById(R.id.item_subtitle); + final ImageView settingsIcon = (ImageView)view.findViewById(R.id.item_settings_icon); + final View subtypeView = view.findViewById(R.id.item_subtype); if (subtypeName == null) { itemTitle.setText(imiName); itemSubtitle.setVisibility(View.GONE); |