summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/current.txt28
-rw-r--r--core/java/android/app/Activity.java2
-rw-r--r--core/java/android/app/BackStackRecord.java29
-rw-r--r--core/java/android/app/Fragment.java40
-rw-r--r--core/java/android/app/FragmentManager.java29
-rw-r--r--core/java/android/app/backup/BackupAgent.java3
-rw-r--r--core/java/android/net/ConnectivityManager.java10
-rw-r--r--core/java/android/provider/ContactsContract.java110
-rw-r--r--core/java/android/service/wallpaper/WallpaperService.java63
-rw-r--r--core/java/android/speech/tts/AudioPlaybackHandler.java53
-rw-r--r--core/java/android/speech/tts/PlaybackSynthesisCallback.java35
-rw-r--r--core/java/android/speech/tts/SynthesisMessageParams.java75
-rw-r--r--core/java/android/text/StaticLayout.java24
-rw-r--r--core/java/android/text/TextLine.java19
-rw-r--r--core/java/android/text/TextPaint.java51
-rw-r--r--core/java/android/text/TextUtils.java7
-rw-r--r--core/java/android/text/style/EasyEditSpan.java54
-rw-r--r--core/java/android/text/style/SuggestionSpan.java67
-rw-r--r--core/java/android/view/Surface.java14
-rw-r--r--core/java/android/view/inputmethod/InputMethodManager.java8
-rw-r--r--core/java/android/view/textservice/TextServicesManager.java20
-rw-r--r--core/java/android/webkit/HTML5VideoInline.java6
-rw-r--r--core/java/android/webkit/WebView.java4
-rw-r--r--core/java/android/widget/SpellChecker.java2
-rw-r--r--core/java/android/widget/TextView.java419
-rw-r--r--core/java/com/android/internal/widget/TransportControlView.java367
-rw-r--r--core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java191
-rw-r--r--core/jni/android_util_Binder.cpp38
-rw-r--r--core/jni/android_view_Surface.cpp4
-rw-r--r--core/res/AndroidManifest.xml3
-rw-r--r--core/res/res/drawable-hdpi/ab_bottom_solid_dark_holo.9.pngbin209 -> 144 bytes
-rw-r--r--core/res/res/drawable-hdpi/ab_bottom_solid_inverse_holo.9.pngbin241 -> 138 bytes
-rw-r--r--core/res/res/drawable-hdpi/ab_bottom_solid_light_holo.9.pngbin248 -> 144 bytes
-rw-r--r--core/res/res/drawable-hdpi/ab_bottom_transparent_dark_holo.9.pngbin209 -> 135 bytes
-rw-r--r--core/res/res/drawable-hdpi/ab_bottom_transparent_light_holo.9.pngbin208 -> 134 bytes
-rw-r--r--core/res/res/drawable-hdpi/ab_solid_dark_holo.9.pngbin229 -> 146 bytes
-rw-r--r--core/res/res/drawable-hdpi/ab_solid_light_holo.9.pngbin225 -> 145 bytes
-rw-r--r--core/res/res/drawable-hdpi/ab_solid_shadow_holo.9.pngbin200 -> 192 bytes
-rw-r--r--core/res/res/drawable-hdpi/ab_stacked_solid_dark_holo.9.pngbin223 -> 146 bytes
-rw-r--r--core/res/res/drawable-hdpi/ab_stacked_solid_inverse_holo.9.pngbin221 -> 146 bytes
-rw-r--r--core/res/res/drawable-hdpi/ab_stacked_solid_light_holo.9.pngbin228 -> 146 bytes
-rw-r--r--core/res/res/drawable-hdpi/ab_stacked_transparent_dark_holo.9.pngbin217 -> 139 bytes
-rw-r--r--core/res/res/drawable-hdpi/ab_stacked_transparent_light_holo.9.pngbin208 -> 133 bytes
-rw-r--r--core/res/res/drawable-hdpi/ab_transparent_dark_holo.9.pngbin230 -> 155 bytes
-rw-r--r--core/res/res/drawable-hdpi/ab_transparent_light_holo.9.pngbin213 -> 145 bytes
-rw-r--r--core/res/res/drawable-hdpi/btn_cab_done_default_holo_dark.9.pngbin275 -> 175 bytes
-rw-r--r--core/res/res/drawable-hdpi/btn_cab_done_default_holo_light.9.pngbin260 -> 170 bytes
-rw-r--r--core/res/res/drawable-hdpi/btn_cab_done_focused_holo_dark.9.pngbin273 -> 174 bytes
-rw-r--r--core/res/res/drawable-hdpi/btn_cab_done_focused_holo_light.9.pngbin263 -> 180 bytes
-rw-r--r--core/res/res/drawable-hdpi/btn_cab_done_pressed_holo_dark.9.pngbin273 -> 174 bytes
-rw-r--r--core/res/res/drawable-hdpi/btn_cab_done_pressed_holo_light.9.pngbin260 -> 178 bytes
-rw-r--r--core/res/res/drawable-hdpi/cab_background_bottom_holo_dark.9.pngbin239 -> 149 bytes
-rw-r--r--core/res/res/drawable-hdpi/cab_background_bottom_holo_light.9.pngbin244 -> 145 bytes
-rw-r--r--core/res/res/drawable-hdpi/cab_background_top_holo_dark.9.pngbin241 -> 147 bytes
-rw-r--r--core/res/res/drawable-hdpi/cab_background_top_holo_light.9.pngbin241 -> 147 bytes
-rw-r--r--core/res/res/drawable-hdpi/ic_lockscreen_player_background.9.pngbin0 -> 243 bytes
-rw-r--r--core/res/res/drawable-hdpi/ic_media_embed_play.pngbin1112 -> 5320 bytes
-rw-r--r--core/res/res/drawable-hdpi/ic_menu_moreoverflow_normal_holo_dark.pngbin344 -> 145 bytes
-rw-r--r--core/res/res/drawable-hdpi/ic_menu_moreoverflow_normal_holo_light.pngbin338 -> 147 bytes
-rw-r--r--core/res/res/drawable-mdpi/ab_bottom_solid_dark_holo.9.pngbin176 -> 134 bytes
-rw-r--r--core/res/res/drawable-mdpi/ab_bottom_solid_inverse_holo.9.pngbin214 -> 129 bytes
-rw-r--r--core/res/res/drawable-mdpi/ab_bottom_solid_light_holo.9.pngbin217 -> 134 bytes
-rw-r--r--core/res/res/drawable-mdpi/ab_bottom_transparent_dark_holo.9.pngbin176 -> 123 bytes
-rw-r--r--core/res/res/drawable-mdpi/ab_bottom_transparent_light_holo.9.pngbin173 -> 123 bytes
-rw-r--r--core/res/res/drawable-mdpi/ab_solid_dark_holo.9.pngbin183 -> 133 bytes
-rw-r--r--core/res/res/drawable-mdpi/ab_solid_light_holo.9.pngbin183 -> 133 bytes
-rw-r--r--core/res/res/drawable-mdpi/ab_solid_shadow_holo.9.pngbin175 -> 168 bytes
-rw-r--r--core/res/res/drawable-mdpi/ab_stacked_solid_dark_holo.9.pngbin184 -> 134 bytes
-rw-r--r--core/res/res/drawable-mdpi/ab_stacked_solid_inverse_holo.9.pngbin182 -> 133 bytes
-rw-r--r--core/res/res/drawable-mdpi/ab_stacked_solid_light_holo.9.pngbin183 -> 133 bytes
-rw-r--r--core/res/res/drawable-mdpi/ab_stacked_transparent_dark_holo.9.pngbin183 -> 127 bytes
-rw-r--r--core/res/res/drawable-mdpi/ab_stacked_transparent_light_holo.9.pngbin169 -> 123 bytes
-rw-r--r--core/res/res/drawable-mdpi/ab_transparent_dark_holo.9.pngbin192 -> 139 bytes
-rw-r--r--core/res/res/drawable-mdpi/ab_transparent_light_holo.9.pngbin180 -> 133 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_cab_done_default_holo_dark.9.pngbin242 -> 153 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_cab_done_default_holo_light.9.pngbin228 -> 151 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_cab_done_focused_holo_dark.9.pngbin241 -> 156 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_cab_done_focused_holo_light.9.pngbin236 -> 159 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_cab_done_pressed_holo_dark.9.pngbin240 -> 153 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_cab_done_pressed_holo_light.9.pngbin233 -> 155 bytes
-rw-r--r--core/res/res/drawable-mdpi/cab_background_bottom_holo_dark.9.pngbin199 -> 127 bytes
-rw-r--r--core/res/res/drawable-mdpi/cab_background_bottom_holo_light.9.pngbin203 -> 124 bytes
-rw-r--r--core/res/res/drawable-mdpi/cab_background_top_holo_dark.9.pngbin199 -> 130 bytes
-rw-r--r--core/res/res/drawable-mdpi/cab_background_top_holo_light.9.pngbin195 -> 128 bytes
-rw-r--r--core/res/res/drawable-mdpi/ic_lockscreen_player_background.9.pngbin0 -> 230 bytes
-rw-r--r--core/res/res/drawable-mdpi/ic_media_embed_play.pngbin934 -> 3159 bytes
-rw-r--r--core/res/res/drawable-mdpi/ic_media_ff.pngbin929 -> 1410 bytes
-rw-r--r--core/res/res/drawable-mdpi/ic_media_fullscreen.pngbin1396 -> 2125 bytes
-rw-r--r--core/res/res/drawable-mdpi/ic_media_next.pngbin864 -> 1211 bytes
-rw-r--r--core/res/res/drawable-mdpi/ic_media_pause.pngbin561 -> 1065 bytes
-rw-r--r--core/res/res/drawable-mdpi/ic_media_play.pngbin918 -> 1360 bytes
-rw-r--r--core/res/res/drawable-mdpi/ic_media_previous.pngbin858 -> 1211 bytes
-rw-r--r--core/res/res/drawable-mdpi/ic_media_rew.pngbin997 -> 1410 bytes
-rw-r--r--core/res/res/drawable-mdpi/ic_menu_moreoverflow_normal_holo_dark.pngbin321 -> 123 bytes
-rw-r--r--core/res/res/drawable-mdpi/ic_menu_moreoverflow_normal_holo_light.pngbin320 -> 127 bytes
-rw-r--r--core/res/res/drawable-xhdpi/ab_bottom_solid_dark_holo.9.pngbin226 -> 165 bytes
-rw-r--r--core/res/res/drawable-xhdpi/ab_bottom_solid_inverse_holo.9.pngbin268 -> 157 bytes
-rw-r--r--core/res/res/drawable-xhdpi/ab_bottom_solid_light_holo.9.pngbin270 -> 166 bytes
-rw-r--r--core/res/res/drawable-xhdpi/ab_bottom_transparent_dark_holo.9.pngbin226 -> 153 bytes
-rw-r--r--core/res/res/drawable-xhdpi/ab_bottom_transparent_light_holo.9.pngbin223 -> 152 bytes
-rw-r--r--core/res/res/drawable-xhdpi/ab_solid_dark_holo.9.pngbin244 -> 163 bytes
-rw-r--r--core/res/res/drawable-xhdpi/ab_solid_light_holo.9.pngbin243 -> 163 bytes
-rw-r--r--core/res/res/drawable-xhdpi/ab_solid_shadow_holo.9.pngbin220 -> 290 bytes
-rw-r--r--core/res/res/drawable-xhdpi/ab_stacked_solid_dark_holo.9.pngbin245 -> 163 bytes
-rw-r--r--core/res/res/drawable-xhdpi/ab_stacked_solid_inverse_holo.9.pngbin242 -> 163 bytes
-rw-r--r--core/res/res/drawable-xhdpi/ab_stacked_solid_light_holo.9.pngbin243 -> 163 bytes
-rw-r--r--core/res/res/drawable-xhdpi/ab_stacked_transparent_dark_holo.9.pngbin236 -> 158 bytes
-rw-r--r--core/res/res/drawable-xhdpi/ab_stacked_transparent_light_holo.9.pngbin229 -> 152 bytes
-rw-r--r--core/res/res/drawable-xhdpi/ab_transparent_dark_holo.9.pngbin243 -> 171 bytes
-rw-r--r--core/res/res/drawable-xhdpi/ab_transparent_light_holo.9.pngbin232 -> 160 bytes
-rw-r--r--core/res/res/drawable-xhdpi/btn_cab_done_default_holo_dark.9.pngbin333 -> 211 bytes
-rw-r--r--core/res/res/drawable-xhdpi/btn_cab_done_default_holo_light.9.pngbin312 -> 207 bytes
-rw-r--r--core/res/res/drawable-xhdpi/btn_cab_done_focused_holo_dark.9.pngbin333 -> 222 bytes
-rw-r--r--core/res/res/drawable-xhdpi/btn_cab_done_focused_holo_light.9.pngbin322 -> 214 bytes
-rw-r--r--core/res/res/drawable-xhdpi/btn_cab_done_pressed_holo_dark.9.pngbin328 -> 211 bytes
-rw-r--r--core/res/res/drawable-xhdpi/btn_cab_done_pressed_holo_light.9.pngbin321 -> 215 bytes
-rw-r--r--core/res/res/drawable-xhdpi/cab_background_bottom_holo_dark.9.pngbin260 -> 166 bytes
-rw-r--r--core/res/res/drawable-xhdpi/cab_background_bottom_holo_light.9.pngbin264 -> 161 bytes
-rw-r--r--core/res/res/drawable-xhdpi/cab_background_top_holo_dark.9.pngbin258 -> 174 bytes
-rw-r--r--core/res/res/drawable-xhdpi/cab_background_top_holo_light.9.pngbin257 -> 161 bytes
-rw-r--r--core/res/res/drawable-xhdpi/ic_lockscreen_player_background.9.pngbin0 -> 245 bytes
-rw-r--r--core/res/res/drawable-xhdpi/ic_menu_moreoverflow_normal_holo_dark.pngbin386 -> 166 bytes
-rw-r--r--core/res/res/drawable-xhdpi/ic_menu_moreoverflow_normal_holo_light.pngbin370 -> 179 bytes
-rw-r--r--core/res/res/layout-sw600dp/keyguard_screen_status_land.xml3
-rw-r--r--core/res/res/layout-sw600dp/keyguard_screen_status_port.xml3
-rw-r--r--core/res/res/layout/keyguard_screen_password_landscape.xml2
-rw-r--r--core/res/res/layout/keyguard_screen_password_portrait.xml2
-rw-r--r--core/res/res/layout/keyguard_screen_tab_unlock.xml4
-rw-r--r--core/res/res/layout/keyguard_screen_tab_unlock_land.xml4
-rw-r--r--core/res/res/layout/keyguard_screen_unlock_landscape.xml2
-rw-r--r--core/res/res/layout/keyguard_screen_unlock_portrait.xml2
-rw-r--r--core/res/res/layout/keyguard_transport_control.xml131
-rw-r--r--core/res/res/values-land/arrays.xml44
-rw-r--r--core/res/res/values-sw600dp/colors.xml2
-rw-r--r--core/res/res/values/arrays.xml46
-rwxr-xr-xcore/res/res/values/attrs.xml21
-rwxr-xr-xcore/res/res/values/config.xml3
-rw-r--r--core/res/res/values/public.xml4
-rwxr-xr-xcore/res/res/values/strings.xml28
-rw-r--r--core/res/res/values/styles.xml7
-rw-r--r--core/res/res/values/themes.xml1
-rw-r--r--data/fonts/DroidSansFallback.ttfbin5300184 -> 3725920 bytes
-rw-r--r--data/fonts/DroidSansFallbackFull.ttfbin0 -> 5300184 bytes
-rw-r--r--data/fonts/fonts.mk8
-rw-r--r--docs/html/sdk/ndk/index.jd52
-rw-r--r--docs/html/sdk/sdk_toc.cs2
-rw-r--r--graphics/java/android/graphics/Paint.java2
-rw-r--r--graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java25
-rw-r--r--include/media/AudioSystem.h7
-rw-r--r--include/private/surfaceflinger/LayerState.h4
-rw-r--r--include/surfaceflinger/SurfaceComposerClient.h2
-rw-r--r--libs/gui/SurfaceComposerClient.cpp6
-rw-r--r--libs/gui/tests/Android.mk10
-rw-r--r--libs/hwui/FontRenderer.cpp4
-rw-r--r--media/java/android/media/AudioService.java48
-rw-r--r--media/java/android/media/MediaPlayer.java21
-rw-r--r--media/java/android/media/RemoteControlClient.java86
-rwxr-xr-xmedia/java/android/media/videoeditor/VideoEditorProfile.java2
-rw-r--r--media/libmedia/AudioSystem.cpp8
-rw-r--r--media/libmedia/AudioTrack.cpp4
-rw-r--r--media/libmediaplayerservice/nuplayer/StreamingSource.cpp2
-rw-r--r--media/libstagefright/AACExtractor.cpp33
-rw-r--r--media/libstagefright/AwesomePlayer.cpp3
-rw-r--r--media/libstagefright/mpeg2ts/ATSParser.cpp21
-rw-r--r--media/libstagefright/mpeg2ts/ATSParser.h12
-rw-r--r--media/tests/MediaDump/src/com/android/mediadump/VideoDumpView.java5
-rw-r--r--packages/SystemUI/res/layout/status_bar.xml1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodsPanel.java2
-rw-r--r--policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java33
-rw-r--r--policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java25
-rw-r--r--policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java34
-rw-r--r--policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java52
-rw-r--r--policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java3
-rw-r--r--services/audioflinger/AudioFlinger.cpp20
-rw-r--r--services/audioflinger/AudioFlinger.h6
-rw-r--r--services/input/EventHub.cpp5
-rw-r--r--services/java/com/android/server/BackupManagerService.java50
-rw-r--r--services/java/com/android/server/ConnectivityService.java24
-rw-r--r--services/java/com/android/server/InputMethodManagerService.java17
-rwxr-xr-xservices/java/com/android/server/NotificationManagerService.java18
-rw-r--r--services/java/com/android/server/TextServicesManagerService.java13
-rw-r--r--services/java/com/android/server/net/NetworkPolicyManagerService.java6
-rw-r--r--services/java/com/android/server/net/NetworkStatsService.java4
-rw-r--r--services/java/com/android/server/wm/WindowManagerService.java18
-rw-r--r--services/surfaceflinger/Layer.cpp53
-rw-r--r--services/surfaceflinger/LayerBase.cpp18
-rw-r--r--services/surfaceflinger/LayerBase.h6
-rw-r--r--services/surfaceflinger/Transform.cpp12
-rw-r--r--services/surfaceflinger/Transform.h4
-rw-r--r--services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java6
-rw-r--r--services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java22
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java5
-rw-r--r--telephony/java/com/android/internal/telephony/IccCard.java20
-rwxr-xr-xtelephony/java/com/android/internal/telephony/cdma/sms/BearerData.java3
-rwxr-xr-xtelephony/java/com/android/internal/telephony/gsm/SIMRecords.java10
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/SimCard.java2
-rw-r--r--tests/BandwidthTests/Android.mk24
-rw-r--r--tests/BandwidthTests/AndroidManifest.xml31
-rw-r--r--tests/BandwidthTests/res/layout/main.xml29
-rw-r--r--tests/BandwidthTests/res/values/strings.xml21
-rw-r--r--tests/BandwidthTests/src/com/android/tests/bandwidthenforcement/BandwidthEnforcementTestActivity.java27
-rw-r--r--tests/BandwidthTests/src/com/android/tests/bandwidthenforcement/BandwidthEnforcementTestService.java210
-rw-r--r--voip/java/com/android/server/sip/SipSessionGroup.java26
-rw-r--r--wifi/java/android/net/wifi/WifiNative.java13
-rw-r--r--wifi/java/android/net/wifi/p2p/WifiP2pService.java89
206 files changed, 2665 insertions, 758 deletions
diff --git a/api/current.txt b/api/current.txt
index ef40053..c4256af 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -370,6 +370,7 @@ package android {
field public static final int dialogTitle = 16843250; // 0x10101f2
field public static final int digits = 16843110; // 0x1010166
field public static final int direction = 16843217; // 0x10101d1
+ field public static final int directionDescriptions = 16843695; // 0x10103af
field public static final int directionPriority = 16843218; // 0x10101d2
field public static final int disableDependentsState = 16843249; // 0x10101f1
field public static final int disabledAlpha = 16842803; // 0x1010033
@@ -938,6 +939,7 @@ package android {
field public static final int tag = 16842961; // 0x10100d1
field public static final int targetActivity = 16843266; // 0x1010202
field public static final int targetClass = 16842799; // 0x101002f
+ field public static final int targetDescriptions = 16843694; // 0x10103ae
field public static final int targetDrawables = 16843654; // 0x1010386
field public static final int targetPackage = 16842785; // 0x1010021
field public static final int targetSdkVersion = 16843376; // 0x1010270
@@ -3277,6 +3279,7 @@ package android.app {
method public void setArguments(android.os.Bundle);
method public void setHasOptionsMenu(boolean);
method public void setInitialSavedState(android.app.Fragment.SavedState);
+ method public void setMenuVisibility(boolean);
method public void setRetainInstance(boolean);
method public void setTargetFragment(android.app.Fragment, int);
method public void startActivity(android.content.Intent);
@@ -3342,6 +3345,7 @@ package android.app {
method public abstract java.lang.CharSequence getBreadCrumbTitle();
method public abstract int getBreadCrumbTitleRes();
method public abstract int getId();
+ method public abstract java.lang.String getName();
}
public static abstract interface FragmentManager.OnBackStackChangedListener {
@@ -4040,6 +4044,7 @@ package android.app.backup {
public abstract class BackupAgent extends android.content.ContextWrapper {
ctor public BackupAgent();
+ method public final void fullBackupFile(java.io.File, android.app.backup.FullBackupDataOutput);
method public abstract void onBackup(android.os.ParcelFileDescriptor, android.app.backup.BackupDataOutput, android.os.ParcelFileDescriptor) throws java.io.IOException;
method public void onCreate();
method public void onDestroy();
@@ -10676,6 +10681,7 @@ package android.media {
method public void setOnVideoSizeChangedListener(android.media.MediaPlayer.OnVideoSizeChangedListener);
method public void setScreenOnWhilePlaying(boolean);
method public void setTexture(android.graphics.SurfaceTexture);
+ method public void setSurface(android.view.Surface);
method public void setVolume(float, float);
method public void setWakeMode(android.content.Context, int);
method public void start() throws java.lang.IllegalStateException;
@@ -16052,7 +16058,7 @@ package android.provider {
public final class ContactsContract {
ctor public ContactsContract();
- field public static final java.lang.String ALLOW_PROFILE = "allow_profile";
+ method public static boolean isProfileId(long);
field public static final java.lang.String AUTHORITY = "com.android.contacts";
field public static final android.net.Uri AUTHORITY_URI;
field public static final java.lang.String CALLER_IS_SYNCADAPTER = "caller_is_syncadapter";
@@ -16579,6 +16585,16 @@ package android.provider {
field public static final android.net.Uri CONTENT_RAW_CONTACTS_URI;
field public static final android.net.Uri CONTENT_URI;
field public static final android.net.Uri CONTENT_VCARD_URI;
+ field public static final long MIN_ID = 9223372034707292160L; // 0x7fffffff80000000L
+ }
+
+ public static final class ContactsContract.ProfileSyncState implements android.provider.SyncStateContract.Columns {
+ method public static byte[] get(android.content.ContentProviderClient, android.accounts.Account) throws android.os.RemoteException;
+ method public static android.util.Pair<android.net.Uri, byte[]> getWithUri(android.content.ContentProviderClient, android.accounts.Account) throws android.os.RemoteException;
+ method public static android.content.ContentProviderOperation newSetOperation(android.accounts.Account, byte[]);
+ method public static void set(android.content.ContentProviderClient, android.accounts.Account, byte[]) throws android.os.RemoteException;
+ field public static final java.lang.String CONTENT_DIRECTORY = "syncstate";
+ field public static final android.net.Uri CONTENT_URI;
}
public static final class ContactsContract.QuickContact {
@@ -16677,6 +16693,7 @@ package android.provider {
field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/status-update";
field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/status-update";
field public static final android.net.Uri CONTENT_URI;
+ field public static final android.net.Uri PROFILE_CONTENT_URI;
}
public static final class ContactsContract.StreamItemPhotos implements android.provider.BaseColumns android.provider.ContactsContract.StreamItemPhotosColumns {
@@ -20672,6 +20689,14 @@ package android.text.style {
field protected final int mVerticalAlignment;
}
+ public class EasyEditSpan implements android.text.ParcelableSpan {
+ ctor public EasyEditSpan();
+ ctor public EasyEditSpan(android.os.Parcel);
+ method public int describeContents();
+ method public int getSpanTypeId();
+ method public void writeToParcel(android.os.Parcel, int);
+ }
+
public class ForegroundColorSpan extends android.text.style.CharacterStyle implements android.text.ParcelableSpan android.text.style.UpdateAppearance {
ctor public ForegroundColorSpan(int);
ctor public ForegroundColorSpan(android.os.Parcel);
@@ -22509,6 +22534,7 @@ package android.view {
}
public class Surface implements android.os.Parcelable {
+ ctor public Surface(android.graphics.SurfaceTexture);
method public int describeContents();
method public boolean isValid();
method public android.graphics.Canvas lockCanvas(android.graphics.Rect) throws java.lang.IllegalArgumentException, android.view.Surface.OutOfResourcesException;
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 1271ddd..0e3eaaa 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -4206,7 +4206,6 @@ public class Activity extends ContextThemeWrapper
fragment.mContainerId = containerId;
fragment.mTag = tag;
fragment.mInLayout = true;
- fragment.mImmediateActivity = this;
fragment.mFragmentManager = mFragments;
fragment.onInflate(this, attrs, fragment.mSavedFragmentState);
mFragments.addFragment(fragment, true);
@@ -4222,7 +4221,6 @@ public class Activity extends ContextThemeWrapper
// This fragment was retained from a previous instance; get it
// going now.
fragment.mInLayout = true;
- fragment.mImmediateActivity = this;
// If this fragment is newly instantiated (either right now, or
// from last saved state), then give it the attributes to
// initialize itself.
diff --git a/core/java/android/app/BackStackRecord.java b/core/java/android/app/BackStackRecord.java
index 93330a7..e9e8e16 100644
--- a/core/java/android/app/BackStackRecord.java
+++ b/core/java/android/app/BackStackRecord.java
@@ -344,10 +344,6 @@ final class BackStackRecord extends FragmentTransaction implements
}
private void doAddOp(int containerViewId, Fragment fragment, String tag, int opcmd) {
- if (fragment.mImmediateActivity != null) {
- throw new IllegalStateException("Fragment already added: " + fragment);
- }
- fragment.mImmediateActivity = mManager.mActivity;
fragment.mFragmentManager = mManager;
if (tag != null) {
@@ -388,11 +384,6 @@ final class BackStackRecord extends FragmentTransaction implements
}
public FragmentTransaction remove(Fragment fragment) {
- if (fragment.mImmediateActivity == null) {
- throw new IllegalStateException("Fragment not added: " + fragment);
- }
- fragment.mImmediateActivity = null;
-
Op op = new Op();
op.cmd = OP_REMOVE;
op.fragment = fragment;
@@ -402,10 +393,6 @@ final class BackStackRecord extends FragmentTransaction implements
}
public FragmentTransaction hide(Fragment fragment) {
- if (fragment.mImmediateActivity == null) {
- throw new IllegalStateException("Fragment not added: " + fragment);
- }
-
Op op = new Op();
op.cmd = OP_HIDE;
op.fragment = fragment;
@@ -415,10 +402,6 @@ final class BackStackRecord extends FragmentTransaction implements
}
public FragmentTransaction show(Fragment fragment) {
- if (fragment.mImmediateActivity == null) {
- throw new IllegalStateException("Fragment not added: " + fragment);
- }
-
Op op = new Op();
op.cmd = OP_SHOW;
op.fragment = fragment;
@@ -428,10 +411,6 @@ final class BackStackRecord extends FragmentTransaction implements
}
public FragmentTransaction detach(Fragment fragment) {
- //if (fragment.mImmediateActivity == null) {
- // throw new IllegalStateException("Fragment not added: " + fragment);
- //}
-
Op op = new Op();
op.cmd = OP_DETACH;
op.fragment = fragment;
@@ -441,10 +420,6 @@ final class BackStackRecord extends FragmentTransaction implements
}
public FragmentTransaction attach(Fragment fragment) {
- //if (fragment.mImmediateActivity == null) {
- // throw new IllegalStateException("Fragment not added: " + fragment);
- //}
-
Op op = new Op();
op.cmd = OP_ATTACH;
op.fragment = fragment;
@@ -663,7 +638,6 @@ final class BackStackRecord extends FragmentTransaction implements
case OP_ADD: {
Fragment f = op.fragment;
f.mNextAnim = op.popExitAnim;
- f.mImmediateActivity = null;
mManager.removeFragment(f,
FragmentManagerImpl.reverseTransit(mTransition),
mTransitionStyle);
@@ -671,7 +645,6 @@ final class BackStackRecord extends FragmentTransaction implements
case OP_REPLACE: {
Fragment f = op.fragment;
f.mNextAnim = op.popExitAnim;
- f.mImmediateActivity = null;
mManager.removeFragment(f,
FragmentManagerImpl.reverseTransit(mTransition),
mTransitionStyle);
@@ -679,7 +652,6 @@ final class BackStackRecord extends FragmentTransaction implements
for (int i=0; i<op.removed.size(); i++) {
Fragment old = op.removed.get(i);
old.mNextAnim = op.popEnterAnim;
- f.mImmediateActivity = mManager.mActivity;
mManager.addFragment(old, false);
}
}
@@ -687,7 +659,6 @@ final class BackStackRecord extends FragmentTransaction implements
case OP_REMOVE: {
Fragment f = op.fragment;
f.mNextAnim = op.popEnterAnim;
- f.mImmediateActivity = mManager.mActivity;
mManager.addFragment(f, false);
} break;
case OP_HIDE: {
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index a8621f8..3a08e6d 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -402,10 +402,6 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
// from all transactions.
FragmentManager mFragmentManager;
- // Set as soon as a fragment is added to a transaction (or removed),
- // to be able to do validation.
- Activity mImmediateActivity;
-
// Activity this fragment is attached to.
Activity mActivity;
@@ -438,7 +434,10 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
// If set this fragment has menu items to contribute.
boolean mHasMenu;
-
+
+ // Set to true to allow the fragment's menu to be shown.
+ boolean mMenuVisible = true;
+
// Used to verify that subclasses call through to super class.
boolean mCalled;
@@ -888,7 +887,25 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
}
}
}
-
+
+ /**
+ * Set a hint for whether this fragment's menu should be visible. This
+ * is useful if you know that a fragment has been placed in your view
+ * hierarchy so that the user can not currently seen it, so any menu items
+ * it has should also not be shown.
+ *
+ * @param menuVisible The default is true, meaning the fragment's menu will
+ * be shown as usual. If false, the user will not see the menu.
+ */
+ public void setMenuVisibility(boolean menuVisible) {
+ if (mMenuVisible != menuVisible) {
+ mMenuVisible = menuVisible;
+ if (mHasMenu && isAdded() && !isHidden()) {
+ mFragmentManager.invalidateOptionsMenu();
+ }
+ }
+ }
+
/**
* Return the LoaderManager for this fragment, creating it if needed.
*/
@@ -1233,7 +1250,7 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
mRestored = false;
mBackStackNesting = 0;
mFragmentManager = null;
- mActivity = mImmediateActivity = null;
+ mActivity = null;
mFragmentId = 0;
mContainerId = 0;
mTag = null;
@@ -1421,17 +1438,14 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
writer.print(" mInLayout="); writer.println(mInLayout);
writer.print(prefix); writer.print("mHidden="); writer.print(mHidden);
writer.print(" mDetached="); writer.print(mDetached);
- writer.print(" mRetainInstance="); writer.print(mRetainInstance);
- writer.print(" mRetaining="); writer.print(mRetaining);
+ writer.print(" mMenuVisible="); writer.print(mMenuVisible);
writer.print(" mHasMenu="); writer.println(mHasMenu);
+ writer.print(prefix); writer.print("mRetainInstance="); writer.print(mRetainInstance);
+ writer.print(" mRetaining="); writer.println(mRetaining);
if (mFragmentManager != null) {
writer.print(prefix); writer.print("mFragmentManager=");
writer.println(mFragmentManager);
}
- if (mImmediateActivity != null) {
- writer.print(prefix); writer.print("mImmediateActivity=");
- writer.println(mImmediateActivity);
- }
if (mActivity != null) {
writer.print(prefix); writer.print("mActivity=");
writer.println(mActivity);
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index 70e6866..7a6759f 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -67,6 +67,13 @@ public abstract class FragmentManager {
public int getId();
/**
+ * Get the name that was supplied to
+ * {@link FragmentTransaction#addToBackStack(String)
+ * FragmentTransaction.addToBackStack(String)} when creating this entry.
+ */
+ public String getName();
+
+ /**
* Return the full bread crumb title resource identifier for the entry,
* or 0 if it does not have one.
*/
@@ -949,7 +956,6 @@ final class FragmentManagerImpl extends FragmentManager {
if (!f.mRetaining) {
makeInactive(f);
} else {
- f.mImmediateActivity = null;
f.mActivity = null;
f.mFragmentManager = null;
}
@@ -1037,7 +1043,7 @@ final class FragmentManagerImpl extends FragmentManager {
mAdded.add(fragment);
fragment.mAdded = true;
fragment.mRemoving = false;
- if (fragment.mHasMenu) {
+ if (fragment.mHasMenu && fragment.mMenuVisible) {
mNeedMenuInvalidate = true;
}
if (moveToStateNow) {
@@ -1051,7 +1057,7 @@ final class FragmentManagerImpl extends FragmentManager {
final boolean inactive = !fragment.isInBackStack();
if (!fragment.mDetached || inactive) {
mAdded.remove(fragment);
- if (fragment.mHasMenu) {
+ if (fragment.mHasMenu && fragment.mMenuVisible) {
mNeedMenuInvalidate = true;
}
fragment.mAdded = false;
@@ -1086,7 +1092,7 @@ final class FragmentManagerImpl extends FragmentManager {
fragment.mView.setVisibility(View.GONE);
}
}
- if (fragment.mAdded && fragment.mHasMenu) {
+ if (fragment.mAdded && fragment.mHasMenu && fragment.mMenuVisible) {
mNeedMenuInvalidate = true;
}
fragment.onHiddenChanged(true);
@@ -1106,7 +1112,7 @@ final class FragmentManagerImpl extends FragmentManager {
}
fragment.mView.setVisibility(View.VISIBLE);
}
- if (fragment.mAdded && fragment.mHasMenu) {
+ if (fragment.mAdded && fragment.mHasMenu && fragment.mMenuVisible) {
mNeedMenuInvalidate = true;
}
fragment.onHiddenChanged(false);
@@ -1120,7 +1126,7 @@ final class FragmentManagerImpl extends FragmentManager {
if (fragment.mAdded) {
// We are not already in back stack, so need to remove the fragment.
mAdded.remove(fragment);
- if (fragment.mHasMenu) {
+ if (fragment.mHasMenu && fragment.mMenuVisible) {
mNeedMenuInvalidate = true;
}
fragment.mAdded = false;
@@ -1136,7 +1142,7 @@ final class FragmentManagerImpl extends FragmentManager {
if (!fragment.mAdded) {
mAdded.add(fragment);
fragment.mAdded = true;
- if (fragment.mHasMenu) {
+ if (fragment.mHasMenu && fragment.mMenuVisible) {
mNeedMenuInvalidate = true;
}
moveToState(fragment, mCurState, transition, transitionStyle);
@@ -1640,7 +1646,6 @@ final class FragmentManagerImpl extends FragmentManager {
"No instantiated fragment for index #" + fms.mAdded[i]);
}
f.mAdded = true;
- f.mImmediateActivity = mActivity;
if (DEBUG) Log.v(TAG, "restoreAllState: making added #" + i + ": " + f);
mAdded.add(f);
}
@@ -1748,7 +1753,7 @@ final class FragmentManagerImpl extends FragmentManager {
if (mActive != null) {
for (int i=0; i<mAdded.size(); i++) {
Fragment f = mAdded.get(i);
- if (f != null && !f.mHidden && f.mHasMenu) {
+ if (f != null && !f.mHidden && f.mHasMenu && f.mMenuVisible) {
show = true;
f.onCreateOptionsMenu(menu, inflater);
if (newMenus == null) {
@@ -1778,7 +1783,7 @@ final class FragmentManagerImpl extends FragmentManager {
if (mActive != null) {
for (int i=0; i<mAdded.size(); i++) {
Fragment f = mAdded.get(i);
- if (f != null && !f.mHidden && f.mHasMenu) {
+ if (f != null && !f.mHidden && f.mHasMenu && f.mMenuVisible) {
show = true;
f.onPrepareOptionsMenu(menu);
}
@@ -1791,7 +1796,7 @@ final class FragmentManagerImpl extends FragmentManager {
if (mActive != null) {
for (int i=0; i<mAdded.size(); i++) {
Fragment f = mAdded.get(i);
- if (f != null && !f.mHidden && f.mHasMenu) {
+ if (f != null && !f.mHidden && f.mHasMenu && f.mMenuVisible) {
if (f.onOptionsItemSelected(item)) {
return true;
}
@@ -1819,7 +1824,7 @@ final class FragmentManagerImpl extends FragmentManager {
if (mActive != null) {
for (int i=0; i<mAdded.size(); i++) {
Fragment f = mAdded.get(i);
- if (f != null && !f.mHidden && f.mHasMenu) {
+ if (f != null && !f.mHidden && f.mHasMenu && f.mMenuVisible) {
f.onOptionsMenuClosed(menu);
}
}
diff --git a/core/java/android/app/backup/BackupAgent.java b/core/java/android/app/backup/BackupAgent.java
index 58ea0c3..9542874 100644
--- a/core/java/android/app/backup/BackupAgent.java
+++ b/core/java/android/app/backup/BackupAgent.java
@@ -255,10 +255,7 @@ public abstract class BackupAgent extends ContextWrapper {
* will be delivered to the backup destination along with the metadata necessary
* to place it with the proper location and permissions on the device where the
* data is restored.
- * @hide
*
- * @param context The BackupAgent that is calling this method. It is an error to
- * call it from something other than a running BackupAgent instance.
* @param file The file to be backed up. The file must exist and be readable by
* the caller.
* @param output The destination to which the backed-up file data will be sent.
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 9c96883..3441217 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -23,6 +23,7 @@ import android.annotation.SdkConstant.SdkConstantType;
import android.os.Binder;
import android.os.Build.VERSION_CODES;
import android.os.RemoteException;
+import android.provider.Settings;
import java.net.InetAddress;
@@ -71,6 +72,15 @@ public class ConnectivityManager {
public static final String CONNECTIVITY_ACTION = "android.net.conn.CONNECTIVITY_CHANGE";
/**
+ * Identical to {@link #CONNECTIVITY_ACTION} broadcast, but sent without any
+ * applicable {@link Settings.Secure#CONNECTIVITY_CHANGE_DELAY}.
+ *
+ * @hide
+ */
+ public static final String CONNECTIVITY_ACTION_IMMEDIATE =
+ "android.net.conn.CONNECTIVITY_CHANGE_IMMEDIATE";
+
+ /**
* The lookup key for a {@link NetworkInfo} object. Retrieve with
* {@link android.content.Intent#getParcelableExtra(String)}.
*
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index 5321c6a..1f2b342 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -125,19 +125,6 @@ public final class ContactsContract {
public static final String CALLER_IS_SYNCADAPTER = "caller_is_syncadapter";
/**
- * An optional URI parameter for selection queries that instructs the
- * provider to allow the user's personal profile contact entry (if any)
- * to appear in a list of contact results. It is only useful when issuing
- * a query that may retrieve more than one contact. If present, the user's
- * profile will always be the first entry returned. The default value is
- * false.
- *
- * Specifying this parameter will result in a security error if the calling
- * application does not have android.permission.READ_PROFILE permission.
- */
- public static final String ALLOW_PROFILE = "allow_profile";
-
- /**
* Query parameter that should be used by the client to access a specific
* {@link Directory}. The parameter value should be the _ID of the corresponding
* directory, e.g.
@@ -557,7 +544,7 @@ public final class ContactsContract {
}
/**
- * A table provided for sync adapters to use for storing private sync state data.
+ * A table provided for sync adapters to use for storing private sync state data for contacts.
*
* @see SyncStateContract
*/
@@ -608,6 +595,60 @@ public final class ContactsContract {
}
}
+
+ /**
+ * A table provided for sync adapters to use for storing private sync state data for the
+ * user's personal profile.
+ *
+ * @see SyncStateContract
+ */
+ public static final class ProfileSyncState implements SyncStateContract.Columns {
+ /**
+ * This utility class cannot be instantiated
+ */
+ private ProfileSyncState() {}
+
+ public static final String CONTENT_DIRECTORY =
+ SyncStateContract.Constants.CONTENT_DIRECTORY;
+
+ /**
+ * The content:// style URI for this table
+ */
+ public static final Uri CONTENT_URI =
+ Uri.withAppendedPath(Profile.CONTENT_URI, CONTENT_DIRECTORY);
+
+ /**
+ * @see android.provider.SyncStateContract.Helpers#get
+ */
+ public static byte[] get(ContentProviderClient provider, Account account)
+ throws RemoteException {
+ return SyncStateContract.Helpers.get(provider, CONTENT_URI, account);
+ }
+
+ /**
+ * @see android.provider.SyncStateContract.Helpers#get
+ */
+ public static Pair<Uri, byte[]> getWithUri(ContentProviderClient provider, Account account)
+ throws RemoteException {
+ return SyncStateContract.Helpers.getWithUri(provider, CONTENT_URI, account);
+ }
+
+ /**
+ * @see android.provider.SyncStateContract.Helpers#set
+ */
+ public static void set(ContentProviderClient provider, Account account, byte[] data)
+ throws RemoteException {
+ SyncStateContract.Helpers.set(provider, CONTENT_URI, account, data);
+ }
+
+ /**
+ * @see android.provider.SyncStateContract.Helpers#newSetOperation
+ */
+ public static ContentProviderOperation newSetOperation(Account account, byte[] data) {
+ return SyncStateContract.Helpers.newSetOperation(CONTENT_URI, account, data);
+ }
+ }
+
/**
* Generic columns for use by sync adapters. The specific functions of
* these columns are private to the sync adapter. Other clients of the API
@@ -1875,8 +1916,8 @@ public final class ContactsContract {
* Constants for the user's profile data, which is represented as a single contact on
* the device that represents the user. The profile contact is not aggregated
* together automatically in the same way that normal contacts are; instead, each
- * account on the device may contribute a single raw contact representing the user's
- * personal profile data from that source.
+ * account (including data set, if applicable) on the device may contribute a single
+ * raw contact representing the user's personal profile data from that source.
* </p>
* <p>
* Access to the profile entry through these URIs (or incidental access to parts of
@@ -1950,6 +1991,31 @@ public final class ContactsContract {
*/
public static final Uri CONTENT_RAW_CONTACTS_URI = Uri.withAppendedPath(CONTENT_URI,
"raw_contacts");
+
+ /**
+ * The minimum ID for any entity that belongs to the profile. This essentially
+ * defines an ID-space in which profile data is stored, and is used by the provider
+ * to determine whether a request via a non-profile-specific URI should be directed
+ * to the profile data rather than general contacts data, along with all the special
+ * permission checks that entails.
+ *
+ * Callers may use {@link #isProfileId} to check whether a specific ID falls into
+ * the set of data intended for the profile.
+ */
+ public static final long MIN_ID = Long.MAX_VALUE - (long) Integer.MAX_VALUE;
+ }
+
+ /**
+ * This method can be used to identify whether the given ID is associated with profile
+ * data. It does not necessarily indicate that the ID is tied to valid data, merely
+ * that accessing data using this ID will result in profile access checks and will only
+ * return data from the profile.
+ *
+ * @param id The ID to check.
+ * @return Whether the ID is associated with profile data.
+ */
+ public static boolean isProfileId(long id) {
+ return id >= Profile.MIN_ID;
}
protected interface RawContactsColumns {
@@ -4542,6 +4608,12 @@ public final class ContactsContract {
* either.
* </p>
* <p>
+ * Inserting or updating a status update for the user's profile requires either using
+ * the {@link #DATA_ID} to identify the data row to attach the update to, or
+ * {@link StatusUpdates#PROFILE_CONTENT_URI} to ensure that the change is scoped to the
+ * profile.
+ * </p>
+ * <p>
* You cannot use {@link ContentResolver#update} to change a status, but
* {@link ContentResolver#insert} will replace the latests status if it already
* exists.
@@ -4687,6 +4759,12 @@ public final class ContactsContract {
public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "status_updates");
/**
+ * The content:// style URI for this table, specific to the user's profile.
+ */
+ public static final Uri PROFILE_CONTENT_URI =
+ Uri.withAppendedPath(Profile.CONTENT_URI, "status_updates");
+
+ /**
* Gets the resource ID for the proper presence icon.
*
* @param status the status to get the icon for
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index 4c563ce..39f9367 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -139,6 +139,7 @@ public abstract class WallpaperService extends Service {
boolean mSurfaceCreated;
boolean mIsCreating;
boolean mDrawingAllowed;
+ boolean mOffsetsChanged;
int mWidth;
int mHeight;
int mFormat;
@@ -604,12 +605,15 @@ public abstract class WallpaperService extends Service {
if (DEBUG) Log.v(TAG, "Layout: Surface destroyed");
return;
}
-
+
+ boolean didSurface = false;
+
try {
mSurfaceHolder.ungetCallbacks();
if (surfaceCreating) {
mIsCreating = true;
+ didSurface = true;
if (DEBUG) Log.v(TAG, "onSurfaceCreated("
+ mSurfaceHolder + "): " + this);
onSurfaceCreated(mSurfaceHolder);
@@ -637,6 +641,7 @@ public abstract class WallpaperService extends Service {
+ mSurfaceHolder + ", " + mFormat
+ ", " + mCurWidth + ", " + mCurHeight
+ "): " + this);
+ didSurface = true;
onSurfaceChanged(mSurfaceHolder, mFormat,
mCurWidth, mCurHeight);
SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks();
@@ -661,6 +666,26 @@ public abstract class WallpaperService extends Service {
}
}
+ if (didSurface && !mReportedVisible) {
+ // This wallpaper is currently invisible, but its
+ // surface has changed. At this point let's tell it
+ // again that it is invisible in case the report about
+ // the surface caused it to start running. We really
+ // don't want wallpapers running when not visible.
+ if (mIsCreating) {
+ // Some wallpapers will ignore this call if they
+ // had previously been told they were invisble,
+ // so if we are creating a new surface then toggle
+ // the state to get them to notice.
+ if (DEBUG) Log.v(TAG, "onVisibilityChanged(true) at surface: "
+ + this);
+ onVisibilityChanged(true);
+ }
+ if (DEBUG) Log.v(TAG, "onVisibilityChanged(false) at surface: "
+ + this);
+ onVisibilityChanged(false);
+ }
+
} finally {
mIsCreating = false;
mSurfaceCreated = true;
@@ -701,6 +726,7 @@ public abstract class WallpaperService extends Service {
onCreate(mSurfaceHolder);
mInitializing = false;
+ mReportedVisible = false;
updateSurface(false, false, false);
}
@@ -711,7 +737,7 @@ public abstract class WallpaperService extends Service {
mIWallpaperEngine.mReqWidth = desiredWidth;
mIWallpaperEngine.mReqHeight = desiredHeight;
onDesiredSizeChanged(desiredWidth, desiredHeight);
- doOffsetsChanged();
+ doOffsetsChanged(true);
}
}
@@ -733,6 +759,7 @@ public abstract class WallpaperService extends Service {
// If becoming visible, in preview mode the surface
// may have been destroyed so now we need to make
// sure it is re-created.
+ doOffsetsChanged(false);
updateSurface(false, false, false);
}
onVisibilityChanged(visible);
@@ -740,11 +767,15 @@ public abstract class WallpaperService extends Service {
}
}
- void doOffsetsChanged() {
+ void doOffsetsChanged(boolean always) {
if (mDestroyed) {
return;
}
-
+
+ if (!always && !mOffsetsChanged) {
+ return;
+ }
+
float xOffset;
float yOffset;
float xOffsetStep;
@@ -759,15 +790,19 @@ public abstract class WallpaperService extends Service {
mPendingSync = false;
mOffsetMessageEnqueued = false;
}
-
+
if (mSurfaceCreated) {
- if (DEBUG) Log.v(TAG, "Offsets change in " + this
- + ": " + xOffset + "," + yOffset);
- final int availw = mIWallpaperEngine.mReqWidth-mCurWidth;
- final int xPixels = availw > 0 ? -(int)(availw*xOffset+.5f) : 0;
- final int availh = mIWallpaperEngine.mReqHeight-mCurHeight;
- final int yPixels = availh > 0 ? -(int)(availh*yOffset+.5f) : 0;
- onOffsetsChanged(xOffset, yOffset, xOffsetStep, yOffsetStep, xPixels, yPixels);
+ if (mReportedVisible) {
+ if (DEBUG) Log.v(TAG, "Offsets change in " + this
+ + ": " + xOffset + "," + yOffset);
+ final int availw = mIWallpaperEngine.mReqWidth-mCurWidth;
+ final int xPixels = availw > 0 ? -(int)(availw*xOffset+.5f) : 0;
+ final int availh = mIWallpaperEngine.mReqHeight-mCurHeight;
+ final int yPixels = availh > 0 ? -(int)(availh*yOffset+.5f) : 0;
+ onOffsetsChanged(xOffset, yOffset, xOffsetStep, yOffsetStep, xPixels, yPixels);
+ } else {
+ mOffsetsChanged = true;
+ }
}
if (sync) {
@@ -953,7 +988,7 @@ public abstract class WallpaperService extends Service {
mEngine.doVisibilityChanged(message.arg1 != 0);
break;
case MSG_WALLPAPER_OFFSETS: {
- mEngine.doOffsetsChanged();
+ mEngine.doOffsetsChanged(true);
} break;
case MSG_WALLPAPER_COMMAND: {
WallpaperCommand cmd = (WallpaperCommand)message.obj;
@@ -962,7 +997,7 @@ public abstract class WallpaperService extends Service {
case MSG_WINDOW_RESIZED: {
final boolean reportDraw = message.arg1 != 0;
mEngine.updateSurface(true, false, reportDraw);
- mEngine.doOffsetsChanged();
+ mEngine.doOffsetsChanged(true);
} break;
case MSG_TOUCH_EVENT: {
boolean skip = false;
diff --git a/core/java/android/speech/tts/AudioPlaybackHandler.java b/core/java/android/speech/tts/AudioPlaybackHandler.java
index 89b6f32..75dcd6e 100644
--- a/core/java/android/speech/tts/AudioPlaybackHandler.java
+++ b/core/java/android/speech/tts/AudioPlaybackHandler.java
@@ -390,10 +390,10 @@ class AudioPlaybackHandler {
audioTrack.play();
}
int count = 0;
- while (count < bufferCopy.mLength) {
+ while (count < bufferCopy.mBytes.length) {
// Note that we don't take bufferCopy.mOffset into account because
// it is guaranteed to be 0.
- int written = audioTrack.write(bufferCopy.mBytes, count, bufferCopy.mLength);
+ int written = audioTrack.write(bufferCopy.mBytes, count, bufferCopy.mBytes.length);
if (written <= 0) {
break;
}
@@ -415,6 +415,9 @@ class AudioPlaybackHandler {
}
if (params.mBytesWritten < params.mAudioBufferSize) {
+ if (DBG) Log.d(TAG, "Stopping audio track to flush audio, state was : " +
+ audioTrack.getPlayState());
+ params.mIsShortUtterance = true;
audioTrack.stop();
}
@@ -452,10 +455,40 @@ class AudioPlaybackHandler {
return;
}
+ if (params.mIsShortUtterance) {
+ // In this case we would have called AudioTrack#stop() to flush
+ // buffers to the mixer. This makes the playback head position
+ // unobservable and notification markers do not work reliably. We
+ // have no option but to wait until we think the track would finish
+ // playing and release it after.
+ //
+ // This isn't as bad as it looks because (a) We won't end up waiting
+ // for much longer than we should because even at 4khz mono, a short
+ // utterance weighs in at about 2 seconds, and (b) such short utterances
+ // are expected to be relatively infrequent and in a stream of utterances
+ // this shows up as a slightly longer pause.
+ blockUntilEstimatedCompletion(params);
+ } else {
+ blockUntilCompletion(params);
+ }
+ }
+
+ private static void blockUntilEstimatedCompletion(SynthesisMessageParams params) {
+ final int lengthInFrames = params.mBytesWritten / params.mBytesPerFrame;
+ final long estimatedTimeMs = (lengthInFrames * 1000 / params.mSampleRateInHz);
+
+ if (DBG) Log.d(TAG, "About to sleep for: " + estimatedTimeMs + "ms for a short utterance");
+
+ try {
+ Thread.sleep(estimatedTimeMs);
+ } catch (InterruptedException ie) {
+ // Do nothing.
+ }
+ }
+
+ private static void blockUntilCompletion(SynthesisMessageParams params) {
final AudioTrack audioTrack = params.mAudioTrack;
- final int bytesPerFrame = getBytesPerFrame(params.mAudioFormat);
- final int lengthInBytes = params.mBytesWritten;
- final int lengthInFrames = lengthInBytes / bytesPerFrame;
+ final int lengthInFrames = params.mBytesWritten / params.mBytesPerFrame;
int currentPosition = 0;
while ((currentPosition = audioTrack.getPlaybackHeadPosition()) < lengthInFrames) {
@@ -511,16 +544,6 @@ class AudioPlaybackHandler {
return 0;
}
- static int getBytesPerFrame(int audioFormat) {
- if (audioFormat == AudioFormat.ENCODING_PCM_8BIT) {
- return 1;
- } else if (audioFormat == AudioFormat.ENCODING_PCM_16BIT) {
- return 2;
- }
-
- return -1;
- }
-
private static void setupVolume(AudioTrack audioTrack, float volume, float pan) {
float vol = clip(volume, 0.0f, 1.0f);
float panning = clip(pan, -1.0f, 1.0f);
diff --git a/core/java/android/speech/tts/PlaybackSynthesisCallback.java b/core/java/android/speech/tts/PlaybackSynthesisCallback.java
index 7dbf1ac..0cca06a 100644
--- a/core/java/android/speech/tts/PlaybackSynthesisCallback.java
+++ b/core/java/android/speech/tts/PlaybackSynthesisCallback.java
@@ -85,6 +85,7 @@ class PlaybackSynthesisCallback extends AbstractSynthesisCallback {
// Note that mLogger.mError might be true too at this point.
mLogger.onStopped();
+ SynthesisMessageParams token = null;
synchronized (mStateLock) {
if (mStopped) {
Log.w(TAG, "stop() called twice");
@@ -97,9 +98,19 @@ class PlaybackSynthesisCallback extends AbstractSynthesisCallback {
// In all other cases, mAudioTrackHandler.stop() will
// result in onComplete being called.
mLogger.onWriteData();
+ } else {
+ token = mToken;
}
mStopped = true;
}
+
+ if (token != null) {
+ // This might result in the synthesis thread being woken up, at which
+ // point it will write an additional buffer to the token - but we
+ // won't worry about that because the audio playback queue will be cleared
+ // soon after (see SynthHandler#stop(String).
+ token.clearBuffers();
+ }
}
@Override
@@ -155,18 +166,22 @@ class PlaybackSynthesisCallback extends AbstractSynthesisCallback {
+ length + " bytes)");
}
+ SynthesisMessageParams token = null;
synchronized (mStateLock) {
if (mToken == null || mStopped) {
return TextToSpeech.ERROR;
}
-
- // Sigh, another copy.
- final byte[] bufferCopy = new byte[length];
- System.arraycopy(buffer, offset, bufferCopy, 0, length);
- mToken.addBuffer(bufferCopy);
- mAudioTrackHandler.enqueueSynthesisDataAvailable(mToken);
+ token = mToken;
}
+ // Sigh, another copy.
+ final byte[] bufferCopy = new byte[length];
+ System.arraycopy(buffer, offset, bufferCopy, 0, length);
+ // Might block on mToken.this, if there are too many buffers waiting to
+ // be consumed.
+ token.addBuffer(bufferCopy);
+ mAudioTrackHandler.enqueueSynthesisDataAvailable(token);
+
mLogger.onEngineDataReceived();
return TextToSpeech.SUCCESS;
@@ -176,6 +191,7 @@ class PlaybackSynthesisCallback extends AbstractSynthesisCallback {
public int done() {
if (DBG) Log.d(TAG, "done()");
+ SynthesisMessageParams token = null;
synchronized (mStateLock) {
if (mDone) {
Log.w(TAG, "Duplicate call to done()");
@@ -188,9 +204,12 @@ class PlaybackSynthesisCallback extends AbstractSynthesisCallback {
return TextToSpeech.ERROR;
}
- mAudioTrackHandler.enqueueSynthesisDone(mToken);
- mLogger.onEngineComplete();
+ token = mToken;
}
+
+ mAudioTrackHandler.enqueueSynthesisDone(token);
+ mLogger.onEngineComplete();
+
return TextToSpeech.SUCCESS;
}
diff --git a/core/java/android/speech/tts/SynthesisMessageParams.java b/core/java/android/speech/tts/SynthesisMessageParams.java
index 7da5daa..779721e 100644
--- a/core/java/android/speech/tts/SynthesisMessageParams.java
+++ b/core/java/android/speech/tts/SynthesisMessageParams.java
@@ -15,6 +15,7 @@
*/
package android.speech.tts;
+import android.media.AudioFormat;
import android.media.AudioTrack;
import android.speech.tts.TextToSpeechService.UtteranceCompletedDispatcher;
@@ -24,6 +25,8 @@ import java.util.LinkedList;
* Params required to play back a synthesis request.
*/
final class SynthesisMessageParams extends MessageParams {
+ private static final long MAX_UNCONSUMED_AUDIO_MS = 500;
+
final int mStreamType;
final int mSampleRateInHz;
final int mAudioFormat;
@@ -32,10 +35,22 @@ final class SynthesisMessageParams extends MessageParams {
final float mPan;
final EventLogger mLogger;
+ final int mBytesPerFrame;
+
volatile AudioTrack mAudioTrack;
- // Not volatile, accessed only from the synthesis thread.
- int mBytesWritten;
+ // Written by the synthesis thread, but read on the audio playback
+ // thread.
+ volatile int mBytesWritten;
+ // A "short utterance" is one that uses less bytes than the audio
+ // track buffer size (mAudioBufferSize). In this case, we need to call
+ // AudioTrack#stop() to send pending buffers to the mixer, and slightly
+ // different logic is required to wait for the track to finish.
+ //
+ // Not volatile, accessed only from the audio playback thread.
+ boolean mIsShortUtterance;
int mAudioBufferSize;
+ // Always synchronized on "this".
+ int mUnconsumedBytes;
private final LinkedList<ListEntry> mDataBufferList = new LinkedList<ListEntry>();
@@ -53,6 +68,8 @@ final class SynthesisMessageParams extends MessageParams {
mPan = pan;
mLogger = logger;
+ mBytesPerFrame = getBytesPerFrame(mAudioFormat) * mChannelCount;
+
// initially null.
mAudioTrack = null;
mBytesWritten = 0;
@@ -64,18 +81,36 @@ final class SynthesisMessageParams extends MessageParams {
return TYPE_SYNTHESIS;
}
- synchronized void addBuffer(byte[] buffer, int offset, int length) {
- mDataBufferList.add(new ListEntry(buffer, offset, length));
+ synchronized void addBuffer(byte[] buffer) {
+ long unconsumedAudioMs = 0;
+
+ while ((unconsumedAudioMs = getUnconsumedAudioLengthMs()) > MAX_UNCONSUMED_AUDIO_MS) {
+ try {
+ wait();
+ } catch (InterruptedException ie) {
+ return;
+ }
+ }
+
+ mDataBufferList.add(new ListEntry(buffer));
+ mUnconsumedBytes += buffer.length;
}
- synchronized void addBuffer(byte[] buffer) {
- mDataBufferList.add(new ListEntry(buffer, 0, buffer.length));
+ synchronized void clearBuffers() {
+ mDataBufferList.clear();
+ mUnconsumedBytes = 0;
+ notifyAll();
}
synchronized ListEntry getNextBuffer() {
- return mDataBufferList.poll();
- }
+ ListEntry entry = mDataBufferList.poll();
+ if (entry != null) {
+ mUnconsumedBytes -= entry.mBytes.length;
+ notifyAll();
+ }
+ return entry;
+ }
void setAudioTrack(AudioTrack audioTrack) {
mAudioTrack = audioTrack;
@@ -85,15 +120,29 @@ final class SynthesisMessageParams extends MessageParams {
return mAudioTrack;
}
+ // Must be called synchronized on this.
+ private long getUnconsumedAudioLengthMs() {
+ final int unconsumedFrames = mUnconsumedBytes / mBytesPerFrame;
+ final long estimatedTimeMs = unconsumedFrames * 1000 / mSampleRateInHz;
+
+ return estimatedTimeMs;
+ }
+
+ private static int getBytesPerFrame(int audioFormat) {
+ if (audioFormat == AudioFormat.ENCODING_PCM_8BIT) {
+ return 1;
+ } else if (audioFormat == AudioFormat.ENCODING_PCM_16BIT) {
+ return 2;
+ }
+
+ return -1;
+ }
+
static final class ListEntry {
final byte[] mBytes;
- final int mOffset;
- final int mLength;
- ListEntry(byte[] bytes, int offset, int length) {
+ ListEntry(byte[] bytes) {
mBytes = bytes;
- mOffset = offset;
- mLength = length;
}
}
}
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java
index 788711d..e8b2045 100644
--- a/core/java/android/text/StaticLayout.java
+++ b/core/java/android/text/StaticLayout.java
@@ -729,12 +729,22 @@ public class StaticLayout extends Layout {
start - widthStart, end - start);
}
- // If ellipsize is in marquee mode, do not apply ellipsis on the first line
- if (ellipsize != null && (ellipsize != TextUtils.TruncateAt.MARQUEE || j != 0)) {
+ if (ellipsize != null) {
+ // If there is only one line, then do any type of ellipsis except when it is MARQUEE
+ // if there are multiple lines, just allow END ellipsis on the last line
+ boolean firstLine = (j == 0);
+ boolean currentLineIsTheLastVisibleOne = (j + 1 == mMaximumVisibleLineCount);
boolean forceEllipsis = moreChars && (mLineCount + 1 == mMaximumVisibleLineCount);
- calculateEllipsis(start, end, widths, widthStart,
- ellipsisWidth, ellipsize, j,
- textWidth, paint, forceEllipsis);
+
+ boolean doEllipsis = (firstLine && !moreChars &&
+ ellipsize != TextUtils.TruncateAt.MARQUEE) ||
+ (!firstLine && (currentLineIsTheLastVisibleOne || !moreChars) &&
+ ellipsize == TextUtils.TruncateAt.END);
+ if (doEllipsis) {
+ calculateEllipsis(start, end, widths, widthStart,
+ ellipsisWidth, ellipsize, j,
+ textWidth, paint, forceEllipsis);
+ }
}
mLineCount++;
@@ -797,8 +807,8 @@ public class StaticLayout extends Layout {
ellipsisStart = i;
ellipsisCount = len - i;
- if (forceEllipsis && ellipsisCount == 0 && i > 0) {
- ellipsisStart = i - 1;
+ if (forceEllipsis && ellipsisCount == 0 && len > 0) {
+ ellipsisStart = len - 1;
ellipsisCount = 1;
}
} else {
diff --git a/core/java/android/text/TextLine.java b/core/java/android/text/TextLine.java
index fcc372e..68a6b3e 100644
--- a/core/java/android/text/TextLine.java
+++ b/core/java/android/text/TextLine.java
@@ -723,7 +723,7 @@ class TextLine {
float ret = 0;
int contextLen = contextEnd - contextStart;
- if (needWidth || (c != null && (wp.bgColor != 0 || wp.underlineColor !=0 || runIsRtl))) {
+ if (needWidth || (c != null && (wp.bgColor != 0 || wp.underlineCount != 0 || runIsRtl))) {
int flags = runIsRtl ? Paint.DIRECTION_RTL : Paint.DIRECTION_LTR;
if (mCharsValid) {
ret = wp.getTextRunAdvances(mChars, start, runLen,
@@ -753,21 +753,26 @@ class TextLine {
wp.setColor(previousColor);
}
- if (wp.underlineColor != 0) {
+ if (wp.underlineCount != 0) {
// kStdUnderline_Offset = 1/9, defined in SkTextFormatParams.h
- float middle = y + wp.baselineShift + (1.0f / 9.0f) * wp.getTextSize();
- // kStdUnderline_Thickness = 1/18, defined in SkTextFormatParams.h
- float halfHeight = wp.underlineThickness * (1.0f / 18.0f / 2.0f) * wp.getTextSize();
+ float underlineTop = y + wp.baselineShift + (1.0f / 9.0f) * wp.getTextSize();
int previousColor = wp.getColor();
Paint.Style previousStyle = wp.getStyle();
+ boolean previousAntiAlias = wp.isAntiAlias();
- wp.setColor(wp.underlineColor);
wp.setStyle(Paint.Style.FILL);
- c.drawRect(x, middle - halfHeight, x + ret, middle + halfHeight, wp);
+ wp.setAntiAlias(true);
+
+ for (int i = 0; i < wp.underlineCount; i++) {
+ wp.setColor(wp.underlineColors[i]);
+ c.drawRect(x, underlineTop, x + ret, underlineTop + wp.underlineThicknesses[i],
+ wp);
+ }
wp.setStyle(previousStyle);
wp.setColor(previousColor);
+ wp.setAntiAlias(previousAntiAlias);
}
drawTextRun(c, wp, start, end, contextStart, contextEnd, runIsRtl,
diff --git a/core/java/android/text/TextPaint.java b/core/java/android/text/TextPaint.java
index de57dfa..625d869 100644
--- a/core/java/android/text/TextPaint.java
+++ b/core/java/android/text/TextPaint.java
@@ -23,6 +23,9 @@ import android.graphics.Paint;
* data used during text measuring and drawing.
*/
public class TextPaint extends Paint {
+
+ private static final int DEFAULT_UNDERLINE_SIZE = 3;
+
// Special value 0 means no background paint
public int bgColor;
public int baselineShift;
@@ -33,12 +36,17 @@ public class TextPaint extends Paint {
* Special value 0 means no custom underline
* @hide
*/
- public int underlineColor;
+ public int[] underlineColors;
/**
* Defined as a multiplier of the default underline thickness. Use 1.0f for default thickness.
* @hide
*/
- public float underlineThickness;
+ public float[] underlineThicknesses;
+ /**
+ * The number of underlines currently stored in the array. If 0, no underline is drawn.
+ * @hide
+ */
+ public int underlineCount;
public TextPaint() {
super();
@@ -64,24 +72,43 @@ public class TextPaint extends Paint {
linkColor = tp.linkColor;
drawableState = tp.drawableState;
density = tp.density;
- underlineColor = tp.underlineColor;
- underlineThickness = tp.underlineThickness;
+ underlineColors = tp.underlineColors;
+ underlineThicknesses = tp.underlineThicknesses;
+ underlineCount = tp.underlineCount;
}
/**
* Defines a custom underline for this Paint.
* @param color underline solid color
- * @param thickness underline thickness, defined as a multiplier of the default underline
- * thickness.
+ * @param thickness underline thickness
* @hide
*/
- public void setUnderlineText(boolean isUnderlined, int color, float thickness) {
- setUnderlineText(false);
- if (isUnderlined) {
- underlineColor = color;
- underlineThickness = thickness;
+ public void setUnderlineText(int color, float thickness) {
+ if (color == 0) {
+ // No underline
+ return;
+ }
+
+ if (underlineCount == 0) {
+ underlineColors = new int[DEFAULT_UNDERLINE_SIZE];
+ underlineThicknesses = new float[DEFAULT_UNDERLINE_SIZE];
+ underlineColors[underlineCount] = color;
+ underlineThicknesses[underlineCount] = thickness;
+ underlineCount++;
} else {
- underlineColor = 0;
+ if (underlineCount == underlineColors.length) {
+ int[] newColors = new int[underlineColors.length + DEFAULT_UNDERLINE_SIZE];
+ float[] newThickness = new float[underlineThicknesses.length
+ + DEFAULT_UNDERLINE_SIZE];
+ System.arraycopy(underlineColors, 0, newColors, 0, underlineColors.length);
+ System.arraycopy(
+ underlineThicknesses, 0, newThickness, 0, underlineThicknesses.length);
+ underlineColors = newColors;
+ underlineThicknesses = newThickness;
+ }
+ underlineColors[underlineCount] = color;
+ underlineThicknesses[underlineCount] = thickness;
+ underlineCount++;
}
}
}
diff --git a/core/java/android/text/TextUtils.java b/core/java/android/text/TextUtils.java
index b8b54f4..e914316 100644
--- a/core/java/android/text/TextUtils.java
+++ b/core/java/android/text/TextUtils.java
@@ -25,6 +25,7 @@ import android.text.style.BackgroundColorSpan;
import android.text.style.BulletSpan;
import android.text.style.CharacterStyle;
import android.text.style.ForegroundColorSpan;
+import android.text.style.EasyEditSpan;
import android.text.style.LeadingMarginSpan;
import android.text.style.MetricAffectingSpan;
import android.text.style.QuoteSpan;
@@ -585,6 +586,8 @@ public class TextUtils {
public static final int SPELL_CHECK_SPAN = 20;
/** @hide */
public static final int SUGGESTION_RANGE_SPAN = 21;
+ /** @hide */
+ public static final int EASY_EDIT_SPAN = 22;
/**
* Flatten a CharSequence and whatever styles can be copied across processes
@@ -748,6 +751,10 @@ public class TextUtils {
readSpan(p, sp, new SuggestionRangeSpan());
break;
+ case EASY_EDIT_SPAN:
+ readSpan(p, sp, new EasyEditSpan(p));
+ break;
+
default:
throw new RuntimeException("bogus span encoding " + kind);
}
diff --git a/core/java/android/text/style/EasyEditSpan.java b/core/java/android/text/style/EasyEditSpan.java
new file mode 100644
index 0000000..e6e4d2c
--- /dev/null
+++ b/core/java/android/text/style/EasyEditSpan.java
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+
+package android.text.style;
+
+import android.os.Parcel;
+import android.text.ParcelableSpan;
+import android.text.TextUtils;
+import android.widget.TextView;
+
+/**
+ * Provides an easy way to edit a portion of text.
+ * <p>
+ * The {@link TextView} uses this span to allow the user to delete a chuck of text in one click.
+ * the text. {@link TextView} removes this span as soon as the text is edited, or the cursor moves.
+ */
+public class EasyEditSpan implements ParcelableSpan {
+
+ public EasyEditSpan() {
+ // Empty
+ }
+
+ public EasyEditSpan(Parcel src) {
+ this();
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ // Empty
+ }
+
+ @Override
+ public int getSpanTypeId() {
+ return TextUtils.EASY_EDIT_SPAN;
+ }
+}
diff --git a/core/java/android/text/style/SuggestionSpan.java b/core/java/android/text/style/SuggestionSpan.java
index ea57f917..8625257 100644
--- a/core/java/android/text/style/SuggestionSpan.java
+++ b/core/java/android/text/style/SuggestionSpan.java
@@ -61,12 +61,6 @@ public class SuggestionSpan extends CharacterStyle implements ParcelableSpan {
public static final String SUGGESTION_SPAN_PICKED_BEFORE = "before";
public static final String SUGGESTION_SPAN_PICKED_HASHCODE = "hashcode";
- /**
- * The default underline thickness as a percentage of the system's default underline thickness
- * (i.e., 100 means the default thickness, and 200 is a double thickness).
- */
- private static final int DEFAULT_UNDERLINE_PERCENTAGE = 100;
-
public static final int SUGGESTIONS_MAX_SIZE = 5;
/*
@@ -82,10 +76,8 @@ public class SuggestionSpan extends CharacterStyle implements ParcelableSpan {
private final String mNotificationTargetClassName;
private final int mHashCode;
- private float mMisspelledUnderlineThickness;
- private int mMisspelledUnderlineColor;
- private float mEasyCorrectUnderlineThickness;
- private int mEasyCorrectUnderlineColor;
+ private float mUnderlineThickness;
+ private int mUnderlineColor;
/*
* TODO: If switching IME is required, needs to add parameters for ids of InputMethodInfo
@@ -140,31 +132,26 @@ public class SuggestionSpan extends CharacterStyle implements ParcelableSpan {
}
private void initStyle(Context context) {
- // Read the colors. We need to store the color and the underline thickness, as the span
- // does not have access to the context when it is read from a parcel.
- TypedArray typedArray;
+ int defStyle = 0;
+ if ((getFlags() & FLAG_MISSPELLED) != 0) {
+ defStyle = com.android.internal.R.attr.textAppearanceMisspelledSuggestion;
+ } else if ((getFlags() & FLAG_EASY_CORRECT) != 0) {
+ defStyle = com.android.internal.R.attr.textAppearanceEasyCorrectSuggestion;
+ } else {
+ // No style is applied.
+ mUnderlineThickness = 0;
+ mUnderlineColor = 0;
+ return;
+ }
- typedArray = context.obtainStyledAttributes(null,
+ TypedArray typedArray = context.obtainStyledAttributes(null,
com.android.internal.R.styleable.SuggestionSpan,
- com.android.internal.R.attr.textAppearanceEasyCorrectSuggestion, 0);
+ defStyle, 0);
- mEasyCorrectUnderlineThickness = getThicknessPercentage(typedArray,
- com.android.internal.R.styleable.SuggestionSpan_textUnderlineThicknessPercentage);
- mEasyCorrectUnderlineColor = typedArray.getColor(
+ mUnderlineThickness = typedArray.getDimension(
+ com.android.internal.R.styleable.SuggestionSpan_textUnderlineThickness, 0);
+ mUnderlineColor = typedArray.getColor(
com.android.internal.R.styleable.SuggestionSpan_textUnderlineColor, Color.BLACK);
-
- typedArray = context.obtainStyledAttributes(null,
- com.android.internal.R.styleable.SuggestionSpan,
- com.android.internal.R.attr.textAppearanceMisspelledSuggestion, 0);
- mMisspelledUnderlineThickness = getThicknessPercentage(typedArray,
- com.android.internal.R.styleable.SuggestionSpan_textUnderlineThicknessPercentage);
- mMisspelledUnderlineColor = typedArray.getColor(
- com.android.internal.R.styleable.SuggestionSpan_textUnderlineColor, Color.BLACK);
- }
-
- private static float getThicknessPercentage(TypedArray typedArray, int index) {
- int value = typedArray.getInteger(index, DEFAULT_UNDERLINE_PERCENTAGE);
- return value / 100.0f;
}
public SuggestionSpan(Parcel src) {
@@ -173,10 +160,8 @@ public class SuggestionSpan extends CharacterStyle implements ParcelableSpan {
mLocaleString = src.readString();
mNotificationTargetClassName = src.readString();
mHashCode = src.readInt();
- mEasyCorrectUnderlineColor = src.readInt();
- mEasyCorrectUnderlineThickness = src.readFloat();
- mMisspelledUnderlineColor = src.readInt();
- mMisspelledUnderlineThickness = src.readFloat();
+ mUnderlineColor = src.readInt();
+ mUnderlineThickness = src.readFloat();
}
/**
@@ -226,10 +211,8 @@ public class SuggestionSpan extends CharacterStyle implements ParcelableSpan {
dest.writeString(mLocaleString);
dest.writeString(mNotificationTargetClassName);
dest.writeInt(mHashCode);
- dest.writeInt(mEasyCorrectUnderlineColor);
- dest.writeFloat(mEasyCorrectUnderlineThickness);
- dest.writeInt(mMisspelledUnderlineColor);
- dest.writeFloat(mMisspelledUnderlineThickness);
+ dest.writeInt(mUnderlineColor);
+ dest.writeFloat(mUnderlineThickness);
}
@Override
@@ -271,10 +254,6 @@ public class SuggestionSpan extends CharacterStyle implements ParcelableSpan {
@Override
public void updateDrawState(TextPaint tp) {
- if ((getFlags() & FLAG_MISSPELLED) != 0) {
- tp.setUnderlineText(true, mMisspelledUnderlineColor, mMisspelledUnderlineThickness);
- } else if ((getFlags() & FLAG_EASY_CORRECT) != 0) {
- tp.setUnderlineText(true, mEasyCorrectUnderlineColor, mEasyCorrectUnderlineThickness);
- }
+ tp.setUnderlineText(mUnderlineColor, mUnderlineThickness);
}
}
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index ef3d3fa..3880bc4 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -36,10 +36,14 @@ public class Surface implements Parcelable {
public static final int ROTATION_270 = 3;
/**
- * Create Surface from a SurfaceTexture.
+ * Create Surface from a {@link SurfaceTexture}.
*
- * @param surfaceTexture The {@link SurfaceTexture} that is updated by this Surface.
- * @hide
+ * Images drawn to the Surface will be made available to the {@link
+ * SurfaceTexture}, which can attach them an OpenGL ES texture via {@link
+ * SurfaceTexture#updateTexImage}.
+ *
+ * @param surfaceTexture The {@link SurfaceTexture} that is updated by this
+ * Surface.
*/
public Surface(SurfaceTexture surfaceTexture) {
if (DEBUG_RELEASE) {
@@ -442,7 +446,9 @@ public class Surface implements Parcelable {
/** @hide */
public native void setLayer(int zorder);
/** @hide */
- public native void setPosition(int x, int y);
+ public void setPosition(int x, int y) { setPosition((float)x, (float)y); }
+ /** @hide */
+ public native void setPosition(float x, float y);
/** @hide */
public native void setSize(int w, int h);
/** @hide */
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index da5baf8..302be57 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -1583,6 +1583,14 @@ public final class InputMethodManager {
/**
* Set additional input method subtypes. Only a process which shares the same uid with the IME
* can add additional input method subtypes to the IME.
+ * Please note that a subtype's status is stored in the system.
+ * For example, enabled subtypes are remembered by the framework even after they are removed
+ * by using this method. If you re-add the same subtypes again,
+ * they will just get enabled. If you want to avoid such conflicts, for instance, you may
+ * want to create a "different" new subtype even with the same locale and mode,
+ * by changing its extra value. The different subtype won't get affected by the stored past
+ * status. (You may want to take a look at {@link InputMethodSubtype#hashCode()} to refer
+ * to the current implementation.)
* @param imiId Id of InputMethodInfo which additional input method subtypes will be added to.
* @param subtypes subtypes will be added as additional subtypes of the current input method.
* @return true if the additional input method subtypes are successfully added.
diff --git a/core/java/android/view/textservice/TextServicesManager.java b/core/java/android/view/textservice/TextServicesManager.java
index c85b2d9..01587aa 100644
--- a/core/java/android/view/textservice/TextServicesManager.java
+++ b/core/java/android/view/textservice/TextServicesManager.java
@@ -66,7 +66,13 @@ public final class TextServicesManager {
/**
* Get a spell checker session for the specified spell checker
- * @param locale the locale for the spell checker
+ * @param locale the locale for the spell checker. If {@param locale} is null and
+ * referToSpellCheckerLanguageSettings is true, the locale specified in Settings will be
+ * returned. If {@param locale} is not null and referToSpellCheckerLanguageSettings is true,
+ * the locale specified in Settings will be returned only when it is same as {@param locale}.
+ * Exceptionally, when referToSpellCheckerLanguageSettings is true and {@param locale} is
+ * only language (e.g. "en"), the specified locale in Settings (e.g. "en_US") will be
+ * selected.
* @param listener a spell checker session lister for getting results from a spell checker.
* @param referToSpellCheckerLanguageSettings if true, the session for one of enabled
* languages in settings will be returned.
@@ -81,6 +87,11 @@ public final class TextServicesManager {
throw new IllegalArgumentException("Locale should not be null if you don't refer"
+ " settings.");
}
+
+ if (referToSpellCheckerLanguageSettings && !isSpellCheckerEnabled()) {
+ return null;
+ }
+
final SpellCheckerInfo sci;
try {
sci = sService.getCurrentSpellChecker(null);
@@ -108,7 +119,12 @@ public final class TextServicesManager {
final String localeStr = locale.toString();
for (int i = 0; i < sci.getSubtypeCount(); ++i) {
final SpellCheckerSubtype subtype = sci.getSubtypeAt(i);
- if (subtype.getLocale().equals(localeStr)) {
+ final String tempSubtypeLocale = subtype.getLocale();
+ if (tempSubtypeLocale.equals(localeStr)) {
+ subtypeInUse = subtype;
+ break;
+ } else if (localeStr.length() >= 2 && tempSubtypeLocale.length() >= 2
+ && localeStr.startsWith(tempSubtypeLocale)) {
subtypeInUse = subtype;
}
}
diff --git a/core/java/android/webkit/HTML5VideoInline.java b/core/java/android/webkit/HTML5VideoInline.java
index ef1906c..1b9a25e 100644
--- a/core/java/android/webkit/HTML5VideoInline.java
+++ b/core/java/android/webkit/HTML5VideoInline.java
@@ -5,6 +5,7 @@ import android.graphics.SurfaceTexture;
import android.media.MediaPlayer;
import android.webkit.HTML5VideoView;
import android.webkit.HTML5VideoViewProxy;
+import android.view.Surface;
import android.opengl.GLES20;
/**
@@ -38,7 +39,10 @@ public class HTML5VideoInline extends HTML5VideoView{
@Override
public void decideDisplayMode() {
- mPlayer.setTexture(getSurfaceTexture(getVideoLayerId()));
+ SurfaceTexture surfaceTexture = getSurfaceTexture(getVideoLayerId());
+ Surface surface = new Surface(surfaceTexture);
+ mPlayer.setSurface(surface);
+ surface.release();
}
// Normally called immediately after setVideoURI. But for full screen,
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 2aa481c..4748522 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -9124,7 +9124,9 @@ public class WebView extends AbsoluteLayout
/** @hide send content invalidate */
protected void contentInvalidateAll() {
- mWebViewCore.sendMessage(EventHub.CONTENT_INVALIDATE_ALL);
+ if (mWebViewCore != null && !mBlockWebkitViewMessages) {
+ mWebViewCore.sendMessage(EventHub.CONTENT_INVALIDATE_ALL);
+ }
}
/** @hide call pageSwapCallback upon next page swap */
diff --git a/core/java/android/widget/SpellChecker.java b/core/java/android/widget/SpellChecker.java
index ff13dcb..b89b8ec 100644
--- a/core/java/android/widget/SpellChecker.java
+++ b/core/java/android/widget/SpellChecker.java
@@ -112,6 +112,8 @@ public class SpellChecker implements SpellCheckerSessionListener {
private void scheduleSpellCheck() {
if (mLength == 0) return;
+ if (spellCheckerSession == null) return;
+
if (mChecker != null) {
mTextView.removeCallbacks(mChecker);
}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index e9662ae..4ce2d90 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -64,6 +64,7 @@ import android.text.TextDirectionHeuristics;
import android.text.TextPaint;
import android.text.TextUtils;
import android.text.TextWatcher;
+import android.text.TextUtils.TruncateAt;
import android.text.method.AllCapsTransformationMethod;
import android.text.method.ArrowKeyMovementMethod;
import android.text.method.DateKeyListener;
@@ -81,7 +82,9 @@ import android.text.method.TimeKeyListener;
import android.text.method.TransformationMethod;
import android.text.method.TransformationMethod2;
import android.text.method.WordIterator;
+import android.text.style.CharacterStyle;
import android.text.style.ClickableSpan;
+import android.text.style.EasyEditSpan;
import android.text.style.ParagraphStyle;
import android.text.style.SpellCheckSpan;
import android.text.style.SuggestionRangeSpan;
@@ -364,6 +367,35 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
private boolean mResolvedDrawables = false;
+ /**
+ * On some devices the fading edges add a performance penalty if used
+ * extensively in the same layout. This mode indicates how the marquee
+ * is currently being shown, if applicable. (mEllipsize will == MARQUEE)
+ */
+ private int mMarqueeFadeMode = MARQUEE_FADE_NORMAL;
+
+ /**
+ * When mMarqueeFadeMode is not MARQUEE_FADE_NORMAL, this stores
+ * the layout that should be used when the mode switches.
+ */
+ private Layout mSavedMarqueeModeLayout;
+
+ /**
+ * Draw marquee text with fading edges as usual
+ */
+ private static final int MARQUEE_FADE_NORMAL = 0;
+
+ /**
+ * Draw marquee text as ellipsize end while inactive instead of with the fade.
+ * (Useful for devices where the fade can be expensive if overdone)
+ */
+ private static final int MARQUEE_FADE_SWITCH_SHOW_ELLIPSIS = 1;
+
+ /**
+ * Draw marquee text with fading edges because it is currently active/animating.
+ */
+ private static final int MARQUEE_FADE_SWITCH_SHOW_FADE = 2;
+
/*
* Kick-start the font cache for the zygote process (to pay the cost of
* initializing freetype for our default font only once).
@@ -995,8 +1027,13 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
setEllipsize(TextUtils.TruncateAt.END);
break;
case 4:
- setHorizontalFadingEdgeEnabled(
- ViewConfiguration.get(context).isFadingMarqueeEnabled());
+ if (ViewConfiguration.get(context).isFadingMarqueeEnabled()) {
+ setHorizontalFadingEdgeEnabled(true);
+ mMarqueeFadeMode = MARQUEE_FADE_NORMAL;
+ } else {
+ setHorizontalFadingEdgeEnabled(false);
+ mMarqueeFadeMode = MARQUEE_FADE_SWITCH_SHOW_ELLIPSIS;
+ }
setEllipsize(TextUtils.TruncateAt.MARQUEE);
break;
}
@@ -3067,8 +3104,13 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
if (text instanceof Spanned &&
((Spanned) text).getSpanStart(TextUtils.TruncateAt.MARQUEE) >= 0) {
- setHorizontalFadingEdgeEnabled(
- ViewConfiguration.get(mContext).isFadingMarqueeEnabled());
+ if (ViewConfiguration.get(mContext).isFadingMarqueeEnabled()) {
+ setHorizontalFadingEdgeEnabled(true);
+ mMarqueeFadeMode = MARQUEE_FADE_NORMAL;
+ } else {
+ setHorizontalFadingEdgeEnabled(false);
+ mMarqueeFadeMode = MARQUEE_FADE_SWITCH_SHOW_ELLIPSIS;
+ }
setEllipsize(TextUtils.TruncateAt.MARQUEE);
}
@@ -4761,7 +4803,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
final int layoutDirection = getResolvedLayoutDirection();
final int absoluteGravity = Gravity.getAbsoluteGravity(mGravity, layoutDirection);
- if (mEllipsize == TextUtils.TruncateAt.MARQUEE) {
+ if (mEllipsize == TextUtils.TruncateAt.MARQUEE &&
+ mMarqueeFadeMode != MARQUEE_FADE_SWITCH_SHOW_ELLIPSIS) {
if (!mSingleLine && getLineCount() == 1 && canMarquee() &&
(absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) != Gravity.LEFT) {
canvas.translate(mLayout.getLineRight(0) - (mRight - mLeft -
@@ -5945,7 +5988,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
mSavedHintLayout = (BoringLayout) mHintLayout;
}
- mLayout = mHintLayout = null;
+ mSavedMarqueeModeLayout = mLayout = mHintLayout = null;
// Since it depends on the value of mLayout
prepareCursorControllers();
@@ -6065,73 +6108,25 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
Layout.Alignment alignment = getLayoutAlignment();
boolean shouldEllipsize = mEllipsize != null && mInput == null;
+ final boolean switchEllipsize = mEllipsize == TruncateAt.MARQUEE &&
+ mMarqueeFadeMode != MARQUEE_FADE_NORMAL;
+ TruncateAt effectiveEllipsize = mEllipsize;
+ if (mEllipsize == TruncateAt.MARQUEE &&
+ mMarqueeFadeMode == MARQUEE_FADE_SWITCH_SHOW_ELLIPSIS) {
+ effectiveEllipsize = TruncateAt.END;
+ }
if (mTextDir == null) {
resolveTextDirection();
}
- if (mText instanceof Spannable) {
- mLayout = new DynamicLayout(mText, mTransformed, mTextPaint, w,
- alignment, mTextDir, mSpacingMult,
- mSpacingAdd, mIncludePad, mInput == null ? mEllipsize : null,
- ellipsisWidth);
- } else {
- if (boring == UNKNOWN_BORING) {
- boring = BoringLayout.isBoring(mTransformed, mTextPaint, mTextDir, mBoring);
- if (boring != null) {
- mBoring = boring;
- }
- }
-
- if (boring != null) {
- if (boring.width <= w &&
- (mEllipsize == null || boring.width <= ellipsisWidth)) {
- if (mSavedLayout != null) {
- mLayout = mSavedLayout.
- replaceOrMake(mTransformed, mTextPaint,
- w, alignment, mSpacingMult, mSpacingAdd,
- boring, mIncludePad);
- } else {
- mLayout = BoringLayout.make(mTransformed, mTextPaint,
- w, alignment, mSpacingMult, mSpacingAdd,
- boring, mIncludePad);
- }
- mSavedLayout = (BoringLayout) mLayout;
- } else if (shouldEllipsize && boring.width <= w) {
- if (mSavedLayout != null) {
- mLayout = mSavedLayout.
- replaceOrMake(mTransformed, mTextPaint,
- w, alignment, mSpacingMult, mSpacingAdd,
- boring, mIncludePad, mEllipsize,
- ellipsisWidth);
- } else {
- mLayout = BoringLayout.make(mTransformed, mTextPaint,
- w, alignment, mSpacingMult, mSpacingAdd,
- boring, mIncludePad, mEllipsize,
- ellipsisWidth);
- }
- } else if (shouldEllipsize) {
- mLayout = new StaticLayout(mTransformed,
- 0, mTransformed.length(),
- mTextPaint, w, alignment, mTextDir, mSpacingMult,
- mSpacingAdd, mIncludePad, mEllipsize,
- ellipsisWidth, mMaxMode == LINES ? mMaximum : Integer.MAX_VALUE);
- } else {
- mLayout = new StaticLayout(mTransformed, mTextPaint,
- w, alignment, mTextDir, mSpacingMult, mSpacingAdd,
- mIncludePad);
- }
- } else if (shouldEllipsize) {
- mLayout = new StaticLayout(mTransformed,
- 0, mTransformed.length(),
- mTextPaint, w, alignment, mTextDir, mSpacingMult,
- mSpacingAdd, mIncludePad, mEllipsize,
- ellipsisWidth, mMaxMode == LINES ? mMaximum : Integer.MAX_VALUE);
- } else {
- mLayout = new StaticLayout(mTransformed, mTextPaint,
- w, alignment, mTextDir, mSpacingMult, mSpacingAdd,
- mIncludePad);
- }
+ mLayout = makeSingleLayout(w, boring, ellipsisWidth, alignment, shouldEllipsize,
+ effectiveEllipsize, effectiveEllipsize == mEllipsize);
+ if (switchEllipsize) {
+ TruncateAt oppositeEllipsize = effectiveEllipsize == TruncateAt.MARQUEE ?
+ TruncateAt.END : TruncateAt.MARQUEE;
+ mSavedMarqueeModeLayout = makeSingleLayout(w, boring, ellipsisWidth, alignment,
+ shouldEllipsize, oppositeEllipsize, effectiveEllipsize != mEllipsize);
}
shouldEllipsize = mEllipsize != null;
@@ -6222,6 +6217,77 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
prepareCursorControllers();
}
+ private Layout makeSingleLayout(int w, BoringLayout.Metrics boring, int ellipsisWidth,
+ Layout.Alignment alignment, boolean shouldEllipsize, TruncateAt effectiveEllipsize,
+ boolean useSaved) {
+ Layout result = null;
+ if (mText instanceof Spannable) {
+ result = new DynamicLayout(mText, mTransformed, mTextPaint, w,
+ alignment, mTextDir, mSpacingMult,
+ mSpacingAdd, mIncludePad, mInput == null ? effectiveEllipsize : null,
+ ellipsisWidth);
+ } else {
+ if (boring == UNKNOWN_BORING) {
+ boring = BoringLayout.isBoring(mTransformed, mTextPaint, mTextDir, mBoring);
+ if (boring != null) {
+ mBoring = boring;
+ }
+ }
+
+ if (boring != null) {
+ if (boring.width <= w &&
+ (effectiveEllipsize == null || boring.width <= ellipsisWidth)) {
+ if (useSaved && mSavedLayout != null) {
+ result = mSavedLayout.replaceOrMake(mTransformed, mTextPaint,
+ w, alignment, mSpacingMult, mSpacingAdd,
+ boring, mIncludePad);
+ } else {
+ result = BoringLayout.make(mTransformed, mTextPaint,
+ w, alignment, mSpacingMult, mSpacingAdd,
+ boring, mIncludePad);
+ }
+
+ if (useSaved) {
+ mSavedLayout = (BoringLayout) result;
+ }
+ } else if (shouldEllipsize && boring.width <= w) {
+ if (useSaved && mSavedLayout != null) {
+ result = mSavedLayout.replaceOrMake(mTransformed, mTextPaint,
+ w, alignment, mSpacingMult, mSpacingAdd,
+ boring, mIncludePad, effectiveEllipsize,
+ ellipsisWidth);
+ } else {
+ result = BoringLayout.make(mTransformed, mTextPaint,
+ w, alignment, mSpacingMult, mSpacingAdd,
+ boring, mIncludePad, effectiveEllipsize,
+ ellipsisWidth);
+ }
+ } else if (shouldEllipsize) {
+ result = new StaticLayout(mTransformed,
+ 0, mTransformed.length(),
+ mTextPaint, w, alignment, mTextDir, mSpacingMult,
+ mSpacingAdd, mIncludePad, effectiveEllipsize,
+ ellipsisWidth, mMaxMode == LINES ? mMaximum : Integer.MAX_VALUE);
+ } else {
+ result = new StaticLayout(mTransformed, mTextPaint,
+ w, alignment, mTextDir, mSpacingMult, mSpacingAdd,
+ mIncludePad);
+ }
+ } else if (shouldEllipsize) {
+ result = new StaticLayout(mTransformed,
+ 0, mTransformed.length(),
+ mTextPaint, w, alignment, mTextDir, mSpacingMult,
+ mSpacingAdd, mIncludePad, effectiveEllipsize,
+ ellipsisWidth, mMaxMode == LINES ? mMaximum : Integer.MAX_VALUE);
+ } else {
+ result = new StaticLayout(mTransformed, mTextPaint,
+ w, alignment, mTextDir, mSpacingMult, mSpacingAdd,
+ mIncludePad);
+ }
+ }
+ return result;
+ }
+
private boolean compressText(float width) {
if (isHardwareAccelerated()) return false;
@@ -7177,7 +7243,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
private boolean canMarquee() {
int width = (mRight - mLeft - getCompoundPaddingLeft() - getCompoundPaddingRight());
- return width > 0 && mLayout.getLineWidth(0) > width;
+ return width > 0 && (mLayout.getLineWidth(0) > width ||
+ (mMarqueeFadeMode != MARQUEE_FADE_NORMAL && mSavedMarqueeModeLayout != null &&
+ mSavedMarqueeModeLayout.getLineWidth(0) > width));
}
private void startMarquee() {
@@ -7191,6 +7259,16 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
if ((mMarquee == null || mMarquee.isStopped()) && (isFocused() || isSelected()) &&
getLineCount() == 1 && canMarquee()) {
+ if (mMarqueeFadeMode == MARQUEE_FADE_SWITCH_SHOW_ELLIPSIS) {
+ mMarqueeFadeMode = MARQUEE_FADE_SWITCH_SHOW_FADE;
+ final Layout tmp = mLayout;
+ mLayout = mSavedMarqueeModeLayout;
+ mSavedMarqueeModeLayout = tmp;
+ setHorizontalFadingEdgeEnabled(true);
+ requestLayout();
+ invalidate();
+ }
+
if (mMarquee == null) mMarquee = new Marquee(this);
mMarquee.start(mMarqueeRepeatLimit);
}
@@ -7200,6 +7278,16 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
if (mMarquee != null && !mMarquee.isStopped()) {
mMarquee.stop();
}
+
+ if (mMarqueeFadeMode == MARQUEE_FADE_SWITCH_SHOW_FADE) {
+ mMarqueeFadeMode = MARQUEE_FADE_SWITCH_SHOW_ELLIPSIS;
+ final Layout tmp = mSavedMarqueeModeLayout;
+ mSavedMarqueeModeLayout = mLayout;
+ mLayout = tmp;
+ setHorizontalFadingEdgeEnabled(false);
+ requestLayout();
+ invalidate();
+ }
}
private void startStopMarquee(boolean start) {
@@ -7705,10 +7793,148 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
}
+ /**
+ * Controls the {@link EasyEditSpan} monitoring when it is added, and when the related
+ * pop-up should be displayed.
+ */
+ private class EditTextShortcutController {
+
+ private EditTextShortcutPopupWindow mPopupWindow;
+
+ private EasyEditSpan mEditTextShortcutSpan;
+
+ private void hide() {
+ if (mEditTextShortcutSpan != null) {
+ mPopupWindow.hide();
+ if (mText instanceof Spannable) {
+ ((Spannable) mText).removeSpan(mEditTextShortcutSpan);
+ }
+ mEditTextShortcutSpan = null;
+ }
+ }
+
+ /**
+ * Monitors the changes in the text.
+ *
+ * <p>{@link ChangeWatcher#onSpanAdded(Spannable, Object, int, int)} cannot be used,
+ * as the notifications are not sent when a spannable (with spans) is inserted.
+ */
+ public void onTextChange(CharSequence buffer) {
+ if (mEditTextShortcutSpan != null) {
+ hide();
+ }
+
+ if (buffer instanceof Spanned) {
+ mEditTextShortcutSpan = getSpan((Spanned) buffer);
+ if (mEditTextShortcutSpan != null) {
+ if (mPopupWindow == null) {
+ mPopupWindow = new EditTextShortcutPopupWindow();
+ }
+ mPopupWindow.show(mEditTextShortcutSpan);
+ }
+ }
+ }
+
+ private EasyEditSpan getSpan(Spanned spanned) {
+ EasyEditSpan[] inputMethodSpans = spanned.getSpans(0, spanned.length(),
+ EasyEditSpan.class);
+
+ if (inputMethodSpans.length == 0) {
+ return null;
+ } else {
+ return inputMethodSpans[0];
+ }
+ }
+ }
+
+ /**
+ * Displays the actions associated to an {@link EasyEditSpan}. The pop-up is controlled
+ * by {@link EditTextShortcutController}.
+ */
+ private class EditTextShortcutPopupWindow extends PinnedPopupWindow
+ implements OnClickListener {
+ private static final int POPUP_TEXT_LAYOUT =
+ com.android.internal.R.layout.text_edit_action_popup_text;
+ private TextView mDeleteTextView;
+ private EasyEditSpan mEditTextShortcutSpan;
+
+ @Override
+ protected void createPopupWindow() {
+ mPopupWindow = new PopupWindow(TextView.this.mContext, null,
+ com.android.internal.R.attr.textSelectHandleWindowStyle);
+ mPopupWindow.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED);
+ mPopupWindow.setClippingEnabled(true);
+ }
+
+ @Override
+ protected void initContentView() {
+ mContentView.setOrientation(LinearLayout.HORIZONTAL);
+ mContentView.setBackgroundResource(
+ com.android.internal.R.drawable.text_edit_side_paste_window);
+
+ LayoutInflater inflater = (LayoutInflater)TextView.this.mContext.
+ getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+
+ LayoutParams wrapContent = new LayoutParams(
+ ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+
+ mDeleteTextView = (TextView) inflater.inflate(POPUP_TEXT_LAYOUT, null);
+ mDeleteTextView.setLayoutParams(wrapContent);
+ mDeleteTextView.setText(com.android.internal.R.string.delete);
+ mDeleteTextView.setOnClickListener(this);
+ mContentView.addView(mDeleteTextView);
+ }
+
+ public void show(EasyEditSpan inputMethodSpan) {
+ mEditTextShortcutSpan = inputMethodSpan;
+ super.show();
+ }
+
+ @Override
+ public void onClick(View view) {
+ if (view == mDeleteTextView) {
+ deleteText();
+ }
+ }
+
+ private void deleteText() {
+ Editable editable = (Editable) mText;
+ int start = editable.getSpanStart(mEditTextShortcutSpan);
+ int end = editable.getSpanEnd(mEditTextShortcutSpan);
+ if (start >= 0 && end >= 0) {
+ editable.delete(start, end);
+ }
+ }
+
+ @Override
+ protected int getTextOffset() {
+ // Place the pop-up at the end of the span
+ Editable editable = (Editable) mText;
+ return editable.getSpanEnd(mEditTextShortcutSpan);
+ }
+
+ @Override
+ protected int getVerticalLocalPosition(int line) {
+ return mLayout.getLineBottom(line);
+ }
+
+ @Override
+ protected int clipVertically(int positionY) {
+ // As we display the pop-up below the span, no vertical clipping is required.
+ return positionY;
+ }
+ }
+
private class ChangeWatcher implements TextWatcher, SpanWatcher {
private CharSequence mBeforeText;
+ private EditTextShortcutController mEditTextShortcutController;
+
+ private ChangeWatcher() {
+ mEditTextShortcutController = new EditTextShortcutController();
+ }
+
public void beforeTextChanged(CharSequence buffer, int start,
int before, int after) {
if (DEBUG_EXTRACT) Log.v(LOG_TAG, "beforeTextChanged start=" + start
@@ -7729,6 +7955,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
+ " before=" + before + " after=" + after + ": " + buffer);
TextView.this.handleTextChanged(buffer, start, before, after);
+ mEditTextShortcutController.onTextChange(buffer);
+
if (AccessibilityManager.getInstance(mContext).isEnabled() &&
(isFocused() || isSelected() && isShown())) {
sendAccessibilityEventTypeViewTextChanged(mBeforeText, start, before, after);
@@ -7763,6 +7991,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
+ " what=" + what + ": " + buf);
TextView.this.spanChange(buf, what, s, -1, e, -1);
}
+
+ private void hideControllers() {
+ mEditTextShortcutController.hide();
+ }
}
/**
@@ -8261,7 +8493,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
@Override
protected float getLeftFadingEdgeStrength() {
if (mCurrentAlpha <= ViewConfiguration.ALPHA_THRESHOLD_INT) return 0.0f;
- if (mEllipsize == TextUtils.TruncateAt.MARQUEE) {
+ if (mEllipsize == TextUtils.TruncateAt.MARQUEE &&
+ mMarqueeFadeMode != MARQUEE_FADE_SWITCH_SHOW_ELLIPSIS) {
if (mMarquee != null && !mMarquee.isStopped()) {
final Marquee marquee = mMarquee;
if (marquee.shouldDrawLeftFade()) {
@@ -8290,7 +8523,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
@Override
protected float getRightFadingEdgeStrength() {
if (mCurrentAlpha <= ViewConfiguration.ALPHA_THRESHOLD_INT) return 0.0f;
- if (mEllipsize == TextUtils.TruncateAt.MARQUEE) {
+ if (mEllipsize == TextUtils.TruncateAt.MARQUEE &&
+ mMarqueeFadeMode != MARQUEE_FADE_SWITCH_SHOW_ELLIPSIS) {
if (mMarquee != null && !mMarquee.isStopped()) {
final Marquee marquee = mMarquee;
return (marquee.mMaxFadeScroll - marquee.mScroll) / getHorizontalFadingEdgeLength();
@@ -8928,6 +9162,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
stopSelectionActionMode();
} else {
selectCurrentWord();
+ getSelectionController().show();
}
handled = true;
}
@@ -9183,6 +9418,34 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
}
+ private static class SuggestionRangeSpan extends CharacterStyle {
+
+ private final int mTextColor;
+ private final int mBackgroundColor;
+
+ public SuggestionRangeSpan(Context context) {
+ TypedArray typedArray = context.obtainStyledAttributes(null,
+ com.android.internal.R.styleable.SuggestionRangeSpan,
+ com.android.internal.R.attr.textAppearanceSuggestionRange, 0);
+
+ mTextColor = typedArray.getColor(
+ com.android.internal.R.styleable.SuggestionRangeSpan_textColor, 0);
+ mBackgroundColor = typedArray.getColor(
+ com.android.internal.R.styleable.SuggestionRangeSpan_colorBackground, 0);
+ }
+
+ @Override
+ public void updateDrawState(TextPaint tp) {
+ if (mTextColor != 0) {
+ tp.setColor(mTextColor);
+ }
+
+ if (mBackgroundColor != 0) {
+ tp.bgColor = mBackgroundColor;
+ }
+ }
+ }
+
private class SuggestionsPopupWindow extends PinnedPopupWindow implements OnClickListener {
private static final int MAX_NUMBER_SUGGESTIONS = SuggestionSpan.SUGGESTIONS_MAX_SIZE;
private static final int NO_SUGGESTIONS = -1;
@@ -9367,7 +9630,15 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
if (totalNbSuggestions == 0) return false;
- if (mSuggestionRangeSpan == null) mSuggestionRangeSpan = new SuggestionRangeSpan();
+ if (mSuggestionRangeSpan == null) {
+ mSuggestionRangeSpan = new SuggestionRangeSpan(getContext());
+ }
+
+ ((Editable) mText).setSpan(mSuggestionRangeSpan, spanUnionStart, spanUnionEnd,
+ Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+
+ if (mSuggestionRangeSpan == null) mSuggestionRangeSpan =
+ new SuggestionRangeSpan(getContext());
((Editable) mText).setSpan(mSuggestionRangeSpan, spanUnionStart, spanUnionEnd,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
@@ -10694,6 +10965,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
private void hideControllers() {
hideInsertionPointCursorController();
stopSelectionActionMode();
+
+ if (mChangeWatcher != null) {
+ mChangeWatcher.hideControllers();
+ }
}
/**
diff --git a/core/java/com/android/internal/widget/TransportControlView.java b/core/java/com/android/internal/widget/TransportControlView.java
index 3961de3..1c47ca8 100644
--- a/core/java/com/android/internal/widget/TransportControlView.java
+++ b/core/java/com/android/internal/widget/TransportControlView.java
@@ -16,88 +16,369 @@
package com.android.internal.widget;
-import com.android.internal.R;
+import java.lang.ref.WeakReference;
+
+import com.android.internal.widget.LockScreenWidgetCallback;
+import com.android.internal.widget.LockScreenWidgetInterface;
+import android.content.ComponentName;
import android.content.Context;
+import android.content.Intent;
+import android.graphics.Bitmap;
import android.media.AudioManager;
+import android.media.MediaMetadataRetriever;
+import android.media.RemoteControlClient;
+import android.media.IRemoteControlDisplay;
+import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
+import android.os.RemoteException;
+import android.text.Spannable;
+import android.text.TextUtils;
+import android.text.style.ForegroundColorSpan;
import android.util.AttributeSet;
+import android.util.Log;
+import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
-import android.widget.LinearLayout;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.TextView;
-/**
- * A special widget for displaying audio playback ("transport controls") in LockScreen.
- *
- */
-public class TransportControlView extends LinearLayout implements LockScreenWidgetInterface,
- OnClickListener {
- private static final String TAG = "TransportControlView";
- static final int sViewIds[] = { R.id.control_prev, R.id.control_pauseplay, R.id.control_next };
- protected static final int AUDIO_FOCUS_CHANGED = 100;
- private LockScreenWidgetCallback mCallback;
+import com.android.internal.R;
+
+public class TransportControlView extends FrameLayout implements OnClickListener,
+ LockScreenWidgetInterface {
+
+ private static final int MSG_UPDATE_STATE = 100;
+ private static final int MSG_SET_METADATA = 101;
+ private static final int MSG_SET_TRANSPORT_CONTROLS = 102;
+ private static final int MSG_SET_ARTWORK = 103;
+ private static final int MSG_SET_GENERATION_ID = 104;
+ private static final int MAXDIM = 512;
+ protected static final boolean DEBUG = true;
+ protected static final String TAG = "TransportControlView";
+
+ private ImageView mAlbumArt;
+ private TextView mTrackTitle;
+ private ImageView mBtnPrev;
+ private ImageView mBtnPlay;
+ private ImageView mBtnNext;
+ private int mClientGeneration;
+ private Metadata mMetadata = new Metadata();
+ private boolean mAttached;
+ private ComponentName mClientName;
+ private int mTransportControlFlags;
+ private int mPlayState;
+ private AudioManager mAudioManager;
+ private LockScreenWidgetCallback mWidgetCallbacks;
+ private IRemoteControlDisplayWeak mIRCD;
+
+ /**
+ * The metadata which should be populated into the view once we've been attached
+ */
+ private Bundle mPopulateMetadataWhenAttached = null;
+
+ // This handler is required to ensure messages from IRCD are handled in sequence and on
+ // the UI thread.
private Handler mHandler = new Handler() {
+ @Override
public void handleMessage(Message msg) {
- switch (msg.what){
- case AUDIO_FOCUS_CHANGED:
- handleAudioFocusChange(msg.arg1);
+ switch (msg.what) {
+ case MSG_UPDATE_STATE:
+ if (mClientGeneration == msg.arg1) updatePlayPauseState(msg.arg2);
+ break;
+
+ case MSG_SET_METADATA:
+ if (mClientGeneration == msg.arg1) updateMetadata((Bundle) msg.obj);
+ break;
+
+ case MSG_SET_TRANSPORT_CONTROLS:
+ if (mClientGeneration == msg.arg1) updateTransportControls(msg.arg2);
+ break;
+
+ case MSG_SET_ARTWORK:
+ if (mClientGeneration == msg.arg1) {
+ mMetadata.bitmap = (Bitmap) msg.obj;
+ mAlbumArt.setImageBitmap(mMetadata.bitmap);
+ }
+ break;
+
+ case MSG_SET_GENERATION_ID:
+ if (mWidgetCallbacks != null) {
+ boolean clearing = msg.arg2 != 0;
+ if (DEBUG) Log.v(TAG, "New genId = " + msg.arg1 + ", clearing = " + clearing);
+ if (!clearing) {
+ mWidgetCallbacks.requestShow(TransportControlView.this);
+ } else {
+ mWidgetCallbacks.requestHide(TransportControlView.this);
+ }
+ }
+ mClientGeneration = msg.arg1;
+ mClientName = (ComponentName) msg.obj;
+ break;
+
}
}
};
- AudioManager.OnAudioFocusChangeListener mAudioFocusChangeListener =
- new AudioManager.OnAudioFocusChangeListener() {
- public void onAudioFocusChange(final int focusChange) {
- mHandler.obtainMessage(AUDIO_FOCUS_CHANGED, focusChange, 0).sendToTarget();
+ /**
+ * This class is required to have weak linkage to the current TransportControlView
+ * because the remote process can hold a strong reference to this binder object and
+ * we can't predict when it will be GC'd in the remote process. Without this code, it
+ * would allow a heavyweight object to be held on this side of the binder when there's
+ * no requirement to run a GC on the other side.
+ */
+ private static class IRemoteControlDisplayWeak extends IRemoteControlDisplay.Stub {
+ private WeakReference<Handler> mLocalHandler;
+
+ IRemoteControlDisplayWeak(Handler handler) {
+ mLocalHandler = new WeakReference<Handler>(handler);
+ }
+
+ public void setPlaybackState(int generationId, int state) {
+ Handler handler = mLocalHandler.get();
+ if (handler != null) {
+ handler.obtainMessage(MSG_UPDATE_STATE, generationId, state).sendToTarget();
}
- };
+ }
- public TransportControlView(Context context) {
- this(context, null);
- }
+ public void setMetadata(int generationId, Bundle metadata) {
+ Handler handler = mLocalHandler.get();
+ if (handler != null) {
+ handler.obtainMessage(MSG_SET_METADATA, generationId, 0, metadata).sendToTarget();
+ }
+ }
+
+ public void setTransportControlFlags(int generationId, int flags) {
+ Handler handler = mLocalHandler.get();
+ if (handler != null) {
+ handler.obtainMessage(MSG_SET_TRANSPORT_CONTROLS, generationId, flags)
+ .sendToTarget();
+ }
+ }
+
+ public void setArtwork(int generationId, Bitmap bitmap) {
+ Handler handler = mLocalHandler.get();
+ if (handler != null) {
+ handler.obtainMessage(MSG_SET_ARTWORK, generationId, 0, bitmap).sendToTarget();
+ }
+ }
+
+ public void setAllMetadata(int generationId, Bundle metadata, Bitmap bitmap) {
+ Handler handler = mLocalHandler.get();
+ if (handler != null) {
+ handler.obtainMessage(MSG_SET_METADATA, generationId, 0, metadata).sendToTarget();
+ handler.obtainMessage(MSG_SET_ARTWORK, generationId, 0, bitmap).sendToTarget();
+ }
+ }
+
+ public void setCurrentClientId(int clientGeneration, ComponentName clientEventReceiver,
+ boolean clearing) throws RemoteException {
+ Handler handler = mLocalHandler.get();
+ if (handler != null) {
+ handler.obtainMessage(MSG_SET_GENERATION_ID,
+ clientGeneration, (clearing ? 1 : 0), clientEventReceiver).sendToTarget();
+ }
+ }
+ };
public TransportControlView(Context context, AttributeSet attrs) {
super(context, attrs);
+ Log.v(TAG, "Create TCV " + this);
+ mAudioManager = new AudioManager(mContext);
+ mIRCD = new IRemoteControlDisplayWeak(mHandler);
}
- protected void handleAudioFocusChange(int focusChange) {
- // TODO
+ private void updateTransportControls(int transportControlFlags) {
+ mTransportControlFlags = transportControlFlags;
}
- public void setCallback(LockScreenWidgetCallback callback) {
- mCallback = callback;
+ @Override
+ public void onFinishInflate() {
+ super.onFinishInflate();
+ mTrackTitle = (TextView) findViewById(R.id.title);
+ mTrackTitle.setSelected(true); // enable marquee
+ mAlbumArt = (ImageView) findViewById(R.id.albumart);
+ mBtnPrev = (ImageView) findViewById(R.id.btn_prev);
+ mBtnPlay = (ImageView) findViewById(R.id.btn_play);
+ mBtnNext = (ImageView) findViewById(R.id.btn_next);
+ final View buttons[] = { mBtnPrev, mBtnPlay, mBtnNext };
+ for (View view : buttons) {
+ view.setOnClickListener(this);
+ }
}
@Override
- public void onFinishInflate() {
- for (int i = 0; i < sViewIds.length; i++) {
- View view = findViewById(sViewIds[i]);
- if (view != null) {
- view.setOnClickListener(this);
+ public void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ if (mPopulateMetadataWhenAttached != null) {
+ updateMetadata(mPopulateMetadataWhenAttached);
+ mPopulateMetadataWhenAttached = null;
+ }
+ if (!mAttached) {
+ if (DEBUG) Log.v(TAG, "Registering TCV " + this);
+ mAudioManager.registerRemoteControlDisplay(mIRCD);
+ }
+ mAttached = true;
+ }
+
+ @Override
+ public void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+ if (mAttached) {
+ if (DEBUG) Log.v(TAG, "Unregistering TCV " + this);
+ mAudioManager.unregisterRemoteControlDisplay(mIRCD);
+ }
+ mAttached = false;
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ int dim = Math.min(MAXDIM, Math.max(getWidth(), getHeight()));
+// Log.v(TAG, "setting max bitmap size: " + dim + "x" + dim);
+// mAudioManager.remoteControlDisplayUsesBitmapSize(mIRCD, dim, dim);
+ }
+
+ class Metadata {
+ private String artist;
+ private String trackTitle;
+ private String albumTitle;
+ private Bitmap bitmap;
+
+ public String toString() {
+ return "Metadata[artist=" + artist + " trackTitle=" + trackTitle + " albumTitle=" + albumTitle + "]";
+ }
+ }
+
+ private String getMdString(Bundle data, int id) {
+ return data.getString(Integer.toString(id));
+ }
+
+ private void updateMetadata(Bundle data) {
+ if (mAttached) {
+ mMetadata.artist = getMdString(data, MediaMetadataRetriever.METADATA_KEY_ALBUMARTIST);
+ mMetadata.trackTitle = getMdString(data, MediaMetadataRetriever.METADATA_KEY_TITLE);
+ mMetadata.albumTitle = getMdString(data, MediaMetadataRetriever.METADATA_KEY_ALBUM);
+ populateMetadata();
+ } else {
+ mPopulateMetadataWhenAttached = data;
+ }
+ }
+
+ /**
+ * Populates the given metadata into the view
+ */
+ private void populateMetadata() {
+ StringBuilder sb = new StringBuilder();
+ int trackTitleLength = 0;
+ if (!TextUtils.isEmpty(mMetadata.trackTitle)) {
+ sb.append(mMetadata.trackTitle);
+ trackTitleLength = mMetadata.trackTitle.length();
+ }
+ if (!TextUtils.isEmpty(mMetadata.artist)) {
+ if (sb.length() != 0) {
+ sb.append(" - ");
+ }
+ sb.append(mMetadata.artist);
+ }
+ if (!TextUtils.isEmpty(mMetadata.albumTitle)) {
+ if (sb.length() != 0) {
+ sb.append(" - ");
}
+ sb.append(mMetadata.albumTitle);
+ }
+ mTrackTitle.setText(sb.toString(), TextView.BufferType.SPANNABLE);
+ Spannable str = (Spannable) mTrackTitle.getText();
+ if (trackTitleLength != 0) {
+ str.setSpan(new ForegroundColorSpan(0xffffffff), 0, trackTitleLength,
+ Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+ trackTitleLength++;
+ }
+ if (sb.length() > trackTitleLength) {
+ str.setSpan(new ForegroundColorSpan(0x7fffffff), trackTitleLength, sb.length(),
+ Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
+
+ mAlbumArt.setImageBitmap(mMetadata.bitmap);
+ final int flags = mTransportControlFlags;
+ setVisibilityBasedOnFlag(mBtnPrev, flags, RemoteControlClient.FLAG_KEY_MEDIA_PREVIOUS);
+ setVisibilityBasedOnFlag(mBtnNext, flags, RemoteControlClient.FLAG_KEY_MEDIA_NEXT);
+ setVisibilityBasedOnFlag(mBtnPrev, flags,
+ RemoteControlClient.FLAG_KEY_MEDIA_PLAY
+ | RemoteControlClient.FLAG_KEY_MEDIA_PAUSE
+ | RemoteControlClient.FLAG_KEY_MEDIA_PLAY_PAUSE
+ | RemoteControlClient.FLAG_KEY_MEDIA_STOP);
+
+ updatePlayPauseState(mPlayState);
}
- public void onClick(View v) {
- switch (v.getId()) {
- case R.id.control_prev:
- // TODO
+ private static void setVisibilityBasedOnFlag(View view, int flags, int flag) {
+ if ((flags & flag) != 0) {
+ view.setVisibility(View.VISIBLE);
+ } else {
+ view.setVisibility(View.GONE);
+ }
+ }
+
+ private void updatePlayPauseState(int state) {
+ if (DEBUG) Log.v(TAG,
+ "updatePlayPauseState(), old=" + mPlayState + ", state=" + state);
+ if (state == mPlayState) {
+ return;
+ }
+ switch (state) {
+ case RemoteControlClient.PLAYSTATE_PLAYING:
+ mBtnPlay.setImageResource(com.android.internal.R.drawable.ic_media_pause);
break;
- case R.id.control_pauseplay:
- // TODO
+ case RemoteControlClient.PLAYSTATE_BUFFERING:
+ mBtnPlay.setImageResource(com.android.internal.R.drawable.ic_media_stop);
break;
- case R.id.control_next:
- // TODO
+ case RemoteControlClient.PLAYSTATE_PAUSED:
+ default:
+ mBtnPlay.setImageResource(com.android.internal.R.drawable.ic_media_play);
break;
}
- // Have any button click extend lockscreen's timeout.
- if (mCallback != null) {
- mCallback.userActivity(this);
+ mPlayState = state;
+ }
+
+ public void onClick(View v) {
+ int keyCode = -1;
+ if (v == mBtnPrev) {
+ keyCode = KeyEvent.KEYCODE_MEDIA_PREVIOUS;
+ } else if (v == mBtnNext) {
+ keyCode = KeyEvent.KEYCODE_MEDIA_NEXT;
+ } else if (v == mBtnPlay) {
+ keyCode = KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE;
+
+ }
+ if (keyCode != -1) {
+ sendMediaButtonClick(keyCode);
+ if (mWidgetCallbacks != null) {
+ mWidgetCallbacks.userActivity(this);
+ }
}
}
+ private void sendMediaButtonClick(int keyCode) {
+ // TODO: target to specific player based on mClientName
+ KeyEvent keyEvent = new KeyEvent(KeyEvent.ACTION_DOWN, keyCode);
+ Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON);
+ intent.putExtra(Intent.EXTRA_KEY_EVENT, keyEvent);
+ getContext().sendOrderedBroadcast(intent, null);
+
+ keyEvent = new KeyEvent(KeyEvent.ACTION_UP, keyCode);
+ intent = new Intent(Intent.ACTION_MEDIA_BUTTON);
+ intent.putExtra(Intent.EXTRA_KEY_EVENT, keyEvent);
+ getContext().sendOrderedBroadcast(intent, null);
+ }
+
+ public void setCallback(LockScreenWidgetCallback callback) {
+ mWidgetCallbacks = callback;
+ }
+
}
diff --git a/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java b/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java
index ec926e4..76bc535 100644
--- a/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java
+++ b/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java
@@ -16,8 +16,6 @@
package com.android.internal.widget.multiwaveview;
-import java.util.ArrayList;
-
import android.animation.Animator;
import android.animation.Animator.AnimatorListener;
import android.animation.AnimatorListenerAdapter;
@@ -31,15 +29,20 @@ import android.graphics.Canvas;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.os.Vibrator;
+import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.View;
-import android.view.View.MeasureSpec;
+import android.view.ViewConfiguration;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityManager;
import com.android.internal.R;
+import java.util.ArrayList;
+
/**
* A special widget containing a center and outer ring. Moving the center ring to the outer ring
* causes an event that can be caught by implementing OnTriggerListener.
@@ -82,6 +85,8 @@ public class MultiWaveView extends View {
private ArrayList<TargetDrawable> mChevronDrawables = new ArrayList<TargetDrawable>();
private ArrayList<Tweener> mChevronAnimations = new ArrayList<Tweener>();
private ArrayList<Tweener> mTargetAnimations = new ArrayList<Tweener>();
+ private ArrayList<String> mTargetDescriptions;
+ private ArrayList<String> mDirectionDescriptions;
private Tweener mHandleAnimation;
private OnTriggerListener mOnTriggerListener;
private TargetDrawable mHandleDrawable;
@@ -103,6 +108,9 @@ public class MultiWaveView extends View {
private boolean mDragging;
private int mNewTargetResources;
+ private boolean mWaveHovered = false;
+ private long mLastHoverExitTimeMillis = 0;
+
private AnimatorListener mResetListener = new AnimatorListenerAdapter() {
public void onAnimationEnd(Animator animator) {
switchToState(STATE_IDLE, mWaveCenterX, mWaveCenterY);
@@ -128,6 +136,8 @@ public class MultiWaveView extends View {
}
};
private int mTargetResourceId;
+ private int mTargetDescriptionsResourceId;
+ private int mDirectionDescriptionsResourceId;
public MultiWaveView(Context context) {
this(context, null);
@@ -177,6 +187,25 @@ public class MultiWaveView extends View {
throw new IllegalStateException("Must specify at least one target drawable");
}
+ // Read array of target descriptions
+ if (a.getValue(R.styleable.MultiWaveView_targetDescriptions, outValue)) {
+ final int resourceId = outValue.resourceId;
+ if (resourceId == 0) {
+ throw new IllegalStateException("Must specify target descriptions");
+ }
+ setTargetDescriptionsResourceId(resourceId);
+ }
+
+ // Read array of direction descriptions
+ if (a.getValue(R.styleable.MultiWaveView_directionDescriptions, outValue)) {
+ final int resourceId = outValue.resourceId;
+ if (resourceId == 0) {
+ throw new IllegalStateException("Must specify direction descriptions");
+ }
+ setDirectionDescriptionsResourceId(resourceId);
+ }
+
+ a.recycle();
setVibrateEnabled(mVibrationDuration > 0);
}
@@ -247,6 +276,9 @@ public class MultiWaveView extends View {
showTargets(true);
mHandleDrawable.setState(TargetDrawable.STATE_ACTIVE);
setGrabbedState(OnTriggerListener.CENTER_HANDLE);
+ if (AccessibilityManager.getInstance(mContext).isEnabled()) {
+ announceTargets();
+ }
break;
case STATE_TRACKING:
@@ -347,6 +379,13 @@ public class MultiWaveView extends View {
}
}
+ private void dispatchGrabbedEvent(int whichHandler) {
+ vibrate();
+ if (mOnTriggerListener != null) {
+ mOnTriggerListener.onGrabbed(this, whichHandler);
+ }
+ }
+
private void doFinish() {
final int activeTarget = mActiveTarget;
boolean targetHit = activeTarget != -1;
@@ -475,6 +514,7 @@ public class MultiWaveView extends View {
Drawable drawable = array.getDrawable(i);
targetDrawables.add(new TargetDrawable(res, drawable));
}
+ array.recycle();
mTargetResourceId = resourceId;
mTargetDrawables = targetDrawables;
updateTargetPositions();
@@ -499,6 +539,48 @@ public class MultiWaveView extends View {
}
/**
+ * Sets the resource id specifying the target descriptions for accessibility.
+ *
+ * @param resourceId The resource id.
+ */
+ public void setTargetDescriptionsResourceId(int resourceId) {
+ mTargetDescriptionsResourceId = resourceId;
+ if (mTargetDescriptions != null) {
+ mTargetDescriptions.clear();
+ }
+ }
+
+ /**
+ * Gets the resource id specifying the target descriptions for accessibility.
+ *
+ * @return The resource id.
+ */
+ public int getTargetDescriptionsResourceId() {
+ return mTargetDescriptionsResourceId;
+ }
+
+ /**
+ * Sets the resource id specifying the target direction descriptions for accessibility.
+ *
+ * @param resourceId The resource id.
+ */
+ public void setDirectionDescriptionsResourceId(int resourceId) {
+ mDirectionDescriptionsResourceId = resourceId;
+ if (mDirectionDescriptions != null) {
+ mDirectionDescriptions.clear();
+ }
+ }
+
+ /**
+ * Gets the resource id specifying the target direction descriptions.
+ *
+ * @return The resource id.
+ */
+ public int getDirectionDescriptionsResourceId() {
+ return mDirectionDescriptionsResourceId;
+ }
+
+ /**
* Enable or disable vibrate on touch.
*
* @param enabled
@@ -593,6 +675,43 @@ public class MultiWaveView extends View {
}
}
+ @Override
+ public boolean onHoverEvent(MotionEvent event) {
+ if (AccessibilityManager.getInstance(mContext).isTouchExplorationEnabled()) {
+ final int action = event.getAction();
+ switch (action) {
+ case MotionEvent.ACTION_HOVER_ENTER:
+ case MotionEvent.ACTION_HOVER_MOVE:
+ final float dx = event.getX() - mWaveCenterX;
+ final float dy = event.getY() - mWaveCenterY;
+ if (dist2(dx,dy) <= square(mTapRadius)) {
+ if (!mWaveHovered) {
+ mWaveHovered = true;
+ final long timeSinceLastHoverExitMillis =
+ event.getEventTime() - mLastHoverExitTimeMillis;
+ final long recurringEventsInterval =
+ ViewConfiguration.getSendRecurringAccessibilityEventsInterval();
+ if (timeSinceLastHoverExitMillis > recurringEventsInterval) {
+ String text =
+ mContext.getString(R.string.content_description_sliding_handle);
+ announceText(text);
+ }
+ }
+ } else {
+ mWaveHovered = false;
+ }
+ break;
+ case MotionEvent.ACTION_HOVER_EXIT:
+ mLastHoverExitTimeMillis = event.getEventTime();
+ mWaveHovered = false;
+ break;
+ default:
+ mWaveHovered = false;
+ }
+ }
+ return super.onHoverEvent(event);
+ }
+
private void handleUp(MotionEvent event) {
if (DEBUG && mDragging) Log.v(TAG, "** Handle RELEASE");
switchToState(STATE_FINISH, event.getX(), event.getY());
@@ -663,7 +782,11 @@ public class MultiWaveView extends View {
invalidateGlobalRegion(mHandleDrawable);
if (mActiveTarget != activeTarget && activeTarget != -1) {
- vibrate();
+ dispatchGrabbedEvent(activeTarget);
+ if (AccessibilityManager.getInstance(mContext).isEnabled()) {
+ String targetContentDescription = getTargetDescription(activeTarget);
+ announceText(targetContentDescription);
+ }
}
mActiveTarget = activeTarget;
}
@@ -771,4 +894,62 @@ public class MultiWaveView extends View {
return dx*dx + dy*dy;
}
-} \ No newline at end of file
+ private void announceTargets() {
+ StringBuilder utterance = new StringBuilder();
+ final int targetCount = mTargetDrawables.size();
+ for (int i = 0; i < targetCount; i++) {
+ String targetDescription = getTargetDescription(i);
+ String directionDescription = getDirectionDescription(i);
+ if (!TextUtils.isEmpty(targetDescription)
+ && !TextUtils.isEmpty(directionDescription)) {
+ utterance.append(targetDescription);
+ utterance.append(" ");
+ utterance.append(directionDescription);
+ utterance.append(".");
+ }
+ }
+ announceText(utterance.toString());
+ }
+
+ private void announceText(String text) {
+ setContentDescription(text);
+ sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
+ setContentDescription(null);
+ }
+
+ private String getTargetDescription(int index) {
+ if (mTargetDescriptions == null || mTargetDescriptions.isEmpty()) {
+ mTargetDescriptions = loadDescriptions(mTargetDescriptionsResourceId);
+ if (mTargetDrawables.size() != mTargetDescriptions.size()) {
+ Log.w(TAG, "The number of target drawables must be"
+ + " euqal to the number of target descriptions.");
+ return null;
+ }
+ }
+ return mTargetDescriptions.get(index);
+ }
+
+ private String getDirectionDescription(int index) {
+ if (mDirectionDescriptions == null || mDirectionDescriptions.isEmpty()) {
+ mDirectionDescriptions = loadDescriptions(mDirectionDescriptionsResourceId);
+ if (mTargetDrawables.size() != mDirectionDescriptions.size()) {
+ Log.w(TAG, "The number of target drawables must be"
+ + " euqal to the number of direction descriptions.");
+ return null;
+ }
+ }
+ return mDirectionDescriptions.get(index);
+ }
+
+ private ArrayList<String> loadDescriptions(int resourceId) {
+ TypedArray array = getContext().getResources().obtainTypedArray(resourceId);
+ final int count = array.length();
+ ArrayList<String> targetContentDescriptions = new ArrayList<String>(count);
+ for (int i = 0; i < count; i++) {
+ String contentDescription = array.getString(i);
+ targetContentDescriptions.add(contentDescription);
+ }
+ array.recycle();
+ return targetContentDescriptions;
+ }
+}
diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp
index 4cf4afa..494a2b3 100644
--- a/core/jni/android_util_Binder.cpp
+++ b/core/jni/android_util_Binder.cpp
@@ -119,6 +119,11 @@ static struct binderproxy_offsets_t
} gBinderProxyOffsets;
+static struct class_offsets_t
+{
+ jmethodID mGetName;
+} gClassOffsets;
+
// ----------------------------------------------------------------------------
static struct parcel_offsets_t
@@ -452,22 +457,18 @@ public:
// Okay, something is wrong -- we have a hard reference to a live death
// recipient on the VM side, but the list is being torn down.
JNIEnv* env = javavm_to_jnienv(mVM);
- ScopedLocalRef<jclass> classRef(env, env->GetObjectClass(mObject));
- jmethodID getnameMethod = env->GetMethodID(classRef.get(),
- "getName", "()Ljava/lang/String;");
- if (getnameMethod) {
- ScopedLocalRef<jstring> nameRef(env,
- (jstring) env->CallObjectMethod(classRef.get(), getnameMethod));
- ScopedUtfChars nameUtf(env, nameRef.get());
- if (nameUtf.c_str() != NULL) {
- LOGW("BinderProxy is being destroyed but the application did not call "
- "unlinkToDeath to unlink all of its death recipients beforehand. "
- "Releasing leaked death recipient: %s", nameUtf.c_str());
- } else {
- LOGW("BinderProxy being destroyed; unable to get DR object name");
- env->ExceptionClear();
- }
- } else LOGW("BinderProxy being destroyed; unable to find DR class getName");
+ ScopedLocalRef<jclass> objClassRef(env, env->GetObjectClass(mObject));
+ ScopedLocalRef<jstring> nameRef(env,
+ (jstring) env->CallObjectMethod(objClassRef.get(), gClassOffsets.mGetName));
+ ScopedUtfChars nameUtf(env, nameRef.get());
+ if (nameUtf.c_str() != NULL) {
+ LOGW("BinderProxy is being destroyed but the application did not call "
+ "unlinkToDeath to unlink all of its death recipients beforehand. "
+ "Releasing leaked death recipient: %s", nameUtf.c_str());
+ } else {
+ LOGW("BinderProxy being destroyed; unable to get DR object name");
+ env->ExceptionClear();
+ }
}
}
@@ -1230,6 +1231,11 @@ static int int_register_android_os_BinderProxy(JNIEnv* env)
= env->GetFieldID(clazz, "mOrgue", "I");
assert(gBinderProxyOffsets.mOrgue);
+ clazz = env->FindClass("java/lang/Class");
+ LOG_FATAL_IF(clazz == NULL, "Unable to find java.lang.Class");
+ gClassOffsets.mGetName = env->GetMethodID(clazz, "getName", "()Ljava/lang/String;");
+ assert(gClassOffsets.mGetName);
+
return AndroidRuntime::registerNativeMethods(
env, kBinderProxyPathName,
gBinderProxyMethods, NELEM(gBinderProxyMethods));
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index 4c1ca31..49441eb 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -589,7 +589,7 @@ static void Surface_setLayer(
}
static void Surface_setPosition(
- JNIEnv* env, jobject clazz, jint x, jint y)
+ JNIEnv* env, jobject clazz, jfloat x, jfloat y)
{
const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
if (surface == 0) return;
@@ -832,7 +832,7 @@ static JNINativeMethod gSurfaceMethods[] = {
{"screenshot", "(II)Landroid/graphics/Bitmap;", (void*)Surface_screenshotAll },
{"screenshot", "(IIII)Landroid/graphics/Bitmap;", (void*)Surface_screenshot },
{"setLayer", "(I)V", (void*)Surface_setLayer },
- {"setPosition", "(II)V",(void*)Surface_setPosition },
+ {"setPosition", "(FF)V",(void*)Surface_setPosition },
{"setSize", "(II)V",(void*)Surface_setSize },
{"hide", "()V", (void*)Surface_hide },
{"show", "()V", (void*)Surface_show },
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 540c65a..01f2a8f 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -93,6 +93,9 @@
<protected-broadcast android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
<protected-broadcast android:name="android.hardware.usb.action.USB_DEVICE_DETACHED" />
+ <protected-broadcast android:name="android.net.conn.CONNECTIVITY_CHANGE" />
+ <protected-broadcast android:name="android.net.conn.CONNECTIVITY_CHANGE_IMMEDIATE" />
+
<protected-broadcast android:name="android.nfc.action.LLCP_LINK_STATE_CHANGED" />
<protected-broadcast android:name="com.android.nfc_extras.action.RF_FIELD_ON_DETECTED" />
<protected-broadcast android:name="com.android.nfc_extras.action.RF_FIELD_OFF_DETECTED" />
diff --git a/core/res/res/drawable-hdpi/ab_bottom_solid_dark_holo.9.png b/core/res/res/drawable-hdpi/ab_bottom_solid_dark_holo.9.png
index 81829bb..769463b 100644
--- a/core/res/res/drawable-hdpi/ab_bottom_solid_dark_holo.9.png
+++ b/core/res/res/drawable-hdpi/ab_bottom_solid_dark_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ab_bottom_solid_inverse_holo.9.png b/core/res/res/drawable-hdpi/ab_bottom_solid_inverse_holo.9.png
index 0436801..88f11dc 100644
--- a/core/res/res/drawable-hdpi/ab_bottom_solid_inverse_holo.9.png
+++ b/core/res/res/drawable-hdpi/ab_bottom_solid_inverse_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ab_bottom_solid_light_holo.9.png b/core/res/res/drawable-hdpi/ab_bottom_solid_light_holo.9.png
index 6574c8c..7305047 100644
--- a/core/res/res/drawable-hdpi/ab_bottom_solid_light_holo.9.png
+++ b/core/res/res/drawable-hdpi/ab_bottom_solid_light_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ab_bottom_transparent_dark_holo.9.png b/core/res/res/drawable-hdpi/ab_bottom_transparent_dark_holo.9.png
index 1565ac2..712a551 100644
--- a/core/res/res/drawable-hdpi/ab_bottom_transparent_dark_holo.9.png
+++ b/core/res/res/drawable-hdpi/ab_bottom_transparent_dark_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ab_bottom_transparent_light_holo.9.png b/core/res/res/drawable-hdpi/ab_bottom_transparent_light_holo.9.png
index 77d4c4b..bf3b943 100644
--- a/core/res/res/drawable-hdpi/ab_bottom_transparent_light_holo.9.png
+++ b/core/res/res/drawable-hdpi/ab_bottom_transparent_light_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ab_solid_dark_holo.9.png b/core/res/res/drawable-hdpi/ab_solid_dark_holo.9.png
index 0fc8632..cbbaec5 100644
--- a/core/res/res/drawable-hdpi/ab_solid_dark_holo.9.png
+++ b/core/res/res/drawable-hdpi/ab_solid_dark_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ab_solid_light_holo.9.png b/core/res/res/drawable-hdpi/ab_solid_light_holo.9.png
index 74540c1..af917e5 100644
--- a/core/res/res/drawable-hdpi/ab_solid_light_holo.9.png
+++ b/core/res/res/drawable-hdpi/ab_solid_light_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ab_solid_shadow_holo.9.png b/core/res/res/drawable-hdpi/ab_solid_shadow_holo.9.png
index 69bcd7a..2d59f35 100644
--- a/core/res/res/drawable-hdpi/ab_solid_shadow_holo.9.png
+++ b/core/res/res/drawable-hdpi/ab_solid_shadow_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ab_stacked_solid_dark_holo.9.png b/core/res/res/drawable-hdpi/ab_stacked_solid_dark_holo.9.png
index 9f8829f..0520e5a 100644
--- a/core/res/res/drawable-hdpi/ab_stacked_solid_dark_holo.9.png
+++ b/core/res/res/drawable-hdpi/ab_stacked_solid_dark_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ab_stacked_solid_inverse_holo.9.png b/core/res/res/drawable-hdpi/ab_stacked_solid_inverse_holo.9.png
index d63e85e..42528b1 100644
--- a/core/res/res/drawable-hdpi/ab_stacked_solid_inverse_holo.9.png
+++ b/core/res/res/drawable-hdpi/ab_stacked_solid_inverse_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ab_stacked_solid_light_holo.9.png b/core/res/res/drawable-hdpi/ab_stacked_solid_light_holo.9.png
index 9cff5d8..e3e3f93 100644
--- a/core/res/res/drawable-hdpi/ab_stacked_solid_light_holo.9.png
+++ b/core/res/res/drawable-hdpi/ab_stacked_solid_light_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ab_stacked_transparent_dark_holo.9.png b/core/res/res/drawable-hdpi/ab_stacked_transparent_dark_holo.9.png
index 12a6454..1e39572 100644
--- a/core/res/res/drawable-hdpi/ab_stacked_transparent_dark_holo.9.png
+++ b/core/res/res/drawable-hdpi/ab_stacked_transparent_dark_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ab_stacked_transparent_light_holo.9.png b/core/res/res/drawable-hdpi/ab_stacked_transparent_light_holo.9.png
index 3355d30..a16db85 100644
--- a/core/res/res/drawable-hdpi/ab_stacked_transparent_light_holo.9.png
+++ b/core/res/res/drawable-hdpi/ab_stacked_transparent_light_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ab_transparent_dark_holo.9.png b/core/res/res/drawable-hdpi/ab_transparent_dark_holo.9.png
index a5e8570..0eff695 100644
--- a/core/res/res/drawable-hdpi/ab_transparent_dark_holo.9.png
+++ b/core/res/res/drawable-hdpi/ab_transparent_dark_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ab_transparent_light_holo.9.png b/core/res/res/drawable-hdpi/ab_transparent_light_holo.9.png
index c49412a..219b170 100644
--- a/core/res/res/drawable-hdpi/ab_transparent_light_holo.9.png
+++ b/core/res/res/drawable-hdpi/ab_transparent_light_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_cab_done_default_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_cab_done_default_holo_dark.9.png
index fabc252..0d165bb 100644
--- a/core/res/res/drawable-hdpi/btn_cab_done_default_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_cab_done_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_cab_done_default_holo_light.9.png b/core/res/res/drawable-hdpi/btn_cab_done_default_holo_light.9.png
index f59ef4e..73c7e25 100644
--- a/core/res/res/drawable-hdpi/btn_cab_done_default_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_cab_done_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_cab_done_focused_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_cab_done_focused_holo_dark.9.png
index c87c5a6..1459eee 100644
--- a/core/res/res/drawable-hdpi/btn_cab_done_focused_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_cab_done_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_cab_done_focused_holo_light.9.png b/core/res/res/drawable-hdpi/btn_cab_done_focused_holo_light.9.png
index 6e4cae2..04de530 100644
--- a/core/res/res/drawable-hdpi/btn_cab_done_focused_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_cab_done_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_cab_done_pressed_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_cab_done_pressed_holo_dark.9.png
index e6f83cc..bab70fa 100644
--- a/core/res/res/drawable-hdpi/btn_cab_done_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_cab_done_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_cab_done_pressed_holo_light.9.png b/core/res/res/drawable-hdpi/btn_cab_done_pressed_holo_light.9.png
index 5c97e3f..b46adfa 100644
--- a/core/res/res/drawable-hdpi/btn_cab_done_pressed_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_cab_done_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/cab_background_bottom_holo_dark.9.png b/core/res/res/drawable-hdpi/cab_background_bottom_holo_dark.9.png
index 269def4..1d836f6 100644
--- a/core/res/res/drawable-hdpi/cab_background_bottom_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/cab_background_bottom_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/cab_background_bottom_holo_light.9.png b/core/res/res/drawable-hdpi/cab_background_bottom_holo_light.9.png
index 49bcfb4..5818666 100644
--- a/core/res/res/drawable-hdpi/cab_background_bottom_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/cab_background_bottom_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/cab_background_top_holo_dark.9.png b/core/res/res/drawable-hdpi/cab_background_top_holo_dark.9.png
index b7ddc14..564fb34 100644
--- a/core/res/res/drawable-hdpi/cab_background_top_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/cab_background_top_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/cab_background_top_holo_light.9.png b/core/res/res/drawable-hdpi/cab_background_top_holo_light.9.png
index af80ad5..ae21b76 100644
--- a/core/res/res/drawable-hdpi/cab_background_top_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/cab_background_top_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_player_background.9.png b/core/res/res/drawable-hdpi/ic_lockscreen_player_background.9.png
new file mode 100644
index 0000000..b187358
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_lockscreen_player_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_embed_play.png b/core/res/res/drawable-hdpi/ic_media_embed_play.png
index 05778c1..23ac7e4 100644
--- a/core/res/res/drawable-hdpi/ic_media_embed_play.png
+++ b/core/res/res/drawable-hdpi/ic_media_embed_play.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_moreoverflow_normal_holo_dark.png b/core/res/res/drawable-hdpi/ic_menu_moreoverflow_normal_holo_dark.png
index 1e69eac..5f2f604 100644
--- a/core/res/res/drawable-hdpi/ic_menu_moreoverflow_normal_holo_dark.png
+++ b/core/res/res/drawable-hdpi/ic_menu_moreoverflow_normal_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_moreoverflow_normal_holo_light.png b/core/res/res/drawable-hdpi/ic_menu_moreoverflow_normal_holo_light.png
index 2f6accc..7f3459c 100644
--- a/core/res/res/drawable-hdpi/ic_menu_moreoverflow_normal_holo_light.png
+++ b/core/res/res/drawable-hdpi/ic_menu_moreoverflow_normal_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_bottom_solid_dark_holo.9.png b/core/res/res/drawable-mdpi/ab_bottom_solid_dark_holo.9.png
index b3d51ed..b229367 100644
--- a/core/res/res/drawable-mdpi/ab_bottom_solid_dark_holo.9.png
+++ b/core/res/res/drawable-mdpi/ab_bottom_solid_dark_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_bottom_solid_inverse_holo.9.png b/core/res/res/drawable-mdpi/ab_bottom_solid_inverse_holo.9.png
index abae537..c65f443 100644
--- a/core/res/res/drawable-mdpi/ab_bottom_solid_inverse_holo.9.png
+++ b/core/res/res/drawable-mdpi/ab_bottom_solid_inverse_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_bottom_solid_light_holo.9.png b/core/res/res/drawable-mdpi/ab_bottom_solid_light_holo.9.png
index 4c98afb..0706c8a 100644
--- a/core/res/res/drawable-mdpi/ab_bottom_solid_light_holo.9.png
+++ b/core/res/res/drawable-mdpi/ab_bottom_solid_light_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_bottom_transparent_dark_holo.9.png b/core/res/res/drawable-mdpi/ab_bottom_transparent_dark_holo.9.png
index de8010a..d814d02 100644
--- a/core/res/res/drawable-mdpi/ab_bottom_transparent_dark_holo.9.png
+++ b/core/res/res/drawable-mdpi/ab_bottom_transparent_dark_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_bottom_transparent_light_holo.9.png b/core/res/res/drawable-mdpi/ab_bottom_transparent_light_holo.9.png
index ecb2a0e..b139c8e 100644
--- a/core/res/res/drawable-mdpi/ab_bottom_transparent_light_holo.9.png
+++ b/core/res/res/drawable-mdpi/ab_bottom_transparent_light_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_solid_dark_holo.9.png b/core/res/res/drawable-mdpi/ab_solid_dark_holo.9.png
index 56d27a8..743d00b 100644
--- a/core/res/res/drawable-mdpi/ab_solid_dark_holo.9.png
+++ b/core/res/res/drawable-mdpi/ab_solid_dark_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_solid_light_holo.9.png b/core/res/res/drawable-mdpi/ab_solid_light_holo.9.png
index 98b4956..17c1fb9 100644
--- a/core/res/res/drawable-mdpi/ab_solid_light_holo.9.png
+++ b/core/res/res/drawable-mdpi/ab_solid_light_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_solid_shadow_holo.9.png b/core/res/res/drawable-mdpi/ab_solid_shadow_holo.9.png
index dcd3703..ddfc8e3 100644
--- a/core/res/res/drawable-mdpi/ab_solid_shadow_holo.9.png
+++ b/core/res/res/drawable-mdpi/ab_solid_shadow_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_stacked_solid_dark_holo.9.png b/core/res/res/drawable-mdpi/ab_stacked_solid_dark_holo.9.png
index aa0a3a0..007a4b2 100644
--- a/core/res/res/drawable-mdpi/ab_stacked_solid_dark_holo.9.png
+++ b/core/res/res/drawable-mdpi/ab_stacked_solid_dark_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_stacked_solid_inverse_holo.9.png b/core/res/res/drawable-mdpi/ab_stacked_solid_inverse_holo.9.png
index cf17967..a823841 100644
--- a/core/res/res/drawable-mdpi/ab_stacked_solid_inverse_holo.9.png
+++ b/core/res/res/drawable-mdpi/ab_stacked_solid_inverse_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_stacked_solid_light_holo.9.png b/core/res/res/drawable-mdpi/ab_stacked_solid_light_holo.9.png
index ab0003b..ad6e1a4 100644
--- a/core/res/res/drawable-mdpi/ab_stacked_solid_light_holo.9.png
+++ b/core/res/res/drawable-mdpi/ab_stacked_solid_light_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_stacked_transparent_dark_holo.9.png b/core/res/res/drawable-mdpi/ab_stacked_transparent_dark_holo.9.png
index 5f1eb1e..0ad6c88 100644
--- a/core/res/res/drawable-mdpi/ab_stacked_transparent_dark_holo.9.png
+++ b/core/res/res/drawable-mdpi/ab_stacked_transparent_dark_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_stacked_transparent_light_holo.9.png b/core/res/res/drawable-mdpi/ab_stacked_transparent_light_holo.9.png
index 89822b6..19b50ab 100644
--- a/core/res/res/drawable-mdpi/ab_stacked_transparent_light_holo.9.png
+++ b/core/res/res/drawable-mdpi/ab_stacked_transparent_light_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_transparent_dark_holo.9.png b/core/res/res/drawable-mdpi/ab_transparent_dark_holo.9.png
index bd9921f..ad980b1 100644
--- a/core/res/res/drawable-mdpi/ab_transparent_dark_holo.9.png
+++ b/core/res/res/drawable-mdpi/ab_transparent_dark_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_transparent_light_holo.9.png b/core/res/res/drawable-mdpi/ab_transparent_light_holo.9.png
index 8d93926..60e6c52 100644
--- a/core/res/res/drawable-mdpi/ab_transparent_light_holo.9.png
+++ b/core/res/res/drawable-mdpi/ab_transparent_light_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_cab_done_default_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_cab_done_default_holo_dark.9.png
index d00d235..9e936b3 100644
--- a/core/res/res/drawable-mdpi/btn_cab_done_default_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_cab_done_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_cab_done_default_holo_light.9.png b/core/res/res/drawable-mdpi/btn_cab_done_default_holo_light.9.png
index d7b2049..0360104 100644
--- a/core/res/res/drawable-mdpi/btn_cab_done_default_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_cab_done_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_cab_done_focused_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_cab_done_focused_holo_dark.9.png
index 59c1580..dd947d2 100644
--- a/core/res/res/drawable-mdpi/btn_cab_done_focused_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_cab_done_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_cab_done_focused_holo_light.9.png b/core/res/res/drawable-mdpi/btn_cab_done_focused_holo_light.9.png
index 143564a..51cfca2 100644
--- a/core/res/res/drawable-mdpi/btn_cab_done_focused_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_cab_done_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_cab_done_pressed_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_cab_done_pressed_holo_dark.9.png
index e5b9cfd..fd6e6c7 100644
--- a/core/res/res/drawable-mdpi/btn_cab_done_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_cab_done_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_cab_done_pressed_holo_light.9.png b/core/res/res/drawable-mdpi/btn_cab_done_pressed_holo_light.9.png
index ec43f85..5db212c 100644
--- a/core/res/res/drawable-mdpi/btn_cab_done_pressed_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_cab_done_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/cab_background_bottom_holo_dark.9.png b/core/res/res/drawable-mdpi/cab_background_bottom_holo_dark.9.png
index 0e4b28e..d8f1c8b 100644
--- a/core/res/res/drawable-mdpi/cab_background_bottom_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/cab_background_bottom_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/cab_background_bottom_holo_light.9.png b/core/res/res/drawable-mdpi/cab_background_bottom_holo_light.9.png
index e449090..31e4989 100644
--- a/core/res/res/drawable-mdpi/cab_background_bottom_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/cab_background_bottom_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/cab_background_top_holo_dark.9.png b/core/res/res/drawable-mdpi/cab_background_top_holo_dark.9.png
index d0ebc1a..7c2cbe5 100644
--- a/core/res/res/drawable-mdpi/cab_background_top_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/cab_background_top_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/cab_background_top_holo_light.9.png b/core/res/res/drawable-mdpi/cab_background_top_holo_light.9.png
index c2dd608..30cbdc1 100644
--- a/core/res/res/drawable-mdpi/cab_background_top_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/cab_background_top_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lockscreen_player_background.9.png b/core/res/res/drawable-mdpi/ic_lockscreen_player_background.9.png
new file mode 100644
index 0000000..8cfd1af
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_lockscreen_player_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_embed_play.png b/core/res/res/drawable-mdpi/ic_media_embed_play.png
index 3576ce5..fc5d8c6 100644
--- a/core/res/res/drawable-mdpi/ic_media_embed_play.png
+++ b/core/res/res/drawable-mdpi/ic_media_embed_play.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_ff.png b/core/res/res/drawable-mdpi/ic_media_ff.png
index 170dd2d..892772e 100644
--- a/core/res/res/drawable-mdpi/ic_media_ff.png
+++ b/core/res/res/drawable-mdpi/ic_media_ff.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_fullscreen.png b/core/res/res/drawable-mdpi/ic_media_fullscreen.png
index 960aa85..1c60e15 100644
--- a/core/res/res/drawable-mdpi/ic_media_fullscreen.png
+++ b/core/res/res/drawable-mdpi/ic_media_fullscreen.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_next.png b/core/res/res/drawable-mdpi/ic_media_next.png
index a6feed0..bbe311b 100644
--- a/core/res/res/drawable-mdpi/ic_media_next.png
+++ b/core/res/res/drawable-mdpi/ic_media_next.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_pause.png b/core/res/res/drawable-mdpi/ic_media_pause.png
index 548ba02..e4e8d86 100644
--- a/core/res/res/drawable-mdpi/ic_media_pause.png
+++ b/core/res/res/drawable-mdpi/ic_media_pause.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_play.png b/core/res/res/drawable-mdpi/ic_media_play.png
index 0fe6806..8eaf962 100644
--- a/core/res/res/drawable-mdpi/ic_media_play.png
+++ b/core/res/res/drawable-mdpi/ic_media_play.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_previous.png b/core/res/res/drawable-mdpi/ic_media_previous.png
index 0163d09..e9abc7f 100644
--- a/core/res/res/drawable-mdpi/ic_media_previous.png
+++ b/core/res/res/drawable-mdpi/ic_media_previous.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_rew.png b/core/res/res/drawable-mdpi/ic_media_rew.png
index 5489180..a5eb94a 100644
--- a/core/res/res/drawable-mdpi/ic_media_rew.png
+++ b/core/res/res/drawable-mdpi/ic_media_rew.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_moreoverflow_normal_holo_dark.png b/core/res/res/drawable-mdpi/ic_menu_moreoverflow_normal_holo_dark.png
index 135ca6e..1d2592a 100644
--- a/core/res/res/drawable-mdpi/ic_menu_moreoverflow_normal_holo_dark.png
+++ b/core/res/res/drawable-mdpi/ic_menu_moreoverflow_normal_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_moreoverflow_normal_holo_light.png b/core/res/res/drawable-mdpi/ic_menu_moreoverflow_normal_holo_light.png
index ccbf143..4060afe 100644
--- a/core/res/res/drawable-mdpi/ic_menu_moreoverflow_normal_holo_light.png
+++ b/core/res/res/drawable-mdpi/ic_menu_moreoverflow_normal_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_bottom_solid_dark_holo.9.png b/core/res/res/drawable-xhdpi/ab_bottom_solid_dark_holo.9.png
index 506cd68..5753346 100644
--- a/core/res/res/drawable-xhdpi/ab_bottom_solid_dark_holo.9.png
+++ b/core/res/res/drawable-xhdpi/ab_bottom_solid_dark_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_bottom_solid_inverse_holo.9.png b/core/res/res/drawable-xhdpi/ab_bottom_solid_inverse_holo.9.png
index c185112..7e6c047 100644
--- a/core/res/res/drawable-xhdpi/ab_bottom_solid_inverse_holo.9.png
+++ b/core/res/res/drawable-xhdpi/ab_bottom_solid_inverse_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_bottom_solid_light_holo.9.png b/core/res/res/drawable-xhdpi/ab_bottom_solid_light_holo.9.png
index 8ed7f9b..8155fe8 100644
--- a/core/res/res/drawable-xhdpi/ab_bottom_solid_light_holo.9.png
+++ b/core/res/res/drawable-xhdpi/ab_bottom_solid_light_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_bottom_transparent_dark_holo.9.png b/core/res/res/drawable-xhdpi/ab_bottom_transparent_dark_holo.9.png
index c4694cd..6cee9a1 100644
--- a/core/res/res/drawable-xhdpi/ab_bottom_transparent_dark_holo.9.png
+++ b/core/res/res/drawable-xhdpi/ab_bottom_transparent_dark_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_bottom_transparent_light_holo.9.png b/core/res/res/drawable-xhdpi/ab_bottom_transparent_light_holo.9.png
index 57f5cfa..fa4d76a 100644
--- a/core/res/res/drawable-xhdpi/ab_bottom_transparent_light_holo.9.png
+++ b/core/res/res/drawable-xhdpi/ab_bottom_transparent_light_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_solid_dark_holo.9.png b/core/res/res/drawable-xhdpi/ab_solid_dark_holo.9.png
index d16e50c..6622cba 100644
--- a/core/res/res/drawable-xhdpi/ab_solid_dark_holo.9.png
+++ b/core/res/res/drawable-xhdpi/ab_solid_dark_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_solid_light_holo.9.png b/core/res/res/drawable-xhdpi/ab_solid_light_holo.9.png
index 45cc807..c427297 100644
--- a/core/res/res/drawable-xhdpi/ab_solid_light_holo.9.png
+++ b/core/res/res/drawable-xhdpi/ab_solid_light_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_solid_shadow_holo.9.png b/core/res/res/drawable-xhdpi/ab_solid_shadow_holo.9.png
index a9e0d4d..d0df29d 100644
--- a/core/res/res/drawable-xhdpi/ab_solid_shadow_holo.9.png
+++ b/core/res/res/drawable-xhdpi/ab_solid_shadow_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_stacked_solid_dark_holo.9.png b/core/res/res/drawable-xhdpi/ab_stacked_solid_dark_holo.9.png
index 5ea235d..a0d9c1b 100644
--- a/core/res/res/drawable-xhdpi/ab_stacked_solid_dark_holo.9.png
+++ b/core/res/res/drawable-xhdpi/ab_stacked_solid_dark_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_stacked_solid_inverse_holo.9.png b/core/res/res/drawable-xhdpi/ab_stacked_solid_inverse_holo.9.png
index 0220c8d..16b9bef 100644
--- a/core/res/res/drawable-xhdpi/ab_stacked_solid_inverse_holo.9.png
+++ b/core/res/res/drawable-xhdpi/ab_stacked_solid_inverse_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_stacked_solid_light_holo.9.png b/core/res/res/drawable-xhdpi/ab_stacked_solid_light_holo.9.png
index be13077..d36f99f 100644
--- a/core/res/res/drawable-xhdpi/ab_stacked_solid_light_holo.9.png
+++ b/core/res/res/drawable-xhdpi/ab_stacked_solid_light_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_stacked_transparent_dark_holo.9.png b/core/res/res/drawable-xhdpi/ab_stacked_transparent_dark_holo.9.png
index ab02e7a..5ad475d 100644
--- a/core/res/res/drawable-xhdpi/ab_stacked_transparent_dark_holo.9.png
+++ b/core/res/res/drawable-xhdpi/ab_stacked_transparent_dark_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_stacked_transparent_light_holo.9.png b/core/res/res/drawable-xhdpi/ab_stacked_transparent_light_holo.9.png
index 0b5a24e..6ade5ee 100644
--- a/core/res/res/drawable-xhdpi/ab_stacked_transparent_light_holo.9.png
+++ b/core/res/res/drawable-xhdpi/ab_stacked_transparent_light_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_transparent_dark_holo.9.png b/core/res/res/drawable-xhdpi/ab_transparent_dark_holo.9.png
index 6d21429..719b923 100644
--- a/core/res/res/drawable-xhdpi/ab_transparent_dark_holo.9.png
+++ b/core/res/res/drawable-xhdpi/ab_transparent_dark_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_transparent_light_holo.9.png b/core/res/res/drawable-xhdpi/ab_transparent_light_holo.9.png
index c34c46f..6da264d 100644
--- a/core/res/res/drawable-xhdpi/ab_transparent_light_holo.9.png
+++ b/core/res/res/drawable-xhdpi/ab_transparent_light_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_cab_done_default_holo_dark.9.png b/core/res/res/drawable-xhdpi/btn_cab_done_default_holo_dark.9.png
index a338924..01efef4 100644
--- a/core/res/res/drawable-xhdpi/btn_cab_done_default_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/btn_cab_done_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_cab_done_default_holo_light.9.png b/core/res/res/drawable-xhdpi/btn_cab_done_default_holo_light.9.png
index 6f2d3e5..c287605 100644
--- a/core/res/res/drawable-xhdpi/btn_cab_done_default_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/btn_cab_done_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_cab_done_focused_holo_dark.9.png b/core/res/res/drawable-xhdpi/btn_cab_done_focused_holo_dark.9.png
index faa36b0..9a496e8 100644
--- a/core/res/res/drawable-xhdpi/btn_cab_done_focused_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/btn_cab_done_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_cab_done_focused_holo_light.9.png b/core/res/res/drawable-xhdpi/btn_cab_done_focused_holo_light.9.png
index c57f3ff..e2a38b4 100644
--- a/core/res/res/drawable-xhdpi/btn_cab_done_focused_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/btn_cab_done_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_cab_done_pressed_holo_dark.9.png b/core/res/res/drawable-xhdpi/btn_cab_done_pressed_holo_dark.9.png
index 9d6402f..911722f 100644
--- a/core/res/res/drawable-xhdpi/btn_cab_done_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/btn_cab_done_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_cab_done_pressed_holo_light.9.png b/core/res/res/drawable-xhdpi/btn_cab_done_pressed_holo_light.9.png
index bfd966c..da169bf 100644
--- a/core/res/res/drawable-xhdpi/btn_cab_done_pressed_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/btn_cab_done_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/cab_background_bottom_holo_dark.9.png b/core/res/res/drawable-xhdpi/cab_background_bottom_holo_dark.9.png
index 2bd8cee..0bd0980 100644
--- a/core/res/res/drawable-xhdpi/cab_background_bottom_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/cab_background_bottom_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/cab_background_bottom_holo_light.9.png b/core/res/res/drawable-xhdpi/cab_background_bottom_holo_light.9.png
index d254e77..43ed26d 100644
--- a/core/res/res/drawable-xhdpi/cab_background_bottom_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/cab_background_bottom_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/cab_background_top_holo_dark.9.png b/core/res/res/drawable-xhdpi/cab_background_top_holo_dark.9.png
index 919eac0..6b31579 100644
--- a/core/res/res/drawable-xhdpi/cab_background_top_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/cab_background_top_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/cab_background_top_holo_light.9.png b/core/res/res/drawable-xhdpi/cab_background_top_holo_light.9.png
index 1357105..df0121b 100644
--- a/core/res/res/drawable-xhdpi/cab_background_top_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/cab_background_top_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lockscreen_player_background.9.png b/core/res/res/drawable-xhdpi/ic_lockscreen_player_background.9.png
new file mode 100644
index 0000000..7fb0cbc
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_lockscreen_player_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_moreoverflow_normal_holo_dark.png b/core/res/res/drawable-xhdpi/ic_menu_moreoverflow_normal_holo_dark.png
index 81306ca..1ce25e2 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_moreoverflow_normal_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_moreoverflow_normal_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_moreoverflow_normal_holo_light.png b/core/res/res/drawable-xhdpi/ic_menu_moreoverflow_normal_holo_light.png
index 1f46e7a..dcd6514 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_moreoverflow_normal_holo_light.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_moreoverflow_normal_holo_light.png
Binary files differ
diff --git a/core/res/res/layout-sw600dp/keyguard_screen_status_land.xml b/core/res/res/layout-sw600dp/keyguard_screen_status_land.xml
index f3850d5..3a7c1e1 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_status_land.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_status_land.xml
@@ -42,11 +42,8 @@
<com.android.internal.widget.DigitalClock android:id="@+id/time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_alignParentTop="true"
- android:layout_alignParentLeft="true"
android:layout_marginTop="8dip"
android:layout_marginBottom="8dip"
- android:layout_marginLeft="-10dip"
>
<!-- Because we can't have multi-tone fonts, we render two TextViews, one on
diff --git a/core/res/res/layout-sw600dp/keyguard_screen_status_port.xml b/core/res/res/layout-sw600dp/keyguard_screen_status_port.xml
index f4c99f1..c02341e 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_status_port.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_status_port.xml
@@ -45,8 +45,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dip"
- android:layout_marginBottom="8dip"
- android_layout_marginLeft="-10dip">
+ android:layout_marginBottom="8dip">
<!-- Because we can't have multi-tone fonts, we render two TextViews, one on
top of the other. Hence the redundant layout... -->
diff --git a/core/res/res/layout/keyguard_screen_password_landscape.xml b/core/res/res/layout/keyguard_screen_password_landscape.xml
index 12df99e..694db50 100644
--- a/core/res/res/layout/keyguard_screen_password_landscape.xml
+++ b/core/res/res/layout/keyguard_screen_password_landscape.xml
@@ -186,6 +186,8 @@
android:layout_rowSpan="6"
android:layout_columnSpan="1"
android:layout_gravity="fill"
+ android:layout_width="0dip"
+ android:layout_height="0dip"
/>
</GridLayout>
diff --git a/core/res/res/layout/keyguard_screen_password_portrait.xml b/core/res/res/layout/keyguard_screen_password_portrait.xml
index 6145e47..cf3bd42 100644
--- a/core/res/res/layout/keyguard_screen_password_portrait.xml
+++ b/core/res/res/layout/keyguard_screen_password_portrait.xml
@@ -174,6 +174,8 @@
android:layout_rowSpan="3"
android:layout_columnSpan="1"
android:layout_gravity="fill"
+ android:layout_width="0dip"
+ android:layout_height="0dip"
/>
</GridLayout>
diff --git a/core/res/res/layout/keyguard_screen_tab_unlock.xml b/core/res/res/layout/keyguard_screen_tab_unlock.xml
index 6016d4e..4c8c0d1 100644
--- a/core/res/res/layout/keyguard_screen_tab_unlock.xml
+++ b/core/res/res/layout/keyguard_screen_tab_unlock.xml
@@ -130,6 +130,8 @@
android:layout_alignParentBottom="true"
android:targetDrawables="@array/lockscreen_targets_with_camera"
+ android:targetDescriptions="@array/lockscreen_target_descriptions_with_camera"
+ android:directionDescriptions="@array/lockscreen_direction_descriptions_with_camera"
android:handleDrawable="@drawable/ic_lockscreen_handle"
android:waveDrawable="@drawable/ic_lockscreen_outerring"
android:outerRadius="@dimen/multiwaveview_target_placement_radius"
@@ -188,6 +190,8 @@
android:layout_rowSpan="4"
android:layout_columnSpan="1"
android:layout_gravity="fill"
+ android:layout_width="0dip"
+ android:layout_height="0dip"
/>
</GridLayout>
diff --git a/core/res/res/layout/keyguard_screen_tab_unlock_land.xml b/core/res/res/layout/keyguard_screen_tab_unlock_land.xml
index 0568dd9..ba55f0c0 100644
--- a/core/res/res/layout/keyguard_screen_tab_unlock_land.xml
+++ b/core/res/res/layout/keyguard_screen_tab_unlock_land.xml
@@ -135,6 +135,8 @@
android:layout_rowSpan="7"
android:targetDrawables="@array/lockscreen_targets_with_camera"
+ android:targetDescriptions="@array/lockscreen_target_descriptions_with_camera"
+ android:directionDescriptions="@array/lockscreen_direction_descriptions_with_camera"
android:handleDrawable="@drawable/ic_lockscreen_handle"
android:waveDrawable="@drawable/ic_lockscreen_outerring"
android:outerRadius="@dimen/multiwaveview_target_placement_radius"
@@ -155,6 +157,8 @@
android:layout_rowSpan="5"
android:layout_columnSpan="1"
android:layout_gravity="fill"
+ android:layout_width="0dip"
+ android:layout_height="0dip"
/>
</GridLayout>
diff --git a/core/res/res/layout/keyguard_screen_unlock_landscape.xml b/core/res/res/layout/keyguard_screen_unlock_landscape.xml
index 9b28731..d71dbff 100644
--- a/core/res/res/layout/keyguard_screen_unlock_landscape.xml
+++ b/core/res/res/layout/keyguard_screen_unlock_landscape.xml
@@ -156,6 +156,8 @@
android:layout_rowSpan="5"
android:layout_columnSpan="1"
android:layout_gravity="fill"
+ android:layout_width="0dip"
+ android:layout_height="0dip"
/>
</GridLayout>
diff --git a/core/res/res/layout/keyguard_screen_unlock_portrait.xml b/core/res/res/layout/keyguard_screen_unlock_portrait.xml
index 433dda7..64c479f 100644
--- a/core/res/res/layout/keyguard_screen_unlock_portrait.xml
+++ b/core/res/res/layout/keyguard_screen_unlock_portrait.xml
@@ -167,6 +167,8 @@
android:layout_rowSpan="4"
android:layout_columnSpan="1"
android:layout_gravity="fill"
+ android:layout_width="0dip"
+ android:layout_height="0dip"
/>
</GridLayout>
diff --git a/core/res/res/layout/keyguard_transport_control.xml b/core/res/res/layout/keyguard_transport_control.xml
index 6308b02..2ebe5fc 100644
--- a/core/res/res/layout/keyguard_transport_control.xml
+++ b/core/res/res/layout/keyguard_transport_control.xml
@@ -1,53 +1,102 @@
<?xml version="1.0" encoding="utf-8"?>
-<!--
-**
-** Copyright 2008, 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.
-*/
+<!-- 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.
-->
+<!-- Note: This file is meant to be included in various password unlock screens. As such,
+ LayoutParams (layout_*) for TransportControlView should *NOT* be specified here,
+ but rather as include tags for this file or the layout will break. -->
<com.android.internal.widget.TransportControlView
xmlns:android="http://schemas.android.com/apk/res/android"
- android:gravity="bottom"
- android:orientation="horizontal"
- android:background="#a0808080"
- android:visibility="gone">
+ android:id="@+id/transport_controls"
+ android:background="@drawable/ic_lockscreen_player_background">
- <Button android:id="@+id/control_prev"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:background="#80ff0000"
+ <ImageView
+ android:id="@+id/albumart"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_gravity="fill"
+ android:scaleType="centerCrop"
+ android:adjustViewBounds="false"
/>
- <Space android:layout_width="0dip"
- android:layout_height="0dip"
- android:layout_weight="1"/>
-
- <Button android:id="@+id/control_pauseplay"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:background="#8000ff00"
- />
-
- <Space android:layout_width="0dip"
- android:layout_height="0dip"
- android:layout_weight="1"/>
-
- <Button android:id="@+id/control_next"
- android:layout_width="wrap_content"
+ <LinearLayout
+ android:orientation="vertical"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:background="#800000ff"
+ android:background="#c8000000"
+ android:layout_gravity="bottom">
+ <TextView
+ android:id="@+id/title"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dip"
+ android:layout_marginLeft="16dip"
+ android:layout_marginRight="16dip"
+ android:gravity="center_horizontal"
+ android:singleLine="true"
+ android:ellipsize="end"
+ android:textAppearance="?android:attr/textAppearanceMedium"
/>
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:layout_marginTop="5dip">
+ <FrameLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="1">
+ <ImageView
+ android:id="@+id/btn_prev"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:src="@drawable/ic_media_rew"
+ android:clickable="true"
+ android:background="?android:attr/selectableItemBackground"
+ android:padding="10dip"/>
+ </FrameLayout>
+ <FrameLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="1">
+ <ImageView
+ android:id="@+id/btn_play"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:clickable="true"
+ android:src="@drawable/ic_media_play"
+ android:background="?android:attr/selectableItemBackground"
+ android:padding="10dip"/>
+ </FrameLayout>
+ <FrameLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="1">
+ <ImageView
+ android:id="@+id/btn_next"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:clickable="true"
+ android:src="@drawable/ic_media_ff"
+ android:background="?android:attr/selectableItemBackground"
+ android:padding="10dip"/>
+ </FrameLayout>
+ </LinearLayout>
+ </LinearLayout>
</com.android.internal.widget.TransportControlView>
diff --git a/core/res/res/values-land/arrays.xml b/core/res/res/values-land/arrays.xml
index fd492ec..57aafc8 100644
--- a/core/res/res/values-land/arrays.xml
+++ b/core/res/res/values-land/arrays.xml
@@ -27,13 +27,41 @@
<item>@drawable/ic_lockscreen_soundon</item>
</array>
+ <array name="lockscreen_target_descriptions_when_silent">
+ <item>@null</item>
+ <item>@string/description_target_unlock</item>
+ <item>@null</item>
+ <item>@string/description_target_soundon</item>
+ </array>
+
+ <array name="lockscreen_direction_descriptions_when_silent">
+ <item>@null</item>
+ <item>@string/description_direction_up</item>
+ <item>@null</item>
+ <item>@string/description_direction_down</item>
+ </array>
+
<array name="lockscreen_targets_when_soundon">
- <item>@null</item>"
+ <item>@null</item>
<item>@drawable/ic_lockscreen_unlock</item>
<item>@null</item>
<item>@drawable/ic_lockscreen_silent</item>
</array>
+ <array name="lockscreen_target_descriptions_when_soundon">
+ <item>@null</item>
+ <item>@string/description_target_unlock</item>
+ <item>@null</item>
+ <item>@string/description_target_silent</item>
+ </array>
+
+ <array name="lockscreen_direction_descriptions_when_soundon">
+ <item>@null</item>
+ <item>@string/description_direction_up</item>
+ <item>@null</item>
+ <item>@string/description_direction_down</item>
+ </array>
+
<array name="lockscreen_targets_with_camera">
<item>@null</item>
<item>@drawable/ic_lockscreen_unlock</item>
@@ -41,4 +69,18 @@
<item>@drawable/ic_lockscreen_camera</item>
</array>
+ <array name="lockscreen_target_descriptions_with_camera">
+ <item>@null</item>
+ <item>@string/description_target_unlock</item>
+ <item>@null</item>
+ <item>@string/description_target_camera</item>
+ </array>
+
+ <array name="lockscreen_direction_descriptions_with_camera">
+ <item>@null</item>
+ <item>@string/description_direction_up</item>
+ <item>@null</item>
+ <item>@string/description_direction_down</item>
+ </array>
+
</resources>
diff --git a/core/res/res/values-sw600dp/colors.xml b/core/res/res/values-sw600dp/colors.xml
index 6b5a55a..edd2712 100644
--- a/core/res/res/values-sw600dp/colors.xml
+++ b/core/res/res/values-sw600dp/colors.xml
@@ -21,7 +21,7 @@
<!-- keyguard clock -->
<color name="lockscreen_clock_background">#b3ffffff</color>
<color name="lockscreen_clock_foreground">#7affffff</color>
- <color name="lockscreen_clock_am_pm">#ff9a9a9a</color>
+ <color name="lockscreen_clock_am_pm">#ffffffff</color>
<color name="lockscreen_owner_info">#ff9a9a9a</color>
</resources>
diff --git a/core/res/res/values/arrays.xml b/core/res/res/values/arrays.xml
index 57e9bbf..c9043ba 100644
--- a/core/res/res/values/arrays.xml
+++ b/core/res/res/values/arrays.xml
@@ -349,18 +349,60 @@
<item>@null</item>
</array>
+ <array name="lockscreen_target_descriptions_when_silent">
+ <item>@string/description_target_unlock</item>
+ <item>@null</item>
+ <item>@string/description_target_soundon</item>
+ <item>@null</item>
+ </array>
+
+ <array name="lockscreen_direction_descriptions_when_silent">
+ <item>@string/description_direction_right</item>
+ <item>@null</item>
+ <item>@string/description_direction_left</item>
+ <item>@null</item>
+ </array>
+
<array name="lockscreen_targets_when_soundon">
<item>@drawable/ic_lockscreen_unlock</item>
<item>@null</item>
<item>@drawable/ic_lockscreen_silent</item>
- <item>@null</item>"
+ <item>@null</item>
+ </array>
+
+ <array name="lockscreen_target_descriptions_when_soundon">
+ <item>@string/description_target_unlock</item>
+ <item>@null</item>
+ <item>@string/description_target_silent</item>
+ <item>@null</item>
+ </array>
+
+ <array name="lockscreen_direction_descriptions_when_soundon">
+ <item>@string/description_direction_right</item>
+ <item>@null</item>
+ <item>@string/description_direction_left</item>
+ <item>@null</item>
</array>
<array name="lockscreen_targets_with_camera">
<item>@drawable/ic_lockscreen_unlock</item>
<item>@null</item>
<item>@drawable/ic_lockscreen_camera</item>
- <item>@null</item>"
+ <item>@null</item>
+ </array>
+
+ <array name="lockscreen_target_descriptions_with_camera">
+ <item>@string/description_target_unlock</item>
+ <item>@null</item>
+ <item>@string/description_target_camera</item>
+ <item>@null</item>
+ </array>
+
+ <array name="lockscreen_direction_descriptions_with_camera">
+ <item>@string/description_direction_right</item>
+ <item>@null</item>
+ <item>@string/description_direction_left</item>
+ <item>@null</item>
</array>
</resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index dae9f70..fed5651 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -158,11 +158,14 @@
<!-- The underline color and thickness for misspelled suggestion -->
<attr name="textAppearanceMisspelledSuggestion" format="reference" />
+ <!-- The text color and the background for suggestion range span. This span identifies the
+ portion of text the suggestions refer to). -->
+ <attr name="textAppearanceSuggestionRange" format="reference" />
+
<!-- The underline color -->
<attr name="textUnderlineColor" format="reference|color" />
- <!-- The underline thickness, expressed as a percentage of the default underline thickness
- (i.e., 100 means default thickness, and 200 means double thickness). -->
- <attr name="textUnderlineThicknessPercentage" format="reference|integer" />
+ <!-- The underline thickness -->
+ <attr name="textUnderlineThickness" format="reference|dimension" />
<!-- EditText text foreground color. -->
<attr name="editTextColor" format="reference|color" />
@@ -3149,7 +3152,11 @@
</declare-styleable>
<declare-styleable name="SuggestionSpan">
<attr name="textUnderlineColor" />
- <attr name="textUnderlineThicknessPercentage" />
+ <attr name="textUnderlineThickness" />
+ </declare-styleable>
+ <declare-styleable name="SuggestionRangeSpan">
+ <attr name="textColor" />
+ <attr name="colorBackground" />
</declare-styleable>
<!-- An <code>input-extras</code> is a container for extra data to supply to
an input method. Contains
@@ -5169,6 +5176,12 @@
<!-- Reference to an array resource that be shown as targets around a circle. -->
<attr name="targetDrawables" format="reference"/>
+ <!-- Reference to an array resource that be used as description for the targets around the circle. -->
+ <attr name="targetDescriptions" format="reference"/>
+
+ <!-- Reference to an array resource that be used to announce the directions with targets around the circle. -->
+ <attr name="directionDescriptions" format="reference"/>
+
<!-- Sets a drawable as the drag center. -->
<attr name="handleDrawable" format="reference" />
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index b155b80..051ed14 100755
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -189,6 +189,9 @@
<!-- Boolean indicating whether the wifi chipset has p2p support -->
<bool translatable="false" name="config_wifi_p2p_support">false</bool>
+ <!-- Device type information conforming to Annex B format in WiFi Direct specification.
+ The default represents a dual-mode smartphone -->
+ <string translatable="false" name="config_wifi_p2p_device_type">10-0050F204-5</string>
<!-- Boolean indicating whether the wifi chipset supports background scanning mechanism.
This mechanism allows the host to remain in suspend state and the dongle to actively
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index fcd3bba..6988f6b 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2006,4 +2006,8 @@
<public type="color" name="holo_orange_dark" />
<public type="color" name="holo_purple" />
<public type="color" name="holo_blue_bright" />
+
+ <public type="attr" name="targetDescriptions" />
+ <public type="attr" name="directionDescriptions" />
+
</resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 8e0f300..a9e2971 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1763,7 +1763,7 @@
--> <skip />
<!-- On the keyguard screen, it shows the carrier the phone is connected to. This is displayed if the phone is not connected to a carrier.-->
- <string name="lockscreen_carrier_default">(No service)</string>
+ <string name="lockscreen_carrier_default">No service.</string>
<!-- Shown in the lock screen to tell the user that the screen is locked. -->
<string name="lockscreen_screen_locked">Screen locked.</string>
@@ -2472,6 +2472,9 @@
<!-- Item on EditText context menu. This action is used to replace the current word by other suggested words, suggested by the IME or the spell checker -->
<string name="replace">Replace\u2026</string>
+ <!-- Item on EditText pop-up window. This action is used to delete the text that the user recently added. [CHAR LIMIT=15] -->
+ <string name="delete">Delete</string>
+
<!-- Item on EditText context menu. This action is used to copy a URL from the edit field into the clipboard. -->
<string name="copyUrl">Copy URL</string>
@@ -3129,6 +3132,29 @@
<!-- Description of the Enter button in a KeyboardView. [CHAR LIMIT=NONE] -->
<string name="keyboardview_keycode_enter">Enter</string>
+ <!-- Slide lock screen -->
+
+ <!-- Description of the sliding handle in the Slide unlock screen. [CHAR LIMIT=NONE] -->
+ <string name="content_description_sliding_handle">"Sliding handle. Tap and hold."</string>
+
+ <!-- Description of the up direction in which one can to slide the handle in the Slide unlock screen. [CHAR LIMIT=NONE] -->
+ <string name="description_direction_up">"Up</string>
+ <!-- Description of the down direction in which one can to slide the handle in the Slide unlock screen. [CHAR LIMIT=NONE] -->
+ <string name="description_direction_down">Down</string>
+ <!-- Description of the left direction in which one can to slide the handle in the Slide unlock screen. [CHAR LIMIT=NONE] -->
+ <string name="description_direction_left">"Left</string>
+ <!-- Description of the right direction in which one can to slide the handle in the Slide unlock screen. [CHAR LIMIT=NONE] -->
+ <string name="description_direction_right">Right</string>
+
+ <!-- Description of the unlock target in the Slide unlock screen. [CHAR LIMIT=NONE] -->
+ <string name="description_target_unlock">Unlock</string>
+ <!-- Description of the camera target in the Slide unlock screen. [CHAR LIMIT=NONE] -->
+ <string name="description_target_camera">Camera</string>
+ <!-- Description of the silent target in the Slide unlock screen. [CHAR LIMIT=NONE] -->
+ <string name="description_target_silent">Silent</string>
+ <!-- Description of the sound on target in the Slide unlock screen. [CHAR LIMIT=NONE] -->
+ <string name="description_target_soundon">Sound on</string>
+
<!-- Announce that a headset is required to hear keyboard keys while typing a password. [CHAR LIMIT=NONE] -->
<string name="keyboard_headset_required_to_hear_password">Key. Headset required to hear
keys while typing a password.</string>
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 052a040..1a2ad05 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -244,7 +244,7 @@ please see styles_device_defaults.xml.
</style>
<style name="TextAppearance.Suggestion">
- <item name="android:textUnderlineThicknessPercentage">200</item>
+ <item name="android:textUnderlineThickness">2dip</item>
</style>
<style name="TextAppearance.EasyCorrectSuggestion" parent="TextAppearance.Suggestion">
@@ -255,6 +255,11 @@ please see styles_device_defaults.xml.
<item name="android:textUnderlineColor">@color/holo_red_light</item>
</style>
+ <style name="TextAppearance.SuggestionRange">
+ <item name="android:textColor">@color/white</item>
+ <item name="android:colorBackground">@color/holo_blue_dark</item>
+ </style>
+
<!-- Widget Styles -->
<style name="Widget">
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index f434ce8..899c9d5 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -91,6 +91,7 @@ please see themes_device_defaults.xml.
<item name="textAppearanceEasyCorrectSuggestion">@android:style/TextAppearance.EasyCorrectSuggestion</item>
<item name="textAppearanceMisspelledSuggestion">@android:style/TextAppearance.MisspelledSuggestion</item>
+ <item name="textAppearanceSuggestionRange">@android:style/TextAppearance.SuggestionRange</item>
<item name="textAppearanceButton">@android:style/TextAppearance.Widget.Button</item>
diff --git a/data/fonts/DroidSansFallback.ttf b/data/fonts/DroidSansFallback.ttf
index 03ceae5..ba9d76f 100644
--- a/data/fonts/DroidSansFallback.ttf
+++ b/data/fonts/DroidSansFallback.ttf
Binary files differ
diff --git a/data/fonts/DroidSansFallbackFull.ttf b/data/fonts/DroidSansFallbackFull.ttf
new file mode 100644
index 0000000..03ceae5
--- /dev/null
+++ b/data/fonts/DroidSansFallbackFull.ttf
Binary files differ
diff --git a/data/fonts/fonts.mk b/data/fonts/fonts.mk
index d8c1fa2..cacbdaa 100644
--- a/data/fonts/fonts.mk
+++ b/data/fonts/fonts.mk
@@ -15,10 +15,10 @@
# Warning: this is actually a product definition, to be inherited from
PRODUCT_COPY_FILES := \
- frameworks/base/data/fonts/Roboto-Regular.ttf:system/fonts/Roboto-Regular.ttf \
- frameworks/base/data/fonts/Roboto-Bold.ttf:system/fonts/Roboto-Bold.ttf \
- frameworks/base/data/fonts/Roboto-Italic.ttf:system/fonts/Roboto-Italic.ttf \
- frameworks/base/data/fonts/Roboto-BoldItalic.ttf:system/fonts/Roboto-BoldItalic.ttf \
+ frameworks/base/data/fonts/Roboto-Regular.ttf:system/fonts/Roboto-Regular.ttf \
+ frameworks/base/data/fonts/Roboto-Bold.ttf:system/fonts/Roboto-Bold.ttf \
+ frameworks/base/data/fonts/Roboto-Italic.ttf:system/fonts/Roboto-Italic.ttf \
+ frameworks/base/data/fonts/Roboto-BoldItalic.ttf:system/fonts/Roboto-BoldItalic.ttf \
frameworks/base/data/fonts/DroidSans.ttf:system/fonts/DroidSans.ttf \
frameworks/base/data/fonts/DroidSans-Bold.ttf:system/fonts/DroidSans-Bold.ttf \
frameworks/base/data/fonts/DroidNaskh-Regular.ttf:system/fonts/DroidNaskh-Regular.ttf \
diff --git a/docs/html/sdk/ndk/index.jd b/docs/html/sdk/ndk/index.jd
index 97df84f..f87e1f6 100644
--- a/docs/html/sdk/ndk/index.jd
+++ b/docs/html/sdk/ndk/index.jd
@@ -1,16 +1,16 @@
ndk=true
-ndk.win_download=android-ndk-r6-windows.zip
-ndk.win_bytes=67642809
-ndk.win_checksum=9c7d5ccc02151a3e5e950c70dc05ac6d
+ndk.win_download=android-ndk-r6b-windows.zip
+ndk.win_bytes=67670219
+ndk.win_checksum=f496b48fffb6d341303de170a081b812
-ndk.mac_download=android-ndk-r6-darwin-x86.tar.bz2
-ndk.mac_bytes=52682746
-ndk.mac_checksum=a154905e49a6246abd823b75b6eda738
+ndk.mac_download=android-ndk-r6b-darwin-x86.tar.bz2
+ndk.mac_bytes=52798843
+ndk.mac_checksum=65f2589ac1b08aabe3183f9ed1a8ce8e
-ndk.linux_download=android-ndk-r6-linux-x86.tar.bz2
-ndk.linux_bytes=46425290
-ndk.linux_checksum=ff0a43085fe206696d5cdcef3f4f4637
+ndk.linux_download=android-ndk-r6b-linux-x86.tar.bz2
+ndk.linux_bytes=46532436
+ndk.linux_checksum=309f35e49b64313cfb20ac428df4cec2
page.title=Android NDK
@jd:body
@@ -58,10 +58,42 @@ padding: .25em 1em;
}
</style>
-
<div class="toggleable open">
<a href="#" onclick="return toggleDiv(this)"><img src=
"{@docRoot}assets/images/triangle-opened.png" class="toggle-img" height="9px" width="9px">
+ Android NDK, Revision 6b</a> <em>(August 2011)</em>
+
+ <div class="toggleme">
+ <p>This release of the NDK does not include any new features compared to r6. The r6b release
+ addresses the following issues in the r6 release:</p>
+ <dl>
+ <dt>Important bug fixes</dt>
+ <dd>
+ <ul>
+ <li>Fixed the build when <code>APP_ABI="armeabi x86"</code> is used for
+ multi-architecture builds.</li>
+ <li>Fixed the location of prebuilt STLport binaries in the NDK release package.
+ A bug in the packaging script placed them in the wrong location.</li>
+ <li>Fixed <code>atexit()</code> usage in shared libraries with the x86standalone
+ toolchain.</li>
+ <li>Fixed <code>make-standalone-toolchain.sh --arch=x86</code>. It used to fail
+ to copy the proper GNU libstdc++ binaries to the right location.</li>
+ <li>Fixed the standalone toolchain linker warnings about missing the definition and
+ size for the <code>__dso_handle</code> symbol (ARM only).</li>
+ <li>Fixed the inclusion order of <code>$(SYSROOT)/usr/include</code> for x86 builds.
+ See the <a href="http://code.google.com/p/android/issues/detail?id=18540">bug</a> for
+ more information.</li>
+ <li>Fixed the definitions of <code>ptrdiff_t</code> and <code>size_t</code> in
+ x86-specific systems when they are used with the x86 standalone toolchain.</li>
+ </ul>
+ </dd>
+ </dl>
+ </div>
+</div>
+
+<div class="toggleable closed">
+ <a href="#" onclick="return toggleDiv(this)"><img src=
+ "{@docRoot}assets/images/triangle-closed.png" class="toggle-img" height="9px" width="9px">
Android NDK, Revision 6</a> <em>(July 2011)</em>
<div class="toggleme">
diff --git a/docs/html/sdk/sdk_toc.cs b/docs/html/sdk/sdk_toc.cs
index 1b1fc8d..a00ca12 100644
--- a/docs/html/sdk/sdk_toc.cs
+++ b/docs/html/sdk/sdk_toc.cs
@@ -183,7 +183,7 @@ r3</a> <span class="new">new!</span></li>
<span style="display:none" class="zh-TW"></span>
</h2>
<ul>
- <li><a href="<?cs var:toroot ?>sdk/ndk/index.html">Android NDK, r6</a>
+ <li><a href="<?cs var:toroot ?>sdk/ndk/index.html">Android NDK, r6b</a>
<span class="new">new!</span>
</li>
<li><a href="<?cs var:toroot ?>sdk/ndk/overview.html">What is the NDK?</a></li>
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index b4d94f3..896f81e 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -1349,7 +1349,7 @@ public class Paint {
if (text == null) {
throw new IllegalArgumentException("text cannot be null");
}
- if ((index | count) < 0 || index + count > text.length) {
+ if (index < 0 || text.length - index < Math.abs(count)) {
throw new ArrayIndexOutOfBoundsException();
}
diff --git a/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java b/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java
index 94a8488..7c4e147 100644
--- a/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java
@@ -55,7 +55,7 @@ public class AnimatedRotateDrawable extends Drawable implements Drawable.Callbac
private void init() {
final AnimatedRotateState state = mState;
- mIncrement = 360.0f / (float) state.mFramesCount;
+ mIncrement = 360.0f / state.mFramesCount;
final Drawable drawable = state.mDrawable;
if (drawable != null) {
drawable.setFilterBitmap(true);
@@ -65,6 +65,7 @@ public class AnimatedRotateDrawable extends Drawable implements Drawable.Callbac
}
}
+ @Override
public void draw(Canvas canvas) {
int saveCount = canvas.save();
@@ -146,14 +147,17 @@ public class AnimatedRotateDrawable extends Drawable implements Drawable.Callbac
| mState.mDrawable.getChangingConfigurations();
}
+ @Override
public void setAlpha(int alpha) {
mState.mDrawable.setAlpha(alpha);
}
+ @Override
public void setColorFilter(ColorFilter cf) {
mState.mDrawable.setColorFilter(cf);
}
+ @Override
public int getOpacity() {
return mState.mDrawable.getOpacity();
}
@@ -228,10 +232,10 @@ public class AnimatedRotateDrawable extends Drawable implements Drawable.Callbac
tv = a.peekValue(R.styleable.AnimatedRotateDrawable_pivotY);
final boolean pivotYRel = tv.type == TypedValue.TYPE_FRACTION;
final float pivotY = pivotYRel ? tv.getFraction(1.0f, 1.0f) : tv.getFloat();
-
- final int framesCount = a.getInt(R.styleable.AnimatedRotateDrawable_framesCount, 12);
- final int frameDuration = a.getInt(R.styleable.AnimatedRotateDrawable_frameDuration, 150);
-
+
+ setFramesCount(a.getInt(R.styleable.AnimatedRotateDrawable_framesCount, 12));
+ setFramesDuration(a.getInt(R.styleable.AnimatedRotateDrawable_frameDuration, 150));
+
final int res = a.getResourceId(R.styleable.AnimatedRotateDrawable_drawable, 0);
Drawable drawable = null;
if (res > 0) {
@@ -265,8 +269,6 @@ public class AnimatedRotateDrawable extends Drawable implements Drawable.Callbac
rotateState.mPivotX = pivotX;
rotateState.mPivotYRel = pivotYRel;
rotateState.mPivotY = pivotY;
- rotateState.mFramesCount = framesCount;
- rotateState.mFrameDuration = frameDuration;
init();
@@ -275,6 +277,15 @@ public class AnimatedRotateDrawable extends Drawable implements Drawable.Callbac
}
}
+ public void setFramesCount(int framesCount) {
+ mState.mFramesCount = framesCount;
+ mIncrement = 360.0f / mState.mFramesCount;
+ }
+
+ public void setFramesDuration(int framesDuration) {
+ mState.mFrameDuration = framesDuration;
+ }
+
@Override
public Drawable mutate() {
if (!mMutated && super.mutate() == this) {
diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h
index e0d7898..6a15f6e 100644
--- a/include/media/AudioSystem.h
+++ b/include/media/AudioSystem.h
@@ -185,6 +185,10 @@ public:
static status_t unregisterEffect(int id);
static status_t setEffectEnabled(int id, bool enabled);
+ // clear stream to output mapping cache (gStreamOutputMap)
+ // and output configuration cache (gOutputs)
+ static void clearAudioConfigCache();
+
static const sp<IAudioPolicyService>& get_audio_policy_service();
// ----------------------------------------------------------------------------
@@ -236,7 +240,8 @@ private:
// mapping between stream types and outputs
static DefaultKeyedVector<int, audio_io_handle_t> gStreamOutputMap;
- // list of output descritor containing cached parameters (sampling rate, framecount, channel count...)
+ // list of output descriptors containing cached parameters
+ // (sampling rate, framecount, channel count...)
static DefaultKeyedVector<audio_io_handle_t, OutputDescriptor *> gOutputs;
};
diff --git a/include/private/surfaceflinger/LayerState.h b/include/private/surfaceflinger/LayerState.h
index d2fed41..3eb5c99 100644
--- a/include/private/surfaceflinger/LayerState.h
+++ b/include/private/surfaceflinger/LayerState.h
@@ -54,8 +54,8 @@ struct layer_state_t {
};
SurfaceID surface;
uint32_t what;
- int32_t x;
- int32_t y;
+ float x;
+ float y;
uint32_t z;
uint32_t w;
uint32_t h;
diff --git a/include/surfaceflinger/SurfaceComposerClient.h b/include/surfaceflinger/SurfaceComposerClient.h
index 7fbbfb24..ace0735 100644
--- a/include/surfaceflinger/SurfaceComposerClient.h
+++ b/include/surfaceflinger/SurfaceComposerClient.h
@@ -145,7 +145,7 @@ public:
status_t setAlpha(SurfaceID id, float alpha=1.0f);
status_t setFreezeTint(SurfaceID id, uint32_t tint);
status_t setMatrix(SurfaceID id, float dsdx, float dtdx, float dsdy, float dtdy);
- status_t setPosition(SurfaceID id, int32_t x, int32_t y);
+ status_t setPosition(SurfaceID id, float x, float y);
status_t setSize(SurfaceID id, uint32_t w, uint32_t h);
status_t destroySurface(SurfaceID sid);
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 3b0ffea..00a4bf6 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -102,7 +102,7 @@ class Composer : public Singleton<Composer>
public:
status_t setPosition(const sp<SurfaceComposerClient>& client, SurfaceID id,
- int32_t x, int32_t y);
+ float x, float y);
status_t setSize(const sp<SurfaceComposerClient>& client, SurfaceID id,
uint32_t w, uint32_t h);
status_t setLayer(const sp<SurfaceComposerClient>& client, SurfaceID id,
@@ -161,7 +161,7 @@ layer_state_t* Composer::getLayerStateLocked(
}
status_t Composer::setPosition(const sp<SurfaceComposerClient>& client,
- SurfaceID id, int32_t x, int32_t y) {
+ SurfaceID id, float x, float y) {
Mutex::Autolock _l(mLock);
layer_state_t* s = getLayerStateLocked(client, id);
if (!s)
@@ -372,7 +372,7 @@ status_t SurfaceComposerClient::setFreezeTint(SurfaceID id, uint32_t tint) {
return getComposer().setFreezeTint(this, id, tint);
}
-status_t SurfaceComposerClient::setPosition(SurfaceID id, int32_t x, int32_t y) {
+status_t SurfaceComposerClient::setPosition(SurfaceID id, float x, float y) {
return getComposer().setPosition(this, id, x, y);
}
diff --git a/libs/gui/tests/Android.mk b/libs/gui/tests/Android.mk
index 0308af3..55ac133 100644
--- a/libs/gui/tests/Android.mk
+++ b/libs/gui/tests/Android.mk
@@ -1,4 +1,4 @@
-# Build the unit tests.
+# Build the unit tests,
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
@@ -22,17 +22,15 @@ LOCAL_SHARED_LIBRARIES := \
libui \
libutils \
-LOCAL_STATIC_LIBRARIES := \
- libgtest \
- libgtest_main \
-
LOCAL_C_INCLUDES := \
bionic \
bionic/libstdc++/include \
external/gtest/include \
external/stlport/stlport \
-include $(BUILD_EXECUTABLE)
+# Build the binary to $(TARGET_OUT_DATA_NATIVE_TESTS)/$(LOCAL_MODULE)
+# to integrate with auto-test framework.
+include $(BUILD_NATIVE_TEST)
# Include subdirectory makefiles
# ============================================================
diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp
index 9acf99b..dd05e61 100644
--- a/libs/hwui/FontRenderer.cpp
+++ b/libs/hwui/FontRenderer.cpp
@@ -394,14 +394,14 @@ void FontRenderer::flushAllAndInvalidate() {
bool FontRenderer::cacheBitmap(const SkGlyph& glyph, uint32_t* retOriginX, uint32_t* retOriginY) {
// If the glyph is too tall, don't cache it
- if (glyph.fHeight > mCacheLines[mCacheLines.size() - 1]->mMaxHeight) {
+ if (glyph.fHeight + 2 > mCacheLines[mCacheLines.size() - 1]->mMaxHeight) {
if (mCacheHeight < MAX_TEXT_CACHE_HEIGHT) {
// Default cache not large enough for large glyphs - resize cache to
// max size and try again
flushAllAndInvalidate();
initTextTexture(true);
}
- if (glyph.fHeight > mCacheLines[mCacheLines.size() - 1]->mMaxHeight) {
+ if (glyph.fHeight + 2 > mCacheLines[mCacheLines.size() - 1]->mMaxHeight) {
LOGE("Font size to large to fit in cache. width, height = %i, %i",
(int) glyph.fWidth, (int) glyph.fHeight);
return false;
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index dbe4115..bfc6b5d 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -2637,7 +2637,7 @@ public class AudioService extends IAudioService.Stub {
notifyTopOfAudioFocusStack();
// there's a new top of the stack, let the remote control know
synchronized(mRCStack) {
- checkUpdateRemoteControlDisplay(RC_INFO_ALL);
+ checkUpdateRemoteControlDisplay_syncRcs(RC_INFO_ALL);
}
}
} else {
@@ -2680,7 +2680,7 @@ public class AudioService extends IAudioService.Stub {
notifyTopOfAudioFocusStack();
// there's a new top of the stack, let the remote control know
synchronized(mRCStack) {
- checkUpdateRemoteControlDisplay(RC_INFO_ALL);
+ checkUpdateRemoteControlDisplay_syncRcs(RC_INFO_ALL);
}
}
}
@@ -2784,7 +2784,7 @@ public class AudioService extends IAudioService.Stub {
// there's a new top of the stack, let the remote control know
synchronized(mRCStack) {
- checkUpdateRemoteControlDisplay(RC_INFO_ALL);
+ checkUpdateRemoteControlDisplay_syncRcs(RC_INFO_ALL);
}
}//synchronized(mAudioFocusLock)
@@ -3182,7 +3182,7 @@ public class AudioService extends IAudioService.Stub {
* Helper function:
* Called synchronized on mRCStack
*/
- private void clearRemoteControlDisplay() {
+ private void clearRemoteControlDisplay_syncRcs() {
synchronized(mCurrentRcLock) {
mCurrentRcClient = null;
}
@@ -3195,14 +3195,14 @@ public class AudioService extends IAudioService.Stub {
* Called synchronized on mRCStack
* mRCStack.empty() is false
*/
- private void updateRemoteControlDisplay(int infoChangedFlags) {
+ private void updateRemoteControlDisplay_syncRcs(int infoChangedFlags) {
RemoteControlStackEntry rcse = mRCStack.peek();
int infoFlagsAboutToBeUsed = infoChangedFlags;
// this is where we enforce opt-in for information display on the remote controls
// with the new AudioManager.registerRemoteControlClient() API
if (rcse.mRcClient == null) {
//Log.w(TAG, "Can't update remote control display with null remote control client");
- clearRemoteControlDisplay();
+ clearRemoteControlDisplay_syncRcs();
return;
}
synchronized(mCurrentRcLock) {
@@ -3225,11 +3225,11 @@ public class AudioService extends IAudioService.Stub {
* that has changed, if applicable (checking for the update conditions might trigger a
* clear, rather than an update event).
*/
- private void checkUpdateRemoteControlDisplay(int infoChangedFlags) {
+ private void checkUpdateRemoteControlDisplay_syncRcs(int infoChangedFlags) {
// determine whether the remote control display should be refreshed
// if either stack is empty, there is a mismatch, so clear the RC display
if (mRCStack.isEmpty() || mFocusStack.isEmpty()) {
- clearRemoteControlDisplay();
+ clearRemoteControlDisplay_syncRcs();
return;
}
// if the top of the two stacks belong to different packages, there is a mismatch, clear
@@ -3237,17 +3237,17 @@ public class AudioService extends IAudioService.Stub {
&& (mFocusStack.peek().mPackageName != null)
&& !(mRCStack.peek().mCallingPackageName.compareTo(
mFocusStack.peek().mPackageName) == 0)) {
- clearRemoteControlDisplay();
+ clearRemoteControlDisplay_syncRcs();
return;
}
// if the audio focus didn't originate from the same Uid as the one in which the remote
// control information will be retrieved, clear
if (mRCStack.peek().mCallingUid != mFocusStack.peek().mCallingUid) {
- clearRemoteControlDisplay();
+ clearRemoteControlDisplay_syncRcs();
return;
}
// refresh conditions were verified: update the remote controls
- updateRemoteControlDisplay(infoChangedFlags);
+ updateRemoteControlDisplay_syncRcs(infoChangedFlags);
}
/** see AudioManager.registerMediaButtonEventReceiver(ComponentName eventReceiver) */
@@ -3258,7 +3258,7 @@ public class AudioService extends IAudioService.Stub {
synchronized(mRCStack) {
pushMediaButtonReceiver(eventReceiver);
// new RC client, assume every type of information shall be queried
- checkUpdateRemoteControlDisplay(RC_INFO_ALL);
+ checkUpdateRemoteControlDisplay_syncRcs(RC_INFO_ALL);
}
}
}
@@ -3273,7 +3273,7 @@ public class AudioService extends IAudioService.Stub {
removeMediaButtonReceiver(eventReceiver);
if (topOfStackWillChange) {
// current RC client will change, assume every type of info needs to be queried
- checkUpdateRemoteControlDisplay(RC_INFO_ALL);
+ checkUpdateRemoteControlDisplay_syncRcs(RC_INFO_ALL);
}
}
}
@@ -3329,7 +3329,7 @@ public class AudioService extends IAudioService.Stub {
// if the eventReceiver is at the top of the stack
// then check for potential refresh of the remote controls
if (isCurrentRcController(eventReceiver)) {
- checkUpdateRemoteControlDisplay(RC_INFO_ALL);
+ checkUpdateRemoteControlDisplay_syncRcs(RC_INFO_ALL);
}
}
}
@@ -3426,7 +3426,9 @@ public class AudioService extends IAudioService.Stub {
}
/**
- * Register an IRemoteControlDisplay and notify all IRemoteControlClient of the new display.
+ * Register an IRemoteControlDisplay.
+ * Notify all IRemoteControlClient of the new display and cause the RemoteControlClient
+ * at the top of the stack to update the new display with its information.
* Since only one IRemoteControlDisplay is supported, this will unregister the previous display.
* @param rcd the IRemoteControlDisplay to register. No effect if null.
*/
@@ -3458,20 +3460,8 @@ public class AudioService extends IAudioService.Stub {
}
}
- // we have a new display, tell the current client that it needs to send info
- // (following lock order: mRCStack then mCurrentRcLock)
- synchronized(mCurrentRcLock) {
- if (mCurrentRcClient != null) {
- // tell the current client that it needs to send info
- try {
- mCurrentRcClient.onInformationRequested(mCurrentRcClientGen,
- RC_INFO_ALL, mArtworkExpectedWidth, mArtworkExpectedHeight);
- } catch (RemoteException e) {
- Log.e(TAG, "Current valid remote client is dead: "+e);
- mCurrentRcClient = null;
- }
- }
- }
+ // we have a new display, of which all the clients are now aware: have it be updated
+ updateRemoteControlDisplay_syncRcs(RC_INFO_ALL);
}
}
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 66bd56a..1ee9a1f 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -381,7 +381,7 @@ import java.lang.ref.WeakReference;
* <td>{} </p></td>
* <td>This method can be called in any state and calling it does not change
* the object state. </p></td></tr>
- * <tr><td>setTexture </p></td>
+ * <tr><td>setSurface </p></td>
* <td>any </p></td>
* <td>{} </p></td>
* <td>This method can be called in any state and calling it does not change
@@ -608,7 +608,7 @@ public class MediaPlayer
* portion of the media.
*
* Either a surface holder or surface must be set if a display or video sink
- * is needed. Not calling this method or {@link #setTexture(SurfaceTexture)}
+ * is needed. Not calling this method or {@link #setSurface(Surface)}
* when playing back a video will result in only the audio track being played.
* A null surface holder or surface will result in only the audio track being
* played.
@@ -629,14 +629,21 @@ public class MediaPlayer
/**
* Sets the {@link Surface} to be used as the sink for the video portion of
- * the media. This is similar to {@link #setDisplay(SurfaceHolder)}, but does not
- * support {@link #setScreenOnWhilePlaying(boolean)} or {@link #updateSurfaceScreenOn()}.
- * Setting a Surface will un-set any Surface or SurfaceHolder that was previously set.
+ * the media. This is similar to {@link #setDisplay(SurfaceHolder)}, but
+ * does not support {@link #setScreenOnWhilePlaying(boolean)}. Setting a
+ * Surface will un-set any Surface or SurfaceHolder that was previously set.
* A null surface will result in only the audio track being played.
*
- * @param surface The {@link Surface} to be used for the video portion of the media.
+ * If the Surface sends frames to a {@link SurfaceTexture}, the timestamps
+ * returned from {@link SurfaceTexture#getTimestamp()} will have an
+ * unspecified zero point. These timestamps cannot be directly compared
+ * between different media sources, different instances of the same media
+ * source, or multiple runs of the same program. The timestamp is normally
+ * monotonically increasing and is unaffected by time-of-day adjustments,
+ * but it is reset when the position is set.
*
- * @hide Pending review by API council.
+ * @param surface The {@link Surface} to be used for the video portion of
+ * the media.
*/
public void setSurface(Surface surface) {
if (mScreenOnWhilePlaying && surface != null) {
diff --git a/media/java/android/media/RemoteControlClient.java b/media/java/android/media/RemoteControlClient.java
index d59bc2b..d7b85e4 100644
--- a/media/java/android/media/RemoteControlClient.java
+++ b/media/java/android/media/RemoteControlClient.java
@@ -22,6 +22,7 @@ import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
+import android.media.MediaMetadataRetriever;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
@@ -29,6 +30,7 @@ import android.os.Message;
import android.os.RemoteException;
import android.util.Log;
+import java.lang.IllegalArgumentException;
import java.util.HashMap;
/**
@@ -236,6 +238,23 @@ public class RemoteControlClient
mEventHandler = new EventHandler(this, looper);
}
+ private static final int[] METADATA_KEYS_TYPE_STRING = {
+ MediaMetadataRetriever.METADATA_KEY_ALBUM,
+ MediaMetadataRetriever.METADATA_KEY_ALBUMARTIST,
+ MediaMetadataRetriever.METADATA_KEY_TITLE,
+ MediaMetadataRetriever.METADATA_KEY_ARTIST,
+ MediaMetadataRetriever.METADATA_KEY_AUTHOR,
+ MediaMetadataRetriever.METADATA_KEY_COMPILATION,
+ MediaMetadataRetriever.METADATA_KEY_COMPOSER,
+ MediaMetadataRetriever.METADATA_KEY_DATE,
+ MediaMetadataRetriever.METADATA_KEY_GENRE,
+ MediaMetadataRetriever.METADATA_KEY_TITLE,
+ MediaMetadataRetriever.METADATA_KEY_WRITER };
+ private static final int[] METADATA_KEYS_TYPE_LONG = {
+ MediaMetadataRetriever.METADATA_KEY_CD_TRACK_NUMBER,
+ MediaMetadataRetriever.METADATA_KEY_DISC_NUMBER,
+ MediaMetadataRetriever.METADATA_KEY_DURATION };
+
/**
* Class used to modify metadata in a {@link RemoteControlClient} object.
*/
@@ -256,6 +275,11 @@ public class RemoteControlClient
}
/**
+ * The metadata key for the content artwork / album art.
+ */
+ public final static int METADATA_KEY_ARTWORK = 100;
+
+ /**
* Adds textual information to be displayed.
* Note that none of the information added after {@link #apply()} has been called,
* will be displayed.
@@ -265,49 +289,73 @@ public class RemoteControlClient
* {@link android.media.MediaMetadataRetriever#METADATA_KEY_TITLE},
* {@link android.media.MediaMetadataRetriever#METADATA_KEY_ARTIST},
* {@link android.media.MediaMetadataRetriever#METADATA_KEY_AUTHOR},
- * {@link android.media.MediaMetadataRetriever#METADATA_KEY_CD_TRACK_NUMBER},
* {@link android.media.MediaMetadataRetriever#METADATA_KEY_COMPILATION},
* {@link android.media.MediaMetadataRetriever#METADATA_KEY_COMPOSER},
* {@link android.media.MediaMetadataRetriever#METADATA_KEY_DATE},
- * {@link android.media.MediaMetadataRetriever#METADATA_KEY_DISC_NUMBER},
- * {@link android.media.MediaMetadataRetriever#METADATA_KEY_DURATION},
* {@link android.media.MediaMetadataRetriever#METADATA_KEY_GENRE},
* {@link android.media.MediaMetadataRetriever#METADATA_KEY_TITLE},
* {@link android.media.MediaMetadataRetriever#METADATA_KEY_WRITER},
- * {@link android.media.MediaMetadataRetriever#METADATA_KEY_YEAR}.
- * @param value the text for the given key, or null to signify there is no valid
+ * .
+ * @param value the text for the given key, or {@code null} to signify there is no valid
* information for the field.
* @return FIXME description
*/
- public synchronized MetadataEditor putString(int key, String value) {
+ public synchronized MetadataEditor putString(int key, String value)
+ throws IllegalArgumentException {
if (mApplied) {
Log.e(TAG, "Can't edit a previously applied MetadataEditor");
return this;
}
+ if (!validTypeForKey(key, METADATA_KEYS_TYPE_STRING)) {
+ throw(new IllegalArgumentException("Invalid type 'String' for key "+ key));
+ }
mEditorMetadata.putString(String.valueOf(key), value);
mMetadataChanged = true;
return this;
}
/**
- * The metadata key for the content artwork / album art.
+ * FIXME javadoc
+ * @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
+ * @throws IllegalArgumentException
*/
- public final int METADATA_KEY_ARTWORK = 100;
+ public synchronized MetadataEditor putLong(int key, long value)
+ throws IllegalArgumentException {
+ if (mApplied) {
+ Log.e(TAG, "Can't edit a previously applied MetadataEditor");
+ return this;
+ }
+ if (!validTypeForKey(key, METADATA_KEYS_TYPE_LONG)) {
+ throw(new IllegalArgumentException("Invalid type 'long' for key "+ key));
+ }
+ mEditorMetadata.putLong(String.valueOf(key), value);
+ mMetadataChanged = true;
+ return this;
+ }
/**
* 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
+ * @throws IllegalArgumentException
* @see android.graphics.Bitmap
*/
- public synchronized MetadataEditor putBitmap(int key, Bitmap bitmap) {
+ public synchronized MetadataEditor putBitmap(int key, Bitmap bitmap)
+ throws IllegalArgumentException {
if (mApplied) {
Log.e(TAG, "Can't edit a previously applied MetadataEditor");
return this;
}
if (key != METADATA_KEY_ARTWORK) {
- return this;
+ throw(new IllegalArgumentException("Invalid type 'Bitmap' for key "+ key));
}
if ((mArtworkExpectedWidth > 0) && (mArtworkExpectedHeight > 0)) {
mEditorArtwork = scaleBitmapIfTooBig(bitmap,
@@ -740,6 +788,24 @@ public class RemoteControlClient
}
}
return bitmap;
+ }
+ /**
+ * Fast routine to go through an array of allowed keys and return whether the key is part
+ * of that array
+ * @param key the key value
+ * @param validKeys the array of valid keys for a given type
+ * @return true if the key is part of the array, false otherwise
+ */
+ private static boolean validTypeForKey(int key, int[] validKeys) {
+ try {
+ for (int i = 0 ; ; i++) {
+ if (key == validKeys[i]) {
+ return true;
+ }
+ }
+ } catch (ArrayIndexOutOfBoundsException e) {
+ return false;
+ }
}
}
diff --git a/media/java/android/media/videoeditor/VideoEditorProfile.java b/media/java/android/media/videoeditor/VideoEditorProfile.java
index ecdcdfb..202a2df 100755
--- a/media/java/android/media/videoeditor/VideoEditorProfile.java
+++ b/media/java/android/media/videoeditor/VideoEditorProfile.java
@@ -91,7 +91,7 @@ public class VideoEditorProfile
case MediaProperties.VCODEC_H263:
case MediaProperties.VCODEC_H264:
case MediaProperties.VCODEC_MPEG4:
- level = native_get_videoeditor_export_profile(vidCodec);
+ level = native_get_videoeditor_export_level(vidCodec);
break;
default :
throw new IllegalArgumentException("Unsupported video codec" + vidCodec);
diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp
index bb91fa9..853a5f6 100644
--- a/media/libmedia/AudioSystem.cpp
+++ b/media/libmedia/AudioSystem.cpp
@@ -727,6 +727,14 @@ status_t AudioSystem::isStreamActive(int stream, bool* state, uint32_t inPastMs)
}
+void AudioSystem::clearAudioConfigCache()
+{
+ Mutex::Autolock _l(gLock);
+ LOGV("clearAudioConfigCache()");
+ gStreamOutputMap.clear();
+ gOutputs.clear();
+}
+
// ---------------------------------------------------------------------------
void AudioSystem::AudioPolicyServiceClient::binderDied(const wp<IBinder>& who) {
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index cecedb5..3b6c64d 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -1164,6 +1164,10 @@ status_t AudioTrack::restoreTrack_l(audio_track_cblk_t*& cblk, bool fromStart)
cblk->cv.broadcast();
cblk->lock.unlock();
+ // refresh the audio configuration cache in this process to make sure we get new
+ // output parameters in getOutput_l() and createTrack_l()
+ AudioSystem::clearAudioConfigCache();
+
// if the new IAudioTrack is created, createTrack_l() will modify the
// following member variables: mAudioTrack, mCblkMemory and mCblk.
// It will also delete the strong references on previous IAudioTrack and IMemory
diff --git a/media/libmediaplayerservice/nuplayer/StreamingSource.cpp b/media/libmediaplayerservice/nuplayer/StreamingSource.cpp
index a6a3a18..f41e9d2 100644
--- a/media/libmediaplayerservice/nuplayer/StreamingSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/StreamingSource.cpp
@@ -42,7 +42,7 @@ NuPlayer::StreamingSource::~StreamingSource() {
void NuPlayer::StreamingSource::start() {
mStreamListener = new NuPlayerStreamListener(mSource, 0);
- mTSParser = new ATSParser;
+ mTSParser = new ATSParser(ATSParser::TS_TIMESTAMPS_ARE_ABSOLUTE);
mStreamListener->start();
}
diff --git a/media/libstagefright/AACExtractor.cpp b/media/libstagefright/AACExtractor.cpp
index a5a6b64..52b1200 100644
--- a/media/libstagefright/AACExtractor.cpp
+++ b/media/libstagefright/AACExtractor.cpp
@@ -33,8 +33,6 @@
namespace android {
-#define ADTS_HEADER_LENGTH 7
-
class AACSource : public MediaSource {
public:
AACSource(const sp<DataSource> &source,
@@ -88,7 +86,16 @@ uint32_t get_sample_rate(const uint8_t sf_index)
return 0;
}
-static size_t getFrameSize(const sp<DataSource> &source, off64_t offset) {
+// Returns the frame length in bytes as described in an ADTS header starting at the given offset,
+// or 0 if the size can't be read due to an error in the header or a read failure.
+// The returned value is the AAC frame size with the ADTS header length (regardless of
+// the presence of the CRC).
+// If headerSize is non-NULL, it will be used to return the size of the header of this ADTS frame.
+static size_t getAdtsFrameLength(const sp<DataSource> &source, off64_t offset, size_t* headerSize) {
+
+ const size_t kAdtsHeaderLengthNoCrc = 7;
+ const size_t kAdtsHeaderLengthWithCrc = 9;
+
size_t frameSize = 0;
uint8_t syncword[2];
@@ -111,7 +118,15 @@ static size_t getFrameSize(const sp<DataSource> &source, off64_t offset) {
}
frameSize = (header[0] & 0x3) << 11 | header[1] << 3 | header[2] >> 5;
- frameSize += ADTS_HEADER_LENGTH + protectionAbsent ? 0 : 2;
+
+ // protectionAbsent is 0 if there is CRC
+ size_t headSize = protectionAbsent ? kAdtsHeaderLengthNoCrc : kAdtsHeaderLengthWithCrc;
+ if (headSize > frameSize) {
+ return 0;
+ }
+ if (headerSize != NULL) {
+ *headerSize = headSize;
+ }
return frameSize;
}
@@ -148,7 +163,7 @@ AACExtractor::AACExtractor(const sp<DataSource> &source)
if (mDataSource->getSize(&streamSize) == OK) {
while (offset < streamSize) {
- if ((frameSize = getFrameSize(source, offset)) == 0) {
+ if ((frameSize = getAdtsFrameLength(source, offset, NULL)) == 0) {
return;
}
@@ -268,8 +283,8 @@ status_t AACSource::read(
}
}
- size_t frameSize, frameSizeWithoutHeader;
- if ((frameSize = getFrameSize(mDataSource, mOffset)) == 0) {
+ size_t frameSize, frameSizeWithoutHeader, headerSize;
+ if ((frameSize = getAdtsFrameLength(mDataSource, mOffset, &headerSize)) == 0) {
return ERROR_END_OF_STREAM;
}
@@ -279,8 +294,8 @@ status_t AACSource::read(
return err;
}
- frameSizeWithoutHeader = frameSize - ADTS_HEADER_LENGTH;
- if (mDataSource->readAt(mOffset + ADTS_HEADER_LENGTH, buffer->data(),
+ frameSizeWithoutHeader = frameSize - headerSize;
+ if (mDataSource->readAt(mOffset + headerSize, buffer->data(),
frameSizeWithoutHeader) != (ssize_t)frameSizeWithoutHeader) {
buffer->release();
buffer = NULL;
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index 142dda0..f98b0de 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -513,7 +513,8 @@ void AwesomePlayer::reset_l() {
// If we did this later, audio would continue playing while we
// shutdown the video-related resources and the player appear to
// not be as responsive to a reset request.
- if (mAudioPlayer == NULL && mAudioSource != NULL) {
+ if ((mAudioPlayer == NULL || !(mFlags & AUDIOPLAYER_STARTED))
+ && mAudioSource != NULL) {
// If we had an audio player, it would have effectively
// taken possession of the audio source and stopped it when
// _it_ is stopped. Otherwise this is still our responsibility.
diff --git a/media/libstagefright/mpeg2ts/ATSParser.cpp b/media/libstagefright/mpeg2ts/ATSParser.cpp
index 5bbc2b4..74a3b32 100644
--- a/media/libstagefright/mpeg2ts/ATSParser.cpp
+++ b/media/libstagefright/mpeg2ts/ATSParser.cpp
@@ -325,14 +325,16 @@ sp<MediaSource> ATSParser::Program::getSource(SourceType type) {
}
int64_t ATSParser::Program::convertPTSToTimestamp(uint64_t PTS) {
- if (!mFirstPTSValid) {
- mFirstPTSValid = true;
- mFirstPTS = PTS;
- PTS = 0;
- } else if (PTS < mFirstPTS) {
- PTS = 0;
- } else {
- PTS -= mFirstPTS;
+ if (!(mParser->mFlags & TS_TIMESTAMPS_ARE_ABSOLUTE)) {
+ if (!mFirstPTSValid) {
+ mFirstPTSValid = true;
+ mFirstPTS = PTS;
+ PTS = 0;
+ } else if (PTS < mFirstPTS) {
+ PTS = 0;
+ } else {
+ PTS -= mFirstPTS;
+ }
}
return (PTS * 100) / 9;
@@ -734,7 +736,8 @@ sp<MediaSource> ATSParser::Stream::getSource(SourceType type) {
////////////////////////////////////////////////////////////////////////////////
-ATSParser::ATSParser() {
+ATSParser::ATSParser(uint32_t flags)
+ : mFlags(flags) {
}
ATSParser::~ATSParser() {
diff --git a/media/libstagefright/mpeg2ts/ATSParser.h b/media/libstagefright/mpeg2ts/ATSParser.h
index 1e6451d..d12d998 100644
--- a/media/libstagefright/mpeg2ts/ATSParser.h
+++ b/media/libstagefright/mpeg2ts/ATSParser.h
@@ -38,7 +38,16 @@ struct ATSParser : public RefBase {
DISCONTINUITY_FORMATCHANGE
};
- ATSParser();
+ enum Flags {
+ // The 90kHz clock (PTS/DTS) is absolute, i.e. PTS=0 corresponds to
+ // a media time of 0.
+ // If this flag is _not_ specified, the first PTS encountered in a
+ // program of this stream will be assumed to correspond to media time 0
+ // instead.
+ TS_TIMESTAMPS_ARE_ABSOLUTE = 1
+ };
+
+ ATSParser(uint32_t flags = 0);
void feedTSPacket(const void *data, size_t size);
@@ -73,6 +82,7 @@ private:
struct Program;
struct Stream;
+ uint32_t mFlags;
Vector<sp<Program> > mPrograms;
void parseProgramAssociationTable(ABitReader *br);
diff --git a/media/tests/MediaDump/src/com/android/mediadump/VideoDumpView.java b/media/tests/MediaDump/src/com/android/mediadump/VideoDumpView.java
index 809ee82..f76cf37 100644
--- a/media/tests/MediaDump/src/com/android/mediadump/VideoDumpView.java
+++ b/media/tests/MediaDump/src/com/android/mediadump/VideoDumpView.java
@@ -49,6 +49,7 @@ import android.opengl.Matrix;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
+import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.View;
import android.widget.MediaController;
@@ -569,7 +570,9 @@ class VideoDumpView extends GLSurfaceView implements MediaPlayerControl {
mSurface = new SurfaceTexture(mTextureID);
mSurface.setOnFrameAvailableListener(this);
- mMediaPlayer.setTexture(mSurface);
+ Surface surface = new Surface(mSurface);
+ mMediaPlayer.setSurface(surface);
+ surface.release();
try {
mMediaPlayer.prepare();
diff --git a/packages/SystemUI/res/layout/status_bar.xml b/packages/SystemUI/res/layout/status_bar.xml
index ed13ace..f3d0bee 100644
--- a/packages/SystemUI/res/layout/status_bar.xml
+++ b/packages/SystemUI/res/layout/status_bar.xml
@@ -71,6 +71,7 @@
</LinearLayout>
<com.android.systemui.statusbar.policy.Clock
+ android:id="@+id/clock"
android:textAppearance="@*android:style/TextAppearance.StatusBar.Icon"
android:layout_width="wrap_content"
android:layout_height="match_parent"
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 6e6567b..e3ea0de 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -1060,6 +1060,12 @@ public class PhoneStatusBar extends StatusBar {
*/
}
+ public void showClock(boolean show) {
+ View clock = mStatusBarView.findViewById(R.id.clock);
+ if (clock != null) {
+ clock.setVisibility(show ? View.VISIBLE : View.GONE);
+ }
+ }
/**
* State is one or more of the DISABLE constants from StatusBarManager.
@@ -1074,6 +1080,10 @@ public class PhoneStatusBar extends StatusBar {
old, state, diff));
}
+ if ((diff & StatusBarManager.DISABLE_CLOCK) != 0) {
+ boolean show = (state & StatusBarManager.DISABLE_CLOCK) == 0;
+ showClock(show);
+ }
if ((diff & StatusBarManager.DISABLE_EXPAND) != 0) {
if ((state & StatusBarManager.DISABLE_EXPAND) != 0) {
Slog.d(TAG, "DISABLE_EXPAND: yes");
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 1e417ac..5911378 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodsPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodsPanel.java
@@ -428,7 +428,7 @@ public class InputMethodsPanel extends LinearLayout implements StatusBarPanel,
private CharSequence getIMIName(InputMethodInfo imi) {
if (imi == null) return null;
- return mPackageManager.getApplicationLabel(imi.getServiceInfo().applicationInfo);
+ return imi.loadLabel(mPackageManager);
}
private CharSequence getSubtypeName(InputMethodInfo imi, InputMethodSubtype subtype) {
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java b/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java
index 9629702..40cc7d8 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java
@@ -20,6 +20,7 @@ import com.android.internal.R;
import com.android.internal.telephony.IccCard;
import com.android.internal.telephony.IccCard.State;
import com.android.internal.widget.LockPatternUtils;
+import com.android.internal.widget.TransportControlView;
import com.android.internal.policy.impl.KeyguardUpdateMonitor.SimStateCallback;
import java.util.ArrayList;
@@ -52,8 +53,6 @@ class KeyguardStatusViewManager implements OnClickListener {
public static final int BATTERY_LOW_ICON = 0; //R.drawable.ic_lock_idle_low_battery;
private static final long INSTRUCTION_RESET_DELAY = 2000; // time until instruction text resets
- private static final int SHOW_WIDGET = 8;
- private static final int HIDE_WIDGET = 9;
private static final int INSTRUCTION_TEXT = 10;
private static final int CARRIER_TEXT = 11;
private static final int CARRIER_HELP_TEXT = 12;
@@ -71,7 +70,7 @@ class KeyguardStatusViewManager implements OnClickListener {
private TextView mStatus1View;
private TextView mOwnerInfoView;
private TextView mAlarmStatusView;
- private View mTransportView;
+ private TransportControlView mTransportView;
// Top-level container view for above views
private View mContainer;
@@ -162,7 +161,7 @@ class KeyguardStatusViewManager implements OnClickListener {
mStatus1View = (TextView) findViewById(R.id.status1);
mAlarmStatusView = (TextView) findViewById(R.id.alarm_status);
mOwnerInfoView = (TextView) findViewById(R.id.propertyOf);
- mTransportView = findViewById(R.id.transport);
+ mTransportView = (TransportControlView) findViewById(R.id.transport);
mEmergencyCallButton = (Button) findViewById(R.id.emergencyCallButton);
if (mEmergencyCallButton != null) {
mEmergencyCallButton.setText(R.string.lockscreen_emergency_call);
@@ -192,20 +191,6 @@ class KeyguardStatusViewManager implements OnClickListener {
mUpdateMonitor.getTelephonyPlmn(), mUpdateMonitor.getTelephonySpn()));
}
- public void enterWidgetMode() {
- if (mTransportView != null) {
- mTransportView.setVisibility(View.VISIBLE);
- update(SHOW_WIDGET, null);
- }
- }
-
- public void leaveWidgetMode() {
- if (mTransportView != null) {
- mTransportView.setVisibility(View.GONE);
- update(HIDE_WIDGET, null);
- }
- }
-
private boolean inWidgetMode() {
return mTransportView != null && mTransportView.getVisibility() == View.VISIBLE;
}
@@ -248,7 +233,8 @@ class KeyguardStatusViewManager implements OnClickListener {
* @param lockIcon
*/
public void setHelpMessage(int textResId, int lockIcon) {
- mHelpMessageText = getText(textResId).toString();
+ final CharSequence tmp = getText(textResId);
+ mHelpMessageText = tmp == null ? null : tmp.toString();
update(HELP_MESSAGE_TEXT, mHelpMessageText);
}
@@ -603,15 +589,6 @@ class KeyguardStatusViewManager implements OnClickListener {
public void onPhoneStateChanged(String newState) {
updateEmergencyCallButtonState();
}
-
- public void onTransportControlStateChanged(int state) {
- // TODO: define what state means
- if (state == 0) {
- leaveWidgetMode();
- } else {
- enterWidgetMode();
- }
- }
};
private SimStateCallback mSimStateCallback = new SimStateCallback() {
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java b/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java
index 77f1932..2955de3 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java
@@ -25,6 +25,7 @@ import static android.os.BatteryManager.BATTERY_STATUS_CHARGING;
import static android.os.BatteryManager.BATTERY_STATUS_FULL;
import static android.os.BatteryManager.BATTERY_STATUS_UNKNOWN;
import android.media.AudioManager;
+import android.media.IRemoteControlClient;
import android.os.BatteryManager;
import android.os.Handler;
import android.os.Message;
@@ -93,8 +94,6 @@ public class KeyguardUpdateMonitor {
private static final int MSG_SIM_STATE_CHANGE = 304;
private static final int MSG_RINGER_MODE_CHANGED = 305;
private static final int MSG_PHONE_STATE_CHANGED = 306;
- private static final int MSG_TRANSPORT_CONTROL_STATE_CHANGED = 307;
-
/**
* When we receive a
@@ -171,9 +170,6 @@ public class KeyguardUpdateMonitor {
case MSG_PHONE_STATE_CHANGED:
handlePhoneStateChanged((String)msg.obj);
break;
- case MSG_TRANSPORT_CONTROL_STATE_CHANGED:
- handleTransportControlStateChanged(msg.arg1);
- break;
}
}
};
@@ -263,23 +259,10 @@ public class KeyguardUpdateMonitor {
String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
mHandler.sendMessage(mHandler.obtainMessage(MSG_PHONE_STATE_CHANGED, state));
}
- // TODO
- else if ("android.media.TRANSPORT_CONTROL_CHANGED".equals(action)) {
- int state = intent.getIntExtra("state", 0);
- mHandler.sendMessage(mHandler.obtainMessage(MSG_TRANSPORT_CONTROL_STATE_CHANGED,
- state));
- }
}
}, filter);
}
- protected void handleTransportControlStateChanged(int state) {
- if (DEBUG) Log.d(TAG, "handleTransportControlStateChanged()");
- for (int i = 0; i < mInfoCallbacks.size(); i++) {
- mInfoCallbacks.get(i).onTransportControlStateChanged(state);
- }
- }
-
protected void handlePhoneStateChanged(String newState) {
if (DEBUG) Log.d(TAG, "handlePhoneStateChanged(" + newState + ")");
for (int i = 0; i < mInfoCallbacks.size(); i++) {
@@ -465,11 +448,6 @@ public class KeyguardUpdateMonitor {
*/
void onPhoneStateChanged(String newState);
- /**
- * Called when AudioService informs us of a change to the transport control client.
- *
- */
- void onTransportControlStateChanged(int state);
}
/**
@@ -567,4 +545,5 @@ public class KeyguardUpdateMonitor {
public void reportFailedAttempt() {
mFailedAttempts++;
}
+
}
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
index 5661116..162381d 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
@@ -145,10 +145,10 @@ public class KeyguardViewMediator implements KeyguardViewCallback,
private static final int KEYGUARD_DONE_DRAWING_TIMEOUT_MS = 2000;
/**
- * Allow the user to operate the status bar when the keyguard is engaged (without a pattern or
- * password).
+ * Allow the user to expand the status bar when the keyguard is engaged
+ * (without a pattern or password).
*/
- private static final boolean ENABLE_STATUS_BAR_IN_KEYGUARD = true;
+ private static final boolean ENABLE_INSECURE_STATUS_BAR_EXPAND = true;
private Context mContext;
private AlarmManager mAlarmManager;
@@ -1184,19 +1184,25 @@ public class KeyguardViewMediator implements KeyguardViewCallback,
}
}
- // if the keyguard is shown, allow the status bar to open only if the keyguard is
- // insecure and (is covered by another window OR this feature is enabled in general)
- boolean enable = !mShowing
- || ((ENABLE_STATUS_BAR_IN_KEYGUARD || mHidden) && !isSecure());
+ int flags = StatusBarManager.DISABLE_NONE;
+ if (mShowing && !mHidden) {
+ // showing lockscreen exclusively; disable various extra
+ // statusbar components.
+ flags |= StatusBarManager.DISABLE_NAVIGATION;
+ flags |= StatusBarManager.DISABLE_CLOCK;
+ }
+ if (mShowing && (isSecure() || !ENABLE_INSECURE_STATUS_BAR_EXPAND)) {
+ // showing secure lockscreen; disable expanding.
+ flags |= StatusBarManager.DISABLE_EXPAND;
+ }
+
if (DEBUG) {
- Log.d(TAG, "adjustStatusBarLocked: mShowing=" + mShowing + " mHidden=" + mHidden
- + " isSecure=" + isSecure() + " --> enable=" + enable);
+ Log.d(TAG,
+ "adjustStatusBarLocked: mShowing=" + mShowing + " mHidden=" + mHidden
+ + " isSecure=" + isSecure() + " --> flags=" + flags);
}
- mStatusBarManager.disable(enable ?
- StatusBarManager.DISABLE_NONE :
- ( StatusBarManager.DISABLE_EXPAND
- | StatusBarManager.DISABLE_NAVIGATION
- | StatusBarManager.DISABLE_CLOCK));
+
+ mStatusBarManager.disable(flags);
}
}
diff --git a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
index 5c85903..9c14734 100644
--- a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
+++ b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
@@ -20,6 +20,8 @@ import com.android.internal.R;
import com.android.internal.policy.impl.LockPatternKeyguardView.UnlockMode;
import com.android.internal.telephony.IccCard;
import com.android.internal.widget.LockPatternUtils;
+import com.android.internal.widget.LockScreenWidgetCallback;
+import com.android.internal.widget.TransportControlView;
import android.accounts.Account;
import android.accounts.AccountManager;
@@ -66,6 +68,8 @@ import java.io.IOException;
*/
public class LockPatternKeyguardView extends KeyguardViewBase {
+ private static final int TRANSPORT_USERACTIVITY_TIMEOUT = 10000;
+
static final boolean DEBUG_CONFIGURATION = false;
// time after launching EmergencyDialer before the screen goes blank.
@@ -179,6 +183,22 @@ public class LockPatternKeyguardView extends KeyguardViewBase {
}
};
+ private LockScreenWidgetCallback mWidgetCallback = new LockScreenWidgetCallback() {
+ public void userActivity(View self) {
+ mKeyguardScreenCallback.pokeWakelock(TRANSPORT_USERACTIVITY_TIMEOUT);
+ }
+
+ public void requestShow(View view) {
+ if (DEBUG) Log.v(TAG, "View " + view + " requested show transports");
+ view.setVisibility(View.VISIBLE);
+ }
+
+ public void requestHide(View view) {
+ if (DEBUG) Log.v(TAG, "View " + view + " requested hide transports");
+ view.setVisibility(View.GONE);
+ }
+ };
+
/**
* @return Whether we are stuck on the lock screen because the sim is
* missing.
@@ -490,6 +510,14 @@ public class LockPatternKeyguardView extends KeyguardViewBase {
super.onDetachedFromWindow();
}
+ protected void onConfigurationChanged(Configuration newConfig) {
+ Resources resources = getResources();
+ mShowLockBeforeUnlock = resources.getBoolean(R.bool.config_enableLockBeforeUnlockScreen);
+ mConfiguration = newConfig;
+ if (DEBUG_CONFIGURATION) Log.v(TAG, "**** re-creating lock screen since config changed");
+ updateScreen(mMode, true /* force */);
+ }
+
@Override
protected boolean dispatchHoverEvent(MotionEvent event) {
// Do not let the screen to get locked while the user is disabled and touch
@@ -502,14 +530,6 @@ public class LockPatternKeyguardView extends KeyguardViewBase {
return super.dispatchHoverEvent(event);
}
- protected void onConfigurationChanged(Configuration newConfig) {
- Resources resources = getResources();
- mShowLockBeforeUnlock = resources.getBoolean(R.bool.config_enableLockBeforeUnlockScreen);
- mConfiguration = newConfig;
- if (DEBUG_CONFIGURATION) Log.v(TAG, "**** re-creating lock screen since config changed");
- updateScreen(mMode, true /* force */);
- }
-
@Override
public void wakeWhenReadyTq(int keyCode) {
if (DEBUG) Log.d(TAG, "onWakeKey");
@@ -639,12 +659,14 @@ public class LockPatternKeyguardView extends KeyguardViewBase {
}
View createLockScreen() {
- return new LockScreen(
+ View lockView = new LockScreen(
mContext,
mConfiguration,
mLockPatternUtils,
mUpdateMonitor,
mKeyguardScreenCallback);
+ initializeTransportControlView(lockView);
+ return lockView;
}
View createUnlockScreenFor(UnlockMode unlockMode) {
@@ -710,10 +732,22 @@ public class LockPatternKeyguardView extends KeyguardViewBase {
} else {
throw new IllegalArgumentException("unknown unlock mode " + unlockMode);
}
+ initializeTransportControlView(unlockView);
mUnlockScreenMode = unlockMode;
return unlockView;
}
+ private void initializeTransportControlView(View view) {
+ com.android.internal.widget.TransportControlView tcv =
+ (TransportControlView) view.findViewById(R.id.transport);
+ if (tcv == null) {
+ if (DEBUG) Log.w(TAG, "Couldn't find transport control widget");
+ } else {
+ tcv.setVisibility(View.GONE); // hide tcv until we get the callback below to show it.
+ tcv.setCallback(mWidgetCallback);
+ }
+ }
+
/**
* Given the current state of things, what should be the initial mode of
* the lock screen (lock or unlock).
diff --git a/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java b/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java
index ce3bc74..2f2d3b7 100644
--- a/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java
@@ -347,7 +347,8 @@ public class PasswordUnlockScreen extends LinearLayout implements KeyguardScreen
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
// Check if this was the result of hitting the enter key
- if (actionId == EditorInfo.IME_NULL || actionId == EditorInfo.IME_ACTION_DONE) {
+ if (actionId == EditorInfo.IME_NULL || actionId == EditorInfo.IME_ACTION_DONE
+ || actionId == EditorInfo.IME_ACTION_NEXT) {
verifyPasswordAndUnlock();
return true;
}
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index d617af8..94efa74 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -1362,6 +1362,7 @@ AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinge
for (int stream = 0; stream < AUDIO_STREAM_CNT; stream++) {
mStreamTypes[stream].volume = mAudioFlinger->streamVolumeInternal(stream);
mStreamTypes[stream].mute = mAudioFlinger->streamMute(stream);
+ mStreamTypes[stream].valid = true;
}
}
@@ -1530,6 +1531,14 @@ sp<AudioFlinger::PlaybackThread::Track> AudioFlinger::PlaybackThread::createTra
chain->setStrategy(AudioSystem::getStrategyForStream((audio_stream_type_t)track->type()));
chain->incTrackCnt();
}
+
+ // invalidate track immediately if the stream type was moved to another thread since
+ // createTrack() was called by the client process.
+ if (!mStreamTypes[streamType].valid) {
+ LOGW("createTrack_l() on thread %p: invalidating track on stream %d",
+ this, streamType);
+ android_atomic_or(CBLK_INVALID_ON, &track->mCblk->flags);
+ }
}
lStatus = NO_ERROR;
@@ -2219,6 +2228,14 @@ void AudioFlinger::MixerThread::invalidateTracks(int streamType)
}
}
+void AudioFlinger::PlaybackThread::setStreamValid(int streamType, bool valid)
+{
+ LOGV ("PlaybackThread::setStreamValid() thread %p, streamType %d, valid %d",
+ this, streamType, valid);
+ Mutex::Autolock _l(mLock);
+
+ mStreamTypes[streamType].valid = valid;
+}
// getTrackName_l() must be called with ThreadBase::mLock held
int AudioFlinger::MixerThread::getTrackName_l()
@@ -5074,11 +5091,14 @@ status_t AudioFlinger::setStreamOutput(uint32_t stream, int output)
LOGV("setStreamOutput() stream %d to output %d", stream, output);
audioConfigChanged_l(AudioSystem::STREAM_CONFIG_CHANGED, output, &stream);
+ dstThread->setStreamValid(stream, true);
+
for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
PlaybackThread *thread = mPlaybackThreads.valueAt(i).get();
if (thread != dstThread &&
thread->type() != ThreadBase::DIRECT) {
MixerThread *srcThread = (MixerThread *)thread;
+ srcThread->setStreamValid(stream, false);
srcThread->invalidateTracks(stream);
}
}
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 1ceb0ec..2e05593 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -751,14 +751,18 @@ private:
virtual uint32_t hasAudioSession(int sessionId);
virtual uint32_t getStrategyForSession_l(int sessionId);
+ void setStreamValid(int streamType, bool valid);
+
struct stream_type_t {
stream_type_t()
: volume(1.0f),
- mute(false)
+ mute(false),
+ valid(true)
{
}
float volume;
bool mute;
+ bool valid;
};
protected:
diff --git a/services/input/EventHub.cpp b/services/input/EventHub.cpp
index 1d7cc19..06dea36 100644
--- a/services/input/EventHub.cpp
+++ b/services/input/EventHub.cpp
@@ -1094,9 +1094,8 @@ void EventHub::clearKeyboardPropertiesLocked(Device* device, bool builtInKeyboar
bool EventHub::isExternalDeviceLocked(Device* device) {
if (device->configuration) {
bool value;
- if (device->configuration->tryGetProperty(String8("device.internal"), value)
- && value) {
- return false;
+ if (device->configuration->tryGetProperty(String8("device.internal"), value)) {
+ return !value;
}
}
return device->identifier.bus == BUS_USB || device->identifier.bus == BUS_BLUETOOTH;
diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java
index b3309e5..997318a 100644
--- a/services/java/com/android/server/BackupManagerService.java
+++ b/services/java/com/android/server/BackupManagerService.java
@@ -197,14 +197,14 @@ class BackupManagerService extends IBackupManager.Stub {
= new SparseArray<HashSet<ApplicationInfo>>();
// set of backup services that have pending changes
class BackupRequest {
- public ApplicationInfo appInfo;
+ public String packageName;
- BackupRequest(ApplicationInfo app) {
- appInfo = app;
+ BackupRequest(String pkgName) {
+ packageName = pkgName;
}
public String toString() {
- return "BackupRequest{app=" + appInfo + "}";
+ return "BackupRequest{pkg=" + packageName + "}";
}
}
// Backups that we haven't started yet. Keys are package names.
@@ -877,6 +877,7 @@ class BackupManagerService extends IBackupManager.Stub {
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_PACKAGE_ADDED);
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
+ filter.addAction(Intent.ACTION_PACKAGE_REPLACED);
filter.addDataScheme("package");
mContext.registerReceiver(mBroadcastReceiver, filter);
// Register for events related to sdcard installation.
@@ -1174,7 +1175,8 @@ class BackupManagerService extends IBackupManager.Stub {
Bundle extras = intent.getExtras();
String pkgList[] = null;
if (Intent.ACTION_PACKAGE_ADDED.equals(action) ||
- Intent.ACTION_PACKAGE_REMOVED.equals(action)) {
+ Intent.ACTION_PACKAGE_REMOVED.equals(action) ||
+ Intent.ACTION_PACKAGE_REPLACED.equals(action)) {
Uri uri = intent.getData();
if (uri == null) {
return;
@@ -1183,8 +1185,14 @@ class BackupManagerService extends IBackupManager.Stub {
if (pkgName != null) {
pkgList = new String[] { pkgName };
}
- added = Intent.ACTION_PACKAGE_ADDED.equals(action);
- replacing = extras.getBoolean(Intent.EXTRA_REPLACING, false);
+ if (Intent.ACTION_PACKAGE_REPLACED.equals(action)) {
+ // use the existing "add with replacement" logic
+ if (MORE_DEBUG) Slog.d(TAG, "PACKAGE_REPLACED, updating package " + pkgName);
+ added = replacing = true;
+ } else {
+ added = Intent.ACTION_PACKAGE_ADDED.equals(action);
+ replacing = extras.getBoolean(Intent.EXTRA_REPLACING, false);
+ }
} else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(action)) {
added = true;
pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
@@ -1192,6 +1200,7 @@ class BackupManagerService extends IBackupManager.Stub {
added = false;
pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
}
+
if (pkgList == null || pkgList.length == 0) {
return;
}
@@ -1665,9 +1674,7 @@ class BackupManagerService extends IBackupManager.Stub {
if (status == BackupConstants.TRANSPORT_OK) {
PackageManagerBackupAgent pmAgent = new PackageManagerBackupAgent(
mPackageManager, allAgentPackages());
- BackupRequest pmRequest = new BackupRequest(new ApplicationInfo());
- pmRequest.appInfo.packageName = PACKAGE_MANAGER_SENTINEL;
- status = processOneBackup(pmRequest,
+ status = processOneBackup(PACKAGE_MANAGER_SENTINEL,
IBackupAgent.Stub.asInterface(pmAgent.onBind()), mTransport);
}
@@ -1716,7 +1723,7 @@ class BackupManagerService extends IBackupManager.Stub {
if (status != BackupConstants.TRANSPORT_OK) {
Slog.w(TAG, "Backup pass unsuccessful, restaging");
for (BackupRequest req : mQueue) {
- dataChangedImpl(req.appInfo.packageName);
+ dataChangedImpl(req.packageName);
}
// We also want to reset the backup schedule based on whatever
@@ -1750,9 +1757,11 @@ class BackupManagerService extends IBackupManager.Stub {
// Verify that the requested app exists; it might be something that
// requested a backup but was then uninstalled. The request was
// journalled and rather than tamper with the journal it's safer
- // to sanity-check here.
+ // to sanity-check here. This also gives us the classname of the
+ // package's backup agent.
+ PackageInfo pkg;
try {
- mPackageManager.getPackageInfo(request.appInfo.packageName, 0);
+ pkg = mPackageManager.getPackageInfo(request.packageName, 0);
} catch (NameNotFoundException e) {
Slog.d(TAG, "Package does not exist; skipping");
continue;
@@ -1760,11 +1769,11 @@ class BackupManagerService extends IBackupManager.Stub {
IBackupAgent agent = null;
try {
- mWakelock.setWorkSource(new WorkSource(request.appInfo.uid));
- agent = bindToAgentSynchronous(request.appInfo,
+ mWakelock.setWorkSource(new WorkSource(pkg.applicationInfo.uid));
+ agent = bindToAgentSynchronous(pkg.applicationInfo,
IApplicationThread.BACKUP_MODE_INCREMENTAL);
if (agent != null) {
- int result = processOneBackup(request, agent, transport);
+ int result = processOneBackup(request.packageName, agent, transport);
if (result != BackupConstants.TRANSPORT_OK) return result;
}
} catch (SecurityException ex) {
@@ -1772,7 +1781,7 @@ class BackupManagerService extends IBackupManager.Stub {
Slog.d(TAG, "error in bind/backup", ex);
} finally {
try { // unbind even on timeout, just in case
- mActivityManager.unbindBackupAgent(request.appInfo);
+ mActivityManager.unbindBackupAgent(pkg.applicationInfo);
} catch (RemoteException e) {}
}
}
@@ -1782,9 +1791,8 @@ class BackupManagerService extends IBackupManager.Stub {
return BackupConstants.TRANSPORT_OK;
}
- private int processOneBackup(BackupRequest request, IBackupAgent agent,
+ private int processOneBackup(String packageName, IBackupAgent agent,
IBackupTransport transport) {
- final String packageName = request.appInfo.packageName;
if (DEBUG) Slog.d(TAG, "processOneBackup doBackup() on " + packageName);
File savedStateName = new File(mStateDir, packageName);
@@ -4207,7 +4215,7 @@ class BackupManagerService extends IBackupManager.Stub {
if (app.packageName.equals(packageName)) {
// Add the caller to the set of pending backups. If there is
// one already there, then overwrite it, but no harm done.
- BackupRequest req = new BackupRequest(app);
+ BackupRequest req = new BackupRequest(packageName);
if (mPendingBackups.put(app.packageName, req) == null) {
// Journal this request in case of crash. The put()
// operation returned null when this package was not already
@@ -4218,7 +4226,7 @@ class BackupManagerService extends IBackupManager.Stub {
int numKeys = mPendingBackups.size();
Slog.d(TAG, "Now awaiting backup for " + numKeys + " participants:");
for (BackupRequest b : mPendingBackups.values()) {
- Slog.d(TAG, " + " + b + " agent=" + b.appInfo.backupAgentName);
+ Slog.d(TAG, " + " + b);
}
}
}
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index bfca851..3815c3b 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -17,6 +17,8 @@
package com.android.server;
import static android.Manifest.permission.MANAGE_NETWORK_POLICY;
+import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
+import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE;
import static android.net.ConnectivityManager.isNetworkTypeValid;
import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL;
import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
@@ -1418,6 +1420,9 @@ public class ConnectivityService extends IConnectivityManager.Stub {
// do this before we broadcast the change
handleConnectivityChange(prevNetType, doReset);
+ final Intent immediateIntent = new Intent(intent);
+ immediateIntent.setAction(CONNECTIVITY_ACTION_IMMEDIATE);
+ sendStickyBroadcast(immediateIntent);
sendStickyBroadcastDelayed(intent, getConnectivityChangeDelay());
/*
* If the failover network is already connected, then immediately send
@@ -1476,11 +1481,13 @@ public class ConnectivityService extends IConnectivityManager.Stub {
}
private void sendConnectedBroadcast(NetworkInfo info) {
- sendGeneralBroadcast(info, ConnectivityManager.CONNECTIVITY_ACTION);
+ sendGeneralBroadcast(info, CONNECTIVITY_ACTION_IMMEDIATE);
+ sendGeneralBroadcast(info, CONNECTIVITY_ACTION);
}
private void sendConnectedBroadcastDelayed(NetworkInfo info, int delayMs) {
- sendGeneralBroadcastDelayed(info, ConnectivityManager.CONNECTIVITY_ACTION, delayMs);
+ sendGeneralBroadcast(info, CONNECTIVITY_ACTION_IMMEDIATE);
+ sendGeneralBroadcastDelayed(info, CONNECTIVITY_ACTION, delayMs);
}
private void sendInetConditionBroadcast(NetworkInfo info) {
@@ -1559,6 +1566,10 @@ public class ConnectivityService extends IConnectivityManager.Stub {
}
intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION, mDefaultInetConditionPublished);
+
+ final Intent immediateIntent = new Intent(intent);
+ immediateIntent.setAction(CONNECTIVITY_ACTION_IMMEDIATE);
+ sendStickyBroadcast(immediateIntent);
sendStickyBroadcast(intent);
/*
* If the failover network is already connected, then immediately send
@@ -1576,8 +1587,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
}
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
if (DBG) {
- log("sendStickyBroadcast: NetworkInfo=" +
- intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO));
+ log("sendStickyBroadcast: action=" + intent.getAction());
}
mContext.sendStickyBroadcast(intent);
@@ -1588,7 +1598,10 @@ public class ConnectivityService extends IConnectivityManager.Stub {
if (delayMs <= 0) {
sendStickyBroadcast(intent);
} else {
- if (DBG) log("sendStickyBroadcastDelayed: delayMs=" + delayMs + " intent=" + intent);
+ if (DBG) {
+ log("sendStickyBroadcastDelayed: delayMs=" + delayMs + ", action="
+ + intent.getAction());
+ }
mHandler.sendMessageDelayed(mHandler.obtainMessage(
EVENT_SEND_STICKY_BROADCAST_INTENT, intent), delayMs);
}
@@ -2281,7 +2294,6 @@ public class ConnectivityService extends IConnectivityManager.Stub {
case EVENT_SEND_STICKY_BROADCAST_INTENT:
{
Intent intent = (Intent)msg.obj;
- log("EVENT_SEND_STICKY_BROADCAST_INTENT: sendStickyBroadcast intent=" + intent);
sendStickyBroadcast(intent);
break;
}
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index 38bcebc..bb831f5 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -1682,7 +1682,12 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
for (int i = 0; i < packageNum; ++i) {
if (packageInfos[i].equals(imi.getPackageName())) {
mFileManager.addInputMethodSubtypes(imi, subtypes);
- buildInputMethodListLocked(mMethodList, mMethodMap);
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ buildInputMethodListLocked(mMethodList, mMethodMap);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
return true;
}
}
@@ -1707,7 +1712,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
return;
}
- long ident = Binder.clearCallingIdentity();
+ final long ident = Binder.clearCallingIdentity();
try {
setInputMethodLocked(id, subtypeId);
} finally {
@@ -3065,17 +3070,11 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
public void addInputMethodSubtypes(
InputMethodInfo imi, InputMethodSubtype[] additionalSubtypes) {
synchronized (mMethodMap) {
- final HashSet<InputMethodSubtype> existingSubtypes =
- new HashSet<InputMethodSubtype>();
- for (int i = 0; i < imi.getSubtypeCount(); ++i) {
- existingSubtypes.add(imi.getSubtypeAt(i));
- }
-
final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
final int N = additionalSubtypes.length;
for (int i = 0; i < N; ++i) {
final InputMethodSubtype subtype = additionalSubtypes[i];
- if (!subtypes.contains(subtype) && !existingSubtypes.contains(subtype)) {
+ if (!subtypes.contains(subtype)) {
subtypes.add(subtype);
}
}
diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java
index 7a3a344..6ee20bb 100755
--- a/services/java/com/android/server/NotificationManagerService.java
+++ b/services/java/com/android/server/NotificationManagerService.java
@@ -101,6 +101,7 @@ public class NotificationManagerService extends INotificationManager.Stub
private Vibrator mVibrator = new Vibrator();
// for enabling and disabling notification pulse behavior
+ private boolean mScreenOn = true;
private boolean mInCall = false;
private boolean mNotificationPulseEnabled;
@@ -344,9 +345,19 @@ public class NotificationManagerService extends INotificationManager.Stub
cancelAllNotificationsInt(pkgName, 0, 0, !queryRestart);
}
}
+ } else if (action.equals(Intent.ACTION_SCREEN_ON)) {
+ // Keep track of screen on/off state, but do not turn off the notification light
+ // until user passes through the lock screen or views the notification.
+ mScreenOn = true;
+ } else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
+ mScreenOn = false;
} else if (action.equals(TelephonyManager.ACTION_PHONE_STATE_CHANGED)) {
- mInCall = (intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(TelephonyManager.EXTRA_STATE_OFFHOOK));
+ mInCall = (intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(
+ TelephonyManager.EXTRA_STATE_OFFHOOK));
updateNotificationPulse();
+ } else if (action.equals(Intent.ACTION_USER_PRESENT)) {
+ // turn off LED when user passes through lock screen
+ mNotificationLight.turnOff();
}
}
};
@@ -417,6 +428,7 @@ public class NotificationManagerService extends INotificationManager.Stub
filter.addAction(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
+ filter.addAction(Intent.ACTION_USER_PRESENT);
mContext.registerReceiver(mIntentReceiver, filter);
IntentFilter pkgFilter = new IntentFilter();
pkgFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
@@ -1057,8 +1069,8 @@ public class NotificationManagerService extends INotificationManager.Stub
}
}
- // Don't flash while we are in a call
- if (mLedNotification == null || mInCall) {
+ // Don't flash while we are in a call or screen is on
+ if (mLedNotification == null || mInCall || mScreenOn) {
mNotificationLight.turnOff();
} else {
int ledARGB = mLedNotification.notification.ledARGB;
diff --git a/services/java/com/android/server/TextServicesManagerService.java b/services/java/com/android/server/TextServicesManagerService.java
index f6c369e..c792b33 100644
--- a/services/java/com/android/server/TextServicesManagerService.java
+++ b/services/java/com/android/server/TextServicesManagerService.java
@@ -201,7 +201,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
Settings.Secure.getString(mContext.getContentResolver(),
Settings.Secure.SELECTED_SPELL_CHECKER_SUBTYPE);
if (DBG) {
- Slog.w(TAG, "getCurrentSpellChecker: " + subtypeHashCodeStr);
+ Slog.w(TAG, "getCurrentSpellCheckerSubtype: " + subtypeHashCodeStr);
}
final SpellCheckerInfo sci = getCurrentSpellChecker(null);
if (sci == null || sci.getSubtypeCount() == 0) {
@@ -509,7 +509,8 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
listener.mScLocale, listener.mScListener, listener.mBundle);
listener.mTsListener.onServiceConnected(session);
} catch (RemoteException e) {
- Slog.e(TAG, "Exception in getting the spell checker session: " + e);
+ Slog.e(TAG, "Exception in getting the spell checker session."
+ + "Reconnect to the spellchecker. ", e);
removeAll();
return;
}
@@ -579,8 +580,12 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
Slog.d(TAG, "cleanLocked");
}
if (mListeners.isEmpty()) {
- if (mSpellCheckerBindGroups.containsKey(this)) {
- mSpellCheckerBindGroups.remove(this);
+ final String sciId = mInternalConnection.mSciId;
+ if (mSpellCheckerBindGroups.containsKey(sciId)) {
+ if (DBG) {
+ Slog.d(TAG, "Remove bind group.");
+ }
+ mSpellCheckerBindGroups.remove(sciId);
}
// Unbind service when there is no active clients.
mContext.unbindService(mInternalConnection);
diff --git a/services/java/com/android/server/net/NetworkPolicyManagerService.java b/services/java/com/android/server/net/NetworkPolicyManagerService.java
index 77f53c2..8af90ff 100644
--- a/services/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -26,7 +26,7 @@ import static android.Manifest.permission.READ_PHONE_STATE;
import static android.content.Intent.ACTION_PACKAGE_ADDED;
import static android.content.Intent.ACTION_UID_REMOVED;
import static android.content.Intent.EXTRA_UID;
-import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
+import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE;
import static android.net.ConnectivityManager.TYPE_ETHERNET;
import static android.net.ConnectivityManager.TYPE_MOBILE;
import static android.net.ConnectivityManager.TYPE_WIFI;
@@ -51,6 +51,7 @@ import static android.net.NetworkTemplate.MATCH_WIFI;
import static android.net.NetworkTemplate.buildTemplateMobileAll;
import static android.text.format.DateUtils.DAY_IN_MILLIS;
import static com.android.internal.util.Preconditions.checkNotNull;
+import static com.android.server.NetworkManagementService.LIMIT_GLOBAL_ALERT;
import static com.android.server.net.NetworkPolicyManagerService.XmlUtils.readBooleanAttribute;
import static com.android.server.net.NetworkPolicyManagerService.XmlUtils.readIntAttribute;
import static com.android.server.net.NetworkPolicyManagerService.XmlUtils.readLongAttribute;
@@ -60,7 +61,6 @@ import static com.android.server.net.NetworkPolicyManagerService.XmlUtils.writeL
import static com.android.server.net.NetworkStatsService.ACTION_NETWORK_STATS_UPDATED;
import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
import static org.xmlpull.v1.XmlPullParser.START_TAG;
-import static com.android.server.NetworkManagementService.LIMIT_GLOBAL_ALERT;
import android.app.IActivityManager;
import android.app.INotificationManager;
@@ -321,7 +321,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
mContext.registerReceiver(mScreenReceiver, screenFilter, null, mHandler);
// watch for network interfaces to be claimed
- final IntentFilter connFilter = new IntentFilter(CONNECTIVITY_ACTION);
+ final IntentFilter connFilter = new IntentFilter(CONNECTIVITY_ACTION_IMMEDIATE);
mContext.registerReceiver(mConnReceiver, connFilter, CONNECTIVITY_INTERNAL, mHandler);
// listen for package/uid changes to update policy
diff --git a/services/java/com/android/server/net/NetworkStatsService.java b/services/java/com/android/server/net/NetworkStatsService.java
index bb0a0d1..e0dc96f 100644
--- a/services/java/com/android/server/net/NetworkStatsService.java
+++ b/services/java/com/android/server/net/NetworkStatsService.java
@@ -24,7 +24,7 @@ import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY;
import static android.content.Intent.ACTION_SHUTDOWN;
import static android.content.Intent.ACTION_UID_REMOVED;
import static android.content.Intent.EXTRA_UID;
-import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
+import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE;
import static android.net.NetworkStats.IFACE_ALL;
import static android.net.NetworkStats.SET_ALL;
import static android.net.NetworkStats.SET_DEFAULT;
@@ -239,7 +239,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
}
// watch for network interfaces to be claimed
- final IntentFilter connFilter = new IntentFilter(CONNECTIVITY_ACTION);
+ final IntentFilter connFilter = new IntentFilter(CONNECTIVITY_ACTION_IMMEDIATE);
mContext.registerReceiver(mConnReceiver, connFilter, CONNECTIVITY_INTERNAL, mHandler);
// listen for periodic polling events
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 192d32b..1a4caa7 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -2533,6 +2533,7 @@ public class WindowManagerService extends IWindowManager.Stub
boolean wallpaperMayMove = win.mViewVisibility != viewVisibility
&& (win.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0;
+ wallpaperMayMove |= (flagChanges & FLAG_SHOW_WALLPAPER) != 0;
win.mRelayoutCalled = true;
final int oldVisibility = win.mViewVisibility;
@@ -7925,11 +7926,26 @@ public class WindowManagerService extends IWindowManager.Stub
}
if (windowAnimationBackgroundColor != 0) {
+ // If this window that wants black is the current wallpaper
+ // target, then the black goes *below* the wallpaper so we
+ // don't cause the wallpaper to suddenly disappear.
+ WindowState target = windowAnimationBackground;
+ if (mWallpaperTarget == windowAnimationBackground
+ || mLowerWallpaperTarget == windowAnimationBackground
+ || mUpperWallpaperTarget == windowAnimationBackground) {
+ for (i=0; i<mWindows.size(); i++) {
+ WindowState w = mWindows.get(i);
+ if (w.mIsWallpaper) {
+ target = w;
+ break;
+ }
+ }
+ }
if (mWindowAnimationBackgroundSurface == null) {
mWindowAnimationBackgroundSurface = new DimSurface(mFxSession);
}
mWindowAnimationBackgroundSurface.show(dw, dh,
- windowAnimationBackground.mAnimLayer - LAYER_OFFSET_DIM,
+ target.mAnimLayer - LAYER_OFFSET_DIM,
windowAnimationBackgroundColor);
} else if (mWindowAnimationBackgroundSurface != null) {
mWindowAnimationBackgroundSurface.hide();
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index f8925b8..edbc7b0 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -212,19 +212,6 @@ void Layer::setGeometry(hwc_layer_t* hwcl)
} else {
hwcl->transform = finalTransform;
}
-}
-
-void Layer::setPerFrameData(hwc_layer_t* hwcl) {
- const sp<GraphicBuffer>& buffer(mActiveBuffer);
- if (buffer == NULL) {
- // this can happen if the client never drew into this layer yet,
- // or if we ran out of memory. In that case, don't let
- // HWC handle it.
- hwcl->flags |= HWC_SKIP_LAYER;
- hwcl->handle = NULL;
- } else {
- hwcl->handle = buffer->handle;
- }
if (isCropped()) {
hwcl->sourceCrop.left = mCurrentCrop.left;
@@ -232,6 +219,7 @@ void Layer::setPerFrameData(hwc_layer_t* hwcl) {
hwcl->sourceCrop.right = mCurrentCrop.right;
hwcl->sourceCrop.bottom = mCurrentCrop.bottom;
} else {
+ const sp<GraphicBuffer>& buffer(mActiveBuffer);
hwcl->sourceCrop.left = 0;
hwcl->sourceCrop.top = 0;
if (buffer != NULL) {
@@ -244,6 +232,19 @@ void Layer::setPerFrameData(hwc_layer_t* hwcl) {
}
}
+void Layer::setPerFrameData(hwc_layer_t* hwcl) {
+ const sp<GraphicBuffer>& buffer(mActiveBuffer);
+ if (buffer == NULL) {
+ // this can happen if the client never drew into this layer yet,
+ // or if we ran out of memory. In that case, don't let
+ // HWC handle it.
+ hwcl->flags |= HWC_SKIP_LAYER;
+ hwcl->handle = NULL;
+ } else {
+ hwcl->handle = buffer->handle;
+ }
+}
+
void Layer::onDraw(const Region& clip) const
{
if (CC_UNLIKELY(mActiveBuffer == 0)) {
@@ -416,8 +417,7 @@ void Layer::lockPageFlip(bool& recomputeVisibleRegions)
return;
}
- mActiveBuffer = mSurfaceTexture->getCurrentBuffer();
- mSurfaceTexture->getTransformMatrix(mTextureMatrix);
+ sp<GraphicBuffer> newFrontBuffer(mSurfaceTexture->getCurrentBuffer());
const Rect crop(mSurfaceTexture->getCurrentCrop());
const uint32_t transform(mSurfaceTexture->getCurrentTransform());
@@ -432,7 +432,23 @@ void Layer::lockPageFlip(bool& recomputeVisibleRegions)
mFlinger->invalidateHwcGeometry();
}
- mCurrentOpacity = getOpacityForFormat(mActiveBuffer->format);
+ GLfloat textureMatrix[16];
+ mSurfaceTexture->getTransformMatrix(textureMatrix);
+ if (memcmp(textureMatrix, mTextureMatrix, sizeof(textureMatrix))) {
+ memcpy(mTextureMatrix, textureMatrix, sizeof(textureMatrix));
+ mFlinger->invalidateHwcGeometry();
+ }
+
+ uint32_t bufWidth = newFrontBuffer->getWidth();
+ uint32_t bufHeight = newFrontBuffer->getHeight();
+ if (mActiveBuffer != NULL) {
+ if (bufWidth != uint32_t(mActiveBuffer->width) ||
+ bufHeight != uint32_t(mActiveBuffer->height)) {
+ mFlinger->invalidateHwcGeometry();
+ }
+ }
+
+ mCurrentOpacity = getOpacityForFormat(newFrontBuffer->format);
if (oldOpacity != isOpaque()) {
recomputeVisibleRegions = true;
}
@@ -446,15 +462,14 @@ void Layer::lockPageFlip(bool& recomputeVisibleRegions)
// FIXME: mPostedDirtyRegion = dirty & bounds
mPostedDirtyRegion.set(front.w, front.h);
+ // update active buffer
+ mActiveBuffer = newFrontBuffer;
if ((front.w != front.requested_w) ||
(front.h != front.requested_h))
{
// check that we received a buffer of the right size
// (Take the buffer's orientation into account)
- sp<GraphicBuffer> newFrontBuffer(mActiveBuffer);
- uint32_t bufWidth = newFrontBuffer->getWidth();
- uint32_t bufHeight = newFrontBuffer->getHeight();
if (mCurrentTransform & Transform::ROT_90) {
swap(bufWidth, bufHeight);
}
diff --git a/services/surfaceflinger/LayerBase.cpp b/services/surfaceflinger/LayerBase.cpp
index 4cc245a..603fb60 100644
--- a/services/surfaceflinger/LayerBase.cpp
+++ b/services/surfaceflinger/LayerBase.cpp
@@ -45,7 +45,6 @@ LayerBase::LayerBase(SurfaceFlinger* flinger, DisplayID display)
mFlinger(flinger), mFiltering(false),
mNeedsFiltering(false),
mOrientation(0),
- mLeft(0), mTop(0),
mTransactionFlags(0),
mPremultipliedAlpha(true), mName("unnamed"), mDebug(false),
mInvalidate(0)
@@ -119,7 +118,7 @@ uint32_t LayerBase::setTransactionFlags(uint32_t flags) {
return android_atomic_or(flags, &mTransactionFlags);
}
-bool LayerBase::setPosition(int32_t x, int32_t y) {
+bool LayerBase::setPosition(float x, float y) {
if (mCurrentState.transform.tx() == x && mCurrentState.transform.ty() == y)
return false;
mCurrentState.sequence++;
@@ -259,8 +258,6 @@ void LayerBase::validateVisibility(const Transform& planeTransform)
mOrientation = tr.getOrientation();
mTransform = tr;
mTransformedBounds = tr.makeBounds(w, h);
- mLeft = tr.tx();
- mTop = tr.ty();
}
void LayerBase::lockPageFlip(bool& recomputeVisibleRegions)
@@ -335,17 +332,18 @@ void LayerBase::setGeometry(hwc_layer_t* hwcl)
reinterpret_cast<hwc_rect_t const *>(
visibleRegionScreen.getArray(
&hwcl->visibleRegionScreen.numRects));
-}
-void LayerBase::setPerFrameData(hwc_layer_t* hwcl) {
- hwcl->compositionType = HWC_FRAMEBUFFER;
- hwcl->handle = NULL;
hwcl->sourceCrop.left = 0;
hwcl->sourceCrop.top = 0;
hwcl->sourceCrop.right = mTransformedBounds.width();
hwcl->sourceCrop.bottom = mTransformedBounds.height();
}
+void LayerBase::setPerFrameData(hwc_layer_t* hwcl) {
+ hwcl->compositionType = HWC_FRAMEBUFFER;
+ hwcl->handle = NULL;
+}
+
void LayerBase::setFiltering(bool filtering)
{
mFiltering = filtering;
@@ -476,10 +474,10 @@ void LayerBase::dump(String8& result, char* buffer, size_t SIZE) const
snprintf(buffer, SIZE,
"+ %s %p\n"
" "
- "z=%9d, pos=(%4d,%4d), size=(%4d,%4d), "
+ "z=%9d, pos=(%g,%g), size=(%4d,%4d), "
"isOpaque=%1d, needsDithering=%1d, invalidate=%1d, "
"alpha=0x%02x, flags=0x%08x, tr=[%.2f, %.2f][%.2f, %.2f]\n",
- getTypeId(), this, s.z, tx(), ty(), s.w, s.h,
+ getTypeId(), this, s.z, s.transform.tx(), s.transform.ty(), s.w, s.h,
isOpaque(), needsDithering(), contentDirty,
s.alpha, s.flags,
s.transform[0][0], s.transform[0][1],
diff --git a/services/surfaceflinger/LayerBase.h b/services/surfaceflinger/LayerBase.h
index 2cd3a94..d20f06a 100644
--- a/services/surfaceflinger/LayerBase.h
+++ b/services/surfaceflinger/LayerBase.h
@@ -84,7 +84,7 @@ public:
String8 getName() const;
// modify current state
- bool setPosition(int32_t x, int32_t y);
+ bool setPosition(float x, float y);
bool setLayer(uint32_t z);
bool setSize(uint32_t w, uint32_t h);
bool setAlpha(uint8_t alpha);
@@ -217,8 +217,6 @@ public:
inline State& currentState() { return mCurrentState; }
int32_t getOrientation() const { return mOrientation; }
- int tx() const { return mLeft; }
- int ty() const { return mTop; }
protected:
const GraphicPlane& graphicPlane(int dpy) const;
@@ -250,8 +248,6 @@ protected:
Transform mTransform;
GLfloat mVertices[4][2];
Rect mTransformedBounds;
- int mLeft;
- int mTop;
// these are protected by an external lock
State mCurrentState;
diff --git a/services/surfaceflinger/Transform.cpp b/services/surfaceflinger/Transform.cpp
index 05b7527..ba345ce 100644
--- a/services/surfaceflinger/Transform.cpp
+++ b/services/surfaceflinger/Transform.cpp
@@ -91,12 +91,12 @@ bool Transform::transformed() const {
return type() > TRANSLATE;
}
-int Transform::tx() const {
- return floorf(mMatrix[2][0] + 0.5f);
+float Transform::tx() const {
+ return mMatrix[2][0];
}
-int Transform::ty() const {
- return floorf(mMatrix[2][1] + 0.5f);
+float Transform::ty() const {
+ return mMatrix[2][1];
}
void Transform::reset() {
@@ -239,7 +239,9 @@ Region Transform::transform(const Region& reg) const
out.set(transform(reg.bounds()));
}
} else {
- out = reg.translate(tx(), ty());
+ int xpos = floorf(tx() + 0.5f);
+ int ypos = floorf(ty() + 0.5f);
+ out = reg.translate(xpos, ypos);
}
return out;
}
diff --git a/services/surfaceflinger/Transform.h b/services/surfaceflinger/Transform.h
index 8fa5b86..ec74243 100644
--- a/services/surfaceflinger/Transform.h
+++ b/services/surfaceflinger/Transform.h
@@ -64,8 +64,8 @@ public:
uint32_t getOrientation() const;
float const* operator [] (int i) const; // returns column i
- int tx() const;
- int ty() const;
+ float tx() const;
+ float ty() const;
// modify the transform
void reset();
diff --git a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
index f67d251..e892b5e 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
@@ -18,7 +18,7 @@ package com.android.server;
import static android.content.Intent.ACTION_UID_REMOVED;
import static android.content.Intent.EXTRA_UID;
-import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
+import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE;
import static android.net.ConnectivityManager.TYPE_WIFI;
import static android.net.NetworkPolicy.LIMIT_DISABLED;
import static android.net.NetworkPolicy.SNOOZE_NEVER;
@@ -511,7 +511,7 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase {
future = expectMeteredIfacesChanged();
replay();
- mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
+ mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION_IMMEDIATE));
future.get();
verifyAndReset();
@@ -615,7 +615,7 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase {
future = expectMeteredIfacesChanged(TEST_IFACE);
replay();
- mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
+ mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION_IMMEDIATE));
future.get();
verifyAndReset();
}
diff --git a/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java
index 6dd8cd6..54f3bb0 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java
@@ -18,7 +18,7 @@ package com.android.server;
import static android.content.Intent.ACTION_UID_REMOVED;
import static android.content.Intent.EXTRA_UID;
-import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
+import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE;
import static android.net.ConnectivityManager.TYPE_MOBILE;
import static android.net.ConnectivityManager.TYPE_WIFI;
import static android.net.ConnectivityManager.TYPE_WIMAX;
@@ -180,7 +180,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
expectNetworkStatsSummary(buildEmptyStats());
replay();
- mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
+ mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION_IMMEDIATE));
// verify service has empty history for wifi
assertNetworkTotal(sTemplateWifi, 0L, 0L, 0L, 0L, 0);
@@ -232,7 +232,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
expectNetworkStatsSummary(buildEmptyStats());
replay();
- mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
+ mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION_IMMEDIATE));
// verify service has empty history for wifi
assertNetworkTotal(sTemplateWifi, 0L, 0L, 0L, 0L, 0);
@@ -322,7 +322,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
expectNetworkStatsSummary(buildEmptyStats());
replay();
- mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
+ mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION_IMMEDIATE));
verifyAndReset();
// modify some number on wifi, and trigger poll event
@@ -372,7 +372,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
expectNetworkStatsSummary(buildEmptyStats());
replay();
- mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
+ mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION_IMMEDIATE));
verifyAndReset();
// create some traffic on first network
@@ -410,7 +410,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
expectNetworkStatsPoll();
replay();
- mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
+ mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION_IMMEDIATE));
mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
verifyAndReset();
@@ -452,7 +452,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
expectNetworkStatsSummary(buildEmptyStats());
replay();
- mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
+ mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION_IMMEDIATE));
verifyAndReset();
// create some traffic
@@ -509,7 +509,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
expectNetworkStatsSummary(buildEmptyStats());
replay();
- mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
+ mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION_IMMEDIATE));
verifyAndReset();
// create some traffic
@@ -541,7 +541,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
expectNetworkStatsPoll();
replay();
- mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
+ mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION_IMMEDIATE));
mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
verifyAndReset();
@@ -575,7 +575,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
expectNetworkStatsSummary(buildEmptyStats());
replay();
- mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
+ mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION_IMMEDIATE));
verifyAndReset();
// create some traffic for two apps
@@ -637,7 +637,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
expectNetworkStatsSummary(buildEmptyStats());
replay();
- mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
+ mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION_IMMEDIATE));
verifyAndReset();
// create some initial traffic
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 1954172..c59dd3c 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -60,12 +60,13 @@ public class TelephonyManager {
/** @hide */
public TelephonyManager(Context context) {
+ context = context.getApplicationContext();
if (sContext == null) {
- sContext = context.getApplicationContext();
+ sContext = context;
sRegistry = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService(
"telephony.registry"));
- } else {
+ } else if (sContext != context) {
Log.e(TAG, "Hidden constructor called more than once per process!");
Log.e(TAG, "Original: " + sContext.getPackageName() + ", new: " +
context.getPackageName());
diff --git a/telephony/java/com/android/internal/telephony/IccCard.java b/telephony/java/com/android/internal/telephony/IccCard.java
index bce9991..955849d 100644
--- a/telephony/java/com/android/internal/telephony/IccCard.java
+++ b/telephony/java/com/android/internal/telephony/IccCard.java
@@ -470,19 +470,6 @@ public abstract class IccCard {
} else if (isIccCardAdded) {
mHandler.sendMessage(mHandler.obtainMessage(EVENT_CARD_ADDED, null));
}
-
-
-
- /*
- * TODO: We need to try to remove this, maybe if the RIL sends up a RIL_UNSOL_SIM_REFRESH?
- */
- if (oldState != State.READY && newState == State.READY &&
- mPhone.getLteOnCdmaMode() == Phone.LTE_ON_CDMA_TRUE) {
- if (mPhone.mIccRecords instanceof SIMRecords) {
- ((SIMRecords)mPhone.mIccRecords).onSimReady();
- }
- }
-
}
private void onIccSwap(boolean isAdded) {
@@ -720,17 +707,14 @@ public abstract class IccCard {
currentRadioState == RadioState.SIM_NOT_READY ||
currentRadioState == RadioState.RUIM_NOT_READY ||
currentRadioState == RadioState.NV_NOT_READY ||
- (currentRadioState == RadioState.NV_READY &&
- (mPhone.getLteOnCdmaMode() != Phone.LTE_ON_CDMA_TRUE))) {
+ currentRadioState == RadioState.NV_READY) {
return IccCard.State.NOT_READY;
}
if( currentRadioState == RadioState.SIM_LOCKED_OR_ABSENT ||
currentRadioState == RadioState.SIM_READY ||
currentRadioState == RadioState.RUIM_LOCKED_OR_ABSENT ||
- currentRadioState == RadioState.RUIM_READY ||
- (currentRadioState == RadioState.NV_READY &&
- (mPhone.getLteOnCdmaMode() == Phone.LTE_ON_CDMA_TRUE))) {
+ currentRadioState == RadioState.RUIM_READY) {
State csimState =
getAppState(mIccCardStatus.getCdmaSubscriptionAppIndex());
diff --git a/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java b/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java
index e17d98d..6743da0 100755
--- a/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java
+++ b/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java
@@ -36,6 +36,7 @@ import com.android.internal.util.BitwiseOutputStream;
import android.content.res.Resources;
+import java.util.TimeZone;
/**
@@ -231,7 +232,7 @@ public final class BearerData {
public static class TimeStamp extends Time {
public TimeStamp() {
- super(Time.TIMEZONE_UTC);
+ super(TimeZone.getDefault().getID()); // 3GPP2 timestamps use the local timezone
}
public static TimeStamp fromByteArray(byte[] data) {
diff --git a/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java b/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java
index 28034cc..d84715e 100755
--- a/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java
+++ b/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java
@@ -181,11 +181,7 @@ public class SIMRecords extends IccRecords {
// recordsToLoad is set to 0 because no requests are made yet
recordsToLoad = 0;
- // SIMRecord is used by CDMA+LTE mode, and SIM_READY event
- // will be subscribed by CdmaLteServiceStateTracker.
- if (phone.getLteOnCdmaMode() != Phone.LTE_ON_CDMA_TRUE) {
- p.mCM.registerForSIMReady(this, EVENT_SIM_READY, null);
- }
+ p.mCM.registerForSIMReady(this, EVENT_SIM_READY, null);
p.mCM.registerForOffOrNotAvailable(
this, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
p.mCM.setOnSmsOnSim(this, EVENT_SMS_ON_SIM, null);
@@ -199,9 +195,7 @@ public class SIMRecords extends IccRecords {
@Override
public void dispose() {
//Unregister for all events
- if (phone.getLteOnCdmaMode() != Phone.LTE_ON_CDMA_TRUE) {
- phone.mCM.unregisterForSIMReady(this);
- }
+ phone.mCM.unregisterForSIMReady(this);
phone.mCM.unregisterForOffOrNotAvailable( this);
phone.mCM.unregisterForIccRefresh(this);
}
diff --git a/telephony/java/com/android/internal/telephony/gsm/SimCard.java b/telephony/java/com/android/internal/telephony/gsm/SimCard.java
index 643f709..1fa278a 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SimCard.java
+++ b/telephony/java/com/android/internal/telephony/gsm/SimCard.java
@@ -49,7 +49,6 @@ public final class SimCard extends IccCard {
updateStateProperty();
if(mPhone.getLteOnCdmaMode() == Phone.LTE_ON_CDMA_TRUE) {
- mPhone.mCM.registerForNVReady(mHandler, EVENT_ICC_READY, null);
mPhone.mCM.registerForIccStatusChanged(mHandler, EVENT_ICC_LOCKED_OR_ABSENT, null);
}
}
@@ -63,7 +62,6 @@ public final class SimCard extends IccCard {
mPhone.mCM.unregisterForSIMReady(mHandler);
if(mPhone.getLteOnCdmaMode() == Phone.LTE_ON_CDMA_TRUE) {
- mPhone.mCM.unregisterForNVReady(mHandler);
mPhone.mCM.unregisterForIccStatusChanged(mHandler);
}
}
diff --git a/tests/BandwidthTests/Android.mk b/tests/BandwidthTests/Android.mk
new file mode 100644
index 0000000..7bc5f857
--- /dev/null
+++ b/tests/BandwidthTests/Android.mk
@@ -0,0 +1,24 @@
+#
+# 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 := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_PACKAGE_NAME := BandwidthEnforcementTest
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+include $(BUILD_PACKAGE)
diff --git a/tests/BandwidthTests/AndroidManifest.xml b/tests/BandwidthTests/AndroidManifest.xml
new file mode 100644
index 0000000..19f38ca
--- /dev/null
+++ b/tests/BandwidthTests/AndroidManifest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.tests.bandwidthenforcement">
+ <uses-permission android:name="android.permission.INTERNET" />
+ <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+ <application>
+ <activity android:name=".BandwidthEnforcementTestActivity">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ <!-- adb shell am startservice -n com.android.tests.bandwidthenforcement/.BandwidthEnforcementTestService -->
+ <service android:name=".BandwidthEnforcementTestService" android:exported="true" />
+ </application>
+</manifest>
diff --git a/tests/BandwidthTests/res/layout/main.xml b/tests/BandwidthTests/res/layout/main.xml
new file mode 100644
index 0000000..3392b21
--- /dev/null
+++ b/tests/BandwidthTests/res/layout/main.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal">
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/app_name" />
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/app_desc" />
+</LinearLayout>
diff --git a/tests/BandwidthTests/res/values/strings.xml b/tests/BandwidthTests/res/values/strings.xml
new file mode 100644
index 0000000..a4a78c2
--- /dev/null
+++ b/tests/BandwidthTests/res/values/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name">BandwidthEnforcementTest</string>
+ <string name="app_desc">Tries several tricks to get Internet access.</string>
+ <string name="start">Start</string>
+ <string name="stop">Stop</string>
+</resources>
diff --git a/tests/BandwidthTests/src/com/android/tests/bandwidthenforcement/BandwidthEnforcementTestActivity.java b/tests/BandwidthTests/src/com/android/tests/bandwidthenforcement/BandwidthEnforcementTestActivity.java
new file mode 100644
index 0000000..f0e43ac
--- /dev/null
+++ b/tests/BandwidthTests/src/com/android/tests/bandwidthenforcement/BandwidthEnforcementTestActivity.java
@@ -0,0 +1,27 @@
+/*
+ * 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.
+ */
+package com.android.tests.bandwidthenforcement;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class BandwidthEnforcementTestActivity extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.main);
+ }
+}
diff --git a/tests/BandwidthTests/src/com/android/tests/bandwidthenforcement/BandwidthEnforcementTestService.java b/tests/BandwidthTests/src/com/android/tests/bandwidthenforcement/BandwidthEnforcementTestService.java
new file mode 100644
index 0000000..a2427f5
--- /dev/null
+++ b/tests/BandwidthTests/src/com/android/tests/bandwidthenforcement/BandwidthEnforcementTestService.java
@@ -0,0 +1,210 @@
+/*
+ * 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.
+ */
+package com.android.tests.bandwidthenforcement;
+
+import android.app.IntentService;
+import android.content.Intent;
+import android.net.SntpClient;
+import android.os.Environment;
+import android.util.Log;
+
+import java.io.BufferedWriter;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.DatagramPacket;
+import java.net.DatagramSocket;
+import java.net.HttpURLConnection;
+import java.net.InetAddress;
+import java.net.URL;
+import java.util.Random;
+
+import libcore.io.Streams;
+
+/*
+ * Test Service that tries to connect to the web via different methods and outputs the results to
+ * the log and a output file.
+ */
+public class BandwidthEnforcementTestService extends IntentService {
+ private static final String TAG = "BandwidthEnforcementTestService";
+ private static final String OUTPUT_FILE = "BandwidthEnforcementTestServiceOutputFile";
+
+ public BandwidthEnforcementTestService() {
+ super(TAG);
+ }
+
+ @Override
+ protected void onHandleIntent(Intent intent) {
+ Log.d(TAG, "Trying to establish a connection.");
+ // Read output file path from intent.
+ String outputFile = intent.getStringExtra(OUTPUT_FILE);
+ dumpResult("testUrlConnection", testUrlConnection(), outputFile);
+ dumpResult("testUrlConnectionv6", testUrlConnectionv6(), outputFile);
+ dumpResult("testSntp", testSntp(), outputFile);
+ dumpResult("testDns", testDns(), outputFile);
+ }
+
+ public static void dumpResult(String tag, boolean result, String outputFile) {
+ Log.d(TAG, "Test output file: " + outputFile);
+ try {
+ if (outputFile != null){
+ File extStorage = Environment.getExternalStorageDirectory();
+ File outFile = new File(extStorage, outputFile);
+ FileWriter writer = new FileWriter(outFile, true);
+ BufferedWriter out = new BufferedWriter(writer);
+ if (result) {
+ out.append(tag + ":fail\n");
+ } else {
+ out.append(tag + ":pass\n");
+ }
+ out.close();
+ }
+ if (result) {
+ Log.e(TAG, tag + " FAILURE ====================");
+ Log.e(TAG, tag + " FAILURE was able to use data");
+ Log.e(TAG, tag + " FAILURE ====================");
+ } else {
+ Log.d(TAG, tag + " success; unable to use data");
+ }
+ } catch (IOException e) {
+ Log.e(TAG, "Could not write file " + e.getMessage());
+ }
+ }
+
+ /**
+ * Tests a normal http url connection.
+ * @return true if it was able to connect, false otherwise.
+ */
+ public static boolean testUrlConnection() {
+ try {
+ final HttpURLConnection conn = (HttpURLConnection) new URL("http://www.google.com/")
+ .openConnection();
+ try {
+ conn.connect();
+ final String content = Streams.readFully(
+ new InputStreamReader(conn.getInputStream()));
+ if (content.contains("Google")) {
+ return true;
+ }
+ } finally {
+ conn.disconnect();
+ }
+ } catch (IOException e) {
+ Log.d(TAG, "error: " + e);
+ }
+ return false;
+ }
+
+ /**
+ * Tests a ipv6 http url connection.
+ * @return true if it was able to connect, false otherwise.
+ */
+ public static boolean testUrlConnectionv6() {
+ try {
+ final HttpURLConnection conn = (HttpURLConnection) new URL("http://ipv6.google.com/")
+ .openConnection();
+ try {
+ conn.connect();
+ final String content = Streams.readFully(
+ new InputStreamReader(conn.getInputStream()));
+ if (content.contains("Google")) {
+ return true;
+ }
+ } finally {
+ conn.disconnect();
+ }
+ } catch (IOException e) {
+ Log.d(TAG, "error: " + e);
+ }
+ return false;
+ }
+
+ /**
+ * Tests to connect via sntp.
+ * @return true if it was able to connect, false otherwise.
+ */
+ public static boolean testSntp() {
+ final SntpClient client = new SntpClient();
+ if (client.requestTime("0.pool.ntp.org", 10000)) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Tests dns query.
+ * @return true if it was able to connect, false otherwise.
+ */
+ public static boolean testDns() {
+ try {
+ final DatagramSocket socket = new DatagramSocket();
+ try {
+ socket.setSoTimeout(10000);
+
+ final byte[] query = buildDnsQuery("www", "android", "com");
+ final DatagramPacket queryPacket = new DatagramPacket(
+ query, query.length, InetAddress.parseNumericAddress("8.8.8.8"), 53);
+ socket.send(queryPacket);
+
+ final byte[] reply = new byte[query.length];
+ final DatagramPacket replyPacket = new DatagramPacket(reply, reply.length);
+ socket.receive(replyPacket);
+ return true;
+
+ } finally {
+ socket.close();
+ }
+ } catch (IOException e) {
+ Log.d(TAG, "error: " + e);
+ }
+ return false;
+ }
+
+ /**
+ * Helper method to build a dns query
+ * @param query the dns strings of the server
+ * @return the byte array of the dns query to send
+ * @throws IOException
+ */
+ private static byte[] buildDnsQuery(String... query) throws IOException {
+ final Random random = new Random();
+ final ByteArrayOutputStream out = new ByteArrayOutputStream();
+
+ final byte[] id = new byte[2];
+ random.nextBytes(id);
+
+ out.write(id);
+ out.write(new byte[] { 0x01, 0x00 });
+ out.write(new byte[] { 0x00, 0x01 });
+ out.write(new byte[] { 0x00, 0x00 });
+ out.write(new byte[] { 0x00, 0x00 });
+ out.write(new byte[] { 0x00, 0x00 });
+
+ for (String phrase : query) {
+ final byte[] bytes = phrase.getBytes("US-ASCII");
+ out.write(bytes.length);
+ out.write(bytes);
+ }
+ out.write(0x00);
+
+ out.write(new byte[] { 0x00, 0x01 });
+ out.write(new byte[] { 0x00, 0x01 });
+
+ return out.toByteArray();
+ }
+}
diff --git a/voip/java/com/android/server/sip/SipSessionGroup.java b/voip/java/com/android/server/sip/SipSessionGroup.java
index 3b3cbf3..49effa8 100644
--- a/voip/java/com/android/server/sip/SipSessionGroup.java
+++ b/voip/java/com/android/server/sip/SipSessionGroup.java
@@ -72,6 +72,7 @@ import javax.sip.TransactionUnavailableException;
import javax.sip.address.Address;
import javax.sip.address.SipURI;
import javax.sip.header.CSeqHeader;
+import javax.sip.header.ContactHeader;
import javax.sip.header.ExpiresHeader;
import javax.sip.header.FromHeader;
import javax.sip.header.HeaderAddress;
@@ -873,16 +874,21 @@ class SipSessionGroup implements SipListener {
}
private int getExpiryTime(Response response) {
- int expires = EXPIRY_TIME;
- ExpiresHeader expiresHeader = (ExpiresHeader)
- response.getHeader(ExpiresHeader.NAME);
- if (expiresHeader != null) expires = expiresHeader.getExpires();
- expiresHeader = (ExpiresHeader)
- response.getHeader(MinExpiresHeader.NAME);
- if (expiresHeader != null) {
- expires = Math.max(expires, expiresHeader.getExpires());
- }
- return expires;
+ int time = -1;
+ ContactHeader contact = (ContactHeader) response.getHeader(ContactHeader.NAME);
+ if (contact != null) {
+ time = contact.getExpires();
+ }
+ ExpiresHeader expires = (ExpiresHeader) response.getHeader(ExpiresHeader.NAME);
+ if (expires != null && (time < 0 || time > expires.getExpires())) {
+ time = expires.getExpires();
+ }
+ expires = (ExpiresHeader) response.getHeader(MinExpiresHeader.NAME);
+ if (expires != null && time < expires.getExpires()) {
+ time = expires.getExpires();
+ }
+ Log.v(TAG, "Expiry time = " + time);
+ return (time > 0) ? time : EXPIRY_TIME;
}
private boolean registeringToReady(EventObject evt)
diff --git a/wifi/java/android/net/wifi/WifiNative.java b/wifi/java/android/net/wifi/WifiNative.java
index 8d327d0..2cd54d9 100644
--- a/wifi/java/android/net/wifi/WifiNative.java
+++ b/wifi/java/android/net/wifi/WifiNative.java
@@ -217,6 +217,19 @@ public class WifiNative {
return doBooleanCommand("WPS_PIN any " + pin);
}
+ public static boolean setPersistentReconnect(boolean enabled) {
+ int value = (enabled == true) ? 1 : 0;
+ return WifiNative.doBooleanCommand("SET persistent_reconnect " + value);
+ }
+
+ public static boolean setDeviceName(String name) {
+ return WifiNative.doBooleanCommand("SET device_name " + name);
+ }
+
+ public static boolean setDeviceType(String type) {
+ return WifiNative.doBooleanCommand("SET device_type " + type);
+ }
+
public static boolean p2pFind() {
return doBooleanCommand("P2P_FIND");
}
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pService.java b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
index bdf0120..f67680d 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pService.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
@@ -50,6 +50,7 @@ import android.os.Message;
import android.os.Messenger;
import android.os.ServiceManager;
import android.os.SystemProperties;
+import android.provider.Settings;
import android.util.Slog;
import android.view.LayoutInflater;
import android.view.View;
@@ -126,6 +127,8 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
private static final int WIFI_DISABLE_USER_ACCEPT = BASE + 11;
private final boolean mP2pSupported;
+ private final String mDeviceType;
+ private String mDeviceName;
private NetworkInfo mNetworkInfo;
@@ -142,6 +145,9 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
mP2pSupported = mContext.getResources().getBoolean(
com.android.internal.R.bool.config_wifi_p2p_support);
+ mDeviceType = mContext.getResources().getString(
+ com.android.internal.R.string.config_wifi_p2p_device_type);
+ mDeviceName = getDefaultDeviceName();
mP2pStateMachine = new P2pStateMachine(TAG, mP2pSupported);
mP2pStateMachine.start();
@@ -182,6 +188,14 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
"WifiP2pService");
}
+ /* We use the 4 digits of the ANDROID_ID to have a friendly
+ * default that has low likelihood of collision with a peer */
+ private String getDefaultDeviceName() {
+ String id = Settings.Secure.getString(mContext.getContentResolver(),
+ Settings.Secure.ANDROID_ID);
+ return "Android_" + id.substring(0,4);
+ }
+
/**
* Get a reference to handler. This is used by a client to establish
* an AsyncChannel communication with WifiP2pService
@@ -577,6 +591,7 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
mNetworkInfo.setIsAvailable(true);
//Start listening for new connections
WifiNative.p2pListen();
+ initializeP2pSettings();
}
@Override
@@ -637,6 +652,22 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
if (mPeers.clear()) sendP2pPeersChangedBroadcast();
transitionTo(mP2pDisabledState);
sendMessageDelayed(WifiP2pManager.ENABLE_P2P, P2P_RESTART_INTERVAL_MSECS);
+ break;
+ case WifiMonitor.P2P_GROUP_STARTED_EVENT:
+ mGroup = (WifiP2pGroup) message.obj;
+ if (DBG) logd(getName() + " group started");
+ if (mGroup.isGroupOwner()) {
+ startDhcpServer(mGroup.getInterface());
+ } else {
+ mDhcpStateMachine = DhcpStateMachine.makeDhcpStateMachine(mContext,
+ P2pStateMachine.this, mGroup.getInterface());
+ mDhcpStateMachine.sendMessage(DhcpStateMachine.CMD_START_DHCP);
+ WifiP2pDevice groupOwner = mGroup.getOwner();
+ updateDeviceStatus(groupOwner.deviceAddress, Status.CONNECTED);
+ sendP2pPeersChangedBroadcast();
+ }
+ transitionTo(mGroupCreatedState);
+ break;
default:
return NOT_HANDLED;
}
@@ -708,21 +739,6 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
sendP2pPeersChangedBroadcast();
transitionTo(mInactiveState);
break;
- case WifiMonitor.P2P_GROUP_STARTED_EVENT:
- mGroup = (WifiP2pGroup) message.obj;
- if (DBG) logd(getName() + " group started");
- if (mGroup.isGroupOwner()) {
- startDhcpServer(mGroup.getInterface());
- } else {
- mDhcpStateMachine = DhcpStateMachine.makeDhcpStateMachine(mContext,
- P2pStateMachine.this, mGroup.getInterface());
- mDhcpStateMachine.sendMessage(DhcpStateMachine.CMD_START_DHCP);
- WifiP2pDevice groupOwner = mGroup.getOwner();
- updateDeviceStatus(groupOwner.deviceAddress, Status.CONNECTED);
- sendP2pPeersChangedBroadcast();
- }
- transitionTo(mGroupCreatedState);
- break;
case GROUP_NEGOTIATION_TIMED_OUT:
if (mGroupNegotiationTimeoutIndex == message.arg1) {
if (DBG) logd("Group negotiation timed out");
@@ -760,25 +776,33 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
//After a GO setup, STA connected event comes with interface address
String interfaceAddress = (String) message.obj;
String deviceAddress = getDeviceAddress(interfaceAddress);
- mGroup.addClient(deviceAddress);
- updateDeviceStatus(deviceAddress, Status.CONNECTED);
- if (DBG) logd(getName() + " ap sta connected");
- sendP2pPeersChangedBroadcast();
+ if (deviceAddress != null) {
+ mGroup.addClient(deviceAddress);
+ updateDeviceStatus(deviceAddress, Status.CONNECTED);
+ if (DBG) logd(getName() + " ap sta connected");
+ sendP2pPeersChangedBroadcast();
+ } else {
+ loge("Connect on unknown device address : " + interfaceAddress);
+ }
break;
case WifiMonitor.AP_STA_DISCONNECTED_EVENT:
interfaceAddress = (String) message.obj;
deviceAddress = getDeviceAddress(interfaceAddress);
- updateDeviceStatus(deviceAddress, Status.AVAILABLE);
- if (mGroup.removeClient(deviceAddress)) {
- if (DBG) logd("Removed client " + deviceAddress);
- sendP2pPeersChangedBroadcast();
- } else {
- if (DBG) logd("Failed to remove client " + deviceAddress);
- for (WifiP2pDevice c : mGroup.getClientList()) {
- if (DBG) logd("client " + c.deviceAddress);
+ if (deviceAddress != null) {
+ updateDeviceStatus(deviceAddress, Status.AVAILABLE);
+ if (mGroup.removeClient(deviceAddress)) {
+ if (DBG) logd("Removed client " + deviceAddress);
+ sendP2pPeersChangedBroadcast();
+ } else {
+ if (DBG) logd("Failed to remove client " + deviceAddress);
+ for (WifiP2pDevice c : mGroup.getClientList()) {
+ if (DBG) logd("client " + c.deviceAddress);
+ }
}
+ if (DBG) loge(getName() + " ap sta disconnected");
+ } else {
+ loge("Disconnect on unknown device address : " + interfaceAddress);
}
- if (DBG) loge(getName() + " ap sta disconnected");
break;
case DhcpStateMachine.CMD_POST_DHCP_ACTION:
DhcpInfoInternal dhcpInfo = (DhcpInfoInternal) message.obj;
@@ -857,6 +881,9 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
case WifiMonitor.P2P_PROV_DISC_ENTER_PIN_EVENT:
notifyP2pProvDiscPinRequest((WifiP2pDevice) message.obj);
break;
+ case WifiMonitor.P2P_GROUP_STARTED_EVENT:
+ Slog.e(TAG, "Duplicate group creation event notice, ignore");
+ break;
case WifiP2pManager.WPS_PBC:
WifiNative.wpsPbc();
break;
@@ -1117,6 +1144,12 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
return null;
}
+ private void initializeP2pSettings() {
+ WifiNative.setPersistentReconnect(true);
+ WifiNative.setDeviceName(mDeviceName);
+ WifiNative.setDeviceType(mDeviceType);
+ }
+
//State machine initiated requests can have replyTo set to null indicating
//there are no recepients, we ignore those reply actions
private void replyToMessage(Message msg, int what) {