diff options
37 files changed, 672 insertions, 330 deletions
diff --git a/api/current.txt b/api/current.txt index 7c4bae275886..f33c6cb10718 100644 --- a/api/current.txt +++ b/api/current.txt @@ -10696,6 +10696,7 @@ package android.media { field public static final int METADATA_KEY_GENRE = 6; // 0x6 field public static final int METADATA_KEY_HAS_AUDIO = 16; // 0x10 field public static final int METADATA_KEY_HAS_VIDEO = 17; // 0x11 + field public static final int METADATA_KEY_LOCATION = 23; // 0x17 field public static final int METADATA_KEY_MIMETYPE = 12; // 0xc field public static final int METADATA_KEY_NUM_TRACKS = 10; // 0xa field public static final int METADATA_KEY_TITLE = 7; // 0x7 @@ -18890,7 +18891,8 @@ package android.speech.tts { method public int playSilence(long, int, java.util.HashMap<java.lang.String, java.lang.String>); method public deprecated int setEngineByPackageName(java.lang.String); method public int setLanguage(java.util.Locale); - method public int setOnUtteranceCompletedListener(android.speech.tts.TextToSpeech.OnUtteranceCompletedListener); + method public deprecated int setOnUtteranceCompletedListener(android.speech.tts.TextToSpeech.OnUtteranceCompletedListener); + method public int setOnUtteranceProgressListener(android.speech.tts.UtteranceProgressListener); method public int setPitch(float); method public int setSpeechRate(float); method public void shutdown(); @@ -18963,6 +18965,13 @@ package android.speech.tts { method protected abstract void onSynthesizeText(android.speech.tts.SynthesisRequest, android.speech.tts.SynthesisCallback); } + public abstract class UtteranceProgressListener { + ctor public UtteranceProgressListener(); + method public abstract void onDone(java.lang.String); + method public abstract void onError(java.lang.String); + method public abstract void onStart(java.lang.String); + } + } package android.telephony { diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java index f81ea81be237..91398bce21f3 100644 --- a/core/java/android/app/WallpaperManager.java +++ b/core/java/android/app/WallpaperManager.java @@ -212,7 +212,11 @@ public class WallpaperManager { */ mHandler.sendEmptyMessage(MSG_CLEAR_WALLPAPER); } - + + public Handler getHandler() { + return mHandler; + } + public Bitmap peekWallpaperBitmap(Context context, boolean returnDefault) { synchronized (this) { if (mWallpaper != null) { @@ -604,7 +608,7 @@ public class WallpaperManager { // Ignore } } - + /** * Set the position of the current wallpaper within any larger space, when * that wallpaper is visible behind the given window. The X and Y offsets @@ -619,16 +623,23 @@ public class WallpaperManager { * @param yOffset The offset along the Y dimension, from 0 to 1. */ public void setWallpaperOffsets(IBinder windowToken, float xOffset, float yOffset) { - try { - //Log.v(TAG, "Sending new wallpaper offsets from app..."); - ViewRootImpl.getWindowSession(mContext.getMainLooper()).setWallpaperPosition( - windowToken, xOffset, yOffset, mWallpaperXStep, mWallpaperYStep); - //Log.v(TAG, "...app returning after sending offsets!"); - } catch (RemoteException e) { - // Ignore. - } + final IBinder fWindowToken = windowToken; + final float fXOffset = xOffset; + final float fYOffset = yOffset; + sGlobals.getHandler().post(new Runnable() { + public void run() { + try { + //Log.v(TAG, "Sending new wallpaper offsets from app..."); + ViewRootImpl.getWindowSession(mContext.getMainLooper()).setWallpaperPosition( + fWindowToken, fXOffset, fYOffset, mWallpaperXStep, mWallpaperYStep); + //Log.v(TAG, "...app returning after sending offsets!"); + } catch (RemoteException e) { + // Ignore. + } + } + }); } - + /** * For applications that use multiple virtual screens showing a wallpaper, * specify the step size between virtual screens. For example, if the diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index 36056529c3a6..f6e627c930d8 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -464,6 +464,19 @@ public class NetworkStats implements Parcelable { * time, and that none of them have disappeared. */ public NetworkStats subtract(NetworkStats value) throws NonMonotonicException { + return subtract(value, false); + } + + /** + * Subtract the given {@link NetworkStats}, effectively leaving the delta + * between two snapshots in time. Assumes that statistics rows collect over + * time, and that none of them have disappeared. + * + * @param clampNonMonotonic When non-monotonic stats are found, just clamp + * to 0 instead of throwing {@link NonMonotonicException}. + */ + public NetworkStats subtract(NetworkStats value, boolean clampNonMonotonic) + throws NonMonotonicException { final long deltaRealtime = this.elapsedRealtime - value.elapsedRealtime; if (deltaRealtime < 0) { throw new NonMonotonicException(this, value); @@ -497,7 +510,15 @@ public class NetworkStats implements Parcelable { if (entry.rxBytes < 0 || entry.rxPackets < 0 || entry.txBytes < 0 || entry.txPackets < 0 || entry.operations < 0) { - throw new NonMonotonicException(this, i, value, j); + if (clampNonMonotonic) { + entry.rxBytes = Math.max(entry.rxBytes, 0); + entry.rxPackets = Math.max(entry.rxPackets, 0); + entry.txBytes = Math.max(entry.txBytes, 0); + entry.txPackets = Math.max(entry.txPackets, 0); + entry.operations = Math.max(entry.operations, 0); + } else { + throw new NonMonotonicException(this, i, value, j); + } } } diff --git a/core/java/android/speech/tts/AudioMessageParams.java b/core/java/android/speech/tts/AudioMessageParams.java index 68d8738027a1..29b436731c43 100644 --- a/core/java/android/speech/tts/AudioMessageParams.java +++ b/core/java/android/speech/tts/AudioMessageParams.java @@ -15,12 +15,12 @@ */ package android.speech.tts; -import android.speech.tts.TextToSpeechService.UtteranceCompletedDispatcher; +import android.speech.tts.TextToSpeechService.UtteranceProgressDispatcher; class AudioMessageParams extends MessageParams { private final BlockingMediaPlayer mPlayer; - AudioMessageParams(UtteranceCompletedDispatcher dispatcher, + AudioMessageParams(UtteranceProgressDispatcher dispatcher, String callingApp, BlockingMediaPlayer player) { super(dispatcher, callingApp); mPlayer = player; diff --git a/core/java/android/speech/tts/AudioPlaybackHandler.java b/core/java/android/speech/tts/AudioPlaybackHandler.java index d970ae61a64d..0194240adc29 100644 --- a/core/java/android/speech/tts/AudioPlaybackHandler.java +++ b/core/java/android/speech/tts/AudioPlaybackHandler.java @@ -312,10 +312,11 @@ class AudioPlaybackHandler { private void handleSilence(MessageParams msg) { if (DBG) Log.d(TAG, "handleSilence()"); SilenceMessageParams params = (SilenceMessageParams) msg; + params.getDispatcher().dispatchOnStart(); if (params.getSilenceDurationMs() > 0) { params.getConditionVariable().block(params.getSilenceDurationMs()); } - params.getDispatcher().dispatchUtteranceCompleted(); + params.getDispatcher().dispatchOnDone(); if (DBG) Log.d(TAG, "handleSilence() done."); } @@ -323,11 +324,12 @@ class AudioPlaybackHandler { private void handleAudio(MessageParams msg) { if (DBG) Log.d(TAG, "handleAudio()"); AudioMessageParams params = (AudioMessageParams) msg; + params.getDispatcher().dispatchOnStart(); // Note that the BlockingMediaPlayer spawns a separate thread. // // TODO: This can be avoided. params.getPlayer().startAndWait(); - params.getDispatcher().dispatchUtteranceCompleted(); + params.getDispatcher().dispatchOnDone(); if (DBG) Log.d(TAG, "handleAudio() done."); } @@ -361,6 +363,7 @@ class AudioPlaybackHandler { if (DBG) Log.d(TAG, "Created audio track [" + audioTrack.hashCode() + "]"); param.setAudioTrack(audioTrack); + msg.getDispatcher().dispatchOnStart(); } // More data available to be flushed to the audio track. @@ -411,6 +414,7 @@ class AudioPlaybackHandler { final AudioTrack audioTrack = params.getAudioTrack(); if (audioTrack == null) { + params.getDispatcher().dispatchOnError(); return; } @@ -439,7 +443,7 @@ class AudioPlaybackHandler { audioTrack.release(); params.setAudioTrack(null); } - params.getDispatcher().dispatchUtteranceCompleted(); + params.getDispatcher().dispatchOnDone(); mLastSynthesisRequest = null; params.mLogger.onWriteData(); } diff --git a/core/java/android/speech/tts/ITextToSpeechCallback.aidl b/core/java/android/speech/tts/ITextToSpeechCallback.aidl index 40902ae53f9a..f0287d4a3b0a 100755 --- a/core/java/android/speech/tts/ITextToSpeechCallback.aidl +++ b/core/java/android/speech/tts/ITextToSpeechCallback.aidl @@ -21,5 +21,7 @@ package android.speech.tts; * {@hide} */ oneway interface ITextToSpeechCallback { - void utteranceCompleted(String utteranceId); + void onStart(String utteranceId); + void onDone(String utteranceId); + void onError(String utteranceId); } diff --git a/core/java/android/speech/tts/MessageParams.java b/core/java/android/speech/tts/MessageParams.java index e7d6da3782a6..de9cc0740414 100644 --- a/core/java/android/speech/tts/MessageParams.java +++ b/core/java/android/speech/tts/MessageParams.java @@ -15,22 +15,22 @@ */ package android.speech.tts; -import android.speech.tts.TextToSpeechService.UtteranceCompletedDispatcher; +import android.speech.tts.TextToSpeechService.UtteranceProgressDispatcher; abstract class MessageParams { static final int TYPE_SYNTHESIS = 1; static final int TYPE_AUDIO = 2; static final int TYPE_SILENCE = 3; - private final UtteranceCompletedDispatcher mDispatcher; + private final UtteranceProgressDispatcher mDispatcher; private final String mCallingApp; - MessageParams(UtteranceCompletedDispatcher dispatcher, String callingApp) { + MessageParams(UtteranceProgressDispatcher dispatcher, String callingApp) { mDispatcher = dispatcher; mCallingApp = callingApp; } - UtteranceCompletedDispatcher getDispatcher() { + UtteranceProgressDispatcher getDispatcher() { return mDispatcher; } diff --git a/core/java/android/speech/tts/PlaybackSynthesisCallback.java b/core/java/android/speech/tts/PlaybackSynthesisCallback.java index 0cca06accd1f..ce3522be2d86 100644 --- a/core/java/android/speech/tts/PlaybackSynthesisCallback.java +++ b/core/java/android/speech/tts/PlaybackSynthesisCallback.java @@ -15,7 +15,7 @@ */ package android.speech.tts; -import android.speech.tts.TextToSpeechService.UtteranceCompletedDispatcher; +import android.speech.tts.TextToSpeechService.UtteranceProgressDispatcher; import android.util.Log; /** @@ -62,12 +62,12 @@ class PlaybackSynthesisCallback extends AbstractSynthesisCallback { private volatile boolean mDone = false; - private final UtteranceCompletedDispatcher mDispatcher; + private final UtteranceProgressDispatcher mDispatcher; private final String mCallingApp; private final EventLogger mLogger; PlaybackSynthesisCallback(int streamType, float volume, float pan, - AudioPlaybackHandler audioTrackHandler, UtteranceCompletedDispatcher dispatcher, + AudioPlaybackHandler audioTrackHandler, UtteranceProgressDispatcher dispatcher, String callingApp, EventLogger logger) { mStreamType = streamType; mVolume = volume; diff --git a/core/java/android/speech/tts/SilenceMessageParams.java b/core/java/android/speech/tts/SilenceMessageParams.java index 7a4ff1c0cdeb..99091268c92a 100644 --- a/core/java/android/speech/tts/SilenceMessageParams.java +++ b/core/java/android/speech/tts/SilenceMessageParams.java @@ -16,13 +16,13 @@ package android.speech.tts; import android.os.ConditionVariable; -import android.speech.tts.TextToSpeechService.UtteranceCompletedDispatcher; +import android.speech.tts.TextToSpeechService.UtteranceProgressDispatcher; class SilenceMessageParams extends MessageParams { private final ConditionVariable mCondVar = new ConditionVariable(); private final long mSilenceDurationMs; - SilenceMessageParams(UtteranceCompletedDispatcher dispatcher, + SilenceMessageParams(UtteranceProgressDispatcher dispatcher, String callingApp, long silenceDurationMs) { super(dispatcher, callingApp); mSilenceDurationMs = silenceDurationMs; diff --git a/core/java/android/speech/tts/SynthesisMessageParams.java b/core/java/android/speech/tts/SynthesisMessageParams.java index 779721eb1c5e..0c0f033fa066 100644 --- a/core/java/android/speech/tts/SynthesisMessageParams.java +++ b/core/java/android/speech/tts/SynthesisMessageParams.java @@ -17,7 +17,7 @@ package android.speech.tts; import android.media.AudioFormat; import android.media.AudioTrack; -import android.speech.tts.TextToSpeechService.UtteranceCompletedDispatcher; +import android.speech.tts.TextToSpeechService.UtteranceProgressDispatcher; import java.util.LinkedList; @@ -56,7 +56,7 @@ final class SynthesisMessageParams extends MessageParams { SynthesisMessageParams(int streamType, int sampleRate, int audioFormat, int channelCount, - float volume, float pan, UtteranceCompletedDispatcher dispatcher, + float volume, float pan, UtteranceProgressDispatcher dispatcher, String callingApp, EventLogger logger) { super(dispatcher, callingApp); diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java index fdc25708f2d1..38699eaad44f 100755 --- a/core/java/android/speech/tts/TextToSpeech.java +++ b/core/java/android/speech/tts/TextToSpeech.java @@ -482,7 +482,7 @@ public class TextToSpeech { private OnInitListener mInitListener; // Written from an unspecified application thread, read from // a binder thread. - private volatile OnUtteranceCompletedListener mUtteranceCompletedListener; + private volatile UtteranceProgressListener mUtteranceProgressListener; private final Object mStartLock = new Object(); private String mRequestedEngine; @@ -1146,9 +1146,28 @@ public class TextToSpeech { * @param listener The listener to use. * * @return {@link #ERROR} or {@link #SUCCESS}. + * + * @deprecated Use {@link #setOnUtteranceProgressListener(UtteranceProgressListener)} + * instead. */ + @Deprecated public int setOnUtteranceCompletedListener(final OnUtteranceCompletedListener listener) { - mUtteranceCompletedListener = listener; + mUtteranceProgressListener = UtteranceProgressListener.from(listener); + return TextToSpeech.SUCCESS; + } + + /** + * Sets the listener that will be notified of various events related to the + * synthesis of a given utterance. + * + * See {@link UtteranceProgressListener} and + * {@link TextToSpeech.Engine#KEY_PARAM_UTTERANCE_ID}. + * + * @param listener the listener to use. + * @return {@link #ERROR} or {@link #SUCCESS} + */ + public int setOnUtteranceProgressListener(UtteranceProgressListener listener) { + mUtteranceProgressListener = listener; return TextToSpeech.SUCCESS; } @@ -1204,10 +1223,26 @@ public class TextToSpeech { private ITextToSpeechService mService; private final ITextToSpeechCallback.Stub mCallback = new ITextToSpeechCallback.Stub() { @Override - public void utteranceCompleted(String utteranceId) { - OnUtteranceCompletedListener listener = mUtteranceCompletedListener; + public void onDone(String utteranceId) { + UtteranceProgressListener listener = mUtteranceProgressListener; + if (listener != null) { + listener.onDone(utteranceId); + } + } + + @Override + public void onError(String utteranceId) { + UtteranceProgressListener listener = mUtteranceProgressListener; + if (listener != null) { + listener.onError(utteranceId); + } + } + + @Override + public void onStart(String utteranceId) { + UtteranceProgressListener listener = mUtteranceProgressListener; if (listener != null) { - listener.onUtteranceCompleted(utteranceId); + listener.onStart(utteranceId); } } }; diff --git a/core/java/android/speech/tts/TextToSpeechService.java b/core/java/android/speech/tts/TextToSpeechService.java index 83b6d4c24f21..39922da68b34 100644 --- a/core/java/android/speech/tts/TextToSpeechService.java +++ b/core/java/android/speech/tts/TextToSpeechService.java @@ -306,6 +306,7 @@ public abstract class TextToSpeechService extends Service { */ public int enqueueSpeechItem(int queueMode, final SpeechItem speechItem) { if (!speechItem.isValid()) { + speechItem.dispatchOnError(); return TextToSpeech.ERROR; } @@ -332,6 +333,7 @@ public abstract class TextToSpeechService extends Service { return TextToSpeech.SUCCESS; } else { Log.w(TAG, "SynthThread has quit"); + speechItem.dispatchOnError(); return TextToSpeech.ERROR; } } @@ -381,14 +383,16 @@ public abstract class TextToSpeechService extends Service { } } - interface UtteranceCompletedDispatcher { - public void dispatchUtteranceCompleted(); + interface UtteranceProgressDispatcher { + public void dispatchOnDone(); + public void dispatchOnStart(); + public void dispatchOnError(); } /** * An item in the synth thread queue. */ - private abstract class SpeechItem implements UtteranceCompletedDispatcher { + private abstract class SpeechItem implements UtteranceProgressDispatcher { private final String mCallingApp; protected final Bundle mParams; private boolean mStarted = false; @@ -443,10 +447,27 @@ public abstract class TextToSpeechService extends Service { stopImpl(); } - public void dispatchUtteranceCompleted() { + @Override + public void dispatchOnDone() { + final String utteranceId = getUtteranceId(); + if (!TextUtils.isEmpty(utteranceId)) { + mCallbacks.dispatchOnDone(getCallingApp(), utteranceId); + } + } + + @Override + public void dispatchOnStart() { + final String utteranceId = getUtteranceId(); + if (!TextUtils.isEmpty(utteranceId)) { + mCallbacks.dispatchOnStart(getCallingApp(), utteranceId); + } + } + + @Override + public void dispatchOnError() { final String utteranceId = getUtteranceId(); if (!TextUtils.isEmpty(utteranceId)) { - mCallbacks.dispatchUtteranceCompleted(getCallingApp(), utteranceId); + mCallbacks.dispatchOnError(getCallingApp(), utteranceId); } } @@ -617,9 +638,12 @@ public abstract class TextToSpeechService extends Service { @Override protected int playImpl() { + dispatchOnStart(); int status = super.playImpl(); if (status == TextToSpeech.SUCCESS) { - dispatchUtteranceCompleted(); + dispatchOnDone(); + } else { + dispatchOnError(); } return status; } @@ -856,16 +880,34 @@ public abstract class TextToSpeechService extends Service { } } - public void dispatchUtteranceCompleted(String packageName, String utteranceId) { - ITextToSpeechCallback cb; - synchronized (mAppToCallback) { - cb = mAppToCallback.get(packageName); + public void dispatchOnDone(String packageName, String utteranceId) { + ITextToSpeechCallback cb = getCallbackFor(packageName); + if (cb == null) return; + try { + cb.onDone(utteranceId); + } catch (RemoteException e) { + Log.e(TAG, "Callback onDone failed: " + e); } + } + + public void dispatchOnStart(String packageName, String utteranceId) { + ITextToSpeechCallback cb = getCallbackFor(packageName); + if (cb == null) return; + try { + cb.onStart(utteranceId); + } catch (RemoteException e) { + Log.e(TAG, "Callback onStart failed: " + e); + } + + } + + public void dispatchOnError(String packageName, String utteranceId) { + ITextToSpeechCallback cb = getCallbackFor(packageName); if (cb == null) return; try { - cb.utteranceCompleted(utteranceId); + cb.onError(utteranceId); } catch (RemoteException e) { - Log.e(TAG, "Callback failed: " + e); + Log.e(TAG, "Callback onError failed: " + e); } } @@ -886,6 +928,15 @@ public abstract class TextToSpeechService extends Service { } } + private ITextToSpeechCallback getCallbackFor(String packageName) { + ITextToSpeechCallback cb; + synchronized (mAppToCallback) { + cb = mAppToCallback.get(packageName); + } + + return cb; + } + } } diff --git a/core/java/android/speech/tts/UtteranceProgressListener.java b/core/java/android/speech/tts/UtteranceProgressListener.java new file mode 100644 index 000000000000..a04458a4ddf7 --- /dev/null +++ b/core/java/android/speech/tts/UtteranceProgressListener.java @@ -0,0 +1,68 @@ +// Copyright 2011 Google Inc. All Rights Reserved. + +package android.speech.tts; + +/** + * Listener for events relating to the progress of an utterance through + * the synthesis queue. Each utterance is associated with a call to + * {@link TextToSpeech#speak} or {@link TextToSpeech#synthesizeToFile} with an + * associated utterance identifier, as per {@link TextToSpeech.Engine#KEY_PARAM_UTTERANCE_ID}. + * + * The callbacks specified in this method can be called from multiple threads. + */ +public abstract class UtteranceProgressListener { + /** + * Called when an utterance "starts" as perceived by the caller. This will + * be soon before audio is played back in the case of a {@link TextToSpeech#speak} + * or before the first bytes of a file are written to storage in the case + * of {@link TextToSpeech#synthesizeToFile}. + * + * @param utteranceId the utterance ID of the utterance. + */ + public abstract void onStart(String utteranceId); + + /** + * Called when an utterance has successfully completed processing. + * All audio will have been played back by this point for audible output, and all + * output will have been written to disk for file synthesis requests. + * + * This request is guaranteed to be called after {@link #onStart(String)}. + * + * @param utteranceId the utterance ID of the utterance. + */ + public abstract void onDone(String utteranceId); + + /** + * Called when an error has occurred during processing. This can be called + * at any point in the synthesis process. Note that there might be calls + * to {@link #onStart(String)} for specified utteranceId but there will never + * be a call to both {@link #onDone(String)} and {@link #onError(String)} for + * the same utterance. + * + * @param utteranceId the utterance ID of the utterance. + */ + public abstract void onError(String utteranceId); + + /** + * Wraps an old deprecated OnUtteranceCompletedListener with a shiny new + * progress listener. + * + * @hide + */ + static UtteranceProgressListener from( + final TextToSpeech.OnUtteranceCompletedListener listener) { + return new UtteranceProgressListener() { + @Override + public synchronized void onDone(String utteranceId) { + listener.onUtteranceCompleted(utteranceId); + } + + // The following methods are left unimplemented. + @Override + public void onStart(String utteranceId) { } + + @Override + public void onError(String utteranceId) { } + }; + } +} diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java index c1e36ed9efda..73e127376b58 100644 --- a/core/java/android/widget/ImageView.java +++ b/core/java/android/widget/ImageView.java @@ -1036,6 +1036,7 @@ public class ImageView extends View { } } + @RemotableViewMethod @Override public void setVisibility(int visibility) { super.setVisibility(visibility); diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java index 8ba7beed3ffd..5fa4ad09655f 100644 --- a/core/java/android/widget/PopupWindow.java +++ b/core/java/android/widget/PopupWindow.java @@ -1248,6 +1248,8 @@ public class PopupWindow { */ public void dismiss() { if (isShowing() && mPopupView != null) { + mIsShowing = false; + unregisterForScrollChanged(); try { @@ -1257,7 +1259,6 @@ public class PopupWindow { ((ViewGroup) mPopupView).removeView(mContentView); } mPopupView = null; - mIsShowing = false; if (mOnDismissListener != null) { mOnDismissListener.onDismiss(); diff --git a/include/media/mediametadataretriever.h b/include/media/mediametadataretriever.h index 9aa67005278d..534afce498f0 100644 --- a/include/media/mediametadataretriever.h +++ b/include/media/mediametadataretriever.h @@ -54,6 +54,7 @@ enum { METADATA_KEY_BITRATE = 20, METADATA_KEY_TIMED_TEXT_LANGUAGES = 21, METADATA_KEY_IS_DRM = 22, + METADATA_KEY_LOCATION = 23, // Add more here... }; diff --git a/include/media/stagefright/MetaData.h b/include/media/stagefright/MetaData.h index 57f678c75512..4cdee1702fe0 100644 --- a/include/media/stagefright/MetaData.h +++ b/include/media/stagefright/MetaData.h @@ -85,6 +85,7 @@ enum { kKeyDate = 'date', // cstring kKeyWriter = 'writ', // cstring kKeyCompilation = 'cpil', // cstring + kKeyLocation = 'loc ', // cstring kKeyTimeScale = 'tmsl', // int32_t // video profile and level diff --git a/media/java/android/media/MediaMetadataRetriever.java b/media/java/android/media/MediaMetadataRetriever.java index 10694c35e314..11ecd1f98e4e 100644 --- a/media/java/android/media/MediaMetadataRetriever.java +++ b/media/java/android/media/MediaMetadataRetriever.java @@ -458,5 +458,12 @@ public class MediaMetadataRetriever * @hide */ public static final int METADATA_KEY_IS_DRM = 22; + /** + * This key retrieves the location information, if available. + * The location should be specified according to ISO-6709 standard, under + * a mp4/3gp box "@xyz". Location with longitude of -90 degrees and latitude + * of 180 degrees will be retrieved as "-90.0000+180.0000", for instance. + */ + public static final int METADATA_KEY_LOCATION = 23; // Add more here... } diff --git a/media/libeffects/visualizer/EffectVisualizer.cpp b/media/libeffects/visualizer/EffectVisualizer.cpp index 3c3af8f343af..1a06cc62938a 100644 --- a/media/libeffects/visualizer/EffectVisualizer.cpp +++ b/media/libeffects/visualizer/EffectVisualizer.cpp @@ -47,17 +47,22 @@ enum visualizer_state_e { VISUALIZER_STATE_ACTIVE, }; +// maximum number of reads from same buffer before resetting capture buffer. This means +// that the framework has stopped playing audio and we must start returning silence +#define MAX_STALL_COUNT 10 + struct VisualizerContext { const struct effect_interface_s *mItfe; effect_config_t mConfig; - uint32_t mState; uint32_t mCaptureIdx; uint32_t mCaptureSize; - uint32_t mCurrentBuf; + uint8_t mState; + uint8_t mCurrentBuf; + uint8_t mLastBuf; + uint8_t mStallCount; uint8_t mCaptureBuf[2][VISUALIZER_CAPTURE_SIZE_MAX]; }; - // //--- Local functions // @@ -66,6 +71,8 @@ void Visualizer_reset(VisualizerContext *pContext) { pContext->mCaptureIdx = 0; pContext->mCurrentBuf = 0; + pContext->mLastBuf = 1; + pContext->mStallCount = 0; memset(pContext->mCaptureBuf[0], 0x80, VISUALIZER_CAPTURE_SIZE_MAX); memset(pContext->mCaptureBuf[1], 0x80, VISUALIZER_CAPTURE_SIZE_MAX); } @@ -417,9 +424,24 @@ int Visualizer_command(effect_handle_t self, uint32_t cmdCode, uint32_t cmdSize, memcpy(pReplyData, pContext->mCaptureBuf[pContext->mCurrentBuf ^ 1], pContext->mCaptureSize); + // if audio framework has stopped playing audio although the effect is still + // active we must clear the capture buffer to return silence + if (pContext->mLastBuf == pContext->mCurrentBuf) { + if (pContext->mStallCount < MAX_STALL_COUNT) { + if (++pContext->mStallCount == MAX_STALL_COUNT) { + memset(pContext->mCaptureBuf[pContext->mCurrentBuf ^ 1], + 0x80, + pContext->mCaptureSize); + } + } + } else { + pContext->mStallCount = 0; + } + pContext->mLastBuf = pContext->mCurrentBuf; } else { memset(pReplyData, 0x80, pContext->mCaptureSize); } + break; default: diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp index 1e24599985bb..1ebf0a8c31ce 100644 --- a/media/libstagefright/MPEG4Extractor.cpp +++ b/media/libstagefright/MPEG4Extractor.cpp @@ -1136,6 +1136,41 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { break; } + // @xyz + case FOURCC('\xA9', 'x', 'y', 'z'): + { + // Best case the total data length inside "@xyz" box + // would be 8, for instance "@xyz" + "\x00\x04\x15\xc7" + "0+0/", + // where "\x00\x04" is the text string length with value = 4, + // "\0x15\xc7" is the language code = en, and "0+0" is a + // location (string) value with longitude = 0 and latitude = 0. + if (chunk_data_size < 8) { + return ERROR_MALFORMED; + } + + // Worst case the location string length would be 18, + // for instance +90.0000-180.0000, without the trailing "/" and + // the string length + language code. + char buffer[18]; + + // Substracting 5 from the data size is because the text string length + + // language code takes 4 bytes, and the trailing slash "/" takes 1 byte. + off64_t location_length = chunk_data_size - 5; + if (location_length >= (off64_t) sizeof(buffer)) { + return ERROR_MALFORMED; + } + + if (mDataSource->readAt( + data_offset + 4, buffer, location_length) < location_length) { + return ERROR_IO; + } + + buffer[location_length] = '\0'; + mFileMetaData->setCString(kKeyLocation, buffer); + *offset += chunk_size; + break; + } + case FOURCC('e', 's', 'd', 's'): { if (chunk_data_size < 4) { diff --git a/media/libstagefright/StagefrightMetadataRetriever.cpp b/media/libstagefright/StagefrightMetadataRetriever.cpp index c74cb5aeb02c..4491c9708882 100644 --- a/media/libstagefright/StagefrightMetadataRetriever.cpp +++ b/media/libstagefright/StagefrightMetadataRetriever.cpp @@ -418,6 +418,7 @@ void StagefrightMetadataRetriever::parseMetaData() { { kKeyYear, METADATA_KEY_YEAR }, { kKeyWriter, METADATA_KEY_WRITER }, { kKeyCompilation, METADATA_KEY_COMPILATION }, + { kKeyLocation, METADATA_KEY_LOCATION }, }; static const size_t kNumMapEntries = sizeof(kMap) / sizeof(kMap[0]); diff --git a/media/libstagefright/rtsp/ARTPConnection.cpp b/media/libstagefright/rtsp/ARTPConnection.cpp index 47de4e0938d0..cd374e2a2017 100644 --- a/media/libstagefright/rtsp/ARTPConnection.cpp +++ b/media/libstagefright/rtsp/ARTPConnection.cpp @@ -220,7 +220,7 @@ void ARTPConnection::onRemoveStream(const sp<AMessage> &msg) { } if (it == mStreams.end()) { - TRESPASS(); + return; } mStreams.erase(it); @@ -274,41 +274,52 @@ void ARTPConnection::onPollStreams() { } int res = select(maxSocket + 1, &rs, NULL, NULL, &tv); - CHECK_GE(res, 0); if (res > 0) { - for (List<StreamInfo>::iterator it = mStreams.begin(); - it != mStreams.end(); ++it) { + List<StreamInfo>::iterator it = mStreams.begin(); + while (it != mStreams.end()) { if ((*it).mIsInjected) { + ++it; continue; } + status_t err = OK; if (FD_ISSET(it->mRTPSocket, &rs)) { - receive(&*it, true); + err = receive(&*it, true); } - if (FD_ISSET(it->mRTCPSocket, &rs)) { - receive(&*it, false); + if (err == OK && FD_ISSET(it->mRTCPSocket, &rs)) { + err = receive(&*it, false); } + + if (err == -ECONNRESET) { + // socket failure, this stream is dead, Jim. + + LOGW("failed to receive RTP/RTCP datagram."); + it = mStreams.erase(it); + continue; + } + + ++it; } } - postPollEvent(); - int64_t nowUs = ALooper::GetNowUs(); if (mLastReceiverReportTimeUs <= 0 || mLastReceiverReportTimeUs + 5000000ll <= nowUs) { sp<ABuffer> buffer = new ABuffer(kMaxUDPSize); - for (List<StreamInfo>::iterator it = mStreams.begin(); - it != mStreams.end(); ++it) { + List<StreamInfo>::iterator it = mStreams.begin(); + while (it != mStreams.end()) { StreamInfo *s = &*it; if (s->mIsInjected) { + ++it; continue; } if (s->mNumRTCPPacketsReceived == 0) { // We have never received any RTCP packets on this stream, // we don't even know where to send a report. + ++it; continue; } @@ -327,16 +338,34 @@ void ARTPConnection::onPollStreams() { if (buffer->size() > 0) { LOGV("Sending RR..."); - ssize_t n = sendto( + ssize_t n; + do { + n = sendto( s->mRTCPSocket, buffer->data(), buffer->size(), 0, (const struct sockaddr *)&s->mRemoteRTCPAddr, sizeof(s->mRemoteRTCPAddr)); + } while (n < 0 && errno == EINTR); + + if (n <= 0) { + LOGW("failed to send RTCP receiver report (%s).", + n == 0 ? "connection gone" : strerror(errno)); + + it = mStreams.erase(it); + continue; + } + CHECK_EQ(n, (ssize_t)buffer->size()); mLastReceiverReportTimeUs = nowUs; } + + ++it; } } + + if (!mStreams.empty()) { + postPollEvent(); + } } status_t ARTPConnection::receive(StreamInfo *s, bool receiveRTP) { @@ -350,16 +379,19 @@ status_t ARTPConnection::receive(StreamInfo *s, bool receiveRTP) { (!receiveRTP && s->mNumRTCPPacketsReceived == 0) ? sizeof(s->mRemoteRTCPAddr) : 0; - ssize_t nbytes = recvfrom( + ssize_t nbytes; + do { + nbytes = recvfrom( receiveRTP ? s->mRTPSocket : s->mRTCPSocket, buffer->data(), buffer->capacity(), 0, remoteAddrLen > 0 ? (struct sockaddr *)&s->mRemoteRTCPAddr : NULL, remoteAddrLen > 0 ? &remoteAddrLen : NULL); + } while (nbytes < 0 && errno == EINTR); - if (nbytes < 0) { - return -1; + if (nbytes <= 0) { + return -ECONNRESET; } buffer->setRange(0, nbytes); diff --git a/media/libstagefright/rtsp/ARTSPConnection.cpp b/media/libstagefright/rtsp/ARTSPConnection.cpp index bd0e49158633..4f0363b7462a 100644 --- a/media/libstagefright/rtsp/ARTSPConnection.cpp +++ b/media/libstagefright/rtsp/ARTSPConnection.cpp @@ -187,10 +187,13 @@ bool ARTSPConnection::ParseURL( return true; } -static void MakeSocketBlocking(int s, bool blocking) { +static status_t MakeSocketBlocking(int s, bool blocking) { // Make socket non-blocking. int flags = fcntl(s, F_GETFL, 0); - CHECK_NE(flags, -1); + + if (flags == -1) { + return UNKNOWN_ERROR; + } if (blocking) { flags &= ~O_NONBLOCK; @@ -198,7 +201,9 @@ static void MakeSocketBlocking(int s, bool blocking) { flags |= O_NONBLOCK; } - CHECK_NE(fcntl(s, F_SETFL, flags), -1); + flags = fcntl(s, F_SETFL, flags); + + return flags == -1 ? UNKNOWN_ERROR : OK; } void ARTSPConnection::onConnect(const sp<AMessage> &msg) { @@ -302,27 +307,32 @@ void ARTSPConnection::onConnect(const sp<AMessage> &msg) { reply->post(); } +void ARTSPConnection::performDisconnect() { + if (mUIDValid) { + HTTPBase::UnRegisterSocketUserTag(mSocket); + } + close(mSocket); + mSocket = -1; + + flushPendingRequests(); + + mUser.clear(); + mPass.clear(); + mAuthType = NONE; + mNonce.clear(); + + mState = DISCONNECTED; +} + void ARTSPConnection::onDisconnect(const sp<AMessage> &msg) { if (mState == CONNECTED || mState == CONNECTING) { - if (mUIDValid) { - HTTPBase::UnRegisterSocketUserTag(mSocket); - } - close(mSocket); - mSocket = -1; - - flushPendingRequests(); + performDisconnect(); } sp<AMessage> reply; CHECK(msg->findMessage("reply", &reply)); reply->setInt32("result", OK); - mState = DISCONNECTED; - - mUser.clear(); - mPass.clear(); - mAuthType = NONE; - mNonce.clear(); reply->post(); } @@ -427,21 +437,25 @@ void ARTSPConnection::onSendRequest(const sp<AMessage> &msg) { send(mSocket, request.c_str() + numBytesSent, request.size() - numBytesSent, 0); - if (n == 0) { - // Server closed the connection. - LOGE("Server unexpectedly closed the connection."); + if (n < 0 && errno == EINTR) { + continue; + } - reply->setInt32("result", ERROR_IO); - reply->post(); - return; - } else if (n < 0) { - if (errno == EINTR) { - continue; + if (n <= 0) { + performDisconnect(); + + if (n == 0) { + // Server closed the connection. + LOGE("Server unexpectedly closed the connection."); + + reply->setInt32("result", ERROR_IO); + reply->post(); + } else { + LOGE("Error sending rtsp request. (%s)", strerror(errno)); + reply->setInt32("result", -errno); + reply->post(); } - LOGE("Error sending rtsp request."); - reply->setInt32("result", -errno); - reply->post(); return; } @@ -512,17 +526,22 @@ status_t ARTSPConnection::receive(void *data, size_t size) { size_t offset = 0; while (offset < size) { ssize_t n = recv(mSocket, (uint8_t *)data + offset, size - offset, 0); - if (n == 0) { - // Server closed the connection. - LOGE("Server unexpectedly closed the connection."); - return ERROR_IO; - } else if (n < 0) { - if (errno == EINTR) { - continue; - } - LOGE("Error reading rtsp response."); - return -errno; + if (n < 0 && errno == EINTR) { + continue; + } + + if (n <= 0) { + performDisconnect(); + + if (n == 0) { + // Server closed the connection. + LOGE("Server unexpectedly closed the connection."); + return ERROR_IO; + } else { + LOGE("Error reading rtsp response. (%s)", strerror(errno)); + return -errno; + } } offset += (size_t)n; @@ -681,24 +700,8 @@ bool ARTSPConnection::receiveRTSPReponse() { if (contentLength > 0) { response->mContent = new ABuffer(contentLength); - size_t numBytesRead = 0; - while (numBytesRead < contentLength) { - ssize_t n = recv( - mSocket, response->mContent->data() + numBytesRead, - contentLength - numBytesRead, 0); - - if (n == 0) { - // Server closed the connection. - TRESPASS(); - } else if (n < 0) { - if (errno == EINTR) { - continue; - } - - TRESPASS(); - } - - numBytesRead += (size_t)n; + if (receive(response->mContent->data(), contentLength) != OK) { + return false; } } @@ -765,17 +768,20 @@ bool ARTSPConnection::handleServerRequest(const sp<ARTSPResponse> &request) { send(mSocket, response.c_str() + numBytesSent, response.size() - numBytesSent, 0); - if (n == 0) { - // Server closed the connection. - LOGE("Server unexpectedly closed the connection."); + if (n < 0 && errno == EINTR) { + continue; + } - return false; - } else if (n < 0) { - if (errno == EINTR) { - continue; + if (n <= 0) { + if (n == 0) { + // Server closed the connection. + LOGE("Server unexpectedly closed the connection."); + } else { + LOGE("Error sending rtsp response (%s).", strerror(errno)); } - LOGE("Error sending rtsp response."); + performDisconnect(); + return false; } diff --git a/media/libstagefright/rtsp/ARTSPConnection.h b/media/libstagefright/rtsp/ARTSPConnection.h index 5cb84fd08f96..68f2d59ea80e 100644 --- a/media/libstagefright/rtsp/ARTSPConnection.h +++ b/media/libstagefright/rtsp/ARTSPConnection.h @@ -91,6 +91,8 @@ private: AString mUserAgent; + void performDisconnect(); + void onConnect(const sp<AMessage> &msg); void onDisconnect(const sp<AMessage> &msg); void onCompleteConnection(const sp<AMessage> &msg); diff --git a/media/libstagefright/rtsp/MyHandler.h b/media/libstagefright/rtsp/MyHandler.h index 6a5efa4adbdc..794c60b6a9a8 100644 --- a/media/libstagefright/rtsp/MyHandler.h +++ b/media/libstagefright/rtsp/MyHandler.h @@ -463,8 +463,17 @@ struct MyHandler : public AHandler { mBaseURL = tmp; } - CHECK_GT(mSessionDesc->countTracks(), 1u); - setupTrack(1); + if (mSessionDesc->countTracks() < 2) { + // There's no actual tracks in this session. + // The first "track" is merely session meta + // data. + + LOGW("Session doesn't contain any playable " + "tracks. Aborting."); + result = ERROR_UNSUPPORTED; + } else { + setupTrack(1); + } } } } @@ -783,9 +792,13 @@ struct MyHandler : public AHandler { } if (mNumAccessUnitsReceived == 0) { +#if 1 LOGI("stream ended? aborting."); (new AMessage('abor', id()))->post(); break; +#else + LOGI("haven't seen an AU in a looong time."); +#endif } mNumAccessUnitsReceived = 0; diff --git a/packages/SystemUI/res/drawable-hdpi/ic_notification_open.png b/packages/SystemUI/res/drawable-hdpi/ic_notification_open.png Binary files differindex d697c2fdce63..cd9a54a904df 100644 --- a/packages/SystemUI/res/drawable-hdpi/ic_notification_open.png +++ b/packages/SystemUI/res/drawable-hdpi/ic_notification_open.png diff --git a/packages/SystemUI/res/drawable-mdpi/ic_notification_open.png b/packages/SystemUI/res/drawable-mdpi/ic_notification_open.png Binary files differindex 839c134a7598..5661eaf947f4 100644 --- a/packages/SystemUI/res/drawable-mdpi/ic_notification_open.png +++ b/packages/SystemUI/res/drawable-mdpi/ic_notification_open.png diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_notification_open.png b/packages/SystemUI/res/drawable-xhdpi/ic_notification_open.png Binary files differindex 4f8c98711c90..98455cf5b558 100644 --- a/packages/SystemUI/res/drawable-xhdpi/ic_notification_open.png +++ b/packages/SystemUI/res/drawable-xhdpi/ic_notification_open.png diff --git a/packages/SystemUI/res/layout/signal_cluster_view.xml b/packages/SystemUI/res/layout/signal_cluster_view.xml index 93ac22ed0920..9be90415201d 100644 --- a/packages/SystemUI/res/layout/signal_cluster_view.xml +++ b/packages/SystemUI/res/layout/signal_cluster_view.xml @@ -51,7 +51,7 @@ android:visibility="gone" android:id="@+id/spacer" /> - <FrameLayout + <!--<FrameLayout android:id="@+id/wimax_combo" android:layout_height="wrap_content" android:layout_width="wrap_content" @@ -72,6 +72,7 @@ android:layout_gravity="center|bottom" /> </FrameLayout> + --> <FrameLayout android:layout_height="wrap_content" android:layout_width="wrap_content" diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index a0d7b13a012e..fc81f8ef6dd7 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -257,10 +257,16 @@ <string name="accessibility_wifi_three_bars">Wi-Fi three bars.</string> <!-- Content description of the WIFI signal when it is full for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> <string name="accessibility_wifi_signal_full">WiFi signal full.</string> + + <!-- Content description of the WiMAX signal when no signal for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> <string name="accessibility_no_wimax">No WiMAX.</string> + <!-- Content description of the WiMAX signal when it is one bar for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> <string name="accessibility_wimax_one_bar">WiMAX one bar.</string> + <!-- Content description of the WiMAX signal when it is two bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> <string name="accessibility_wimax_two_bars">WiMAX two bars.</string> + <!-- Content description of the WiMAX signal when it is three bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> <string name="accessibility_wimax_three_bars">WiMAX three bars.</string> + <!-- Content description of the WiMAX signal when it is full for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> <string name="accessibility_wimax_signal_full">WiMAX signal full.</string> <!-- Content description of the data connection type GPRS for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBar.java index 2e1803e67d07..2be35b73ec7d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBar.java @@ -118,15 +118,20 @@ public abstract class StatusBar extends SystemUI implements CommandQueue.Callbac WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH, - PixelFormat.OPAQUE); + // We use a pixel format of RGB565 for the status bar to save memory bandwidth and + // to ensure that the layer can be handled by HWComposer. On some devices the + // HWComposer is unable to handle SW-rendered RGBX_8888 layers. + PixelFormat.RGB_565); // the status bar should be in an overlay if possible final Display defaultDisplay = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE)) .getDefaultDisplay(); - if (ActivityManager.isHighEndGfx(defaultDisplay)) { - lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED; - } + + // We explicitly leave FLAG_HARDWARE_ACCELERATED out of the flags. The status bar occupies + // very little screen real-estate and is updated fairly frequently. By using CPU rendering + // for the status bar, we prevent the GPU from having to wake up just to do these small + // updates, which should help keep power consumption down. lp.gravity = getStatusBarGravity(); lp.setTitle("StatusBar"); 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 b0e6968c46fd..51fb262bff82 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -350,11 +350,11 @@ public class PhoneStatusBar extends StatusBar { (SignalClusterView)sb.findViewById(R.id.signal_cluster); mNetworkController.addSignalCluster(signalCluster); signalCluster.setNetworkController(mNetworkController); - final ImageView wimaxRSSI = - (ImageView)sb.findViewById(R.id.wimax_signal); - if (wimaxRSSI != null) { - mNetworkController.addWimaxIconView(wimaxRSSI); - } +// final ImageView wimaxRSSI = +// (ImageView)sb.findViewById(R.id.wimax_signal); +// if (wimaxRSSI != null) { +// mNetworkController.addWimaxIconView(wimaxRSSI); +// } // Recents Panel mRecentTasksLoader = new RecentTasksLoader(context); updateRecentsPanel(); 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 f77e93f1ba84..55a5b0ac3136 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java @@ -111,6 +111,7 @@ public class NetworkController extends BroadcastReceiver { com.android.internal.R.drawable.stat_sys_tether_bluetooth; //wimax + private boolean mWimaxSupported = false; private boolean mIsWimaxEnabled = false; private boolean mWimaxConnected = false; private boolean mWimaxIdle = false; @@ -213,9 +214,9 @@ public class NetworkController extends BroadcastReceiver { filter.addAction(ConnectivityManager.INET_CONDITION_ACTION); filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED); filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED); - boolean isWimaxConfigEnabled = mContext.getResources().getBoolean( + mWimaxSupported = mContext.getResources().getBoolean( com.android.internal.R.bool.config_wimaxEnabled); - if(isWimaxConfigEnabled) { + if(mWimaxSupported) { filter.addAction(WimaxManagerConstants.WIMAX_NETWORK_STATE_CHANGED_ACTION); filter.addAction(WimaxManagerConstants.SIGNAL_LEVEL_CHANGED_ACTION); filter.addAction(WimaxManagerConstants.NET_4G_STATE_CHANGED_ACTION); @@ -262,19 +263,36 @@ public class NetworkController extends BroadcastReceiver { public void addSignalCluster(SignalCluster cluster) { mSignalClusters.add(cluster); + refreshSignalCluster(cluster); + } + + public void refreshSignalCluster(SignalCluster cluster) { cluster.setWifiIndicators( mWifiConnected, // only show wifi in the cluster if connected mWifiIconId, mWifiActivityIconId, mContentDescriptionWifi); - cluster.setMobileDataIndicators( - mHasMobileDataFeature, - mShowPhoneRSSIForData ? mPhoneSignalIconId : mDataSignalIconId, - mMobileActivityIconId, - mDataTypeIconId, - mContentDescriptionPhoneSignal, - mContentDescriptionDataType); + if (mIsWimaxEnabled && mWimaxConnected) { + // wimax is special + cluster.setMobileDataIndicators( + true, + mWimaxIconId, + mMobileActivityIconId, + mDataTypeIconId, + mContentDescriptionWimax, + mContentDescriptionDataType); + } else { + // normal mobile data + cluster.setMobileDataIndicators( + mHasMobileDataFeature, + mShowPhoneRSSIForData ? mPhoneSignalIconId : mDataSignalIconId, + mMobileActivityIconId, + mDataTypeIconId, + mContentDescriptionPhoneSignal, + mContentDescriptionDataType); + } + cluster.setIsAirplaneMode(mAirplaneMode); } public void setStackedMode(boolean stacked) { @@ -311,7 +329,7 @@ public class NetworkController extends BroadcastReceiver { } else if (action.equals(WimaxManagerConstants.NET_4G_STATE_CHANGED_ACTION) || action.equals(WimaxManagerConstants.SIGNAL_LEVEL_CHANGED_ACTION) || action.equals(WimaxManagerConstants.WIMAX_NETWORK_STATE_CHANGED_ACTION)) { - updateWimaxState(intent); + updateWimaxState(intent); refreshViews(); } } @@ -466,91 +484,100 @@ public class NetworkController extends BroadcastReceiver { } private final void updateDataNetType() { - switch (mDataNetType) { - case TelephonyManager.NETWORK_TYPE_UNKNOWN: - if (!mShowAtLeastThreeGees) { - mDataIconList = TelephonyIcons.DATA_G[mInetCondition]; - mDataTypeIconId = 0; + if (mIsWimaxEnabled && mWimaxConnected) { + // wimax is a special 4g network not handled by telephony + mDataIconList = TelephonyIcons.DATA_4G[mInetCondition]; + mDataTypeIconId = R.drawable.stat_sys_data_connected_4g; + mContentDescriptionDataType = mContext.getString( + R.string.accessibility_data_connection_4g); + } else { + switch (mDataNetType) { + case TelephonyManager.NETWORK_TYPE_UNKNOWN: + if (!mShowAtLeastThreeGees) { + mDataIconList = TelephonyIcons.DATA_G[mInetCondition]; + mDataTypeIconId = 0; + mContentDescriptionDataType = mContext.getString( + R.string.accessibility_data_connection_gprs); + break; + } else { + // fall through + } + case TelephonyManager.NETWORK_TYPE_EDGE: + if (!mShowAtLeastThreeGees) { + mDataIconList = TelephonyIcons.DATA_E[mInetCondition]; + mDataTypeIconId = R.drawable.stat_sys_data_connected_e; + mContentDescriptionDataType = mContext.getString( + R.string.accessibility_data_connection_edge); + break; + } else { + // fall through + } + case TelephonyManager.NETWORK_TYPE_UMTS: + mDataIconList = TelephonyIcons.DATA_3G[mInetCondition]; + mDataTypeIconId = R.drawable.stat_sys_data_connected_3g; mContentDescriptionDataType = mContext.getString( - R.string.accessibility_data_connection_gprs); + R.string.accessibility_data_connection_3g); break; - } else { - // fall through - } - case TelephonyManager.NETWORK_TYPE_EDGE: - if (!mShowAtLeastThreeGees) { - mDataIconList = TelephonyIcons.DATA_E[mInetCondition]; - mDataTypeIconId = R.drawable.stat_sys_data_connected_e; + case TelephonyManager.NETWORK_TYPE_HSDPA: + case TelephonyManager.NETWORK_TYPE_HSUPA: + case TelephonyManager.NETWORK_TYPE_HSPA: + case TelephonyManager.NETWORK_TYPE_HSPAP: + if (mHspaDataDistinguishable) { + mDataIconList = TelephonyIcons.DATA_H[mInetCondition]; + mDataTypeIconId = R.drawable.stat_sys_data_connected_h; + mContentDescriptionDataType = mContext.getString( + R.string.accessibility_data_connection_3_5g); + } else { + mDataIconList = TelephonyIcons.DATA_3G[mInetCondition]; + mDataTypeIconId = R.drawable.stat_sys_data_connected_3g; + mContentDescriptionDataType = mContext.getString( + R.string.accessibility_data_connection_3g); + } + break; + case TelephonyManager.NETWORK_TYPE_CDMA: + // display 1xRTT for IS95A/B + mDataIconList = TelephonyIcons.DATA_1X[mInetCondition]; + mDataTypeIconId = R.drawable.stat_sys_data_connected_1x; mContentDescriptionDataType = mContext.getString( - R.string.accessibility_data_connection_edge); + R.string.accessibility_data_connection_cdma); break; - } else { - // fall through - } - case TelephonyManager.NETWORK_TYPE_UMTS: - mDataIconList = TelephonyIcons.DATA_3G[mInetCondition]; - mDataTypeIconId = R.drawable.stat_sys_data_connected_3g; - mContentDescriptionDataType = mContext.getString( - R.string.accessibility_data_connection_3g); - break; - case TelephonyManager.NETWORK_TYPE_HSDPA: - case TelephonyManager.NETWORK_TYPE_HSUPA: - case TelephonyManager.NETWORK_TYPE_HSPA: - case TelephonyManager.NETWORK_TYPE_HSPAP: - if (mHspaDataDistinguishable) { - mDataIconList = TelephonyIcons.DATA_H[mInetCondition]; - mDataTypeIconId = R.drawable.stat_sys_data_connected_h; + case TelephonyManager.NETWORK_TYPE_1xRTT: + mDataIconList = TelephonyIcons.DATA_1X[mInetCondition]; + mDataTypeIconId = R.drawable.stat_sys_data_connected_1x; mContentDescriptionDataType = mContext.getString( - R.string.accessibility_data_connection_3_5g); - } else { + R.string.accessibility_data_connection_cdma); + break; + case TelephonyManager.NETWORK_TYPE_EVDO_0: //fall through + case TelephonyManager.NETWORK_TYPE_EVDO_A: + case TelephonyManager.NETWORK_TYPE_EVDO_B: + case TelephonyManager.NETWORK_TYPE_EHRPD: mDataIconList = TelephonyIcons.DATA_3G[mInetCondition]; mDataTypeIconId = R.drawable.stat_sys_data_connected_3g; mContentDescriptionDataType = mContext.getString( R.string.accessibility_data_connection_3g); - } - break; - case TelephonyManager.NETWORK_TYPE_CDMA: - // display 1xRTT for IS95A/B - mDataIconList = TelephonyIcons.DATA_1X[mInetCondition]; - mDataTypeIconId = R.drawable.stat_sys_data_connected_1x; - mContentDescriptionDataType = mContext.getString( - R.string.accessibility_data_connection_cdma); - break; - case TelephonyManager.NETWORK_TYPE_1xRTT: - mDataIconList = TelephonyIcons.DATA_1X[mInetCondition]; - mDataTypeIconId = R.drawable.stat_sys_data_connected_1x; - mContentDescriptionDataType = mContext.getString( - R.string.accessibility_data_connection_cdma); - break; - case TelephonyManager.NETWORK_TYPE_EVDO_0: //fall through - case TelephonyManager.NETWORK_TYPE_EVDO_A: - case TelephonyManager.NETWORK_TYPE_EVDO_B: - case TelephonyManager.NETWORK_TYPE_EHRPD: - mDataIconList = TelephonyIcons.DATA_3G[mInetCondition]; - mDataTypeIconId = R.drawable.stat_sys_data_connected_3g; - mContentDescriptionDataType = mContext.getString( - R.string.accessibility_data_connection_3g); - break; - case TelephonyManager.NETWORK_TYPE_LTE: - mDataIconList = TelephonyIcons.DATA_4G[mInetCondition]; - mDataTypeIconId = R.drawable.stat_sys_data_connected_4g; - mContentDescriptionDataType = mContext.getString( - R.string.accessibility_data_connection_4g); - break; - default: - if (!mShowAtLeastThreeGees) { - mDataIconList = TelephonyIcons.DATA_G[mInetCondition]; - mDataTypeIconId = R.drawable.stat_sys_data_connected_g; - mContentDescriptionDataType = mContext.getString( - R.string.accessibility_data_connection_gprs); - } else { - mDataIconList = TelephonyIcons.DATA_3G[mInetCondition]; - mDataTypeIconId = R.drawable.stat_sys_data_connected_3g; + break; + case TelephonyManager.NETWORK_TYPE_LTE: + mDataIconList = TelephonyIcons.DATA_4G[mInetCondition]; + mDataTypeIconId = R.drawable.stat_sys_data_connected_4g; mContentDescriptionDataType = mContext.getString( - R.string.accessibility_data_connection_3g); - } - break; + R.string.accessibility_data_connection_4g); + break; + default: + if (!mShowAtLeastThreeGees) { + mDataIconList = TelephonyIcons.DATA_G[mInetCondition]; + mDataTypeIconId = R.drawable.stat_sys_data_connected_g; + mContentDescriptionDataType = mContext.getString( + R.string.accessibility_data_connection_gprs); + } else { + mDataIconList = TelephonyIcons.DATA_3G[mInetCondition]; + mDataTypeIconId = R.drawable.stat_sys_data_connected_3g; + mContentDescriptionDataType = mContext.getString( + R.string.accessibility_data_connection_3g); + } + break; + } } + if ((isCdma() && isCdmaEri()) || mPhone.isNetworkRoaming()) { mDataTypeIconId = R.drawable.stat_sys_data_connected_roam; } @@ -763,8 +790,7 @@ public class NetworkController extends BroadcastReceiver { } - // ===== Wimax =================================================================== - + // ===== Wimax =================================================================== private final void updateWimaxState(Intent intent) { final String action = intent.getAction(); boolean wasConnected = mWimaxConnected; @@ -772,42 +798,41 @@ public class NetworkController extends BroadcastReceiver { int wimaxStatus = intent.getIntExtra(WimaxManagerConstants.EXTRA_4G_STATE, WimaxManagerConstants.NET_4G_STATE_UNKNOWN); mIsWimaxEnabled = (wimaxStatus == - WimaxManagerConstants.NET_4G_STATE_ENABLED)? true : false; + WimaxManagerConstants.NET_4G_STATE_ENABLED); } else if (action.equals(WimaxManagerConstants.SIGNAL_LEVEL_CHANGED_ACTION)) { mWimaxSignal = intent.getIntExtra(WimaxManagerConstants.EXTRA_NEW_SIGNAL_LEVEL, 0); } else if (action.equals(WimaxManagerConstants.WIMAX_NETWORK_STATE_CHANGED_ACTION)) { - mWimaxState = intent.getIntExtra(WimaxManagerConstants.EXTRA_WIMAX_STATE, + mWimaxState = intent.getIntExtra(WimaxManagerConstants.EXTRA_WIMAX_STATE, WimaxManagerConstants.NET_4G_STATE_UNKNOWN); mWimaxExtraState = intent.getIntExtra( WimaxManagerConstants.EXTRA_WIMAX_STATE_DETAIL, WimaxManagerConstants.NET_4G_STATE_UNKNOWN); mWimaxConnected = (mWimaxState == - WimaxManagerConstants.WIMAX_STATE_CONNECTED) ? true : false; - mWimaxIdle = (mWimaxExtraState == WimaxManagerConstants.WIMAX_IDLE)? true : false; + WimaxManagerConstants.WIMAX_STATE_CONNECTED); + mWimaxIdle = (mWimaxExtraState == WimaxManagerConstants.WIMAX_IDLE); } + updateDataNetType(); updateWimaxIcons(); } - private void updateWimaxIcons() { - Slog.d(TAG, "in .... updateWimaxIcons function : "+mIsWimaxEnabled); - if (mIsWimaxEnabled) { - if (mWimaxConnected) { - Slog.d(TAG, "in .... updateWimaxIcons function WiMAX COnnected"); - if (mWimaxIdle) - mWimaxIconId = WimaxIcons.WIMAX_IDLE; - else - mWimaxIconId = WimaxIcons.WIMAX_SIGNAL_STRENGTH[mInetCondition][mWimaxSignal]; - mContentDescriptionWimax = mContext.getString( - AccessibilityContentDescriptions.WIMAX_CONNECTION_STRENGTH[mWimaxSignal]); - } else { - Slog.d(TAG, "in .... updateWimaxIcons function WiMAX Disconnected"); - mWimaxIconId = WimaxIcons.WIMAX_DISCONNECTED; - mContentDescriptionWimax = mContext.getString(R.string.accessibility_no_wimax); - } - } else { - Slog.d(TAG, "in .... updateWimaxIcons function wimax icon id 0"); - mWimaxIconId = 0; - } + + private void updateWimaxIcons() { + if (mIsWimaxEnabled) { + if (mWimaxConnected) { + if (mWimaxIdle) + mWimaxIconId = WimaxIcons.WIMAX_IDLE; + else + mWimaxIconId = WimaxIcons.WIMAX_SIGNAL_STRENGTH[mInetCondition][mWimaxSignal]; + mContentDescriptionWimax = mContext.getString( + AccessibilityContentDescriptions.WIMAX_CONNECTION_STRENGTH[mWimaxSignal]); + } else { + mWimaxIconId = WimaxIcons.WIMAX_DISCONNECTED; + mContentDescriptionWimax = mContext.getString(R.string.accessibility_no_wimax); + } + } else { + mWimaxIconId = 0; } + } + // ===== Full or limited Internet connectivity ================================== private void updateConnectivity(Intent intent) { @@ -827,14 +852,14 @@ public class NetworkController extends BroadcastReceiver { mInetCondition = (connectionStatus > INET_CONDITION_THRESHOLD ? 1 : 0); if (info != null && info.getType() == ConnectivityManager.TYPE_BLUETOOTH) { - mBluetoothTethered = info.isConnected() ? true: false; + mBluetoothTethered = info.isConnected(); } else { mBluetoothTethered = false; } // We want to update all the icons, all at once, for any condition change updateDataNetType(); - updateWimaxIcons(); + updateWimaxIcons(); updateDataIcon(); updateTelephonySignalStrength(); updateWifiIcons(); @@ -921,7 +946,7 @@ public class NetworkController extends BroadcastReceiver { combinedSignalIconId = mDataSignalIconId; } - else if (!mDataConnected && !mWifiConnected && !mBluetoothTethered) { + else if (!mDataConnected && !mWifiConnected && !mBluetoothTethered && !mWimaxConnected) { // pretty much totally disconnected label = context.getString(R.string.status_bar_settings_signal_meter_disconnected); @@ -961,23 +986,12 @@ public class NetworkController extends BroadcastReceiver { if (mLastPhoneSignalIconId != mPhoneSignalIconId || mLastDataDirectionOverlayIconId != combinedActivityIconId || mLastWifiIconId != mWifiIconId + || mLastWimaxIconId != mWimaxIconId || mLastDataTypeIconId != mDataTypeIconId) { // NB: the mLast*s will be updated later for (SignalCluster cluster : mSignalClusters) { - cluster.setWifiIndicators( - mWifiConnected, // only show wifi in the cluster if connected - mWifiIconId, - mWifiActivityIconId, - mContentDescriptionWifi); - cluster.setMobileDataIndicators( - mHasMobileDataFeature, - mShowPhoneRSSIForData ? mPhoneSignalIconId : mDataSignalIconId, - mMobileActivityIconId, - mDataTypeIconId, - mContentDescriptionPhoneSignal, - mContentDescriptionDataType); - cluster.setIsAirplaneMode(mAirplaneMode); + refreshSignalCluster(cluster); } } @@ -1152,11 +1166,22 @@ public class NetworkController extends BroadcastReceiver { pw.println(mWifiLevel); pw.print(" mWifiSsid="); pw.println(mWifiSsid); - pw.print(String.format(" mWifiIconId=0x%08x/%s", + pw.println(String.format(" mWifiIconId=0x%08x/%s", mWifiIconId, getResourceName(mWifiIconId))); pw.print(" mWifiActivity="); pw.println(mWifiActivity); + if (mWimaxSupported) { + pw.println(" - wimax ------"); + pw.print(" mIsWimaxEnabled="); pw.println(mIsWimaxEnabled); + pw.print(" mWimaxConnected="); pw.println(mWimaxConnected); + pw.print(" mWimaxIdle="); pw.println(mWimaxIdle); + pw.println(String.format(" mWimaxIconId=0x%08x/%s", + mWimaxIconId, getResourceName(mWimaxIconId))); + pw.println(String.format(" mWimaxSignal=%d", mWimaxSignal)); + pw.println(String.format(" mWimaxState=%d", mWimaxState)); + pw.println(String.format(" mWimaxExtraState=%d", mWimaxExtraState)); + } pw.println(" - Bluetooth ----"); pw.print(" mBtReverseTethered="); @@ -1190,7 +1215,7 @@ public class NetworkController extends BroadcastReceiver { pw.print(" mLastDataTypeIconId=0x"); pw.print(Integer.toHexString(mLastDataTypeIconId)); pw.print("/"); - pw.println(getResourceName(mLastCombinedSignalIconId)); + pw.println(getResourceName(mLastDataTypeIconId)); pw.print(" mLastLabel="); pw.print(mLastLabel); pw.println(""); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WimaxIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WimaxIcons.java index 86054895e8af..d3d43387d8b7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WimaxIcons.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WimaxIcons.java @@ -1,5 +1,5 @@ /*
- * Copyright (C) 2008 The Android Open Source Project
+ * 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.
@@ -16,22 +16,13 @@ package com.android.systemui.statusbar.policy;
+import com.android.systemui.statusbar.policy.TelephonyIcons;
import com.android.systemui.R;
class WimaxIcons {
- static final int[][] WIMAX_SIGNAL_STRENGTH = {
- { R.drawable.stat_sys_data_wimax_signal_0,
- R.drawable.stat_sys_data_wimax_signal_1,
- R.drawable.stat_sys_data_wimax_signal_2,
- R.drawable.stat_sys_data_wimax_signal_3 },
- { R.drawable.stat_sys_data_wimax_signal_0_fully,
- R.drawable.stat_sys_data_wimax_signal_1_fully,
- R.drawable.stat_sys_data_wimax_signal_2_fully,
- R.drawable.stat_sys_data_wimax_signal_3_fully }
- };
+ static final int[][] WIMAX_SIGNAL_STRENGTH = TelephonyIcons.DATA_SIGNAL_STRENGTH;
- static final int WIMAX_DISCONNECTED =
- R.drawable.stat_sys_data_wimax_signal_disconnected;
- static final int WIMAX_IDLE = R.drawable.stat_sys_data_wimax_signal_idle;
- static final int WIFI_LEVEL_COUNT = WIMAX_SIGNAL_STRENGTH[0].length;
+ static final int WIMAX_DISCONNECTED = WIMAX_SIGNAL_STRENGTH[0][0];
+
+ static final int WIMAX_IDLE = WIMAX_DISCONNECTED; // XXX: unclear if we need a different icon
}
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java index ed9ba79f74d3..921f3313fb0f 100755 --- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java @@ -360,6 +360,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { int mResettingSystemUiFlags = 0; // Bits that we are currently always keeping cleared. int mForceClearedSystemUiFlags = 0; + // What we last reported to system UI about whether the compatibility + // menu needs to be displayed. + boolean mLastFocusNeedsMenu = false; FakeWindow mHideNavFakeWindow = null; @@ -370,8 +373,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { static final Rect mTmpNavigationFrame = new Rect(); WindowState mTopFullscreenOpaqueWindowState; - WindowState mTopAppWindowState; - WindowState mLastTopAppWindowState; boolean mTopIsFullscreen; boolean mForceStatusBar; boolean mHideLockScreen; @@ -2250,7 +2251,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { /** {@inheritDoc} */ public void beginAnimationLw(int displayWidth, int displayHeight) { mTopFullscreenOpaqueWindowState = null; - mTopAppWindowState = null; mForceStatusBar = false; mHideLockScreen = false; @@ -2288,12 +2288,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } } - if (mTopAppWindowState == null && win.isVisibleOrBehindKeyguardLw()) { - if (attrs.type >= FIRST_APPLICATION_WINDOW - && attrs.type <= LAST_APPLICATION_WINDOW) { - mTopAppWindowState = win; - } - } } /** {@inheritDoc} */ @@ -2349,35 +2343,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { mTopIsFullscreen = topIsFullscreen; - if (mTopAppWindowState != null && mTopAppWindowState != mLastTopAppWindowState) { - mLastTopAppWindowState = mTopAppWindowState; - - final boolean topNeedsMenu = (mTopAppWindowState.getAttrs().flags - & WindowManager.LayoutParams.FLAG_NEEDS_MENU_KEY) != 0; - - mHandler.post(new Runnable() { - public void run() { - if (mStatusBarService == null) { - // This is the one that can not go away, but it doesn't come up - // before the window manager does, so don't fail if it doesn't - // exist. This works as long as no fullscreen windows come up - // before the status bar service does. - mStatusBarService = IStatusBarService.Stub.asInterface( - ServiceManager.getService("statusbar")); - } - final IStatusBarService sbs = mStatusBarService; - if (mStatusBarService != null) { - try { - sbs.topAppWindowChanged(topNeedsMenu); - } catch (RemoteException e) { - // This should be impossible because we're in the same process. - mStatusBarService = null; - } - } - } - }); - } - // Hide the key guard if a visible window explicitly specifies that it wants to be displayed // when the screen is locked if (mKeyguard != null) { @@ -3711,10 +3676,13 @@ public class PhoneWindowManager implements WindowManagerPolicy { & ~mResettingSystemUiFlags & ~mForceClearedSystemUiFlags; int diff = visibility ^ mLastSystemUiFlags; - if (diff == 0) { + final boolean needsMenu = (mFocusedWindow.getAttrs().flags + & WindowManager.LayoutParams.FLAG_NEEDS_MENU_KEY) != 0; + if (diff == 0 && mLastFocusNeedsMenu == needsMenu) { return 0; } mLastSystemUiFlags = visibility; + mLastFocusNeedsMenu = needsMenu; mHandler.post(new Runnable() { public void run() { if (mStatusBarService == null) { @@ -3724,6 +3692,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (mStatusBarService != null) { try { mStatusBarService.setSystemUiVisibility(visibility); + mStatusBarService.topAppWindowChanged(needsMenu); } catch (RemoteException e) { // not much to be done mStatusBarService = null; @@ -3756,6 +3725,10 @@ public class PhoneWindowManager implements WindowManagerPolicy { pw.print(" mForceClearedSystemUiFlags=0x"); pw.println(Integer.toHexString(mForceClearedSystemUiFlags)); } + if (mLastFocusNeedsMenu) { + pw.print(prefix); pw.print("mLastFocusNeedsMenu="); + pw.println(mLastFocusNeedsMenu); + } pw.print(prefix); pw.print("mUiMode="); pw.print(mUiMode); pw.print(" mDockMode="); pw.print(mDockMode); pw.print(" mCarDockRotation="); pw.print(mCarDockRotation); diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java index fc870337579d..6e4aca778828 100644 --- a/services/java/com/android/server/ConnectivityService.java +++ b/services/java/com/android/server/ConnectivityService.java @@ -1597,6 +1597,7 @@ private NetworkStateTracker makeWimaxStateTracker() { if (checkType == prevNetType) continue; if (mNetConfigs[checkType] == null) continue; if (!mNetConfigs[checkType].isDefault()) continue; + if (mNetTrackers[checkType] == null) continue; // Enabling the isAvailable() optimization caused mobile to not get // selected if it was in the middle of error handling. Specifically diff --git a/services/java/com/android/server/net/NetworkStatsService.java b/services/java/com/android/server/net/NetworkStatsService.java index 77b0d96f4242..63655258fe5a 100644 --- a/services/java/com/android/server/net/NetworkStatsService.java +++ b/services/java/com/android/server/net/NetworkStatsService.java @@ -806,9 +806,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final NetworkStats networkDevSnapshot; try { // collect any tethering stats - final String[] tetheredIfacePairs = mConnManager.getTetheredIfacePairs(); - final NetworkStats tetherSnapshot = mNetworkManager.getNetworkStatsTethering( - tetheredIfacePairs); + final NetworkStats tetherSnapshot = getNetworkStatsTethering(); // record uid stats, folding in tethering stats uidSnapshot = mNetworkManager.getNetworkStatsUidDetail(UID_ALL); @@ -1505,7 +1503,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { NetworkStats before, NetworkStats current, boolean collectStale, String type) { if (before != null) { try { - return current.subtract(before); + return current.subtract(before, false); } catch (NonMonotonicException e) { Log.w(TAG, "found non-monotonic values; saving to dropbox"); @@ -1517,8 +1515,13 @@ public class NetworkStatsService extends INetworkStatsService.Stub { builder.append("right=").append(e.right).append('\n'); mDropBox.addText(TAG_NETSTATS_ERROR, builder.toString()); - // return empty delta to avoid recording broken stats - return new NetworkStats(0L, 10); + try { + // return clamped delta to help recover + return current.subtract(before, true); + } catch (NonMonotonicException e1) { + Log.wtf(TAG, "found non-monotonic values; returning empty delta", e1); + return new NetworkStats(0L, 10); + } } } else if (collectStale) { // caller is okay collecting stale stats for first call. @@ -1530,6 +1533,20 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } } + /** + * Return snapshot of current tethering statistics. Will return empty + * {@link NetworkStats} if any problems are encountered. + */ + private NetworkStats getNetworkStatsTethering() throws RemoteException { + try { + final String[] tetheredIfacePairs = mConnManager.getTetheredIfacePairs(); + return mNetworkManager.getNetworkStatsTethering(tetheredIfacePairs); + } catch (IllegalStateException e) { + Log.wtf(TAG, "problem reading network stats", e); + return new NetworkStats(0L, 10); + } + } + private static NetworkStats computeNetworkXtSnapshotFromUid(NetworkStats uidSnapshot) { return uidSnapshot.groupedByIface(); } |